Conversations
List conversations
/v1/conversationsRequest
curl https://api.repull.dev/v1/conversations?limit=20 \ -H "Authorization: Bearer $REPULL_API_KEY"
Response
{
"data": [
{
"id": "123",
"platform": "airbnb",
"guestId": "123",
"listingId": "123",
"reservationId": "123",
"subject": "Example text",
"lastMessageAt": "2026-06-01T12:00:00.000Z",
"lastMessagePreview": "Example text",
"unreadCount": 0,
"status": "open",
"createdAt": "2026-06-01T12:00:00.000Z",
"updatedAt": "2026-06-01T12:00:00.000Z",
"externalThreadId": "123"
}
],
"pagination": {
"nextCursor": "eyJpZCI6MTIzfQ==",
"hasMore": true,
"total": 0
}
}Captured from a real response. Regenerated on every release, and CI fails if this shape stops matching the API.
Query Parameters
accountstringOnly one connected account's records, as `provider:externalAccountId` (e.g. `airbnb:79730216`, `booking:10167991`, `vrbo:36`, `hostaway:…`) — the pair on every webhook `account` block, on `connect.session.completed`, and on each record's `account`. See /for-platforms.
cursorstringOpaque cursor returned in the previous response's `pagination.nextCursor`. Omit to fetch the first page.
offsetintegerFirst-class alias for cursor-based pagination. Mutually exclusive with `cursor` — passing both returns 422. Accepts integers in `[0, 10000]`; deeper walks must use `cursor` (constant per-page cost). The response always includes `pagination.nextCursor` so consumers can switch from offset → cursor mid-walk for deep pagination without re-keying.
limitintegerMax items per page. Hard cap is 100.
platformstringRestrict to threads on a single channel.
statusstringFilter by archive status. `archived` currently always returns an empty page — kept for forward-compat.
Get messages in a conversation
/v1/conversations/:id/messagesRequest
curl https://api.repull.dev/v1/conversations/123/messages?limit=20 \ -H "Authorization: Bearer $REPULL_API_KEY"
Response
{
"data": [
{
"id": "123",
"externalMessageId": "123",
"direction": "outbound",
"senderType": "user",
"senderName": "Example",
"senderAvatar": null,
"channel": "airbnb",
"body": "Example text",
"translatedBody": null,
"attachments": [],
"isAutomated": false,
"aiGenerated": false,
"sentAt": "2026-06-01T12:00:00.000Z",
"deliveredAt": "2026-06-01T12:00:00.000Z",
"readAt": null
}
],
"pagination": {
"nextCursor": "eyJpZCI6MTIzfQ==",
"hasMore": true
}
}Captured from a real response. Regenerated on every release, and CI fails if this shape stops matching the API.
Send a message in a conversation
/v1/conversations/:id/messagesNote
Request
curl -X POST https://api.repull.dev/v1/conversations/123/messages \
-H "Authorization: Bearer $REPULL_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"message": "Welcome to your stay!"
}'Response
{
"id": "1847911",
"conversationId": "164743",
"externalMessageId": "32837172381",
"channel": "airbnb",
"status": "sent",
"direction": "outbound",
"contentRewritten": false,
"submittedContent": "Your check-in details are ready.",
"deliveredContent": "Your check-in details are ready.",
"statusReason": null,
"attachments": []
}Body Parameters
messagestringThe text to send the guest, up to 4000 characters. Required unless you send attachments, and always required on Booking.com.
channelstringForce a channel. Omit to send on whichever channel the conversation already uses, which is the right default. `airbnb`, `booking`, `vrbo`, `sms`, `email` or `website` — or, on a conversation a connected PMS relays, the PMS's own channel name.
attachmentsarray1 to 5 files as `{ url, contentType?, filename? }`. Each `url` must be a public https URL, up to 10 MB. Supported on Airbnb and Booking.com; other channels return 422 attachments_not_supported and nothing is sent.
List Airbnb inquiries
/v1/inquiriesNote
Request
curl https://api.repull.dev/v1/inquiries?status=open \ -H "Authorization: Bearer $REPULL_API_KEY"
Response
{
"data": [
{
"id": "25173",
"conversationId": "164743",
"listingId": "23892",
"channel": "airbnb",
"status": "open",
"checkIn": "2026-10-01",
"checkOut": "2026-10-05",
"guests": { "total": 2, "adults": 2, "children": 0, "infants": 0, "pets": 0 },
"expectedPayout": { "amount": 812.4, "currency": "USD" },
"reservationId": null,
"relayedBy": null,
"respondBy": "2026-09-23T17:40:38.000Z",
"respondedAt": null,
"createdAt": "2026-09-22T17:40:38.000Z",
"updatedAt": "2026-09-22T17:40:38.000Z"
}
],
"pagination": { "nextCursor": null, "hasMore": false }
}Query Parameters
statusstringDefault: openopen, pre_approved, special_offer_sent, booked, expired, declined, not_possible, or all.
listing_idintegerOnly inquiries about this Repull listing.
conversation_idintegerThe inquiry on one conversation. Combine with status=all.
limitintegerDefault: 50Max 100.
cursorstringpagination.nextCursor from the previous page.
offsetintegerAlias for shallow paging, 0 to 10000. Mutually exclusive with cursor.
include_totalbooleanAdds pagination.total.
Pre-approve an inquiry (Airbnb, VRBO, or through a PMS)
/v1/conversations/:id/pre-approvalNote
Request
curl -X POST https://api.repull.dev/v1/conversations/164743/pre-approval \
-H "Authorization: Bearer $REPULL_API_KEY" \
-H "Content-Type: application/json" \
-d '{}'Response
{
"conversationId": "164743",
"status": "pre_approved",
"blockInstantBooking": false,
"expiresAt": "2026-09-23T17:40:38Z"
}Body Parameters
blockInstantBookingbooleantrue makes the guest book through the pre-approval rather than Instant Book. Default false. The body is optional.
Send an Airbnb special offer
/v1/conversations/:id/special-offersNote
Request
curl -X POST https://api.repull.dev/v1/conversations/164743/special-offers \
-H "Authorization: Bearer $REPULL_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"checkIn": "2026-10-01",
"checkOut": "2026-10-05",
"guests": { "adults": 2, "children": 1 },
"totalPrice": 880
}'Response
{
"id": "1459920384",
"conversationId": "164743",
"status": "active",
"listingId": "23892",
"airbnbListingId": "955656266214757921",
"checkIn": "2026-10-01",
"checkOut": "2026-10-05",
"nights": 4,
"guests": { "total": 3, "adults": 2, "children": 1, "infants": 0, "pets": 0 },
"totalPrice": 880,
"createdAt": "2026-09-22T18:00:00Z",
"expiresAt": "2026-09-23T18:00:00Z"
}Body Parameters
checkIndateRequiredYYYY-MM-DD.
checkOutdateRequiredYYYY-MM-DD, after checkIn.
guestsobjectRequired{ adults (at least 1), children?, infants?, pets? }.
totalPricenumberRequiredTotal for the whole stay, in the listing's Airbnb currency.
listingIdintegerRepull listing id to offer. Omit to offer the listing the guest asked about.
Get a special offer
/v1/conversations/:id/special-offers/:offerIdNote
Request
curl https://api.repull.dev/v1/conversations/164743/special-offers/1459920384 \ -H "Authorization: Bearer $REPULL_API_KEY"
Response
{
"id": "1459920384",
"conversationId": "164743",
"status": "active",
"listingId": "23892",
"airbnbListingId": "955656266214757921",
"checkIn": "2026-10-01",
"checkOut": "2026-10-05",
"nights": 4,
"guests": { "total": 3, "adults": 2, "children": 1, "infants": 0, "pets": 0 },
"totalPrice": 880,
"createdAt": "2026-09-22T18:00:00Z",
"expiresAt": "2026-09-23T18:00:00Z"
}Withdraw a special offer
/v1/conversations/:id/special-offers/:offerIdNote
Request
curl -X DELETE https://api.repull.dev/v1/conversations/164743/special-offers/1459920384 \ -H "Authorization: Bearer $REPULL_API_KEY"
Response
{ "id": "1459920384", "conversationId": "164743", "status": "withdrawn" }