Saltar al contenido principal

Vivin Booking Engine integration

The vivin-booking-engine-integration API connects a white-label booking site (the Vivin Booking Engine) to VIVIN, for the developers who build or maintain that site.

Before you start​

ItemValue
Base URLhttps://api.vivin.app/vivin-booking-engine-integration. Swagger is at the same address; the OpenAPI file at https://api.vivin.app/vivin-booking-engine-integration-json
AuthenticationAuthorization: Bearer <partner-token> on every route, plus vivin-api-key: <account-key> on POST /property-listing (Authentication)
ScopeThe token is not tied to one account: GET /listings returns the booking-engine units of every account that uses the engine. A site serving one account keeps the units whose landlordEmail is that account's Integration Email
Account sideLandlords manage the Vivin Booking Engine card under Settings → Integrations → Booking Platforms

Endpoints​

MethodPathWhat it does
GET/listingsLists every published unit with its calendar and prices
GET/listings/{externalId}Returns one unit
PUT/listingWrites rent and stay limits of one linked unit back into VIVIN
POST/property-listingCreates a property and its units in one account
POST/bookingsSends a confirmed booking. VIVIN queues it and creates it later
GET/listings/{externalId}/housematesLists the people who live in the unit's property today

Which units the API returns​

A unit is published to the engine only when all of these are true:

  • It is linked to the booking engine. An operator opens the unit in Portfolio → Listings, and in the Channels section of the Setup tab clicks the pencil (Add listing URL) on the booking-engine row, which shows the account's logo or the VIVIN logo. They paste the unit's page address on your site, in the form …/house/<property id>/<room id>. Units created with POST /property-listing are linked automatically.
  • It is Included in feed: in the unit's Full integration tab, the Integration listings section shows the VIVIN row as included. This is the default.
  • The unit is not archived, and its property is not archived.
  • It has a usable rent: above zero, and for seasonal rent, above zero in every month.

The externalId comes from the unit's page address on your site:

Page address on your siteexternalId
…/house/8812/3 (a room)8812_3
…/house/8812 (a whole property or studio)8812

A unit linked by its property ID alone is still found with a reference such as 8812_3.

Read listings​

GET /listings and GET /listings/{externalId} return the same listing object as every partial feed: externalId, availableFrom, minStayPeriod, maxStayPeriod, isRentFixed, rent, rentsPerMonth, capacity, the fees and deposit, unavailabilities, bookingWindows and landlordEmail. Every field is described in The listing object.

Example request​

curl https://api.vivin.app/vivin-booking-engine-integration/listings/8812_3 \
-H "Authorization: Bearer <partner-token>"
  • Both responses are live: a change in VIVIN shows up on the next call.
  • rent and rentsPerMonth include the Markup on the Vivin Booking Engine card. When the rent varies by month, rent is the highest month.
  • unavailabilities[].to is the last blocked night: a tenant who checks out on 23 December shows "to": "2026-12-22", plus any preparation days. To get the next possible move-in, read availableFrom (Reading availability).
  • With a Calendar Block (days) on the card, a unit whose last booking or block ends more than that many days from today also gets a block for the two years after it.
  • GET /listings leaves out blocks that ended before today; the single-unit call returns them all.
  • No marketing copy, amenities or photos.

Errors​

StatusmessageCauseWhat to do
404Listing not found for vivinbookingengine with externalId <id>The unit is unknown, not linked to the booking engine, excluded from the feed, or archived (unit or property)Check the link in the unit's Channels
404Listing not availableThe unit has no usable rentSet a rent with PUT /listing
401Missing integration credentials and othersMissing or wrong partner tokenSee Authentication

Update a listing​

PUT /listing writes price and stay changes made on your site back into VIVIN. Use it only for changes that start on your site: changes made in VIVIN are pushed to you (Updates VIVIN sends).

Request fields​

The schema requires every field below, but VIVIN saves only some of them.

NameTypeRequiredSavedDescription
externalIdstringYes—The unit to update
isRentFixedbooleanYesYestrue clears the monthly schedule. false uses rentsPerMonth
rentnumberYesYesMonthly rent to store, without markup. 0 leaves the unit without a usable rent, so it leaves the API until priced
rentsPerMontharrayYesYesEntries with month (1–12) and rent (0 or more). A month you leave out takes rent. Send [] for a fixed rent
minStayPeriodnumberYesYesMinimum stay in months, a whole number, 0 or more
maxStayPeriodnumberYesYesMaximum stay in months, a whole number, 0 or more. 0: no maximum
extraPricePerTenantnumberYesYesExtra monthly rent for each occupant after the first
availableFromdateYesNoVIVIN works it out from its own calendar
capacity, cleaningFeeValue, billsIncludedMaxValue, adminFeeValue, depositValuenumberYesNoChange these in VIVIN
landlordEmailstringYesNo
unavailabilitiesarrayYesNoEntries with from, to (dates) and reason. To block dates, an operator adds a block in VIVIN, or you send a booking

Send the amounts you want stored, not the prices you read: reads add the platform markup, so writing a read price back adds it twice. Operators see the changes in the unit's Changelog.

Example request​

PUT /vivin-booking-engine-integration/listing HTTP/1.1
Host: api.vivin.app
Authorization: Bearer <partner-token>
Content-Type: application/json
{
"externalId": "8812_3",
"landlordEmail": "[email protected]",
"availableFrom": "2026-10-01",
"minStayPeriod": 3,
"maxStayPeriod": 12,
"isRentFixed": true,
"rent": 650,
"capacity": 1,
"extraPricePerTenant": 0,
"cleaningFeeValue": 0,
"billsIncludedMaxValue": 0,
"adminFeeValue": 0,
"depositValue": 650,
"rentsPerMonth": [],
"unavailabilities": []
}

Response​

200 OK with an empty body. Swagger shows true as the response, but the body is empty.

Errors​

StatusmessageCauseWhat to do
400<field> must be a number conforming to the specified constraints, rentsPerMonth.0.month must not be greater than 12 and similarA missing field or a wrong typeSend every field with its type
400property <name> should not existAn unknown keyRemove it
400Min stay period must be a non-negative integer (or Max stay period)A negative or fractional stay limitSend a whole number
400Min stay period cannot be greater than max stay periodminStayPeriod above a maxStayPeriod that is not 0Fix the limits
404Listing not found for vivinbookingengine with externalId <id>The unit is not linked to the engine, excluded from the feed, or archived (unit or property)Check the link. A unit without a usable rent can still be updated
410Gone: this account is served by the native VIVIN Booking Engine…The request carries a vivin-api-key of an account that moved to the native engineStop sending requests for that account

Create a property and its units​

POST /property-listing creates one property and one unit for each room, in the account that vivin-api-key identifies.

Request headers​

NameRequiredDescription
AuthorizationYesBearer <partner-token>
vivin-api-keyYesThe landlord account's key. Landlords see its last characters as the read-only Integration API key on the Vivin Booking Engine card. Swagger cannot send it: use curl

Request fields​

Only id and address are required. The schema accepts many more fields (photos, amenities, visit times, house rules) that are not saved; unknown top-level keys return 400.

NameTypeRequiredWhat VIVIN does with it
idstringYesYour property ID. It becomes the first part of each unit's externalId
addressstringYesThe property address
floorstringNoThe floor
internal_namestringNoThe property name
incompleteRentTypestringNoHow partial months are charged: daily, monthly, or biweekly / fortnightly
paidAtMovinDatestringNoSecurity Deposit: only the deposit is due at move-in. Any other value: the deposit and the last rent
securityDepositstringNoThe deposit amount as text, for example "650"
extraAdministrativeFeenumberNoThe admin fee, switched on when above 0
cleaningLadyPricenumberNoThe cleaning fee, switched on when above 0
billsIncludedbooleanNoBills included in the rent
billsMaxnumberNoThe cap on included bills
roomsarrayNoOne unit for each entry

Each entry in rooms:

NameTypeWhat VIVIN does with it
idstring or numberYour room ID. The unit's externalId becomes <property id>_<room id>
accommodationstringrooms creates a room; any other value a whole-property unit
internalNamestringThe unit name. It must be unique in the account
numbernumberThe room label: 3 becomes Room 3 (default Room 1)
rent, fixedRentnumber, booleanThe monthly rent. Send fixedRent: true: seasonal rent cannot be created here
periodStayMinnumberThe minimum stay in months
periodStayMax, periodStayMaxBooleannumber, stringThe maximum stay in months, used only when periodStayMaxBoolean is the string "true"
numPeople, extraTenantsPricenumberThe unit's capacity (default 1) and the extra rent for each additional tenant

Other property rules take defaults: the contract type is Traditional rental, and the First rent is due to confirm a booking. Operators can change them in the property editor.

Example request​

curl -X POST https://api.vivin.app/vivin-booking-engine-integration/property-listing \
-H "Authorization: Bearer <partner-token>" \
-H "vivin-api-key: <account-key>" \
-H "Content-Type: application/json" \
-d '{
"id": "8812",
"address": "Example Street 10, 1000-001 Lisbon",
"internal_name": "Example Street 10",
"incompleteRentType": "daily",
"paidAtMovinDate": "Security Deposit",
"securityDeposit": "650",
"rooms": [
{
"id": "3",
"accommodation": "rooms",
"internalName": "Example Street 10 - Room 3",
"number": 3,
"rent": 650,
"fixedRent": true,
"periodStayMin": 3,
"numPeople": 1
}
]
}'

Response​

201 Created with { "property": { … }, "listings": [ … ] }, the records VIVIN created. { "property": null, "listings": [] } means VIVIN has turned property creation off for that account: contact VIVIN.

Errors​

StatusmessageCauseWhat to do
400id must be a string, address must be a stringA required field is missing or has the wrong typeSend both as strings
400property <name> should not existAn unknown top-level keyRemove it
400Listing with this internal name already existsA room's internalName is already used in the accountUse a unique name
400Rent per month is required when rent is not fixedA room with fixedRent: false or no fixedRentCreate it with a fixed rent, then send monthly prices with PUT /listing
401Missing vivin-api-key headerNo vivin-api-key, or an empty oneAdd the account key
401UnauthorizedThe vivin-api-key matches no account, or the partner token is wrongCheck both keys
410Gone: this account is served by the native VIVIN Booking Engine…The account moved to the native engineStop sending requests for that account

When a room fails, VIVIN returns the error and emails the account. The property and earlier rooms may already exist, so check Listings before you retry.

Send a booking​

POST /bookings works as on every partner prefix: Creating bookings has the fields, the 201 response and the errors.

{
"externalId": "8812_3",
"checkInDate": "2026-10-01",
"checkOutDate": "2027-06-30",
"bookingId": "3f6c2a9e-8b1d-4c7a-9e2f-5d4b7a1c0e93",
"numberOfExtraTenants": 1,
"tenant": {
"firstName": "Casey",
"lastName": "Sample",
"email": "[email protected]",
"phone": "+15555550100",
"fiscalId": "123456789",
"nationality": "PT"
}
}
  • 201 means the booking was queued, not created. An unknown externalId or overlapping dates still get 201, and the booking then fails in the background (Booking lifecycle and validations).
  • platformProviderPaymentValue is optional here: when you leave it out, VIVIN works it out from the unit's rent.
  • numberOfExtraTenants is the total number of people: 1 means one tenant.
  • tenant.nationality is the tenant's two-letter ISO 3166-1 country code, in either letter case (PT or pt). VIVIN shows it on the booking's tenant details. A tenant who already exists in the account keeps their details (Tenant fields).
  • Duplicates are dropped silently: use a new bookingId for each new reservation (Retries and duplicates).

Housemates​

GET /listings/{externalId}/housemates supports a "meet your housemates" section on a room page.

curl https://api.vivin.app/vivin-booking-engine-integration/listings/8812_3/housemates \
-H "Authorization: Bearer <partner-token>"

Response​

200 OK with an array:

[
{
"name": "Casey Sample",
"nationality": "PT",
"moveIn": "2026-02-01",
"moveOut": "2026-11-30",
"photo": null,
"age": null,
"occupation": null,
"gender": null
}
]
FieldTypeDescription
namestringThe tenant's first and last name
nationalitystring or nullnull when VIVIN has none
moveIn, moveOutdateThe booking's contract dates
photo, age, occupation, gendernullAlways null
  • The list covers everyone living in the same property today: bookings whose contract dates include today, not cancelled. It includes the current tenant of the requested unit.
  • A whole-property unit returns [].
  • The response holds tenants' names. Show it only where your site's privacy notice covers it.
  • An unknown or unpublished unit returns 404 Listing not found for vivinbookingengine with externalId <id>.

Updates VIVIN sends to the engine​

When a linked unit changes in VIVIN, VIVIN pushes it to the booking engine without waiting for a call from you. It checks for changed units every minute and sends each one as a POST to the engine's /updateListing endpoint, with the account's key in the vivin-api-key header. The body has the same fields as GET /listings/{externalId}, except that the unit reference is named listing_id instead of externalId.

Answer 200. Any other status marks the push as failed; VIVIN does not retry it, and sends the unit again only after its next change. To catch up after downtime, read GET /listings.

Errors​

Every route can also return the standard errors. Specific to this prefix:

StatusmessageCauseWhat to do
401Missing vivin-api-key headerPOST /property-listing without the account keyAdd vivin-api-key
410Gone: this account is served by the native VIVIN Booking Engine…Any request carrying the vivin-api-key of an account that moved to VIVIN's native booking engineStop sending requests for that account. Retrying does not help

Troubleshooting​

SymptomLikely cause and fix
Prices grow every time your site saves a unitYou write back the prices you read, which include the markup. Send the amounts to store
A unit disappeared after PUT /listingIts rent is now 0, or a month is at 0. Set a rent
POST /property-listing returns an empty resultProperty creation is turned off for that account. Contact VIVIN
POST /property-listing failed half-waySome rooms may exist already. Check Listings before you retry
Your site shows other landlords' unitsThe token covers every account on the engine. Filter on landlordEmail