Ship Updates. Not Headaches.
GAMAN is the travel-booking API platform built for agents and OTAs who move fast. One API for authentication, organization management, flight search & booking, and hotels — all live today.
Deploy with confidence
A single, consistent REST API for authentication, org management, and flight booking — no juggling multiple systems.
Secure by default
Every request is authenticated with a Bearer token, and wallet operations are validated against your organization's balance in real time.
Full organization control
Manage sub-agents, wallets, markup packages, and audit logs — all scoped cleanly to your organization.
Clear, predictable responses
Every endpoint returns the same
success / data /
error shape, so integration stays
simple from day one.
https://staging.gaman.co.inHow to read this documentation: the left sidebar is organized by section (Organization, Flights, Hotels, etc.). Each endpoint shows its HTTP method and path, a plain-English explanation of every field, and a real JSON example for both the request and the response.
Authentication
All endpoints (except login) require a Bearer token in the header:
Authorization: Bearer <access_token>
Login (Org User)
POST /api/v1/auth/login Request:
{
"agent_id": "GAMDEMO0001",
"username": "admin",
"password": "OrgAdmin@123"
}
Success Response (200):
{
"success": true,
"message": "login successful",
"data": {
"user": {
"id": "11111111-1111-1111-1111-111111111111",
"username": "admin",
"email": "admin@demo.com",
"name": "Demo Admin",
"role": "org_admin",
"status": "active",
"org_id": "9551fa77-16ad-4df5-9284-dc23cb95c237",
"sub_agent_id": "GAMDEMO0002"
},
"tokens": {
"access_token": "eyJhbGciOiJIUzI1NiIs...",
"refresh_token": "eyJhbGciOiJIUzI1NiIs...",
"expires_in_seconds": 3600
},
"agent_id": "GAMDEMO0001"
}
}
Field Reference:
| Field | Description |
|---|---|
user.id |
Unique ID of the logged-in user. |
user.role |
Permission level: org_admin
(full org access) or agent
(restricted, self-scoped access).
|
user.org_id |
ID of the organization this user belongs to. |
user.sub_agent_id |
Human-readable agent code used in some org endpoints (e.g. wallet topup). |
tokens.access_token |
Short-lived JWT. Send it as
Authorization: Bearer <access_token>
on every subsequent request.
|
tokens.refresh_token |
Long-lived token used to obtain a new access token once it expires. |
tokens.expires_in_seconds |
How long the access token stays valid, in seconds (3600 = 1 hour). |
agent_id |
Public-facing agency code for the organization (e.g. shown on invoices). |
| Field | Description |
|---|---|
refresh_token |
The long-lived token returned by Login (or a prior refresh). Required. |
tokens.access_token |
New short-lived JWT. Send as Authorization: Bearer <access_token>. |
tokens.refresh_token |
New refresh token. Store it and discard the old one — the old token is revoked after a successful refresh. |
tokens.expires_in_seconds |
Lifetime of the new access token in seconds (21600 = 6 hours). |
subscription_type of
full or api_only (visible on
GET /org/profile):
-
full— access to both the API and the management frontend portal. -
api_only— programmatic API and self-service only. The management/portal endpoints under Agent Management, Flight Pricing Package, Hotel Pricing Package, Fare Transactions and Organization Wallet (ledger, agent transactions, topup, export) return 403 Forbidden.
{
"success": false,
"error": "your organization subscription (API only) does not include portal access to this feature"
}
Error Response (401):
{
"success": false,
"error": "invalid credentials"
}
Organization Profile
Your organization is the root account for everything below — wallet, agents, pricing packages, and branding. Read or update its public profile and settings here.
Get Organization Profile
GET /api/v1/org/profile Success Response (200):
{
"success": true,
"message": "profile retrieved",
"data": {
"id": "9551fa77-16ad-4df5-9284-dc23cb95c237",
"agent_id": "GAMDEMO0001",
"name": "Demo Travel Agency",
"slug": "demo-travel",
"email": "org@demo.com",
"phone": "+91 9876543210",
"address": "123 Main Street, Mumbai",
"country": "IN",
"subscription_type": "full",
"status": "active",
"ip_whitelist_enabled": false,
"wallet": {
"id": "11111111-1111-1111-1111-111111111110",
"balance": 100000,
"currency": "INR",
"credit_limit": 0,
"is_active": true
}
}
}
Field Reference:
| Field | Description |
|---|---|
agent_id |
Public agency/organization code (e.g. shown to sub-agents and on documents). |
slug |
URL-friendly identifier for the organization. |
subscription_type |
Plan tier the org is on (e.g. full). |
status |
Organization state — active or suspended. |
ip_whitelist_enabled |
If true, only requests from whitelisted IPs are accepted for this org. |
wallet.balance |
Current available wallet balance for the organization. |
wallet.credit_limit |
Additional credit the org can spend beyond its balance (0 = no credit line). |
wallet.is_active |
Whether the wallet can currently be used for transactions. |
Organization Settings
Key/value settings scoped to your organization. Use these to store portal or integration preferences. The GET endpoint returns the full list of settings for the org.
Get Organization Settings
GET /api/v1/org/settings Success Response (200):
{
"success": true,
"message": "settings retrieved",
"data": [
{
"id": "7d2f1a...",
"org_id": "9551fa77-16ad-4df5-9284-dc23cb95c237",
"key": "portal_theme",
"value": "sunset",
"created_at": "2026-04-10T09:23:20Z",
"updated_at": "2026-04-10T09:23:20Z"
}
]
}
Upsert a Setting
PUT /api/v1/org/settings Request:
{
"key": "portal_theme",
"value": "sunset"
}
Validation: key and value are required strings.
{
"success": true,
"message": "setting updated"
}
More Features — Power Up Your Portal
Go beyond the API. The features in this group turn a bare API integration into a fully managed travel operation — so your organization can onboard and manage agents, set smart markups with pricing packages, and fund agent wallets, all from one console. Built for teams that want to scale without writing more code.
- Agent Management — onboard, organize, and control sub-agents under your organization in minutes.
- Wallet Transactions — fund agent wallets and export the org ledger for full financial visibility.
- Flight Pricing Package — set flight markups once and assign them to agents or your whole org.
- Hotel Pricing Package — do the same for hotels, with markups assigned per agent or org-wide.
Agent Management
List Agents
GET /api/v1/org/users
Query Parameters: page,
per_page, role
(org_admin | agent),
status
(active | suspended).
{
"success": true,
"data": [
{
"id": "5b920162-500f-474f-8e7a-5f131053a7d5",
"username": "testagent",
"email": "agent@demo.com",
"name": "Test Agent",
"role": "agent",
"status": "active",
"created_at": "2026-04-10T14:47:58.251295+05:30"
}
],
"meta": {
"page": 1,
"per_page": 20,
"total": 2,
"total_pages": 1
}
}
Field Reference:
| Field | Description |
|---|---|
role |
org_admin can manage the whole
org (agents, wallet, packages);
agent is limited to their own
bookings, wallet, and profile.
|
status |
active or suspended. Suspended users cannot log in. |
meta.page / per_page |
Current page number and page size used for pagination. |
meta.total / total_pages |
Total matching records, and total number of pages available. |
Add Agent
POST /api/v1/org/users Request:
{
"email": "agent@demo.com",
"name": "Test Agent",
"username": "testagent",
"password": "Agent@123",
"role": "agent"
}
Valid Roles: org_admin, agent.
Optional field: phone.
{
"success": true,
"message": "user created",
"data": {
"id": "5b920162-500f-474f-8e7a-5f131053a7d5",
"username": "testagent",
"email": "agent@demo.com",
"name": "Test Agent",
"role": "agent",
"status": "active",
"org_id": "9551fa77-16ad-4df5-9284-dc23cb95c237",
"sub_agent_id": "GAMWE0VFZSA"
}
}
Get Agent by ID
GET /api/v1/org/users/:id Success Response (200):
{
"success": true,
"data": {
"id": "5b920162-500f-474f-8e7a-5f131053a7d5",
"username": "testagent",
"email": "agent@demo.com",
"name": "Test Agent",
"role": "agent",
"status": "active",
"created_at": "2026-04-10T14:47:58.251295+05:30"
}
}
Update Agent
PUT /api/v1/org/users/:id Request:
{
"name": "Updated Name",
"phone": "+919999999999",
"status": "active"
}
All fields optional. Valid status values:
active, suspended.
{
"success": true,
"message": "user updated",
"data": {
"id": "5b920162-500f-474f-8e7a-5f131053a7d5",
"username": "testagent",
"email": "new@demo.com",
"name": "Updated Name",
"phone": "+919999999999",
"role": "agent",
"status": "active"
}
}
Delete Agent
DELETE /api/v1/org/users/:id Success Response (200):
{
"success": true,
"message": "user deleted"
}
Suspend Agent
PUT /api/v1/org/users/:id/suspend Success Response (200):
{
"success": true,
"message": "user suspended"
}
Activate Agent
PUT /api/v1/org/users/:id/activate Success Response (200):
{
"success": true,
"message": "user activated"
}
Agent Fare Transactions
Every agent's own fare ledger — each ticketed
booking's public fare, the fare charged to the agent
(agent_fare), and the agent's commission.
Use ?period=weekly|monthly (default
monthly).
{
"success": true,
"message": "fare transactions",
"data": {
"period": "monthly",
"summary": {
"total_public_fare": 2405,
"total_agent_fare": 2400,
"total_agent_commission": 5,
"transaction_count": 1
},
"transactions": [
{
"id": "a1b2c3...",
"booking_ref": "FA-1775272567576",
"pnr": "FVRVRV",
"agent_id": "550e8400-...",
"agent_name": "John Smith",
"public_fare": 2405,
"agent_fare": 2400,
"agent_commission": 5,
"currency": "INR",
"issued_at": "2026-04-10T09:23:20Z"
}
],
"total": 1,
"page": 1,
"per_page": 20
}
}
Organization Wallet
Get Organization Wallet
GET /api/v1/org/wallet Success Response (200):
{
"success": true,
"message": "wallet retrieved",
"data": {
"id": "11111111-1111-1111-1111-111111111110",
"owner_id": "9551fa77-16ad-4df5-9284-dc23cb95c237",
"owner_type": "org",
"balance": 100000,
"currency": "INR",
"credit_limit": 0,
"is_active": true
}
}
Field Reference:
| Field | Description |
|---|---|
owner_type |
Who owns this wallet — org (the organization) or user (an individual agent). |
balance |
Current spendable funds in the wallet's currency. |
credit_limit |
Extra credit allowed beyond the balance before bookings are blocked (0 = none). |
is_active |
If false, the wallet cannot be used to pay for bookings. |
Get Wallet Transactions
GET /api/v1/org/wallet/transactions?page=1&per_page=20Returns the org wallet's transaction history with optional filters. Each entry records a debit when the admin allocated funds to an agent, or a credit when the super admin topped up.
Query Parameters:| Parameter | Type | Description |
|---|---|---|
page |
int | Page number (default: 1). |
per_page |
int | Results per page, max 100 (default: 20). |
type |
string | Filter by transaction type — credit or debit. |
ref_type |
string | Filter by reference type — topup, booking, refund, deduction. |
from |
date | Start date filter (YYYY-MM-DD). |
to |
date | End date filter (YYYY-MM-DD). |
min_amount |
float | Minimum transaction amount. |
max_amount |
float | Maximum transaction amount. |
search |
string | Search keyword in description (case-insensitive). |
{
"success": true,
"data": [
{
"id": "c5f3a2b1-1111-2222-3333-444444444444",
"created_at": "2026-04-15T10:00:00.000000+05:30",
"updated_at": "2026-04-15T10:00:00.000000+05:30",
"wallet_id": "11111111-1111-1111-1111-111111111110",
"type": "debit",
"amount": 5000,
"balance_before": 105000,
"balance_after": 100000,
"ref_type": "topup",
"ref_id": "550e8400-e29b-41d4-a716-446655440001",
"description": "allocated to agent: flight testing credits",
"performed_by": "5b920162-500f-474f-8e7a-5f131053a7d5",
"agent_id": "550e8400-e29b-41d4-a716-446655440001",
"agent_name": "John Smith"
},
{
"id": "d6e4b3c2-2222-3333-4444-555555555555",
"created_at": "2026-04-14T15:30:00.000000+05:30",
"updated_at": "2026-04-14T15:30:00.000000+05:30",
"wallet_id": "11111111-1111-1111-1111-111111111110",
"type": "credit",
"amount": 50000,
"balance_before": 55000,
"balance_after": 105000,
"ref_type": "topup",
"ref_id": null,
"description": "org wallet topup by super admin",
"performed_by": "00000000-0000-0000-0000-000000000001"
}
],
"meta": {
"page": 1,
"per_page": 20,
"total": 15,
"total_pages": 1
}
}
Field Reference:
| Field | Description |
|---|---|
type |
debit (funds deducted from the org wallet when allocating to an agent) or credit (funds added, e.g. super-admin topup to org, or a refund). |
wallet_id |
The org wallet's unique identifier — all transactions in this list share the same wallet. |
amount |
Transaction amount in INR. |
balance_before / balance_after |
Org wallet balance immediately before and after the transaction. |
ref_type |
Reason code — topup (allocation to/from agent), booking (flight booking), refund, or deduction. |
ref_id |
Optional reference to a related entity (e.g. booking reference). null for topups. |
description |
Human-readable note — "allocated to agent: <reason>" for admin-to-agent topups, or "org wallet topup by super admin" when SA adds funds. |
performed_by |
User ID of the admin (org admin or super admin) who performed the action. |
agent_id |
If this transaction is an agent allocation, the agent's UUID. omitted for non-allocation transactions. |
agent_name |
Agent's display name. omitted for non-allocation transactions. |
Wallet Transactions
Agent-level wallet funding and ledger exports. These let an org admin allocate funds to individual agents and download the org wallet's transaction history as CSV. All actions are scoped to the organization.
Export Transactions
GET /api/v1/org/wallet/transactions/export?from=2026-07-01&to=2026-07-28Downloads the org wallet's transaction history as a CSV file. Supports the same filters as the transactions list endpoint (without pagination).
Success Response (200):
Returns a text/csv file with
Content-Disposition: attachment.
Columns: ID, Date, Type, Amount, Balance Before,
Balance After, Reference Type, Description,
Performed By.
Topup Agent Wallet
POST /api/v1/org/wallet/topup/:agent_id
Allocates funds from the org wallet to an agent's
allocated balance. The :agent_id path
param is the agent's internal UUID.
{
"amount": 5000,
"description": "Monthly allocation for John"
}
Success Response (200):
{
"success": true,
"message": "wallet allocated to agent"
}
Error Response (400 — Insufficient Balance):
{
"success": false,
"error": "insufficient org wallet balance (available: 750.00)"
}
Field Reference:
| Field | Description |
|---|---|
amount |
Amount to allocate to the agent (deducted from org wallet). Must be greater than zero and ≤ org wallet balance. |
description |
Reason for the allocation. Visible in both org and agent transaction history. |
Get Wallet Summary
GET /api/v1/org/wallet/summaryDashboard-style roll-up of the org wallet: balances, total allocated to agents, and this month's credit/debit activity.
Success Response (200):
{
"success": true,
"message": "wallet summary retrieved",
"data": {
"current_balance": 100000,
"credit_limit": 0,
"available_balance": 100000,
"total_allocated_to_agents": 25000,
"agent_count": 8,
"this_month": {
"total_credits": 50000,
"total_debits": 12000,
"net_change": 38000,
"transaction_count": 14
},
"balance_trend": []
}
}
List Agents & Allocations
GET /api/v1/org/wallet/agentsEvery agent in the org with their current and lifetime allocated balances.
Success Response (200):
{
"success": true,
"message": "agents retrieved",
"data": [
{
"agent_id": "550e8400-e29b-41d4-a716-446655440001",
"name": "John Smith",
"username": "john",
"allocated_balance": 5000,
"total_allocated_to_date": 12000,
"last_allocation": "2026-04-14T15:30:00Z",
"is_active": true
}
]
}
Get Agent Transactions
GET /api/v1/org/wallet/agents/:agent_id/transactions?page=1&per_page=20Same transaction ledger as /org/wallet/transactions but scoped to a single agent. Supports the same type, ref_type, from, to, min_amount, max_amount and search filters.
{
"success": true,
"data": [
{
"id": "c5f3a2b1-1111-2222-3333-444444444444",
"type": "debit",
"amount": 5000,
"balance_before": 105000,
"balance_after": 100000,
"ref_type": "topup",
"description": "allocated to agent: flight testing credits",
"agent_id": "550e8400-e29b-41d4-a716-446655440001",
"agent_name": "John Smith"
}
],
"meta": { "page": 1, "per_page": 20, "total": 3, "total_pages": 1 }
}
Flight Pricing Package
Manage org-scoped flight pricing packages and agent-level package assignments. Org-scoped packages override global defaults and are only visible within the org. A package can be assigned to the whole organization (yourself) or to individual agents — an agent-level assignment overrides the org-level one.
Create Package
POST /api/v1/org/packages Request:
{
"name": "Premium Package",
"description": "Best fares with a flat markup",
"markup_type": "flat",
"markup_value": 150.0,
"markup_apply_on": "commission",
"priority": 0
}
Fields: markup_type (flat |
percent),
markup_apply_on
(commission | fare |
total).
service_fee_type /
service_fee_value,
gst_on_service_fee,
platform_charge,
min_commission, or
max_commission on org packages. These are
platform-level terms configured by the super admin
(global packages / SA markup rules) and are always
stored as zero for org-scoped packages. Any of these
keys sent in the request body are ignored.
{
"success": true,
"message": "package created",
"data": {
"id": "b3f1a2c4-...",
"name": "Premium Package",
"description": "Best fares with a flat markup",
"org_id": "9551fa77-...",
"scope": "org",
"markup_type": "flat",
"markup_value": 150.0,
"markup_apply_on": "commission",
"min_commission": 0,
"max_commission": 0,
"service_fee_type": "flat",
"service_fee_value": 0,
"gst_on_service_fee": 0,
"platform_charge": 0,
"priority": 0,
"is_active": true,
"created_by": "5b920162-...",
"created_at": "2026-04-15T10:00:00Z",
"updated_at": "2026-04-15T10:00:00Z"
}
}
List Packages
GET /api/v1/org/packages Success Response (200):
{
"success": true,
"message": "packages retrieved",
"data": [
{
"id": "b3f1a2c4-...",
"name": "Premium Package",
"scope": "org",
"org_id": "9551fa77-...",
"markup_type": "flat",
"markup_value": 150.0,
"markup_apply_on": "commission",
"min_commission": 0,
"max_commission": 0,
"service_fee_type": "flat",
"service_fee_value": 0,
"gst_on_service_fee": 0,
"platform_charge": 0,
"priority": 0,
"is_active": true,
"is_applied": false,
"created_at": "2026-04-15T10:00:00Z",
"updated_at": "2026-04-15T10:00:00Z"
}
]
}
Get Assigned Package
GET /api/v1/org/packages/assigned
Returns the currently assigned org-level package (not
agent-specific). Returns 404 if no package
is assigned.
{
"success": true,
"message": "assigned package",
"data": {
"id": "b3f1a2c4-...",
"name": "Premium Package",
"scope": "org",
"org_id": "9551fa77-...",
"markup_type": "flat",
"markup_value": 150.0,
"markup_apply_on": "commission",
"min_commission": 0,
"max_commission": 0,
"service_fee_type": "flat",
"service_fee_value": 0,
"gst_on_service_fee": 0,
"platform_charge": 0,
"priority": 0,
"is_active": true,
"created_by": "5b920162-...",
"created_at": "2026-04-15T10:00:00Z",
"updated_at": "2026-04-15T10:00:00Z",
"assignments": null
}
}
Update Package
PUT /api/v1/org/packages/:idSame request body as Create Package. Updates all configurable fields.
Success Response (200):
{
"success": true,
"message": "package updated",
"data": {
"id": "b3f1a2c4-...",
"name": "Premium Package",
"description": "Best fares with a flat markup",
"org_id": "9551fa77-...",
"scope": "org",
"markup_type": "flat",
"markup_value": 175.0,
"markup_apply_on": "commission",
"min_commission": 0,
"max_commission": 0,
"service_fee_type": "flat",
"service_fee_value": 0,
"gst_on_service_fee": 0,
"platform_charge": 0,
"priority": 0,
"is_active": true,
"created_by": "5b920162-...",
"created_at": "2026-04-15T10:00:00Z",
"updated_at": "2026-04-16T11:32:07Z"
}
}
Delete Package
DELETE /api/v1/org/packages/:idPerforms a hard delete (scoped to the org).
Success Response (200):
{
"success": true,
"message": "package deleted"
}
Assign Package to Organization
POST /api/v1/org/packages/assignAssigns a package to the org itself. Removes any previous org-level assignment.
Request:
{
"package_id": "b3f1a2c4-..."
}
Success Response (200):
{
"success": true,
"message": "package assigned"
}
Unassign Package from Organization
DELETE /api/v1/org/packages/assign Success Response (200):
{
"success": true,
"message": "package unassigned"
}
List Agent Assignments
GET /api/v1/org/packages/agent-assignmentsReturns all agent-specific package assignments for the org, with the preloaded package details.
Success Response (200):
{
"success": true,
"message": "agent assignments",
"data": [
{
"id": "a1b2c3d4-...",
"package_id": "b3f1a2c4-...",
"org_id": "9551fa77-...",
"agent_id": "5b920162-...",
"assigned_at": "2026-04-15T10:00:00Z",
"assigned_by": "6315581f-...",
"package": {
"id": "b3f1a2c4-...",
"name": "Premium Package",
"markup_type": "flat",
"markup_value": 150.0,
...
}
}
]
}
Assign Package to Agent
POST /api/v1/org/packages/assign-agent/:agent_idAssigns a package to a specific agent (agent-level override). Replaces any prior agent assignment.
Request:
{
"package_id": "b3f1a2c4-..."
}
Success Response (200):
{
"success": true,
"message": "package assigned to agent"
}
Unassign Package from Agent
DELETE /api/v1/org/packages/assign-agent/:agent_id Success Response (200):
{
"success": true,
"message": "agent assignment removed"
}
Delete Package
DELETE /api/v1/org/packages/:id Success Response (200):
{
"success": true,
"message": "package deleted"
}
Hotel Pricing Package
Manage org-scoped hotel pricing packages and agent-level
assignments. A hotel package may define price bands
(price_ranges) that drive the markup by
booking total, or a single fallback
markup_type / markup_value.
Org-scoped packages override global defaults. A package can
be assigned to the whole organization (yourself) or to
individual agents — an agent-level assignment
overrides the org-level one.
List Hotel Packages
GET /api/v1/org/hotel-packages Success Response (200):
{
"success": true,
"message": "hotel packages retrieved",
"data": [
{
"id": "c3f1a2c4-...",
"name": "Premium Hotel Package",
"scope": "org",
"org_id": "9551fa77-...",
"service_type": "hotel",
"markup_type": "flat",
"markup_value": 150.0,
"markup_apply_on": "commission",
"priority": 0,
"is_active": true,
"price_ranges": [
{ "id": "pr1", "min_amount": 0, "max_amount": null, "markup_type": "flat", "markup_value": 100 }
],
"created_at": "2026-04-15T10:00:00Z",
"updated_at": "2026-04-15T10:00:00Z"
}
]
}
Create Hotel Package
POST /api/v1/org/hotel-packages Request:
{
"name": "Premium Hotel Package",
"description": "Best hotel fares with a flat markup",
"markup_type": "flat",
"markup_value": 150.0,
"price_ranges": [
{ "min_amount": 0, "max_amount": null, "markup_type": "flat", "markup_value": 100 }
]
}
service_fee_type / service_fee_value,
gst_on_service_fee, platform_charge,
min_commission or max_commission on
org packages. These are platform-level terms configured by
the super admin and are always stored as zero for org-scoped
packages. Any of these keys sent in the request body are ignored.
{
"success": true,
"message": "hotel package created",
"data": {
"id": "c3f1a2c4-...",
"name": "Premium Hotel Package",
"description": "Best hotel fares with a flat markup",
"org_id": "9551fa77-...",
"scope": "org",
"service_type": "hotel",
"markup_type": "flat",
"markup_value": 150.0,
"markup_apply_on": "commission",
"priority": 0,
"is_active": true,
"price_ranges": [
{ "id": "pr1", "min_amount": 0, "max_amount": null, "markup_type": "flat", "markup_value": 100, "sort_order": 0 }
],
"created_by": "5b920162-...",
"created_at": "2026-04-15T10:00:00Z",
"updated_at": "2026-04-15T10:00:00Z"
}
}
Update Hotel Package
PUT /api/v1/org/hotel-packages/:idSame request body as Create Hotel Package. Updates all configurable fields.
Success Response (200):
{
"success": true,
"message": "hotel package updated",
"data": {
"id": "c3f1a2c4-...",
"name": "Premium Hotel Package",
"markup_type": "flat",
"markup_value": 175.0,
"markup_apply_on": "commission",
"priority": 0,
"is_active": true,
"price_ranges": [
{ "id": "pr1", "min_amount": 0, "max_amount": null, "markup_type": "flat", "markup_value": 125, "sort_order": 0 }
],
"updated_at": "2026-04-16T11:32:07Z"
}
}
Delete Hotel Package
DELETE /api/v1/org/hotel-packages/:idPerforms a hard delete (scoped to the org).
Success Response (200):
{
"success": true,
"message": "hotel package deleted"
}
Assign Package to Organization
POST /api/v1/org/hotel-packages/assignAssigns a hotel package to the org itself. Replaces any previous org-level assignment.
Request:
{
"package_id": "c3f1a2c4-..."
}
Success Response (200):
{
"success": true,
"message": "hotel package assigned"
}
Assign Package to Agent
POST /api/v1/org/hotel-packages/assign-agent/:agent_idAssigns a hotel package to a specific agent (agent-level override). Replaces any prior agent assignment.
Request:
{
"package_id": "c3f1a2c4-..."
}
Success Response (200):
{
"success": true,
"message": "hotel package assigned to agent"
}
Delete Hotel Package
DELETE /api/v1/org/hotel-packages/:id Success Response (200):
{
"success": true,
"message": "hotel package deleted"
}
Fare Transactions
View fare transaction history (fare ledger) for the
entire organization. Only org_admin can
access these endpoints.
List Fare Transactions
GET /api/v1/org/fare-transactions
Query Parameters: page,
per_page, period
(weekly | monthly, default
monthly).
{
"success": true,
"message": "fare transactions",
"data": {
"period": "monthly",
"summary": {
"total_public_fare": 125000.50,
"total_agent_fare": 118750.48,
"total_agent_commission": 6250.02,
"transaction_count": 42
},
"transactions": [
{
"id": "uuid",
"booking_ref": "GAM-ABCDEF",
"pnr": "6EABCD",
"agent_id": "5b920162-...",
"agent_name": "Test Agent",
"public_fare": 5500.00,
"agent_fare": 5225.00,
"agent_commission": 275.00,
"currency": "INR",
"issued_at": "2026-04-15T10:00:00Z"
}
],
"total": 42,
"page": 1,
"per_page": 20
}
}
Agent Fare Transactions (by Agent ID)
GET /api/v1/org/fare-transactions/:agent_id
Same response shape as List Fare Transactions,
but scoped to a single agent within the organization.
Query Parameters: page, per_page,
period (weekly |
monthly, default monthly).
{
"success": true,
"message": "fare transactions",
"data": {
"period": "monthly",
"summary": {
"total_public_fare": 125000.50,
"total_agent_fare": 118750.48,
"total_agent_commission": 6250.02,
"transaction_count": 42
},
"transactions": [
{
"id": "uuid",
"booking_ref": "GAM-ABCDEF",
"pnr": "6EABCD",
"agent_id": "5b920162-...",
"agent_name": "Test Agent",
"public_fare": 5500.00,
"agent_fare": 5225.00,
"agent_commission": 275.00,
"currency": "INR",
"issued_at": "2026-04-15T10:00:00Z"
}
],
"total": 42,
"page": 1,
"per_page": 20
}
}
Supplier Summary
GET /api/v1/org/finance-summary
Aggregated fare ledger grouped by supplier for the
organization. Query Parameter: period
(weekly | monthly, default
monthly).
{
"success": true,
"message": "supplier finance summary",
"data": {
"period": "monthly",
"by_supplier": [
{
"provider": "rezb",
"currency": "INR",
"public_fare": 125000.50,
"agent_fare": 118750.48,
"markup": 6250.02,
"bookings": 42
}
]
}
}
Organization Reports
Generate and download org-scoped reports. Reports are
generated asynchronously — create one, then poll
GET /org/reports until its status
is ready, then download the CSV.
Agents have an equivalent self-scoped surface under
/reports and /reports/:id/download
with the identical request/response schema, scoped to the
requesting agent.
Generate a Report
POST /api/v1/org/reports Request:
{
"type": "sales",
"period_start": "2026-07-01",
"period_end": "2026-07-31",
"filters": {}
}
type is one of
sales, agent_activity,
booking, wallet.
period_start / period_end are
required YYYY-MM-DD.
{
"success": true,
"message": "report queued for generation",
"data": {
"id": "3f9c2b...",
"type": "sales",
"status": "queued",
"period_start": "2026-07-01T00:00:00Z",
"period_end": "2026-07-31T00:00:00Z",
"requested_by": "5b920162-...",
"requester_type": "org_user",
"org_id": "9551fa77-...",
"created_at": "2026-07-28T10:00:00Z"
}
}
List Reports
GET /api/v1/org/reports?page=1&per_page=20 Success Response (200):
{
"success": true,
"data": [
{
"id": "3f9c2b...",
"type": "sales",
"status": "ready",
"period_start": "2026-07-01T00:00:00Z",
"period_end": "2026-07-31T00:00:00Z",
"file_url": "/reports/3f9c2b.../download",
"generated_at": "2026-07-28T10:01:12Z",
"expires_at": "2026-08-28T10:01:12Z"
}
],
"meta": { "page": 1, "per_page": 20, "total": 1, "total_pages": 1 }
}
status values:
queued, processing,
ready, failed.
Download Report (CSV)
GET /api/v1/org/reports/:id/download
Returns the report as a CSV file attachment
(Content-Disposition: attachment; filename="report-<type>-<id>.csv"),
not a JSON body. The report must have
status: "ready" or the API returns
400.
HTTP/1.1 200 OK Content-Type: text/csv Content-Disposition: attachment; filename="report-sales-3f9c2b....csv" booking_ref,pnr,public_fare,agent_fare,... FA-...,...,2405,2400,...
Self Profile (/me endpoints)
All authenticated org users (both
org_admin and agent) can
access these endpoints.
Get My Profile
GET /api/v1/me Success Response (200):
{
"success": true,
"message": "profile retrieved",
"data": {
"id": "11111111-1111-1111-1111-111111111111",
"username": "admin",
"email": "admin@demo.com",
"name": "Demo Admin",
"phone": "",
"role": "org_admin",
"status": "active",
"org_id": "9551fa77-16ad-4df5-9284-dc23cb95c237",
"sub_agent_id": "GAMDEMO0002",
"last_login_at": "2026-04-10T14:45:35.36903+05:30"
}
}
Update My Profile
PUT /api/v1/me Request:
{
"name": "Updated Name",
"phone": "+919999999999"
}
Success Response (200):
{
"success": true,
"message": "profile updated",
"data": {
"id": "11111111-1111-1111-1111-111111111111",
"username": "admin",
"email": "admin@demo.com",
"name": "Updated Name",
"phone": "+919999999999",
"role": "org_admin",
"status": "active"
}
}
Change Password
PUT /api/v1/me/password Request:
{
"current_password": "OldPassword@123",
"new_password": "NewPassword@123"
}
Success Response (200):
{
"success": true,
"message": "password changed successfully"
}
Error Response (400):
{
"success": false,
"error": "current password is incorrect"
}
My Stats
GET /api/v1/me/stats Success Response (200):
{
"success": true,
"message": "stats retrieved",
"data": {
"total_bookings": 0,
"confirmed_bookings": 0,
"cancelled_bookings": 0,
"total_spent": 0,
"total_commissions": 0,
"wallet_balance": 0
}
}
Wallet (Self)
Get My Wallet
GET /api/v1/wallet Success Response (200):
{
"success": true,
"message": "wallet retrieved",
"data": {
"id": "22222222-2222-2222-2222-222222222220",
"owner_id": "5b920162-500f-474f-8e7a-5f131053a7d5",
"owner_type": "user",
"balance": 5000,
"allocated_balance": 5000,
"currency": "INR",
"credit_limit": 0,
"is_active": true
}
}
Get My Transactions
GET /api/v1/wallet/transactions
Query Parameters: page,
per_page
{
"success": true,
"data": [
{
"id": "uuid",
"type": "credit",
"amount": 5000,
"description": "Wallet topup from org",
"created_at": "2026-04-15T10:00:00Z"
}
],
"meta": {
"page": 1,
"per_page": 20,
"total": 1,
"total_pages": 1
}
}
Flight Search
Search one-way, round-trip, or multi-city itineraries across airlines and get shoppable fares you can price and book in the next steps.
POST /api/v1/flights/searchOne Way
{
"search_params": {
"trip_type": "ONE_WAY",
"passengers": {
"adults": 1,
"children": 0,
"infants": 0
},
"cabin_class": "ECONOMY",
"preferred_currency": "INR",
"direct_flights_only": false,
"max_results": 3,
"airline_id": ""
},
"slices": [
{
"origin": "DEL",
"destination": "BOM",
"departure_date": "2026-05-01"
}
]
}
Round Trip
{
"search_params": {
"trip_type": "RETURN",
"passengers": {
"adults": 1,
"children": 0,
"infants": 0
},
"cabin_class": "ECONOMY",
"preferred_currency": "INR",
"max_results": 3
},
"slices": [
{
"origin": "DEL",
"destination": "BOM",
"departure_date": "2026-05-01"
},
{
"origin": "BOM",
"destination": "DEL",
"departure_date": "2026-05-05"
}
]
}
Trip Types: ONE_WAY,
RETURN, MULTI_CITY
Cabin Classes: ECONOMY,
PREMIUM_ECONOMY, BUSINESS,
FIRST
Validation: cabin_class is required,
adults 1-9, children 0-9, infants 0-9,
preferred_currency must be 3 letters,
slices min=1 max=6
{
"success": true,
"message": "3 offers found",
"data": {
"search_id": "srch_20260410_17407",
"search_meta": {
"currency": "INR",
"created_at": "2026-04-10T09:23:20.254656Z",
"expires_at": "2026-04-10T09:48:20.260503Z",
"total_results": 3,
"duration_ms": 20189,
"provider_status": {
"m7n4p8qr": { "status": "success", "duration_ms": 20189, "results": 831 },
"a3f9kx2b": { "status": "success", "duration_ms": 0, "results": 0 }
}
},
"dictionaries": {
"airlines": {
"6E": { "name": "IndiGo", "logo_url": "https://pics.avs.io/200/200/6E.png" },
"I5": { "name": "AirAsia India", "logo_url": "https://pics.avs.io/200/200/I5.png" }
},
"airports": {
"DEL": { "name": "Indira Gandhi International Airport", "city": "Delhi", "country": "India", "iso_country": "IN", "timezone": "Asia/Kolkata", "utc_offset": "+05:30" },
"BOM": { "name": "Chhatrapati Shivaji International Airport", "city": "Mumbai", "country": "India", "iso_country": "IN", "timezone": "Asia/Kolkata", "utc_offset": "+05:30" }
},
"baggage": {
"BAG_15KG": { "check_in": "15KG", "cabin": "7KG", "fare_family": "Saver", "desc": "15 kg check-in + 7 kg cabin" }
},
"refund_policies": {
"REF_NON": { "is_refundable": false, "cancel_fee": null, "change_fee": null, "no_show_fee": null }
}
},
"segments": [
{
"segment_id": "seg_591c95",
"airline": "I5",
"flight_number": "IX 1056",
"origin": "DEL",
"destination": "BOM",
"departure": "2026-05-01T18:10:00Z",
"arrival": "2026-05-01T20:30:00Z",
"duration_minutes": 140,
"aircraft_type": "A320",
"cabin": "ECONOMY",
"operating_carrier": "I5",
"seats_available": 9
}
],
"legs": [
{
"leg_id": "leg_delbom_0",
"route_index": 0,
"origin": "DEL",
"destination": "BOM",
"departure": "2026-05-01T18:10:00Z",
"arrival": "2026-05-01T20:30:00Z",
"duration_minutes": 140,
"stops": 0,
"stops_detail": [],
"segments": ["seg_591c95"],
"operating_carrier": "I5"
}
],
"offers": [
{
"offer_id": "off_m7n4p8qr:YeRaP0TPvhs...",
"type": "combinable",
"route_index": 0,
"combination_group_id": "cg_abc123",
"combinable_with": "cg_abc123",
"legs": ["leg_delbom_0"],
"supplier": "m7n4p8qr",
"price": {
"total": 2368,
"public_fare": 2368,
"agent_price": {
"service_fee": 50,
"gst_on_service_fee": 9,
"platform_charge": 25,
"agent_fare": 2363
},
"currency": "INR",
"breakdown": [
{
"passenger_type": "ADT",
"count": 1,
"unit_base": 1001,
"unit_tax": 1367,
"subtotal": 2368
}
]
},
"fare_details": {
"fare_class": "E",
"fare_family": "Saver",
"fare_name": "VALUE",
"seats_left": 9,
"baggage_ref": "BAG_15KG",
"refund_ref": "REF_NON"
},
"supplier_ref": {
"offer_token": "m7n4p8qr:YeRaP0TPvhs...",
"integrity_hash": "a1b2c3d4e5f6...",
"expires_at": "2026-04-10T09:53:07.279146Z"
}
}
],
"debug": {
"provider_errors": {}
}
}
}
The
type field in each offer indicates how
the offer can be combined with other offers for
multi-passenger bookings:| Type | Description | Usage |
|---|---|---|
combinable |
Offer can be combined with other combinable offers of the same airline/route to form a single booking | Use directly in booking - can mix with other combinable offers for group bookings |
bundled |
Offer is a pre-bundled package that must be booked as-is | Use directly in booking - cannot combine with other offers |
one_way |
Offer is for a single leg only (return journey requires separate booking) | Book separately or combine with another one_way for return |
offer |
NDC-style offer from provider | Use directly in booking – cannot combine with other offers |
Example - Booking 3 passengers with combinable offers:
If you have 3 passengers and find 3 separate
combinable offers for the same flight, you
can select all 3 in the price-itinerary request to get a
combined price for all passengers. The
offer_id from each combinable offer should
be included in the offer_ids array.
| Field | Description |
|---|---|
offer_id |
Unique ID for this fare offer — pass it to /price or /fare-rules. |
supplier |
Code of the flight provider that returned this offer (matches keys in provider_status). |
price.total / public_fare |
Total price shown to the end customer, in price.currency. |
price.agent_price.agent_fare |
The net amount actually deducted from the agent's wallet for this booking. |
price.agent_price.service_fee |
Platform service fee added on top of the base fare. |
price.agent_price.gst_on_service_fee |
Tax (GST) charged on the service fee. |
fare_details.fare_class / fare_family |
Airline's fare bucket and named fare tier (e.g. "Saver"). |
fare_details.seats_left |
Number of seats remaining at this fare — useful for urgency messaging. |
fare_details.baggage_ref / refund_ref |
Keys that look up baggage and refund policy details in the dictionaries object. |
supplier_ref.expires_at |
Timestamp after which this offer is no longer bookable — re-search after this time. |
{
"success": true,
"message": "2 offers found",
"data": {
"search_id": "srch_20260410_17411",
"search_meta": {
"currency": "INR",
"created_at": "2026-04-10T09:24:05.101832Z",
"expires_at": "2026-04-10T09:49:05.108021Z",
"total_results": 2,
"duration_ms": 18422,
"provider_status": {
"m7n4p8qr": { "status": "success", "duration_ms": 18422, "results": 412 }
}
},
"dictionaries": {
"airlines": {
"6E": { "name": "IndiGo", "logo_url": "https://pics.avs.io/200/200/6E.png" }
},
"airports": {
"DEL": { "name": "Indira Gandhi International Airport", "city": "Delhi", "country": "India", "iso_country": "IN", "timezone": "Asia/Kolkata", "utc_offset": "+05:30" },
"BOM": { "name": "Chhatrapati Shivaji International Airport", "city": "Mumbai", "country": "India", "iso_country": "IN", "timezone": "Asia/Kolkata", "utc_offset": "+05:30" }
},
"baggage": {
"BAG_15KG": { "check_in": "15KG", "cabin": "7KG", "fare_family": "Saver", "desc": "15 kg check-in + 7 kg cabin" }
},
"refund_policies": {
"REF_NON": { "is_refundable": false, "cancel_fee": null, "change_fee": null, "no_show_fee": null }
}
},
"segments": [
{ "segment_id": "seg_out_1", "airline": "6E", "flight_number": "6E 320", "origin": "DEL", "destination": "BOM", "departure": "2026-05-01T08:40:00Z", "arrival": "2026-05-01T10:20:00Z", "duration_minutes": 100, "aircraft_type": "A320", "cabin": "ECONOMY", "operating_carrier": "6E", "seats_available": 6 },
{ "segment_id": "seg_ret_1", "airline": "6E", "flight_number": "6E 455", "origin": "BOM", "destination": "DEL", "departure": "2026-05-05T19:15:00Z", "arrival": "2026-05-05T21:05:00Z", "duration_minutes": 110, "aircraft_type": "A320", "cabin": "ECONOMY", "operating_carrier": "6E", "seats_available": 4 }
],
"legs": [
{ "leg_id": "leg_delbom_0", "route_index": 0, "origin": "DEL", "destination": "BOM", "departure": "2026-05-01T08:40:00Z", "arrival": "2026-05-01T10:20:00Z", "duration_minutes": 100, "stops": 0, "stops_detail": [], "segments": ["seg_out_1"], "operating_carrier": "6E" },
{ "leg_id": "leg_bomdel_1", "route_index": 1, "origin": "BOM", "destination": "DEL", "departure": "2026-05-05T19:15:00Z", "arrival": "2026-05-05T21:05:00Z", "duration_minutes": 110, "stops": 0, "stops_detail": [], "segments": ["seg_ret_1"], "operating_carrier": "6E" }
],
"offers": [
{
"offer_id": "off_m7n4p8qr:W8j24Tcq6yjEiC6Sn8BKGwSb...",
"type": "combinable",
"route_index": 0,
"combination_group_id": "cg_rt001",
"combinable_with": "cg_rt001",
"legs": ["leg_delbom_0"],
"supplier": "m7n4p8qr",
"price": {
"total": 2405,
"public_fare": 2405,
"agent_price": { "service_fee": 50, "gst_on_service_fee": 9, "platform_charge": 25, "agent_fare": 2400 },
"currency": "INR",
"breakdown": [{ "passenger_type": "ADT", "count": 1, "unit_base": 1000, "unit_tax": 1405, "subtotal": 2405 }]
},
"fare_details": { "fare_class": "R", "fare_family": "Saver", "fare_name": "SAVER", "seats_left": 6, "baggage_ref": "BAG_15KG", "refund_ref": "REF_NON" },
"supplier_ref": { "offer_token": "m7n4p8qr:W8j24Tcq6yjEiC6Sn8BKGwSb...", "integrity_hash": "b2c3d4e5f6a7...", "expires_at": "2026-04-10T09:54:05.108021Z" }
},
{
"offer_id": "off_m7n4p8qr:9kLm3NpQr7tYvBxZ5cFgHsJd...",
"type": "combinable",
"route_index": 1,
"combination_group_id": "cg_rt002",
"combinable_with": "cg_rt002",
"legs": ["leg_bomdel_1"],
"supplier": "m7n4p8qr",
"price": {
"total": 2405,
"public_fare": 2405,
"agent_price": { "service_fee": 50, "gst_on_service_fee": 9, "platform_charge": 25, "agent_fare": 2400 },
"currency": "INR",
"breakdown": [{ "passenger_type": "ADT", "count": 1, "unit_base": 1000, "unit_tax": 1405, "subtotal": 2405 }]
},
"fare_details": { "fare_class": "R", "fare_family": "Saver", "fare_name": "SAVER", "seats_left": 4, "baggage_ref": "BAG_15KG", "refund_ref": "REF_NON" },
"supplier_ref": { "offer_token": "m7n4p8qr:9kLm3NpQr7tYvBxZ5cFgHsJd...", "integrity_hash": "c3d4e5f6a7b8...", "expires_at": "2026-04-10T09:54:05.108021Z" }
}
],
"debug": { "provider_errors": {} }
}
}
Round Trip: each route_index
(0 = outbound, 1 = return) has its own set of offers.
To book both directions together, pass one
offer_id from
route_index: 0 and one from
route_index: 1 in the
offer_ids array sent to
Price Itinerary.
Stream Search (Server-Sent Events)
POST /api/v1/flights/search/stream
Identical request body to Search
Flights, but results are pushed as a
Server-Sent Events stream
(text/event-stream) instead of a single JSON
response. Each event carries the complete
SearchResponse snapshot, so the client can
replace its state wholesale as providers return.
event: results
data: { "success": true, "message": "N offers found", "data": { "search_id": "...", "search_meta": {...}, "segments": [...] } }
event: done
data: { "success": true, "message": "search complete", "data": { "search_id": "...", "search_meta": {...}, "segments": [...] } }
Get Fare Rules
POST /api/v1/flights/fare-rules Request:
{
"search_id": "srch_20260410_17407",
"offer_ids": ["m7n4p8qr:W8j24Tcq6yjEiC6Sn8BKGwSb..."]
}
Note: Use offer_ids from
the search response. Alternatively, you can pass
fare_keys or booking_keys.
At least one of these arrays must be non-empty.
m7n4p8qr,
the underlying GetFareRule call may return a
provider-side error (e.g.
EX-Unable to get FareRule for the requested flight)
in non-production/sandbox environments. The request is
built correctly (it carries the track ID, flight number
and travel date reconstructed from the fare key); the
failure originates at the supplier, not the aggregator.
{
"success": true,
"message": "fare rules retrieved",
"data": {
"fare_key": "m7n4p8qr:W8j24Tcq6yjEiC6Sn8BKGwSb...",
"cancellation": "Cancellation 0H-24H: INR 350",
"date_change": "Date change allowed with fare difference",
"baggage_policy": "Check-in: 15KG | Cabin: 7KG",
"raw_text": "FARE BASIS: XNRA015\nFARE TYPE: Refundable\nCANCELLATION: 0H-24H penalty INR 350\nBAGGAGE: 15KG check-in + 7KG cabin"
}
}
Price Itinerary
POST /api/v1/flights/priceOne Way
{
"offer_ids": ["m7n4p8qr:W8j24Tcq6yjEiC6Sn8BKGwSb..."],
"adults": 1,
"children": 0,
"infants": 0
}
Round Trip
{
"offer_ids": [
"m7n4p8qr:W8j24Tcq6yjEiC6Sn8BKGwSb...",
"m7n4p8qr:9kLm3NpQr7tYvBxZ5cFgHsJd..."
],
"adults": 1,
"children": 0,
"infants": 0
}
Alternative format: Wrap
offer_ids inside
flight_selection object. The API accepts
both offer_ids at root level and
{ flight_selection: { offer_ids: [...] } }.
Response — One Way / Round Trip
{
"success": true,
"message": "pricing successful",
"data": {
"booking_keys": ["m7n4p8qr-book:1BG8QVD8geiCxp0Phy...."],
"status": "PRICE_VERIFIED",
"currency": "INR",
"expires_at": "2026-04-10T16:26:54.903522+05:30",
"price_summary": {
"total_payable": 2410,
"public_fare": 2410,
"currency": "INR",
"exchange_rate": 1,
"base_fare_total": 1000,
"tax_total": 1321,
"agent_details": {
"agent_fare": 2405,
"service_fee": 50,
"gst_on_service_fee": 9,
"platform_charge": 25
}
},
"passenger_breakdown": [
{
"pax_type": "ADT",
"count": 1,
"base_per_pax": 1000,
"tax_per_pax": 1410,
"total_per_pax": 2410,
"tax_breakdown": [
{ "code": "RCF", "amount": 50, "description": "Regulatory Compliance Fee" },
{ "code": "YQ", "amount": 600, "description": "Fuel Surcharge" },
{ "code": "ASF", "amount": 236, "description": "Airport Service Fee" },
{ "code": "UDF", "amount": 152, "description": "User Development Fee" }
]
}
],
"itinerary_snapshot": {
"segments": [
{
"segment_id": "seg_1",
"airline": "6E",
"operating_carrier": "6E",
"flight_number": "6E 320",
"origin": "DEL",
"destination": "BOM",
"dep_terminal": "1",
"arr_terminal": "2",
"departure": "2026-04-15T08:40:00",
"arrival": "2026-04-15T10:20:00",
"cabin_class": "ECONOMY",
"rbd": "R",
"fare_basis": "RLIP",
"fare_type": "B",
"baggage": "20 KG",
"cabin_baggage": "7 Kg",
"refundable": true,
"avail_seats": 114,
"duration_minutes": 100
}
]
},
"fare_rules": {
"is_refundable": true,
"cancellation_fee": null,
"change_fee": null,
"rule_text": null
},
"ancillaries": [
{
"type": "MEAL",
"code": "VLML",
"name": "Veg lacto meal + beverage",
"price": 0,
"segment_id": "seg_1"
},
{
"type": "BAGGAGE",
"code": "XBPC",
"name": "ExcessBaggage 15KG",
"price": 4500,
"segment_id": "seg_1"
}
]
}
}
Field Reference:
| Field | Description |
|---|---|
booking_keys |
Locked-in price keys — pass these to /book instead of the original offer_ids. |
status |
PRICE_VERIFIED means the fare is confirmed and safe to book before expires_at. |
expires_at |
Deadline by which the booking must be completed at this price. |
price_summary.total_payable |
Final amount the customer pays, including all taxes. |
price_summary.agent_details.agent_fare |
Amount that will be deducted from the agent's wallet if they proceed with booking. |
passenger_breakdown[].tax_breakdown |
Itemized taxes and surcharges (e.g. fuel surcharge, airport fee) per passenger type. |
fare_rules.is_refundable |
Whether this fare allows a refund on cancellation. |
ancillaries |
Optional add-ons (meals, extra baggage, etc.) available for this itinerary, with their price. |
itinerary_snapshot.segments
difference:
"itinerary_snapshot": {
"segments": [
{
"segment_id": "seg_1",
"airline": "6E",
"operating_carrier": "6E",
"flight_number": "6E 320",
"origin": "DEL",
"destination": "BOM",
"dep_terminal": "1",
"arr_terminal": "2",
"departure": "2026-05-01T08:40:00",
"arrival": "2026-05-01T10:20:00",
"cabin_class": "ECONOMY",
"rbd": "R",
"fare_basis": "RLIP",
"fare_type": "B",
"baggage": "15 KG",
"cabin_baggage": "7 Kg",
"refundable": false,
"avail_seats": 6,
"duration_minutes": 100
},
{
"segment_id": "seg_2",
"airline": "6E",
"operating_carrier": "6E",
"flight_number": "6E 455",
"origin": "BOM",
"destination": "DEL",
"dep_terminal": "2",
"arr_terminal": "3",
"departure": "2026-05-05T19:15:00",
"arrival": "2026-05-05T21:05:00",
"cabin_class": "ECONOMY",
"rbd": "R",
"fare_basis": "RLIP",
"fare_type": "B",
"baggage": "15 KG",
"cabin_baggage": "7 Kg",
"refundable": false,
"avail_seats": 4,
"duration_minutes": 110
}
]
}
For a round trip, every other field in the response
(price_summary,
passenger_breakdown,
fare_rules, ancillaries)
keeps the same shape shown above — only
itinerary_snapshot.segments grows to one
entry per flight leg (outbound + return), and the
totals reflect the combined price of both legs.
{
"success": false,
"error": "insufficient wallet balance to proceed — available: 0.00, required: 2372.00 (agent fare)"
}
This means the agent's wallet doesn't have enough
balance to cover the agent_fare. Top up
the wallet before retrying (see
Organization Wallet or
Wallet (Self)).
{
"success": false,
"error": "offer has expired, please search again"
}
Offers from Flight Search
are only valid for a short window
(supplier_ref.expires_at). If pricing is
attempted after that window, re-run the search and
price the new offer_id.
Book Flight
POST /api/v1/flights/bookOne Way
{
"booking_keys": ["m7n4p8qr-book:1BG8QVD8gz...."],
"contact_email": "john.doe@example.com",
"contact_phone": "9876543210",
"contact_country_code": "91",
"passengers": [
{
"pax_index": 1,
"type": "ADT",
"title": "MR",
"first_name": "JOHN",
"last_name": "DOE",
"gender": "Male",
"dob": "1990-06-15",
"infant_ref": 0,
"ancillaries": [
{
"type": "MEAL",
"code": "VLML-",
"segment_id": "seg_1"
}
]
}
]
}
Round Trip
{
"booking_keys": [
"m7n4p8qr-book:1BG8QVD8gz....",
"m7n4p8qr-book:9kLm3NpQr7tYvBxZ..."
],
"contact_email": "john.doe@example.com",
"contact_phone": "9876543210",
"contact_country_code": "91",
"passengers": [
{
"pax_index": 1,
"type": "ADT",
"title": "MR",
"first_name": "JOHN",
"last_name": "DOE",
"gender": "Male",
"dob": "1990-06-15",
"infant_ref": 0,
"ancillaries": [
{
"type": "MEAL",
"code": "VLML-",
"segment_id": "seg_1"
}
]
}
]
}
booking_keys
array comes from the /price response.
Use offer_ids instead if booking
without pricing. If the org has ticket password
enabled, include
"issue_ticket_password": "your-password".
Response — One Way
{
"success": true,
"message": "booking confirmed",
"data": {
"booking_ref": "FA-1773235577155",
"provider": "m7n4p8qr",
"status": "CONFIRMED",
"total_amount": 4540,
"currency": "INR",
"legs": [
{
"booking_track_id": "RACCU03000030103585841103260092140",
"provider_pnr": "BX11HC0130",
"airline_pnr": "U11VNS",
"ticket_number": "BX11HC01301-1",
"origin": "DEL",
"destination": "CCU",
"gross_amount": 4540,
"currency": "INR",
"issued_date": "11/03/2026 18:56:13"
}
]
}
}
Response — Round Trip
{
"success": true,
"message": "booking confirmed",
"data": {
"booking_ref": "FA-1773241902318",
"provider": "m7n4p8qr",
"status": "CONFIRMED",
"total_amount": 4810,
"currency": "INR",
"legs": [
{
"booking_track_id": "RACCU03000030103585841103260092141",
"provider_pnr": "BX11HC0131",
"airline_pnr": "U11VNT",
"ticket_number": "BX11HC01311-1",
"origin": "DEL",
"destination": "BOM",
"gross_amount": 2405,
"currency": "INR",
"issued_date": "11/03/2026 18:59:02"
},
{
"booking_track_id": "RACCU03000030103585841103260092142",
"provider_pnr": "BX11HC0132",
"airline_pnr": "U11VNU",
"ticket_number": "BX11HC01311-2",
"origin": "BOM",
"destination": "DEL",
"gross_amount": 2405,
"currency": "INR",
"issued_date": "11/03/2026 18:59:02"
}
]
}
}
Field Reference:
| Field | Description |
|---|---|
booking_ref |
GAMAN's own booking reference — use this for all later booking-management calls. |
provider |
Code of the airline/GDS provider that fulfilled the booking. |
status |
CONFIRMED means seats are held; ticketing may still be pending — check tickets/issue-ticket. |
legs[].booking_track_id |
Internal tracking ID for this leg — used by the /track endpoint. |
legs[].provider_pnr / airline_pnr |
Reservation code from the provider system and the airline respectively — give the airline PNR to customers. |
legs[].ticket_number |
Airline e-ticket number, once issued. |
Round Trip: as shown above, the
legs array contains 2 entries — the
first for the outbound flight, the second for the
return flight — each with its own PNR and ticket
number.
{
"success": false,
"error": "booking key has expired, please price the itinerary again"
}
Returned when the booking_keys from
Price Itinerary have
passed their expires_at time before
/book was called. Re-run
Price Itinerary to get fresh
booking_keys and retry.
List Bookings
GET /api/v1/flights/bookings
Query Parameters: page,
per_page, status (pending,
confirmed, cancelled)
{
"success": true,
"data": [
{
"id": "8555813d-f437-49ff-9e7e-a1d144894528",
"booking_ref": "FA-1775272567576",
"pnr": "BX04HD0001",
"provider": "m7n4p8qr",
"origin": "BOM",
"destination": "DEL",
"passenger_count": 1,
"base_fare": 2162,
"public_fare": 2162,
"currency": "INR",
"status": "confirmed",
"booked_at": "2026-04-04T08:46:07.576683+05:30",
"passengers": [
{
"title": "MR",
"first_name": "JOHN",
"last_name": "DOE",
"type": "ADT"
}
]
}
],
"meta": {
"page": 1,
"per_page": 20,
"total": 3,
"total_pages": 1
}
}
Get Booking Details
GET /api/v1/flights/bookings/:ref Example:GET /api/v1/flights/bookings/FA-1775272567576Success Response (200):
{
"success": true,
"message": "booking retrieved",
"data": {
"booking_id": "ca056426-bc9a-4859-8dbc-44c5bac26e83",
"booking_ref": "FA-1773235577155",
"provider": "m7n4p8qr",
"provider_ref": "RACCU03000030103585841103260092140",
"status": "CONFIRMED",
"created_at": "2026-03-11T18:56:17.159116+05:30",
"currency": "INR",
"pnr_details": [
{
"pnr": "BX11HC0130",
"airline_pnr": "U11VNS",
"airline": "6E",
"supplier": "m7n4p8qr",
"supplier_ref": "RACCU03000030103585841103260092140",
"status": "CONFIRMED",
"segment_refs": ["seg_1"],
"ancillaries": [
{ "type": "MEAL", "code": "VLML-", "segment_id": "seg_1" }
]
}
],
"passengers": [
{
"pax_id": "pax_001",
"type": "ADT",
"title": "MR",
"first_name": "JOHN",
"last_name": "DOE",
"dob": "1990-06-15",
"gender": "Male",
"seat_onward": "",
"seat_return": ""
}
],
"itinerary": {
"legs": [
{ "leg_index": 0, "origin": "DEL", "destination": "CCU", "segment_refs": ["seg_1"] }
],
"segments": [
{
"segment_id": "seg_1",
"airline": "6E",
"flight_number": "6E 320",
"origin": "DEL",
"destination": "CCU",
"departure": "2026-03-11T18:30:00",
"arrival": "2026-03-11T20:45:00",
"duration_minutes": 135,
"cabin": "ECONOMY",
"rbd": "R",
"baggage": "15KG",
"cabin_baggage": "7KG",
"operating_carrier": "6E",
"status": "CONFIRMED"
}
]
},
"pricing": {
"currency": "INR",
"total_payable": 4540,
"supplier_currency": "INR",
"supplier_total": 4540,
"exchange_rate": 1,
"public_fare": 2410,
"agent_fare": 2405,
"ancillary": 0,
"agent_details": {
"agent_fare": 2405,
"service_fee": 50,
"gst_on_service_fee": 9,
"platform_charge": 25
},
"pax_breakdown": [
{
"pax_id": "pax_001",
"type": "ADT",
"base": 1000,
"tax": 1410,
"total": 2410
}
]
},
"tickets": [
{
"tkt_number": "BX11HC01301-1",
"pax_id": "pax_001",
"pnr_ref": "BX11HC0130",
"status": "ISSUED",
"segment_refs": ["seg_1"]
}
],
"baggage_allowance": [],
"contact_details": {
"country_code": "91",
"phone": "9876543210",
"email": "john.doe@example.com"
},
"can_issue_ticket": false
}
}
Field Reference:
| Field | Description |
|---|---|
pnr_details[].status |
Status of this specific PNR (a booking can span multiple PNRs). |
passengers[].seat_onward / seat_return |
Assigned seat numbers, if seat selection was made — empty if not yet assigned. |
pricing.public_fare vs agent_fare |
Customer-facing price vs. what was actually charged to the agent's wallet; the difference includes fees and commission. |
pricing.ancillary |
Total of all ancillaries (meals / baggage / seats) selected at booking time, added on top of public_fare. Equals total_payable − public_fare − fees when present. |
pricing.agent_details |
Optional breakdown mirroring the Price response: agent_fare, service_fee, gst_on_service_fee, platform_charge, markup_amount. Omitted when no package is assigned. Provided for reconciliation; not shown on the customer-facing booking page. |
tickets[].status |
ISSUED means the e-ticket exists; otherwise call Issue Ticket. |
can_issue_ticket |
Whether the /issue-ticket endpoint can currently be called for this booking. |
pnr field is
deprecated. Use pnr_details array for
multi-PNR bookings.
itinerary.legs array contains 2 entries
(index 0 = outbound, index 1 = inbound), and
itinerary.segments includes all segments
across both legs. The pnr_details array may
contain separate PNRs per leg depending on the provider.
Retrieve Booking
Fetches latest booking data directly from the provider system and returns both the local DB record and the provider's response.
GET /api/v1/flights/bookings/:ref/retrieve Example:GET /api/v1/flights/bookings/FA-1775272567576/retrieveSuccess Response (200):
{
"success": true,
"message": "booking retrieved",
"data": {
"local": {
"booking_ref": "FA-1775272567576",
"pnr": "BX04HD0001",
"status": "confirmed",
"provider": "m7n4p8qr"
},
"provider": {
"booking_ref": "FA-1775272567576",
"pnr": "BX04HD0001",
"status": "confirmed",
"provider_booking_id": "RACCU03000030103630040404260094069",
"ticket_status": "CONFIRMED"
}
}
}
Track Booking Status
Tracks booking status from the provider. Response format is provider-specific.
GET /api/v1/flights/bookings/:ref/track Example:GET /api/v1/flights/bookings/FA-1775272567576/trackSuccess Response (200) — m7n4p8qr provider:
{
"success": true,
"message": "booking status",
"data": {
"Status": {
"Track_Status": "SUCCESS",
"ResultCode": "1"
},
"TrackStatusresponse": {
"ItinearyDetails": [
{
"RiyaPNR": "BX04HD0001",
"TotalAmount": "2162.00",
"TicketStatus": "CONFIRMED",
"TripType": "O"
}
]
}
}
}
Special Service Requests (SSR)
Retrieve and attach Special Service Requests (meals, baggage, seats) for an existing flight booking.
Get SSR (Special Services)
Retrieves Special Service Requests for a booking. Response is provider-dependent.
GET /api/v1/flights/bookings/:ref/ssr Query Parameters:?airline_pnr=U11VNS (optional)Example:
GET /api/v1/flights/bookings/FA-1775272567576/ssrSuccess Response (200):
{
"success": true,
"message": "SSR options",
"data": {
"SsrDetails": {
"Segments": [
{
"SegmentNo": "1",
"Meals": [
{
"Code": "VGML",
"Description": "Vegetarian Vegan Meal",
"Price": 350,
"Currency": "INR"
},
{
"Code": "VLML",
"Description": "Vegetarian Lacto/Ovo Meal",
"Price": 350,
"Currency": "INR"
}
],
"Baggage": [
{
"Code": "BAG15",
"Description": "Extra Baggage 15 KG",
"Price": 1200,
"Currency": "INR"
}
],
"Seats": [
{
"Code": "12A",
"Description": "Window Seat",
"Price": 500,
"Currency": "INR"
},
{
"Code": "12B",
"Description": "Aisle Seat",
"Price": 500,
"Currency": "INR"
}
]
}
]
}
}
}
airline_pnr
query parameter can be used to target a specific PNR.
provider does not support SSR here
because a3f9kx2b exposes ancillaries via the
Price response
(ancillaries), not a booked-PNR lookup. Use
/price to fetch a3f9kx2b SSR options.
Add SSR to Booking
Attaches ancillaries (meals / baggage / seats) to an
already-booked PNR. This complements adding
ancillaries at book time (see
Book Flight). Supported for
m7n4p8qr bookings; other providers return
provider does not support adding SSR.
{
"ssr": [
{
"type": "MEAL",
"code": "VLML-",
"segment_id": "seg_1",
"pax_ref": 1,
"name": "Veg Meal"
}
],
"remarks": ""
}
Validation: ssr is required
(at least one item). Each item needs type
(MEAL | BAGGAGE |
SEAT | OTHER),
code (the provider SSR code) and
pax_ref (1-based passenger reference
number). segment_id targets a specific
segment.
{
"success": true,
"message": "SSR added",
"data": { }
}
data is the provider's updated booking
(provider-specific). On failure the provider error is
returned verbatim.
Cancellation
Get the cancellation penalty for an existing flight booking before cancelling it.
Cancellation
POST /api/v1/flights/bookings/:ref/penalty Example:POST /api/v1/flights/bookings/FA-1775272567576/penaltyRequest:
{}
Success Response (200):
{
"success": true,
"message": "cancellation penalty",
"data": {
"booking_ref": "FA-1775272567576",
"pnr": "BX04HD0001",
"penalty": 350,
"refund_amount": 1812,
"currency": "INR"
}
}
Cancel Booking
POST /api/v1/flights/bookings/:ref/cancel Example:POST /api/v1/flights/bookings/FA-1775272567576/cancelRequest:
{}
Success Response (200):
{
"success": true,
"message": "booking cancelled"
}
Note: Always check
/penalty first to see the
cancellation fee before cancelling.
Issue Ticket
Issue a held (booked-but-not-ticketed) flight booking.
Issue Ticket
POST /api/v1/flights/bookings/:ref/issue-ticket Example:POST /api/v1/flights/bookings/FA-1775272567576/issue-ticketRequest:
{
"amount": 4540,
"public_fare": 2410,
"agent_fare": 2405,
"agent_commission": 5
}
Validation: amount is
required and must be > 0.
{
"success": true,
"message": "ticket issued",
"data": {
"ticket_numbers": ["BX04HD00011-1"],
"status": "issued"
}
}
Reschedule
Change the date/route of an existing booking: first check availability, then get the penalty quote (the new fare difference plus the provider's cancellation charge for the existing booking), and finally confirm the reschedule — which books the new itinerary and cancels (refunding to wallet) the original.
Reschedule Availability
Returns the flights available for the new date/route so you can pick a replacement before rescheduling.
POST /api/v1/flights/bookings/:ref/reschedule-avail Example:POST /api/v1/flights/bookings/FA-1775272567576/reschedule-availRequest:
{
"origin": "BOM",
"destination": "DEL",
"new_date": "2026-06-15",
"remarks": ""
}
Validation: origin and
destination are required (3-letter IATA codes).
new_date is required (format: YYYYMMDD
or YYYY-MM-DD).
{
"success": true,
"message": "reschedule availability",
"data": [
{
"itinerary_id": "itn_P9Q4N_fe0f65",
"source": "a3f9kx2b",
"validating_carrier": {
"code": "IX",
"name": "Air India Express",
"logo_url": "https://pics.avs.io/200/200/IX.png"
},
"pricing": {
"currency": "INR",
"total": 2642,
"base": 1001,
"taxes": 1641,
"fees": 0,
"is_refundable": true,
"provider_agent_fare": 2642
},
"slices": [
{
"slice_id": "seg_62a777",
"duration_minutes": 140,
"segments": [
{
"id": "seg_2cbfc8",
"flight_number": "IX1056",
"airline": "IX",
"operating_carrier": "IX",
"origin": { "code": "DEL", "name": "Indira Gandhi Airport", "city": "Delhi", "country": "IN", "terminal": "1" },
"destination": { "code": "BOM", "name": "Chhatrapati Shivaji Maharaj Intl", "city": "Mumbai", "country": "IN", "terminal": "2" },
"departure": "2026-10-01T17:50:00Z",
"arrival": "2026-10-01T20:10:00Z",
"duration_minutes": 140,
"seats_available": 4,
"cabin": "ECONOMY"
}
]
}
],
"fare_key": "tbo:..."
}
]
}
Reschedule Penalty Quote
Get the cost of rescheduling a booking: the new itinerary's fare difference plus the provider's cancellation charge for the existing booking.
POST /api/v1/flights/bookings/:ref/reschedule-penalty Example:POST /api/v1/flights/bookings/FA-1775272567576/reschedule-penaltyRequest:
{
"fare_key": "m7n4p8qr:UB3OIvUu8kiJPzhNgFuo29...",
"itinerary_id": "itn_P9Q4N_fe0f65"
}
Success Response (200):
{
"success": true,
"message": "reschedule penalty quote",
"data": {
"booking_ref": "FA-1775272567576",
"pnr": "BX04HD0001",
"original_agent_fare": 2400,
"original_public_fare": 2405,
"new_agent_fare": 2642,
"new_public_fare": 2642,
"fare_difference_agent": 242,
"fare_difference_public": 237,
"penalty": 500,
"currency": "INR",
"total_reschedule_charge": 737,
"note": ""
}
}
Confirm Reschedule
Books the new itinerary and then cancels (refunding to
wallet) the original booking. Use the
fare_key from the penalty quote together
with the passenger / contact details from the original
booking.
POST /api/v1/flights/bookings/FA-1775272567576/rescheduleRequest:
{
"fare_keys": ["m7n4p8qr:UB3OIvUu8kiJPzhNgFuo29..."],
"contact_email": "traveler@example.com",
"contact_phone": "9999999999",
"contact_country_code": "IN",
"passengers": [
{
"pax_index": 1,
"title": "Mr",
"first_name": "Test",
"last_name": "User",
"type": "ADT",
"gender": "Male"
}
],
"pnr": "",
"remarks": ""
}
Success Response (200):
{
"success": true,
"message": "reschedule confirmed",
"data": {
"new_booking": {
"booking_ref": "FA-1775279999",
"pnr": "NEWPNR001",
"status": "booked"
},
"cancellation": {
"booking_ref": "FA-1775272567576",
"status": "cancelled",
"refund_to_wallet": 1900
}
}
}
Flight Refunds
List Refunds
GET /api/v1/flights/refunds?page=1&per_page=20All refunds in your org (or, for agents, only your own). Supports the same page/per_page pagination.
{
"success": true,
"data": [
{
"booking_ref": "FA-1775272567576",
"pnr": "FVRVRV",
"booking_status": "CANCELLED",
"refund_status": "refunded",
"provider_refund_id": "PR-...",
"cancellation_charge": 500,
"provider_refund_amount": 1900,
"platform_charges": 0,
"refund_to_wallet": 1900,
"currency": "INR",
"agent_name": "John Smith",
"cancelled_at": "2026-04-12T10:00:00Z",
"refunded_at": "2026-04-12T12:00:00Z"
}
],
"meta": { "page": 1, "per_page": 20, "total": 1, "total_pages": 1 }
}
Refund Status
POST /api/v1/flights/bookings/:ref/refund-statusLive status of a refund for a booking reference. No request body required.
Success Response (200):
{
"success": true,
"message": "refund status",
"data": {
"booking_ref": "FA-1775272567576",
"status": "refunded",
"provider": "m7n4p8qr",
"cancellation_charge": 500,
"provider_refund_amount": 1900,
"platform_charges": 0,
"refund_to_wallet": 1900,
"currency": "INR",
"refund_id": "PR-...",
"credit_note_no": "CN-...",
"refunded_at": "2026-04-12T12:00:00Z",
"message": "refund completed"
}
}
Hotels
The Hotels API follows the standard booking lifecycle — SEARCH → PRICE → BOOK → RETRIEVE → CANCEL — through a single provider-agnostic interface. The platform currently connects to the RezLive (XMLHub) bed bank, with Travelport, Sabre and TBO hotel providers supported by the same unified layer.
Endpoint Summary
| Method | Endpoint | Description |
|---|---|---|
| POST | /api/v1/hotels/search |
Search available hotels for a stay. |
| POST | /api/v1/hotels/price |
Get detailed pricing for selected rooms. |
| POST | /api/v1/hotels/book |
Create a reservation. |
| GET | /api/v1/hotels/bookings |
List bookings (paginated). |
| GET | /api/v1/hotels/bookings/:ref |
Get a single booking's details. |
| POST | /api/v1/hotels/bookings/:ref/cancel |
Cancel a reservation. |
Authentication
All hotel endpoints require the same
Authorization: Bearer <access_token>
header and the standard role chain
(authenticated user, org admin or agent). Responses
always use the unified
success / data /
error shape.
hotel_id prefix returned by search. Every
provider returns an obfuscated, prefixed id — e.g.
HZL_109712 (RezLive), TBH_…
(TBO), SBH_… (Sabre),
TPH_… (Travelport). You never pick a
provider manually — just echo the exact
hotel_id values returned by search into the
price / details / book steps. A
hotel_id without its prefix (e.g.
109712) cannot be routed and will be
rejected by /hotels/details.
api_only and
full organizations — they are not gated
by the portal-access restriction described above.
Hotel Search
Search Hotels
POST /api/v1/hotels/searchSearches for available hotels across the configured providers. Multiple rooms and children can be searched in one call. Results are grouped per provider, and a per-provider status is always returned — a provider failure never produces an HTTP error.
Request (by hotel ids):
{
"currency": "INR",
"language": "en",
"check_in": "2026-08-05",
"check_out": "2026-08-08",
"rooms": [
{
"adults": 2,
"children": 1,
"children_ages": [8]
}
],
"location": {
"type": "hotel_id",
"hotel_ids": ["109712", "116828"]
},
"guest_nationality": "IN"
}
Request (by destination):
{
"check_in": "2026-08-05",
"check_out": "2026-08-08",
"rooms": [
{ "adults": 2, "children": 0, "children_ages": [] }
],
"location": {
"type": "city",
"code": "DXB",
"name": "Dubai",
"latitude": 25.2048,
"longitude": 55.2708,
"radius_km": 20
},
"filters": {
"star_rating": [4, 5],
"price_min": 2000,
"price_max": 15000,
"meal_plan": ["breakfast", "all_inclusive"],
"property_type": ["hotel", "resort"]
},
"sort": { "field": "price", "order": "asc" },
"pagination": { "page": 1, "per_page": 20 },
"currency": "INR",
"guest_nationality": "IN"
}
Request Fields
| Field | Description |
|---|---|
search_id |
Optional. Omit to auto-generate one; echo it
into the /price call.
|
check_in / check_out |
Stay dates as YYYY-MM-DD (required). |
rooms[] |
One entry per room: adults (1–9), children (0–9), optional children_ages[]. |
location.type |
hotel_id (with hotel_ids[]), city, airport, or coordinates. |
currency |
Defaults to INR. |
filters / sort / pagination |
Optional. Filters include star_rating, price_min/max, amenities, property_type, refundable_only, meal_plan, payment_type. |
{
"success": true,
"message": "hotels found",
"data": {
"search_id": "srch_hotel_20260803_a1b2c",
"status": "success",
"currency": "INR",
"total_results": 2,
"page": 1,
"per_page": 20,
"duration_ms": 842,
"provider_status": {
"HZL": {
"status": "success",
"results_count": 2,
"duration_ms": 842
}
},
"hotels": [
{
"hotel_id": "HZL109712",
"provider": "HZL",
"provider_hotel_id": "109712",
"name": "Dubai Marine Beach Resort & Spa",
"star_rating": 4,
"property_type": "resort",
"address": {
"line1": "Jumeirah Beach Road",
"city": "Dubai",
"country": "AE"
},
"images": [
{ "url": "https://.../photo.jpg", "type": "main" }
],
"rooms": [
{
"room_id": "BK-8842945",
"provider_room_id": "BK-8842945",
"name": "Deluxe Sea View Room",
"bed_type": "king",
"max_occupancy": 3,
"availability": { "status": "available", "rooms_left": 5 },
"pricing": {
"rate_id": "BK-8842945",
"rate_name": "Deluxe Sea View Room",
"currency": "INR",
"total_after_tax": 5718,
"meal_plan": "breakfast",
"refundable": true,
"pay_at_hotel_fees": 500,
"pay_at_hotel_fees_currency": "INR"
}
}
]
}
]
}
}
Response Fields
| Field | Description |
|---|---|
search_id |
Session id — send it with /price. |
hotel_id |
Prefixed with the provider token, e.g. HZL109712. Use as-is in later calls. |
rooms[].room_id / rooms[].pricing.rate_id |
The provider booking key needed for /price and /book. |
provider_status |
Per-provider outcome: success, error, or skipped (disabled for this org). |
rooms[].pricing.pay_at_hotel_fees is
greater than 0, the frontend must display
pay_at_hotel_fees and
pay_at_hotel_fees_currency prominently on the
room card. These are charges the customer settles directly at the
hotel desk and are NOT included in
total_after_tax. Failing to surface them may result in
unexpected on-property charges for the traveller.
City Lookup
GET /api/v1/hotels/cities?q=dubai&limit=15Autocomplete over the provider destination-city list for the hotel search box.
Success Response (200):
{
"success": true,
"message": "cities",
"data": [
{ "code": "DXB", "name": "Dubai", "country_code": "AE" },
{ "code": "DXBA", "name": "Dubai Al Maktoum Intl", "country_code": "AE" }
]
}
Hotel Details
Fetch descriptive details (description, address, amenities, images, room amenities) for one
or more hotels in a single call. Pass a list of hotel_ids to retrieve them all at once.
hotel_ids returned by search to get full
details on exactly those properties.
hotel_id exactly as
returned by /hotels/search (it is already prefixed with the
provider token, e.g. HZL109712). Sending an ID from a
different provider will not resolve.
Hotel Details
POST /api/v1/hotels/details Request:
{
"hotel_ids": ["109712", "116828"]
}
Success Response (200):
{
"success": true,
"message": "hotel details retrieved",
"data": [
{
"provider": "HZL",
"hotels": [
{
"hotel_id": "HZL109712",
"provider_hotel_id": "109712",
"name": "Dubai Marine Beach Resort & Spa",
"star_rating": 5,
"property_type": "Hotel",
"description": "Beachfront resort...",
"address": { "line1": "...", "city": "Dubai", "country": "AE" },
"contact": { "phone": "...", "email": "..." },
"images": [],
"amenities": [],
"room_amenities": [],
"has_free_breakfast": true
}
]
}
]
}
Hotel Price
POST /api/v1/hotels/price
Locks in detailed pricing for the selected rooms of one
hotel (RezLive: pre-book step). Returns a
price_id that must be echoed into the book
call.
{
"search_id": "srch_hotel_20260803_a1b2c",
"hotel_id": "HZL109712",
"room_selections": [
{
"room_id": "BK-8842945",
"rate_id": "BK-8842945",
"quantity": 1
}
]
}
Success Response (200):
{
"success": true,
"message": "pricing retrieved",
"data": {
"price_id": "HZL_price_HZL109712",
"hotel_id": "HZL109712",
"status": "success",
"expires_at": "2026-08-03T06:25:00Z",
"currency": "INR",
"pricing_breakdown": {
"room_charges": { "nights": 3, "rate_per_night": 5718, "subtotal": 17154 },
"taxes": { "total_taxes": 0 },
"fees": { "service_charge": 0, "resort_fee": 0, "total_fees": 0 },
"discounts": { "loyalty_discount": 0, "total_discounts": 0 },
"total_before_discount": 17154,
"total_discount": 0,
"total_after_discount": 17154,
"grand_total": 17154
}
}
}
The grand_total is the supplier amount.
Your final charge may include platform fees — use
the fare block in
/book to record the payable amount.
Book Hotel
POST /api/v1/hotels/book
Creates a reservation. The wallet is debited for the
fare.agent_fare after the booking is
persisted. An insufficient balance returns
402 Payment Required.
{
"price_id": "HZL_price_HZL109712",
"hotel_id": "HZL109712",
"check_in": "2026-08-05",
"check_out": "2026-08-08",
"rooms": [
{
"room_id": "ROOM-1",
"rate_id": "BK-8842945",
"guests": [
{
"type": "adult",
"title": "Mr",
"first_name": "John",
"last_name": "Doe",
"nationality": "IN"
},
{
"type": "child",
"title": "Master",
"first_name": "Jay",
"last_name": "Doe"
}
]
}
],
"contact": {
"first_name": "John",
"last_name": "Doe",
"email": "john@example.com",
"phone": "+911234567890"
},
"fare": {
"public_fare": 17154,
"agent_fare": 17154,
"agent_commission": 0,
"currency": "INR"
}
}
Request Fields
| Field | Description |
|---|---|
price_id |
From the /price response — resumes the pricing session. |
hotel_id |
The prefixed id from search, e.g. HZL109712. |
rooms[] |
Each selected room with its room_id, rate_id (booking key) and guest list. |
contact |
Booking contact (email/phone used for the reservation). |
fare |
Optional block echoed from pricing: public_fare, agent_fare (amount the wallet is checked and debited for), agent_commission, currency.
|
{
"success": true,
"message": "hotel booking created",
"data": {
"booking_id": "BK-HTL-2026-a1b2c3d4",
"status": "confirmed",
"confirmation_number": "RZL8824",
"provider_confirmation": "88241230",
"created_at": "2026-08-03T06:00:00Z",
"hotel": { "name": "Dubai Marine Beach Resort & Spa" },
"reservation": {
"check_in": "2026-08-05",
"check_out": "2026-08-08",
"nights": 3,
"rooms": [ { "room_type": "Deluxe Sea View Room", "guests": [] } ]
},
"pricing": {
"currency": "INR",
"room_charges": 17154,
"taxes": 0,
"fees": 0,
"discounts": 0,
"total_paid": 17154,
"payment_status": "pending"
}
}
}
GET /hotels/bookings/:ref.
List Hotel Bookings
GET /api/v1/hotels/bookings
Query Parameters: page,
per_page. Org admins see the whole
organization; agents see only their own bookings.
{
"success": true,
"data": [
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"booking_ref": "HTL-1785319200000",
"provider": "HZL",
"provider_booking_id": "88241230",
"provider_confirmation": "RZL8824",
"hotel_id": "HZL109712",
"hotel_name": "Dubai Marine Beach Resort & Spa",
"check_in": "2026-08-05",
"check_out": "2026-08-08",
"nights": 3,
"room_count": 1,
"currency": "INR",
"total_amount": 17154,
"net_amount": 17154,
"public_fare": 17154,
"status": "confirmed",
"payment_status": "pending",
"booked_at": "2026-08-03T06:00:00Z",
"contact_email": "john@example.com",
"contact_phone": "+911234567890",
"created_at": "2026-08-03T06:00:00Z",
"guests": [
{
"id": "550e8400-e29b-41d4-a716-446655440001",
"title": "Mr",
"first_name": "John",
"last_name": "Doe",
"type": "adult",
"nationality": "IN"
}
]
}
],
"meta": {
"page": 1,
"per_page": 20,
"total": 1,
"total_pages": 1
}
}
Get Hotel Booking Details
GET /api/v1/hotels/bookings/:ref
Fetches a single booking by its
booking_ref (e.g.
HTL-1785319200000). If the stored status is
pending, the platform refreshes it from the
provider before responding.
{
"success": true,
"message": "hotel booking retrieved",
"data": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"booking_ref": "HTL-1785319200000",
"provider": "HZL",
"provider_booking_id": "88241230",
"provider_confirmation": "RZL8824",
"hotel_id": "HZL109712",
"hotel_name": "Dubai Marine Beach Resort & Spa",
"check_in": "2026-08-05",
"check_out": "2026-08-08",
"nights": 3,
"room_count": 1,
"currency": "INR",
"total_amount": 17154,
"net_amount": 17154,
"public_fare": 17154,
"status": "confirmed",
"payment_status": "pending",
"booked_at": "2026-08-03T06:00:00Z",
"contact_email": "john@example.com",
"contact_phone": "+911234567890",
"guests": [
{
"id": "550e8400-e29b-41d4-a716-446655440001",
"title": "Mr",
"first_name": "John",
"last_name": "Doe",
"type": "adult",
"nationality": "IN"
}
]
}
}
Get Voucher
GET /api/v1/hotels/bookings/:ref/voucherRetrieves the provider voucher for a confirmed hotel booking.
Success Response (200):
{
"success": true,
"message": "hotel voucher retrieved",
"data": {
"confirmation_number": "RZL8824",
"status": "Confirmed",
"hotel_name": "Dubai Marine Beach Resort & Spa",
"hotel_address": "Jumeirah Beach Road, Dubai",
"check_in": "2026-08-05",
"check_out": "2026-08-08",
"currency": "INR",
"total_price": "17154",
"provider": "HZL"
}
}
Cancel Hotel Booking
POST /api/v1/hotels/bookings/:ref/cancelCancels a reservation at the provider and updates the stored booking. Already-cancelled or refunded bookings cannot be cancelled again.
Request:
{
"reason": "change of plans",
"notify_guest": false
}
Success Response (200):
{
"success": true,
"message": "hotel booking cancelled",
"data": {
"booking_id": "88241230",
"status": "cancelled",
"cancelled_at": "2026-08-03T07:30:00Z",
"cancellation_fee": {
"amount": 0,
"currency": "INR",
"reason": ""
},
"refund": {
"amount": 17154,
"currency": "INR",
"method": "",
"estimated_processing_days": 0
},
"message": ""
}
}
Bookings
Booking management is shared across the
Flights and Hotels
surfaces. org_admin users see every booking
in the organization; agent users see only
their own. The detailed request/response schemas for each
endpoint are documented in the
Flights and
Hotels sections —
this section is a consolidated index of the booking
lifecycle APIs.
Flight Booking APIs
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/v1/flights/bookings |
List the org's flight bookings (paginated). |
| GET | /api/v1/flights/bookings/:ref |
Get a single flight booking's details. |
| GET | /api/v1/flights/bookings/:ref/retrieve |
Re-fetch live status from the supplier. |
| GET | /api/v1/flights/bookings/:ref/track |
Track booking status over time. |
| GET | /api/v1/flights/bookings/:ref/ssr |
Get SSR (special service request) options. |
| POST | /api/v1/flights/bookings/:ref/ssr |
Add SSR (ancillaries) to an existing booking. |
| POST | /api/v1/flights/bookings/:ref/penalty |
Calculate cancellation penalty. |
| POST | /api/v1/flights/bookings/:ref/cancel |
Cancel a booking (refunds to wallet). |
| POST | /api/v1/flights/bookings/:ref/issue-ticket |
Issue the e-ticket. |
| POST | /api/v1/flights/bookings/:ref/reschedule-avail |
Check reschedule availability. |
| POST | /api/v1/flights/bookings/:ref/reschedule-penalty |
Get the reschedule penalty quote. |
| POST | /api/v1/flights/bookings/:ref/reschedule |
Confirm the reschedule (books new, cancels old). |
Hotel Booking APIs
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/v1/hotels/bookings |
List the org's hotel bookings (paginated). |
| GET | /api/v1/hotels/bookings/:ref |
Get a single hotel booking's details (refreshes pending status from supplier). |
| GET | /api/v1/hotels/bookings/:ref/voucher |
Download the booking voucher. |
| POST | /api/v1/hotels/bookings/:ref/cancel |
Cancel a hotel booking. |
Notifications
Stay in the loop with booking, wallet, and system events. List them, count what's unread, and mark them read — one at a time or all at once.
List Notifications
GET /api/v1/notifications
Query Parameters: page,
per_page
{
"success": true,
"data": [],
"meta": {
"page": 1,
"per_page": 20,
"total": 0,
"total_pages": 0
}
}
Get Unread Count
GET /api/v1/notifications/unread-count Success Response (200):
{
"success": true,
"message": "unread count",
"data": {
"unread": 0
}
}
Mark Notification as Read
PUT /api/v1/notifications/:id/read Success Response (200):
{
"success": true,
"message": "notification marked as read"
}
Mark All as Read
PUT /api/v1/notifications/read-all Success Response (200):
{
"success": true,
"message": "all notifications marked as read"
}
Common Error Responses
Every error — whether auth, validation, or server
— returns the same predictable
success / error shape, so your
client can handle failures in one place.
401 Unauthorized
{
"success": false,
"error": "invalid credentials"
}
403 Forbidden
{
"success": false,
"error": "access denied"
}
404 Not Found
{
"success": false,
"error": "resource not found"
}
422 Validation Error
{
"success": false,
"error": "code=422, message=[{field this field is required}]"
}
402 Payment Required (Insufficient Balance)
{
"success": false,
"error": "insufficient wallet balance to proceed — available: 0.00, required: 2372.00 (agent fare)"
}
429 Rate Limited
{
"success": false,
"error": "too many requests"
}
500 Internal Server Error
{
"success": false,
"error": "internal server error, please try again later"
}
Rare, and not tied to anything in your request. Safe to retry with backoff; if it persists on a specific endpoint, contact GAMAN support with the approximate request time.