Skip to content

Accounts

Accounts represent channel connections (e.g., Airbnb, Hostaway, or other PMS accounts) linked to a user.

Endpoint Method Scope Description
/api/v1/users/<user_id>/accounts/ GET user:read List accounts for a user
/api/v1/users/<user_id>/accounts/ POST user:write Add an account for a user
/api/v1/users/<user_id>/accounts/<account_id>/ GET user:read Get one account for a user
/api/v1/users/<user_id>/accounts/<account_id>/refresh/ POST user:write Queue a full refresh for an account
/api/v1/users/<user_id>/accounts/<account_id>/ DELETE user:write Delete an account

Try it out

Explore parameters, schemas, supported channels with their required credentials, and live requests in the Swagger UI.

List Accounts

Returns a paginated list of accounts (channel connections) for the specified user.

Use this endpoint to monitor the background import that starts after an account is created. The response includes sync-status, which can be used to detect whether the account is still queued, in_progress, or completed.

For the end-to-end workflow, see the partner onboarding flow.

Request

GET /api/v1/users/456/accounts/
Parameter Description
page[number], page[size] Standard pagination. Default page size 25, maximum 100. Newest accounts first.

Response

{
  "data": [
    {
      "type": "accounts",
      "id": "123",
      "attributes": {
        "user-id": 456,
        "channel": "hostaway",
        "channel-id": "hw-account-789",
        "channel-display-id": null,
        "label": "Hostaway",
        "email": "user@example.com",
        "valid": true,
        "nb-enabled-listings": 12,
        "nb-listings": 15,
        "is-pms": true,
        "sync-status": {
          "state": "completed",
          "last-successful-sync-at": "2026-08-09T04:12:44Z"
        }
      }
    }
  ],
  "meta": {
    "pagination": {"page": 1, "pages": 1, "count": 1}
  }
}
Field Description
user-id The user who owns this account.
channel Channel identifier (e.g. airbnb, hostaway, guesty).
channel-id The account's identifier on the channel side.
channel-display-id Human-readable channel-side id, when the channel provides one; null otherwise.
label Human-readable channel label.
email Email associated with this account on the channel; null when the channel does not expose one.
valid Whether the stored credentials are currently valid on the channel.
nb-listings, nb-enabled-listings Total and enabled listing counts imported from this account.
is-pms Whether this channel is a property management system.
sync-status.state queued, in_progress, completed, or unknown.
sync-status.last-successful-sync-at Timestamp of the last successful listing sync; null if never synced.

Get Account

GET /api/v1/users/<user_id>/accounts/<account_id>/ returns one account, with the same attributes as the list entries above. 404 when the user or account is not visible to your token.

Add Account

Add a channel connection (account) for a user. Each channel requires specific credentials (API key, client ID/secret, JWT, etc.). The Swagger UI documents the complete list of 50+ supported channels and the credentials each one requires.

User-scoped tokens may call this endpoint, but the bound credential must have global edit or admin permissions.

Request

{
  "data": {
    "type": "accounts",
    "attributes": {
      "channel": "hostaway",
      "credentials": {
        "client_id": "12345",
        "client_secret": "abcdef123456"
      }
    }
  }
}
Field Description
channel Required. Channel identifier (e.g. hostify, hostaway, guesty). An unsupported value is a 400.
credentials Required. Channel-specific credential object — the field set differs per channel and is validated against that channel's schema. See the Swagger UI for every channel's required fields. Credential keys are snake_case, as shown.

The endpoint also accepts one optional query parameter:

Parameter Description
sync-priority Optional. high (the default) or normal. See Sync priority below. Any other value is a 400.

Returns 201 Created with the account resource (same shape as the list entries), with sync-status.state still queued.

If channel validation or authentication fails, the API returns 422 Unprocessable Entity with a meta.channel field identifying which channel failed and a meta.code field with the error type.

Send one request per account and wait for it to answer before sending another. Several POST /accounts/ calls for the same user and channel in flight at once all resolve to the same account and are applied one at a time; a request that waits too long for its turn — because another create or a credentials refresh for the same account is still running — is rejected with 409 Conflict and code: "concurrent_modification". It changed nothing and is safe to retry, but the wait is avoidable by not sending requests concurrently. See 409 -- Conflict.

Creating an account starts a background sync that imports reservation history and creates listings for the connected account. Rather than polling sync-status, subscribe to the account.created webhook, which fires once that sync finishes and reports how many listings were created.

Sync priority

The sync-priority query parameter tells Beyond how soon the account's import should start.

Value Effect Use it when
high Beyond starts the import as soon as it can. Someone is waiting on the result, for example an account connected during an interactive signup.
normal The import can take longer to start when Beyond is busy. You add many accounts at once and none of them is urgent.

The parameter is optional. A request that leaves it out is treated as high.

Priority affects only how soon the import starts. Either value imports the same data and fires the same account.created webhook.

POST /api/v1/users/456/accounts/?sync-priority=normal

The request body is unchanged:

{
  "data": {
    "type": "accounts",
    "attributes": {
      "channel": "hostify",
      "credentials": {
        "api_key": "your-api-key-here"
      }
    }
  }
}

Refresh Account

Queue a full listings and reservations refresh for an existing account.

User-scoped tokens may call this endpoint, but the bound credential must have global edit or admin permissions.

Use this endpoint when you want to manually trigger another import after the account has already been connected, for example after fixing channel-side data issues or when you want to force a fresh sync without reconnecting the account.

This refresh is prioritized ahead of normal queued work and replaces an existing pending account refresh that has not started yet.

If a sync for the account is already running, the API returns 409 Conflict instead of queuing another one. Wait for the in-progress sync to finish (or for the account.refreshed webhook, if registered) and retry shortly.

Request

POST /api/v1/users/456/accounts/123/refresh/?recent-sync-threshold-minutes=0
Parameter Description
recent-sync-threshold-minutes Optional. Skip listings synced within the last N minutes. Defaults to 60; 0 disables the skip and refreshes all listings. A non-integer value is a 400.

The snake_case spelling recent_sync_threshold_minutes is deprecated. The endpoint still accepts it, so existing integrations keep working, but new integrations must use recent-sync-threshold-minutes. When a request carries both, the dasherized name wins.

No request body. The endpoint returns 202 Accepted once the refresh job is queued:

{
  "meta": {
    "status": "accepted",
    "message": "Refresh queued",
    "recent-sync-threshold-minutes": 60
  },
  "links": {
    "related": "$BASE_URL/api/v1/users/456/accounts/123/"
  }
}

The refresh runs asynchronously — poll the account's sync-status via links.related, or subscribe to the account.refreshed webhook. Reservations are refreshed by separate background jobs and can still be in flight when that event fires.

Delete Account

Remove an account (channel connection) for the specified user.

User-scoped tokens may call this endpoint, but the bound credential must have global edit or admin permissions.

Returns 204 No Content on success.

Deleting and Re-creating an Account

Deleting an account is a soft delete: the account and its listings are retained, not erased. Re-creating the account with the same channel and credentials revives the same account, and its previously synced listings are resurrected on the next sync rather than being recreated from scratch.

Two conditions must hold for recovery to work:

  • The credentials must still be valid on the channel. A revoked or invalid key returns 422 with a Invalid Credentials error instead of reviving the account.
  • The channel must return the same account and listing IDs as before.

Errors

Status Cause
400 Unsupported channel, credentials failing the channel's schema, or an invalid recent-sync-threshold-minutes.
401 Missing or invalid bearer token.
403 Token lacks the required scope, or the bound credential lacks global edit/admin permissions for a write.
404 User or account not found, or not visible to your token.
409 Refresh requested while a sync is already running for the account (code: "sync_in_progress"), or the request timed out waiting for a concurrent operation on the same account (code: "concurrent_modification"). Both are transient — nothing about the request needs to change before retrying.
422 Channel validation/authentication failed (meta.channel names the channel, meta.code the error type).
429 Rate limit exceeded — refresh is additionally capped at 100 requests/minute. See Rate Limiting.
502 The channel's own API failed while validating the connection. Transient — retry with backoff.