Checkout API
Use the Checkout API to trigger a complete CheckYout check-out from your own system — exactly as if the guest had scanned the QR code at the door. The call sends the WhatsApp notification to the cleaner, dispatches email and webhook notifications, drops the heating into eco mode (tado°, Netatmo, Vaillant, Nest), turns lights off (Hue), and runs your Shelly devices.
When to use
Use this endpoint when your system (e.g. Resavio, Smoobu check-out, your own PMS) already detects when a guest leaves the property — for example through an online check-out, a paid final invoice, or a manual trigger by the host. Instead of asking the guest to scan the QR code as well, CheckYout takes over all downstream actions.
Difference from the Notify API
/api/v1/notify only sends a WhatsApp message to a given phone number. /api/v1/checkout kicks off the full check-out workflow with every configured notification and smart-home action.
Endpoint
/api/v1/checkoutRequest
| Header | Value | Required |
|---|---|---|
Content-Type | application/json | Yes |
X-API-Key | Your API key | Yes |
Request body
| Field | Type | Required | Description |
|---|---|---|---|
resavio_property_id | string | One of | Property ID from Resavio. Set per property in the CheckYout dashboard beforehand. |
external_property_id | string | One of | Alias for resavio_property_id — for other partner integrations. |
device_id | string | One of | Direct device ID, if known. Faster, but less flexible. |
source | string | No | Source of the signal: resavio or partner. Defaults to resavio when resavio_property_id is set, otherwise partner. |
Property mapping
So CheckYout can match a device to a Resavio property, the host stores the Resavio property ID per property in the CheckYout dashboard under Settings → Resavio Property ID. After that, calling with resavio_property_id is enough.
Response
Success response (200)
{
"success": true,
"eventId": "8a4b1c2d-3e4f-5a6b-7c8d-9e0f1a2b3c4d",
"notified": true,
"device_id": "ZNKKPJZV",
"property_name": "Chalet Rösi"
}If a check-out for the same device was already triggered within the last 60 seconds, the API responds with "eventId": "rate-limited" and "reason": "rate_limited" — this is not an error, just a guard against double triggering.
Error responses
| Status | Cause | Example |
|---|---|---|
400 | No identifier provided | {"error": "Provide one of: device_id, resavio_property_id, external_property_id"} |
401 | Invalid or missing API key | {"error": "Invalid or missing API key"} |
404 | Device not found or does not belong to your account | {"error": "Device not found or does not belong to your account"} |
429 | Too many requests per minute (30/min/IP) | {"error": "Too many requests"} |
Code examples
curl -X POST https://checkyout.app/api/v1/checkout \
-H "Content-Type: application/json" \
-H "X-API-Key: cyo_YourApiKey" \
-d '{
"resavio_property_id": "abc-123"
}'const response = await fetch('https://checkyout.app/api/v1/checkout', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-API-Key': process.env.CHECKYOUT_API_KEY,
},
body: JSON.stringify({
resavio_property_id: 'abc-123',
}),
});
const data = await response.json();
console.log('Check-out triggered:', data.eventId);import requests
import os
response = requests.post(
"https://checkyout.app/api/v1/checkout",
headers={
"Content-Type": "application/json",
"X-API-Key": os.environ["CHECKYOUT_API_KEY"],
},
json={"resavio_property_id": "abc-123"},
)
response.raise_for_status()
data = response.json()
print(f"Check-out triggered: {data['eventId']}")<?php
$ch = curl_init('https://checkyout.app/api/v1/checkout');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Content-Type: application/json',
'X-API-Key: ' . getenv('CHECKYOUT_API_KEY'),
],
CURLOPT_POSTFIELDS => json_encode([
'resavio_property_id' => 'abc-123',
]),
]);
$response = curl_exec($ch);
curl_close($ch);
echo $response;Behaviour
Idempotency and rate limiting
We accept at most one check-out event per device per minute. Repeat calls within that window return the same response shape, but do not trigger duplicate notifications.
Smart home and PMS
If a PMS is connected, we check whether a new arrival is scheduled for the same day before lowering the heating. If yes, the heating stays on.
Webhook source
If you have outbound partner webhooks subscribed, the payload field source carries the value "resavio" or "partner" — so you can tell whether the check-out came from a QR scan or your integration.
Related: Notify API · Webhooks · Events