Vai al contenuto principale

Creating bookings

POST /<prefix>/bookings sends a booking confirmed on your platform to the landlord's VIVIN account.

Before you start​

ItemValue
Base URLhttps://api.vivin.app/<prefix>, for example /uniplaces-integration. Every partner prefix accepts bookings, single-landlord ones included; ical-integration does not
AuthenticationAuthorization: Bearer <partner-token> (Authentication)
The unitLinked to your platform, so your listing ID is its externalId (Property and unit mapping)
The datesChecked as free with GET /<prefix>/listings/{externalId}, which is always live (Listings and availability)
How it worksVIVIN answers 201 when it has queued the request, then creates the booking in the background, usually within a minute

Airbnb and Booking.com bookings reach VIVIN through the landlord's own connections to those channels, not through this route.

Create a booking​

POST /<prefix>/bookings HTTP/1.1
Host: api.vivin.app
Authorization: Bearer <partner-token>
Content-Type: application/json

On your Swagger page, the body is listed as CreateBookingIntegrationDto.

Request fields​

NameTypeRequiredDescription
checkInDatestring, YYYY-MM-DDYesMove-in date. The check-in time comes from the landlord's settings
checkOutDatestring, YYYY-MM-DDYesMove-out date. Must be after checkInDate: VIVIN does not check it for you
externalIdstring, 1–256 charactersYesYour listing ID for the unit. On single-landlord prefixes, the VIVIN unit ID that the feed returns for unlinked units also works
bookingIdstring, UUIDRecommendedYour reservation ID. VIVIN stores it on the booking and uses it to drop duplicates (Idempotency and retries)
numberOfExtraTenantsinteger, 0 or moreNoDespite its name, the total number of occupants, lead tenant included. 0, 1 or no value: one person. 3: the lead tenant plus two others
platformProviderPaymentValuenumber, 0 or moreYes, in practiceWhat your platform collected from the tenant for this stay and pays to the landlord. Shown as Provider platform payment on the booking and recorded as a Provider platform payment on the tenant's payment plan. Without a value above 0, the booking fails in the background. Exceptions below
otaCommissionValuenumber, 0 or moreNoYour platform's commission on the stay. Stored on the booking for reference. It does not change the payment plan
tenantobjectYesThe lead tenant (Tenant fields)
  • Amounts are in the landlord account's currency and are stored with two decimals.
  • platformProviderPaymentValue exceptions: for Inlife and the Vivin Booking Engine, VIVIN works the amount out from the unit's rent when you leave it out. For Inlife, when you send exactly the base rent of a stay with more than one occupant, VIVIN adds the extra-occupant charge.
  • The body accepts only these fields. Any other top-level key, such as rent, depositValue, checkInTime or secondTenant, returns 400 property <name> should not exist.

Tenant fields​

NameTypeRequiredDescription
firstNamestring, up to 128 charactersYes
lastNamestring, up to 128 charactersNo
emailstring, up to 128 charactersYesThe tenant signs in to the tenant portal with it and gets every email there. VIVIN does not check the format: a typo means the tenant receives nothing
fiscalIdstring, up to 128 charactersNoThe tenant's tax number, for example a NIF in Portugal
phonestring, up to 64 charactersNoFor example +15555550100
nationalitystring, 2 lettersNoThe tenant's two-letter ISO 3166-1 country code, in either letter case, for example PT
  • Existing tenants are reused. VIVIN looks in the landlord's account for a tenant with the same email (in any letter case) or the same fiscalId. When it finds one, it adds the booking to that tenant and leaves their details unchanged.
  • Other keys inside tenant (ID document, addresses, billing or bank details) are accepted and discarded. There is no field for a second tenant or a guarantor: the tenant adds those in the tenant portal, or the landlord's team does.
  • Only presence and length are checked. A misspelled email or a one-letter name is accepted, so check tenant values on your side.

Example request​

{
"checkInDate": "2027-02-01",
"checkOutDate": "2027-06-30",
"externalId": "abc-123",
"bookingId": "550e8400-e29b-41d4-a716-446655440000",
"numberOfExtraTenants": 2,
"platformProviderPaymentValue": 650,
"tenant": {
"firstName": "Casey",
"lastName": "Sample",
"email": "[email protected]",
"phone": "+15555550100",
"fiscalId": "123456789"
}
}
curl -X POST https://api.vivin.app/uniplaces-integration/bookings \
-H "Authorization: Bearer <partner-token>" \
-H "Content-Type: application/json" \
-d @booking.json

Response​

201 Created means VIVIN has queued your request. The body is a receipt for the queued request, not the booking:

{
"identifiers": [{ "id": "4f7c2a9e-1b3d-4e8f-9a6b-2c5d7e8f0a1b" }],
"generatedMaps": [
{
"id": "4f7c2a9e-1b3d-4e8f-9a6b-2c5d7e8f0a1b",
"createdAt": "2026-09-26T10:15:02.123Z"
}
],
"raw": [
{
"id": "4f7c2a9e-1b3d-4e8f-9a6b-2c5d7e8f0a1b",
"createdAt": "2026-09-26T10:15:02.123Z"
}
]
}
  • The id identifies the queued request, not a booking. No route looks it up, but keep it in your logs for support.
  • generatedMaps and raw can carry more keys than shown. Check the status code only.
  • Swagger shows the full booking model as the 201 response. The real body is the one above.

In Swagger, the 201 description says the response acknowledges the queued job. The example value underneath shows the booking schema, which is not what you receive.

Errors​

These errors come back at once, and nothing is queued. Problems with the dates or the unit are found later, in the background (Booking lifecycle and validations).

StatusmessageCauseWhat to do
400checkInDate must be a valid ISO 8601 date string (or checkOutDate)Missing or malformed dateSend YYYY-MM-DD
400externalId should not be empty, externalId must be a stringMissing, empty or non-string externalIdSend your listing ID
400bookingId must be a UUIDbookingId is not a UUIDSend a UUID, or leave the field out
400numberOfExtraTenants must not be less than 0 (or the two amount fields)A negative value or a value that is not a numberSend a number, 0 or more
400tenant must be a non-empty objecttenant is missing or {}Send the tenant
400property <name> should not existA top-level field this route does not acceptRemove it
400A required value is missing.tenant.firstName or tenant.email is missing or emptySend both
400A value is too long for its field.externalId over 256 characters, a tenant value over its limitShorten the value
400A numeric value is out of range.An amount of 100,000,000 or moreCheck the amount
400A value has an invalid format.numberOfExtraTenants is not a whole numberSend an integer
400Request body must be a JSON object, or a JSON parser messageThe body is not a JSON object, or the JSON is malformedSend one JSON object
401Missing integration credentials and othersMissing or wrong partner tokenSee Authentication
404Listing not found for <platform> with externalId <id> (or with listingId <id>)Single-landlord prefixes only: the ID matches no unit of that landlord, or the unit is not in your feedTake the ID from the feed
415Unsupported Media Type: <type>No Content-Type header, or a type the API does not readAdd the header
503This integration is not configured yet. Contact VIVIN support.Single-landlord prefixes only, until VIVIN finishes the setupContact VIVIN. Retrying does not help
503The service is busy. Please try again in a moment.VIVIN is briefly overloaded and did not queue the bookingRetry after the seconds in the Retry-After header

Partner routes have no rate limit and never return 409 or 422: a conflict such as overlapping dates shows up as a background failure. The error body is described in Error handling.

What VIVIN fills in​

The booking takes its contract terms from the landlord's setup, like a booking created in the app with the unit's own values:

TermWhere it comes from
RentThe unit's rent for the booked months, plus the Markup on your platform's card under Settings → Integrations → Booking Platforms, plus Extra Rent per Tenant for each occupant after the first
DepositThe unit's deposit, plus Extra Deposit per Tenant for each occupant after the first
Fees and payment termsCleaning, admin and exit fees, bills included, the contract type, Confirmation payments, Check-in payments and due dates, from the property and Settings → Payments
Check-in and check-out timesThe landlord's defaults
Tenant categoryA tenant with no category gets the one marked Default for integration-created tenants under Settings → Categories, if the landlord marked one

After the booking is created, the landlord's normal onboarding runs: depending on their settings, the contract and onboarding email for the tenant, payment details, scheduled messages, and check-in and check-out tasks.

What happens next​

VIVIN processes queued requests one at a time, about every 30 seconds, not necessarily in the order they arrived. The booking can still fail then, for example when the dates overlap another stay, the externalId is not linked for your platform, or platformProviderPaymentValue is missing. A stay that breaks the unit's capacity or stay limits is created with a warning for the landlord.

Your platform is not told the result. To confirm it, read GET /<prefix>/listings/{externalId} again: once the booking exists, its dates appear as a new entry in unavailabilities. Every check, its message and who is notified are in Booking lifecycle and validations.

Idempotency and retries​

  • bookingId is your idempotency key. A request whose bookingId your platform already imported into that account is queued, then dropped without a second booking or a notification, even when the first booking has other dates or was cancelled.
  • Never resend a request that returned 201, and never reuse a bookingId to change or rebook a stay: ask the landlord to change it in VIVIN.
  • After a timeout or a 5xx, wait a few minutes and read the unit. Resend with the same bookingId only if the dates are still missing from unavailabilities.
  • No partner route changes or cancels a booking. Uniplaces and Housing Anywhere can cancel through their webhooks.

The full duplicate rules are in Retries and duplicates.

Troubleshooting​

SymptomLikely cause and fix
201, but the dates never appear in unavailabilitiesThe booking was refused in the background, or the queue is long. The landlord has the reason (How failures are reported)
The booking was created for one person instead of twonumberOfExtraTenants counts every occupant. Send 2 for two people
400 A required value is missing.tenant.firstName or tenant.email is missing or an empty string
The tenant's details in VIVIN differ from what you sentVIVIN reused an existing tenant with the same email or tax number, and kept their details
The landlord sees Tenant <name> already has an active bookingThe tenant's category does not allow Multiple concurrent bookings. The landlord can allow it under Settings → Categories