API reference
Events
What each webhook event means and what it contains. To receive them, add a webhook for the types you need, or ["*"] for all.
The envelope
Every event has an id (the same on every retry), a type, the schemaVersion of its contents, createdAt and test. Events about a request carry the whole request in data.request as it was when the event was recorded, with its stateVersion; some add more, listed below.
Events can arrive more than once and out of order: skip ids you have seen, and don't overwrite stored request state with a snapshot whose stateVersion is lower than the one you have (still handle the event itself). Several events can share a stateVersion (service.grant_failed and connection.attempt_completed describe an attempt without changing the request, and can arrive after the service.granted it produced), and versions can skip numbers: moving to in_progress raises the version without sending an event. Demo requests send no events. Events are kept for 30 days.
client.created
A client was created, from the dashboard, the API or an access page.
{
"id": "evt_5b1f0c9a2e7d4c38a6f1d2e9b8c7a604",
"type": "client.created",
"schemaVersion": "2026-10-06",
"createdAt": "2026-10-07T10:02:10.000Z",
"test": false,
"data": {
"client": {
"id": "7c1e9f52-3b8a-4d2e-9a61-5f0c2d8b4e17",
"externalClientId": "crm-4821",
"name": "Jamie Rivera",
"...": "the client, as GET /clients/{id} returns it"
}
}
} request.created
An access request was created.
{
"id": "evt_5b1f0c9a2e7d4c38a6f1d2e9b8c7a604",
"type": "request.created",
"schemaVersion": "2026-10-06",
"createdAt": "2026-10-07T10:02:10.000Z",
"test": false,
"data": {
"request": {
"id": "2f6d8a14-91c3-4b7e-a5d0-8e3f1c6b9a72",
"status": "pending",
"stateVersion": 1,
"...": "the whole request, as GET /requests/{id} returns it"
}
}
} request.updated
The request changed in another way: you changed its services, re-requested access, reopened a completed request or unmarked a grant; or set an approval link (Amazon Ads, Shopify Collaborator); or the client reopened a skipped service or said they sent an invite you need to confirm (such as for Google Business Profile). One change can send more than one.
{
"id": "evt_5b1f0c9a2e7d4c38a6f1d2e9b8c7a604",
"type": "request.updated",
"schemaVersion": "2026-10-06",
"createdAt": "2026-10-07T10:02:10.000Z",
"test": false,
"data": {
"request": {
"id": "2f6d8a14-91c3-4b7e-a5d0-8e3f1c6b9a72",
"status": "in_progress",
"stateVersion": 5,
"...": "the whole request, as GET /requests/{id} returns it"
}
}
} service.granted
A service was granted: by the client, or marked granted by your team in the dashboard. Adds service: the service and its platform.
{
"id": "evt_5b1f0c9a2e7d4c38a6f1d2e9b8c7a604",
"type": "service.granted",
"schemaVersion": "2026-10-06",
"createdAt": "2026-10-07T10:02:10.000Z",
"test": false,
"data": {
"request": {
"id": "2f6d8a14-91c3-4b7e-a5d0-8e3f1c6b9a72",
"status": "in_progress",
"stateVersion": 5,
"...": "the whole request, as GET /requests/{id} returns it"
},
"service": {
"service": "Google Ads",
"platform": "Google"
}
}
} service.skipped
The client skipped an optional service. Required services cannot be skipped. Adds service: the service and its platform.
{
"id": "evt_5b1f0c9a2e7d4c38a6f1d2e9b8c7a604",
"type": "service.skipped",
"schemaVersion": "2026-10-06",
"createdAt": "2026-10-07T10:02:10.000Z",
"test": false,
"data": {
"request": {
"id": "2f6d8a14-91c3-4b7e-a5d0-8e3f1c6b9a72",
"status": "in_progress",
"stateVersion": 5,
"...": "the whole request, as GET /requests/{id} returns it"
},
"service": {
"service": "Meta Pixels",
"platform": "Meta"
}
}
} service.grant_failed
Granting a specific Google or Meta service failed. The client sees the error and can try again. Other platforms, and attempts that fail as a whole, report failures only in `connection.attempt_completed`. Adds service, and errors: what the client was shown (each up to 500 characters).
{
"id": "evt_5b1f0c9a2e7d4c38a6f1d2e9b8c7a604",
"type": "service.grant_failed",
"schemaVersion": "2026-10-06",
"createdAt": "2026-10-07T10:02:10.000Z",
"test": false,
"data": {
"request": {
"id": "2f6d8a14-91c3-4b7e-a5d0-8e3f1c6b9a72",
"status": "in_progress",
"stateVersion": 5,
"...": "the whole request, as GET /requests/{id} returns it"
},
"service": {
"service": "Google Ads",
"platform": "Google"
},
"errors": [
"The signed-in Google account has no access to this Google Ads account."
]
}
} connection.attempt_completed
A client finished an attempt to grant access in one step on Google, Meta, Amazon, Microsoft, LinkedIn or Snapchat and the attempt reached the platform, whatever its result. Services granted by following instructions, or granted while signing in, do not send it. Adds attempt: the platform, the outcome (success, partial_success or failed), each service's result and general errors (a server error is replaced with a generic message).
{
"id": "evt_5b1f0c9a2e7d4c38a6f1d2e9b8c7a604",
"type": "connection.attempt_completed",
"schemaVersion": "2026-10-06",
"createdAt": "2026-10-07T10:02:10.000Z",
"test": false,
"data": {
"request": {
"id": "2f6d8a14-91c3-4b7e-a5d0-8e3f1c6b9a72",
"status": "in_progress",
"stateVersion": 5,
"...": "the whole request, as GET /requests/{id} returns it"
},
"attempt": {
"platform": "Google",
"outcome": "partial_success",
"services": [
{
"service": "Google Ads",
"status": "granted",
"errors": []
},
{
"service": "Google Analytics",
"status": "failed",
"errors": [
"No Analytics properties were selected."
]
}
],
"errors": []
}
}
} intake.completed
The client submitted the intake form.
{
"id": "evt_5b1f0c9a2e7d4c38a6f1d2e9b8c7a604",
"type": "intake.completed",
"schemaVersion": "2026-10-06",
"createdAt": "2026-10-07T10:02:10.000Z",
"test": false,
"data": {
"request": {
"id": "2f6d8a14-91c3-4b7e-a5d0-8e3f1c6b9a72",
"status": "in_progress",
"stateVersion": 5,
"...": "the whole request, as GET /requests/{id} returns it"
}
}
} request.completed
Every service is granted (optional ones may be skipped instead, but not all of them) and the intake form, if requested, is submitted. If you later ask for more access, the request goes back to in progress and sends request.updated, then request.completed again when it completes.
{
"id": "evt_5b1f0c9a2e7d4c38a6f1d2e9b8c7a604",
"type": "request.completed",
"schemaVersion": "2026-10-06",
"createdAt": "2026-10-07T10:02:10.000Z",
"test": false,
"data": {
"request": {
"id": "2f6d8a14-91c3-4b7e-a5d0-8e3f1c6b9a72",
"status": "completed",
"stateVersion": 9,
"...": "the whole request, as GET /requests/{id} returns it"
}
}
} request.cancelled
The request was cancelled from the dashboard or the API.
{
"id": "evt_5b1f0c9a2e7d4c38a6f1d2e9b8c7a604",
"type": "request.cancelled",
"schemaVersion": "2026-10-06",
"createdAt": "2026-10-07T10:02:10.000Z",
"test": false,
"data": {
"request": {
"id": "2f6d8a14-91c3-4b7e-a5d0-8e3f1c6b9a72",
"status": "cancelled",
"stateVersion": 6,
"...": "the whole request, as GET /requests/{id} returns it"
}
}
} request.expired
The request passed its deadline before completing. The API reports it as expired right away; the event is sent when the expiry is recorded, shortly after.
{
"id": "evt_5b1f0c9a2e7d4c38a6f1d2e9b8c7a604",
"type": "request.expired",
"schemaVersion": "2026-10-06",
"createdAt": "2026-10-07T10:02:10.000Z",
"test": false,
"data": {
"request": {
"id": "2f6d8a14-91c3-4b7e-a5d0-8e3f1c6b9a72",
"status": "expired",
"stateVersion": 6,
"...": "the whole request, as GET /requests/{id} returns it"
}
}
} Test events
Sending a test from the dashboard or with POST /webhooks/{id}/test delivers a webhook.test event with "test": true. Test events are only sent on request, never for real changes, and are not retried.
{
"id": "evt_0c7e2b9f4a1d4e6c8b3f5a7d9e1c2b40",
"type": "webhook.test",
"schemaVersion": "2026-10-06",
"createdAt": "2026-10-07T10:05:00.000Z",
"test": true,
"data": {
"webhookId": "b81f3c2e-6a4d-4f19-9c7e-0d5a2e8f1b63",
"message": "This is a test event from AgencyAccess. It does not describe a real change."
}
}