# Signed Token Callback Flow

Use the Signed Token Callback Flow when the Advertiser does not operate OAuth 2.0 or wants a smaller integration surface.
Onward places an opaque, short-lived connection token in the Advertiser redirect. After sign-up or sign-in, the
Advertiser backend sends that token and its stable user identifier back to Onward.

## Responsibilities

| Actor | Responsibility |
| --- | --- |
| Platform | Verify its current user, start the connection, and redirect the browser to the URL returned by Onward. |
| Advertiser | Preserve the connection token during sign-up or sign-in and confirm the result from its backend. |
| Onward | Validate the token, link the identities, evaluate optional retroactive events, and provide the Platform return URL. |

## Flow

1. The Platform reads the active quest chain and identifies a task with `condition_event_type: "link_account"`.
2. The Platform backend calls
   [`POST /v1/account/start-connect`](/docs/api-reference/account-connection-api#start-oauth-account-linking) with
   `platform_user_id`, `quest_chain_id`, and its return `redirect_url`.
3. Onward returns a `redirect_url` pointing to the Advertiser with a signed connection token.
4. The Platform redirects the browser to that URL.
5. The Advertiser signs the user in or creates an account while preserving the token.
6. The Advertiser backend calls
   [`POST /v1/users/connect-account`](/docs/api-reference/account-connection-api#complete-oauth-account-linking) with the
   token and `advertiser_user_id`.
7. Onward validates the token, links the identities, evaluates optional retroactive events, and returns the Platform
   redirect URL.
8. The Advertiser redirects the browser to that URL.

<Mermaid
  chart={`sequenceDiagram
    participant Browser
    participant PlatformBackend as Platform backend
    participant Onward as Onward API
    participant AdvertiserBackend as Advertiser backend

    Browser->>PlatformBackend: Start account-linking task
    PlatformBackend->>Onward: POST /v1/account/start-connect
    Onward-->>PlatformBackend: redirect_url with signed token
    PlatformBackend-->>Browser: Redirect to Advertiser
    Browser->>AdvertiserBackend: Sign up or sign in
    AdvertiserBackend->>Onward: POST /v1/users/connect-account
    Onward->>Onward: Verify token and link identities
    Onward-->>AdvertiserBackend: Connection result and Platform redirect_url
    AdvertiserBackend-->>Browser: Redirect to Platform`}
  caption="Signed Token Callback Flow. API credentials and the connection token stay on backend systems."
/>

## Start the connection

The Platform starts this mechanism through the same backend-only `start-connect` call used for OAuth 2.0. The Platform
does not select the mechanism in the request; Onward uses the Advertiser's configured integration and returns the correct
URL.

The Platform must treat the returned `data.redirect_url` as opaque. It should redirect the browser without extracting,
rewriting, or storing the embedded connection token.

## Advertiser landing page

The Advertiser provides a sign-up or connection page that can receive the Onward token. Preserve the token through the
user's sign-up or sign-in session, but do not expose it to analytics, logs, referrer URLs, or unrelated browser storage.

After the user has a stable Advertiser identity, the Advertiser backend confirms the connection:

```http
POST /v1/users/connect-account
Content-Type: application/json
X-API-Key: <advertiser-api-key>
X-API-Secret: <advertiser-api-secret>

{
  "token": "<opaque-connection-token>",
  "advertiser_user_id": "advertiser-user-123",
  "metadata": {
    "loyalty_tier": "gold"
  }
}
```

`advertiser_user_id` must be a stable identifier from the Advertiser system. Do not use an email address or another value
that can be reassigned unless the Advertiser contract explicitly guarantees its permanence.

## Completion

Onward verifies that the token is valid, unexpired, unused, and issued for the calling Advertiser. A successful response
contains the linked identifiers and the validated `redirect_url` supplied by the Platform at the start of the flow.

The Advertiser redirects the browser to that URL. The Platform should then refresh the active quest chain and render the
authoritative task state rather than relying only on redirect parameters.

For actions that happened before confirmation, see
[Retroactive events](/docs/account-linking/retroactive-events). Before implementation, review
[Security requirements](/docs/account-linking/security-requirements).
