For journeys implemented with the Orchestration SDK, completion is determined by the terminal SDK response: Success or Rejection.
For journeys involving user authentication steps, successful completion can initiate a backend token exchange flow. In this model, your client receives an opaque code and passes it to your backend. Your backend then exchanges the opaque code with Mosaic in a server-to-server call to obtain the user access token together with enriched context. This is the recommended mode when you do not want Mosaic user tokens to pass through the client and you want the backend to receive the token directly. It lets you:
- keep user access tokens off the client
- establish session or backend trust using the backend
- align journey orchestration with a more secure token delivery pattern
- use Mosaic capabilities that depend on the backend receiving the access token directly, such as BYOK
Not every successful journey produces a user token flow. If the journey completes successfully but does not authenticate the user, treat Success as the final orchestration result and do not expect a user access token.
This page describes the current SDK journey completion model. Some older integrations still rely on the legacy journey token returned upon successful completion. If your integration depends on that additional legacy artifact, see Journey token.
The Orchestration SDK returns the terminal result. For journeys involving user authentication steps, a successful completion returns an opaque code. Your client passes that code to your backend, which exchanges it with Mosaic using POST /ido/api/v2/token/exchange?clientId=[YOUR_CLIENT_ID]. Your backend then uses the returned user tokens and enriched context to establish the application session or run other business logic.
The opaque code is a short-lived, one-time-use exchange credential.
- the code expires after a short time, up to 5 minutes
- the code can be used only once
- after a successful exchange, the code cannot be reused
This means your backend should exchange the code immediately after receiving it from the client.
To use backend token exchange:
- the journey includes an authentication step
- your backend calls the exchange endpoint
- the backend client is assigned the required Journey Code Exchange (Write) permission. In Mosaic, configure this access by creating or editing a client role under Applications > Client roles, enabling Authentication > Authentication > Journey Code Exchange (Write), and then assigning that role to the backend client under Applications > your app > Clients. Client roles can only be assigned to first-party app clients. For more details, see Manage client roles.
- only a client with that permission on the same
appIdcan consume the opaque code - treat the SDK completion response as the orchestration outcome, and the backend exchange as the authentication outcome
For SDK integration details, see the quickstarts for Web, iOS, Android, and React Native. For user token validation, see Validate tokens.
Endpoint Name: Token Exchange API
Description: Exchanges a one-time opaque code generated upon successful authenticated journey completion for Mosaic user tokens. The code is bound to the journey and application, has a short lifetime, and is consumed on use.
Base URL: https://api.transmitsecurity.io
The base URL can vary depending on your environment:
- Production regions:
api.transmitsecurity.io(US),api.eu.transmitsecurity.io(EU),api.ca.transmitsecurity.io(Canada),api.au.transmitsecurity.io(Australia) - Sandbox:
api.sbx.transmitsecurity.io - Custom domain: If you're using a custom domain for your Mosaic application, replace the host in the base URL with your custom domain.
Method: POST
URL: /ido/api/v2/token/exchange?clientId=[YOUR_CLIENT_ID]
Authentication Required: Yes
For clientId, use the Client ID from the settings of the application running the journey. This ensures the request is routed to the correct application.
Authorize the request using a bearer token generated for the backend client. The token must contain:
- an
app_idclaim - the permission
execute:<app_id>:auth-tokens
This endpoint is different from the standard /oidc/token endpoint. Use /oidc/token only to obtain the backend client's bearer token for authorizing the token exchange request.
To obtain this bearer token, generate a client access token using the /oidc/token endpoint with the backend client credentials. You can find the backend client's Client ID and Client Secret in the Admin Portal > Applications > your app > Clients.
Headers Required:
Content-Type: application/jsonAuthorization: Bearer <BACKEND_CLIENT_ACCESS_TOKEN>
curl -X POST \
"https://api.sbx.transmitsecurity.io/ido/api/v2/token/exchange?clientId=<CLIENT_ID>" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <BACKEND_CLIENT_ACCESS_TOKEN>" \
-d '{
"code": "OPAQUE_CODE",
"journeyId": "JOURNEY_ID"
}'| Parameter | Type | Required | Description |
|---|---|---|---|
clientId | string | Yes | Query string parameter containing the Client ID of the application running the journey |
code | string | Yes | One-time opaque code returned after successful authenticated journey completion |
journeyId | string | Yes | Identifier of the journey that generated the code |
Authorization | string | Yes | Bearer token for the backend client. Must contain an app_id claim and the execute:<app_id>:auth-tokens permission |
A successful response contains user tokens and a session identifier, for example:
{
"access_token": "ACCESS_TOKEN",
"id_token": "ID_TOKEN",
"refresh_token": "REFRESH_TOKEN",
"session_id": "SESSION_ID"
}The returned access_token is a JWT access token that includes IDO-specific custom claims under custom_claims.ido, including:
journey_idsession_idinvocation_idcorrelation_idjourney_name
| Field Name | Type | Description |
|---|---|---|
access_token | string | JWT access token enriched with IDO-specific custom claims under custom_claims.ido |
id_token | string | OpenID Connect ID token |
refresh_token | string | OAuth 2.0 refresh token |
session_id | string | Server-side session identifier |
{
"error_code": 5007,
"message": "invalid_grant"
}Returned when the code is invalid, expired, already consumed, or does not match the supplied journeyId.
{
"error_code": 5001,
"message": "Bad credentials provided, appId not found in token claims"
}Returned when the bearer token is missing or invalid, when the token does not include an app_id claim, or when the backend client is missing the required permission.
The behavior described above is the current SDK journey completion model for authenticated journeys.
If your tenant still uses the legacy journey token behavior, check the global Return journey token on completion setting under B2B or B2C Identity (based on your implementation) > Identity Journeys > Journey settings.
For existing tenants, this setting is enabled by default to preserve backward compatibility. For new tenants, this setting is disabled by default.
- if the setting is enabled, successful journey completion returns a journey token in addition to the opaque code and any user access tokens issued after successful authentication
- if you disable the setting, the legacy journey token is no longer returned
The setting does not control whether authenticated journeys return the opaque code. For successful journeys with an authentication step, the opaque code is returned regardless of whether this setting is enabled.
The journey token is a legacy completion artifact. It does not include OIDC access tokens or ID tokens.
For details about the legacy behavior, see Journey token.