Skip to content

Requests and errors

How every request to the API is made and answered: the address, your key, versions, limits and errors.

The basics

  • Every request goes to https://api.pnrstack.com/v1, over HTTPS.
  • Bodies are JSON in both directions, with Content-Type: application/json.
  • Times are ISO 8601. Times in a reservation are local to the airport, with their UTC offset.
  • IDs start with what they are: lkp_ a lookup, mon_ a monitor, whk_ a webhook endpoint, evt_ an event.

API keys

Send your key as Authorization: Bearer pk_live_…. Sandbox keys start pk_test_ and only reach the sandbox airline. A request without a valid key is answered 401.

Idempotency

Every POST takes an Idempotency-Key header. Send a value unique to what you're doing, such as your order ID, and a retry with the same key within 24 hours gets the first answer back instead of doing it twice. A key reused with a different body is refused with idempotency_conflict.

Versions

The version is in the address. Within v1 we only add: new fields, new event types and new optional fields in requests, so ignore fields you don't recognise. A change that would break your integration comes as a new version at a new address, with months of notice.

Limits

Each account has a limit on lookups a minute and a day, agreed with you when you start. Over it, you get 429 with rate_limited and a Retry-After header saying how many seconds to wait.

Errors

Every error has the same shape:

{
  "error": {
    "code": "invalid_request",
    "message": "The request's surname isn't valid: it can't be empty.",
    "request_id": "f5f5e0e0-626d-4c08-b0a5-872a7c6b9290"
  }
}

The message is written for your logs, not your users. Quote the request_id when you contact us and we can find the request.

StatusCodeWhen
400invalid_requestA field is missing or isn't valid. The message names it
401unauthorisedNo API key, or one that isn't valid
404not_foundNo such lookup, monitor or endpoint on your account
409idempotency_conflictAn Idempotency-Key reused with a different body
429rate_limitedToo many requests: wait Retry-After seconds
500internal_errorSomething went wrong on our side. It's safe to retry

These are errors in the request itself. A lookup that runs and can't retrieve the booking isn't one: it ends failed, with its reason. See Failures.