Quickstart
Make your first staging booking in four requests.
In this quickstart we find a staging property, quote a three-night stay, book it, and cancel it. You need the staging API key that OnSeason sent you and a terminal with curl and jq.
Keep the API key on your servers. Never send it from a browser or a mobile app.
Set your key
Export the key and the staging base URL so the commands below can use them:
export ONSEASON_API_KEY="<your staging key>"
export ONSEASON_BASE_URL="https://zepl-staging.calry.app"Search for a stay
Search near Paris for four guests. Change the dates to a range in the future.
curl --get "$ONSEASON_BASE_URL/api/v1/search" \
--header "x-calry-api-key: $ONSEASON_API_KEY" \
--data-urlencode "checkInDate=2026-12-10" \
--data-urlencode "checkOutDate=2026-12-13" \
--data-urlencode "guests=4" \
--data-urlencode "location=48.8566,2.3522" \
--data-urlencode "radius=25" \
--data-urlencode "displayCurrency=EUR" \
| jq '.listings[] | {id, name, avgNightlyPrice, totalPrice}'You see one object per matching listing. Copy an id. If the list is empty, widen radius or remove location, because the staging catalogue is small.
Quote the stay
Ask for a firm price for the listing you picked:
curl --request POST "$ONSEASON_BASE_URL/api/v1/quote?displayCurrency=EUR" \
--header "x-calry-api-key: $ONSEASON_API_KEY" \
--header "Content-Type: application/json" \
--data '{
"listingID": "<listing id>",
"checkInDate": "2026-12-10",
"checkOutDate": "2026-12-13",
"guests": 4,
"guestCountInfo": { "adults": 3, "children": 1, "infants": 0, "pets": 0 }
}' > quote.json
jq '{totalPrice, currency, quoteTokenExpiresAt, terms: .cancellationPolicy.description}' quote.jsonYou see the total, its currency, the token expiry, and a one-line summary of the cancellation terms. The token is valid for 15 minutes, so do the next step now.
Book it
Send the token and the quoted prices with the guest details:
jq '{
quoteToken, listingID, checkInDate, checkOutDate, guests, currency, totalPrice,
totalBasePrice: .components.basePrice.amount,
totalFeePrice: (.components.fees.amount // 0),
totalTaxPrice: (.components.taxes.amount // 0),
adults: 3, children: 1, infants: 0, pets: 0,
guest: { firstName: "Jane", lastName: "Doe", email: "jane.doe@example.com", phone: "+33123456789" },
notes: "", source: "<your channel name>", reservationType: "INSTANT_BOOKING"
}' quote.json > reservation-request.json
curl --request POST "$ONSEASON_BASE_URL/api/v1/reservation?displayCurrency=EUR" \
--header "x-calry-api-key: $ONSEASON_API_KEY" \
--header "Content-Type: application/json" \
--data @reservation-request.json \
| jq '{id, providerReservationID, status, totalPrice, currency}'You see "status": "CONFIRMED". Store id and providerReservationID. You need id to read or cancel the booking.
Cancel it
Cancel the staging booking so the dates free up again:
curl --request DELETE "$ONSEASON_BASE_URL/api/v1/reservation/<reservation id>" \
--header "x-calry-api-key: $ONSEASON_API_KEY" \
| jqYou see "status": "CANCELLED" and a cancellationCharge worked out from the terms you were quoted. Some PMSs return CANCELLATION_PENDING instead. Cancel a reservation explains why.
Next steps
- Read How booking works for what each call guarantees.
- Read Cancellation policies before you design your checkout.
- Work through the go-live checklist to plan certification.