CrewBench API

REST API for operators to integrate CrewBench with external tools.

Introduction

The CrewBench External API gives your team programmatic access to your company's pilot schedule and duty request workflow. You can use it to pull schedule data into third-party dispatch tools, read pending crew requests, and approve, decline, or modify them — the same actions available in the web and mobile apps.

The API uses REST conventions, accepts and returns JSON, and is authenticated with long-lived API keys you generate in your settings.

Authentication

Every request must include your API key in the Authorization header as a Bearer token.

Authorization: Bearer cbk_your_api_key_here

Requests without a valid key, or using a revoked key, receive a 401 Unauthorized response.

Generating API Keys

To create an API key:

Keep keys secret. Your API key grants full read and write access to your company's data. Do not commit it to version control or share it in plain text.

Base URL & Versioning

All endpoints are prefixed with:

https://crewbench.io/api/v1/external

The current version is v1. The version is included in the URL; breaking changes will be released under a new version.

GET /schedule

Returns all active pilots in your company along with their duty schedule for the requested date range.

GET /api/v1/external/schedule

Query Parameters

ParameterTypeRequiredDescription
start_date string Optional Start of the date range. Format: YYYY-MM-DD. Defaults to today.
end_date string Optional End of the date range. Format: YYYY-MM-DD. Defaults to today + 30 days.

Example Request

curl -X GET "https://crewbench.io/api/v1/external/schedule?start_date=2026-10-01&end_date=2026-10-31" \
  -H "Authorization: Bearer cbk_your_api_key"

Example Response

{
  "schedule": [
    {
      "id": 42,
      "name": "John Smith",
      "role": "Captain",
      "ioe": false,
      "check_airman": true,
      "duty_days": [
        {
          "date": "2026-10-05",
          "duty_code": "ON",
          "label": "On Duty",
          "color": "#2563EB"
        }
      ]
    },
    {
      "id": 43,
      "name": "Sarah Lee",
      "role": "First Officer",
      "ioe": true,
      "check_airman": false,
      "duty_days": []
    }
  ],
  "start_date": "2026-10-01",
  "end_date": "2026-10-31"
}

Pilot fields

FieldTypeDescription
idintegerPilot's unique ID in CrewBench.
namestringFull name.
rolestringOne of: Captain, First Officer, Flight Attendant.
ioebooleantrue if the pilot is currently on Initial Operating Experience.
check_airmanbooleantrue if the pilot is a Check Airman.
duty_daysarrayDuty assignments within the requested date range.

GET /duty_requests

Returns all pending duty requests, regardless of who initiated them. This includes both crew-initiated requests (pilot asking the operator for a duty assignment) and operator-initiated requests (operator asking a pilot to accept a duty assignment).

Use the requires_action field to distinguish between the two: crew-initiated requests require you to approve, decline, or modify them; operator-initiated requests are awaiting the pilot's response and no action is needed from you.

GET /api/v1/external/duty_requests

Example Request

curl -X GET "https://crewbench.io/api/v1/external/duty_requests" \
  -H "Authorization: Bearer cbk_your_api_key"

Example Response

{
  "duty_requests": [
    {
      "id": 99,
      "pilot_name": "Jane Doe",
      "bench_pilot_id": 42,
      "duty_code": "OFF",
      "duty_code_label": "Day Off",
      "dates": ["2026-10-10", "2026-10-11"],
      "initiated_by": "crew",
      "requires_action": true,
      "pilot_message": "Family event",
      "operator_message": null,
      "created_at": "2026-10-03T14:22:00Z"
    },
    {
      "id": 100,
      "pilot_name": "John Smith",
      "bench_pilot_id": 43,
      "duty_code": "ON",
      "duty_code_label": "On Duty",
      "dates": ["2026-10-15"],
      "initiated_by": "operator",
      "requires_action": false,
      "pilot_message": null,
      "operator_message": "We need you on the 15th.",
      "created_at": "2026-10-04T09:10:00Z"
    }
  ]
}

Response fields

FieldTypeDescription
idintegerUnique ID of the duty request.
pilot_namestringFull name of the pilot.
bench_pilot_idintegerPilot's unique ID in CrewBench.
duty_codestringShort duty code (e.g., OFF).
duty_code_labelstringHuman-readable duty code label (e.g., Day Off).
datesarray of stringsRequested dates in YYYY-MM-DD format.
initiated_bystringcrew — pilot submitted this request; operator — your team sent this request to the pilot.
requires_actionbooleantrue for crew-initiated requests (you need to approve, decline, or modify); false for operator-initiated requests (awaiting pilot response).
pilot_messagestring or nullMessage from the pilot. Present on crew-initiated requests.
operator_messagestring or nullMessage from your team. Present on operator-initiated requests.
created_atstring (ISO 8601)When the request was created.

POST /duty_requests/:id/approve

Approve a pending crew-submitted duty request. The request status is set to confirmed. Only applies to crew-initiated requests (requires_action: true).

POST /api/v1/external/duty_requests/:id/approve

Path Parameters

ParameterTypeRequiredDescription
idintegerRequiredThe ID of the duty request to approve.

Request Body (JSON)

FieldTypeRequiredDescription
messagestringOptionalA message sent to the pilot with the decision.

Example Request

curl -X POST "https://crewbench.io/api/v1/external/duty_requests/99/approve" \
  -H "Authorization: Bearer cbk_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{"message": "Approved. Enjoy your days off."}'

Example Response

{ "success": true }

POST /duty_requests/:id/decline

Decline a pending crew-submitted duty request. Only applies to crew-initiated requests (requires_action: true).

POST /api/v1/external/duty_requests/:id/decline

Request Body (JSON)

FieldTypeRequiredDescription
messagestringOptionalExplanation sent to the pilot.

Example Request

curl -X POST "https://crewbench.io/api/v1/external/duty_requests/99/decline" \
  -H "Authorization: Bearer cbk_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{"message": "We need full coverage that week."}'

Example Response

{ "success": true }

POST /duty_requests/:id/modify

Partially approve a crew-initiated request by specifying which of the requested dates are approved. Only applies to crew-initiated requests (requires_action: true).

POST /api/v1/external/duty_requests/:id/modify

Request Body (JSON)

FieldTypeRequiredDescription
approved_datesarray of stringsRequiredThe subset of dates to approve. Format: YYYY-MM-DD. Must be non-empty.
messagestringOptionalExplanation sent to the pilot.

Example Request

curl -X POST "https://crewbench.io/api/v1/external/duty_requests/99/modify" \
  -H "Authorization: Bearer cbk_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{"approved_dates": ["2026-10-10"], "message": "Only the 10th is possible."}'

Example Response

{ "success": true }

Error Responses

All errors return a JSON body with an error field describing the problem.

{ "error": "Unauthorized" }
StatusMeaning
401 Missing, invalid, or revoked API key.
404 The requested resource was not found, or belongs to a different operator.
422 Invalid parameters (e.g., missing approved_dates on a modify request, or an unparseable date string).
429 Rate limit exceeded. See below.

Rate Limits

The API is rate-limited to 60 requests per minute per API key. If you exceed this limit, you will receive a 429 Too Many Requests response. Wait one minute before retrying.