Docs/Webhooks/Account

account.units.added

A connected Booking.com Extranet login gained a property, or a room on a property it already had. Map the new units so their bookings, messages and reviews import.

When it fires

One Extranet login covers every property its Booking.com user can see. When the hotel adds the same user to another property, Repull finds it the next time it reads the login's properties, and sends one event per property with its new rooms. It is not sent for the properties a fresh connection starts with (connect.session.completed covers those), and the same rooms are never announced twice. hotels[].isNew is false when rooms were added to a property the login already had. Today only Booking.com Extranet logins send it.

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": "account.units.added",
  "eventId": "3f1c9a2e-8b7d-4c6a-9e0f-1a2b3c4d5e6f",
  "apiVersion": "2026-04",
  "timestamp": "2026-05-01T12:34:56.000Z",
  "data": {
    "workspaceId": 1204,
    "provider": "booking_extranet",
    "accountId": "20123456",
    "connectionId": "482",
    "handle": "booking_extranet:20123456",
    "hotels": [
      {
        "hotelId": "1234567",
        "name": "Old Town Suites",
        "isNew": true
      }
    ],
    "units": [
      {
        "unitId": "1456",
        "name": "Double Room",
        "hotelId": "1234567",
        "roomId": "123456701",
        "mapped": false,
        "listingId": null
      },
      {
        "unitId": "1457",
        "name": "Twin Room",
        "hotelId": "1234567",
        "roomId": "123456702",
        "mapped": false,
        "listingId": null
      }
    ],
    "addedAt": "2026-11-12T16:40:00.000Z",
    "nextSteps": [
      {
        "method": "GET",
        "path": "/v1/connections/booking_extranet:20123456/units",
        "description": "List the units with mapping suggestions."
      },
      {
        "method": "POST",
        "path": "/v1/connections/booking_extranet:20123456/mappings",
        "description": "Map each new unit to a listing (or create one) so its bookings, messages and reviews import."
      }
    ]
  }
}

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

Sign the raw request body exactly as received, not a re-stringified JSON object. Re-serialisation can reorder keys or change whitespace and break the signature.

Example handler

if (event.event === 'account.units.added') {
  const { hotels, units, nextSteps } = event.data
  // nextSteps carries the mappings path for this connection.
  const mapPath = nextSteps.find((s) => s.method === 'POST').path
  // Create a listing for each new room (or pass a listingId to map it to one you have):
  await repull.post(mapPath, {
    mappings: units.map((u) => ({ unitId: u.unitId, create: true })),
  })
  notify(`New on Booking.com: ${hotels[0].name} (${units.length} rooms)`)
}

Common patterns

  • Show the user a "new property found" prompt that lists units and lets them pick a listing for each, then POST /v1/connections/{id}/mappings.
  • Call GET /v1/connections/{id}/units for mapping suggestions (suggested_listing_id) before asking the user.
  • Route it to the right end customer by account.externalAccountId — the Extranet login — like every other event.

Tip: Acknowledge with a 2xx status within 10 seconds. Failed deliveries are retried up to 5 times with exponential backoff.Webhook reliability →

AI