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 5tmupnc4d06v62bs3kildccjrd will 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-standard 400 invalid_scope response. When the offending scope can be identified, the response's error_description names it explicitly so you can drop or correct the scope without a separate diagnosis cycle.
  • 401 invalid_client is 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_type means the request used a grant other than client_credentials. Only client_credentials is 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.