Docs/Channels/Airbnb

Airbnb Amenities

Read and write the amenities on an Airbnb listing, including accessibility amenities. Writes are partial: only the amenities you name change.

PUT/v1/channels/airbnb/listings/:id/amenities

Parameters

idpathRequired

The Repull listing id (not the Airbnb listing id).

amenitiesarray

[{"id": "wireless_internet", "is_present": true}]. id is an Airbnb amenity id; case is ignored. is_present is required — true claims the amenity, false removes it.

instructionstring

Optional host note shown with an amenity, 500 characters or fewer.

accessibility_amenitiesarray

Same shape, plus an optional photo_ids array carrying the Airbnb photo ids that evidence the claim.

Writes are partial

Only the amenities you name change. Turning one off is a one-line body and nothing else on the listing moves — you never have to read the full set, edit it and send it back, and there is no way to wipe a listing's amenities by omission.

  • {id} is the Repull listing id — from GET /v1/properties or GET /v1/channels/airbnb/listings — not the Airbnb listing id. Repull translates it before calling Airbnb.
  • Ids are the id values GET /v1/channels/airbnb/listings/{id}/amenities returns — wireless_internet, ac, kitchen, hot_water. Case is ignored on the way in.
  • Airbnb's amenity vocabulary is its own: wifi, air_conditioning and hot_tub are not valid Airbnb ids (the real ones are wireless_internet, ac, jacuzzi). An id outside the vocabulary comes back as 422 airbnb_rejected with Airbnb's own message, so read the ids off a GET rather than guessing them.
  • At least one amenity is required. A body that would change nothing is refused rather than reported as a successful write.

Accessibility amenities

Step-free access, wide doorways, grab rails, roll-in showers, accessible-height fixtures, hoists and disabled parking are a separate set on Airbnb, and this endpoint writes them through accessibility_amenities.

  • Airbnb has no way to read them back. There is no endpoint that returns a listing's accessibility amenities, and the combined amenities resource does not answer for production listings either. This is an Airbnb limitation, not a Repull one.
  • What you *can* read back is Repull's copy: this endpoint updates it on success, and GET /v1/channels/airbnb/listings/{id}/amenities returns it under accessibilityAmenities. That read reflects your writes, but it cannot independently confirm what Airbnb is showing on the live listing — check the listing itself if that matters to you.
  • Airbnb may hold an accessibility claim for review until photo evidence is attached. Pass photo_ids with the Airbnb photo ids that show the feature (from GET /v1/channels/airbnb/listings/{id}/photos).
curl -X PUT https://api.repull.dev/v1/channels/airbnb/listings/4118/amenities \
  -H "Authorization: Bearer sk_live_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{"accessibility_amenities": [
        {"id": "step_free_access", "is_present": true, "photo_ids": ["1583920174"]}
      ]}'

Reading your writes back

GET /v1/channels/airbnb/listings/{id}/amenities reflects a successful write straight away — it does not wait for the next sync. The platform-neutral view, GET /v1/listings/{id}?include=amenities, uses Repull's own amenity vocabulary rather than Airbnb's; where an id happens to be identical in both it updates with the write, and otherwise it refreshes on the next sync.

Errors

A successful write returns 200.

  • 422 invalid_params — the body failed validation before anything was sent to Airbnb. field names the field (for example operations.0.max_nights), value_received echoes it and fix says what to send.
  • 422 airbnb_rejected — Airbnb refused the change. message carries Airbnb's own reason. Correct the request; sending the same body again is refused again.
  • 403 listing_not_api_connected — Airbnb API sync is off for this listing (its sync category is none), so Airbnb accepts no writes to it and nothing was sent. Reconnecting the Airbnb account does not fix this — the host has to turn API sync on for that one listing inside Airbnb. See the section above, and https://repull.dev/docs/errors/listing_not_api_connected
  • 403 connection_reauth_required — the host's Airbnb authorization expired or was revoked, or Airbnb refused to refresh it. This takes the whole account down, not one listing. Retrying will not help. Reconnect Airbnb at https://repull.dev/dashboard/connections (or POST /v1/connect/airbnb), then retry.
  • 403 listing_inactive — the listing is inactive. Activate it with PATCH /v1/listings/{id} and {"active": true}, then retry.
  • 404 not_found — no Airbnb-connected listing with this id in your workspace. Check the id is the Repull listing id. 404 no_connection — the workspace has no Airbnb connection at all.
  • 429 airbnb_rate_limited — Airbnb is rate-limiting writes for this host. Wait retry_after seconds when present, otherwise back off exponentially, and put many dates in one operations array instead of one call per date.
  • 502 airbnb_error — Airbnb had an outage or timed out. Nothing about the request needs to change: retry with backoff.

Example

# Claim wifi, drop the air conditioning
curl -X PUT https://api.repull.dev/v1/channels/airbnb/listings/4118/amenities \
  -H "Authorization: Bearer sk_live_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{"amenities": [
        {"id": "wireless_internet", "is_present": true},
        {"id": "ac", "is_present": false, "instruction": "Removed for winter"}
      ]}'

# Read them back, split into regular and accessibility
curl https://api.repull.dev/v1/channels/airbnb/listings/4118/amenities \
  -H "Authorization: Bearer sk_live_YOUR_KEY"

Response

// 200 — PUT /amenities
{
  "data": { "amenities": 2, "accessibilityAmenities": 0 },
  "stored": true
}
AI