AerScheduler

AerScheduler API

Everything the app and the console can do, your own software can do too — book aircraft, close flights out, invoice them, and pull the numbers back. 141 endpoints, described in OpenAPI 3.1, included on every plan.

This is the same API our own clients use. There is no separate “public” tier and no second implementation to fall behind.

Auth
Bearer token, 30-day expiry
Format
JSON over HTTPS, OpenAPI 3.1
Limits
300/min per account
Version
v1.0.0

Quickstart

Two calls to your first result: sign in for a token, then use it. The token is good for 30 days, so an integration signs in rarely rather than on every request.

1 — Sign in
curl -s -X POST https://api.aerscheduler.com/auth \
  -H 'Content-Type: application/json' \
  -d '{"email":"you@yourschool.com","password":"…"}'

# → { "auth": { "accessToken": "eyJ…" }, "data": { … } }
2 — List your aircraft
curl -s https://api.aerscheduler.com/resources/planes \
  -H "Authorization: Bearer $AERSCHEDULER_TOKEN"

# → { "data": [ { "id": 12, "name": "N12345", … } ] }
3 — Book one
curl -s -X POST https://api.aerscheduler.com/reservations \
  -H "Authorization: Bearer $AERSCHEDULER_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{
    "title": "Discovery flight",
    "type": "dual",
    "start": "2026-08-04T15:00:00-06:00",
    "end":   "2026-08-04T17:00:00-06:00",
    "timeZoneName": "America/Denver",
    "resource": { "id": 12 }
  }'

Conventions

These hold across the whole API, so you can write one client wrapper and stop thinking about it.

Responses are wrapped

A body-bearing success is { "data": … }. An error is { "message": "…" }, written to be safe to show a user. Three endpoints break this on purpose and say so: /health, the CSV export, and the OAuth redirects.

401 and 403 mean different things

401 means the token is dead — get a new one. 403 means the token is fine and the answer is still no. Retrying a 403 will never help.

Your organization is implied

The token carries it. You never pass an organization id for your own org, and you can never read another organization’s records.

Money is in cents

Always an integer, never a float. A $165/hr wet rate is 16500.

Times carry an offset

Send start and end with an explicit UTC offset or Z. A bare local datetime is rejected rather than silently booked in the server’s zone — see below.

Parse leniently

New endpoints and new fields on existing responses ship without notice. Ignore fields you don’t recognise; anything that would break a working integration gets a new major version first.

Time zones, and why bookings are strict about them

Scheduling is anchored to the airport’s time zone, not the caller’s device. A booking made for 7am at the field is 7am at the field whether the person making it is in the office, at home, or in another state.

So start and end must carry an explicit UTC offset or Z. A bare 2026-08-04T15:00:00is rejected outright: it would be read in the server’s zone and silently book a different instant than the person picked, and nothing downstream would notice. Send timeZoneName — an IANA zone like America/Denver — alongside, so the booking records which zone it was made in.

Who can book what

Which reservation type a caller may create depends on the roles they hold. Roles are additive, so an instructor who is also a technician gets both sets.

RoleMay create
owner, admin, dispatchersolo, dual, ground, guest, sim, rental, maintenance
instructorsolo, dual, ground, guest, sim
studentsolo, dual, ground, sim
renterrental
technicianmaintenance

Rate limits

Limits are applied per signed-in account, not per IP — a whole school behind one office address does not share one budget.

Per account300 requests / minute, 5,000 / hour
Unauthenticated100 requests / 5 minutes, per IP
Sign-in, password resetTighter still — per IP and per email address

Every response carries RateLimit-Limit, RateLimit-Remaining, and RateLimit-Reset. A 429 carries Retry-After in seconds — honour it rather than retrying on a fixed interval.

Pagination — what to know before you build

There isn’t any yet. Every collection returns its full set, so a large school will get a large response.

Lean on the date-ranged endpoints for anything that grows without bound: GET /reservations requires a window for exactly this reason, and the reporting engine takes one too. Cursor pagination is planned and will be additive — an unpaginated request will keep returning what it returns today.

Common questions

Does AerScheduler have an API?
Yes. AerScheduler exposes a REST API covering 141 endpoints across scheduling, aircraft, maintenance, billing, members, and reporting. It is the same API the AerScheduler mobile app and web console use — there is no separate public tier and no second implementation to fall behind.
Is the API included in the price?
Yes. API access is included on every plan at no extra cost. There is no enterprise tier and no per-call charge.
How do I authenticate with the AerScheduler API?
POST your email and password to /auth and you get back a bearer token valid for 30 days. Send it as an Authorization: Bearer header on every other request. The token is scoped to one organization; POST /organizations/switch/{orgId} returns a token for another.
Is there an OpenAPI specification?
Yes. The machine-readable OpenAPI 3.1 document is published at https://api.aerscheduler.com/openapi.json and needs no authentication to read. Point any standard client generator at it to produce an SDK in your language.
Are there rate limits?
Yes, and they are applied per signed-in account rather than per IP, so a whole school behind one office address does not share one budget. 300 requests a minute and 5,000 an hour per account. Every response carries RateLimit-Remaining, and a 429 carries Retry-After.
Can I use the API to build a booking page on my own website?
Yes. Availability, resources, and reservations are all exposed, so you can check an aircraft's free windows and create a booking from your own front end.

Building something?

Tell us what you’re integrating and we’ll help. If an endpoint you need doesn’t exist yet, we’d rather hear it now than read about it later.