এই ভলিউমে · ভলিউম 07
ইন্টিগ্রেশন
GDS (Amadeus, Sabre) NDC পাবলিক API ওয়েবহুক
বাংলা সারসংক্ষেপ

REST API—পার্টনার এবং থার্ড-পার্টি ডেভেলপারদের জন্য। UI নিজেই API-এর প্রথম গ্রাহক। প্রমাণীকরণ: Personal Access Tokens (tvb_live_*/tvb_test_*)। ভার্সনিং: URL prefix (/v1/)। রেট লিমিট: প্রতি পার্টনার বাকেট। Idempotency-Key হেডার।

Chapter 7.5 — Public API

1. Purpose

travoBooks exposes a REST API that lets partners and approved third-party developers programmatically search offers, create bookings, manage customers/suppliers, retrieve financial data, and ingest webhooks. The same API powers the platform's own UI — the UI is the first consumer of the API. This chapter defines the API's structure, authentication, versioning, rate limiting, error contract, and operational guarantees.

2. Why it matters

The API is the platform's product surface. For developer-segment customers (one of travoBooks' four target segments per Chapter 0.1), it is the product. API design quality drives adoption directly: - Resource modelling clarity = onboarding speed. - Error contract consistency = production reliability. - Versioning discipline = long-term trust.

3. Design principles

  • REST over HTTPS — verbs (GET, POST, PATCH, DELETE); resource-oriented URLs.
  • JSON-only for request/response bodies in Phase 1 (XML support deferred).
  • UTF-8 everywhere.
  • ISO-8601 for dates and datetimes (always with timezone; never naïve).
  • ISO-4217 for currency codes (3-letter).
  • Decimal as string for monetary amounts to preserve precision ("amount": "1234.56").
  • snake_case for JSON keys (matches DB conventions).
  • Idempotency-Key header supported on all non-idempotent endpoints.
  • Cursor pagination for lists (no offset pagination).
  • API-first — the UI uses the same API; no internal-only endpoints in Phase 1.

4. Authentication

Three authentication modes:

4.1 Personal Access Tokens (PATs)

Format: tgc_<env>_<random> where <env> is live or test.

Examples: - tvb_live_K3p9... - tvb_test_8sQv...

Stored hashed (Argon2id) in personal_access_tokens (Chapter 2.2). Sent as bearer token:

Authorization: Bearer tvb_live_K3p9...

Scoped to a single partner; tied to a user; carries the user's permissions.

4.2 OAuth 2.0 (Phase 2)

For third-party apps acting on behalf of partner users. Authorization-code flow with PKCE.

4.3 Session cookies

For the platform's own UI only — __Host-tvb_session cookie. Not used by external clients.

5. Versioning

URL-prefix versioning: /v1/..., /v2/....

  • Within a major version, only backward-compatible changes are introduced (new optional fields, new endpoints).
  • Breaking changes go in a new major version.
  • Each major version is supported for at least 24 months after the next major launches.
  • Deprecation announced ≥ 12 months ahead; Sunset header included on responses for deprecated endpoints.

6. Resource taxonomy

Top-level resources (per partner scope):

Resource URL
Customers /v1/customers
Suppliers /v1/suppliers
Offers /v1/offers
Bookings /v1/bookings
Tickets /v1/tickets
Invoices /v1/invoices
Payments /v1/payments
Refunds /v1/refunds
Memos (ADM/ACM) /v1/memos
Commission accruals /v1/commission/accruals
Journal entries /v1/ledger/journal-entries
Reports /v1/reports/{report-name}
Webhooks /v1/webhooks
Users /v1/users

Each resource supports standard verbs where semantically meaningful.

7. Request / response shape

Request example — Create booking

POST /v1/bookings HTTP/1.1
Authorization: Bearer tvb_live_...
Idempotency-Key: 8c1d4a02-...
Content-Type: application/json

{
  "customer_id": 4521,
  "offer_id": "offer_TG_2026_xyz",
  "passengers": [
    {"first_name": "Ahmed", "last_name": "Khan", "passport_number": "...", "date_of_birth": "1992-04-12"}
  ],
  "remarks": "Window seat preferred"
}

Response shape — Standard envelope

{
  "data": {
    "booking_id": 1009287,
    "booking_ref": "TVB-2026-000123",
    "state": "HELD",
    "pnr": "ABC123",
    "hold_expires_at": "2026-05-26T19:30:00+06:00",
    "amount": "65400.00",
    "currency": "BDT",
    "created_at": "2026-05-26T18:45:00+06:00"
  },
  "meta": {
    "request_id": "req_4f2a..."
  }
}

List response with pagination

{
  "data": [ {...}, {...}, ... ],
  "meta": {
    "request_id": "req_...",
    "pagination": {
      "next_cursor": "Y3Vyc29yOjQ1Njc=",
      "has_more": true
    }
  }
}

Pagination request: ?cursor=Y3Vyc29yOjQ1Njc=&limit=50.

8. Error contract

Standard error envelope:

{
  "error": {
    "code": "BOOKING_HOLD_EXPIRED",
    "message": "The supplier hold has expired. Please re-search.",
    "request_id": "req_4f2a...",
    "field_errors": [
      {"field": "passengers[0].passport_number", "code": "FIELD_REQUIRED", "message": "Passport required for international itinerary"}
    ],
    "retry_advice": "non_retryable"
  }
}

retry_advice values: non_retryable, retryable_after_short, retryable_after_long, requires_user_action.

HTTP Meaning
200 Success
201 Created
202 Accepted (async)
400 Validation error
401 Auth invalid
403 Permission denied
404 Not found
409 Conflict (idempotency conflict, state conflict)
422 Business rule violation
429 Rate limited
500 Server error
503 Supplier unavailable

Full error code catalog: Chapter 14.2.

9. Rate limiting

Per-PAT and per-partner:

Bucket Limit
Search offers 600/min per partner
Booking creation 60/min per partner
Ticket issuance 30/min per partner
Read-only endpoints 1200/min per partner
Report generation 10/min per partner (heavy operation)

Exceeded → 429 Too Many Requests with Retry-After header.

Rate-limit headers on every response: - X-RateLimit-Limit: 600 - X-RateLimit-Remaining: 587 - X-RateLimit-Reset: 1716729600

10. Idempotency

Endpoints that create or modify state accept Idempotency-Key header (UUID format recommended). Server caches the response keyed by (partner_id, endpoint, idempotency_key) for 24 hours.

Replay with same key + same body → cached response. Replay with same key + different body → 409 IDEMPOTENCY_KEY_CONFLICT.

11. Test mode

Each PAT is either live or test. Test PATs hit a parallel sandbox: - Mocked supplier responses (configurable per partner). - Test data isolated from production. - Full feature parity for booking creation, ticket issuance, refund. - BSP / bank / gateway integrations stubbed.

12. Webhook subscriptions

Partners register webhook endpoints via:

POST /v1/webhooks
{
  "url": "https://partner.example/travobooks-events",
  "event_types": ["booking.issued", "refund.completed"],
  "secret": "whsec_..."
}

travoBooks posts events with HMAC-SHA256 signature in travoBooks-Signature header. Detailed in Chapter 7.6.

13. Observability for API clients

Every response includes: - X-Request-ID — for support correlation. - X-travoBooks-Trace — internal trace (debug mode). - Response time, partner ID, user ID logged on travoBooks side.

Partners can retrieve their last 24h of API requests via /v1/diagnostics/requests (rate-limited; for self-debugging).

14. SDKs

Phase 1: official PHP SDK; community-maintained JS/TS bindings. Phase 2: official Node, Python, Go SDKs.

SDKs encapsulate auth, retries, idempotency-key generation, and typed response models.

15. Backward-compatibility commitments

Within v1, travoBooks commits: - Existing fields will not be removed. - Field types will not change. - Enum values will not be removed (new values may be added; clients should ignore unknown values). - Endpoint URLs will not move. - HTTP status semantics will not change.

Additions (new fields, endpoints, enum values, optional headers) may happen at any time and are not breaking. Clients must be tolerant of unknown fields.

16. Common pitfalls

  • ⚠️ Treating 5xx as retryable always. Some 5xx are non-retryable (e.g., supplier responded with a permanent fail).
  • ⚠️ Hard-coding enum values. Always handle the unknown case.
  • ⚠️ Storing PATs in client-side code. Never. Server-to-server only.
  • ⚠️ Skipping idempotency keys on retries. Causes double-bookings.
  • 🔒 Logging full request bodies including PII / auth headers. Strip before logging.
  • ⚠️ Polling for changes instead of using webhooks. Webhooks are authoritative; polling burns rate-limit.