Introduction

View as Markdown

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.

Base URL: https://api-prod.globalairportconcierge.com/api/v1

GAC issues your credentials, and a sandbox base URL if you want one, when your integration is set up.

Getting started

  1. 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.
  2. List services at an airport — find out what is available and at what rate.
  3. Create quote — send the itinerary and get a price back. The booking is created in status quote.
  4. Confirm quote — commit it. Status becomes booking and the customer is emailed.
  5. Look it up later — by our id, our reference, or your own.

Endpoints are numbered in the order you would normally call them.

Booking lifecycle

Create quote
|
[quote] --- Replace / Reprice ---> [quote]
|
Confirm quote
|
[booking]
|
Cancel booking
|
[cancelled]

cancelled is terminal. Every other endpoint refuses a cancelled booking.

A quote is valid for one week. After that, reprice it before confirming.

Response envelope

Every endpoint except Get access token wraps its payload:

1{ "message": "", "status": 200, "responseTime": "125ms", "trace": [], "data": { } }

List endpoints add a pagination block and put an array in data:

1"pagination": { "total_count": 7, "total_pages": 4, "current_page": 1, "limit": 2 }

Errors

Every error carries an error_code. Branch on error_code, not on the message. The code is a contract; the wording is ours to improve.

1{
2 "message": "No booking found with id 99999999. It may not exist, or it may belong to another company.",
3 "status": 404,
4 "responseTime": "22ms",
5 "error_code": "booking_not_found",
6 "data": { "errors": [] }
7}

Validation failures add a top-level errors object keyed by field, and report every problem at once rather than stopping at the first:

1{
2 "message": "The currency field is required. (and 2 more errors)",
3 "status": 422,
4 "error_code": "validation_failed",
5 "errors": {
6 "currency": ["The currency field is required."],
7 "journeys": ["At least one journey is required."]
8 },
9 "data": []
10}
error_codeStatusMeaning
validation_failed422Your payload is wrong. errors says exactly where. Fix and resend.
invalid_client_credentials401client_id or client_secret was rejected when requesting a token.
unauthenticated401Bearer token missing, invalid or expired. Get a new one.
forbidden403Your client is not allowed to do this.
invoice_terms_required403Your company is not set up for invoice payments, so bookings cannot be confirmed.
booking_not_found404No booking with that id or reference, or it belongs to another company. The two are deliberately indistinguishable.
endpoint_not_found404No such endpoint. Check the method and path.
method_not_allowed405Wrong HTTP method for that path.
booking_cancelled409The booking is cancelled and cannot be changed. Terminal, do not retry.
booking_already_confirmed409Already confirmed. Read it back rather than confirming again.
quote_expired409Reprice the quote, then confirm.
payment_incomplete409Payment has not settled yet. Retry later.
booking_not_confirmable409The booking’s state blocks confirmation. Read it back to see why.
booking_total_too_low422No chargeable total. Check a service is attached and priced.
rate_limit_exceeded429Too many requests. Back off and retry.
server_error500Our fault. Nothing was changed. The message carries a reference to quote to GAC support.

A 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.

Pricing inputs

Services are priced from the journey’s adult, child and infant counts and its bag counts. There is no per-service passenger override, so those counts must be accurate.

ServicePriced on
Meet & Assistadult + child, from a nine-tier cumulative table. Infants are not counted.
Porter Servicebag_small + bag_medium + bag_large.
Fast Trackadult + child.
Lounge Accessadult, child and infant charged separately, each at its own rate.
Electric Buggyadult + child, in bands.

Lounge Access is the only service that charges infants, and only where the airport has a non-zero infant rate.

Rate limiting

300 requests per minute. Over that you get 429 rate_limit_exceeded. No Retry-After header is sent, so implement your own backoff rather than retrying immediately. If you expect sustained volume above this, talk to GAC before you go live.

Known quirks

These are real behaviours, documented so you do not lose a day to them.

BehaviourWhat to do
confirm: true when creating a quote does not confirm anything. The booking stays a quote and no error is returned.Call the confirm endpoint explicitly.
Replacing a 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.
trace is always [] on success, and the bookings list omits the key entirely.Ignore it.
Quote validity is one week, not the four hours some older documentation implies.Trust expires_on.
X-Tenant-ID is fixed server-side.Do not send it.

Not available yet

  • No webhooks. Nothing notifies you when a booking changes. Poll the booking endpoint for anything you need to stay current on.
  • 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.
  • No date filter when listing bookings. Reconciliation means paging newest-first.
  • Service discovery is partial. The catalogue endpoint returns only three of the bookable services. Ask GAC for the ids of the rest.

Last reviewed against the live API: 2026-08-24. Every example in this documentation is a real captured response, including the error ones.