Direct Hotel Contracts
Direct contracts are pre-negotiated deals with specific hotels — guaranteed inventory and locked rates for a known airport. They participate in the allocation just like any other provider, with a few advantages.
Why contracts beat GDS
- Rate certainty — locked for the contract period; no surprise at check-in.
- Guaranteed inventory — rooms are held; no surge-pricing stock-outs during a disruption.
- Margin transparency — Nexa surfaces
savingsVsMarket, giving finance a clean report for each booking. - Faster inventory update — no provider callback; Nexa decrements its own counter on confirmation.
Loading a contract
Contracts are CSV/JSON-imported via the Ops Console or the admin API.
curl -X POST https://us-central1.api.nexastudio.io/contracts \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "Ibis MAD — 2026 T2",
"airport": "MAD",
"hotel": {
"name": "Ibis Madrid Aeropuerto Barajas",
"address": "…",
"location": { "lat": 40.47, "lon": -3.58 },
"stars": 3,
"externalIds": {
"amadeus": "HTLABCMAD",
"hotelbeds": "12345"
}
},
"rates": [
{ "from": "2026-04-01", "to": "2026-06-30",
"roomType": "STANDARD", "nightlyRate": 95, "currency": "EUR",
"guaranteedRooms": 30 }
],
"acceptedPayments": ["GUARANTEE"],
"terms": "Late cancellation 24h; early check-in included."
}'
Key fields:
externalIds— the same hotel may appear in Amadeus and Hotelbeds. Listing the provider IDs enables cross-provider deduplication so Nexa doesn't double-count the same property.rates— date-bounded; a contract can have several rate tiers.guaranteedRooms— the cap Nexa will draw from. Bookings decrement it; cancellations restore it.
Dedup across providers
When allocation runs, Nexa:
- Searches Amadeus and Hotelbeds.
- Pulls matching contracts (by airport + date range).
- Deduplicates: provider-id matches via
externalIds, then geo+stars, then name+address. - Prefers the contract offer when a hotel is matched — cheapest rate + guaranteed inventory.
Inventory accounting
Contract: Ibis MAD — 30 rooms
Case A books: 10 rooms → remaining 20
Case B books: 8 rooms → remaining 12
Case A cancels 4 rooms → remaining 16
Nexa persists a ledger per contract so you can audit inventory movements.
Savings vs market
On every booking against a direct contract, Nexa records:
{
"contractRate": 95,
"lowestGdsRate": 112,
"savingsPerNight": 17,
"savingsTotal": 17 * rooms * nights,
"currency": "EUR"
}
This drives the weekly finance report and the CFO dashboard.
When contracts expire
Nexa treats expired contracts as absent — the hotel falls back to GDS pricing. Expiring contracts produce a warning in the Ops Console 14 days before expiry so procurement has time to renegotiate.
Admin actions
- Adjust inventory —
POST /contracts/:urn/inventorywhen the hotel releases extra rooms. - Deactivate —
POST /contracts/:urn/deactivatewhen a hotel pulls out mid-contract; active bookings are unaffected; new allocations won't pick this contract. - Bulk import —
POST /contracts/bulkfor annual procurement refreshes.
All of these are audit-logged with the actor and reason.