Members

People and the roles they hold.

37 endpoints · base URL https://api.aerscheduler.com

get/orgUsers

List members

Every member of your organization with the roles they hold. This is the endpoint for “who is in this organization”, including “who are the instructors” , pass the role as a filter rather than looking for a per-role endpoint.

Role filters combine as OR: ?instructor=true&student=true returns anyone holding either. Roles are additive, so one person can come back under several filters.

Query parameters

qstringFree-text filter. Matches the fields a person would search on.
ownerbooleanSet true to include members holding the owner role.
adminbooleanSet true to include members holding the admin role.
dispatcherbooleanSet true to include members holding the dispatcher role.
instructorbooleanSet true to include members holding the instructor role.
studentbooleanSet true to include members holding the student role.
renterbooleanSet true to include members holding the renter role.
technicianbooleanSet true to include members holding the technician role.
noRolesbooleanSet true to return only members with no role at all , the people who have joined but not been set up yet. Overrides every other role filter.
groupIdstringComma-separated member-group ids to filter by.
groundedbooleanFilter by grounded state.
archivedbooleanArchived members , people the school has retired from the roster , are left out by default. Set true to list them instead of the current members. There is no value that returns both.
approvedForResourceIdintegerAn aircraft id. Every member returned carries approvedForResource, saying whether they are checked out on that aircraft , so you can read approvals for a whole roster in one request instead of one per person.
approvedbooleanWith approvedForResourceId, set true to return only the members approved on that aircraft rather than annotating them all. Ignored on its own.
limitintegerRows to return, 1,1000. Defaults to 1000; a larger value is clamped rather than rejected.
offsetintegerRows to skip, for paging. Defaults to 0.
sortstringField to order by before paging, as a dot path into the row , total, user.firstName. Omit to keep the endpoint's own order. Numbers and ISO timestamps order as numbers and instants, not as text, and empty values always sort last regardless of direction. Ordering happens before the page is cut, so it orders the whole collection rather than the page you are holding.
order"asc" | "desc"asc (default) or desc. Only meaningful with sort.

Responses

200OKThe members.{ data: OrganizationUser[] }
401UnauthorizedNo token, an expired token, or a malformed one. Sign in again.
403ForbiddenAuthenticated, but not allowed to do this.
429Too Many RequestsRate limited. Retry-After says how long to wait.
Example request
curl https://api.aerscheduler.com/orgUsers \
  -H "Authorization: Bearer $AERSCHEDULER_KEY"
get/users

List users

Every person in your organization, as User records. Prefer GET /orgUsers, which carries roles.

Query parameters

limitintegerRows to return, 1,1000. Defaults to 1000; a larger value is clamped rather than rejected.
offsetintegerRows to skip, for paging. Defaults to 0.
sortstringField to order by before paging, as a dot path into the row , total, user.firstName. Omit to keep the endpoint's own order. Numbers and ISO timestamps order as numbers and instants, not as text, and empty values always sort last regardless of direction. Ordering happens before the page is cut, so it orders the whole collection rather than the page you are holding.
order"asc" | "desc"asc (default) or desc. Only meaningful with sort.

Responses

200OKThe users.{ data: User[] }
401UnauthorizedNo token, an expired token, or a malformed one. Sign in again.
403ForbiddenAuthenticated, but not allowed to do this.
429Too Many RequestsRate limited. Retry-After says how long to wait.
Example request
curl https://api.aerscheduler.com/users \
  -H "Authorization: Bearer $AERSCHEDULER_KEY"
patch/users

Update your own profile

Changes your own name, phone, or other profile fields.

Request body

Fields to change.

namestring
phonestring

Responses

200OKUpdated.
401UnauthorizedNo token, an expired token, or a malformed one. Sign in again.
403ForbiddenAuthenticated, but not allowed to do this.
429Too Many RequestsRate limited. Retry-After says how long to wait.
Example request
curl -X PATCH https://api.aerscheduler.com/users \
  -H "Authorization: Bearer $AERSCHEDULER_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name":"…","phone":"…"}'
delete/users

Delete your own account

Soft-deletes the signed-in account.

Responses

204No ContentSuccess. No body.
401UnauthorizedNo token, an expired token, or a malformed one. Sign in again.
403ForbiddenAuthenticated, but not allowed to do this.
429Too Many RequestsRate limited. Retry-After says how long to wait.
Example request
curl -X DELETE https://api.aerscheduler.com/users \
  -H "Authorization: Bearer $AERSCHEDULER_KEY"
get/orgUsers/{orgUserId}

Get a member

One membership record, with roles.

Path parameters

orgUserIdrequiredintegerThe membership id. Note this is NOT the user id.

Responses

200OKSuccess.{ data: OrganizationUser }
401UnauthorizedNo token, an expired token, or a malformed one. Sign in again.
403ForbiddenAuthenticated, but not allowed to do this.
404Not FoundNo such member in your organization.
429Too Many RequestsRate limited. Retry-After says how long to wait.
Example request
curl https://api.aerscheduler.com/orgUsers/:orgUserId \
  -H "Authorization: Bearer $AERSCHEDULER_KEY"
get/orgUsers/preferences

Get your notification preferences

What you have opted into for this organization: email, push, and SMS masters plus per-category switches. SMS also requires a verified US mobile via /users/sms.

Responses

200OKSuccess.{ data: object }
401UnauthorizedNo token, an expired token, or a malformed one. Sign in again.
403ForbiddenAuthenticated, but not allowed to do this.
429Too Many RequestsRate limited. Retry-After says how long to wait.
Example request
curl https://api.aerscheduler.com/orgUsers/preferences \
  -H "Authorization: Bearer $AERSCHEDULER_KEY"
patch/orgUsers/preferences

Update your notification preferences

Changes only the keys you send. Setting smsEnabled: true requires a verified US mobile.

Responses

200OKSuccess.{ data: object }
401UnauthorizedNo token, an expired token, or a malformed one. Sign in again.
403ForbiddenAuthenticated, but not allowed to do this.
429Too Many RequestsRate limited. Retry-After says how long to wait.
Example request
curl -X PATCH https://api.aerscheduler.com/orgUsers/preferences \
  -H "Authorization: Bearer $AERSCHEDULER_KEY"
get/users/{id}

Get a user

One person in your organization.

Path parameters

idrequiredintegerThe user id.

Responses

200OKSuccess.{ data: User }
401UnauthorizedNo token, an expired token, or a malformed one. Sign in again.
403ForbiddenAuthenticated, but not allowed to do this.
404Not FoundNo such user in your organization.
429Too Many RequestsRate limited. Retry-After says how long to wait.
Example request
curl https://api.aerscheduler.com/users/:id \
  -H "Authorization: Bearer $AERSCHEDULER_KEY"
patch/users/mechanicCertificate

Save your mechanic certificate

Stores the caller's own FAA certificate on their membership at the active school, so signing an inspection off can prefill it rather than asking for six exact characters every time.

Scoped to the caller: there is no id in the path. Send an empty string to clear one entered wrongly. The certificate on a compliance record is snapshotted at signature and is not changed by editing this.

Request body

The certificate.

mechanicCertificateNumberstringThe number as printed.
mechanicCertificateTypestringA&P, IA, or repair station.

Responses

200OKSuccess.{ data: object }
400Bad RequestValidation failed.
401UnauthorizedNo token, an expired token, or a malformed one. Sign in again.
403ForbiddenAuthenticated, but not allowed to do this.
429Too Many RequestsRate limited. Retry-After says how long to wait.
Example request
curl -X PATCH https://api.aerscheduler.com/users/mechanicCertificate \
  -H "Authorization: Bearer $AERSCHEDULER_KEY" \
  -H "Content-Type: application/json" \
  -d '{"mechanicCertificateNumber":"3421887","mechanicCertificateType":"IA"}'
get/users/sms

Get your SMS opt-in status

Whether your mobile is verified for transactional SMS. SMS is US mobile numbers only. When available is false, the product kill switch is off (SMS_NOTIFICATIONS_ENABLED) and clients should hide SMS UI. Category toggles still live on GET/PATCH /orgUsers/preferences (smsEnabled and smsNotificationPreferences).

Responses

200OKSuccess.{ data: object }
401UnauthorizedNo token, an expired token, or a malformed one. Sign in again.
403ForbiddenAuthenticated, but not allowed to do this.
429Too Many RequestsRate limited. Retry-After says how long to wait.
Example request
curl https://api.aerscheduler.com/users/sms \
  -H "Authorization: Bearer $AERSCHEDULER_KEY"
get/orgUsers/{orgUserId}/ledger

Get a member's ledger

Account balance and append-only ledger entries for one member. Self or admin. When ledger mode is on, money-in and refunds are separate write routes under this path. ledgerEnabled tells you whether the org is in ledger billing mode; the balance is still returned when mode is off (usually 0).

Path parameters

orgUserIdrequiredintegerThe membership id.

Query parameters

qstringFree-text filter. Matches the fields a person would search on.
startDatestringStart of the window, ISO 8601. Include an offset or Z.
endDatestringEnd of the window, ISO 8601.
typestringComma-separated ledger entry types to include (topup, cash, check, other, adjustment, flight_charge, item_charge, fee, refund, reversal).
limitintegerRows of entries to return, 1–1000. Defaults to 1000.
offsetintegerEntries to skip, for paging. Defaults to 0.
sort"createdAt" | "amountCents" | "type" | "id"Order entries by createdAt, amountCents, type, or id. Defaults to createdAt.
order"asc" | "desc"asc or desc. Defaults to desc.

Responses

200OKBalance plus a page of entries.{ data: MemberLedger }
401UnauthorizedNo token, an expired token, or a malformed one. Sign in again.
403ForbiddenNot in your organization, or not allowed to view another member's ledger.
429Too Many RequestsRate limited. Retry-After says how long to wait.
Example request
curl https://api.aerscheduler.com/orgUsers/:orgUserId/ledger \
  -H "Authorization: Bearer $AERSCHEDULER_KEY"
get/orgUsers/{orgUserId}/users

Get the person behind a membership

Resolves a membership id to the underlying person. Useful when you have an orgUserId from a booking and want the account behind it , the two ids are different and are not interchangeable.

Path parameters

orgUserIdrequiredintegerThe membership id.

Responses

200OKSuccess.{ data: User }
401UnauthorizedNo token, an expired token, or a malformed one. Sign in again.
403ForbiddenThat membership is not in your organization.
429Too Many RequestsRate limited. Retry-After says how long to wait.
Example request
curl https://api.aerscheduler.com/orgUsers/:orgUserId/users \
  -H "Authorization: Bearer $AERSCHEDULER_KEY"
get/users/{userId}/approvedResources

List a member's approved resources

Which aircraft this person has been checked out on.

Path parameters

userIdrequiredintegerThe user id.

Query parameters

limitintegerRows to return, 1,1000. Defaults to 1000; a larger value is clamped rather than rejected.
offsetintegerRows to skip, for paging. Defaults to 0.
sortstringField to order by before paging, as a dot path into the row , total, user.firstName. Omit to keep the endpoint's own order. Numbers and ISO timestamps order as numbers and instants, not as text, and empty values always sort last regardless of direction. Ordering happens before the page is cut, so it orders the whole collection rather than the page you are holding.
order"asc" | "desc"asc (default) or desc. Only meaningful with sort.

Responses

200OKThe approved resources.{ data: Resource[] }
401UnauthorizedNo token, an expired token, or a malformed one. Sign in again.
403ForbiddenAuthenticated, but not allowed to do this.
429Too Many RequestsRate limited. Retry-After says how long to wait.
Example request
curl https://api.aerscheduler.com/users/:userId/approvedResources \
  -H "Authorization: Bearer $AERSCHEDULER_KEY"
get/users/{userId}/details

Get a person's contact details

Phone numbers, date of birth, address and emergency contacts.

Readable by the person themselves, an admin or dispatcher of your organization, or an instructor the person is assigned to as a student. Anyone else gets 403 , these are home phone numbers and next of kin, not roster data.

Path parameters

userIdrequiredintegerThe user id. Use your own to read your own record.

Responses

200OKSuccess.{ data: UserDetails }
401UnauthorizedNo token, an expired token, or a malformed one. Sign in again.
403ForbiddenYou are not allowed to see this person's contact details.
429Too Many RequestsRate limited. Retry-After says how long to wait.
Example request
curl https://api.aerscheduler.com/users/:userId/details \
  -H "Authorization: Bearer $AERSCHEDULER_KEY"
patch/users/{userId}/details

Update a person's contact details

Writable by the person themselves and by an admin or dispatcher , the front desk genuinely does take a corrected number over the counter. Instructors are read-only.

Every change is written to the audit trail, with phone numbers masked.

Phone numbers are normalized to E.164 and validated; an unreal number is a 400, not a silent accept. Omit a field to leave it alone; send null or "" to clear it.

Path parameters

userIdrequiredintegerThe user id.

Request body

Fields to change. All optional.

phonestringPrimary/mobile number. Any format; stored as E.164.
homePhonestring
workPhonestring
dateOfBirthstringYYYY-MM-DD. Cannot be in the future.
preferredNamestring
sexstring
defaultCountrystringISO 3166-1 alpha-2 used to read numbers sent without a country code. Defaults to US.

Responses

200OKSuccess.{ data: UserDetails }
400Bad RequestA phone number or date was not valid.
401UnauthorizedNo token, an expired token, or a malformed one. Sign in again.
403ForbiddenYou are not allowed to change this person's contact details.
429Too Many RequestsRate limited. Retry-After says how long to wait.
Example request
curl -X PATCH https://api.aerscheduler.com/users/:userId/details \
  -H "Authorization: Bearer $AERSCHEDULER_KEY" \
  -H "Content-Type: application/json" \
  -d '{"phone":"…","homePhone":"…"}'
get/users/{userId}/emergencyContacts

List a person's emergency contacts

Primary first. Same read permissions as GET /users/{userId}/details.

Path parameters

userIdrequiredintegerThe user id.

Query parameters

limitintegerRows to return, 1,1000. Defaults to 1000; a larger value is clamped rather than rejected.
offsetintegerRows to skip, for paging. Defaults to 0.
sortstringField to order by before paging, as a dot path into the row , total, user.firstName. Omit to keep the endpoint's own order. Numbers and ISO timestamps order as numbers and instants, not as text, and empty values always sort last regardless of direction. Ordering happens before the page is cut, so it orders the whole collection rather than the page you are holding.
order"asc" | "desc"asc (default) or desc. Only meaningful with sort.

Responses

200OKThe emergency contacts.{ data: EmergencyContact[] }
401UnauthorizedNo token, an expired token, or a malformed one. Sign in again.
403ForbiddenNot allowed.
429Too Many RequestsRate limited. Retry-After says how long to wait.
Example request
curl https://api.aerscheduler.com/users/:userId/emergencyContacts \
  -H "Authorization: Bearer $AERSCHEDULER_KEY"
post/users/{userId}/emergencyContacts

Add an emergency contact

name and a valid phone are required. Setting isPrimary clears it on the others.

Path parameters

userIdrequiredintegerThe user id.

Request body

The new contact.

namestring
relationshipstring
phonestringRequired. Any format; stored as E.164.
altPhonestring
emailstring
notesstring
isPrimaryboolean
sortOrderinteger
defaultCountrystringISO 3166-1 alpha-2 for numbers with no country code.

Responses

201CreatedSuccess.{ data: EmergencyContact }
400Bad RequestA name and a valid phone number are required.
401UnauthorizedNo token, an expired token, or a malformed one. Sign in again.
403ForbiddenNot allowed.
429Too Many RequestsRate limited. Retry-After says how long to wait.
Example request
curl -X POST https://api.aerscheduler.com/users/:userId/emergencyContacts \
  -H "Authorization: Bearer $AERSCHEDULER_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name":"…","relationship":"…"}'
get/users/{userId}/roles

Get a member's roles

The roles a person holds in your organization. Requires the admin role.

Path parameters

userIdrequiredintegerThe user id.

Responses

200OKSuccess.{ data: User }
401UnauthorizedNo token, an expired token, or a malformed one. Sign in again.
403ForbiddenAuthenticated, but not allowed to do this.
429Too Many RequestsRate limited. Retry-After says how long to wait.
Example request
curl https://api.aerscheduler.com/users/:userId/roles \
  -H "Authorization: Bearer $AERSCHEDULER_KEY"
patch/users/{userId}/roles

Set a member's roles

Replaces the whole role set , send every role you want them to keep, not just the change. Requires the admin role.

Two invariants are enforced: an organization must always have at least one owner and at least one administrator, and an owner must also be an administrator.

Path parameters

userIdrequiredintegerThe user id.

Request body

The complete role set.

ownerboolean
adminboolean
dispatcherboolean
instructorboolean
studentboolean
renterboolean
technicianboolean

Responses

200OKRoles updated.
400Bad RequestThe change would leave the organization without an owner or an administrator.
401UnauthorizedNo token, an expired token, or a malformed one. Sign in again.
403ForbiddenAuthenticated, but not allowed to do this.
429Too Many RequestsRate limited. Retry-After says how long to wait.
Example request
curl -X PATCH https://api.aerscheduler.com/users/:userId/roles \
  -H "Authorization: Bearer $AERSCHEDULER_KEY" \
  -H "Content-Type: application/json" \
  -d '{"owner":true,"admin":true}'
post/users/sms/opt-out

Opt out of SMS

Turns off SMS for your account. Equivalent to replying STOP to an AerScheduler text.

Responses

200OKSuccess.{ data: object }
401UnauthorizedNo token, an expired token, or a malformed one. Sign in again.
403ForbiddenAuthenticated, but not allowed to do this.
429Too Many RequestsRate limited. Retry-After says how long to wait.
Example request
curl -X POST https://api.aerscheduler.com/users/sms/opt-out \
  -H "Authorization: Bearer $AERSCHEDULER_KEY"
get/orgUsers/{orgUserId}/ledger/auto-refill

Get ledger auto-refill

The member's auto-refill (Auto Pay) settings. Missing row returns defaults with enabled: false. Self or admin.

Path parameters

orgUserIdrequiredintegerThe membership id.

Responses

200OKSuccess.{ data: LedgerAutoRefill }
401UnauthorizedNo token, an expired token, or a malformed one. Sign in again.
403ForbiddenAuthenticated, but not allowed to do this.
429Too Many RequestsRate limited. Retry-After says how long to wait.
Example request
curl https://api.aerscheduler.com/orgUsers/:orgUserId/ledger/auto-refill \
  -H "Authorization: Bearer $AERSCHEDULER_KEY"
patch/orgUsers/{orgUserId}/ledger/auto-refill

Update ledger auto-refill

Create or update auto-refill. Charges the default saved card on the cadence when ledger mode is on. Self or admin. Three modes: under_threshold, pay_balance, fixed_amount. Cadence daily or monthly (day 1–28). The hourly cron runs in the organization's time zone after runHourLocal (default 4).

Path parameters

orgUserIdrequiredintegerThe membership id.

Request body

Auto-refill patch. Send any subset.

enabledboolean
mode"under_threshold" | "pay_balance" | "fixed_amount"
thresholdCentsinteger
chargeCentsinteger
cadence"daily" | "monthly"
monthlyDayinteger
runHourLocalinteger

Responses

200OKSaved settings.{ data: LedgerAutoRefill }
400Bad RequestValidation failed or ledger mode is off.
401UnauthorizedNo token, an expired token, or a malformed one. Sign in again.
403ForbiddenAuthenticated, but not allowed to do this.
429Too Many RequestsRate limited. Retry-After says how long to wait.
Example request
curl -X PATCH https://api.aerscheduler.com/orgUsers/:orgUserId/ledger/auto-refill \
  -H "Authorization: Bearer $AERSCHEDULER_KEY" \
  -H "Content-Type: application/json" \
  -d '{"enabled":true,"mode":"under_threshold"}'
post/orgUsers/{orgUserId}/ledger/entries

Post an admin ledger credit or adjustment

Desk money-in without Stripe: cash, check, or other (positive cents), or adjustment (signed). Admin only. Memo required. Ledger mode must be on.

Path parameters

orgUserIdrequiredintegerThe membership id.

Request body

Credit or adjustment.

amountCentsrequiredintegerPositive for credits; signed for adjustments.
typerequired"cash" | "check" | "other" | "adjustment"
memorequiredstringRequired note (check #, reason, …).

Responses

201CreatedPosted entry and new balance.{ data: object }
400Bad RequestNot an admin, ledger off, or validation failed.
401UnauthorizedNo token, an expired token, or a malformed one. Sign in again.
403ForbiddenAuthenticated, but not allowed to do this.
429Too Many RequestsRate limited. Retry-After says how long to wait.
Example request
curl -X POST https://api.aerscheduler.com/orgUsers/:orgUserId/ledger/entries \
  -H "Authorization: Bearer $AERSCHEDULER_KEY" \
  -H "Content-Type: application/json" \
  -d '{"amountCents":1,"type":"cash","memo":"…"}'
get/orgUsers/{orgUserId}/ledger/refundable

List refundable top-ups

Current balance plus card top-ups with remaining refundable cents. Self or admin. Used by the desk Refund UI.

Path parameters

orgUserIdrequiredintegerThe membership id.

Responses

200OKSuccess.{ data: LedgerRefundable }
401UnauthorizedNo token, an expired token, or a malformed one. Sign in again.
403ForbiddenNot in your organization, or not allowed.
429Too Many RequestsRate limited. Retry-After says how long to wait.
Example request
curl https://api.aerscheduler.com/orgUsers/:orgUserId/ledger/refundable \
  -H "Authorization: Bearer $AERSCHEDULER_KEY"
post/orgUsers/{orgUserId}/ledger/refunds

Refund from a member ledger

First-class refund. method: stripe refunds a top-up PaymentIntent then posts a refund entry; check_cash posts the ledger entry only (school pays out of band). Admin only. Capped by balance and, for Stripe, by that top-up's remaining refundable cents.

Path parameters

orgUserIdrequiredintegerThe membership id.

Request body

Refund request.

amountCentsrequiredintegerPositive cents to remove from the account.
methodrequired"stripe" | "check_cash"
memorequiredstringRequired. Check # / reason.
topupEntryIdintegerRequired for stripe; optional provenance for check_cash.
idempotencyKeystringOptional Stripe idempotency key for stripe refunds.

Responses

201CreatedRefund posted.{ data: object }
400Bad RequestCap exceeded, Stripe rejected, ledger off, or validation failed.
401UnauthorizedNo token, an expired token, or a malformed one. Sign in again.
403ForbiddenAuthenticated, but not allowed to do this.
429Too Many RequestsRate limited. Retry-After says how long to wait.
Example request
curl -X POST https://api.aerscheduler.com/orgUsers/:orgUserId/ledger/refunds \
  -H "Authorization: Bearer $AERSCHEDULER_KEY" \
  -H "Content-Type: application/json" \
  -d '{"amountCents":1,"method":"stripe","memo":"…"}'
get/orgUsers/{orgUserId}/ledger/statement

Get a member ledger statement

Inclusive period statement: opening balance (sum of entries before start), period entries oldest-first with running balance, and closing. Self or admin. Period must be under two years and under 5000 entries.

Path parameters

orgUserIdrequiredintegerThe membership id.

Query parameters

startrequiredstringInclusive period start. ISO 8601 instant, or YYYY-MM-DD for the start of that calendar day in the school's time zone (falls back to the viewer zone, then UTC).
endrequiredstringInclusive period end. ISO 8601 instant, or YYYY-MM-DD for the end of that calendar day in the school's time zone (falls back to the viewer zone, then UTC).

Responses

200OKStatement for the requested period.{ data: LedgerStatement }
400Bad RequestInvalid range, or too many rows.
401UnauthorizedNo token, an expired token, or a malformed one. Sign in again.
403ForbiddenNot allowed to view this member's ledger.
429Too Many RequestsRate limited. Retry-After says how long to wait.
Example request
curl https://api.aerscheduler.com/orgUsers/:orgUserId/ledger/statement?start=…&end=… \
  -H "Authorization: Bearer $AERSCHEDULER_KEY"
post/orgUsers/{orgUserId}/ledger/topups

Start a ledger card top-up

Creates a PaymentIntent on the school's connected Stripe account to credit this member's ledger. Self or admin. Requires ledger mode. Minimum $1. Pass paymentMethodId to confirm immediately with a saved card (native clients); otherwise return the client secret for Stripe.js.

Path parameters

orgUserIdrequiredintegerThe membership id.

Request body

Top-up amount.

amountCentsrequiredintegerAmount in cents. Minimum 100.
paymentMethodIdstringOptional saved Stripe payment method to confirm off-session.
idempotencyKeystringOptional Stripe idempotency key.

Responses

201CreatedPaymentIntent created (and confirmed when paymentMethodId was sent).{ data: LedgerTopUpIntent }
400Bad RequestLedger off, amount too small, or Stripe rejected the charge.
401UnauthorizedNo token, an expired token, or a malformed one. Sign in again.
403ForbiddenAuthenticated, but not allowed to do this.
429Too Many RequestsRate limited. Retry-After says how long to wait.
Example request
curl -X POST https://api.aerscheduler.com/orgUsers/:orgUserId/ledger/topups \
  -H "Authorization: Bearer $AERSCHEDULER_KEY" \
  -H "Content-Type: application/json" \
  -d '{"amountCents":1}'
patch/users/{userId}/emergencyContacts/{contactId}

Update an emergency contact

Omit a field to leave it. phone may be changed but not cleared.

Path parameters

userIdrequiredintegerThe user id.
contactIdrequiredintegerThe emergency contact id.

Request body

Fields to change.

namestring
relationshipstring
phonestring
altPhonestring
emailstring
notesstring
isPrimaryboolean
sortOrderinteger

Responses

200OKSuccess.{ data: EmergencyContact }
400Bad RequestA field was not valid.
401UnauthorizedNo token, an expired token, or a malformed one. Sign in again.
403ForbiddenAuthenticated, but not allowed to do this.
404Not FoundThat emergency contact doesn't exist.
429Too Many RequestsRate limited. Retry-After says how long to wait.
Example request
curl -X PATCH https://api.aerscheduler.com/users/:userId/emergencyContacts/:contactId \
  -H "Authorization: Bearer $AERSCHEDULER_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name":"…","relationship":"…"}'
delete/users/{userId}/emergencyContacts/{contactId}

Remove an emergency contact

Soft-deletes it.

Path parameters

userIdrequiredintegerThe user id.
contactIdrequiredintegerThe emergency contact id.

Responses

204No ContentSuccess. No body.
401UnauthorizedNo token, an expired token, or a malformed one. Sign in again.
403ForbiddenAuthenticated, but not allowed to do this.
404Not FoundThat emergency contact doesn't exist.
429Too Many RequestsRate limited. Retry-After says how long to wait.
Example request
curl -X DELETE https://api.aerscheduler.com/users/:userId/emergencyContacts/:contactId \
  -H "Authorization: Bearer $AERSCHEDULER_KEY"
patch/users/{userId}/orgUser/archive

Archive or restore a member

Retires somebody from the roster, or brings them back. Requires the admin role , a dispatcher cannot.

An archived member is not notified, ever , no email, no push, no in-app notice. They are left out of GET /orgUsers unless you pass archived=true (which is also how you list them again), and they cannot be added to a booking. Nothing is deleted: their flights, invoices and history are untouched, and restoring them is the same call with false.

Use this rather than grounding to tidy a roster. Grounding is a live restriction and emails the member, so grounding a batch of people who stopped flying years ago sends each of them an unexpected notice.

Path parameters

userIdrequiredintegerThe user id , not the membership id.

Request body

Whether the member should be archived.

archivedrequiredboolean

Responses

200OKSuccess.{ data: User }
400Bad Requestarchived was missing or not a boolean, or you tried to archive your own membership.
401UnauthorizedNo token, an expired token, or a malformed one. Sign in again.
403ForbiddenYou are not an owner or admin of this organization, or that person is not a member of it.
429Too Many RequestsRate limited. Retry-After says how long to wait.
Example request
curl -X PATCH https://api.aerscheduler.com/users/:userId/orgUser/archive \
  -H "Authorization: Bearer $AERSCHEDULER_KEY" \
  -H "Content-Type: application/json" \
  -d '{"archived":true}'
post/users/sms/verify/confirm

Confirm an SMS verification code

Marks the mobile as opted-in and verified when the code matches.

Request body

The code from the text.

codestring

Responses

200OKSuccess.{ data: object }
400Bad RequestCode missing, expired, or incorrect.
401UnauthorizedNo token, an expired token, or a malformed one. Sign in again.
403ForbiddenAuthenticated, but not allowed to do this.
429Too Many RequestsRate limited. Retry-After says how long to wait.
Example request
curl -X POST https://api.aerscheduler.com/users/sms/verify/confirm \
  -H "Authorization: Bearer $AERSCHEDULER_KEY" \
  -H "Content-Type: application/json" \
  -d '{"code":"123456"}'
post/users/sms/verify/start

Send an SMS verification code

Texts a one-time code to the US mobile on your profile. Required before smsEnabled can be turned on.

Responses

200OKSuccess.{ data: object }
400Bad RequestNo US mobile on file, or the number cannot receive SMS.
401UnauthorizedNo token, an expired token, or a malformed one. Sign in again.
403ForbiddenAuthenticated, but not allowed to do this.
429Too Many RequestsRate limited. Retry-After says how long to wait.
Example request
curl -X POST https://api.aerscheduler.com/users/sms/verify/start \
  -H "Authorization: Bearer $AERSCHEDULER_KEY"
post/orgUsers/{orgUserId}/ledger/statement/email

Email a member ledger statement

Sends the same period statement to the member's email. Self or admin. Not a Stripe invoice and not synced to QuickBooks.

Path parameters

orgUserIdrequiredintegerThe membership id.

Request body

Statement period.

startrequiredstringInclusive period start. ISO 8601 instant, or YYYY-MM-DD for the start of that calendar day in the school's time zone (falls back to the viewer zone, then UTC).
endrequiredstringInclusive period end. ISO 8601 instant, or YYYY-MM-DD for the end of that calendar day in the school's time zone (falls back to the viewer zone, then UTC).
periodLabelstringOptional YYYY-MM-DD to YYYY-MM-DD printed in the email. Send the calendar days the member picked so the subject matches the school's days, not a UTC slice of instants.

Responses

200OKEmail queued.{ data: object }
400Bad RequestInvalid range, or no email on file.
401UnauthorizedNo token, an expired token, or a malformed one. Sign in again.
403ForbiddenNot allowed to email this member's statement.
429Too Many RequestsRate limited. Retry-After says how long to wait.
500Server ErrorThe statement email could not be sent.
Example request
curl -X POST https://api.aerscheduler.com/orgUsers/:orgUserId/ledger/statement/email \
  -H "Authorization: Bearer $AERSCHEDULER_KEY" \
  -H "Content-Type: application/json" \
  -d '{"start":"2026-08-04T15:00:00-06:00","end":"2026-08-04T15:00:00-06:00"}'
post/orgUsers/{orgUserId}/ledger/topups/confirm

Confirm a ledger card top-up

After Stripe.js confirms the PaymentIntent, post the credit immediately so Home and Billing do not wait on payment_intent.succeeded. Self or admin. Idempotent with the webhook via the PaymentIntent id.

Path parameters

orgUserIdrequiredintegerThe membership id.

Request body

Confirmed PaymentIntent.

paymentIntentIdrequiredstringStripe PaymentIntent id from the top-up create response.

Responses

200OKCredit posted (or already posted) and current balance.{ data: LedgerTopUpConfirm }
400Bad RequestLedger off, PI not succeeded, or not this member's top-up.
401UnauthorizedNo token, an expired token, or a malformed one. Sign in again.
403ForbiddenAuthenticated, but not allowed to do this.
429Too Many RequestsRate limited. Retry-After says how long to wait.
Example request
curl -X POST https://api.aerscheduler.com/orgUsers/:orgUserId/ledger/topups/confirm \
  -H "Authorization: Bearer $AERSCHEDULER_KEY" \
  -H "Content-Type: application/json" \
  -d '{"paymentIntentId":"…"}'
post/orgUsers/{orgUserId}/ledger/entries/{entryId}/reassign

Reassign a flight charge

Moves a flight_charge to another member by reversing the original and posting a new charge (never UPDATE). Admin only. Updates the reservation payer stake link.

Path parameters

orgUserIdrequiredintegerCurrent member who holds the charge.
entryIdrequiredintegerFlight charge ledger entry id.

Request body

Target member.

toOrgUserIdrequiredintegerMembership id that should own the charge.
memostringOptional note on the reversal / new charge.

Responses

201CreatedReversal on the original member and new charge on the target.{ data: object }
400Bad RequestNot an admin, not a flight charge, already reversed, or validation failed.
401UnauthorizedNo token, an expired token, or a malformed one. Sign in again.
403ForbiddenAuthenticated, but not allowed to do this.
404Not FoundEntry not found.
429Too Many RequestsRate limited. Retry-After says how long to wait.
Example request
curl -X POST https://api.aerscheduler.com/orgUsers/:orgUserId/ledger/entries/:entryId/reassign \
  -H "Authorization: Bearer $AERSCHEDULER_KEY" \
  -H "Content-Type: application/json" \
  -d '{"toOrgUserId":1}'
get/orgUsers/{orgUserId}/ledger/entries/{entryId}/receipt

Get a ledger charge receipt

Receipt for a flight_charge, item_charge, or fee entry: line items, member, org, and optional reservation summary. Self or admin. Replaces Stripe PDF in ledger mode.

Path parameters

orgUserIdrequiredintegerThe membership id.
entryIdrequiredintegerLedger entry id.

Responses

200OKSuccess.{ data: LedgerReceipt }
400Bad RequestNot a charge entry, or not allowed.
401UnauthorizedNo token, an expired token, or a malformed one. Sign in again.
403ForbiddenAuthenticated, but not allowed to do this.
404Not FoundEntry not found for this member.
429Too Many RequestsRate limited. Retry-After says how long to wait.
Example request
curl https://api.aerscheduler.com/orgUsers/:orgUserId/ledger/entries/:entryId/receipt \
  -H "Authorization: Bearer $AERSCHEDULER_KEY"
post/orgUsers/{orgUserId}/ledger/entries/{entryId}/reverse

Reverse a flight charge

Posts an opposing entry that cancels a flight_charge, so the flight behind it can be corrected. Admin only.

This is the ledger's counterpart to voiding an invoice. Correcting a recorded reading is refused while live money stands against the booking, and at a ledger school the charge posts automatically the moment the last pilot enters their PIN, so the booking locks on the same tap that finishes it. Reverse the charge, correct the reading, let the crew re-confirm, and the flight bills again from the corrected hours.

Money is countered, never rewritten. The member's statement keeps the original charge and shows the reversal beside it. A charge that has already been reversed is refused, and a reversal cannot itself be reversed.

Only a flight_charge can be reversed here. Correct a top-up, a membership due or a manual adjustment by posting an adjustment of its own.

Path parameters

orgUserIdrequiredintegerMember who holds the charge.
entryIdrequiredintegerFlight charge ledger entry id.

Request body

Optionally, why.

memostringKept on the reversing entry, so the statement says why.

Responses

201CreatedThe reversing entry, and the balance it leaves.{ data: object }
400Bad RequestNot a flight charge, already reversed, or an invalid entry id.
401UnauthorizedNo token, an expired token, or a malformed one. Sign in again.
403ForbiddenAdmin only.
404Not FoundEntry not found.
429Too Many RequestsRate limited. Retry-After says how long to wait.
Example request
curl -X POST https://api.aerscheduler.com/orgUsers/:orgUserId/ledger/entries/:entryId/reverse \
  -H "Authorization: Bearer $AERSCHEDULER_KEY" \
  -H "Content-Type: application/json" \
  -d '{"memo":"…"}'