Active & Inactive Listings

Every listing in your workspace is either active or inactive. You pay for active listings and work with them through the API. Inactive listings cost nothing and keep syncing, ready to activate when you need them. Switching never touches the connected Airbnb, Booking.com, or PMS account.

This is local to Repull only

Activating or deactivating a listing changes nothing on the upstream platform. It does not unlist, delete, snooze, or edit anything in your connected Airbnb, Booking.com, or channel-manager account.

What active and inactive mean

ActiveInactive
Billed, counts toward your plan's listing limitYesNo
Data keeps syncing and is keptYesYes
Readable and writable through the APIYesNo, 403 listing_inactive
Included in collection endpointsYesNo, left out
Webhooks deliveredYesNo

Use this to choose what you manage. If a connection brings in 50 listings and you only work with 20, deactivate the other 30: you stop paying for them, and the day you activate one its reservations, messages and reviews are already up to date.

Inactive listings in the API

  • Single-listing routes return 403 listing_inactive. That covers the listing itself (GET /v1/properties/{id}, GET /v1/listings/{id}) and everything that belongs to it: its reservations, conversations and messages, reviews and review replies, availability, pricing, content, photos, quotes, publish calls, and the channel routes for its Airbnb or Booking.com counterpart. A guest returns 403 only when every one of their reservations is on an inactive listing. The error lists the ids in listing_ids. See listing_inactive.
  • Collections leave inactive listings out. GET /v1/reservations, /v1/conversations, /v1/reviews and /v1/guests skip their data, including in pagination.total. Filtering by an inactive listing (?listing_id=) returns 403 rather than an empty page.
  • Listing lists default to active. GET /v1/listings and GET /v1/properties return active listings unless you pass ?status=inactive or ?status=all. Inactive rows carry identity fields only, id, name, status, inactiveReason, address.city and channels, so you can decide what to activate. inactiveReason says why: plan_limit(held back by your plan — activating needs a free slot or an upgrade), unlisted_on_airbnb, or deactivated (switched off by you). The channel lists (GET /v1/channels/airbnb/listings, /v1/channels/vrbo/listings, /v1/channels/booking/properties) take the same ?status=. Add ?include=thumbnail for a cover photo on every row — see Build a selection screen.
  • Webhooks are not delivered. Events about an inactive listing are dropped, not held. Activating resumes delivery for events from that moment on. Account-level events are always delivered. See Webhooks.
  • The toggles always work. PATCH /v1/listings/{id}, DELETE /v1/listings/{id} and POST /v1/listings/status accept inactive listings.
# Find the listings you can activate
curl "https://api.repull.dev/v1/listings?status=inactive" \
  -H "Authorization: Bearer sk_live_YOUR_KEY"

# {
#   "data": [
#     {
#       "id": "4119",
#       "name": "Harbor Loft",
#       "status": "inactive",
#       "channels": [{ "platform": "airbnb", "externalId": "1234567890123456789", "active": true, "syncEnabled": true }]
#     }
#   ],
#   "pagination": { "nextCursor": null, "hasMore": false }
# }

Build a selection screen

The screen where someone chooses what to activate is the first thing most people build on top of Repull, and a list of names is hard to choose from. Add ?include=thumbnailand every row comes back with a cover photo — active and inactive alike, in a single request, with no follow-up call per property.

The one thing an inactive listing will show you

An inactive listing normally answers 403 listing_inactive everywhere, and on a list it is reduced to its identity fields. ?include=thumbnailis the one exception, precisely because a picker is the one thing you are meant to do with an inactive listing. Everything else — address, content, details — still waits for activation.
# Your whole catalog, active and inactive, with cover photos
curl "https://api.repull.dev/v1/listings?status=all&include=thumbnail&limit=100" \
  -H "Authorization: Bearer sk_live_YOUR_KEY"

# {
#   "data": [
#     {
#       "id": "4118",
#       "name": "Ocean View Villa",
#       "address": { "street": "1 Shoreline Dr", "city": "Malibu" },
#       "thumbnailUrl": "https://a0.muscache.com/im/pictures/oceanview.jpg",
#       "status": "active",
#       "channels": [{ "platform": "airbnb", "externalId": "1234567890123456789", "active": true, "syncEnabled": true }],
#       "createdAt": "2024-12-15T20:39:07.346Z",
#       "updatedAt": "2026-09-01T09:14:22.101Z"
#     },
#     {
#       "id": "4119",
#       "name": "Harbor Loft",
#       "status": "inactive",
#       "channels": [{ "platform": "airbnb", "externalId": "9921884466103372", "active": true, "syncEnabled": true }],
#       "thumbnailUrl": "https://a0.muscache.com/im/pictures/harbor.jpg"
#     }
#   ],
#   "pagination": { "nextCursor": null, "hasMore": false, "total": 2 }
# }

What to expect

  • thumbnailUrl is a plain image URL. Put it straight in an <img src>: it does not expire and needs no authentication.
  • nullmeans the property has no cover photo yet. The property is still in the response — show a placeholder rather than hiding a property someone is looking for.
  • Leave the expansion off and the field is absent, not null. That is how you tell “no photo” apart from “I did not ask for photos”.
  • It is free: the photo already travels with the row, so asking for it does not make the call slower and does not use extra credits.
  • Only building an Airbnb picker? GET /v1/channels/airbnb/listings?include=thumbnail takes the same expansion and returns the Airbnb connection for each property alongside it.
  • Anything other than content, details or thumbnail returns 422 invalid_paramsnaming the values that work — a typo never silently drops the photos.

Activate or deactivate in bulk

POST/v1/listings/status

Sets up to 500 listings active or inactive in one call. The call is all or nothing: either every listing ends up in the requested state, or nothing changes.

# Deactivate three listings
curl -X POST "https://api.repull.dev/v1/listings/status" \
  -H "Authorization: Bearer sk_live_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "listingIds": ["4118", "4119", "4120"], "active": false }'

# Activate them again (subject to your plan's listing limit)
curl -X POST "https://api.repull.dev/v1/listings/status" \
  -H "Authorization: Bearer sk_live_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "listingIds": ["4118", "4119", "4120"], "active": true }'

Body parameters

listingIdsstring[]Required

Listing ids to change, 1 to 500, each at most once. Send them as GET /v1/listings returns them (strings); plain integers are accepted too.

activebooleanRequired

false deactivates every listing in listingIds; true activates them. Active listings count toward your plan's listing limit.

Response

{
  "active": false,
  "updated": ["4118", "4120"],
  "unchanged": ["4119"]
}
activeboolean

The state every listing in the request is now in.

updatedstring[]

Listing ids this call changed, in request order.

unchangedstring[]

Listing ids that were already in the requested state, in request order. Re-sending a request is safe.

Errors

  • 404 not_found: at least one id is not a listing in your workspace. Nothing changes; listing_ids names the unknown ids.
  • 402 listings_limit_exceeded: activating would take you over your plan's listing limit. Nothing changes. Only listings that are currently inactive count toward the new total, so re-sending ids that are already active never trips it. See listings_limit_exceeded.
  • 422 invalid_params: listingIds is empty, has more than 500 entries, repeats an id, or contains something that is not an id, or active is not a boolean. field names the problem.

Works while you are over your limit

When your workspace is over its plan's listing limit, most endpoints return 402 listings_limit_exceeded. POST /v1/listings/status, PATCH /v1/listings/{id} and DELETE /v1/listings/{id} keep working, so you can always deactivate your way back under it.

Activate or deactivate one listing

PATCH/v1/listings/:id

Set active to false to deactivate a listing, or true to activate it. Setting a listing to the state it is already in returns 200. Activating returns 402 listings_limit_exceededwhen it would take you over your plan's listing limit.

# Deactivate
curl -X PATCH "https://api.repull.dev/v1/listings/4118" \
  -H "Authorization: Bearer sk_live_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "active": false }'

# Activate (subject to your plan's listing limit)
curl -X PATCH "https://api.repull.dev/v1/listings/4118" \
  -H "Authorization: Bearer sk_live_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "active": true }'

Body parameters

activebooleanRequired

false deactivates the listing; true activates it, subject to your plan's listing limit.

Response

{
  "id": "4118",
  "active": false
}
idstring

The listing id.

activeboolean

The listing's state after the call.

Deactivate with DELETE

DELETE/v1/listings/:id

The same as PATCH with {"active": false}. Despite the verb, nothing is deleted: the listing is kept and keeps syncing. Returns the same {id, active} response.

curl -X DELETE "https://api.repull.dev/v1/listings/4118" \
  -H "Authorization: Bearer sk_live_YOUR_KEY"

How listings become inactive

  • You deactivate them, with the endpoints above or the toggle on your listings page.
  • You disconnect the account they came from. DELETE /v1/connect/{provider} deactivates that account's listings, unless a listing is still connected through another account or channel. See Disconnect an account.
  • They are unlisted on Airbnb when first imported. Connecting Airbnb imports every listing on the account, including unlisted ones. New listings that are listed on Airbnb arrive active; new unlisted ones arrive inactive. Listings added on Airbnb after you connect are picked up by a daily refresh, following the same rule. A later sync never changes the state of a listing you already have.

What does not change upstream

  • The listing stays live and bookable on Airbnb, Booking.com, or wherever it originated.
  • Your connected PMS or channel-manager account is untouched. No listing is unlisted or deleted.
  • Reservations, guests, and messages on the upstream platform are unaffected, and keep syncing into Repull.

What you're billed for

You are billed for your active listings, nothing else. An inactive listing costs nothing, whether or not it is taking bookings.

“Inactive” means inactive in Repull. Unlisting or snoozing a property on Airbnb does not change your Repull billing on its own. Deactivate it here and it drops out of the count.

Choosing what you pay for

  • In the dashboard: open Listings, find the property, and click Deactivate. Use the status filter to see everything that is currently active.
  • Over the API: POST /v1/listings/status for many listings, or PATCH /v1/listings/{id} for one.
AI