1. Overview
The Partner API is a JSON/HTTPS REST API. Everything you can do in your customer portal (browse tours, quote, book, cancel, check balance) is available programmatically.
GET /quote exact price→POST /bookings→Amount is debited from your credit→Confirmed (instantly or by Ada Vegas)→Webhook to you- Your price is a single wholesale/agency price per tour and season. You decide what your customer pays.
- Your balance pays for each sale. If it runs out the booking is still accepted but stays pending until you top up (see Credit).
- Ada Vegas is notified of every sale in real time: your agency, the tour, date, passengers and amount.
2. Quick start
- In your portal open API & Integration → Keys and create a key. Create a Sandbox key first to test without any charge. The secret is shown once.
- Optionally restrict the key to your server IPs (Trusted IPs).
- Call the API:
curl "https://api.adavegastravel.com/v1/services?date=2026-11-10&pax=2" \
-H "X-Api-Key: YOUR_KEY" \
-H "X-Api-Secret: YOUR_SECRET" \
-H "Accept-Language: en"
Base URL: https://api.adavegastravel.com/v1. No account yet? Try everything right now with the public demo credentials: key demo-key-adavegas, secret demo-secret-adavegas. Your own production and sandbox keys are issued when your account is approved.
Complete example: quote, book, check
# 1. exact price for 2 adults + 1 child
curl "$BASE/services/12/quote?date=2026-11-10&pax=2&children=1" -H "X-Api-Key: $KEY" -H "X-Api-Secret: $SECRET"
# 2. create the booking (safe to retry thanks to the idempotency key)
curl -X POST "$BASE/bookings" \
-H "X-Api-Key: $KEY" -H "X-Api-Secret: $SECRET" \
-H "Content-Type: application/json" \
-H "X-Idempotency-Key: order-10045" \
-d '{"service_id":12,"pax":2,"children":1,"service_date":"2026-11-10",
"customer_name":"Ana Pérez","customer_email":"ana@example.com",
"customer_phone":"+34600111222","notes":"Vegetarian"}'
# 3. later: status
curl "$BASE/bookings/AB-2026-8DB0391E" -H "X-Api-Key: $KEY" -H "X-Api-Secret: $SECRET"
3. Authentication & security
| Header | Value |
|---|---|
X-Api-Key | Your public key |
X-Api-Secret | Your secret (stored hashed on our side; cannot be recovered, only regenerated) |
- Call the API from your server only. Never put the secret in a browser or mobile app.
- Trusted IPs (single IPs or CIDR such as
203.0.113.0/24) can be set per key; other IPs get403. - One active key per environment (production / sandbox). Generating a new key revokes the previous one.
- Always HTTPS. Request bodies are limited to 64 KB.
4. Conventions
| Topic | Rule |
|---|---|
| Format | JSON, UTF-8. Send Content-Type: application/json on POST. |
| Success | {"data": ...} (lists add "meta") |
| Error | {"error": {"code": "...", "message": "..."}}. Branch on code; message is human text (currently Turkish) and may change. |
| Dates | YYYY-MM-DD. Timestamps are ISO-8601 (2026-10-26T10:44:12+00:00). |
| Language | Accept-Language: tr | en | es selects tour names and descriptions (default tr). |
| Currencies | TRY, USD, EUR. Money is a decimal number with 2 decimals. |
| Pagination | page (from 1), per_page (1–100, default 25). meta: {page, perPage, total, totalPages} |
| Rate limit | 60 requests / minute / key (sliding window). Requests that fail authentication are counted per IP: after 10 failures in a minute that IP gets 429 for the rest of the minute, even with a valid key. 429 carries a Retry-After header (seconds). |
| Idempotency | Send X-Idempotency-Key (max 128 chars) on POST /bookings. A repeat with the same key within 24 h returns the original response and creates nothing new, so network retries cannot double-book or double-charge. Use a unique key per order. |
| Version | Every response carries X-Api-Version: 1. Additive changes (new fields) are not versioned: ignore unknown fields. |
5. Credit & balance
Each sale is paid from your prepaid balance (in your account currency: TRY, USD or EUR).
- On booking: the booking total is debited immediately (converted to your account currency at the daily rate if the tour is priced in another currency).
- No balance? The balance goes negative (a debt) and the booking is kept
pendingwithhold_reason: "insufficient_credit". It is not confirmed until your debt is within your allowed limit. - Top up in the portal (Balance → Pay by card, any amount from 10 to 50,000) or by bank transfer (Ada Vegas records it). Pending bookings are then confirmed automatically if auto-approval is enabled for you, otherwise by Ada Vegas staff.
- Cancel a pending booking: the full amount returns to your balance immediately.
credit_limitis the debt Ada Vegas allows you (0 by default).available = balance + credit_limit.- Sandbox bookings never touch your balance.
credit.can_confirm in GET /me, GET /balance or the booking response to know whether new bookings will be confirmed.6. Booking lifecycle
| Status | Meaning |
|---|---|
pending | Received and debited, waiting for confirmation (Ada Vegas staff, auto-approval, or you for website bookings). |
confirmed | Guaranteed. Hotel, guide and programme are arranged by Ada Vegas. |
cancelled | Cancelled; amount refunded to your balance if it was cancelled while pending. |
Allowed moves: pending → confirmed, pending → cancelled, confirmed → cancelled (confirmed cancellations are handled by Ada Vegas; contact us). Every move triggers a webhook.
Channels (channel field): api (your integration), portal (made in the portal), site (made through your own website, see section 12; you confirm these in your portal).
7. Prices & quotes
- Prices come in seasons with a single price per adult, an optional
child_price(empty = same as adult), and optionalmin_pax/max_pax(apply to adults + children). - Tours with accommodation need an
occupancy(e.g.single,double,triple) androoms; the quote lists the valid options per room. - Always call
/quotebefore booking. It runs the exact calculation used byPOST /bookings. In/services,unit_priceandpricing.applicableshow the adult price for the chosen date; children, group limits and accommodation are only in the quote.
8. Endpoints
Your account, currency, webhook status and credit summary.
{"data":{"id":22,"name":"Your Agency","status":"active","currency":"EUR","sandbox":false,
"contact":{"name":"...","email":"...","phone":null},"webhook_configured":false,
"credit":{"balance":825.28,"currency":"EUR","credit_limit":0,"available":825.28,"can_confirm":true}}}
Exchange rates used for conversions (base TRY).
{"data":{"base":"TRY","rates":{"USD":32.1,"EUR":35.2,"TRY":1},"supported":["TRY","USD","EUR"]}}
Tour categories available to you, with their extra field definitions (key, label, type, required, options).
Tours you can sell, with your price for a date.
| Query | Description |
|---|---|
date | Travel date used to pick the season (default today) |
pax | Passengers for the indicative total (default 1) |
currency | TRY|USD|EUR display conversion of the legacy list price |
category_id, q | Filter by category / search in name & description |
page, per_page | Pagination |
Each tour contains:
| Field | Notes |
|---|---|
id, name, duration_days, category, description, description_html | Name/description follow Accept-Language |
pricing | audience (agencia or mayorista), applicable (season for your date: season, start_date, end_date, currency, price, child_price, min_pax, max_pax) and all seasons |
accommodation | Only for tours with hotel nights: stays[] (hotel, start_day, nights, rooms) and options[] (per-room price by occupancy), or null |
guides | Guide name and languages |
content | cover_image, gallery[], includes_html, excludes_html, hotel_category_html, important_notes_html, cancellation_policy_html, transfer_details_html, domestic_flight_html, museum_entries_html, child_age_html |
fields[] | Category-specific attributes |
One tour, same shape as above. 404 service_not_found if it does not exist or is not available to you.
| Query | Description |
|---|---|
date | Travel date |
pax | Adults |
children | Children (priced at child_unit) |
occupancy, rooms | Tours with accommodation |
{"data":{"ok":true,"date":"2026-10-29","pax":2,"children":1,"min_pax":null,"max_pax":null,
"currency":"EUR","season":"Autumn 2026",
"tour":{"unit":58.24,"child_unit":58.24,"total":174.72},
"options":[],"accommodation":null,"total":174.72}}
With accommodation, options lists {occupancy,label,per_room} and accommodation returns the chosen option with a per-hotel breakdown; total = tour + accommodation. Errors: 422 with no_price_for_date, pax_below_min / pax_above_max (plus limit), invalid_occupancy, no_accommodation_price.
| Field | Description | |
|---|---|---|
service_id | required | Tour id |
pax | required | Adults, 1–500 |
children | optional | 0–500 |
service_date | required | YYYY-MM-DD, today or later (past dates → 422 date_in_past) |
occupancy, rooms | if tour has accommodation | Missing occupancy → 422 occupancy_required |
customer_name, customer_email, customer_phone | optional | Your traveller (max 190 / 190 / 50 chars) |
notes | optional | Max 2000 chars (diet, pickup hotel, ...) |
channel, customer_lang | website only | See section 12 |
Returns 201:
{"data":{"booking_ref":"AB-2026-8DB0391E","service_id":1,"service_name":"Istanbul Classics",
"pax":2,"children":1,"currency":"EUR","unit_price":58.24,"total_price":174.72,
"service_date":"2026-10-29","customer_name":"Ana Pérez","status":"confirmed",
"sandbox":false,"channel":"api","sale_total":null,"customer_lang":null,
"credit_charged":"174.72","hold_reason":null,"created_at":"2026-10-26T10:44:12+00:00"},
"credit":{"balance":825.28,"currency":"EUR","credit_limit":0,"available":825.28,"can_confirm":true}}
credit_charged is the amount debited in your account currency. status is confirmed straight away only when auto-approval is on for you and your credit is sufficient; otherwise pending (check hold_reason).
Your bookings, newest first. Filters: status (pending|confirmed|cancelled), customer_email, channel (api|portal|site), from / to (creation date), page, per_page.
One booking (same shape as above). 404 booking_not_found.
Cancels a pending booking and refunds the full amount to your balance. A confirmed booking returns 409 not_cancellable: contact Ada Vegas.
Balance summary plus the latest ledger entries (?limit=1..100, default 20).
{"data":{"balance":825.28,"currency":"EUR","credit_limit":0,"available":825.28,"can_confirm":true,
"transactions":[
{"type":"charge","amount":-174.72,"currency":"EUR","balance_after":825.28,"booking_ref":"AB-2026-8DB0391E","reference":null,"created_at":"..."},
{"type":"topup","amount":1000,"currency":"EUR","balance_after":1000,"booking_ref":null,"reference":"BANK-2210","created_at":"..."}]}}
Types: topup (+), charge (−), refund (+), adjust (±, manual correction by Ada Vegas).
Configuration of your website as set in the portal (name, languages, colours, pages, which tours are shown and your markup). Used by the ready-made website package; 404 site_disabled until you publish. See section 12.
9. Webhooks
Instead of polling, set a Webhook URL in the portal (API & Integration → Webhook). A signing secret is generated for you.
| Event | When |
|---|---|
booking.created | A booking was created (including by your own API call) |
booking.confirmed | Confirmed (auto-approval, Ada Vegas staff, or you) |
booking.cancelled | Cancelled (refund is applied if it was pending) |
POST https://your-site.example/hooks/adavegas
Content-Type: application/json
X-Agency-Webhook-Event: booking.confirmed
X-Agency-Webhook-Signature: sha256=3b1f...e9
{"event":"booking.confirmed","booking_ref":"AB-2026-8DB0391E","status":"confirmed",
"service_id":1,"service_name":"Istanbul Classics","customer_name":"Ana Pérez","customer_email":"ana@example.com",
"channel":"api","credit_charged":"174.72","pax":2,"children":1,"service_date":"2026-10-29",
"currency":"EUR","total_price":174.72,"sandbox":false,"occurred_at":"2026-10-26T10:44:12+00:00"}
Verify the signature
Signature = HMAC-SHA256(raw request body, webhook secret), hex, prefixed with sha256=. Compare in constant time and use the raw body, not re-encoded JSON.
// PHP
$raw = file_get_contents('php://input');
$expected = 'sha256=' . hash_hmac('sha256', $raw, $secret);
if (!hash_equals($expected, $_SERVER['HTTP_X_AGENCY_WEBHOOK_SIGNATURE'] ?? '')) { http_response_code(401); exit; }
// Node.js (Express, with express.raw({type:'application/json'}))
const crypto = require('crypto');
const expected = 'sha256=' + crypto.createHmac('sha256', secret).update(req.body).digest('hex');
const ok = crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(req.get('X-Agency-Webhook-Signature') || ''));
Delivery
- Reply with any
2xxwithin 10 seconds. Anything else is retried up to 5 times with increasing delay (about 2, 4, 8 and 16 minutes). After that the event is dropped; useGET /bookingsto reconcile. - Deliveries are queued and sent within about a minute. Events can arrive more than once or out of order: treat them as "booking X changed, fetch its state" and make your handler idempotent.
10. Sandbox
Create a Sandbox key in the portal. It behaves like production but: bookings are flagged "sandbox": true, your balance is never charged or refunded, and Ada Vegas staff are not notified. Webhooks still fire (with sandbox: true) so you can test your receiver end to end. Both use the same base URL as production; only the key differs. For a quick look without any account, use the public demo (sample data, nothing is stored).
11. Typical integration (server-side)
// PHP 8, cURL
function av(string $method, string $path, ?array $body = null, array $headers = []): array {
$ch = curl_init('https://api.adavegastravel.com/v1' . $path);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true, CURLOPT_CUSTOMREQUEST => $method, CURLOPT_TIMEOUT => 20,
CURLOPT_HTTPHEADER => array_merge(['X-Api-Key: ' . getenv('AV_KEY'), 'X-Api-Secret: ' . getenv('AV_SECRET'),
'Content-Type: application/json', 'Accept-Language: en'], $headers),
CURLOPT_POSTFIELDS => $body ? json_encode($body, JSON_UNESCAPED_UNICODE) : null,
]);
$out = curl_exec($ch); $code = curl_getinfo($ch, CURLINFO_HTTP_CODE); curl_close($ch);
return [$code, json_decode((string) $out, true)];
}
[$c, $q] = av('GET', '/services/12/quote?date=2026-11-10&pax=2&children=1');
if ($c === 200) {
[$c, $b] = av('POST', '/bookings', ['service_id' => 12, 'pax' => 2, 'children' => 1, 'service_date' => '2026-11-10',
'customer_name' => 'Ana Pérez'], ['X-Idempotency-Key: order-10045']);
// $b['data']['status'] is "confirmed" or "pending"; show the customer your own price, keep $b['data']['booking_ref']
}
12. Selling on your own website
Two ways, both use the same API:
A. Ready-made website package ("Vitrin")
A front-end only travel website you upload to your own hosting (PHP 8.1+, no database). You manage its name, colours, texts (ES/EN/TR), pages, which tours are visible and your markup % from the portal (My website). Visitors see your price = Ada Vegas price + your markup, never ours. A visitor's request becomes a booking in your account (debited at the Ada Vegas price) and appears under Bookings → My website, where you confirm or cancel; the traveller gets e-mails in their language and a "My bookings" page. Updates are applied from the portal with one click.
B. Your own site or system
Build your own pages with /services and /quote, then create bookings server-side. To use the markup and e-mail features of your published website configuration, add to POST /bookings:
| Field | Description |
|---|---|
channel: "site" | Booking is treated as a website booking: you confirm it, and sale_total (Ada Vegas price + your markup) is stored and returned. Requires a published website (403 site_disabled otherwise). |
customer_lang | tr|en|es, language of the traveller e-mails |
/quote; never trust a price sent from a browser. The amount debited from you is always the Ada Vegas price, not sale_total.13. Errors
| HTTP | code | Meaning |
|---|---|---|
| 400 | validation_error | Missing or invalid field (service_id, pax, children, service_date is required) |
| 400 | invalid_body | Body is not valid JSON |
| 400 | invalid_currency | Currency not TRY/USD/EUR |
| 401 | unauthorized | Missing/invalid key or secret |
| 403 | forbidden | IP not allowed, or account suspended |
| 403 | site_disabled | Website channel used but site not published / tour hidden |
| 404 | service_not_found | Tour unknown or not available to you |
| 404 | booking_not_found | Unknown reference |
| 409 | not_cancellable | Only pending bookings can be cancelled by API |
| 413 | invalid_body | Body larger than 64 KB |
| 422 | date_in_past | service_date is before today |
| 422 | no_price_for_date | No season price for that date |
| 422 | pax_below_min / pax_above_max | Group size outside the tour limits (limit gives the bound) |
| 422 | occupancy_required / invalid_occupancy / no_accommodation_price | Accommodation tours: room type missing, wrong, or unpriced |
| 429 | rate_limited | Too many requests; wait Retry-After seconds |
A booking that is accepted but waiting for credit is not an error: you get 201 with status: "pending" and hold_reason: "insufficient_credit".
14. Best practices
- Quote right before booking; prices and seasons can change.
- Always send an
X-Idempotency-Keyand, on a timeout, repeat the same request with the same key. - Cache tour content (
/services) for a few minutes to stay well under the rate limit; do not call the API per page view. - Handle
pending: show "request received" to your customer until thebooking.confirmedwebhook arrives. - Keep an eye on
credit.can_confirmand top up before busy periods; enable auto-approval with Ada Vegas for hands-off confirmation. - Log the
booking_refof every call. The portal's Request log shows each API call with time, IP and status. - Rotate keys if a secret may have leaked (portal → generate a new key).
15. Support
Questions, confirmed-booking cancellations, limit increases, auto-approval or integration help: contact your Ada Vegas account manager. Include the booking_ref and the time of the request.
Ada Vegas Partner API v1 · document generated from the live implementation.