{
  "info": {
    "_postman_id": "0f2a6c51-9c37-4a1d-9c6b-3d1f5a77e201",
    "name": "Booking Window - ACT Booking Flow (reserve -> confirm -> release)",
    "description": "Own inventory (source ACT) booking flow on /outApi/*.\n\nGlobalTix (source GT) has its own collection: Activity_GT_Booking_API.postman_collection.json.\n\nAUTH: every request sends header  x-api-key: {{api_key}}  (your Agent API Key).\nSet it once in the collection variables.\n\nFLOW\n  1. activity_list / get_activity_by_id  -- find the activity, its time slots and prices\n  2. reserve_booking                     -- holds the units (hold_minutes in the response),\n                                            checks the wallet WITHOUT charging, re-quotes the price\n  3. create_booking (with booking_ref_no) -- charges the wallet and confirms the hold\n     release_booking                     -- or give the hold back; nothing was charged\n  4. booking_details / cancellation_charges / cancel_booking\n\nA hold nobody confirms is released automatically when it expires.\ncreate_booking WITHOUT booking_ref_no still works as the old one-step booking.\n\nEvery response carries an X-Request-Id header. Quote it when contacting support.",
    "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
  },
  "auth": {
    "type": "apikey",
    "apikey": [
      {
        "key": "key",
        "value": "x-api-key",
        "type": "string"
      },
      {
        "key": "value",
        "value": "{{api_key}}",
        "type": "string"
      },
      {
        "key": "in",
        "value": "header",
        "type": "string"
      }
    ]
  },
  "variable": [
    {
      "key": "baseUrl",
      "value": "http://localhost:5558",
      "type": "string"
    },
    {
      "key": "api_key",
      "value": "AGT_XXXXXXXXXXXXXXXX",
      "type": "string"
    },
    {
      "key": "activity_id",
      "value": "4",
      "type": "string"
    },
    {
      "key": "travel_date",
      "value": "2026-09-18",
      "type": "string"
    },
    {
      "key": "booking_ref_no",
      "value": "",
      "type": "string"
    },
    {
      "key": "booking_id",
      "value": "",
      "type": "string"
    },
    {
      "key": "held_total_price",
      "value": "",
      "type": "string"
    }
  ],
  "item": [
    {
      "name": "1. Find the activity",
      "item": [
        {
          "name": "Activity List",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"country\": \"Thailand\",\n  \"city\": \"Bangkok\",\n  \"travel_date\": \"{{travel_date}}\",\n  \"guest_currency\": \"INR\",\n  \"keyword\": \"Safari world\",\n  \"page\": 1,\n  \"limit\": 20\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "url": {
              "raw": "{{baseUrl}}/outApi/activity_list",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "outApi",
                "activity_list"
              ]
            },
            "description": "Trimmed list item. time_slots carries only the travel date's slots, each with category_id."
          },
          "response": []
        },
        {
          "name": "Get Activity By Id (ACT)",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"activity_id\": \"{{activity_id}}\",\n  \"source\": \"ACT\",\n  \"travel_date\": \"{{travel_date}}\",\n  \"guest_currency\": \"INR\",\n  \"country\": \"Thailand\",\n  \"city\": \"Bangkok\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "url": {
              "raw": "{{baseUrl}}/outApi/get_activity_by_id",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "outApi",
                "get_activity_by_id"
              ]
            },
            "description": "Full detail for the activity. country/city also FILTER an ACT lookup: send the activity's own values or leave them out."
          },
          "response": []
        }
      ]
    },
    {
      "name": "2. Reserve -> confirm -> release",
      "item": [
        {
          "name": "Reserve Booking",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"reference_type\": 1,\n  \"reference_id\": 4,\n  \"source\": \"ACT\",\n  \"travel_date\": \"2026-09-18\",\n  \"time_from\": \"08:30:00\",\n  \"time_to\": \"13:00:00\",\n  \"title\": \"Safari world with Marine Park + Lunch Included\",\n  \"city\": \"Bangkok\",\n  \"country\": \"Thailand\",\n  \"currency\": \"INR\",\n  \"cancellation_policy_id\": 59,\n  \"no_of_travellers\": {\n    \"adult\": 1,\n    \"child\": 0,\n    \"infant\": 0,\n    \"travellers\": 1\n  },\n  \"total_price\": 550,\n  \"guest_info\": {\n    \"first_name\": \"Harish\",\n    \"last_name\": \"K\",\n    \"email\": \"harish@example.com\",\n    \"contact_no\": \"+919999999999\"\n  },\n  \"reference_object\": {\n    \"id\": 4,\n    \"source\": \"ACT\",\n    \"activity_date\": \"2026-09-18\",\n    \"inventory_source\": \"base\",\n    \"time_slots\": [\n      {\n        \"id\": 133449,\n        \"from_time\": \"08:30:00\",\n        \"to_time\": \"13:00:00\",\n        \"slot_hour\": 0,\n        \"inventory_date\": \"2026-09-18\",\n        \"week_days\": null,\n        \"adult_price\": 550,\n        \"child_price\": 550,\n        \"infant_price\": 0,\n        \"mrp_adult\": 660,\n        \"mrp_child\": 660,\n        \"mrp_infant\": 0,\n        \"available_quantity\": 100,\n        \"booking_closed\": 0,\n        \"close_before_days\": 24,\n        \"category_id\": null\n      }\n    ],\n    \"isSelectedTimeSlotObject\": {\n      \"id\": 133449,\n      \"from_time\": \"08:30:00\",\n      \"to_time\": \"13:00:00\",\n      \"slot_hour\": 0,\n      \"inventory_date\": \"2026-09-18\",\n      \"week_days\": null,\n      \"adult_price\": 550,\n      \"child_price\": 550,\n      \"infant_price\": 0,\n      \"mrp_adult\": 660,\n      \"mrp_child\": 660,\n      \"mrp_infant\": 0,\n      \"available_quantity\": 100,\n      \"booking_closed\": 0,\n      \"close_before_days\": 24,\n      \"category_id\": null\n    },\n    \"no_of_travellers\": {\n      \"adult\": 1,\n      \"child\": 0,\n      \"infant\": 0,\n      \"travellers\": 1\n    }\n  }\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "url": {
              "raw": "{{baseUrl}}/outApi/reserve_booking",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "outApi",
                "reserve_booking"
              ]
            },
            "description": "Holds the units and re-quotes the price. Nothing is charged.\n\nReturns booking_ref_no, hold_expires_at, hold_minutes, total_price (what confirm will charge), requested_total_price, price_changed and price_check.\nprice_check 'quoted' = re-priced from the catalogue; 'unavailable' = the quote could not be produced and your own total_price is held (price_changed is then null).\n\nRefusals: insufficient_balance, insufficient_inventory, no_time_slot / no_inventory, duplicate_booking (same activity + amount within a minute)."
          },
          "response": [],
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "const r = pm.response.json();",
                  "pm.test('reserved', () => pm.expect(r.status).to.eql(true));",
                  "if (r.status && r.data) {",
                  "  pm.collectionVariables.set('booking_ref_no', r.data.booking_ref_no);",
                  "  pm.collectionVariables.set('held_total_price', r.data.total_price);",
                  "  if (r.data.price_changed) { console.log('price changed to', r.data.total_price); }",
                  "}"
                ]
              }
            }
          ]
        },
        {
          "name": "Create Booking (confirm the hold)",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"booking_ref_no\": \"{{booking_ref_no}}\",\n  \"total_price\": \"{{held_total_price}}\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "url": {
              "raw": "{{baseUrl}}/outApi/create_booking",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "outApi",
                "create_booking"
              ]
            },
            "description": "Charges the wallet and confirms the hold. total_price is optional; when sent it must equal the held price or the call is refused with price_mismatch (409).\n\nRefusals: already_confirmed, reservation_released, reservation_expired (the hold lapsed -- its units are put back automatically), booking_cancelled, insufficient_balance, not_found."
          },
          "response": [],
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "const r = pm.response.json();",
                  "pm.test('confirmed', () => pm.expect(r.status).to.eql(true));",
                  "if (r.status && r.data) { pm.collectionVariables.set('booking_id', r.data.booking_id); }"
                ]
              }
            }
          ]
        },
        {
          "name": "Release Booking",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"booking_ref_no\": \"{{booking_ref_no}}\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "url": {
              "raw": "{{baseUrl}}/outApi/release_booking",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "outApi",
                "release_booking"
              ]
            },
            "description": "Gives the hold back before it expires. No money moves.\n\nReleasing an already released or expired hold answers 200, so a retry is safe. A CONFIRMED booking is refused with already_confirmed -- use cancel_booking."
          },
          "response": []
        },
        {
          "name": "Create Booking (one step, no hold)",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"reference_type\": 1,\n  \"reference_id\": 4,\n  \"source\": \"ACT\",\n  \"travel_date\": \"2026-09-18\",\n  \"time_from\": \"08:30:00\",\n  \"time_to\": \"13:00:00\",\n  \"title\": \"Safari world with Marine Park + Lunch Included\",\n  \"city\": \"Bangkok\",\n  \"country\": \"Thailand\",\n  \"currency\": \"INR\",\n  \"cancellation_policy_id\": 59,\n  \"no_of_travellers\": {\n    \"adult\": 1,\n    \"child\": 0,\n    \"infant\": 0,\n    \"travellers\": 1\n  },\n  \"total_price\": 550,\n  \"guest_info\": {\n    \"first_name\": \"Harish\",\n    \"last_name\": \"K\",\n    \"email\": \"harish@example.com\",\n    \"contact_no\": \"+919999999999\"\n  },\n  \"reference_object\": {\n    \"id\": 4,\n    \"source\": \"ACT\",\n    \"activity_date\": \"2026-09-18\",\n    \"inventory_source\": \"base\",\n    \"time_slots\": [\n      {\n        \"id\": 133449,\n        \"from_time\": \"08:30:00\",\n        \"to_time\": \"13:00:00\",\n        \"slot_hour\": 0,\n        \"inventory_date\": \"2026-09-18\",\n        \"week_days\": null,\n        \"adult_price\": 550,\n        \"child_price\": 550,\n        \"infant_price\": 0,\n        \"mrp_adult\": 660,\n        \"mrp_child\": 660,\n        \"mrp_infant\": 0,\n        \"available_quantity\": 100,\n        \"booking_closed\": 0,\n        \"close_before_days\": 24,\n        \"category_id\": null\n      }\n    ],\n    \"isSelectedTimeSlotObject\": {\n      \"id\": 133449,\n      \"from_time\": \"08:30:00\",\n      \"to_time\": \"13:00:00\",\n      \"slot_hour\": 0,\n      \"inventory_date\": \"2026-09-18\",\n      \"week_days\": null,\n      \"adult_price\": 550,\n      \"child_price\": 550,\n      \"infant_price\": 0,\n      \"mrp_adult\": 660,\n      \"mrp_child\": 660,\n      \"mrp_infant\": 0,\n      \"available_quantity\": 100,\n      \"booking_closed\": 0,\n      \"close_before_days\": 24,\n      \"category_id\": null\n    },\n    \"no_of_travellers\": {\n      \"adult\": 1,\n      \"child\": 0,\n      \"infant\": 0,\n      \"travellers\": 1\n    }\n  }\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "url": {
              "raw": "{{baseUrl}}/outApi/create_booking",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "outApi",
                "create_booking"
              ]
            },
            "description": "The original one-step booking: freezes inventory, writes the booking and charges the wallet in one call. Unchanged, and still supported for partners that do not reserve first."
          },
          "response": []
        }
      ]
    },
    {
      "name": "3. After the booking",
      "item": [
        {
          "name": "Booking Details",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"booking_ref_no\": \"{{booking_ref_no}}\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "url": {
              "raw": "{{baseUrl}}/outApi/booking_details",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "outApi",
                "booking_details"
              ]
            },
            "description": "The partner's own booking. booking_id also works."
          },
          "response": []
        },
        {
          "name": "Bookings List (holds too)",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"include_reservations\": 1,\n  \"page\": 1,\n  \"limit\": 20\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "url": {
              "raw": "{{baseUrl}}/outApi/bookings_list",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "outApi",
                "bookings_list"
              ]
            },
            "description": "include_reservations: 1 lists holds alongside bookings. booking_status is then RESERVED / RELEASED / EXPIRED, and each row carries reservation_status and hold_expires_at. Without the flag (or with 0) holds are left out."
          },
          "response": []
        },
        {
          "name": "Bookings List (holds only)",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"status\": \"RESERVED\",\n  \"page\": 1,\n  \"limit\": 20\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "url": {
              "raw": "{{baseUrl}}/outApi/bookings_list",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "outApi",
                "bookings_list"
              ]
            },
            "description": "Asking for a hold state by status implies include_reservations. RELEASED and EXPIRED work too."
          },
          "response": []
        },
        {
          "name": "Bookings List",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"page\": 1,\n  \"limit\": 20\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "url": {
              "raw": "{{baseUrl}}/outApi/bookings_list",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "outApi",
                "bookings_list"
              ]
            },
            "description": "Your bookings, newest first."
          },
          "response": []
        },
        {
          "name": "Cancellation Charges",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"booking_ref_no\": \"{{booking_ref_no}}\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "url": {
              "raw": "{{baseUrl}}/outApi/cancellation_charges",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "outApi",
                "cancellation_charges"
              ]
            },
            "description": "What cancelling this booking would cost right now, by the policy in force."
          },
          "response": []
        },
        {
          "name": "Cancel Booking",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"booking_ref_no\": \"{{booking_ref_no}}\",\n  \"remarks\": \"Customer cancelled\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "url": {
              "raw": "{{baseUrl}}/outApi/cancel_booking",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "outApi",
                "cancel_booking"
              ]
            },
            "description": "Cancels a CONFIRMED booking: charge by policy, units restored, refund credited to the wallet."
          },
          "response": []
        },
        {
          "name": "Wallet Balance",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"amount\": 550\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "url": {
              "raw": "{{baseUrl}}/outApi/wallet_balance",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "outApi",
                "wallet_balance"
              ]
            },
            "description": "Your wallet balance. Optional amount turns it into 'can I afford this'."
          },
          "response": []
        }
      ]
    },
    {
      "name": "4. Negative examples",
      "item": [
        {
          "name": "Reserve - sold out slot",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"reference_type\": 1,\n  \"reference_id\": 4,\n  \"source\": \"ACT\",\n  \"travel_date\": \"2026-09-18\",\n  \"time_from\": \"08:30:00\",\n  \"time_to\": \"13:00:00\",\n  \"title\": \"Safari world with Marine Park + Lunch Included\",\n  \"city\": \"Bangkok\",\n  \"country\": \"Thailand\",\n  \"currency\": \"INR\",\n  \"cancellation_policy_id\": 59,\n  \"no_of_travellers\": {\n    \"adult\": 1,\n    \"child\": 0,\n    \"infant\": 0,\n    \"travellers\": 1\n  },\n  \"total_price\": 550,\n  \"guest_info\": {\n    \"first_name\": \"Harish\",\n    \"last_name\": \"K\",\n    \"email\": \"harish@example.com\",\n    \"contact_no\": \"+919999999999\"\n  },\n  \"reference_object\": {\n    \"id\": 4,\n    \"source\": \"ACT\",\n    \"activity_date\": \"2026-09-18\",\n    \"inventory_source\": \"base\",\n    \"time_slots\": [\n      {\n        \"id\": 999999,\n        \"from_time\": \"08:30:00\",\n        \"to_time\": \"13:00:00\",\n        \"slot_hour\": 0,\n        \"inventory_date\": \"2026-09-18\",\n        \"week_days\": null,\n        \"adult_price\": 550,\n        \"child_price\": 550,\n        \"infant_price\": 0,\n        \"mrp_adult\": 660,\n        \"mrp_child\": 660,\n        \"mrp_infant\": 0,\n        \"available_quantity\": 100,\n        \"booking_closed\": 0,\n        \"close_before_days\": 24,\n        \"category_id\": null\n      }\n    ],\n    \"isSelectedTimeSlotObject\": {\n      \"id\": 999999,\n      \"from_time\": \"08:30:00\",\n      \"to_time\": \"13:00:00\",\n      \"slot_hour\": 0,\n      \"inventory_date\": \"2026-09-18\",\n      \"week_days\": null,\n      \"adult_price\": 550,\n      \"child_price\": 550,\n      \"infant_price\": 0,\n      \"mrp_adult\": 660,\n      \"mrp_child\": 660,\n      \"mrp_infant\": 0,\n      \"available_quantity\": 100,\n      \"booking_closed\": 0,\n      \"close_before_days\": 24,\n      \"category_id\": null\n    },\n    \"no_of_travellers\": {\n      \"adult\": 1,\n      \"child\": 0,\n      \"infant\": 0,\n      \"travellers\": 1\n    }\n  }\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "url": {
              "raw": "{{baseUrl}}/outApi/reserve_booking",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "outApi",
                "reserve_booking"
              ]
            },
            "description": "A slot id that does not belong to this activity and date: no_time_slot / insufficient_inventory."
          },
          "response": []
        },
        {
          "name": "Confirm - unknown reference",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"booking_ref_no\": \"ACTNOPE01\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "url": {
              "raw": "{{baseUrl}}/outApi/create_booking",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "outApi",
                "create_booking"
              ]
            },
            "description": "A reference that is not yours: 404 not_found (the same answer as 'no such booking')."
          },
          "response": []
        },
        {
          "name": "Confirm - stale price",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"booking_ref_no\": \"{{booking_ref_no}}\",\n  \"total_price\": 1\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            },
            "url": {
              "raw": "{{baseUrl}}/outApi/create_booking",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "outApi",
                "create_booking"
              ]
            },
            "description": "409 price_mismatch, carrying the held total_price."
          },
          "response": []
        }
      ]
    }
  ]
}