> ## Documentation Index
> Fetch the complete documentation index at: https://docs.trdrs.co/llms.txt
> Use this file to discover all available pages before exploring further.

# Follow registrations

> Two events tell you when a handoff completed or was taken down — and one list route settles any disagreement.

A registration sits pending until a trader acts on it, and nothing on your side knows when that
happens unless you ask. Two webhook events answer it as it happens:
`registration.linked` and `registration.revoked`.

This guide is about those two events only. The endpoint, the signature, the retries, and the
delivery log are the same for every event type and live in [Receive
events](/guides/receive-events) — wire that first, then come back here.

<Steps>
  <Step title="Subscribe to the two registration events">
    [Create a webhook](/api-reference/webhooks/create-a-webhook) with an `events` filter when a
    system only cares about onboarding. An omitted or empty `events` list receives everything,
    including event types added later.

    ```bash theme={null}
    curl -X POST "$TRDRS_API_BASE_URL/api/partner/webhooks" \
      -H "Authorization: Bearer $TRDRS_PARTNER_KEY" \
      -H "Content-Type: application/json" \
      -d '{
        "url": "https://ops.yourfirm.example/hooks/trdrs-onboarding",
        "events": ["registration.linked", "registration.revoked"]
      }'
    ```

    Five endpoints per firm, so an onboarding service and a billing service can each hold their own
    filter rather than sharing one handler.
  </Step>

  <Step title="Read the payload">
    Every delivery is a POST with the same envelope: a `type`, a `createdAt`, and a `data` object.
    For these two, `data` names the registration, the trader's email, and the account number —
    exactly the three things you sent when you created it, so your own record is findable without a
    lookup table.

    ```json theme={null}
    {
      "type": "registration.linked",
      "createdAt": "2026-08-24T19:04:12.318Z",
      "data": {
        "registrationId": "reg_7f3ka9",
        "email": "trader@example.com",
        "accountNumber": "PA-4821-07"
      }
    }
    ```

    | Event                  | Fires when                                                     | What your side should do                                                                                    |
    | ---------------------- | -------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------- |
    | `registration.linked`  | A trader signed in and linked an account your firm registered. | Mark the handoff complete. From here the account can trade, and it can start counting toward usage.         |
    | `registration.revoked` | Your firm revoked a pending registration.                      | Close the loop on the revocation your own system asked for — this is the confirmation, not the instruction. |

    There is no event for a registration expiring. A pending registration that nobody links reaches
    its `expiresAt` silently, so expiry is something you notice on the list, not something that
    arrives.
  </Step>

  <Step title="Make the handler idempotent">
    A non-`2xx` answer — including a timeout — is retried with backoff for about nine hours in
    total, so your endpoint may see the same event twice. Key your processing on the delivery `id`
    from the log, or on `registrationId` in the payload. Either is stable; the arrival is not.
  </Step>

  <Step title="Reconcile against the list route">
    [List your registrations](/api-reference/connect/list-your-registrations) is the settling read.
    It returns every registration your firm has made, newest first, with its current `status` and
    `linkedAt`, and it is computed from the same records the events are emitted from.

    ```bash theme={null}
    curl "$TRDRS_API_BASE_URL/api/partner/connect/accounts" \
      -H "Authorization: Bearer $TRDRS_PARTNER_KEY"
    ```

    Run it on a schedule and diff it against your own table. Anything your table calls pending that
    the list calls `linked` is a delivery you dropped; anything the list calls `expired` is a
    trader who never arrived.
  </Step>
</Steps>

## When your records and ours disagree

Work down this order — each step is cheaper than the one after it.

1. **The list route.** It is the source of truth for status. If it says `linked`, the handoff
   happened, whatever your table says.
2. **[The delivery log](/api-reference/webhooks/list-webhook-deliveries).** Every attempt for one
   endpoint, newest first, each row carrying the exact payload we sent — so an event your receiver
   dropped can be replayed from here rather than lost. `pending` means the delivery is still inside
   its retry schedule; `failed` means the schedule was exhausted and we stopped.
3. **[A test delivery](/api-reference/webhooks/create-a-test-delivery).** A signed `ping`, right
   now, reporting exactly what your endpoint answered. It separates a broken delivery from a
   handler that is refusing.

Terminal delivery rows age out after 60 days; a pending row is never swept. If you delete an
endpoint, its delivery log goes with it — read anything you still need first.

## Where to go deeper

* [Receive events](/guides/receive-events) — the endpoint, the signature, the retry schedule, the log.
* [Register an account](/guides/register-an-account) — the lifecycle these events report on.
* [Events and webhooks](/partner-platform/operator-concepts/events-and-webhooks) — the delivery contract in full.
* [Connect Overview](/guides/connect-overview) — where registrations sit in the product.
