Docs/Channels/Airbnb

Airbnb Resolution Center

View Airbnb Resolution Center cases — the requests you and your guests open to move money after a booking (damage claims, cancellations, adjustments). A pure read of the local mirror: every response carries the dataFreshness envelope, and POST on the same path pulls the latest cases from Airbnb. The money a resolved case moves shows up in Transactions — join a case id to a transaction reference.

GET/v1/channels/airbnb/resolutions

Parameters

account_idstring

Scope the response to ONE connected Airbnb account. The value is the Airbnb host id — the same accounts[].externalAccountId that GET /v1/connect/airbnb returns and DELETE /v1/connect/airbnb?accountId= accepts. Omit it to read every connected account (the default). An id that is not connected to this workspace returns 404 not_found with field: "account_id" and your own ids in valid_values. This is not the X-Account-Id header, which carries a connection id and cannot tell two Airbnb hosts apart.

statusstring

Filter by case status: open or closed

Several Airbnb accounts

A workspace can connect more than one Airbnb account. By default this route returns every connected account's rows; pass ?account_id=<airbnb host id> to scope to one. Every row carries account_id + account_name either way (this route is snake_case throughout), so you can group without a second call. Airbnb host ids exceed 2^53 — keep them as strings and never parse them as numbers: Number("1000000000000000002") is 1772489413932732200, a different account, and returns 404. A two-account walkthrough lives on the Account scope page (/docs/scoping).

# Every connected account — the default, unchanged
curl 'https://api.repull.dev/v1/channels/airbnb/resolutions' \
  -H "Authorization: Bearer sk_live_YOUR_KEY"

# Just one account
curl 'https://api.repull.dev/v1/channels/airbnb/resolutions?account_id=1000000000000000002' \
  -H "Authorization: Bearer sk_live_YOUR_KEY"

# An id this workspace has not connected — 404, with your own ids to copy
# {
#   "error": {
#     "code": "not_found",
#     "message": "No connected Airbnb account `1772489413932732200` in this workspace.",
#     "field": "account_id",
#     "value_received": "1772489413932732200",
#     "valid_values": ["1000000000000000002", "80000001"]
#   }
# }

Data freshness

Airbnb reads are served from Repull's local mirror and never call Airbnb upstream, so every response carries a dataFreshness envelope telling you whether to trust it. lastSyncedAt is the last import that actually landed data — a run that failed or was rate-limited never moves it. accounts[] gives the verdict per connected account; it is omitted when the workspace has no Airbnb account to attribute.

  • Top-level stale: true means every connected account is stale — nothing in the response is current. For the single-account workspace this is exactly the old behaviour.
  • Top-level stale: false with reason: "partial_account_staleness" means some accounts are fine and some are not. The response is usable; read accounts[] to see which rows to distrust. The reason is emitted deliberately even though stale is false, so a consumer reading only the aggregate is never told everything is fine while one account is down.
  • Top-level stale: false with no reason means every account is current.
  • With ?account_id=, accounts[] holds exactly that account and the top-level fields mirror it.
  • reason is one of host_disconnected_since_<iso>, host_disconnected, host_not_activated, sync_lag_>_24h, never_synced, or partial_account_staleness. fixUrl is the dashboard screen that resolves it.
{
  "dataFreshness": {
    "lastSyncedAt": "2026-09-18T04:12:09.000Z",
    "stale": false,
    "reason": "partial_account_staleness",
    "fixUrl": "https://repull.dev/dashboard/connections",
    "accounts": [
      {
        "accountId": "1000000000000000002",
        "accountName": "Seaside Stays",
        "lastSyncedAt": "2026-09-18T04:12:09.000Z",
        "stale": false
      },
      {
        "accountId": "80000001",
        "accountName": "Casey",
        "lastSyncedAt": null,
        "stale": true,
        "reason": "host_disconnected",
        "fixUrl": "https://repull.dev/dashboard/connections"
      }
    ]
  }
}

Get one case

Fetch a single case with GET /v1/channels/airbnb/resolutions/{id}, where {id} is the resolution id from the list (and the reference on the matching transaction). Returns 404 when the case is not in this workspace — POST the list endpoint to refresh first.

Example

# List all resolution cases
curl "https://api.repull.dev/v1/channels/airbnb/resolutions" \
  -H "Authorization: Bearer sk_live_YOUR_KEY"

# Only open cases
curl "https://api.repull.dev/v1/channels/airbnb/resolutions?status=open" \
  -H "Authorization: Bearer sk_live_YOUR_KEY"

# Refresh from Airbnb, then read
curl -X POST "https://api.repull.dev/v1/channels/airbnb/resolutions" \
  -H "Authorization: Bearer sk_live_YOUR_KEY"

# Get one case by id
curl "https://api.repull.dev/v1/channels/airbnb/resolutions/1234567890" \
  -H "Authorization: Bearer sk_live_YOUR_KEY"
AI