Account Created¶
Sent when the background listing sync that follows adding a managed account reaches a terminal state — every listing on the account has been pulled from the channel and created in Beyond, or the sync failed. Use it to learn when an account you just connected is ready, without polling.
| Event type | account.created |
| Resource type | account-created-events |
| Triggered by | POST /api/v1/users/{user_id}/accounts/ |
When It Fires¶
The create-account endpoint validates your credentials against the channel and
returns 201 Created right away. The real work — pulling every listing on the
account — happens afterwards, in the background:
flowchart LR
A[POST /users/id/accounts/] --> B[Validate credentials]
B -- invalid --> X[422 / 502 response<br/>no event]
B -- valid --> C[201 Created]
C --> D[Background: pull listings<br/>from the channel]
D --> E{{account.created}}
This event fires exactly once when the background sync reaches a terminal state:
status: succeeded— every listing on the account synced without error.status: failed— at least one listing failed, or the sync itself did not complete. Theerrorattribute carries a short, human-readable summary.
Because a delivery retry re-uses the same webhook-id, dedupe on it (see
idempotency).
succeeded means listings exist, not that they are priced
Each listing is priced independently after it is created. A listing becomes
fully set up when its initial base price is computed, and emits its own
listing.created event at that point. Wait for
account.created to know the account's listings are all present; wait for
each listing.created to know a listing is priced.
Credential errors are reported synchronously
Invalid credentials, an unsupported 2FA prompt, or a channel outage are
returned on the POST response itself (422 / 502) and emit no event
— the account is never created, so there is nothing to sync.
Re-created accounts¶
Deleting a managed account and adding it again with the same channel and
credentials revives the original account and restores its listings rather
than creating new ones. account.created fires the same way in that case, with
the same fields; the restored listings are counted in nb-listings-synced.
Payload¶
{
"meta": {
"type": "account.created",
"sent-at": "2026-07-03T12:34:56Z"
},
"data": {
"type": "account-created-events",
"id": "msg_01J9Z6M0K3QK7YV8N2C4B5A6D7",
"attributes": {
"status": "succeeded",
"completed-at": "2026-07-03T12:34:56Z",
"channel": "hostaway",
"nb-listings-synced": 40,
"nb-listings-failed": 0
},
"relationships": {
"user": {
"data": { "type": "users", "id": "456" },
"links": { "related": "https://developers.beyondpricing.com/api/v1/users/456/" }
},
"account": {
"data": { "type": "accounts", "id": "789" },
"links": { "related": "https://developers.beyondpricing.com/api/v1/users/456/accounts/789/" }
}
}
}
}
{
"meta": {
"type": "account.created",
"sent-at": "2026-07-03T12:40:00Z"
},
"data": {
"type": "account-created-events",
"id": "msg_01J9Z6M0K3QK7YV8N2C4B5A6D7",
"attributes": {
"status": "failed",
"completed-at": "2026-07-03T12:40:00Z",
"channel": "hostaway",
"nb-listings-synced": 38,
"nb-listings-failed": 2,
"error": "2 listing(s) failed to sync"
},
"relationships": {
"user": {
"data": { "type": "users", "id": "456" }
},
"account": {
"data": { "type": "accounts", "id": "789" }
}
}
}
}
{
"meta": {
"type": "account.created",
"sent-at": "2026-07-03T12:40:00Z"
},
"data": {
"type": "account-created-events",
"id": "msg_01J9Z6M0K3QK7YV8N2C4B5A6D7",
"attributes": {
"status": "failed",
"completed-at": "2026-07-03T12:40:00Z",
"channel": "hostaway",
"nb-listings-synced": 0,
"nb-listings-failed": null,
"error": "The account's listing sync did not complete successfully"
},
"relationships": {
"user": {
"data": { "type": "users", "id": "456" }
},
"account": {
"data": { "type": "accounts", "id": "789" }
}
}
}
}
The meta envelope is documented in the Payload
Envelope section.
data.attributes¶
| Field | Type | Description |
|---|---|---|
status |
string | Terminal outcome: succeeded or failed. |
completed-at |
string (RFC 3339) | UTC timestamp when the sync reached its terminal state. |
channel |
string | The channel the account is connected to (e.g. airbnb, hostaway). |
nb-listings-synced |
integer | Number of listings successfully created — or, for a re-created account, restored — on this account by the sync. |
nb-listings-failed |
integer | null | Number of listings the sync could not create. Always present; 0 when status is succeeded. It is null when the sync did not run to completion (an infrastructure failure, or a channel-wide error), so the per-listing count is unknown — in that case nb-listings-synced reports how many listings exist on the account. |
error |
string | null | Short, human-readable failure description. Present only when status is failed; stable across retries of the same delivery. |
data.relationships¶
Every relationship carries a links.related URL you can GET for the current
state of the related resource.
| Relationship | Description |
|---|---|
user |
The user the account belongs to ({ "type": "users", "id": … }). |
account |
The managed account that was created ({ "type": "accounts", "id": … }). |
Handling Tips¶
- On
succeeded, the account's listings all exist — a good moment toGET/listings/for the user. Their base prices arrive shortly after, each announced by alisting.createdevent. - On
failedwith a numericnb-listings-failed, some listings did sync: read the listings you have, and re-add the account (or contact support) to retry the rest. Anullmeans the sync did not finish and nothing can be concluded about individual listings. - Do not treat
nb-listings-syncedas the account's permanent listing count — listings are added and removed on the channel over time. Followaccount.links.relatedor list the user's listings for current state.