{
  "info": {
    "name": "TransferTourism Enterprise API v1",
    "description": "Production and sandbox collection for the Enterprise API document. The pre-request script creates X-API-KEY, X-TIMESTAMP, X-NONCE and X-SIGNATURE.",
    "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
  },
  "variable": [
    {"key": "baseUrl", "value": "https://api.transfertourism.com/v1"},
    {"key": "sandboxBaseUrl", "value": "https://sandbox-api.transfertourism.com/v1"},
    {"key": "apiKey", "value": ""},
    {"key": "apiSecret", "value": ""},
    {"key": "sandboxApiKey", "value": ""},
    {"key": "sandboxApiSecret", "value": ""},
    {"key": "quoteId", "value": ""},
    {"key": "bookingId", "value": ""},
    {"key": "updatedAfter", "value": "2026-08-26T00:00:00Z"}
  ],
  "event": [{
    "listen": "prerequest",
    "script": {"type": "text/javascript", "exec": [
      "const timestamp = Math.floor(Date.now() / 1000).toString();",
      "const nonce = pm.variables.replaceIn('{{$guid}}');",
      "const path = pm.request.url.getPathWithQuery();",
      "const body = pm.request.body && pm.request.body.mode === 'raw' ? pm.variables.replaceIn(pm.request.body.raw || '') : '';",
      "const bodyHash = CryptoJS.SHA256(body).toString(CryptoJS.enc.Hex);",
      "const sandbox = pm.request.url.toString().includes('sandbox-api') || pm.request.url.toString().includes('/sandbox/');",
      "const apiKey = pm.variables.get(sandbox ? 'sandboxApiKey' : 'apiKey');",
      "const apiSecret = pm.variables.get(sandbox ? 'sandboxApiSecret' : 'apiSecret');",
      "const canonical = `${timestamp}.${nonce}.${pm.request.method}.${path}.${bodyHash}`;",
      "pm.request.headers.upsert({key:'X-API-KEY', value:apiKey});",
      "pm.request.headers.upsert({key:'X-TIMESTAMP', value:timestamp});",
      "pm.request.headers.upsert({key:'X-NONCE', value:nonce});",
      "pm.request.headers.upsert({key:'X-API-BODY-SHA256', value:bodyHash});",
      "pm.request.headers.upsert({key:'X-SIGNATURE', value:CryptoJS.HmacSHA256(canonical, apiSecret).toString(CryptoJS.enc.Hex)});"
    ]}
  }],
  "item": [
    {
      "name": "Production",
      "description": "Use only with production credentials and real partner-owned payment bookings.",
      "item": [
        {"name": "Places", "request": {"method": "GET", "url": {"raw": "{{baseUrl}}/places?query=Antalya&country_code=TR&limit=10", "host": ["{{baseUrl}}"], "path": ["places"], "query": [{"key": "query", "value": "Antalya"}, {"key": "country_code", "value": "TR"}, {"key": "limit", "value": "10"}]}}},
        {"name": "Quote", "request": {"method": "POST", "header": [{"key": "Content-Type", "value": "application/json"}], "body": {"mode": "raw", "raw": "{\n  \"from\": {\"type\": \"AIRPORT\", \"name\": \"Antalya Airport\", \"lat\": 36.8987, \"lng\": 30.8005, \"country_code\": \"TR\"},\n  \"to\": {\"type\": \"HOTEL\", \"name\": \"Example Hotel\", \"lat\": 36.85, \"lng\": 30.78, \"country_code\": \"TR\"},\n  \"pickup_datetime\": \"2026-09-10T12:00:00+03:00\",\n  \"pax\": {\"adults\": 2, \"children\": 0, \"infants\": 0},\n  \"luggage\": 2,\n  \"flight\": {\"code\": \"TK2439\", \"date\": \"2026-09-10\"}\n}"}, "url": {"raw": "{{baseUrl}}/quotes", "host": ["{{baseUrl}}"], "path": ["quotes"]}}, "event": [{"listen": "test", "script": {"type": "text/javascript", "exec": ["if (pm.response.code === 200) pm.collectionVariables.set('quoteId', pm.response.json().quote_id);"]}}]},
        {"name": "Create booking", "request": {"method": "POST", "header": [{"key": "Content-Type", "value": "application/json"}, {"key": "Idempotency-Key", "value": "postman-production-{{$guid}}"}], "body": {"mode": "raw", "raw": "{\n  \"quote_id\": \"{{quoteId}}\",\n  \"partner_reference\": \"POSTMAN-PROD-{{$guid}}\",\n  \"passenger\": {\"first_name\": \"Production\", \"last_name\": \"Passenger\", \"email\": \"production@example.test\", \"phone\": \"5550000000\"}\n}"}, "url": {"raw": "{{baseUrl}}/bookings", "host": ["{{baseUrl}}"], "path": ["bookings"]}}, "event": [{"listen": "test", "script": {"type": "text/javascript", "exec": ["if (pm.response.code === 201 || pm.response.code === 200) pm.collectionVariables.set('bookingId', pm.response.json().booking.booking_id);"]}}]},
        {"name": "Get booking", "request": {"method": "GET", "url": {"raw": "{{baseUrl}}/bookings/{{bookingId}}", "host": ["{{baseUrl}}"], "path": ["bookings", "{{bookingId}}"]}}},
        {"name": "List bookings", "request": {"method": "GET", "url": {"raw": "{{baseUrl}}/bookings?limit=100", "host": ["{{baseUrl}}"], "path": ["bookings"], "query": [{"key": "limit", "value": "100"}]}}},
        {"name": "Update booking", "request": {"method": "POST", "header": [{"key": "Content-Type", "value": "application/json"}], "body": {"mode": "raw", "raw": "{\n  \"flight\": {\"code\": \"TK123\", \"date\": \"2026-09-10\"},\n  \"pickup_time\": \"13:30\",\n  \"note\": \"Updated by partner\"\n}"}, "url": {"raw": "{{baseUrl}}/bookings/{{bookingId}}/update", "host": ["{{baseUrl}}"], "path": ["bookings", "{{bookingId}}", "update"]}}},
        {"name": "Cancel booking", "request": {"method": "POST", "url": {"raw": "{{baseUrl}}/bookings/{{bookingId}}/cancel", "host": ["{{baseUrl}}"], "path": ["bookings", "{{bookingId}}", "cancel"]}}},
        {"name": "Delta polling", "request": {"method": "GET", "url": {"raw": "{{baseUrl}}/bookings/updates?updated_after={{updatedAfter}}&limit=100", "host": ["{{baseUrl}}"], "path": ["bookings", "updates"], "query": [{"key": "updated_after", "value": "{{updatedAfter}}"}, {"key": "limit", "value": "100"}]}}}
      ]
    },
    {
      "name": "Sandbox",
      "description": "Deterministic non-operational scenarios. Sandbox bookings are excluded from dispatch and billing.",
      "item": [
        {"name": "Places", "request": {"method": "GET", "url": {"raw": "{{sandboxBaseUrl}}/places?query=Antalya&country_code=TR&limit=10", "host": ["{{sandboxBaseUrl}}"], "path": ["places"], "query": [{"key": "query", "value": "Antalya"}, {"key": "country_code", "value": "TR"}, {"key": "limit", "value": "10"}]}}},
        {"name": "Quote", "request": {"method": "POST", "header": [{"key": "Content-Type", "value": "application/json"}], "body": {"mode": "raw", "raw": "{\n  \"from\": {\"type\": \"AIRPORT\", \"name\": \"Antalya Airport\", \"lat\": 36.8987, \"lng\": 30.8005, \"country_code\": \"TR\"},\n  \"to\": {\"type\": \"HOTEL\", \"name\": \"Example Hotel\", \"lat\": 36.85, \"lng\": 30.78, \"country_code\": \"TR\"},\n  \"pickup_datetime\": \"2026-09-10T12:00:00+03:00\",\n  \"pax\": {\"adults\": 2, \"children\": 0, \"infants\": 0},\n  \"luggage\": 2,\n  \"flight\": {\"code\": \"TK2439\", \"date\": \"2026-09-10\"}\n}"}, "url": {"raw": "{{sandboxBaseUrl}}/quotes", "host": ["{{sandboxBaseUrl}}"], "path": ["quotes"]}}, "event": [{"listen": "test", "script": {"type": "text/javascript", "exec": ["if (pm.response.code === 200) pm.collectionVariables.set('quoteId', pm.response.json().quote_id);"]}}]},
        {"name": "Create booking", "request": {"method": "POST", "header": [{"key": "Content-Type", "value": "application/json"}, {"key": "Idempotency-Key", "value": "postman-sandbox-{{$guid}}"}], "body": {"mode": "raw", "raw": "{\n  \"quote_id\": \"{{quoteId}}\",\n  \"partner_reference\": \"POSTMAN-SANDBOX-{{$guid}}\",\n  \"passenger\": {\"first_name\": \"Sandbox\", \"last_name\": \"Passenger\", \"email\": \"sandbox@example.test\", \"phone\": \"5550000000\"}\n}"}, "url": {"raw": "{{sandboxBaseUrl}}/bookings", "host": ["{{sandboxBaseUrl}}"], "path": ["bookings"]}}, "event": [{"listen": "test", "script": {"type": "text/javascript", "exec": ["if (pm.response.code === 201 || pm.response.code === 200) pm.collectionVariables.set('bookingId', pm.response.json().booking.booking_id);"]}}]},
        {"name": "Get booking", "request": {"method": "GET", "url": {"raw": "{{sandboxBaseUrl}}/bookings/{{bookingId}}", "host": ["{{sandboxBaseUrl}}"], "path": ["bookings", "{{bookingId}}"]}}},
        {"name": "List bookings", "request": {"method": "GET", "url": {"raw": "{{sandboxBaseUrl}}/bookings?limit=100", "host": ["{{sandboxBaseUrl}}"], "path": ["bookings"], "query": [{"key": "limit", "value": "100"}]}}},
        {"name": "Update booking", "request": {"method": "POST", "header": [{"key": "Content-Type", "value": "application/json"}], "body": {"mode": "raw", "raw": "{\n  \"flight\": {\"code\": \"TK123\", \"date\": \"2026-09-10\"},\n  \"pickup_time\": \"13:30\",\n  \"note\": \"Updated by partner\"\n}"}, "url": {"raw": "{{sandboxBaseUrl}}/bookings/{{bookingId}}/update", "host": ["{{sandboxBaseUrl}}"], "path": ["bookings", "{{bookingId}}", "update"]}}},
        {"name": "Cancel booking", "request": {"method": "POST", "url": {"raw": "{{sandboxBaseUrl}}/bookings/{{bookingId}}/cancel", "host": ["{{sandboxBaseUrl}}"], "path": ["bookings", "{{bookingId}}", "cancel"]}}},
        {"name": "Delta polling", "request": {"method": "GET", "url": {"raw": "{{sandboxBaseUrl}}/bookings/updates?updated_after={{updatedAfter}}&limit=100", "host": ["{{sandboxBaseUrl}}"], "path": ["bookings", "updates"], "query": [{"key": "updated_after", "value": "{{updatedAfter}}"}, {"key": "limit", "value": "100"}]}}}
      ]
    }
  ]
}
