Members
People and the roles they hold.
37 endpoints · base URL https://api.aerscheduler.com
/orgUsersList 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
q | string | Free-text filter. Matches the fields a person would search on. |
owner | boolean | Set true to include members holding the owner role. |
admin | boolean | Set true to include members holding the admin role. |
dispatcher | boolean | Set true to include members holding the dispatcher role. |
instructor | boolean | Set true to include members holding the instructor role. |
student | boolean | Set true to include members holding the student role. |
renter | boolean | Set true to include members holding the renter role. |
technician | boolean | Set true to include members holding the technician role. |
noRoles | boolean | Set 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. |
groupId | string | Comma-separated member-group ids to filter by. |
grounded | boolean | Filter by grounded state. |
archived | boolean | Archived 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. |
approvedForResourceId | integer | An 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. |
approved | boolean | With approvedForResourceId, set true to return only the members approved on that aircraft rather than annotating them all. Ignored on its own. |
limit | integer | Rows to return, 1,1000. Defaults to 1000; a larger value is clamped rather than rejected. |
offset | integer | Rows to skip, for paging. Defaults to 0. |
sort | string | Field 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
200 | OK | The members.→ { data: OrganizationUser[] } |
401 | Unauthorized | No token, an expired token, or a malformed one. Sign in again. |
403 | Forbidden | Authenticated, but not allowed to do this. |
429 | Too Many Requests | Rate limited. Retry-After says how long to wait. |
curl https://api.aerscheduler.com/orgUsers \
-H "Authorization: Bearer $AERSCHEDULER_KEY"/usersList users
Every person in your organization, as User records. Prefer GET /orgUsers, which carries roles.
Query parameters
limit | integer | Rows to return, 1,1000. Defaults to 1000; a larger value is clamped rather than rejected. |
offset | integer | Rows to skip, for paging. Defaults to 0. |
sort | string | Field 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
200 | OK | The users.→ { data: User[] } |
401 | Unauthorized | No token, an expired token, or a malformed one. Sign in again. |
403 | Forbidden | Authenticated, but not allowed to do this. |
429 | Too Many Requests | Rate limited. Retry-After says how long to wait. |
curl https://api.aerscheduler.com/users \
-H "Authorization: Bearer $AERSCHEDULER_KEY"/usersUpdate your own profile
Changes your own name, phone, or other profile fields.
Request body
Fields to change.
name | string | |
phone | string |
Responses
200 | OK | Updated. |
401 | Unauthorized | No token, an expired token, or a malformed one. Sign in again. |
403 | Forbidden | Authenticated, but not allowed to do this. |
429 | Too Many Requests | Rate limited. Retry-After says how long to wait. |
curl -X PATCH https://api.aerscheduler.com/users \
-H "Authorization: Bearer $AERSCHEDULER_KEY" \
-H "Content-Type: application/json" \
-d '{"name":"…","phone":"…"}'/usersDelete your own account
Soft-deletes the signed-in account.
Responses
204 | No Content | Success. No body. |
401 | Unauthorized | No token, an expired token, or a malformed one. Sign in again. |
403 | Forbidden | Authenticated, but not allowed to do this. |
429 | Too Many Requests | Rate limited. Retry-After says how long to wait. |
curl -X DELETE https://api.aerscheduler.com/users \
-H "Authorization: Bearer $AERSCHEDULER_KEY"/orgUsers/{orgUserId}Get a member
One membership record, with roles.
Path parameters
orgUserIdrequired | integer | The membership id. Note this is NOT the user id. |
Responses
200 | OK | Success.→ { data: OrganizationUser } |
401 | Unauthorized | No token, an expired token, or a malformed one. Sign in again. |
403 | Forbidden | Authenticated, but not allowed to do this. |
404 | Not Found | No such member in your organization. |
429 | Too Many Requests | Rate limited. Retry-After says how long to wait. |
curl https://api.aerscheduler.com/orgUsers/:orgUserId \
-H "Authorization: Bearer $AERSCHEDULER_KEY"/orgUsers/preferencesGet 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
200 | OK | Success.→ { data: object } |
401 | Unauthorized | No token, an expired token, or a malformed one. Sign in again. |
403 | Forbidden | Authenticated, but not allowed to do this. |
429 | Too Many Requests | Rate limited. Retry-After says how long to wait. |
curl https://api.aerscheduler.com/orgUsers/preferences \
-H "Authorization: Bearer $AERSCHEDULER_KEY"/orgUsers/preferencesUpdate your notification preferences
Changes only the keys you send. Setting smsEnabled: true requires a verified US mobile.
Responses
200 | OK | Success.→ { data: object } |
401 | Unauthorized | No token, an expired token, or a malformed one. Sign in again. |
403 | Forbidden | Authenticated, but not allowed to do this. |
429 | Too Many Requests | Rate limited. Retry-After says how long to wait. |
curl -X PATCH https://api.aerscheduler.com/orgUsers/preferences \
-H "Authorization: Bearer $AERSCHEDULER_KEY"/users/{id}Get a user
One person in your organization.
Path parameters
idrequired | integer | The user id. |
Responses
200 | OK | Success.→ { data: User } |
401 | Unauthorized | No token, an expired token, or a malformed one. Sign in again. |
403 | Forbidden | Authenticated, but not allowed to do this. |
404 | Not Found | No such user in your organization. |
429 | Too Many Requests | Rate limited. Retry-After says how long to wait. |
curl https://api.aerscheduler.com/users/:id \
-H "Authorization: Bearer $AERSCHEDULER_KEY"/users/mechanicCertificateSave 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.
mechanicCertificateNumber | string | The number as printed. |
mechanicCertificateType | string | A&P, IA, or repair station. |
Responses
200 | OK | Success.→ { data: object } |
400 | Bad Request | Validation failed. |
401 | Unauthorized | No token, an expired token, or a malformed one. Sign in again. |
403 | Forbidden | Authenticated, but not allowed to do this. |
429 | Too Many Requests | Rate limited. Retry-After says how long to wait. |
curl -X PATCH https://api.aerscheduler.com/users/mechanicCertificate \
-H "Authorization: Bearer $AERSCHEDULER_KEY" \
-H "Content-Type: application/json" \
-d '{"mechanicCertificateNumber":"3421887","mechanicCertificateType":"IA"}'/users/smsGet 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
200 | OK | Success.→ { data: object } |
401 | Unauthorized | No token, an expired token, or a malformed one. Sign in again. |
403 | Forbidden | Authenticated, but not allowed to do this. |
429 | Too Many Requests | Rate limited. Retry-After says how long to wait. |
curl https://api.aerscheduler.com/users/sms \
-H "Authorization: Bearer $AERSCHEDULER_KEY"/orgUsers/{orgUserId}/ledgerGet 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
orgUserIdrequired | integer | The membership id. |
Query parameters
q | string | Free-text filter. Matches the fields a person would search on. |
startDate | string | Start of the window, ISO 8601. Include an offset or Z. |
endDate | string | End of the window, ISO 8601. |
type | string | Comma-separated ledger entry types to include (topup, cash, check, other, adjustment, flight_charge, item_charge, fee, refund, reversal). |
limit | integer | Rows of entries to return, 1–1000. Defaults to 1000. |
offset | integer | Entries 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
200 | OK | Balance plus a page of entries.→ { data: MemberLedger } |
401 | Unauthorized | No token, an expired token, or a malformed one. Sign in again. |
403 | Forbidden | Not in your organization, or not allowed to view another member's ledger. |
429 | Too Many Requests | Rate limited. Retry-After says how long to wait. |
curl https://api.aerscheduler.com/orgUsers/:orgUserId/ledger \
-H "Authorization: Bearer $AERSCHEDULER_KEY"/orgUsers/{orgUserId}/usersGet 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
orgUserIdrequired | integer | The membership id. |
Responses
200 | OK | Success.→ { data: User } |
401 | Unauthorized | No token, an expired token, or a malformed one. Sign in again. |
403 | Forbidden | That membership is not in your organization. |
429 | Too Many Requests | Rate limited. Retry-After says how long to wait. |
curl https://api.aerscheduler.com/orgUsers/:orgUserId/users \
-H "Authorization: Bearer $AERSCHEDULER_KEY"/users/{userId}/approvedResourcesList a member's approved resources
Which aircraft this person has been checked out on.
Path parameters
userIdrequired | integer | The user id. |
Query parameters
limit | integer | Rows to return, 1,1000. Defaults to 1000; a larger value is clamped rather than rejected. |
offset | integer | Rows to skip, for paging. Defaults to 0. |
sort | string | Field 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
200 | OK | The approved resources.→ { data: Resource[] } |
401 | Unauthorized | No token, an expired token, or a malformed one. Sign in again. |
403 | Forbidden | Authenticated, but not allowed to do this. |
429 | Too Many Requests | Rate limited. Retry-After says how long to wait. |
curl https://api.aerscheduler.com/users/:userId/approvedResources \
-H "Authorization: Bearer $AERSCHEDULER_KEY"/users/{userId}/detailsGet 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
userIdrequired | integer | The user id. Use your own to read your own record. |
Responses
200 | OK | Success.→ { data: UserDetails } |
401 | Unauthorized | No token, an expired token, or a malformed one. Sign in again. |
403 | Forbidden | You are not allowed to see this person's contact details. |
429 | Too Many Requests | Rate limited. Retry-After says how long to wait. |
curl https://api.aerscheduler.com/users/:userId/details \
-H "Authorization: Bearer $AERSCHEDULER_KEY"/users/{userId}/detailsUpdate 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
userIdrequired | integer | The user id. |
Request body
Fields to change. All optional.
phone | string | Primary/mobile number. Any format; stored as E.164. |
homePhone | string | |
workPhone | string | |
dateOfBirth | string | YYYY-MM-DD. Cannot be in the future. |
preferredName | string | |
sex | string | |
defaultCountry | string | ISO 3166-1 alpha-2 used to read numbers sent without a country code. Defaults to US. |
Responses
200 | OK | Success.→ { data: UserDetails } |
400 | Bad Request | A phone number or date was not valid. |
401 | Unauthorized | No token, an expired token, or a malformed one. Sign in again. |
403 | Forbidden | You are not allowed to change this person's contact details. |
429 | Too Many Requests | Rate limited. Retry-After says how long to wait. |
curl -X PATCH https://api.aerscheduler.com/users/:userId/details \
-H "Authorization: Bearer $AERSCHEDULER_KEY" \
-H "Content-Type: application/json" \
-d '{"phone":"…","homePhone":"…"}'/users/{userId}/emergencyContactsList a person's emergency contacts
Primary first. Same read permissions as GET /users/{userId}/details.
Path parameters
userIdrequired | integer | The user id. |
Query parameters
limit | integer | Rows to return, 1,1000. Defaults to 1000; a larger value is clamped rather than rejected. |
offset | integer | Rows to skip, for paging. Defaults to 0. |
sort | string | Field 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
200 | OK | The emergency contacts.→ { data: EmergencyContact[] } |
401 | Unauthorized | No token, an expired token, or a malformed one. Sign in again. |
403 | Forbidden | Not allowed. |
429 | Too Many Requests | Rate limited. Retry-After says how long to wait. |
curl https://api.aerscheduler.com/users/:userId/emergencyContacts \
-H "Authorization: Bearer $AERSCHEDULER_KEY"/users/{userId}/emergencyContactsAdd an emergency contact
name and a valid phone are required. Setting isPrimary clears it on the others.
Path parameters
userIdrequired | integer | The user id. |
Request body
The new contact.
name | string | |
relationship | string | |
phone | string | Required. Any format; stored as E.164. |
altPhone | string | |
email | string | |
notes | string | |
isPrimary | boolean | |
sortOrder | integer | |
defaultCountry | string | ISO 3166-1 alpha-2 for numbers with no country code. |
Responses
201 | Created | Success.→ { data: EmergencyContact } |
400 | Bad Request | A name and a valid phone number are required. |
401 | Unauthorized | No token, an expired token, or a malformed one. Sign in again. |
403 | Forbidden | Not allowed. |
429 | Too Many Requests | Rate limited. Retry-After says how long to wait. |
curl -X POST https://api.aerscheduler.com/users/:userId/emergencyContacts \
-H "Authorization: Bearer $AERSCHEDULER_KEY" \
-H "Content-Type: application/json" \
-d '{"name":"…","relationship":"…"}'/users/{userId}/rolesGet a member's roles
The roles a person holds in your organization. Requires the admin role.
Path parameters
userIdrequired | integer | The user id. |
Responses
200 | OK | Success.→ { data: User } |
401 | Unauthorized | No token, an expired token, or a malformed one. Sign in again. |
403 | Forbidden | Authenticated, but not allowed to do this. |
429 | Too Many Requests | Rate limited. Retry-After says how long to wait. |
curl https://api.aerscheduler.com/users/:userId/roles \
-H "Authorization: Bearer $AERSCHEDULER_KEY"/users/{userId}/rolesSet 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
userIdrequired | integer | The user id. |
Request body
The complete role set.
owner | boolean | |
admin | boolean | |
dispatcher | boolean | |
instructor | boolean | |
student | boolean | |
renter | boolean | |
technician | boolean |
Responses
200 | OK | Roles updated. |
400 | Bad Request | The change would leave the organization without an owner or an administrator. |
401 | Unauthorized | No token, an expired token, or a malformed one. Sign in again. |
403 | Forbidden | Authenticated, but not allowed to do this. |
429 | Too Many Requests | Rate limited. Retry-After says how long to wait. |
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}'/users/sms/opt-outOpt out of SMS
Turns off SMS for your account. Equivalent to replying STOP to an AerScheduler text.
Responses
200 | OK | Success.→ { data: object } |
401 | Unauthorized | No token, an expired token, or a malformed one. Sign in again. |
403 | Forbidden | Authenticated, but not allowed to do this. |
429 | Too Many Requests | Rate limited. Retry-After says how long to wait. |
curl -X POST https://api.aerscheduler.com/users/sms/opt-out \
-H "Authorization: Bearer $AERSCHEDULER_KEY"/orgUsers/{orgUserId}/ledger/auto-refillGet ledger auto-refill
The member's auto-refill (Auto Pay) settings. Missing row returns defaults with enabled: false. Self or admin.
Path parameters
orgUserIdrequired | integer | The membership id. |
Responses
200 | OK | Success.→ { data: LedgerAutoRefill } |
401 | Unauthorized | No token, an expired token, or a malformed one. Sign in again. |
403 | Forbidden | Authenticated, but not allowed to do this. |
429 | Too Many Requests | Rate limited. Retry-After says how long to wait. |
curl https://api.aerscheduler.com/orgUsers/:orgUserId/ledger/auto-refill \
-H "Authorization: Bearer $AERSCHEDULER_KEY"/orgUsers/{orgUserId}/ledger/auto-refillUpdate 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
orgUserIdrequired | integer | The membership id. |
Request body
Auto-refill patch. Send any subset.
enabled | boolean | |
mode | "under_threshold" | "pay_balance" | "fixed_amount" | |
thresholdCents | integer | |
chargeCents | integer | |
cadence | "daily" | "monthly" | |
monthlyDay | integer | |
runHourLocal | integer |
Responses
200 | OK | Saved settings.→ { data: LedgerAutoRefill } |
400 | Bad Request | Validation failed or ledger mode is off. |
401 | Unauthorized | No token, an expired token, or a malformed one. Sign in again. |
403 | Forbidden | Authenticated, but not allowed to do this. |
429 | Too Many Requests | Rate limited. Retry-After says how long to wait. |
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"}'/orgUsers/{orgUserId}/ledger/entriesPost 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
orgUserIdrequired | integer | The membership id. |
Request body
Credit or adjustment.
amountCentsrequired | integer | Positive for credits; signed for adjustments. |
typerequired | "cash" | "check" | "other" | "adjustment" | |
memorequired | string | Required note (check #, reason, …). |
Responses
201 | Created | Posted entry and new balance.→ { data: object } |
400 | Bad Request | Not an admin, ledger off, or validation failed. |
401 | Unauthorized | No token, an expired token, or a malformed one. Sign in again. |
403 | Forbidden | Authenticated, but not allowed to do this. |
429 | Too Many Requests | Rate limited. Retry-After says how long to wait. |
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":"…"}'/orgUsers/{orgUserId}/ledger/refundableList refundable top-ups
Current balance plus card top-ups with remaining refundable cents. Self or admin. Used by the desk Refund UI.
Path parameters
orgUserIdrequired | integer | The membership id. |
Responses
200 | OK | Success.→ { data: LedgerRefundable } |
401 | Unauthorized | No token, an expired token, or a malformed one. Sign in again. |
403 | Forbidden | Not in your organization, or not allowed. |
429 | Too Many Requests | Rate limited. Retry-After says how long to wait. |
curl https://api.aerscheduler.com/orgUsers/:orgUserId/ledger/refundable \
-H "Authorization: Bearer $AERSCHEDULER_KEY"/orgUsers/{orgUserId}/ledger/refundsRefund 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
orgUserIdrequired | integer | The membership id. |
Request body
Refund request.
amountCentsrequired | integer | Positive cents to remove from the account. |
methodrequired | "stripe" | "check_cash" | |
memorequired | string | Required. Check # / reason. |
topupEntryId | integer | Required for stripe; optional provenance for check_cash. |
idempotencyKey | string | Optional Stripe idempotency key for stripe refunds. |
Responses
201 | Created | Refund posted.→ { data: object } |
400 | Bad Request | Cap exceeded, Stripe rejected, ledger off, or validation failed. |
401 | Unauthorized | No token, an expired token, or a malformed one. Sign in again. |
403 | Forbidden | Authenticated, but not allowed to do this. |
429 | Too Many Requests | Rate limited. Retry-After says how long to wait. |
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":"…"}'/orgUsers/{orgUserId}/ledger/statementGet 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
orgUserIdrequired | integer | The membership id. |
Query parameters
startrequired | string | Inclusive 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). |
endrequired | string | Inclusive 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
200 | OK | Statement for the requested period.→ { data: LedgerStatement } |
400 | Bad Request | Invalid range, or too many rows. |
401 | Unauthorized | No token, an expired token, or a malformed one. Sign in again. |
403 | Forbidden | Not allowed to view this member's ledger. |
429 | Too Many Requests | Rate limited. Retry-After says how long to wait. |
curl https://api.aerscheduler.com/orgUsers/:orgUserId/ledger/statement?start=…&end=… \
-H "Authorization: Bearer $AERSCHEDULER_KEY"/orgUsers/{orgUserId}/ledger/topupsStart 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
orgUserIdrequired | integer | The membership id. |
Request body
Top-up amount.
amountCentsrequired | integer | Amount in cents. Minimum 100. |
paymentMethodId | string | Optional saved Stripe payment method to confirm off-session. |
idempotencyKey | string | Optional Stripe idempotency key. |
Responses
201 | Created | PaymentIntent created (and confirmed when paymentMethodId was sent).→ { data: LedgerTopUpIntent } |
400 | Bad Request | Ledger off, amount too small, or Stripe rejected the charge. |
401 | Unauthorized | No token, an expired token, or a malformed one. Sign in again. |
403 | Forbidden | Authenticated, but not allowed to do this. |
429 | Too Many Requests | Rate limited. Retry-After says how long to wait. |
curl -X POST https://api.aerscheduler.com/orgUsers/:orgUserId/ledger/topups \
-H "Authorization: Bearer $AERSCHEDULER_KEY" \
-H "Content-Type: application/json" \
-d '{"amountCents":1}'/users/{userId}/emergencyContacts/{contactId}Update an emergency contact
Omit a field to leave it. phone may be changed but not cleared.
Path parameters
userIdrequired | integer | The user id. |
contactIdrequired | integer | The emergency contact id. |
Request body
Fields to change.
name | string | |
relationship | string | |
phone | string | |
altPhone | string | |
email | string | |
notes | string | |
isPrimary | boolean | |
sortOrder | integer |
Responses
200 | OK | Success.→ { data: EmergencyContact } |
400 | Bad Request | A field was not valid. |
401 | Unauthorized | No token, an expired token, or a malformed one. Sign in again. |
403 | Forbidden | Authenticated, but not allowed to do this. |
404 | Not Found | That emergency contact doesn't exist. |
429 | Too Many Requests | Rate limited. Retry-After says how long to wait. |
curl -X PATCH https://api.aerscheduler.com/users/:userId/emergencyContacts/:contactId \
-H "Authorization: Bearer $AERSCHEDULER_KEY" \
-H "Content-Type: application/json" \
-d '{"name":"…","relationship":"…"}'/users/{userId}/emergencyContacts/{contactId}Remove an emergency contact
Soft-deletes it.
Path parameters
userIdrequired | integer | The user id. |
contactIdrequired | integer | The emergency contact id. |
Responses
204 | No Content | Success. No body. |
401 | Unauthorized | No token, an expired token, or a malformed one. Sign in again. |
403 | Forbidden | Authenticated, but not allowed to do this. |
404 | Not Found | That emergency contact doesn't exist. |
429 | Too Many Requests | Rate limited. Retry-After says how long to wait. |
curl -X DELETE https://api.aerscheduler.com/users/:userId/emergencyContacts/:contactId \
-H "Authorization: Bearer $AERSCHEDULER_KEY"/users/{userId}/orgUser/archiveArchive 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
userIdrequired | integer | The user id , not the membership id. |
Request body
Whether the member should be archived.
archivedrequired | boolean |
Responses
200 | OK | Success.→ { data: User } |
400 | Bad Request | archived was missing or not a boolean, or you tried to archive your own membership. |
401 | Unauthorized | No token, an expired token, or a malformed one. Sign in again. |
403 | Forbidden | You are not an owner or admin of this organization, or that person is not a member of it. |
429 | Too Many Requests | Rate limited. Retry-After says how long to wait. |
curl -X PATCH https://api.aerscheduler.com/users/:userId/orgUser/archive \
-H "Authorization: Bearer $AERSCHEDULER_KEY" \
-H "Content-Type: application/json" \
-d '{"archived":true}'/users/sms/verify/confirmConfirm an SMS verification code
Marks the mobile as opted-in and verified when the code matches.
Request body
The code from the text.
code | string |
Responses
200 | OK | Success.→ { data: object } |
400 | Bad Request | Code missing, expired, or incorrect. |
401 | Unauthorized | No token, an expired token, or a malformed one. Sign in again. |
403 | Forbidden | Authenticated, but not allowed to do this. |
429 | Too Many Requests | Rate limited. Retry-After says how long to wait. |
curl -X POST https://api.aerscheduler.com/users/sms/verify/confirm \
-H "Authorization: Bearer $AERSCHEDULER_KEY" \
-H "Content-Type: application/json" \
-d '{"code":"123456"}'/users/sms/verify/startSend an SMS verification code
Texts a one-time code to the US mobile on your profile. Required before smsEnabled can be turned on.
Responses
200 | OK | Success.→ { data: object } |
400 | Bad Request | No US mobile on file, or the number cannot receive SMS. |
401 | Unauthorized | No token, an expired token, or a malformed one. Sign in again. |
403 | Forbidden | Authenticated, but not allowed to do this. |
429 | Too Many Requests | Rate limited. Retry-After says how long to wait. |
curl -X POST https://api.aerscheduler.com/users/sms/verify/start \
-H "Authorization: Bearer $AERSCHEDULER_KEY"/orgUsers/{orgUserId}/ledger/statement/emailEmail 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
orgUserIdrequired | integer | The membership id. |
Request body
Statement period.
startrequired | string | Inclusive 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). |
endrequired | string | Inclusive 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). |
periodLabel | string | Optional 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
200 | OK | Email queued.→ { data: object } |
400 | Bad Request | Invalid range, or no email on file. |
401 | Unauthorized | No token, an expired token, or a malformed one. Sign in again. |
403 | Forbidden | Not allowed to email this member's statement. |
429 | Too Many Requests | Rate limited. Retry-After says how long to wait. |
500 | Server Error | The statement email could not be sent. |
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"}'/orgUsers/{orgUserId}/ledger/topups/confirmConfirm 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
orgUserIdrequired | integer | The membership id. |
Request body
Confirmed PaymentIntent.
paymentIntentIdrequired | string | Stripe PaymentIntent id from the top-up create response. |
Responses
200 | OK | Credit posted (or already posted) and current balance.→ { data: LedgerTopUpConfirm } |
400 | Bad Request | Ledger off, PI not succeeded, or not this member's top-up. |
401 | Unauthorized | No token, an expired token, or a malformed one. Sign in again. |
403 | Forbidden | Authenticated, but not allowed to do this. |
429 | Too Many Requests | Rate limited. Retry-After says how long to wait. |
curl -X POST https://api.aerscheduler.com/orgUsers/:orgUserId/ledger/topups/confirm \
-H "Authorization: Bearer $AERSCHEDULER_KEY" \
-H "Content-Type: application/json" \
-d '{"paymentIntentId":"…"}'/orgUsers/{orgUserId}/ledger/entries/{entryId}/reassignReassign 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
orgUserIdrequired | integer | Current member who holds the charge. |
entryIdrequired | integer | Flight charge ledger entry id. |
Request body
Target member.
toOrgUserIdrequired | integer | Membership id that should own the charge. |
memo | string | Optional note on the reversal / new charge. |
Responses
201 | Created | Reversal on the original member and new charge on the target.→ { data: object } |
400 | Bad Request | Not an admin, not a flight charge, already reversed, or validation failed. |
401 | Unauthorized | No token, an expired token, or a malformed one. Sign in again. |
403 | Forbidden | Authenticated, but not allowed to do this. |
404 | Not Found | Entry not found. |
429 | Too Many Requests | Rate limited. Retry-After says how long to wait. |
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}'/orgUsers/{orgUserId}/ledger/entries/{entryId}/receiptGet 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
orgUserIdrequired | integer | The membership id. |
entryIdrequired | integer | Ledger entry id. |
Responses
200 | OK | Success.→ { data: LedgerReceipt } |
400 | Bad Request | Not a charge entry, or not allowed. |
401 | Unauthorized | No token, an expired token, or a malformed one. Sign in again. |
403 | Forbidden | Authenticated, but not allowed to do this. |
404 | Not Found | Entry not found for this member. |
429 | Too Many Requests | Rate limited. Retry-After says how long to wait. |
curl https://api.aerscheduler.com/orgUsers/:orgUserId/ledger/entries/:entryId/receipt \
-H "Authorization: Bearer $AERSCHEDULER_KEY"/orgUsers/{orgUserId}/ledger/entries/{entryId}/reverseReverse 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
orgUserIdrequired | integer | Member who holds the charge. |
entryIdrequired | integer | Flight charge ledger entry id. |
Request body
Optionally, why.
memo | string | Kept on the reversing entry, so the statement says why. |
Responses
201 | Created | The reversing entry, and the balance it leaves.→ { data: object } |
400 | Bad Request | Not a flight charge, already reversed, or an invalid entry id. |
401 | Unauthorized | No token, an expired token, or a malformed one. Sign in again. |
403 | Forbidden | Admin only. |
404 | Not Found | Entry not found. |
429 | Too Many Requests | Rate limited. Retry-After says how long to wait. |
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":"…"}'