General Concepts
A short reference for the cross-cutting concepts that come up across multiple TimeBack endpoints. Read this once before diving into the level-specific guides.
IRI vs Object References
In Caliper events, almost every field that points at another entity — actor, edApp, object, target, generated, referrer, and the nested assignee / assignable inside object — accepts either form:
- An IRI string (e.g.,
"urn:uuid:550e8400-e29b-41d4-a716-446655440000"), used when the entity is already known to the platform. - A full object (e.g.,
{ "id": "urn:uuid:...", "type": "Person" }), used when introducing or updating the entity.
Both forms are valid. The platform resolves an IRI by looking up the corresponding entity. If no entity exists for that IRI yet, it creates a minimal record so subsequent events that send the full object can fill in the rest. This means events can arrive in any order without losing data.
// IRI form (compact — entity already known):
{
"actor": "urn:uuid:550e8400-e29b-41d4-a716-446655440000"
}
// Object form (verbose — introduces or updates the entity):
{
"actor": {
"id": "urn:uuid:550e8400-e29b-41d4-a716-446655440000",
"type": "Person"
}
}
Use the IRI form whenever you don't need to update the entity's fields — it keeps payloads smaller and removes the chance of accidentally overwriting platform-managed metadata.
IRI Format Requirements
A valid IRI on this platform must be one of:
| Form | Example |
|---|---|
urn:uuid:<RFC4122 UUID> |
urn:uuid:550e8400-e29b-41d4-a716-446655440000 |
urn:email:<address> |
urn:email:student@example.org |
| Absolute HTTPS URL | https://example.org/learners/123 |
Common pitfalls to avoid:
- Raw OAuth Client IDs are not UUIDs. A Cognito identifier such as
5tmupnc4d06v62bs3kildccjrdwill fail URN-UUID validation. See App ID vs OAuth Client ID. - IRIs must be lowercase for the URN portion.
URN:UUID:...is normalised internally but you should send lowercase to avoid round-trip surprises. - Trailing whitespace, surrounding quotes, and embedded angle brackets all fail validation.
If your IRI is rejected, the response will name the validation rule that failed (for example, URN with uuid namespace must contain a valid UUID) so you can correct the value directly.
App ID vs OAuth Client ID
When your app is onboarded, you receive two distinct identifiers:
| Identifier | What it looks like | Where it goes |
|---|---|---|
| App ID | UUID, e.g. 550e8400-e29b-41d4-a716-446655440000 |
edApp.id in Caliper events (as urn:uuid:<App ID>) |
| OAuth Client ID | Cognito identifier, e.g. 5tmupnc4d06v62bs3kildccjrd |
The OAuth token request, paired with the Client Secret |
These are not interchangeable. The Client ID is for authentication only — it identifies the credentials used to obtain an access token. The App ID is your application's identity inside TimeBack and is what events refer to when they describe which app produced them.
A frequent mistake is to use the OAuth Client ID as edApp.id. Because Cognito IDs aren't valid UUIDs, the request will be rejected with an IRI validation error.
Caliper Envelope Endpoint and Async Ingest
The canonical event-write endpoint is:
POST /caliper/v1p2
It accepts a Caliper Envelope whose data array contains Caliper Events only — entity-describe items (standalone Entity objects intended to introduce an entity ahead of any event) are not supported on this endpoint. Introduce or update entities by sending events that embed the full object form, or rely on the IRI-resolution behaviour described above.
A successful submission returns:
HTTP/1.1 202 Accepted
The 202 signals that the envelope was structurally valid and accepted onto the ingest queue — not that every event has been fully processed. Resolution of actor, edApp, sessions, organisations, and other references is asynchronous. As a consequence:
- Events whose identifiers eventually resolve to known entities will appear in the analytics endpoints once processing completes.
- Events that reference identifiers the platform never sees described in any event are kept as stub records — they remain queryable by id but won't be associated with rich entity metadata.
- An event with a structurally valid envelope but semantically wrong identifiers (e.g., a typo in
actor) will not surface as a clear error. If you don't see expected data downstream, double-check the identifiers used in the events you sent.
For local development, send a known good actor and edApp and read back via /xp/1.0/users/{id}/entries to confirm round-trip ingestion before scaling up.
Token Endpoint Scope Semantics
The token endpoint (POST /auth/1.0/token) issues an access token for the OAuth client_credentials grant. Scope behaviour to keep in mind:
- All-or-nothing. If any scope you request is not authorised for your client, the entire token request is rejected; the platform does not grant a partial subset and silently drop the rest. Each request must list only scopes you've been granted.
400 invalid_scope. A rejected scope produces an OAuth-standard400 invalid_scoperesponse. When the offending scope can be identified, the response'serror_descriptionnames it explicitly so you can drop or correct the scope without a separate diagnosis cycle.401 invalid_clientis reserved for genuine client-authentication failures — wrong credentials, missing Basic Auth header, or revoked client. If you see this response, the issue is the client ID/secret, not the scope set.400 unsupported_grant_typemeans the request used a grant other thanclient_credentials. Onlyclient_credentialsis accepted on this endpoint.
If you're unsure which of several requested scopes is causing a rejection, request them one at a time. Any specific rejection you receive will already include the offending scope in the description, but probing individually is the fastest way to confirm exactly which scope your client is missing.
