Recovering from desynchronization

If your Experience persists its own list of Experience Connections and Assignments and then loses it — a database failure, a bad migration, a restore from an old backup — you need to rebuild that list from Alianza. This page is the procedure.

Webhooks keep you in sync going forward. This is what to do when "going forward" is no longer enough because your baseline is gone.

1. Make sure webhooks are being handled first

Before you backfill, confirm your endpoint is receiving and processing events. Otherwise you will finish a long re-sync only to be stale again by the time it completes — changes made during the backfill would be lost.

With webhooks running, a change that lands mid-backfill still reaches you, and the updatedAt comparison below keeps it from being clobbered by older list data.

2. Re-read every Experience Connection

List the connections for your Experience and store them. The response is cursor-paged, so keep requesting while a cursor is present.

Initial request

GET {baseUrl}/experience-connections?experienceId=<your-experience-id>
Authorization: Bearer <access_token>
{
  "pageSize": 100,
  "cursor": "3b5e7838-199e-4510-aca8-758f1373041e",
  "entities": [
    {
      "id": "5ba215ef-9152-451b-8c0a-30797fa7e6c4",
      "accountId": "019e1cf7-0e8c-79b0-afc1-d03124571e96",
      "experienceId": "1376f97d-4e9e-4636-b908-4fefd928066d",
      "state": "ACTIVE",
      "updatedAt": "2026-07-16T00:34:15.702279372Z"
    }
  ]
}

Subsequent request — pass the cursor back:

GET {baseUrl}/experience-connections?experienceId=<your-experience-id>&cursor=3b5e7838-199e-4510-aca8-758f1373041e
Authorization: Bearer <access_token>

The last page comes back without a cursor.

Compare updatedAt before you write. A webhook event that arrived while you were paging may already hold newer state than the list page you are processing. Only overwrite a stored record when the incoming updatedAt is newer.

3. Re-read every Experience Assignment

Same procedure against the assignments endpoint:

GET {baseUrl}/experience-assignments?experienceId=<your-experience-id>
Authorization: Bearer <access_token>
{
  "pageSize": 100,
  "cursor": "2b5e7838-199e-4510-aca8-758f1373041e",
  "entities": [
    {
      "id": "0464432b-4020-4658-a76c-38b6ea1b6ef5",
      "experienceId": "1376f97d-4e9e-4636-b908-4fefd928066d",
      "accountId": "019e1cf7-0e8c-79b0-afc1-d03124571e96",
      "targetType": "USER",
      "targetValue": "019e1cf9-9a67-7320-a919-493a437a9e12",
      "updatedAt": "2026-07-16T00:34:15.702279372Z"
    }
  ]
}

Page through with the returned cursor exactly as above.

4. Reconcile deletions

The steps above repair records that still exist. They cannot tell you about records that no longer do — and a stale connection or assignment in your store is worse than a missing one, because your Experience will believe it is still live for a customer it has been removed from.

So treat the full lists as authoritative: any connection or assignment in your store that does not appear in Alianza's lists, and was not just delivered to you by webhook, has been deleted. Remove it.

The webhook caveat matters. A record created moments ago might arrive by webhook before it shows up in a list page you already fetched, so do not delete something the event stream just told you about.

Summary

Step Action
1 Confirm webhook processing is live before starting
2 Page through GET /experience-connections?experienceId=…, honouring updatedAt
3 Page through GET /experience-assignments?experienceId=…, honouring updatedAt
4 Delete stored records absent from both lists and not just received by webhook

Paging rate

A full re-sync fits comfortably inside the API's rate limit of 100 requests per second per credential. At the maximum pageSize of 100, an Experience with 10,000 Connections is 100 requests — roughly a second of traffic, and both lists together still only a few seconds.

So pace the re-sync for your own safety rather than the limit's: page sequentially, one request at a time, and you will not come close to the ceiling. The realistic way to trip it is retrying failures in a tight loop, so back off on error instead of retrying immediately.

See also

  • Event reference — payload schemas, including the updatedAt field this procedure relies on.
  • API conventions — how cursor pagination works across the API.