Error handling
Every VIVIN API error has the same JSON body; this page lists each status code a partner route returns and how your client should react.
Before you start
| Item | Value |
|---|---|
| Applies to | Every partner route under https://api.vivin.app/<prefix>/…, and the management routes (differences below) |
| Not covered | The MCP OAuth endpoints, which answer with OAuth errors (MCP OAuth) |
| Success type | JSON, except the iCal routes, which return text/calendar. Their errors are JSON too |
Error body
{
"statusCode": 400,
"message": "property rent should not exist, bookingId must be a UUID",
"error": "BadRequestException"
}
| Field | Type | What it holds |
|---|---|---|
statusCode | integer | The HTTP status code |
message | string | Always one string. When several fields fail validation, their messages are joined with , |
error | string | The error type, for example BadRequestException, UnauthorizedException, NotFoundException. A few errors use a reason phrase instead, such as Bad Request |
- Some errors add fields next to these three, for example
reasonon the management sign-in routes. Ignore any field you do not recognise. - Branch your code on
statusCode. Usemessagefor logs and for the person fixing the request: its wording can change. - Unexpected server errors never expose internal details. The body is always
{"statusCode":500,"message":"Internal server error","error":"Internal Server Error"}.
Status codes
Partner routes can return the codes below. The listing, booking and booking-engine routes never return 403, 409, 422 or 429: availability and business rules are checked after a booking is queued (see Errors after the 201).
| Status | message (examples) | Cause | What to do |
|---|---|---|---|
400 | externalId should not be empty, bookingId must be a UUID, checkInDate must be a valid ISO 8601 date string | A field is missing, empty or has the wrong type. Empty strings count as missing | Fix the field named in message |
400 | property rent should not exist | The body has a field the route does not accept | Remove it. Each route lists its fields |
400 | Request body must be a JSON object | The body is an array, a string or a number | Send a JSON object |
400 | Body cannot be empty when content-type is set to 'application/json', or a JSON parser message such as Unexpected token } in JSON at position 42 | Empty or malformed JSON | Send valid JSON |
400 | A required value is missing., A value is too long for its field., A numeric value is out of range., A value has an invalid format. | A value passed the field checks but cannot be stored: for example a missing tenant.email, or a tenant name over 128 characters | Fix the value. See the field limits on each route |
400 | landlordKey must be a non-empty value | The {landlordKey} path segment is blank (full feeds, Housing Anywhere webhook) | Put the landlord key in the path |
400 | Validation failed (uuid is expected) | iCal routes only: the unit ID in the path is not a UUID | Use the VIVIN unit ID (iCal feeds) |
401 | Missing integration credentials, Invalid integration credentials, Unauthorized, Missing vivin-api-key header | The partner token or the booking-engine account key is missing or wrong | See Authentication |
404 | Listing not found for <platform> with externalId <id> | The ID is not linked to a unit for your platform, the unit is excluded from your feed, or the unit or its property is archived | Take the ID from your latest feed. See Which listings appear |
404 | Listing not available | The unit has no usable rent | Ask the landlord to set a rent |
404 | Cannot GET /uniplaces-integration/listing | The path or method does not exist | Check the path in your Swagger page |
409 | Ambiguous uniplaces reference <id>: matches listings on multiple accounts | Uniplaces webhook only: two landlord accounts linked the same ID | Ask the landlords to fix the link (Webhooks) |
410 | Gone: this account is served by the native VIVIN Booking Engine… | Booking-engine prefix only: the account behind vivin-api-key moved to VIVIN's native booking engine | Stop sending requests for that account |
415 | Unsupported Media Type: <type> | A body was sent with no Content-Type header, or with a type the API does not read | Send Content-Type: application/json |
500 | Internal server error | An unexpected error on VIVIN's side | Retry with backoff. If it keeps failing, contact support |
503 | This integration is not configured yet. Contact VIVIN support. | Single-landlord feeds only, until VIVIN finishes setting the feed up (error: ServiceUnavailableException) | Contact VIVIN. Retrying does not help |
503 | The service is busy. Please try again in a moment. | Any route: VIVIN is briefly overloaded (error: Service Unavailable). The response has a Retry-After header, normally 5 | Retry after the number of seconds in Retry-After |
<platform>is your platform's lowercase name, for exampleuniplaces,housinganywhere,spotahome,inlife,roomless,erasmuslifelisboaorvivinbookingengine.- A
502,503or504without the JSON body above did not come from the API itself, for example during a restart. Treat it as temporary. - Inbound webhooks also return
2xxbodies with amessage, listed in Webhooks and notifications.
Errors after the 201
POST …/bookings checks only your token and the shape of the body before it answers. 201 Created means VIVIN queued the booking, not that it exists. VIVIN can still refuse it in the background, for example for overlapping dates, an externalId that is not linked for your platform, or a missing platformProviderPaymentValue. Only single-landlord prefixes check the externalId up front, with a 404.
These failures are not sent back to you: the landlord is notified. To confirm a booking, read the unit again and look for the stay in unavailabilities. The checks and messages are in Booking lifecycle and validations.
Retries
| Response | Retry? |
|---|---|
400, 401, 404, 409, 410, 415 | No. Fix the request, the credentials or the mapping first |
503 This integration is not configured yet. … | No. VIVIN has to finish the setup |
503 The service is busy. … | Yes, after the number of seconds in Retry-After |
500, gateway errors, timeouts, dropped connections | Yes, with exponential backoff |
429 (management routes only) | Yes, after the number of seconds in Retry-After |
A sensible backoff is 1 s, 2 s, 4 s, then 8 s between attempts, then stop and alert your team. A failed listing read can usually wait for your next scheduled poll.
Retrying POST …/bookings is safe only with the same bookingId: a repeated bookingId is queued again and then dropped as a duplicate. Before you resend after a timeout, follow Retries and duplicates.
Management routes
The routes the VIVIN web app uses (Management session) share the error body. The differences:
| Status | message | Cause | What to do |
|---|---|---|---|
401 | Missing Authorization header, Invalid Authorization header format, Unauthorized | The access token is missing, malformed or expired (/auth/me words these Missing authentication credentials and Invalid authentication credentials) | Refresh it, or sign in again if the refresh fails |
401 | Your session has ended. | The session was signed out, or the user's password changed | Sign in again |
403 | Forbidden resource | The user's role lacks the permission this route needs, or the user was deactivated | Ask an admin |
429 | ThrottlerException: Too Many Requests | More than the route allows per IP address and minute (600 for most routes) | Wait the seconds in the Retry-After header |
Sign-in routes have tighter limits and their own 429 messages: see Management session.
Troubleshooting
| Symptom | Likely cause and fix |
|---|---|
201 for a booking that never appears | It was refused in the background. The landlord has the reason. See How failures are reported |
An empty /{landlordKey}/listings/full array | Not an error: the landlord key matched no account. Check it with the landlord (Full listing feeds) |
A unit is in VIVIN but missing from GET …/listings | Its single-listing call tells you why: Listing not available means the rent, Listing not found for … means the link or the feed setting. A link made minutes ago may not be listed yet |
400 A required value is missing. on POST …/bookings | tenant.firstName or tenant.email is missing or empty |
415 Unsupported Media Type | Your client sends the JSON body with no Content-Type header, or with a type the API does not read. Send Content-Type: application/json |
When you contact support, include the endpoint, the time of the request with its time zone, the status code and the full response body.
Related
- Authentication: tokens, headers and
401messages - Creating bookings: the
POST …/bookingsbody and its request-time errors - Booking lifecycle and validations: what happens to a queued booking
- Listings and availability: the listing feed and
unavailabilities - Webhooks and notifications: webhook responses and errors