Credential Engine Registry Search API Handbook

Last Updated on 1/27/2025

Overview

The Credential Registry Search API provides a way to programmatically search the Credential Registry and return top-level resources based on data within those resources, including their connections to other resources. This guide explains how to use the Search API.

Requirements

To use the Search API, you will need:

Use Cases and Alternative Consuming Methods to Consider

The Search API is intended to cover a wide variety of use cases involving queries to the Registry. However, there are some cases where alternative approaches will yield better results.

Getting Real-Time Data

The Search API is well-suited to retrieving real-time data from the Registry. The search index is kept up to date with the Registry itself, and is typically current within a few minutes of new records being published. This kind of usage is the primary purpose of the Search API.

While it is possible to find many resources by searching for them, the resources in the Registry are highly linked together. These links are leveraged by the Search API to build its index, but you can leverage these links directly. For example, you can follow the links in a Credential record to find all of the Competencies it requires. Following the links in the resources directly does not require use of the Search API, nor does it require an API key or even a Credential Engine account. This process is also typically instantaneous, as no query is necessary to return a record that is linked to from another record. For these reasons, it is worth considering whether your particular use case can be satisfied by simply following the links in the records themselves.

In some cases, a hybrid approach is best. For example, using a query to find a list of credentials, and then following the links in those credentials to find their associated competencies.

It's also worth keeping in mind that many properties in CTDL are inverse of each other (for example, "offers" and "offeredBy"). The data in the records in the registry is dependent on the publishers, so in some cases one side or the other of these two-way connections may not be complete or available in the records. For these cases, it is advisable to use the Search API to traverse these connections in both directions and ensure that you retrieve the full set of data.

For more information about how these records link together, including ways to manipulate the URIs to load even more information, see the CTID page.

Scraping the Registry or Downloading Records in Bulk

The Search API is not intended to enable scraping of the Registry to download large quantities of records in bulk. An example of this usage includes doing a search for all resources of a given type and paging through the results to download thousands of records.

If your use case requires this kind of data, you should instead use one of these options for Bulk Download for Offline Use.

Credential Engine monitors for use of the Search API for mass downloading of resources, and will contact you if this behavior is detected.

CTDL JSON Query Structure

The Search API uses a unique query structure built from plain JSON that leverages the actual properties and structure of CTDL and the related schemas. This structure is intended to enable highly flexible queries that allow finding resources based on properties deep within the records or even based on connections to other records. This section explains various features of this query structure.

Basics

The Search API expects a JSON object as an input, which serves as a simple wrapper to carry paging and sorting information, as well as the CTDL query itself. This section focuses specifically on the CTDL query inside of this wrapper.

Filter By Resource Type

Use the @type property to filter results to a given CTDL type or list of types.

All Certificates
Look for all resources with a @type of ceterms:Certificate.
{ "@type": "ceterms:Certificate" }
All Learning Opportunities and Courses
Look for all resources with a @type of either ceterms:LearningOpportunityProfile or ceterms:Course
{ "@type": [ "ceterms:LearningOpportunityProfile", "ceterms:Course" ] }

Filter By Text Properties

The Search API supports a number of features for querying properties that have text-based values, including plain strings, URIs, language maps, and dates.

By default, all string-based fields allow for case-insensitive partial matches. For language map fields (such as ceterms:name or ceterms:description, the Search API abstracts away the intricacies of the language map itself, allowing you to query these fields as if their values were plain strings.

All Resources with "Welding" in the Name
Look for all resources with a ceterms:name property that contains "welding". Note that this will not search other properties, including similar ones from other namespaces like ceasn:name or ceasn:competencyLabel.
{ "ceterms:name": "welding" }

It is possible to force more specific kinds of matching by using a JSON object with search:value and search:matchType properties as shown:

All Resources Named Exactly "Welding Course"
Look for all resources with a ceterms:name property that exactly matches "welding course" (case-insensitive).
{ "ceterms:name": { "search:value": "welding course", "search:matchType": "search:exactMatch" } }

Valid values for search:matchType include:

  • search:exactMatch - Will only match if the string is an exact match (case-insensitive) to the provided value
  • search:contains - Will only match if the string contains an exact match (case-insensitive) to the provided value
  • search:startsWith - Will only match if the string starts with the provided value
  • search:endsWith - Will only match if the string ends with the provided value

Matching CTIDs and URIs

In addition to the support for partial matches described above, the Search API also supports matches based on resource URIs and CTIDs. The Search API's index is optimized to work faster if you provide a full URI where expected, but a CTID in a URI property will also work.

All Resources Offered By a Particular Organization (by URI)
Look for all resources with a ceterms:offeredBy property that matches the given URI.
{ "ceterms:offeredBy": "https://credentialengineregistry.org/resources/ce-9e179080-3a4c-45ee-87bb-0538429a60ab" }
All Resources Offered By a Particular Organization (by CTID)
Look for all resources with a ceterms:offeredBy property that matches the given CTID.
{ "ceterms:offeredBy": "ce-9e179080-3a4c-45ee-87bb-0538429a60ab" }

Filtering by Boolean Properties

There are a handful of boolean properties in CTDL. The default value for these properties is null, so you only need to use them if you are looking for an explicitly true or false value. Otherwise, these properties will be ignored when filtering.

All Proctored Assessments
Look for all resources with a @type of ceterms:AssessmentProfile and a value of true for the ceterms:isProctored property
{ "@type": "ceterms:AssessmentProfile", "ceterms:isProctored": true }

Filtering by Numeric Properties

The Search API supports querying for numeric properties, both directly, or as a range by searching for an array with exactly two values where the first value is the minimum boundary, and the second value is the maximum boundary (both the upper and lower bounds are inclusive):

Resources that require exactly one year of experience
Look for all resources that require precisely 1 year of experience.
{ "ceterms:requires": { "ceterms:yearsOfExperience": 1 } }
Resources that require minimal experience
Look for all resources that require 1-5 (inclusive) years of experience.
{ "ceterms:requires": { "ceterms:yearsOfExperience": [ 1, 5 ] } }
Learning Opportunities worth 3-7 credits
Look for all resources with a @type of either ceterms:LearningOpportunityProfile or ceterms:Course, and a ceterms:creditValue with a schema:value inclusively between 3 and 7.
{ "@type": [ "ceterms:LearningOpportunityProfile", "ceterms:Course" ], "ceterms:creditValue": { "schema:value": [ 3, 7 ] } }

Range queries require an array with exactly two values, and only work with properties whose values are numeric (otherwise they will be treated like any normal array of potential options - in other words, an array of three numbers will only match results that contain at least one of those numbers):

Resources that require 1, 5, or 7 years of experience
Look for all resources that require exactly 1, 5, or 7 years of experience (ignoring resources that require 2, 3, 4, or 6 years of experience).
{ "ceterms:requires": { "ceterms:yearsOfExperience": [ 1, 5, 7 ] } }

Range queries also may also be unbounded at one end or the other - just pass null to remove the associated boundary:

Resources that require 5 or more years of experience
Look for all resources that require exactly 5 or more years of experience.
{ "ceterms:requires": { "ceterms:yearsOfExperience": [ 5, null ] } }
Resources that require no more than 5 years of experience
Look for all resources that require no more than 5 years of experience.
{ "ceterms:requires": { "ceterms:yearsOfExperience": [ null, 5 ] } }

Filtering by Date Properties

As with numeric properties, the Search API supports querying for date properties both directly, or as a range (both upper and lower bounds are inclusive; see above for more details). Note that you will need to use the ISO 8601 date format when writing dates:

Resources that became effective on 2000-1-1
Look for all resources that became effective on 2000-1-1.
{ "ceterms:dateEffective": "2000-01-01" }
Resources that became effective between 2000-1-1 and 2020-1-1
Look for all resources that became effective between 2000-1-1 and 2020-1-1.
{ "ceterms:dateEffective": [ "2000-01-01", "2020-01-01" ] }

Date queries can also be unbounded at one end or the other; just pass an empty string to remove the associated boundary:

Resources that became effective after 2000-1-1
Look for all resources that became effective after 2000-1-1.
{ "ceterms:dateEffective": [ "2000-01-01", "" ] }
Resources that became effective before 2020-1-1
Look for all resources that became effective before 2020-1-1.
{ "ceterms:dateEffective": [ "", "2020-01-01" ] }

Filtering by Concepts

There are many areas of CTDL where controlled values (Concept Schemes) are used. Concepts from these schemes may be referenced either directly or via Credential Alignment Object, depending on the property in question.

Competency Frameworks with a status of Published
Look for all Competency Frameworks that reference the "Published" status using the expanded form of the concept's URI.
{ "@type": "ceasn:CompetencyFramework", "ceasn:publicationStatusType": "https://credreg.net/ctdlasn/vocabs/publicationStatus/Published" }
Competencies with a Specific Complexity Level
Look for all Competencies that reference a known complexity level, using that concept's URI.
{ "@type": "ceasn:Competency", "ceasn:complexityLevel": "https://credentialengineregistry.org/resources/ce-e58703f7-15f3-44cd-a039-509896c0ec6e" }

For querying properties that use Credential Alignment Object as their value, see the Filtering by Credential Alignment Objects section below.

Filtering by Current Data

The Search API allows for querying all resources in the Registry, including those which are no longer considered to be in use or available. This is intentional, as it allows the lookup of older credentials which may still be valid even if they are no longer offered.

There are three primary properties (and their associated concept schemes) for describing the status of a resource:

  • For Credentials, use the ceterms:credentialStatusType property with terms from the ceterms:CredentialStatus concept scheme.
  • For Competency Frameworks, Concept Schemes, and Progression Models, use the ceasn:publicationStatusType property with the ceasn:PublicationStatus concept scheme.
  • For many other top-level resources in CTDL, use the ceterms:lifeCycleStatusType property with the ceterms:LifeCycleStatus concept scheme.
Certificates that are active
Look for all Certificates with a ceterms:credentialStatusType of credentialStat:Active
{ "@type": "ceterms:Certificate", "ceterms:credentialStatusType": { "ceterms:targetNode": "credentialStat:Active" } }
Competency Frameworks that are published
Look for all Competency Frameworks with a ceasn:publicationStatusType of publicationStatus:Published
{ "@type": "ceasn:CompetencyFramework", "ceasn:publicationStatusType": "publicationStatus:Published" }
Organizations that are active
Look for all Organizations with a ceterms:lifeCycleStatusType of lifeCycle:Active
{ "@type": [ "ceterms:Organization", "ceterms:CredentialOrganization", "ceterms:QACredentialOrganization" ], "ceterms:lifeCycleStatusType": "lifeCycle:Active" }

Filtering by Any Value or No Value for a Property

In some cases, you only need to know if a resource has a given property, regardless of the value of that property. For these cases, use the special token search:anyValue as the value for the property in question:

Certificates with any cost data
Look for all Certificates with any value for the ceterms:estimatedCost property.
{ "@type": "ceterms:Certificate", "ceterms:estimatedCost": "search:anyValue" }

Similarly, the special token search:noValue can be used to find records which do not have any value for the property in question:

Certificates with no cost data
Look for all Certificates without any value for the ceterms:estimatedCost property
{ "@type": "ceterms:Certificate", "ceterms:estimatedCost": "search:noValue" }

Nested Data

To filter resources based on data that is nested within them, simply use a nested JSON object:

Simple Nested Data Query
This example will look for Certificates with a ceterms:requires property which leads to a nested object (in this case, a ceterms:ConditionProfile) which, in turn, has "welding" in its ceterms:description.
{ "@type": "ceterms:Certificate", "ceterms:requires": { "ceterms:description": "welding" } }

This nesting matches the structure of the CTDL records, and may occur several times for deeply-nested data:

Deeper Nested Data Query
This example will look for Certificates with a ceterms:requires property which leads to a nested object (in this case, a ceterms:ConditionProfile) which, in turn, has "welding" in its ceterms:description as well as a ceterms:jurisdiction property which contains a nested object of its own (in this case, a ceterms:JurisdictionProfile) which, in turn, has a value of true for its ceterms:globalJurisdiction property.
{ "@type": "ceterms:Certificate", "ceterms:requires": { "ceterms:description": "welding", "ceterms:jurisdiction": { "ceterms:globalJurisdiction": true } } }

Note that while it's possible to explicitly indicate the @type(s) of the nested objects, it often isn't necessary, particularly when the property referencing them only ever points to instances of a single class.

For more examples, see the Examples section.

Objects and Arrays: Logical AND vs Logical OR

Often, you will want to find resources which have certain values for multiple properties. For example, you may want all Certificates with "nurse" in their name. Or, you may want results that match any value from a list of potential values, such as credentials with "developer" or "programmer" in their keywords. The Search API allows for such cases by way of the structure of the JSON itself, and a few special tokens to allow further control over how the data is queried.

By default, all properties in a JSON object are treated as being logically AND-ed together:

Default Logical AND-ing
Properties in a JSON object are logically AND-ed together, so this query will match resources with a @type of ceterms:Certificate AND a name containing "Auto Maintenance".
{ "@type": "ceterms:Certificate", "ceterms:name": "Auto Maintenance" }

By contrast, all tokens in a JSON array are treated as being logically OR-ed together:

Default Logical OR-ing
Properties in a JSON array are logically OR-ed together, so this query will match any resource with any of the listed keywords.
{ "ceterms:keyword": [ "Programming", "Computer Science", "Information Technology" ] }

There are cases where you may want to override these behaviors. This can be done via the special property search:operator and the special token values, search:orTerms and search:andTerms:

Overriding Logical AND-ing
Using search:operator with a value of search:orTerms will result in the properties of a JSON object being logically OR-ed together. In this example, that will result in finding any resource with a @type of ceterms:Certificate OR which has "Auto Maintenance" in its name (regardless of its @type)
{ "@type": "ceterms:Certificate", "ceterms:name": "Auto Maintenance", "search:operator": "search:orTerms" }

Note that for arrays, the search:operator property and its search:andTerms value exist alongside the array rather than within it, all of which is wrapped in an otherwise empty JSON object:

Overriding Logical OR-ing
Using search:operator with a value of search:andTerms inside an object with a search:value whose value is an array will cause the values of the array to be logically AND-ed together as values for the property that references that JSON object. In this example, the query will only match resources that have all three provided values for the ceterms:keywords property.
{ "ceterms:keyword": { "search:value": [ "Programming", "Computer Science", "Information Technology" ], "search:operator": "search:orTerms" } }

For more examples, see the Examples section.

Controlling Filter Evaluation via Term Groups

When overriding logical AND-ing and OR-ing, it is often necessary to group sets of terms together. For example, you may want all resources where the type is a ceterms:Certificate regardless, but also where either the name or the description may contain "nurse". This kind of query can be done with the special property search:termGroup, which can be thought of as adding parenthesis around a set of terms within a query to force a specific order of operations and logical AND or OR within that group.

Note that despite using a nested JSON object, search:termGroup does not trigger traversal across or into an object in the data; it operates on the object itself.

Grouping properties together
The search:termGroup creates (as the name implies) a group of terms that are logically evaluated as one unit. In this example, the query will look for resources with a @type of ceterms:Certificate AND which satisfy the group's filter, which in turn looks for resources with "nursing" in the name OR the description (via the use of search:operator search:orTerms as described in the "Logical AND vs Logical OR" section above).
{ "@type": "ceterms:Certificate", "search:termGroup": { "search:operator": "search:orTerms", "ceterms:name": "nursing", "ceterms:description": "nursing" } }

For more examples, see the Examples section.

Graph Traversal

The most powerful feature of linked data is, of course, the linking between resources. The Search API is designed to allow you to perform such traversal by structuring your query as though all of the data is nested, even across multiple resources:

Graph Traversal Query
This example will look for Certificates that require an Assessment Profile which assesses a Competency. This query contains a mix of drilling into nested objects and traversing across standalone top-level objects, but the query is structured as if the entirety of the data is nested.
{ "@type": "ceterms:Certificate", "ceterms:requires": { "ceterms:targetAssessment": { "ceterms:assesses": { "ceterms:targetNode": { "ceasn:competencyText": "Text this competency must contain" } } } } }

In some cases, it is necessary to traverse the graph connections in reverse. This can be done just like normal graph traversal, except that you will prefix the reverse properties with ^:

Reverse Graph Traversal Query
This example looks for Competencies that are assessed by a particular Assessment Profile. In the actual data, the Assessment Profile references the Competency via its ceterms:assesses property, which in turn references the Competency via the nested Credential Alignment Object's ceterms:targetNode property, but since the results we're looking for are the competencies, we must start there. This means we need to crawl the ceterms:assesses connection and the ceterms:targetNode connection in reverse, which is signaled by the ^ in front of those properties. Otherwise, the query is structured the same way as any other traversal, behaving as though all of the data is nested.
{ "@type": "ceasn:Competency", "^ceterms:targetNode": { "^ceterms:assesses": { "ceterms:ctid": "ce-eb0c2d38-66d0-44cc-974e-4494d8eb2b90" } } }

These forward and reverse connections can be mixed as needed in a deeply nested query. For more examples, see the Examples section.

Filtering by Credential Alignment Objects

Credential Alignment Object provides a way to link to another resource, such as a competency or concept, and/or to provide a name and description of the intended data, even when no such resource exists. While this is convenient for publishing data, it must be taken into account when querying the data. Aside from needing to be aware of where and when the schema uses a Credential Alignment Object, the actual structure of the query works as it would with any other nesting and traversal:

Query Through Credential Alignment Object
This example will look for Courses that teach Competencies that match the query. Since the value of the ceterms:teaches property is an array of Credential Alignment Objects, we must then also traverse out along the ceterms:targetNode property to arrive at the Competencies.
{ "@type": "ceterms:Course", "ceterms:teaches": { "ceterms:targetNode": { "ceasn:competencyText": "Text this competency must contain" } } }

For more examples of queries that flow through Credential Alignment Object, see the examples section below.

Special Features

The Search API also enables some special tokens for filters based on record metadata. The sections below describe these features.

Filtering by Record Owner and Record Publisher

In some cases, it is necessary to filter records to just those that are owned or published by a specific organization. Note that ownership and publishing, in this case, refers to ownership and/or publishing of the record itself, not necessarily of the resource that the record describes.

To filter records to a specific owner or publisher, use the CTID of the organization along with the special search:recordOwnedBy or search:recordPublishedBy properties:

Record Owned By
Search for all resources where the Credential Registry record for that resource is owned by the organization with the given CTID (regardless of who owns the underlying resource).
{ "search:recordOwnedBy": "ce-d97aa6f8-8bf6-4c56-bd8c-c465da74a4c4" }
Record Published By
Search for all resources where the Credential Registry record for that resource was published by the organization with the given CTID (regardless of who provides the underlying resource).
{ "search:recordPublishedBy": "ce-d97aa6f8-8bf6-4c56-bd8c-c465da74a4c4" }

Filtering by Record Created Date and Record Updated Date

It is also possible to filter records based on when the record was published to the Registry and/or when that record was most recently updated. This is not to be confused with sorting by these dates. As with other date properties, these can be queried based on a date range where both the upper and lower bounds of the range are inclusive.

Note: When a record is initially created, both its search:recordCreated and its search:recordUpdated dates are set to the same value. Subsequent updates to the record will only update the value of search:recordUpdated.

Records Created in a Specific Year
Search for all resources that were initially published to the Credential Registry in 2020.
{ "search:recordCreated": [ "2020-01-01", "2020-12-31" ] }
Records Updated in a Specific Year
Search for all resources in the Credential Registry that were last updated in 2020 (including those that were initially created in 2020 but haven't had any updates after 2020).
{ "search:recordUpdated": [ "2020-01-01", "2020-12-31" ] }

Filtering by Primary and Secondary Record Source

In most cases, a record in the Registry comes from a primary source (that is, the intellectual property owner of that resource). These records may be published in one of three ways:

  • The record was directly published by the primary source itself.
  • The record was published by a third party with the explicit authorization of the primary source itself, but otherwise originated from that primary source (this is commonly called "third-party publishing").
  • The record was published by a third party with overriding authority, such as a state agency, to publish for that source without needing its permission (this is commonly called "trusted third-party publishing").

However, there are special rare cases where an organization needs to publish data for which it is not a primary source, but where the organization's authority does not rise to the level of trusted third-party publisher. For these cases, Credential Engine may authorize such an organization to perform "secondary source" publishing. A record published by a secondary source is just like any other record, except that its metadata indicates that it is a secondary source record.

By default, the Search API will include primary and secondary source records in its results. You can filter primary or secondary records in or out using the search:resourcePublishType property, with a value of either primary or secondary

Records from Primary Sources
Search for all resources that were published by a primary source, whether directly or via an authorized or trusted third party.
{ "search:resourcePublishType": "primary" }
Records from Secondary Sources
Search for all resources that were published by a secondary source.
{ "search:resourcePublishType": "secondary" }

Filtering by Subclasses

The CTDL schema has a number of class hierarchies. The most obvious example of these are the various subclasses of Credential, which form a tree of subclasses. The Search API allows you to explicitly select one or more of these subclasses of credential, but there are cases where you are looking for any kind of credential, regardless of its specific subclass. To avoid needing to keep track of (and write queries with) every subclass of Credential, you can use the following value for @type:

Subclasses of Credential
Search for all resources that are any subclass of ceterms:Credential.
{ "@type": { "search:value": "ceterms:Credential", "search:matchType": "search:subClassOf" } }
Certificates and Subclasses of Certificate
Search for all resources that are a ceterms:Certiticate or one of its subclasses.
{ "@type": { "search:value": "ceterms:Certificate", "search:matchType": "search:subClassOf" } }

This also works for any other classes that have subclasses. As with the Certificate example above, results will include the class you specify, as well as subclasses of that class.

Organizations and Subclasses of Organization
Search for all resources that are a ceterms:Organization or one of its subclasses.
{ "@type": { "search:value": "ceterms:Organization", "search:matchType": "search:subClassOf" } }

The CTDL Types List page provides a useful reference for the various class/subclass hierarchies in CTDL.

Additional Considerations

The CTDL family of schemas provides a variety of ways to describe information. It also provides a variety of places for that information to be stored. When searching for information in the Registry via the Search API, you will need to consider all of the places in CTDL where that information may have been expressed, and write your queries to check all of them. Some common examples are below.

Owns vs Offers vs Owned By vs Offered By vs Creator vs Publisher vs Record Owned By vs Record Published By

There are a number of properties in the CTDL family of schemas for connecting resources to the organizations that provide them. However, the notion of "providing" a resource encompasses several more granular notions, each of which have their own specific properties. Additionally, there is a distinction between the records in the Registry and the resources those records describe.

  • ceterms:owns - Points from an organization to a resource, and indicates that the organization is the intellectual property owner of that resource
  • ceterms:offers - Points from an organization to a resource, and indicates that the organization offers that resource, typically to end users
  • ceterms:ownedBy - Points from a resource to an organization, and indicates that the organization is the intellectual property owner of that resource
  • ceterms:offeredBy - Points from a resource to an organization, and indicates that the organization offers that resource, typically to end users
  • ceasn:creator - Points from a resource to an organization, and indicates that the organization created that resource
  • ceasn:publisher - Points from a resource to an organization, and indicates that the organization makes that resource available, typically to end users
  • search:recordOwnedBy - Special Search API property (see above) indicating the organization that owns the record in the registry (regardless of the owner of the resource)
  • search:recordPublishedBy - Special Search API property (see above) indicating the organization that published the record in the registry (regardless of who makes that resource available to others)

Compounding this, data may be present for some of these properties, but not others (data is always present for the two special search API properties). This is due to differences in which properties certain organizations choose to use, when/how often they update their data, and rules preventing publishers from modifying data they do not own. This leads to subtle inconsistencies in the connections between records that need to be accounted for when using the Search API.

Some common examples include:

  • A credential may indicate that it is "owned by" an organization, but not have any "offered by" data even when it is also offered by that organization
  • A credential may indicate that it is "offered by" an organization, but that organization's record may not indicate that it "offers" that credential
  • A competency framework may only indicate that its "creator" is a particular organization, even when that organization is also its publisher

Typically, the safest approach is to rely on the connections that exist on the resource and point to the organization. This kind of data is usually part of the minimum requirements for publishing the resource, so it is more likely to be present.

Open Badges Offered By an Organization (via ceterms:offeredBy)
Search for all Open Badges that reference the organization that offers them via the ceterms:offeredBy property.
{ "@type": "ceterms:OpenBadge", "ceterms:offeredBy": { "ceterms:ctid": "CTID for the organization here" } }
Open Badges Offered By an Organization (via ceterms:offers)
Search for all Open Badges that an organization offers, as referenced by the organization record via its ceterms:offers property. Note the use of ^ to enable traversing the ceterms:offers connection in reverse.
{ "@type": "ceterms:OpenBadge", "^ceterms:offers": { "ceterms:ctid": "CTID for the organization here" } }

Quality Assurance

Quality Assurance is expressed in CTDL via a series of properties, each with an inverse:

  • ceterms:accredits points from the Organization doing the accrediting to the resource being accredited. Its inverse is ceterms:accreditedBy which points from the resource being accredited to the Organization that does the accrediting.
  • ceterms:approves points from the Organization doing the approving to the resource being approved. Its inverse is ceterms:approvedBy which points from the resource being approved to the Organization that does the approving.
  • ceterms:recognizes points from the Organization doing the recognizing to the resource being recognized. Its inverse is ceterms:recognizedBy which points from the resource being recognized to the Organization that does the recognizing.
  • ceterms:regulates points from the Organization doing the regulating to the resource being regulated. Its inverse is ceterms:regulatedBy which points from the resource being regulated to the Organization that does the regulating.

The nature of the data published to the Registry means that the above connections will not always be present in both directions. For example, a government agency may publish its own Organization record to the Registry, but not provide a list of credentials that it accredits. Publishers of the data for those credentials, however, may provide such data. In this case, the ceterms:accreditedBy connections will exist, but the ceterms:accredits connections will not. Therefore, the lack of connections flowing both ways does not necessarily imply that a false claim of quality assurance is being made, but if this data is important to your use case, you should reach out to the publishers in question to verify the information.

Bachelor Degrees Accredited By a Particular Organization
Search for all Bachelor Degrees that claim to be accredited by a known organization.
{ "@type": "ceterms:BachelorDegree", "ceterms:accreditedBy": { "ceterms:ctid": "CTID for the organization here" } }
Organizations that Recognize a Certificate (Loose)
Search for all Organizations that recognize a given Certificate. Note that both the ceterms:recognizedBy and the ceterms:recognizes properties are used, with the latter connection being searched in reverse, to arrive at a result set that includes assertions about recognition that come from the Certificate, from the Organization, or both.
{ "@type": "ceterms:Certificate", "search:termGroup": { "search:operator": "search:orTerms", "ceterms:recognizedBy": { "ceterms:ctid": "CTID for the organization here" }, "^ceterms:recognizes": { "ceterms:ctid": "CTID for the organization here" } } }
Organizations that Recognize a Certificate (Strict)
Search for all Organizations that recognize a given Certificate. As with the above example, both the ceterms:recognizedBy and the ceterms:recognizes properties are used, with the latter connection being searched in reverse. However, the lack of a Term Group featuring a search:operator with a value of search:orTerms means that all three properties (@type, ceterms:recognizedBy, and the reversed ceterms:recognizes) must match in order for the result to be returned. This means that this search will only return Certificates where the Certificate claims to be recognized by the specified Organization and the specified Organization claims to recognize the Certificate.
{ "@type": "ceterms:Certificate", "ceterms:recognizedBy": { "ceterms:ctid": "CTID for the organization here" }, "^ceterms:recognizes": { "ceterms:ctid": "CTID for the organization here" } }

Additionally, some Organizations perform quality assurance on other Organizations, or on the programs those Organizations offer, rather than on the Credentials themselves. This must also be taken into account when building your queries.

Organizations that Accredit a Certificate, its Required Assessment, or its Offering Organization
Search for all Certificates where the Certificate, its required Assessment, or the Organization that offers that Certificate are accredited by a given Organization, based on connections that point from those resources to the accrediting Organization or connections from the accrediting Organization to one or more of those resources.
{ "@type": "ceterms:Certificate", "search:termGroup": { "search:operator": "search:orTerms", "ceterms:accreditedBy": { "ceterms:ctid": "CTID for the organization here" }, "^ceterms:accredits": { "ceterms:ctid": "CTID for the organization here" }, "ceterms:requires": { "ceterms:targetAssessment": { "search:operator": "search:orTerms", "ceterms:accreditedBy": { "ceterms:ctid": "CTID for the organization here" }, "^ceterms:accredits": { "ceterms:ctid": "CTID for the organization here" } } }, "ceterms:offeredBy": { "search:operator": "search:orTerms", "ceterms:accreditedBy": { "ceterms:ctid": "CTID for the organization here" }, "^ceterms:accredits": { "ceterms:ctid": "CTID for the organization here" } } } }

Addresses

A common use case is to look for credentials that are available in a particular area, such as a state. There are several ways that the physical location where a resource is offered can be communicated in CTDL, each of which will need to be accounted for when looking for resources based on location. Which ways are in use for a given record depends on the which properties the publisher of the data chose to use, but will fall into one or more of these categories:

  • On the resource itself, generally via ceterms:availableAt or ceterms:availablilityListing
  • Described in detail for the resource itself via ceterms:hasOffering
  • Indirectly via a related resource, such as the required assessments or learning opportunities for a credential (also communicated using ceterms:availableAt or ceterms:availablilityListing)
  • Implicitly via the address(es) of the organization(s) that offer(s) the resource, via ceterms:address
  • Implicitly via the jurisdiction(s) of the organization(s) that offer(s) the resource, via ceterms:jurisdiction

When querying for locations, you will need to leverage the structure of the ceterms:Place class, which contains various familiar properties for describing an address at varying levels of granularity.

Address matching can be somewhat awkward when there is more than one way to write an address. For example, in the US, the ceterms:addressRegion may be published with either the full name of a state, or its two-character postal shorthand. Both kinds of address need to be accounted for in order to avoid missing valid resources, while also avoiding false positives where the two-character string is a substring of a full state's name (for example, Indiana's abbreviation, "IN", can be found in "North Carolina". To handle this, you will need to look both for the full name of the state and its exact abbreviation via search:matchType and search:exactMatch, as shown in the examples below.

Certificates by Location (via ceterms:availableAt)
Search for all Certificates that provide their location data directly.
{ "@type": "ceterms:Certificate", "ceterms:availableAt": { "ceterms:addressRegion": [ "Indiana", { "search:value": "IN", "search:matchType": "search:exactMatch" } ] } }
Certificates by Location (via a Required Learning Opportunity)
Search for all Certificates based on where the required Learning Opportunities (including Courses) are offered.
{ "@type": "ceterms:Certificate", "ceterms:requires": { "ceterms:targetLearningOpportunity": { "ceterms:availableAt": { "ceterms:addressRegion": [ "Indiana", { "search:value": "IN", "search:matchType": "search:exactMatch" } ] } } } }
Certificates by Location (via Offering Organization)
Search for all Certificates based on the address(es) of the organization(s) that offer the Certificate.
{ "@type": "ceterms:Certificate", "ceterms:offeredBy": { "ceterms:address": { "ceterms:addressRegion": [ "Indiana", { "search:value": "IN", "search:matchType": "search:exactMatch" } ] } } }

You should also be aware that many resources may (also) be offered online. This would be indicated via use of ceterms:availableOnlineAt.

Certificates Available Online
Search for all Certificates that are available online.
{ "@type": "ceterms:Certificate", "ceterms:availableOnlineAt": "search:anyValue" }

Combining the above and making use of a Term Group, we can look for Certificates based on address even when we don't know exactly where the address data is published:

Certificates by Location (via Any of the Above Properties)
Search for all Certificates based on location data that is provided in the Certificate's data directly, in its required Learning Opportunities, and/or in the address(es) of the offering Organization(s), or which are offered online.
{ "@type": "ceterms:Certificate", "search:termGroup": { "search:operator": "search:orTerms", "ceterms:availableOnlineAt": "search:anyValue", "ceterms:availableAt": { "ceterms:addressRegion": [ "Indiana", { "search:value": "IN", "search:matchType": "search:exactMatch" } ] }, "ceterms:requires": { "ceterms:targetLearningOpportunity": { "ceterms:availableAt": { "ceterms:addressRegion": [ "Indiana", { "search:value": "IN", "search:matchType": "search:exactMatch" } ] } } }, "ceterms:offeredBy": { "ceterms:address": { "ceterms:addressRegion": [ "Indiana", { "search:value": "IN", "search:matchType": "search:exactMatch" } ] } } } }

Credential Data Describing Related Resources

Some properties of credentials are intended to provide shortcuts for publishers of the data, to avoid needing to publish records for related data, such as assessments or learning opportunities. These properties will also need to be accounted for when designing your queries. For example:

  • ceterms:assessmentDeliveryType exists on credentials, but actually describes the ceterms:deliveryType of a related assessment (often where there is no actual assessment record).
  • ceterms:learningDeliveryType exists on credentials, but actually describes the ceterms:deliveryType of a related learning opportunity (often where there is no actual learning opportunity record).
  • Several properties exist on credentials, but typically actually apply to the program, course, or assessment that leads to the credential, rather than the credential itself. Some examples include:
    • ceterms:availableAt
    • ceterms:availableOnlineAt
    • ceterms:availabilityListing
    • ceterms:estimatedCost
    • ceterms:estimatedDuration
Certificates by Assessment Delivery Type
Search for all Certificates based on the ceterms:deliveryType of the required Assessment and/or the ceterms:assessmentDeliveryType property of the Credential. Since there is no way to know which properties may or may not have data, both must be queried using a Term Group and a search:operator with a value of search:orTerms.
{ "@type": "ceterms:Certificate", "search:termGroup": { "search:operator": "search:orTerms", "ceterms:assessmentDeliveryType": { "ceterms:targetNode": "deliveryType:InPerson" }, "ceterms:requires": { "ceterms:targetAssessment": { "ceterms:deliveryType": { "ceterms:targetNode": "deliveryType:InPerson" } } } } }

Returning Data

The results returned by the Search API always consist of the entire Registry record for each result, for the current "page" of results (in addition to a count of total results). There is no need to specify particular properties to return.

The following sections describe different aspects of how data is returned from the Search API.

Note that the following sections show the complete HTTP POST body object that would be sent to the Search API, whereas the examples above focus on the CTDL portion of the query.

Top-Level Resources

The Search API will only return results consisting of "top level" classes. Top level classes are those which have a CTID property. The following is a list of classes with CTIDs:

asn:ProgressionLevelasn:ProgressionModelceasn:Competencyceasn:CompetencyFrameworkceasn:Rubricceasn:RubricCriterionceterms:AcademicCertificateceterms:AccreditActionceterms:AdvancedStandingActionceterms:AlignmentMapceterms:ApprenticeshipCertificateceterms:ApproveActionceterms:AssessmentComponentceterms:AssessmentProfileceterms:AssociateDegreeceterms:AssociateOfAppliedArtsDegreeceterms:AssociateOfAppliedScienceDegreeceterms:AssociateOfArtsDegreeceterms:AssociateOfScienceDegreeceterms:BachelorDegreeceterms:BachelorOfArtsDegreeceterms:BachelorOfScienceDegreeceterms:Badgeceterms:BasicComponentceterms:BasicTechnicalCertificateceterms:Certificateceterms:CertificateOfCompletionceterms:CertificateOfParticipationceterms:Certificationceterms:CocurricularComponentceterms:Collectionceterms:CollectionComponentceterms:CompetencyComponentceterms:ConditionManifestceterms:CostManifestceterms:Courseceterms:CourseComponentceterms:Credentialceterms:CredentialComponentceterms:CredentialingActionceterms:CredentialOrganizationceterms:Degreeceterms:DigitalBadgeceterms:Diplomaceterms:DoctoralDegreeceterms:ExtracurricularComponentceterms:GeneralEducationDevelopmentceterms:GeneralEducationLevel1Certificateceterms:GeneralEducationLevel2Certificateceterms:HigherEducationLevel1Certificateceterms:HigherEducationLevel2Certificateceterms:Industryceterms:Jobceterms:JobComponentceterms:JourneymanCertificateceterms:LearningOpportunityProfileceterms:LearningProgramceterms:Licenseceterms:MasterCertificateceterms:MasterDegreeceterms:MasterOfArtsDegreeceterms:MasterOfScienceDegreeceterms:MicroCredentialceterms:MultiComponentceterms:Occupationceterms:OfferActionceterms:OpenBadgeceterms:Organizationceterms:Pathwayceterms:PathwaySetceterms:PostBaccalaureateCertificateceterms:PostMasterCertificateceterms:PreApprenticeshipCertificateceterms:ProfessionalCertificateceterms:ProfessionalDoctorateceterms:ProficiencyCertificateceterms:QACredentialOrganizationceterms:QualificationsFrameworkceterms:QualityAssuranceCredentialceterms:RecognizeActionceterms:RegistrationActionceterms:RegulateActionceterms:RenewActionceterms:ResearchDoctorateceterms:RevokeActionceterms:RightsActionceterms:ScheduledOfferingceterms:SecondaryEducationCertificateceterms:SecondarySchoolDiplomaceterms:SpecialistDegreeceterms:SupportServiceceterms:Taskceterms:TechnicalLevel1Certificateceterms:TechnicalLevel2Certificateceterms:TechnicalLevel3Certificateceterms:TransferIntermediaryceterms:TransferValueProfileceterms:VerificationServiceProfileceterms:WorkBasedLearningCertificateceterms:WorkExperienceComponentceterms:WorkforceDemandActionceterms:WorkRoleqdata:DataSetProfileqdata:Metricskos:Conceptskos:ConceptScheme

Paging: Skip and Take

Pagination is handled via the Skip and Take properties of the root of the query:

  • The Skip property indicates how many results (not how many pages) to skip, and uses a 0-based index.
  • The Take property indicates how many of the remaining results (after skipping) to include in the response. It has a maximum limit of 100 resources per page.
Pagination via Skip and Take (First Page)
Skip no results and take the first 20 results.
{ "Query": { "@type": "ceterms:Certificate", "ceterms:name": "Nursing" }, "Skip": 0, "Take": 20 }
Pagination via Skip and Take (Third Page)
Skip the first 40 results and take the next 20 results.
{ "Query": { "@type": "ceterms:Certificate", "ceterms:name": "Nursing" }, "Skip": 40, "Take": 20 }

Sort Order

You can control the sort order of results via the Sort property of the root of the query:

Sort by Record Updated
Sort the results by most recently updated Credential Registry record.
{ "Query": { "@type": "ceterms:Certificate", "ceterms:name": "Nursing" }, "Skip": 0, "Take": 10, "Sort": "search:recordUpdated" }

The Sort property accepts one of the following values:

  1. search:relevance - This will return results based on how closely their text-based properties match any text-based properties in your query. This is the default order if your query contains any text matching properties.
  2. search:recordUpdated - This will return results based on how recently the record was updated, with the most recently updated records coming first. This is the default order if your query does not contain any text matching properties.
  3. search:recordCreated - This will return results based on how recently the record was created, with the most recently created records coming first.
  4. You can also sort based on any alphanumeric property in the root level of the search results. For example, use ceterms:name to order results alphabetically (A-Z) by name.

Note: Do not confuse the usage of search:recordCreated and search:recordUpdated here as sort orders in the root of the query with the usage of those properties as filters in the body of the query as shown here.

Sort by Name (A-Z)
Sort the results by the ceterms:name property, A-Z.
{ "Query": { "@type": "ceterms:Certificate", "ceterms:keywords": "Nursing" }, "Skip": 0, "Take": 10, "Sort": "ceterms:name" }

To reverse the sort order, prefix the value with ^. For example, to sort records by ceterms:name in reverse (Z-A), use ^ceterms:name.

Sort by Name (Z-A)
Sort the results in reverse by the ceterms:name property, Z-A.
{ "Query": { "@type": "ceterms:Certificate", "ceterms:keywords": "Nursing" }, "Skip": 0, "Take": 10, "Sort": "^ceterms:name" }

Record Metadata

Additional metadata about the search results are also available as part of the response to a query. This metadata is encapsulated in an array of JSON objects separate from the results themselves, where each object in the array goes with one of the results. Such metadata includes:

  • ResourceURI - The URI of the search result that this metadata object describes
  • RecordCreated - The date and time that this Record was created in the Registry
  • RecordUpdated - The date and time that this Record was most recently updated in the Registry
  • RecordOwnedBy - The CTID of the organization that owns this Registry record (but does not necessarily own the resource described by the record)
  • RecordPublishedBy - The CTID of the organization that published this Registry record (but does not necessarily publish the resource described by the record)
  • RecordPublishType - Indicates whether this Record is considered a primary or secondary source record.

You can include the metadata in the response by using "IncludeResultsMetadata": true in the root of your query:

Include Record Metadata
Include additional metadata about the results.
{ "Query": { "@type": "ceterms:Certificate", "ceterms:keywords": "Nursing" }, "Skip": 0, "Take": 10, "IncludeResultsMetadata": true }

This will be included in the ResultsMetadata property of the response object:

Where to Find the Record Metadata
In the search results object, look for the ResultsMetadata property.
{ "data": [ "(Search results here...)" ], "valid": true, "status": "", "extra": { "TotalResults": 999, "ResultsMetadata": [ { "ResourceURI": "https://credentialengineregistry.org/resources/ce-fd3e874f-f1d3-4895-8c46-dfed04da9336", "RecordCreated": "2022-07-20T16:50:46.373Z", "RecordUpdated": "2022-07-20T16:50:46.373Z", "RecordOwnedBy": "ce-00efc2bd-d322-4242-a7fd-4a9783d99e54", "RecordPublishedBy": "ce-00efc2bd-d322-4242-a7fd-4a9783d99e54", "RecordPublishType": "primary" }, "(Additional Results Metadata objects...)" ] } }

Graph Data

Some resources contain additional objects in their JSON-LD @graph. These objects range from stub references to things which do not have full registry records (RDF Blank Nodes) to resources that exist as top level resources, but which are also closely tied to some other resource, such as:

  • The Competencies for a Competency Framework
  • The Concepts for a Concept Scheme
  • The Pathway Components for a Pathway

You can include the data from the @graphs for the results by using "IncludeGraphData": true in the root of your query:

Include Graph Data
Include the data from each search result's graph, if any exists.
{ "Query": { "@type": "ceasn:CompetencyFramework" }, "Skip": 0, "Take": 5, "IncludeGraphData": true }

All of the additional data from the results' @graphs (not including the results themselves) will be returned in the RelatedItems array of the response:

Where to Find the Graph Data
In the search results object, look for the RelatedItems property.
{ "data": [ "(Search results here...)" ], "valid": true, "status": "", "extra": { "TotalResults": 999, "RelatedItems": [ { "@id": "https://credentialengineregistry.org/resources/ce-73890ffa-42ca-441f-a0f6-d5e638bca9b5", "@type": "ceasn:Competency", "ceterms:ctid": "ce-73890ffa-42ca-441f-a0f6-d5e638bca9b5", "etc": "etc..." }, "(Additional Graph objects...)" ] } }

Description Sets and Other Related Data

A Description Set is a collection of resources directly relevant (and directly or indirectly connected to) some specific resource, typically beyond that resource's @graph. A Description Set is useful for obtaining a broad depth of data about and logically adjacent to a resource. For example, the Description Set for a credential might include:

  • The credential itself
  • The organization(s) that own or offer that credential
  • Any required assessments or learning opportunities for the credential
  • Any competencies related to the credential, either directly (e.g. the credential requires the competencies) and/or indirectly (e.g. the credential requires an assessment which assesses those competencies)
  • Other similarly relevant information

The Search API also supports returning the Description Sets for results, in two parts: The Description Set itself, and (optionally) the related resources connected via the linkages described by that Description Set. The Description Set itself is an array of objects that provide the URIs of the related resources for each result, along with a special path string that indicates the chain of properties and classes that connects that result to that list of related resources, including the directionality of those connections. A Description Set looks like this:

Example Description Set
Description Set data looks like this.
{ "ResourceURI": "https://credentialengineregistry.org/resources/ce-ac45b4e7-17ef-43c5-a05f-a48aae99c2e5", "RelatedItems": [ { "Path": "> ceterms:accreditedBy > ceterms:Agent", "TotalURIs": 1, "URIs": [ "https://credreg.net/bnodes/b43ef562-4ead-45b3-8296-a398da05534d" ] }, { "Path": "> ceterms:offeredBy > ceterms:Agent", "TotalURIs": 1, "URIs": [ "https://credentialengineregistry.org/resources/ce-a799a6db-1544-493b-9d73-978ea112beec" ] }, { "Path": "< ceterms:offers < ceterms:Agent > ceterms:accreditedBy > ceterms:Agent", "TotalURIs": 1, "URIs": [ "https://credentialengineregistry.org/resources/ce-541da30c-15dd-4ead-881b-729796024b8f" ] }, { "Path": "> ceterms:requires > ceterms:ConditionProfile > ceterms:targetLearningOpportunity > ceterms:LearningOpportunityProfile > ceterms:teaches > ceterms:CredentialAlignmentObject > ceterms:targetNode > ceasn:Competency", "TotalURIs": 4, "URIs": [ "https://credentialengineregistry.org/resources/ce-c0d927d8-1c69-4f87-b158-7a67becc1000", "https://credentialengineregistry.org/resources/ce-76979650-4ce9-42d9-bcbb-e6411694c203", "https://credentialengineregistry.org/resources/ce-71723aab-4c76-408d-b07d-6d7377268b06", "https://credentialengineregistry.org/resources/ce-137b33b8-7bb5-4932-8657-5e3b1feda840" ] }, { "Path": "< ceterms:targetCredential < ceterms:ConditionProfile < ceterms:isRequiredFor < ceterms:LearningOpportunityProfile", "TotalURIs": 1, "URIs": [ "https://credentialengineregistry.org/resources/ce-cf7deabe-9a69-4b67-aa55-9009ff357d7c" ] } ] }

The example above features several key aspects of Description Sets. Namely:

  • ResourceURI - The URI of the search result being described by this Description Set. This is used because Description Sets are returned in a different part of the response from the search results themselves.
  • RelatedItems - The array of objects describing the paths to or from the search result out to some other resource or set of resources, each of which includes:
    • Path - Describes the path taken, through a series of properties and classes, between the search result and the items referenced in the URIs array. The search result is always assumed to be the leftmost object, and the rightmost object is the type of resource being referenced. Path strings may contain a mix of outbound and inbound connections, represented by > and <, respectively. For example:
      • > ceterms:offeredBy > ceterms:Agent means "The search result has a ceterms:offeredBy property that references one or more instances of ceterms:Agent (the superclass for various types of organization), which are linked to in the URIs array".
      • < ceterms:offers < ceterms:Agent means "The search result is referenced by one or more instances of a ceterms:offers property, each of which belongs a ceterms:Agent (the superclass for various types of organization), which are linked to in the URIs array".
    • TotalURIs - A count of total URIs that belong with the provided path. When the number of URIs and/or related resources returned is limited (see below), this provides a way to know how many URIs would be in the URIs array if no limit were applied.
    • URIs - The list of URIs found on the rightmost end of the path. The number of URIs in the array is subject to the limit described below.

The DescriptionSetType property of the outermost layer of the query itself controls what kind of data is returned. It has the following options:

  1. "DescriptionSetType": "Resource" returns just the results themselves. This is the default option, so you do not need to include this property if you only want the resources.
  2. "DescriptionSetType": "Resource_RelatedURIs" returns the results, plus the Description Sets for those results.
  3. "DescriptionSetType": "Resource_RelatedURIs_RelatedData" returns all of the above, plus the related resources (in the RelatedItems array of the response).

Note: Description Sets, when combined with their related resources, may contain a lot of data, and returning them will often take longer than returning just the results. Only request Description Sets if your use case requires them. This is doubly true for returning related data.

You can limit the number of URIs returned for each connection in the Description Set using the DescriptionSetRelatedURIsLimit property in the root of your query. This will also limit the related resources returned to those whose URIs were included in the response.

Since the related resources for all results are combined in a single RelatedItems array in the response, there will only be no duplicate instances of a resource in that array. However, since each "page" of results is independent of each other "page", it is possible to return the same related items multiple times if multiple pages of your results have Description Sets which reference the same related resource. In other words, if 3 Credentials on one page of your results reference the same Organization, that Organization will only appear once in the RelatedItems array. However, if that same Organization is referenced by one or more Credentials on 3 pages of your results, that Organization will be returned once for each page. So again, it is important to only return the related resources if your use case truly needs them.

Example Description Set with Related Resources
Description Set data with related resources looks like this. Notice how the related items are only returned once per item (for the current page of results) even though they are referenced by the Description Sets for multiple search results within the current page.
{ "data": [ { "@id": "https://...sampleResult1", "other properties": "other values" }, { "@id": "https://...sampleResult2", "other properties": "other values" } ], "valid": true, "status": "", "extra": { "TotalResults": 100, "RelatedItemsMap": [ { "ResourceURI": "https://...sampleResult1", "RelatedItems": [ { "Path": "> ceterms:offeredBy > ceterms:Agent", "TotalURIs": 1, "URIs": [ "https://...sampleOrganization1" ] }, { "Path": "> ceterms:requires > ceterms:ConditionProfile > ceterms:targetLearningOpportunity > ceterms:LearningOpportunityProfile > ceterms:teaches > ceterms:CredentialAlignmentObject > ceterms:targetNode > ceasn:Competency", "TotalURIs": 2, "URIs": [ "https://...sampleCompetency1", "https://...sampleCompetency2" ] } ] }, { "ResourceURI": "https://...sampleResult2", "RelatedItems": [ { "Path": "> ceterms:offeredBy > ceterms:Agent", "TotalURIs": 1, "URIs": [ "https://...sampleOrganization1" ] }, { "Path": "> ceterms:requires > ceterms:ConditionProfile > ceterms:targetLearningOpportunity > ceterms:LearningOpportunityProfile > ceterms:teaches > ceterms:CredentialAlignmentObject > ceterms:targetNode > ceasn:Competency", "TotalURIs": 2, "URIs": [ "https://...sampleCompetency2", "https://...sampleCompetency3" ] } ] } ], "RelatedItems": [ { "@id": "https://...sampleOrganization1", "other properties": "other values" }, { "@id": "https://...sampleCompetency1", "other properties": "other values" }, { "@id": "https://...sampleCompetency2", "other properties": "other values" }, { "@id": "https://...sampleCompetency3", "other properties": "other values" } ] } }

Combining Graphs and Description Sets

It is possible to include @graph data in addition to Description Set data (see above). Note that the IncludeGraphData property ignores the DescriptionSetRelatedURIsLimit property, making it possible to return an entire @graph plus a limited Description Set for each result in a single query.

However, it is strongly advised that you only do so if/when truly necessary, in order to conserve resources and ensure the best speed/performance for your users. It is preferable, for example, to return only the resources for a search, and then use a separate page (after the user has clicked on a search result) to query for the @graph and/or Description Set for a single resource.

Calling the Search API

The Credential Registry supports the Search API on both its Sandbox and Production systems, with the following endpoints:

  • Sandbox: https://sandbox.credentialengine.org/assistant/search/ctdl
  • Production: https://apps.credentialengine.org/assistant/search/ctdl

To call the Search API, make an HTTP POST request to one of the above endpoints, including an Authorization header with a value of Bearer followed by a space and then your API key, for example:

Authorization Bearer abcdef12345

The body of the POST request will be the query object, for example:

Example query object
This is what your system will need to send to the API.
{ "Query": { "@type": [ "ceterms:Certificate", "ceterms:Certification" ] }, "Skip": 0, "Take": 5 }

For more examples, see the Query Helper section below.

Calling via Javascript

Warning: Do not make calls to the search API in a way that exposes your API key, such as via a client-side application or web browser. The API key should be kept secret.

A call to the search API via Javascript would look like this:

async function callSearch(keywords, organizationCTID, apiKey) { var response = await fetch("https://apps.credentialengine.org/assistant/search/ctdl", { method: "POST", headers: { "Accept": "application/json", "Content-Type": "application/json", "Authorization": "Bearer " + apiKey }, body: { "Query": { "@type": [ "ceterms:Certificate", "ceterms:Certification" ], "ceterms:name": "keywords", "ceterms:offeredBy": { "ceterms:ctid": organizationCTID } }, "Skip": 0, "Take": 20 } }); if (response.ok) { var responseJSON = await response.json(); return responseJSON; } else { // Handle error } }

Query Helper

The Query Helper is a tool meant to help developers build, test, and experiment with their queries. It provides:

  • A list of pre-made query examples
  • A simple interface for building basic queries
  • A simple query editor for creating fully customizable queries
  • An interface for configuring the root layer of the query
  • A display of exactly what the root layer of the query looks like (this is what your system will need to generate and send to the Search API in the body of your HTTP POST request)
  • Live, real-time results in both a simplified name/description display and raw JSON data formats

Additional Examples

The following sections provide additional query examples.

Simple Query Examples

Certificates by Name
Look for all Certificates with "nursing" in the name.
{ "@type": "ceterms:Certificate", "ceterms:name": "nursing" }
Competencies for Welding
All Competencies with "welding" in their text.
{ "@type": "ceasn:Competency", "ceasn:competencyText": "welding" }
Assessments from Owner
All Assessments or Learning Opportunities owned by an organization with a known URI.
{ "@type": [ "ceterms:AssessmentProfile", "ceterms:LearningOpportunityProfile" ], "ceterms:ownedBy": "https://credentialengineregistry.org/resources/ce-9e179080-3a4c-45ee-87bb-0538429a60ab" }
Any Resource for Programming
All resources, regardless of @type, with a ceterms:description that contains "programming"
{ "ceterms:description": "programming" }

Filtering by Nested Data Examples

Certificates by Requirements Description
Certificates with "paperwork" in the description of their requirements.
{ "@type": "ceterms:Certificate", "ceterms:requires": { "ceterms:description": "paperwork" } }
Organizations that Operate Globally
Organizations with a jurisdiction that is global.
{ "@type": [ "ceterms:Organization", "ceterms:CredentialOrganization", "ceterms:QACredentialOrganization" ], "ceterms:jurisdiction": { "ceterms:globalJurisdiction": true } }
Courses with a Particular Identifier
Courses with an identifier that comes from a specific source and has a particular value.
{ "@type": "ceterms:Course", "ceterms:identifier": { "ceterms:identifierType": "https://example.com/identifiers/coursecodes", "ceterms:identifierValueCode": "ABC-123" } }

Graph Traversal Examples

Degrees that Require Welding Assessments
Degrees that require Assessments with "welding" in the name.
{ "@type": [ "ceterms:Degree", "ceterms:AssociateDegree", "ceterms:BachelorDegree", "ceterms:DoctoralDegree", "ceterms:MasterDegree" ], "ceterms:requires": { "ceterms:targetAssessment": { "ceterms:name": "Welding" } } }
Organizations that Offer Particular Credential Types
Organizations that offer specific types of Credential.
{ "@type": [ "ceterms:Organization", "ceterms:CredentialOrganization", "ceterms:QACredentialOrganization" ], "ceterms:offers": { "@type": [ "ceterms:Certificate", "ceterms:Certification", "ceterms:MicroCredential" ] } }
Competency-Based Badges via Learning Opportunities
Credentials that require Learning Opportunities that teach Competencies with "programming" in their text.
{ "@type": [ "ceterms:Badge", "ceterms:DigitalBadge", "ceterms:OpenBadge" ], "ceterms:requires": { "ceterms:targetLearningOpportunity": { "ceterms:teaches": { "ceasn:competencyText": "programming" } } } }

Overriding AND vs OR Examples

Resources with Name AND Description
Resources (of any type) with "nursing" in both the name and description.
{ "ceterms:name": "nursing", "ceterms:description": "nursing" }
Resources with Name OR Description
Resources (of any type) with "nursing" in either the name or description.
{ "search:operator": "search:orTerms", "ceterms:name": "nursing", "ceterms:description": "nursing" }
Resources with ANY Specific Keywords
Resources (of any type) with at least one of three specific keywords
{ "ceterms:keyword": [ "keyword one", "keyword two", "keyword three" ] }
Resources with ALL Specific Keywords
Resources (of any type) with all three specific keywords
{ "ceterms:keyword": { "search:value": [ "keyword one", "keyword two", "keyword three" ], "search:operator": "search:andTerms" } }

Term Group Examples

Badges with Name OR Description
Resources that have one of the specified types and match at least one of the properties in the term group (via the use of search:orTerms).

Note that unlike nested term searching, a search:termGroup behaves as part of its parent object. A search:termGroup is akin to parenthesis in a mathematical equation, allowing sets of terms to be grouped together. The default "AND" logic of an object thus applies to both the @type property and the group as a whole, while the forced "OR" logic operates only within the group.
{ "@type": [ "ceterms:Badge", "ceterms:DigitalBadge", "ceterms:OpenBadge" ], "search:termGroup": { "search:operator": "search:orTerms", "search:name": "welding", "search:description": "welding" } }
Assessments Owned or Offered By a Particular Organization
Assessments that are either owned by or offered by a particular organization.
{ "@type": "ceterms:Assessment", "search:termGroup": { "search:operator": "search:orTerms", "ceterms:ownedBy": "https://credentialengineregistry.org/resources/ce-9e179080-3a4c-45ee-87bb-0538429a60ab", "ceterms:offeredBy": "https://credentialengineregistry.org/resources/ce-9e179080-3a4c-45ee-87bb-0538429a60ab" } }
Assessments Owned or Offered By Matching Organizations
Assessments owned by or offered by any organization with "college" in its name.
{ "@type": "ceterms:Assessment", "search:termGroup": { "search:operator": "search:orTerms", "ceterms:ownedBy": { "ceterms:name": "college" }, "ceterms:offeredBy": { "ceterms:name": "college" } } }
Credentials owned or offered by an Organization with "acme" in the name
Find credentials of any type that is owned or offered by an organization with particular text in its name.
{ "@type": { "search:value": "ceterms:Credential", "search:matchType": "search:subClassOf" }, "search:termGroup": { "search:operator": "search:orTerms", "ceterms:ownedBy": { "ceterms:name": "acme" }, "ceterms:offeredBy": { "ceterms:name": "acme" } } }
Credentials owned or offered by an Organization with a particular CTID
Find credentials of any type that is owned or offered by an organization with a CTID of "ce-cc3a828d-59b6-465d-b069-87ab9c1896d6".
{ "@type": { "search:value": "ceterms:Credential", "search:matchType": "search:subClassOf" }, "search:termGroup": { "search:operator": "search:orTerms", "ceterms:ownedBy": { "ceterms:ctid": "ce-cc3a828d-59b6-465d-b069-87ab9c1896d6" }, "ceterms:offeredBy": { "ceterms:ctid": "ce-cc3a828d-59b6-465d-b069-87ab9c1896d6" } } }
Indiana Credentials with SOC or CIP Codes
All credentials that 1) have either an instructional program type or an occupation type, and which 2) are either owned or offered by an organization with an address in Indiana.

This example uses search:termGroup with an internal search:value and search:operator to require that both term group objects match the result. Each term group uses search:orTerms internally, but both term group objects must match (because of the use of search:andTerms) in order for the whole search:value to match. This example demonstrates overriding the default logical AND-ing behavior of objects (via use of search:orTerms within each term group object) as well as the default logical OR-ing behavior of arrays (via use of search:andTerms next to the search:value array).

Use of search:value alongside search:operator is required here (rather than making the outermost search:termGroup an array and putting search:andTerms next to that) so that the query knows exactly what to apply the search:andTerms operator to.
{ "@type": { "search:value": "ceterms:Credential", "search:matchType": "search:subClassOf" }, "search:termGroup": { "search:value": [ { "ceterms:instructionalProgramType": "search:anyValue", "ceterms:occupationType": "search:anyValue", "search:operator": "search:orTerms" }, { "ceterms:ownedBy": { "ceterms:address": { "ceterms:addressRegion": [ { "search:value": "IN", "search:matchType": "search:exactMatch" }, { "search:value": "indiana" } ] } }, "ceterms:offeredBy": { "ceterms:address": { "ceterms:addressRegion": [ { "search:value": "IN", "search:matchType": "search:exactMatch" }, { "search:value": "indiana" } ] } }, "search:operator": "search:orTerms" } ], "search:operator": "search:andTerms" } }

Credential Alignment Object Examples

Credential Alignment Object and Classification Systems
Querying through a Credential Alignment Object that references an industry type. Note that this approach applies to ceterms:industryType, ceterms:occupationType, and ceterms:instructionalProgramType.
{ "@type": "ceterms:Certificate", "ceterms:industryType": { "ceterms:codedNotation": "236115" } }
Credential Alignment Object and Concepts
Querying through a Credential Alignment Object that references a skos:Concept.
{ "@type": "ceterms:Certificate", "ceterms:audienceLevelType": { "ceterms:targetNode": "audLevel:Graduate" } }
Credential Alignment Object and Competencies
Querying through a Credential Alignment Object that references a ceasn:Competency.
{ "@type": "ceterms:Certificate", "ceterms:requires": { "ceterms:targetCompetency": { "ceterms:targetNode": { "ceasn:competencyText": "programming" } } } }
Credential Alignment Object and Text
Querying through a Credential Alignment Object that only contains text, and does not reference any separate entity.
{ "@type": "ceterms:Certificate", "ceterms:requires": { "ceterms:targetCompetency": { "ceterms:targetNodeDescription": "programming" } } }

Finding Credentials Connected via Pathway

Suppose you have the data for a Certificate, and want to find any Credentials that any Pathways identify as directly requiring that Certificate. In other words, you want to find 1-n other Credentials that directly require your current Credential according to 1-n Pathways:

Doing so will require following a combination of forward and reverse connections. Let's break each part of the query down into steps, and then combine them:

Find all Pathway Components that reference my Credential
Find any Pathway Component that uses the ceterms:proxyFor property to reference a known Credential. This query includes a @type filter to avoid unintentionally returning things like Collection Members.
{ "@type": [ "ceterms:CredentialComponent", "ceterms:BasicComponent" ], "ceterms:proxyFor": { "ceterms:ctid": "ce-f0f23d10-1228-48ef-b4e9-9222a0921240" } }
Find all Pathway components that require my Pathway Component
Let's assume you only found one Pathway Component that references your Credential, and now you want to find any other Pathway Components that reference your Pathway Component via a Component Condition. Since we're going through a Component Condition, this query has an extra hop.
{ "ceterms:hasCondition": { "ceterms:targetComponent": { "ceterms:ctid": "ce-093f95ab-4419-4788-b825-e49af10d17ee" } } }

At this point, you have 1-n Pathway Components (just one in this example) that reference 1-n credentials via their ceterms:proxyFor property. No further querying is necessary, since you can just follow that link directly in the data.

However, if we wanted to combine all of our searching into one query, we would need to factor this extra hop in as well. Note that the combined query does not include the initial @type filter, since no unwanted kinds of entities would be a part of the complete chain of connections (in other words, only Pathway Components use all of the properties in play, so we don't need to worry about things like Collection Members).

It's also important to keep in mind that the root level of your query represents the results you want to return, which means the starting point for your query is actually the goal in the diagram above, and you need to work your way back to the starting point for your data, which is the known CTID for the Certificate.

Find all Credentials that require my Credential via a Pathway
This query combines the above notions into a single step. It uses an initial reverse lookup to find all resources referenced via ceterms:proxyFor, where said resources also have a ceterms:hasCondition relationship to a resource with a ceterms:targetComponent relationship to a resource with a ceterms:proxyFor relationship to the Credential that we're starting with.

In other words, it walks the above diagram backwards from the Master Degree on the right (the result we want to return) through the chain of connections we're interested in (direct requirement via a pathway) to our known starting point Credential (the Certificate).
{ "^ceterms:proxyFor": { "ceterms:hasCondition": { "ceterms:targetComponent": { "ceterms:proxyFor": { "ceterms:ctid": "ce-f0f23d10-1228-48ef-b4e9-9222a0921240" } } } } }

QData Examples

The following section provides examples for querying data that leverages the QData Schema. It is strongly recommended to review the QData section of the CTDL Handbook before continuing, as the following sections assume some basic knowledge of the structure and usage of QData.

Finding Data Set Profiles based on Summary Data

The Data Set Profile is the primary resource of the QData schema. Depending on what data the publisher chose to provide, it may or may not contain summary information intended to make it easier to find. For Data Set Profiles that do not contain summary information, you will need to query the contents of the Data Set Profile, such as its metrics and dimensions.

Find all Data Set Profiles
Find any resource in the Registry that is of @type qdata:DataSetProfile.
{ "@type": "qdata:DataSetProfile" }
Find Data Set Profiles based on Name and Description
As with many resources, Data Set Profiles can be queried by any combination of name and/or description. This example will return a match from either property.
{ "@type": "qdata:DataSetProfile", "search:termGroup": { "search:operator": "search:orTerms", "ceterms:name": "Workforce", "ceterms:description": "Workforce" } }
Find all Data Set Profiles from a Particular Organization
Often, you will be interested in finding Data Set Profiles from a specific provider. For this, you can use the CTID of the organization that provided the Data Set Profiles.
{ "@type": "qdata:DataSetProfile", "qdata:dataProvider": { "ceterms:ctid": "ce-a38117e5-a6bd-4fad-bf09-f15a575274df" } }
Find all Data Set Profiles about a Particular Resource
For any given Credential, Learning Opportunity, or other such resources, one or more Data Set Profiles may be available. In some cases, one Data Set Profile may cover more than one resource. Use the CTID(s) for the resource(s) to find any Data Set Profiles available for those resources.
{ "@type": "qdata:DataSetProfile", "qdata:relevantDataSetFor": [ { "ceterms:ctid": "ce-b0427413-6611-4573-b0c0-4e3f633cb7b7" } ] }
Find all Data Set Profiles from a Particular Provider about a Particular Resource with "Workforce" in the name and/or description
This query combines the above queries to retrieve data about a specific resource from a specific provider. Note that the name and description are queried inside the term group since a match in either one is sufficient, while the other properties must all match.
{ "@type": "qdata:DataSetProfile", "search:termGroup": { "search:operator": "search:orTerms", "ceterms:name": "Workforce", "ceterms:description": "Workforce" }, "qdata:dataProvider": { "ceterms:ctid": "ce-a38117e5-a6bd-4fad-bf09-f15a575274df" }, "qdata:relevantDataSetFor": [ { "ceterms:ctid": "ce-b0427413-6611-4573-b0c0-4e3f633cb7b7" } ] }
Find all Data Set Profiles for a Particular Time Frame
In some cases, a Data Set Profile will contain values for its qdata:dataSetTemporalCoverage property. This is intended to express the entire range of time that the Data Set Profile covers, even if its contents are for more specific time frames.

This query uses a ceterms:startDate range that is unbounded on one end and a ceterms:endDate range that is unbounded on the other end in order to find any Data Set Profiles with any startDate or endDate that falls within that broader range. See the Filtering by Date Properties section for more information about querying by range.
{ "@type": "qdata:DataSetProfile", "qdata:dataSetTemporalCoverage": { "ceterms:startDate": [ "2004-01-01", "" ], "ceterms:endDate": [ "", "2024-01-01" ] } }

Finding Data Set Profiles based on Internal Content

Below are some example queries for finding Data Set Profiles based on the kinds of content within those profiles.

Find Data Set Profiles based on Metric Type
This query will find Data Set Profiles which have Metrics that have a type of metricCat:Earnings.
{ "@type": "qdata:DataSetProfile", "qdata:hasMetric": { "qdata:metricType": "metricCat:Earnings" } }
Find Data Set Profiles based on Metric Text
This query will find Data Set Profiles which have Metrics that have a name and/or description that includes "graduates".
{ "@type": "qdata:DataSetProfile", "qdata:hasMetric": { "search:operator": "search:orTerms", "ceterms:name": "graduates", "ceterms:description": "graduates" } }
Find Data Set Profiles based on Dimension Type: Demographics
This query will find Data Set Profiles which have a Dimension of type demoCat:Employment.
{ "@type": "qdata:DataSetProfile", "qdata:hasDimension": { "qdata:dimensionType": "demoCat:Employment" } }
Find Data Set Profiles based on Dimension Type: Credentials
This query will find Data Set Profiles which have a Dimension of type of ceterms:Credential.
{ "@type": "qdata:DataSetProfile", "qdata:hasDimension": { "qdata:dimensionType": "ceterms:Credential" } }
Find Data Set Profiles based on Dimensions that Contain Time Frames
This query will find Data Set Profiles which have a Dimension where points along that dimension are of type qdata:DataSetTimeFrame. Note that this query checks the contents of the data, rather than the summary-level time-frames at the Data Set Profile level.
{ "@type": "qdata:DataSetProfile", "qdata:hasDimension": { "qdata:hasPoint": { "@type": "qdata:DataSetTimeFrame" } } }
Find Data Set Profiles based on Dimensions that Contain Time Frames from a Specific Period
This query will find Data Set Profiles which have a Dimension where points along that dimension are of type qdata:DataSetTimeFrame and at least one such time frame matches the indicated range.
{ "@type": "qdata:DataSetProfile", "qdata:hasDimension": { "qdata:hasPoint": { "@type": "qdata:DataSetTimeFrame", "ceterms:startDate": [ "2004-01-01", "" ], "ceterms:endDate": [ "", "2024-01-01" ] } } }
Find Data Set Profiles with Observations that use a Currency of USD
This query will find Data Set Profiles with any Observation(s) that use a schema:currency value of "USD".
{ "@type": "qdata:DataSetProfile", "qdata:hasObservation": { "schema:currency": "USD" } }
Find Data Set Profiles with Observations that have both a Metric and a Dimension
This query will find Data Set Profiles with any Observation(s) that reference both at least one Metric and at least one point along a Dimension.
{ "@type": "qdata:DataSetProfile", "qdata:hasObservation": { "qdata:isObservationOf": "search:anyValue", "qdata:atPoint": "search:anyValue" } }
Find Data Set Profiles with Observations that have a Metric but not a Dimension
This query will find Data Set Profiles with any Observation(s) that reference at least one Metric no points along a Dimension.
{ "@type": "qdata:DataSetProfile", "qdata:hasObservation": { "qdata:isObservationOf": "search:anyValue", "qdata:atPoint": "search:noValue" } }

References

BCP 47:
Best Current Practice 47 - Language Tags
https://tools.ietf.org/html/bcp47
bNode:
In RDF, a blank node (also called bnode) is a node in an RDF graph representing a resource for which a URI or literal is not given.
https://en.wikipedia.org/wiki/Blank_node
ISO 8601:
Data elements and interchange formats - Information interchange - Representation of dates and times:
https://en.wikipedia.org/wiki/ISO_8601
JSON-LD:
JSON Linked Data Specification
https://json-ld.org/
RDF:
Resource Description Framework (RDF)
https://www.w3.org/RDF/
RDF PRIMER:
Latest "RDF Primer" versions
https://www.w3.org/TR/rdf-primer/
SKOS:
Simple Knowledge Organization System (SKOS)
https://www.w3.org/2004/02/skos/
SKOS PRIMER:
SKOS (Simple Knowledge Organization System) Primer
https://www.w3.org/TR/2009/NOTE-skos-primer-20090818/
SKOS REF:
SKOS (Simple Knowledge Organization System) Reference
https://www.w3.org/TR/2009/REC-skos-reference-20090818/
URL:
Uniform Resource Locator
https://en.wikipedia.org/wiki/URL
W3C LD Glossary:
World Wide Web Consortium Linked Data Glossary
https://www.w3.org/TR/ld-glossary/