Trusted Partner: Accounts Registration API

Last Updated on 5/13/2020

Introduction: Registering Organizations via Accounts API

An organization that has been designated as a trusted partner may use the accounts Organization Register API to add their partner organizations.

Calling the Register Organization Endpoint

Make an HTTP POST to the following API endpoint to register organizations:

https://apps.credentialengine.org/accountsapi/organization/register

Include your organization's API key in the header:

Authorization: ApiToken [YOUR API KEY]

Endpoint Steps

The register endpoint will perform the following steps:

  • Verify caller is a trusted partner (using the API Key)
  • Validate the request
  • If valid, add the organization
  • If the contact doesn’t exist (based on the contact email address), create the user
  • Add the provided contact as an administration user to the organization
  • Approve the organization
  • Set up and approve a third party relationship between the organization and the caller (trusted organization)
  • Send emails to all parties

Input Properties

The following sections list the properties for the input classes.

Organization

Property Data
Required
Input Data
The CTID is essentially a product identifier. Any data such as credentials, organizations, assessments, etc. that is published to the registry must have a CTID.
The CTID for an organization is required to be specified as the owning organization when publishing any data to the registry.
Note:
Databases often have a data type for a UUID. For example, SQL Server uses the data type: uniqueidentifer. So the uniqueidentifier with the prefix of ce- could be used.
Yes
Constraints:
The format is an all-lowercase UUID (Universally Unique Identifier) prefixed with ce-. The UUID is often referred to as a GUID in some program languages.
Example:
ce-c427f875-a123-b456-c789-9c6b9ef2143d
Name
Official name of the organization
Yes
Constraints:
2-100 characters
Url
URL for the organizations's main website.
Yes
OrganizationPublishingRoleUris
Publishing role for the organization.
Note:
While ThirdParty is a valid role in the Accounts System, it is not an allowed option here.
Yes
Constraints:
- List of strings
- Values must be one or more of:
  • CredentialOrganization
  • QACredentialOrganization
  • CompetencyFrameworkOrganization
Example:
CredentialOrganization
ProfileName
Screen name for the organization, comparable to one that would be used for social media.
Note:
If no value is provided, one will be generated with the format: profile_f492597f-9b33-4205-b49c-8f6f09a9c466
No
Constraints:
- 3-50 characters
- Must not already be in use by another organization
Example:
SpringfieldU
FEIN
Federal Employer Identification Number
No
DUNS
Data Universal Numbering System number
No
OPEID
Office of Postsecondary Education Identification number
No

AdminContact

Property Data
Required
Input Data
Email
Email address for the organization
Yes
Constraints:
Must be a valid email address
Example:
info@organization.net

PublishingEstimate

Property Data
Required
Input Data
EntityTypeUri
CTDL type URI for the type of entity for this estimate
Yes
Constraints:
Must be a valid CTDL type URI
Example:
ceterms:Certificate

Response Properties

The following sections list the terms returned by the API Response.

Response

Property Data
Notes
Successful
Indicates whether or not the action was successful.
Messages
List of error messages if Successful = false. Typically there are no messages if successful= true.
OrganizationApiKey
If successful, the apiKey for the new organization is returned. The caller can choose to store it, or pass it on to the organization.

Sample Code

The following sections provide code samples.

Sample API Input

{ "Name": "Mid Michigan Community College - Updates", "Ctid": "ce-xxxxxxxx-1220-001c-xxxx-d45917a407ac", "Url": "https://example.com/yourTest/", "FEIN": "xx-1234567", "PrimaryEmail": "test@test.com", "PrimaryPhoneNumber": "(800) 555-1212", "OrganizationPublishingRoleUris": [ "publishRole:CredentialOrganization" ], "OrganizationPublishingMethodUris": [ "RegistryAssistant","BulkUpload" ], "OrganizationTypeUris": [ "orgType:TwoYear","certificationBody" ], "OrganizationSectorUri": "agentSector:Public", "Contacts": [ { "ContactEmail": "test@your.org", "ContactFirstName": "John", "ContactLastName": "AdminUser" } ], "StreetAddress": "1375 S Clare Avenue", "City": "Harrison", "StateProvince": "Michigan", "PostalCode": "48625", }

Sample C# Input Class

public class OrganizationAddition { // Required public string CTID { get; set; } // Required public string Name { get; set; } // Organization Profile name // Max of 50 characters, must be unique to the accounts site // If blank, will be set to default of profile-GUID // IF NOT SURE IT WILL BE UNIQUE - DON'T INCLUDE public string ProfileName { get; set; } // Recommended, but no longer required for registrations by trusted partners public string FEIN { get; set; } public string DUNS { get; set; } public string OPEID { get; set; } // Required Primary URL for the organization public string Url { get; set; } // Required public string PrimaryPhoneNumber { get; set; } public string PrimaryPhoneExtension { get; set; } public string SecondaryPhoneNumber { get; set; } public string SecondaryPhoneExtension { get; set; } public string PrimaryEmail { get; set; } // OrganizationPublishingRoleUris // One or more of // - CredentialOrganization, // - QACredentialOrganization, // - CompetencyFrameworkOrganization // Required public List<string> OrganizationPublishingRoleUris { get; set; } = new List<string>(); // OrganizationPublishingMethodUris // One or more of // - BulkUpload // - CompetencyFrameworks // - ManualEntry // - RegistryAssistant // Required public List<string> OrganizationPublishingMethodUris { get; set; } = new List<string>(); // OrganizationConsumingMethodUris // Zero or more of // - CreateWidget // - OfflineStorage // - SearchApi // Required public List<string> OrganizationConsumingMethodUris { get; set; } = new List<string>(); // OrganizationType concept scheme // See: https://credreg.net/ctdl/terms/OrganizationType#OrganizationType // Required public List<string> OrganizationTypeUris { get; set; } = new List<string>(); // OrganizationSector concept scheme // One of (defaults to Public) // - PrivateNonProfit // - PrivateForProfit // - Public // Required public string OrganizationSectorUri { get; set; } // Feb. 21, 2020 The API will now handle a list of contacts. // The list is checked first. If data is found, any data in the old format will be ignored. // If a list is not found, and the old data is found, it will be imported, and a warning will be returned. // At least one contact is required public List<AdminContact> Contacts { get; set; } = new List<AdminContact>(); // Properties for Address // All required public string StreetAddress { get; set; } public string City { get; set; } public string StateProvince { get; set; } public string Country { get; set; } public string PostalCode { get; set; } // Optional public List<PublishingEstimate> PublishingEstimates { get; set; } = new List<PublishingEstimate>(); } public class PublishingEstimate { public string EntityTypeUri { get; set; } public int EstimatedCount { get; set; } public string Comment { get; set; } } public class AdminContact { public string Email { get; set; } public string LastName { get; set; } public string FirstName { get; set; } public string DaytimePhoneNumber { get; set; } public string DaytimePhoneExtension { get; set; } }

Calling the API - Sample C# Code

The following is sample C# code for calling the API.

// For serialization/deserialization methods using Newtonsoft.Json; public void RegisterOrganization() { string publisherApikey = “provide your api key here”; // URL for sandbox var accountsApiUrl = “https://sandbox.credentialengine.org/accountsAPI/organization/register”; // Provide a valid CTID string ctid = "ce-????????-????-????-????-????????????"; API.OrganizationAddition org = new API.OrganizationAddition() { Name = "Delta College", Url = "http://example.com/DeltaCollege", // Max length = 50. Must be unique. Leave blank to have system set a default. ProfileName = "profile_" + Guid.NewGuid().ToString().ToLower(), // CTID = ctid, FEIN = "??-nnnnnnn", DUNS = "", OPEID = "" }; // Add a publishing role (with or without the namespace of publishRole) org.OrganizationPublishingRoleUris.Add("publishRole:CredentialOrganization"); // Add one or more publishing methods org.OrganizationPublishingMethodUris.Add("ManualEntry"); org.OrganizationPublishingMethodUris.Add("publishMethod:RegistryAssistant"); // Add one sector org.OrganizationSectorUri = "agentSector:Public"; // Add one or more organization types org.OrganizationTypeUris.Add("orgType:TwoYear" ); org.PrimaryEmail = "test@email.com"; org.PrimaryPhoneNumber = "800-555-1212"; // Add an administrator for the new organization org.Contacts.Add( new AdminContact() { Email = "adminUser@myEmail.org", FirstName = "My", LastName = "Name" } ); org.StreetAddress = "1961 Main Str"; org.City = "Somewhere"; org.StateProvince = "Michigan"; org.PostalCode = "48710"; org.Country = "USA"; // Call accounts API string contents = ""; // Serialize string postBody = JsonConvert.SerializeObject(org, GetJsonSettings()); try { using (var client = new HttpClient()) { client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); client.DefaultRequestHeaders.Add("Authorization", "ApiToken " + publisherApikey); var task = client.PostAsync(accountsApiUrl, new StringContent(postBody, Encoding.UTF8, "application/json")); task.Wait(); var response = task.Result; contents = task.Result.Content.ReadAsStringAsync().Result; // Deserialize to the response object (or could use a Dictionary object); var orr = JsonConvert.DeserializeObject(contents); if (response.IsSuccessStatusCode == false) { // Inspect messages individually or place all in a string var status = string.Join("", orr.Messages.ToArray()); } else { // Check to ensure OK // { // "Successful":true, // "Messages":[], // "OrganizationApiKey":"????????-????-????-????-????????????", // "ApprovedToPublish":true // } } } // End using } catch (Exception ex) { // Handle errors, while very unlikely LoggingHelper.LogError(ex, string.Format(thisClassName + ".TestRegisterOrganization FAILED. Publisher OrgName: {0}, target orgCtid", org.Name, org.CTID)); string message = LoggingHelper.FormatExceptions(ex); } } public static JsonSerializerSettings GetJsonSettings() { var settings = new JsonSerializerSettings() { NullValueHandling = NullValueHandling.Ignore, DefaultValueHandling = DefaultValueHandling.Ignore, Formatting = Formatting.Indented, ReferenceLoopHandling = ReferenceLoopHandling.Ignore }; return settings; }