Odaduu · DMC QuoteOps · v1
Odaduu Public API
A small, stable HTTP surface for B2B partners to pull booking status, browse our reference catalogs, and submit new RFQs into the Odaduu sales pipeline. Bearer-authenticated, JSON in and JSON out, cursor-paginated where it matters.
https://builder.odaduu.com/api/public/v1Overview
Every request is bearer-authenticated. Keys are minted per partner and (optionally) bound to a specific agent — an agent-scoped key can only see its own bookings and can only submit RFQs on that agent’s behalf. Reference catalogs are always org-wide.
Default rate limit is 1000 requests per rolling hour per key. Every response carries X-RateLimit-Limit and X-RateLimit-Remaining headers.
Authentication
Send your key in the Authorization header:
Authorization: Bearer odaduu_live_ab12CDEfghIJKlmnOP34
We show the full secret once at mint time. If you lose it, revoke the key and mint a fresh one — we cannot recover the plaintext. The first 20 characters (the odaduu_live_ab12CDEf prefix) stay visible in our admin so we can identify a key without seeing the secret.
Response envelope
All successful responses wrap the payload:
{
"ok": true,
"data": { "id": "cl...", "ref": "OD-2026-4132", "status": "quote_sent", ... },
"meta": { "count": 10, "nextCursor": "eyJ0Ijoi..." }
}Errors follow the same shape:
{
"ok": false,
"error": { "code": "unauthorized", "message": "invalid API key" }
}List endpoints return an opaque meta.nextCursor. Pass it back on the next request to page forward — its value is stable across concurrent writes.
Endpoints
Health
/healthVerifies your key and echoes the tenant it resolves to. Hit this first after mint.
Returns { status: 'ok', orgId, agentId, apiVersion, serverTime }.
Bookings
/bookingsList bookings visible to your key, newest first. Agent-scoped keys see only their own bookings.
| Param | Type | Notes |
|---|---|---|
| status | string, optional | draft_quote | quote_sent | client_confirmed | ops_in_progress | travel_completed | cancelled |
| limit | int, optional | Page size (default 25, max 100) |
| cursor | string, optional | Opaque token from a prior response's meta.nextCursor |
Returns a page of BookingSummary. meta.nextCursor is null when there is no more.
/bookings/{id}Full detail for one booking, including the currently active quote's total in your sell currency.
/quotesSubmit an RFQ. Creates a DRAFT_QUOTE booking on our side; sales picks it up in the internal dashboard and builds the itinerary.
{
"destinationCode": "JP",
"guestName": "Mr. Sharma",
"arrivalDate": "2026-11-05",
"departureDate": "2026-11-14",
"pax": { "adults": 2, "children": 1, "infants": 0 },
"childAges": [8],
"leadSource": "EMAIL",
"agentRequirements": "Vegetarian meals"
}Returns the created BookingDetail (activeQuote is null until sales builds it).
Reference catalogs
/destinationsDestinations available for RFQ submission.
/hotelsHotel catalog. Filter by city or free-text name match.
| Param | Type | Notes |
|---|---|---|
| city | string, optional | Case-insensitive equality |
| q | string, optional | Substring match on name |
| limit | int, optional | Default 100, max 200 |
/sightseeingsPaid activities + free stops.
| Param | Type | Notes |
|---|---|---|
| city | string, optional | Matches against the catalog's cities[] array |
| category | string, optional | PAID | FREE |
| kind | string, optional | SIGHTSEEING | ACTIVITY | SHOPPING | WALKING |
| q | string, optional | Substring match on name |
/fullday-toursPrivate full-day tour catalog with per-seater JPY pricing.
| Param | Type | Notes |
|---|---|---|
| city | string, optional | Matches against the catalog's cities[] array |
| q | string, optional | Substring match on name |
Error codes
Codes are stable across versions. Messages may drift; match on codes.
| Code | HTTP | When it fires |
|---|---|---|
| unauthorized | 401 | Missing / malformed / unknown / expired key. |
| forbidden | 403 | Key is valid but not permitted for this resource. |
| not_found | 404 | Booking (or similar) does not exist or is out of scope for your key. |
| bad_request | 400 | Payload validation failed. `error.details` carries specifics. |
| rate_limited | 429 | Hourly quota exceeded. `error.details.retryAfterSec` tells you when to retry. |
| conflict | 409 | Reserved for write endpoints; not raised by v1 today. |
| internal_error | 500 | Server-side fault. Please report with `error.details.hint`. |
| not_implemented | 501 | Public API is disabled on this deployment. |
curl examples
Health check — first thing to run after minting a key.
curl -H 'Authorization: Bearer odaduu_live_...' \ https://builder.odaduu.com/api/public/v1/health
List your quote-sent bookings.
curl -H 'Authorization: Bearer odaduu_live_...' \ 'https://builder.odaduu.com/api/public/v1/bookings?limit=10&status=quote_sent'
Submit an RFQ.
curl -X POST -H 'Authorization: Bearer odaduu_live_...' \
-H 'Content-Type: application/json' \
-d '{
"destinationCode": "JP",
"guestName": "Mr. Sharma",
"arrivalDate": "2026-11-05",
"departureDate": "2026-11-14",
"pax": { "adults": 2, "children": 1, "infants": 0 },
"childAges": [8],
"leadSource": "EMAIL",
"agentRequirements": "Vegetarian meals; wheelchair-friendly hotels"
}' \
https://builder.odaduu.com/api/public/v1/quotesGetting started
- Ask your Odaduu account manager at info@flygoldfinch.com to mint you a key. They will send you the full secret once — store it in your secret manager immediately.
- Run the
/healthcall above to confirm auth is wired up and your key resolves to the right tenant. - Poll
/bookingsto pull your live pipeline, or hit/quotesto open new RFQs directly from your system. - Watch
X-RateLimit-Remainingon every response and back off when it approaches zero — a429comes withretryAfterSecin the error details.