reservation.request.created
A guest asked to book a listing that does not use Instant Book, and the request is waiting on you.
When it fires
Fires once per request, when it reaches Repull, whether the guest asked in the Airbnb app or anywhere else. data.object is the pending reservation in the shape GET /v1/reservations/{id} returns, and respondBy is when Airbnb expires it: 24 hours after the guest asked.
Payload
Every delivery uses the same outer envelope (event, eventId, apiVersion, timestamp, data). Dedupe on eventId — it stays stable across retries and replays, while the X-Repull-Delivery-Id header changes on every attempt.
{
"event": "reservation.request.created",
"eventId": "3f1c9a2e-8b7d-4c6a-9e0f-1a2b3c4d5e6f",
"apiVersion": "2026-04",
"timestamp": "2026-05-01T12:34:56.000Z",
"data": {
"object": {
"id": "236354",
"uid": "HMT3X9KQZ2",
"channel": "airbnb",
"listingId": "23892",
"customerId": "1",
"checkinDate": "2026-10-02",
"checkoutDate": "2026-10-06",
"status": "pending",
"cancellationPolicy": "firm_14",
"checkInTime": "16:00",
"checkOutTime": "10:00",
"guestId": "231877",
"checkIn": "2026-10-02",
"checkOut": "2026-10-06",
"source": "airbnb",
"platform": "airbnb",
"confirmationCode": "HMT3X9KQZ2",
"totalPrice": "812.00",
"currency": "USD",
"guestDetails": {
"numberOfGuests": 2,
"numberOfAdults": 2,
"numberOfChildren": 0,
"numberOfInfants": 0,
"numberOfPets": 0
},
"primaryGuest": {
"id": "231877",
"firstName": "Jordan",
"lastName": "Ellis",
"language": "en-US"
},
"occupancy": {
"adults": 2,
"children": 0,
"infants": 0,
"pets": 0,
"total": 2
},
"financials": {
"totalPrice": 812,
"currency": "USD",
"cancellationPolicy": "firm_14",
"host": {
"accommodation": 700,
"discounts": [],
"guestFees": [],
"hostFees": [
{
"name": "Host service fee",
"type": "host_service",
"amount": 24.36,
"vat": 0
}
],
"taxes": [],
"revenue": 787.64
},
"guest": {
"totalPrice": 812,
"fees": [
{
"name": "Cleaning Fee",
"type": "cleaning",
"amount": 112
}
],
"taxes": []
}
},
"createdAt": "2026-09-22T09:00:00.000Z",
"updatedAt": "2026-09-22T09:00:05.000Z",
"bookedAt": "2026-09-22T09:00:00.000Z",
"guestName": "Jordan Ellis",
"respondBy": "2026-09-23T09:00:00.000Z"
},
"requestStatus": "pending",
"respondBy": "2026-09-23T09:00:00.000Z",
"occurredAt": "2026-09-22T09:00:05.000Z",
"revision": "2026-09-22T09:00:05.000Z"
}
}Verifying signatures
Every delivery includes a timestamped X-Repull-Signature header of the form t=<unix_ts>,v1=<hex>, where v1 is HMAC-SHA256(signing_secret, `${t}.${raw_body}`). Verify it before processing — see Verify Signatures for full Node.js and Python examples.
Use the raw body
Example handler
app.post('/webhooks/repull', express.raw({ type: 'application/json' }), async (req, res) => {
if (!verifyRepullSignature(req)) return res.sendStatus(401)
const { event, data } = JSON.parse(req.body.toString())
res.sendStatus(200) // acknowledge first, work after
if (event === 'reservation.request.created') {
const r = data.object
await notifyHost(`Booking request ${r.confirmationCode}: ${r.checkIn} to ${r.checkOut}, answer by ${data.respondBy}`)
// Or decide automatically:
// POST /v1/reservations/${r.id}/accept, or /decline with a reason and message
}
})Common patterns
- Accept or decline with
POST /v1/reservations/{id}/acceptor/decline, using the reservationidfromdata.object, beforerespondBy. - The outcome arrives as
reservation.request.updated. Accepting also producesreservation.createdfor the booking. - A request that lapses without Airbnb saying so fires no event.
GET /v1/reservationsstill reports it ascancelledwithstatusDetail: "request_expired", so if you track deadlines, schedule your own check atrespondBy.
Related
Tip: Acknowledge with a 2xx status within 10 seconds. Failed deliveries are retried up to 5 times with exponential backoff.Webhook reliability →