AerScheduler

Memberships

What a club or an FBO charges people for belonging, as opposed to for flying. A plan carries a one-time join fee, recurring dues, or both; a membership is one person's copy of a plan with the money snapshotted at the moment it started, so re-pricing a plan never re-prices anybody already on it. Every dues period is a ledger row, and a period is billed because the membership's own cursor says it is owed — never because of what day it happens to be. Dues and join fees are raised as ordinary invoices, so they appear under Invoices and in the revenue reports with everything else.

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

get/memberships

List memberships

Every membership in the organization. Requires the admin role.

Query parameters

statusstringpending | active | suspended | cancelled
planIdintegerFilter to one plan.
takeintegerPage size, 1-200. Defaults to 50.
skipintegerRows to skip.
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

200OKSuccess.{ data: Membership[] }
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/memberships \
  -H "Authorization: Bearer $AERSCHEDULER_KEY"
post/memberships

Put a member on a plan

Snapshots the plan's prices onto the membership. Starts pending unless start is true — a membership that begins billing the moment it is created is rarely what the desk wants. A member may hold only one live membership at a time. Requires the admin role.

Request body

The membership.

orgUserIdrequiredinteger
planIdrequiredinteger
startbooleanStart it now rather than leaving it pending.
startedAtstringBackdate the start. Defaults to now.
waiveJoinFeebooleanJoin with no join fee — a founding member, or a transfer from another club.
notesstring | null

Responses

201CreatedSuccess.{ data: Membership }
401UnauthorizedNo token, an expired token, or a malformed one. Sign in again.
403ForbiddenAuthenticated, but not allowed to do this.
409This person already has a live membership.
429Too Many RequestsRate limited. Retry-After says how long to wait.
Example request
curl -X POST https://api.aerscheduler.com/memberships \
  -H "Authorization: Bearer $AERSCHEDULER_KEY" \
  -H "Content-Type: application/json" \
  -d '{"orgUserId":1,"planId":1}'
get/memberships/{membershipId}

Get a membership

With its recent dues periods and what the next billable period would be. Requires the admin role.

Path parameters

membershipIdrequiredintegerThe membership id.

Responses

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

Update a membership

Everything that does not change what it costs. agreementOnFile records that the member's paperwork is in — it is a record, never a gate, and nothing is blocked when it is missing. Requires the admin role.

Path parameters

membershipIdrequiredintegerThe membership id.

Request body

Fields to change.

autoBillDuesboolean
notesstring | null
agreementOnFileboolean
agreementDocumentIdinteger | nullMust be a document belonging to this member.
nextDueAtstring | nullMove the billing cursor. The escape hatch for a period settled outside the system.

Responses

200OKSuccess.{ data: Membership }
401UnauthorizedNo token, an expired token, or a malformed one. Sign in again.
403ForbiddenAuthenticated, but not allowed to do this.
404Not FoundNo such membership.
429Too Many RequestsRate limited. Retry-After says how long to wait.
Example request
curl -X PATCH https://api.aerscheduler.com/memberships/:membershipId \
  -H "Authorization: Bearer $AERSCHEDULER_KEY" \
  -H "Content-Type: application/json" \
  -d '{"autoBillDues":true,"notes":"…"}'
get/memberships/me

The caller's own membership

What the caller is on, what it costs, when the next period lands, and what they have been billed. Answers 200 with null when they are not on a plan, which is the ordinary answer at an organization that does not run memberships. Readable by any member.

Responses

200OKSuccess.{ data: object | null }
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/memberships/me \
  -H "Authorization: Bearer $AERSCHEDULER_KEY"
get/memberships/plans

List membership plans

Every plan the organization offers, with how many members are on each. Requires the admin role.

Query parameters

includeArchivedbooleanInclude retired plans. Defaults to false.
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

200OKSuccess.{ data: MembershipPlan[] }
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/memberships/plans \
  -H "Authorization: Bearer $AERSCHEDULER_KEY"
post/memberships/plans

Create a membership plan

Tiers are plans — full, associate, social — so a new tier is a new plan rather than a setting. Amounts are in cents. Leave duesCents empty for a join-fee-only plan, or joinFeeCents empty for dues with no fee. Requires the admin role.

Request body

The plan.

namerequiredstring
descriptionstring | null
joinFeeCentsinteger | nullOne-time, in cents. Null for no join fee.
joinFeeLabelstring | nullHow the fee reads on the invoice.
duesCentsinteger | nullRecurring, in cents. Null for a plan with no dues.
duesLabelstring | null
duesInterval"monthly" | "quarterly" | "annual"
duesDayOfMonthinteger | nullBill every member on this day. Capped at 28 so every month has one. Null bills each member on their own join anniversary instead.
prorateFirstPeriodbooleanCharge a part-period when somebody joins mid-cycle. Only meaningful with duesDayOfMonth.
autoBillDuesbooleanRaise each period's invoice automatically, overnight.
duesDueInDaysinteger | nullDays a member gets to pay a dues or joining-fee invoice. Null means no due date. A term of the money, so it is snapshotted onto the membership at join.
bookingWindowDaysinteger | nullHow far ahead a member on this tier may book, in days. Null means no limit. An entitlement, so it is read live — relaxing it relaxes it for everyone immediately, unlike dues.
agreementDocumentTypeIdinteger | nullThe document a member on this plan is expected to have on file. Recorded only — nothing is enforced on it.

Responses

201CreatedSuccess.{ data: MembershipPlan }
400Bad RequestThe amount, cadence or billing day is not usable.
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/memberships/plans \
  -H "Authorization: Bearer $AERSCHEDULER_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name":"…"}'
get/memberships/vocabulary

Cadences and statuses

The billing cadences and membership statuses this server accepts. A vocabulary, not a permission — any member may read it.

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/memberships/vocabulary \
  -H "Authorization: Bearer $AERSCHEDULER_KEY"
post/memberships/{membershipId}/dues

Bill the next dues period

Which period is decided by the server from the membership's own cursor and is deliberately not accepted from the request — a client that could name the period could bill the same month twice. An outstanding part-period from joining mid-cycle is billed first, at its own price. A period that has already been billed answers 409 rather than raising a second invoice. Requires the admin role.

Path parameters

membershipIdrequiredintegerThe membership id.

Responses

201CreatedSuccess.{ data: object }
401UnauthorizedNo token, an expired token, or a malformed one. Sign in again.
403ForbiddenAuthenticated, but not allowed to do this.
409Nothing is owed, or that period has already been billed.
429Too Many RequestsRate limited. Retry-After says how long to wait.
Example request
curl -X POST https://api.aerscheduler.com/memberships/:membershipId/dues \
  -H "Authorization: Bearer $AERSCHEDULER_KEY"
post/memberships/{membershipId}/joinFee

Bill the join fee

Raises an ordinary invoice for the one-time fee, at the amount snapshotted when the member joined. Billable once. Requires the admin role.

Path parameters

membershipIdrequiredintegerThe membership id.

Responses

201CreatedSuccess.{ data: object }
401UnauthorizedNo token, an expired token, or a malformed one. Sign in again.
403ForbiddenAuthenticated, but not allowed to do this.
409There is no join fee, or it has already been invoiced.
429Too Many RequestsRate limited. Retry-After says how long to wait.
Example request
curl -X POST https://api.aerscheduler.com/memberships/:membershipId/joinFee \
  -H "Authorization: Bearer $AERSCHEDULER_KEY"
post/memberships/{membershipId}/plan

Move a member to a different plan

Takes the new plan's current prices, from the next period. Anything already invoiced is untouched. Requires the admin role.

Path parameters

membershipIdrequiredintegerThe membership id.

Request body

The new plan.

planIdrequiredinteger

Responses

200OKSuccess.{ data: object }
400Bad RequestThe membership has ended, or the plan is retired.
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/memberships/:membershipId/plan \
  -H "Authorization: Bearer $AERSCHEDULER_KEY" \
  -H "Content-Type: application/json" \
  -d '{"planId":1}'
post/memberships/{membershipId}/status

Start, pause, resume or end a membership

Only an active membership accrues dues. Pausing keeps the row and stops the meter, so a member away for the winter does not come back months in arrears. Cancelled is terminal — bringing somebody back is a new membership, because reviving one would resume a cursor that has been sitting still and bill every period since. Requires the admin role.

Path parameters

membershipIdrequiredintegerThe membership id.

Request body

The new status.

statusrequired"pending" | "active" | "suspended" | "cancelled"
reasonstring | null

Responses

200OKSuccess.{ data: object }
400Bad RequestThat transition is not allowed.
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/memberships/:membershipId/status \
  -H "Authorization: Bearer $AERSCHEDULER_KEY" \
  -H "Content-Type: application/json" \
  -d '{"status":"pending"}'
get/memberships/orgUser/{orgUserId}

One member's membership

The live membership for a member, or the most recent one if it has ended. Null when they have never had one. Requires the admin role.

Path parameters

orgUserIdrequiredintegerThe member id.

Responses

200OKSuccess.{ data: object | null }
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/memberships/orgUser/:orgUserId \
  -H "Authorization: Bearer $AERSCHEDULER_KEY"
patch/memberships/plans/{planId}

Update a membership plan

Including the price. This is safe by design: every membership carries its own snapshot, so changing a plan cannot re-price anybody already on it. Moving an existing member to today's price is a separate, deliberate act. Requires the admin role.

Path parameters

planIdrequiredintegerThe plan id.

Request body

Fields to change. Omit a field to leave it alone; send null to clear it.

namestring
descriptionstring | null
joinFeeCentsinteger | null
duesCentsinteger | null
duesInterval"monthly" | "quarterly" | "annual"
duesDayOfMonthinteger | null
prorateFirstPeriodboolean
autoBillDuesboolean
duesDueInDaysinteger | null
bookingWindowDaysinteger | null

Responses

200OKSuccess.{ data: MembershipPlan }
401UnauthorizedNo token, an expired token, or a malformed one. Sign in again.
403ForbiddenAuthenticated, but not allowed to do this.
404Not FoundNo such plan.
429Too Many RequestsRate limited. Retry-After says how long to wait.
Example request
curl -X PATCH https://api.aerscheduler.com/memberships/plans/:planId \
  -H "Authorization: Bearer $AERSCHEDULER_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name":"…","description":"…"}'
get/memberships/plans/options

Plans a member may be put on

Names and prices only, for a plan picker. Readable by any member.

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

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/memberships/plans/options \
  -H "Authorization: Bearer $AERSCHEDULER_KEY"
post/memberships/{membershipId}/dues/skip

Waive the next dues period

Records the period as deliberately not charged — a comped month, or a leave of absence — so nothing comes back for it later. Requires the admin role.

Path parameters

membershipIdrequiredintegerThe membership id.

Request body

Why.

reasonstring | null

Responses

201CreatedSuccess.{ data: object }
401UnauthorizedNo token, an expired token, or a malformed one. Sign in again.
403ForbiddenAuthenticated, but not allowed to do this.
409There are no dues to waive.
429Too Many RequestsRate limited. Retry-After says how long to wait.
Example request
curl -X POST https://api.aerscheduler.com/memberships/:membershipId/dues/skip \
  -H "Authorization: Bearer $AERSCHEDULER_KEY" \
  -H "Content-Type: application/json" \
  -d '{"reason":"…"}'
post/memberships/plans/{planId}/archive

Retire a plan, or bring it back

There is no delete. A plan nobody is on is still the answer to what a member was paying two years ago, so retiring it stops it being offered to new members and leaves every historical charge readable. Members already on it keep being billed. Requires the admin role.

Path parameters

planIdrequiredintegerThe plan id.

Request body

Which way.

archivedbooleanDefaults to true.

Responses

200OKSuccess.{ data: object }
401UnauthorizedNo token, an expired token, or a malformed one. Sign in again.
403ForbiddenAuthenticated, but not allowed to do this.
404Not FoundNo such plan.
429Too Many RequestsRate limited. Retry-After says how long to wait.
Example request
curl -X POST https://api.aerscheduler.com/memberships/plans/:planId/archive \
  -H "Authorization: Bearer $AERSCHEDULER_KEY" \
  -H "Content-Type: application/json" \
  -d '{"archived":true}'
get/memberships/plans/{planId}/rates

A tier's aircraft rates

Only the aircraft this plan overrides. Anything absent bills at the aircraft's own published rate. Requires the admin role.

Path parameters

planIdrequiredintegerThe plan 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

200OKSuccess.{ data: MembershipPlanRate[] }
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/memberships/plans/:planId/rates \
  -H "Authorization: Bearer $AERSCHEDULER_KEY"
put/memberships/plans/{planId}/rates/{resourceId}

Set or clear a tier's rate for one aircraft

What members on this tier pay per hour for this aircraft, in cents. Sending both rates as null clears the override, returning the aircraft to its published rate.

The override applies to a booking only when everyone being billed on it resolves to the same rate — one pilot, or several on the same tier. Pilots on different tiers, or anyone without an active membership, fall back to the aircraft's own rate rather than being priced off somebody else's tier. Requires the admin role.

Path parameters

planIdrequiredintegerThe plan id.
resourceIdrequiredintegerThe aircraft's resource id.

Request body

The rate, in cents per hour. Wet wins over dry, matching ordinary pricing.

wetRateinteger | null
dryRateinteger | null

Responses

200OKSuccess.{ data: object | null }
401UnauthorizedNo token, an expired token, or a malformed one. Sign in again.
403ForbiddenAuthenticated, but not allowed to do this.
404Not FoundNo such plan or aircraft.
429Too Many RequestsRate limited. Retry-After says how long to wait.
Example request
curl -X PUT https://api.aerscheduler.com/memberships/plans/:planId/rates/:resourceId \
  -H "Authorization: Bearer $AERSCHEDULER_KEY" \
  -H "Content-Type: application/json" \
  -d '{"wetRate":1,"dryRate":1}'