Guests & Loyalty
Guests are the people a reservation belongs to. Each guest lives under one property and carries an optional loyalty account that earns on confirmed stays and can be redeemed for a discount.
Register or link a guest
POST /guestsScope: guests:write
Finds a guest by (property, email) or creates one. Idempotent on email — calling it again for the same address links to the existing guest rather than creating a duplicate, so it is safe to call on every checkout.
| Body field | Required | Notes |
|---|---|---|
email | yes | Used as the match key. |
first_name | yes | |
last_name | yes | |
phone | no | |
nationality | no | Free text or ISO country code. |
curl -X POST "$VRDN_BASE/guests" \
-H "Authorization: Bearer $VRDN_KEY" \
-H "Content-Type: application/json" \
-d '{ "email": "[email protected]", "first_name": "Ada", "last_name": "Lovelace", "nationality": "GB" }'{ "guest_id": "G7K2P9QX", "created": true }Returns 201 with "created": true for a new guest, or 200 with "created": false when an existing guest was linked.
Get a guest
GET /guests/{id}Scope: guests:read (PII fields additionally require guests:read:pii)
curl "$VRDN_BASE/guests/G7K2P9QX" -H "Authorization: Bearer $VRDN_KEY"With guests:read only:
{
"id": "G7K2P9QX",
"first_name": "Ada",
"last_name": "Lovelace",
"nationality": "GB",
"status": "active",
"is_local_verified": false
}With guests:read:pii, the response additionally includes email, phone, address, date_of_birth, id_type, and id_number.
| Field | Type | Notes |
|---|---|---|
status | string | active, vip, or blocked. |
is_local_verified | boolean | Whether the guest is verified as a local resident (gates local-only rates). |
Update a guest
PATCH /guests/{id}Scope: guests:write
Update any mutable field. Send only what changes. Setting local_verified is how an admin flow marks a guest as a verified local resident (it stamps the verification time).
| Body field | Notes |
|---|---|
first_name, last_name, phone, nationality, address | Profile fields. |
status | active, vip, or blocked. |
local_verified | Boolean. true unlocks local-only rates for this guest. |
curl -X PATCH "$VRDN_BASE/guests/G7K2P9QX" \
-H "Authorization: Bearer $VRDN_KEY" \
-H "Content-Type: application/json" \
-d '{ "local_verified": true }'Returns the updated guest in the same shape as GET /guests/{id}.
Get loyalty standing
GET /guests/{id}/loyaltyScope: loyalty:read
A guest's points balance, lifetime points, current tier, progress to the next tier, and the recent ledger. Guests with no loyalty activity yet return a zeroed account rather than a 404.
curl "$VRDN_BASE/guests/G7K2P9QX/loyalty" -H "Authorization: Bearer $VRDN_KEY"{
"points_balance": 1260,
"lifetime_points": 1260,
"tier": "Coral",
"next_tier": { "name": "Lagoon", "min_points": 5000 },
"points_to_next_tier": 3740,
"recent_transactions": [
{ "type": "earn", "points": 1260, "description": "Stay RES4K9PA", "created_at": "2026-06-19T08:46:00.000Z" }
]
}| Field | Type | Notes |
|---|---|---|
points_balance | integer | Spendable points. |
lifetime_points | integer | Cumulative earned points (drives tier; never decremented). |
tier | string | Current tier name. |
next_tier | object | null | The next tier and its threshold, or null at the top tier. |
recent_transactions | array | Up to 10 most-recent ledger entries (earn, redeem, expire, adjust). |
Redeem loyalty points
POST /loyalty/redemptionsScope: loyalty:write
Debit a guest's points and record a redeem ledger entry. The balance is checked atomically, so a redemption can never overdraw — an over-redemption returns 409 insufficient_points.
| Body field | Required | Notes |
|---|---|---|
guest_id | yes | Must belong to this property. |
points | yes | Positive integer. |
reservation_id | no | Associates the redemption with a stay; must belong to this property and guest. |
curl -X POST "$VRDN_BASE/loyalty/redemptions" \
-H "Authorization: Bearer $VRDN_KEY" \
-H "Content-Type: application/json" \
-d '{ "guest_id": "G7K2P9QX", "points": 1000, "reservation_id": "RES4K9PA" }'{
"redeemed_points": 1000,
"redeemed_value_usd": 10,
"new_balance": 260,
"tier": "Coral"
}Use redeemed_value_usd as the discount to apply in your own checkout. Points are earned automatically on confirmed USD stays — see Reservations.
Related pages
- Reservations — holds and confirmations that earn loyalty.
- Authentication — how PII scoping works.