{"activeVersionTag":"latest","latestAvailableVersionTag":"latest","collection":{"info":{"_postman_id":"d4ec1598-6624-4bc0-86ea-f9c6f6160e9a","name":"Global Airport Concierge API v1","description":"The **Global Airport Concierge API v1** lets a partner price and book airport concierge services: Meet & Assist, Porter, Lounge Access and more, at over 500 airports.\n\n**Base URL:** `https://api-prod.globalairportconcierge.com/api/v1`\n\n**Published documentation:** https://api-docs.globalairportconcierge.com\n\nGAC issues your credentials, and a sandbox base URL if you want one, when your integration is set up. In Postman every request reads the host from the `base_url` variable, so pick an environment before you send anything.\n\n## Getting started\n\n1. **01 Get access token** — exchange your `client_id` and `client_secret` for a bearer token. Send it as `Authorization: Bearer …` on everything else. Tokens last a year, so cache it.\n2. **02 List services at an airport** — find out what is available and at what rate.\n3. **03 Create quote** — send the itinerary and get a price back. The booking is created in status `quote`.\n4. **06 Confirm quote** — commit it. Status becomes `booking` and the customer is emailed.\n5. **09 / 10 / 11** — read it back later, by our id, our reference, or your own.\n\nRequests are numbered in the order you would normally call them.\n\n## Booking lifecycle\n\n```\n         03 Create quote\n               |\n            [quote]  --- 04 Replace / 05 Reprice ---> [quote]\n               |\n         06 Confirm quote\n               |\n           [booking]\n               |\n         07 Cancel booking\n               |\n          [cancelled]\n```\n\n`cancelled` is terminal. Every other endpoint refuses a cancelled booking.\n\nA quote is valid for **one week**. After that, reprice it before confirming.\n\n## Response envelope\n\nEvery endpoint except **01 Get access token** wraps its payload:\n\n```json\n{ \"message\": \"…\", \"status\": 200, \"responseTime\": \"125ms\", \"trace\": [], \"data\": { } }\n```\n\nList endpoints add a `pagination` block and put an array in `data`:\n\n```json\n\"pagination\": { \"total_count\": 7, \"total_pages\": 4, \"current_page\": 1, \"limit\": 2 }\n```\n\n## Errors\n\nEvery error carries an `error_code`. **Branch on `error_code`, not on the message.** The code is a contract; the wording is ours to improve.\n\n```json\n{\n  \"message\": \"No booking found with id 99999999. It may not exist, or it may belong to another company.\",\n  \"status\": 404,\n  \"responseTime\": \"22ms\",\n  \"error_code\": \"booking_not_found\",\n  \"data\": { \"errors\": [] }\n}\n```\n\nValidation failures add a top-level `errors` object keyed by field, and report **every** problem at once rather than stopping at the first:\n\n```json\n{\n  \"message\": \"The currency field is required. (and 2 more errors)\",\n  \"status\": 422,\n  \"error_code\": \"validation_failed\",\n  \"errors\": {\n    \"currency\": [\"The currency field is required.\"],\n    \"journeys\": [\"At least one journey is required.\"]\n  },\n  \"data\": []\n}\n```\n\n| `error_code` | Status | Meaning |\n| --- | --- | --- |\n| `validation_failed` | 422 | Your payload is wrong. `errors` says exactly where. Fix and resend. |\n| `invalid_client_credentials` | 401 | `client_id` or `client_secret` was rejected at **01 Get access token**. |\n| `unauthenticated` | 401 | Bearer token missing, invalid or expired. Get a new one. |\n| `forbidden` | 403 | Your client is not allowed to do this. |\n| `invoice_terms_required` | 403 | Your company is not set up for invoice payments, so bookings cannot be confirmed. |\n| `booking_not_found` | 404 | No booking with that id or reference, or it belongs to another company. The two are deliberately indistinguishable. |\n| `agent_not_found` | 404 | No agent with that id or reference on your account. |\n| `endpoint_not_found` | 404 | No such endpoint. Check the method and path. |\n| `method_not_allowed` | 405 | Wrong HTTP method for that path. |\n| `booking_cancelled` | 409 | The booking is cancelled and cannot be changed. Terminal, do not retry. |\n| `booking_already_confirmed` | 409 | Already confirmed. Read it back rather than confirming again. |\n| `quote_expired` | 409 | Reprice with **05 Reprice quote**, then confirm. |\n| `payment_incomplete` | 409 | Payment has not settled yet. Retry later. |\n| `booking_not_confirmable` | 409 | The booking's state blocks confirmation. Read it back to see why. |\n| `booking_total_too_low` | 422 | No chargeable total. Check a service is attached and priced. |\n| `rate_limit_exceeded` | 429 | Too many requests. Back off for the number of seconds in `Retry-After`. |\n| `server_error` | 500 | Our fault. Nothing was changed. The message carries a reference to quote to GAC support. |\n\nA `4xx` other than `429` will not succeed on retry without a change on your side. `429` and `500` are the only ones worth retrying as-is.\n\n## What you can book\n\nNine services are bookable. Seven are priced from the journey's passenger and bag counts alone; Car Transfer and Airport By Invitation take extra inputs through `service_options`. **03 Create quote** carries the full table, the service ids, how many airports hold rates for each, and a worked example of every one.\n\nTwo things worth knowing before you plan an integration:\n\n- **02 List services at an airport** returns only Meet & Assist, Porter and Lounge Access. The other six are bookable but not discoverable, so take their ids from **03 Create quote** and ask GAC which airports carry them.\n- **Car Transfer has no rates loaded yet.** It books, and returns a line worth `0`. Do not sell it without talking to GAC first.\n\nServices can also be sold as a named package at a discount. Bundles apply automatically when a booking carries every member service on the same stop, so there is nothing extra to send. See **02b List service bundles**.\n\n## Rate limiting\n\n300 requests per minute, counted **per API key**, so nobody else's traffic eats your budget and yours does not eat theirs.\n\nEvery response carries `X-RateLimit-Limit` and `X-RateLimit-Remaining`, so you can pace yourself before you run out. Go over and you get `429 rate_limit_exceeded` with a `Retry-After` header giving the seconds to wait. Honour it rather than retrying immediately.\n\nIf you expect sustained volume above this, talk to GAC before you go live rather than discovering the ceiling in production.\n\n## Your agents\n\nIf several people book on your account, each needs an agent record, because **03 Create quote** refuses a `booker_id` that is not one of yours. That is what attributes a booking to the person who made it and puts the right name on the confirmation email.\n\nYou create and remove them yourself through **13 Manage your agents**. They are booking records rather than logins: your own system signs the agent in at your end and tells us who it was.\n\n## Known quirks\n\n| Behaviour | What to do |\n| --- | --- |\n| `confirm: true` on **03 Create quote** does not confirm anything. The booking stays a `quote` and no error is returned. | Call **06 Confirm quote** explicitly. |\n| **04 Replace quote** is a full replace. It regenerates `ref_no`, resets `status` to `quote`, clears `billing.status` and resets `expires_on`. | Echo the existing `ref_no` back, and never replace a confirmed booking unless you mean to un-confirm it. |\n| `trace` is always `[]` on success, and **08 List bookings** omits the key entirely. | Ignore it. |\n| Quote validity is one week, not the four hours some older documentation implies. | Trust `expires_on`. |\n| `X-Tenant-ID` is fixed server-side. | Do not send it. |\n\n## Staying in sync\n\nYou do not have to poll. Two mechanisms, and most integrations want both:\n\n- **Webhooks.** We POST the booking to a URL of yours whenever it is confirmed, amended or cancelled, when a greeter is assigned, and when the service is delivered, missed or fails. That includes changes made by GAC operations, which you would otherwise never see. Ask GAC to set one up; there is no self-serve registration. See **12 Webhooks (we call you)**.\n- **`updated_since` on 08 List bookings.** Pull everything that changed since a timestamp. This is the recovery path when your endpoint has been down, and the belt-and-braces option if you would rather reconcile on a schedule.\n\n## Not available yet\n\n- **No idempotency key.** A retried create makes a second booking. Send a unique `settings.customer_reference` every time and use it to detect and recover from duplicates; see **03 Create quote**.\n- **No created-date filter** on **08 List bookings**. `updated_since` covers changes, but there is no way to ask for bookings made between two dates.\n\nLast reviewed against the live API: 2026-09-09. Every example in this collection is a real captured response, including the error ones. The one exception is the sample body in **12.1**, where the passenger and greeter details are placeholders because that collection is shared and a real payload names a customer and an assigned greeter.","schema":"https://schema.getpostman.com/json/collection/v2.0.0/collection.json","isPublicCollection":false,"owner":"771129","team":3885263,"collectionId":"d4ec1598-6624-4bc0-86ea-f9c6f6160e9a","publishedId":"2sAYJ4jMHi","public":true,"publicUrl":"https://api-doc.globalairportconcierge.com","privateUrl":"https://go.postman.co/documentation/771129-d4ec1598-6624-4bc0-86ea-f9c6f6160e9a","customColor":{"top-bar":"FFFFFF","right-sidebar":"e6e7e8","highlight":"70c5bc"},"documentationLayout":"classic-double-column","customisation":{"metaTags":[{"name":"description","value":""},{"name":"title","value":""}],"appearance":{"default":"system_default","themes":[{"name":"dark","logo":null,"colors":{"top-bar":"212121","right-sidebar":"303030","highlight":"70c5bc"}},{"name":"light","logo":null,"colors":{"top-bar":"FFFFFF","right-sidebar":"e6e7e8","highlight":"70c5bc"}}]}},"version":"8.12.8","publishDate":"2026-08-24T22:45:59.000Z","activeVersionTag":"latest","documentationTheme":"light","metaTags":{"title":"","description":""},"logos":{"logoLight":null,"logoDark":null}},"statusCode":200},"environments":[],"user":{"authenticated":false,"permissions":{"publish":false}},"run":{"button":{"js":"https://run.pstmn.io/button.js","css":"https://run.pstmn.io/button.css"}},"web":"https://www.getpostman.com/","team":{"logo":"https://res.cloudinary.com/postman/image/upload/t_team_logo_pubdoc/v1/team/c3e43d5eb47f919599e7423c935825301736d6402a3d9794d9070f4f318cf9cf","favicon":"https://globalairportconcierge.com/favicon.ico"},"isEnvFetchError":false,"languages":"[{\"key\":\"csharp\",\"label\":\"C#\",\"variant\":\"HttpClient\"},{\"key\":\"csharp\",\"label\":\"C#\",\"variant\":\"RestSharp\"},{\"key\":\"curl\",\"label\":\"cURL\",\"variant\":\"cURL\"},{\"key\":\"dart\",\"label\":\"Dart\",\"variant\":\"http\"},{\"key\":\"go\",\"label\":\"Go\",\"variant\":\"Native\"},{\"key\":\"http\",\"label\":\"HTTP\",\"variant\":\"HTTP\"},{\"key\":\"java\",\"label\":\"Java\",\"variant\":\"OkHttp\"},{\"key\":\"java\",\"label\":\"Java\",\"variant\":\"Unirest\"},{\"key\":\"javascript\",\"label\":\"JavaScript\",\"variant\":\"Fetch\"},{\"key\":\"javascript\",\"label\":\"JavaScript\",\"variant\":\"jQuery\"},{\"key\":\"javascript\",\"label\":\"JavaScript\",\"variant\":\"XHR\"},{\"key\":\"c\",\"label\":\"C\",\"variant\":\"libcurl\"},{\"key\":\"nodejs\",\"label\":\"NodeJs\",\"variant\":\"Axios\"},{\"key\":\"nodejs\",\"label\":\"NodeJs\",\"variant\":\"Native\"},{\"key\":\"nodejs\",\"label\":\"NodeJs\",\"variant\":\"Request\"},{\"key\":\"nodejs\",\"label\":\"NodeJs\",\"variant\":\"Unirest\"},{\"key\":\"objective-c\",\"label\":\"Objective-C\",\"variant\":\"NSURLSession\"},{\"key\":\"ocaml\",\"label\":\"OCaml\",\"variant\":\"Cohttp\"},{\"key\":\"php\",\"label\":\"PHP\",\"variant\":\"cURL\"},{\"key\":\"php\",\"label\":\"PHP\",\"variant\":\"Guzzle\"},{\"key\":\"php\",\"label\":\"PHP\",\"variant\":\"HTTP_Request2\"},{\"key\":\"php\",\"label\":\"PHP\",\"variant\":\"pecl_http\"},{\"key\":\"powershell\",\"label\":\"PowerShell\",\"variant\":\"RestMethod\"},{\"key\":\"python\",\"label\":\"Python\",\"variant\":\"http.client\"},{\"key\":\"python\",\"label\":\"Python\",\"variant\":\"Requests\"},{\"key\":\"r\",\"label\":\"R\",\"variant\":\"httr\"},{\"key\":\"r\",\"label\":\"R\",\"variant\":\"RCurl\"},{\"key\":\"ruby\",\"label\":\"Ruby\",\"variant\":\"Net::HTTP\"},{\"key\":\"shell\",\"label\":\"Shell\",\"variant\":\"Httpie\"},{\"key\":\"shell\",\"label\":\"Shell\",\"variant\":\"wget\"},{\"key\":\"swift\",\"label\":\"Swift\",\"variant\":\"URLSession\"}]","languageSettings":[{"key":"csharp","label":"C#","variant":"HttpClient"},{"key":"csharp","label":"C#","variant":"RestSharp"},{"key":"curl","label":"cURL","variant":"cURL"},{"key":"dart","label":"Dart","variant":"http"},{"key":"go","label":"Go","variant":"Native"},{"key":"http","label":"HTTP","variant":"HTTP"},{"key":"java","label":"Java","variant":"OkHttp"},{"key":"java","label":"Java","variant":"Unirest"},{"key":"javascript","label":"JavaScript","variant":"Fetch"},{"key":"javascript","label":"JavaScript","variant":"jQuery"},{"key":"javascript","label":"JavaScript","variant":"XHR"},{"key":"c","label":"C","variant":"libcurl"},{"key":"nodejs","label":"NodeJs","variant":"Axios"},{"key":"nodejs","label":"NodeJs","variant":"Native"},{"key":"nodejs","label":"NodeJs","variant":"Request"},{"key":"nodejs","label":"NodeJs","variant":"Unirest"},{"key":"objective-c","label":"Objective-C","variant":"NSURLSession"},{"key":"ocaml","label":"OCaml","variant":"Cohttp"},{"key":"php","label":"PHP","variant":"cURL"},{"key":"php","label":"PHP","variant":"Guzzle"},{"key":"php","label":"PHP","variant":"HTTP_Request2"},{"key":"php","label":"PHP","variant":"pecl_http"},{"key":"powershell","label":"PowerShell","variant":"RestMethod"},{"key":"python","label":"Python","variant":"http.client"},{"key":"python","label":"Python","variant":"Requests"},{"key":"r","label":"R","variant":"httr"},{"key":"r","label":"R","variant":"RCurl"},{"key":"ruby","label":"Ruby","variant":"Net::HTTP"},{"key":"shell","label":"Shell","variant":"Httpie"},{"key":"shell","label":"Shell","variant":"wget"},{"key":"swift","label":"Swift","variant":"URLSession"}],"languageOptions":[{"label":"C# - HttpClient","value":"csharp - HttpClient - C#"},{"label":"C# - RestSharp","value":"csharp - RestSharp - C#"},{"label":"cURL - cURL","value":"curl - cURL - cURL"},{"label":"Dart - http","value":"dart - http - Dart"},{"label":"Go - Native","value":"go - Native - Go"},{"label":"HTTP - HTTP","value":"http - HTTP - HTTP"},{"label":"Java - OkHttp","value":"java - OkHttp - Java"},{"label":"Java - Unirest","value":"java - Unirest - Java"},{"label":"JavaScript - Fetch","value":"javascript - Fetch - JavaScript"},{"label":"JavaScript - jQuery","value":"javascript - jQuery - JavaScript"},{"label":"JavaScript - XHR","value":"javascript - XHR - JavaScript"},{"label":"C - libcurl","value":"c - libcurl - C"},{"label":"NodeJs - Axios","value":"nodejs - Axios - NodeJs"},{"label":"NodeJs - Native","value":"nodejs - Native - NodeJs"},{"label":"NodeJs - Request","value":"nodejs - Request - NodeJs"},{"label":"NodeJs - Unirest","value":"nodejs - Unirest - NodeJs"},{"label":"Objective-C - NSURLSession","value":"objective-c - NSURLSession - Objective-C"},{"label":"OCaml - Cohttp","value":"ocaml - Cohttp - OCaml"},{"label":"PHP - cURL","value":"php - cURL - PHP"},{"label":"PHP - Guzzle","value":"php - Guzzle - PHP"},{"label":"PHP - HTTP_Request2","value":"php - HTTP_Request2 - PHP"},{"label":"PHP - pecl_http","value":"php - pecl_http - PHP"},{"label":"PowerShell - RestMethod","value":"powershell - RestMethod - PowerShell"},{"label":"Python - http.client","value":"python - http.client - Python"},{"label":"Python - Requests","value":"python - Requests - Python"},{"label":"R - httr","value":"r - httr - R"},{"label":"R - RCurl","value":"r - RCurl - R"},{"label":"Ruby - Net::HTTP","value":"ruby - Net::HTTP - Ruby"},{"label":"Shell - Httpie","value":"shell - Httpie - Shell"},{"label":"Shell - wget","value":"shell - wget - Shell"},{"label":"Swift - URLSession","value":"swift - URLSession - Swift"}],"layoutOptions":[{"value":"classic-single-column","label":"Single Column"},{"value":"classic-double-column","label":"Double Column"}],"versionOptions":[],"environmentOptions":[{"value":"0","label":"No Environment"}],"canonicalUrl":"https://api-doc.globalairportconcierge.com/view/metadata/2sAYJ4jMHi"}