Developer Reference

API Documentation

View .md
VR

Written by Varsha Reddy, SDE at Flyo.ai

varsha@flyo.ai

Getting Started

Ready to integrate?

Get your API key and start sending requests to the Flyo partner API.

Get your API key

Flyo's external partner APIs let you register flight bookings for automated web check-in, poll the current status of a check-in request, and list all your historical check-in requests.

Because these endpoints are consumed by external systems, all paths below are relative paths. Append them to the deployment-specific host your integration points at.

Every request must include a valid X-API-Key header. Get your API key from the Flyo partner dashboard. The key is static and remains valid until it is revoked from the dashboard; there is no separate expiry or refresh flow.

All request and response bodies use JSON. Timestamps are ISO 8601 UTC strings. IATA codes are exactly three uppercase letters.

Authentication

External partner endpoints require an API key passed in the X-API-Key header. The key identifies your enterprise and is used for both authentication and per-key rate limiting.

When a request arrives, the key is validated against the database first. Only if it is not found there do we fall back to the legacy environment-based key list.

Validation rules: the header must be present and non-empty; it must match an active key; revoked, disabled, or unknown keys receive 401. There is no token expiry or refresh; a key stays active until revoked. In development mode only, a default environment key can be used for testing. Production integrations must use a real dashboard-issued key.

Example
GET /extPartner/api/webcheckin/requests
X-API-Key: flyo_<issued-key>
Content-Type: application/json

Rate Limits

Rate limiting is enforced per API key using a rolling window. Two limits apply independently:

  • 60 requests per minute
  • 1,000 requests per hour

When either limit is exceeded the API returns HTTP 429 with a retryAfter value in seconds. Wait at least that many seconds before retrying.

Subscribe also consumes a quota unit in addition to the rate limit.

Error Format

All error responses follow a single JSON shape. The success field is always false. The error field is a stable machine-readable code you can branch on. The message field is a human-readable explanation. Additional context is included only when relevant.

Example
{
  "success": false,
  "error": "VALIDATION_ERROR",
  "message": "Missing or malformed request data"
}

Common Errors

HTTP StatusMessage
400VALIDATION_ERROR: missing or malformed request data.
401Missing, invalid, disabled, or revoked API key.
402QUOTA_EXHAUSTED: no available web-check-in entitlement or quota exhausted.
404NOT_FOUND: the requested check-in or booking does not exist or belongs to another enterprise.
409Conflict: the resource cannot be modified in its current state.
422REJECTED: journey rule rejection such as departure too close, unsupported airline, or invalid route.
429Rate limit exceeded. retryAfter is returned in seconds.
500INTERNAL_ERROR: an unexpected server error occurred.

Pagination

The list endpoint uses offset pagination. page is zero-based, so the first page is 0. limit defaults to 25 and is clamped to a maximum of 100. If you omit the parameters you receive page 0 with 25 items.

The response always includes a pagination object with the page you requested, the actual limit applied, the total matching records, and the total number of pages. Use totalPages to know when you have reached the end of the result set.

Example
{
  "success": true,
  "data": [],
  "pagination": {
    "page": 0,
    "limit": 25,
    "total": 47,
    "totalPages": 2
  }
}

Webhooks

When you subscribe a booking with callbackData, Flyo pushes status changes to your callbackUrl instead of requiring you to poll. Webhooks are sent for the event kind webcheckin.update whenever the check-in attempt changes state.

The callbackData object requires callbackUrl, clientId, clientName, and auth_header. The auth_header must be in the format '<Header-Name>: <Header-Value>' and the header name must be either X-API-Key or Authorization. Flyo forwards this header exactly in every webhook request so your endpoint can verify it.

Webhook delivery is handled through an internal SQS queue. Retries and backoff are managed by the queue consumer; your endpoint should respond with a 2xx status code so delivery is considered successful.

Flyo does not sign the webhook body or add a provider signature header. Authenticate the request using the auth_header value you configured.

Example
{
  "occurredAt": "2026-09-02T09:00:00.000Z",
  "checkin_id": "CHK-783245",
  "changes": {
    "status": "COMPLETED",
    "sub_status": "BOARDING_PASS_AVAILABLE",
    "checkin_message": "Check-in completed and boarding passes are available",
    "missing_info": [],
    "boarding_passes": [
      "https://files.example.com/boarding-pass.pdf"
    ]
  }
}

External Webcheckin APIs

Use these endpoints from an external system to subscribe bookings for automated web check-in, poll for status, and list historical requests.

POST/extPartner/api/webcheckin/subscribe

Create Web Check-in Request

Authentication
X-API-Key: flyo_<issued-key>

Registers a partner booking for automated airline web check-in under the enterprise identified by the API key. Requires an active web-check-in entitlement.

Validates the partner booking payload, checks entitlement and quota, applies journey rules, creates or reuses a partner-scoped check-in attempt, and returns the attempt plus quota details.

Missing passenger or passport information does not automatically reject the request. The attempt can be stored as SCHEDULED with a missing-information sub-status, allowing you to update the booking before automation runs.

If the flight is already inside the check-in window and all required information is present, automation may trigger immediately. Otherwise the attempt is queued for the check-in window.

The response message is one of SCHEDULED, ALREADY_SUBSCRIBED, or REJECTED. When the message is REJECTED, the reason field explains why.

Request

cURL
curl -X POST "/extPartner/api/webcheckin/subscribe" \
  -H "X-API-Key: flyo_<issued-key>" \
  -H "Content-Type: application/json" \
  -d '{"pnr":"ABC123","flights":[{"airline":"AI","flight_number":"AI302","origin":"DEL","destination":"DXB","departure_datetime":"2026-09-02T04:30:00Z","arrival_datetime":"2026-09-02T07:45:00Z"}],"passengers":[{"first_name":"John","last_name":"Doe","email":"john@example.com","phone":"+911234567890","date_of_birth":"1995-07-20","passport":{"number":"N1234567","expiry_date":"2030-05-01","nationality":"IN"},"seat_preference":{"row_preference":"front","column_preference":"window"}}],"callbackData":{"clientId":"acme","clientName":"Acme Travel","callbackUrl":"https://partner.example.com/webhooks/flyo","auth_header":"X-API-Key: A1B2C3D4E5F6G7H8"}}'
Request Body
{
  "pnr": "ABC123",
  "flights": [
    {
      "airline": "AI",
      "flight_number": "AI302",
      "origin": "DEL",
      "destination": "DXB",
      "departure_datetime": "2026-09-02T04:30:00Z",
      "arrival_datetime": "2026-09-02T07:45:00Z"
    }
  ],
  "passengers": [
    {
      "first_name": "John",
      "last_name": "Doe",
      "email": "john@example.com",
      "phone": "+911234567890",
      "date_of_birth": "1995-07-20",
      "passport": {
        "number": "N1234567",
        "expiry_date": "2030-05-01",
        "nationality": "IN"
      },
      "seat_preference": {
        "row_preference": "front",
        "column_preference": "window"
      }
    }
  ],
  "callbackData": {
    "clientId": "acme",
    "clientName": "Acme Travel",
    "callbackUrl": "https://partner.example.com/webhooks/flyo",
    "auth_header": "X-API-Key: A1B2C3D4E5F6G7H8"
  }
}

Request Fields

FieldTypeRequiredDescription
pnrstringYesAirline record locator.
flightsarrayYesOne or more flight legs in travel order. All legs must use the same airline.
flights[].airlineIATA code (3 letters)YesAirline IATA code.
flights[].flight_numberstringYesFlight number including airline prefix.
flights[].originIATA airport codeYesOrigin airport.
flights[].destinationIATA airport codeYesDestination airport.
flights[].departure_datetimeISO 8601 timestampYesDeparture date and time in ISO 8601 UTC format.
flights[].arrival_datetimeISO 8601 timestampNoArrival date and time in ISO 8601 UTC format.
passengersarrayYesNon-empty passenger list.
passengers[].first_namestringYesPassenger first name.
passengers[].last_namestringYesPassenger last name.
passengers[].emailemail stringNoPassenger email address.
passengers[].phoneE.164 phone stringNoPassenger phone number.
passengers[].date_of_birthYYYY-MM-DDNoPassenger date of birth.
passengers[].passportobjectNoPassport details used by airline check-in.
passengers[].passport.numberstringNoPassport number.
passengers[].passport.expiry_dateYYYY-MM-DDNoPassport expiry date.
passengers[].passport.nationalityISO 3166-1 alpha-2NoPassport nationality country code.
passengers[].seat_preferenceobjectNoOptional seat preference.
passengers[].seat_preference.row_preferenceenum: front | middle | backNoPreferred row zone.
passengers[].seat_preference.column_preferenceenum: window | aisle | middleNoPreferred seat column.
callbackDataobjectNoCallback registration for push status updates.
callbackData.clientIdstringYes*Partner callback client identifier. Required when callbackData is provided.
callbackData.clientNamestringYes*Partner callback client name. Required when callbackData is provided.
callbackData.callbackUrlHTTPS URLYes*URL that receives status events. Required when callbackData is provided.
callbackData.auth_headerstringYes*Webhook auth header in '<Header-Name>: <Header-Value>' format. Header name must be X-API-Key or Authorization. Required when callbackData is provided.

Response

Response
{
  "success": true,
  "message": "SCHEDULED",
  "booking_id": 123,
  "checkin_id": "CHK-783245",
  "status": "SCHEDULED",
  "sub_status": "MISSING_INFO",
  "missing_info": [
    { "type": "MISSING_PASSPORT" }
  ],
  "status_message": "Missing passport information",
  "quota": {
    "included_units": 100,
    "consumed_units": 34
  }
}

Response Fields

FieldTypeDescription
successbooleanWhether the operation succeeded.
messageenum: SCHEDULED | ALREADY_SUBSCRIBED | REJECTEDHigh-level result of the subscription.
reasonstring | undefinedPresent when message is REJECTED.
booking_idnumberInternal booking identifier.
checkin_idstringPublic check-in identifier.
statusstringCurrent high-level status.
sub_statusstringDetailed sub-status.
missing_infoarrayList of missing information items, if any.
status_messagestringHuman-readable status explanation.
quotaobject | undefinedEnterprise quota snapshot.
quota.included_unitsnumberIncluded web-check-in units.
quota.consumed_unitsnumberConsumed web-check-in units.

Errors

HTTP StatusMessage
400VALIDATION_ERROR: missing or malformed request data.
401Missing, invalid, disabled, or revoked API key.
402QUOTA_EXHAUSTED: no available entitlement or quota exhausted.
422REJECTED: journey rule rejection, such as departure too close, unsupported airline, or invalid route.
429Rate limit exceeded. retryAfter is returned in seconds.
GET/extPartner/api/webcheckin/status?checkin_id=CHK-...

Get Web Check-in Status

Authentication
X-API-Key: flyo_<issued-key>

Returns the latest status of one check-in request belonging to the enterprise identified by the API key.

Looks up the attempt by checkin_id and the authenticated partnerId, then returns the normalized partner-facing status, missing info, boarding passes, and timestamps.

A check-in belonging to another enterprise is indistinguishable from a missing check-in and returns 404.

Request

cURL
curl -X GET "/extPartner/api/webcheckin/status?checkin_id=CHK-783245" \
  -H "X-API-Key: flyo_<issued-key>"

Request Fields

FieldTypeRequiredDescription
checkin_idstringYesPublic check-in identifier returned by the create API. checkinId is also accepted as a compatibility alias.

Response

Response
{
  "success": true,
  "checkin_id": "CHK-783245",
  "booking_id": 123,
  "status": "COMPLETED",
  "sub_status": "BOARDING_PASS_AVAILABLE",
  "checkin_message": "Check-in completed and boarding passes are available",
  "missing_info": [],
  "boarding_passes": [
    "https://files.example.com/boarding-pass.pdf"
  ],
  "last_updated": "2026-09-02T09:00:00.000Z"
}

Response Fields

FieldTypeDescription
successbooleanWhether the operation succeeded.
checkin_idstringPublic check-in identifier.
booking_idnumberInternal booking identifier.
statusenum: SCHEDULED | IN_PROGRESS | COMPLETED | FAILEDCurrent normalized status.
sub_statusstringDetailed sub-status.
checkin_messagestringHuman-readable status explanation.
missing_infoarrayList of missing information items, if any.
boarding_passesarray of HTTPS URLsBoarding-pass URLs, when available.
last_updatedISO 8601 timestampISO timestamp of the latest update.

Errors

HTTP StatusMessage
400checkin_id is missing.
401Missing, invalid, disabled, or revoked API key.
404The check-in does not exist or belongs to another enterprise.
429Rate limit exceeded. retryAfter is returned in seconds.
GET/extPartner/api/webcheckin/requests?page=0&limit=25&status=COMPLETED

List Enterprise Check-in Requests

Authentication
X-API-Key: flyo_<issued-key>

Returns paginated web check-in request summaries for the enterprise identified by the API key.

Returns the enterprise's paginated, normalized web-check-in request summaries. The result is enterprise-scoped, not scoped by the individual API key used to call this endpoint.

Two API keys belonging to the same enterprise must see the same set of enterprise check-in requests.

page is zero-based. limit defaults to 25 and is clamped between 1 and 100. totalPages is derived from the total count and the applied limit.

Request

cURL
curl -X GET "/extPartner/api/webcheckin/requests?page=0&limit=25&status=COMPLETED" \
  -H "X-API-Key: flyo_<issued-key>"

Request Fields

FieldTypeRequiredDescription
pageinteger >= 0NoZero-based page number. Defaults to 0.
limitinteger 1-100NoItems per page. Defaults to 25; values above 100 are clamped to 100.
statusenum: SCHEDULED | IN_PROGRESS | COMPLETED | FAILEDNoFilter by check-in status.

Response

Response
{
  "success": true,
  "data": [
    {
      "checkin_id": "CHK-783245",
      "booking_id": 123,
      "pnr": "ABC123",
      "origin": "DEL",
      "destination": "DXB",
      "departure_date": "2026-09-02T04:30:00Z",
      "airline": "AI",
      "flight_number": "AI302",
      "status": "COMPLETED",
      "sub_status": "BOARDING_PASS_AVAILABLE",
      "checkin_message": "Check-in completed and boarding passes are available",
      "missing_info": [],
      "boarding_passes": [
        "https://files.example.com/boarding-pass.pdf"
      ],
      "scheduled_time": "2026-09-02T01:30:00Z",
      "created_at": "2026-08-20T10:00:00Z",
      "last_updated": "2026-09-02T09:00:00Z"
    }
  ],
  "pagination": {
    "page": 0,
    "limit": 25,
    "total": 1,
    "totalPages": 1
  }
}

Response Fields

FieldTypeDescription
successbooleanWhether the operation succeeded.
dataarrayList of check-in request summaries.
data[].checkin_idstringPublic check-in identifier.
data[].booking_idnumberInternal booking identifier.
data[].pnrstringAirline record locator.
data[].originIATA airport codeOrigin airport IATA code.
data[].destinationIATA airport codeDestination airport IATA code.
data[].departure_dateISO 8601 timestampDeparture date and time.
data[].airlineIATA codeAirline IATA code.
data[].flight_numberstringFlight number.
data[].statusenum: SCHEDULED | IN_PROGRESS | COMPLETED | FAILEDCurrent normalized status.
data[].sub_statusstringDetailed sub-status.
data[].checkin_messagestringHuman-readable status explanation.
data[].missing_infoarrayList of missing information items.
data[].boarding_passesarray of HTTPS URLsBoarding-pass URLs, when available.
data[].scheduled_timeISO 8601 timestamp | nullScheduled automation time.
data[].created_atISO 8601 timestampRequest creation timestamp.
data[].last_updatedISO 8601 timestampLatest update timestamp.
paginationobjectPagination metadata.
pagination.pageintegerCurrent zero-based page.
pagination.limitintegerItems per page (1-100).
pagination.totalintegerTotal matching items.
pagination.totalPagesintegerTotal pages.

Errors

HTTP StatusMessage
400VALIDATION_ERROR: invalid page, limit, or filter value.
401Missing, invalid, disabled, or revoked API key.
429Rate limit exceeded. retryAfter is returned in seconds.