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
/membershipsList memberships
Every membership in the organization. Requires the admin role.
Query parameters
status | string | pending | active | suspended | cancelled |
planId | integer | Filter to one plan. |
take | integer | Page size, 1-200. Defaults to 50. |
skip | integer | Rows to skip. |
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 | Success.→ { data: Membership[] } |
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/memberships \
-H "Authorization: Bearer $AERSCHEDULER_KEY"/membershipsPut 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.
orgUserIdrequired | integer | |
planIdrequired | integer | |
start | boolean | Start it now rather than leaving it pending. |
startedAt | string | Backdate the start. Defaults to now. |
waiveJoinFee | boolean | Join with no join fee — a founding member, or a transfer from another club. |
notes | string | null |
Responses
201 | Created | Success.→ { data: Membership } |
401 | Unauthorized | No token, an expired token, or a malformed one. Sign in again. |
403 | Forbidden | Authenticated, but not allowed to do this. |
409 | This person already has a live membership. | |
429 | Too Many Requests | Rate limited. Retry-After says how long to wait. |
curl -X POST https://api.aerscheduler.com/memberships \
-H "Authorization: Bearer $AERSCHEDULER_KEY" \
-H "Content-Type: application/json" \
-d '{"orgUserId":1,"planId":1}'/memberships/{membershipId}Get a membership
With its recent dues periods and what the next billable period would be. Requires the admin role.
Path parameters
membershipIdrequired | integer | The membership id. |
Responses
200 | OK | Success.→ { data: Membership } |
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 membership. |
429 | Too Many Requests | Rate limited. Retry-After says how long to wait. |
curl https://api.aerscheduler.com/memberships/:membershipId \
-H "Authorization: Bearer $AERSCHEDULER_KEY"/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
membershipIdrequired | integer | The membership id. |
Request body
Fields to change.
autoBillDues | boolean | |
notes | string | null | |
agreementOnFile | boolean | |
agreementDocumentId | integer | null | Must be a document belonging to this member. |
nextDueAt | string | null | Move the billing cursor. The escape hatch for a period settled outside the system. |
Responses
200 | OK | Success.→ { data: Membership } |
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 membership. |
429 | Too Many Requests | Rate limited. Retry-After says how long to wait. |
curl -X PATCH https://api.aerscheduler.com/memberships/:membershipId \
-H "Authorization: Bearer $AERSCHEDULER_KEY" \
-H "Content-Type: application/json" \
-d '{"autoBillDues":true,"notes":"…"}'/memberships/meThe 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
200 | OK | Success.→ { data: object | null } |
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/memberships/me \
-H "Authorization: Bearer $AERSCHEDULER_KEY"/memberships/plansList membership plans
Every plan the organization offers, with how many members are on each. Requires the admin role.
Query parameters
includeArchived | boolean | Include retired plans. Defaults to false. |
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 | Success.→ { data: MembershipPlan[] } |
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/memberships/plans \
-H "Authorization: Bearer $AERSCHEDULER_KEY"/memberships/plansCreate 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.
namerequired | string | |
description | string | null | |
joinFeeCents | integer | null | One-time, in cents. Null for no join fee. |
joinFeeLabel | string | null | How the fee reads on the invoice. |
duesCents | integer | null | Recurring, in cents. Null for a plan with no dues. |
duesLabel | string | null | |
duesInterval | "monthly" | "quarterly" | "annual" | |
duesDayOfMonth | integer | null | Bill every member on this day. Capped at 28 so every month has one. Null bills each member on their own join anniversary instead. |
prorateFirstPeriod | boolean | Charge a part-period when somebody joins mid-cycle. Only meaningful with duesDayOfMonth. |
autoBillDues | boolean | Raise each period's invoice automatically, overnight. |
duesDueInDays | integer | null | Days 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. |
bookingWindowDays | integer | null | How 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. |
agreementDocumentTypeId | integer | null | The document a member on this plan is expected to have on file. Recorded only — nothing is enforced on it. |
Responses
201 | Created | Success.→ { data: MembershipPlan } |
400 | Bad Request | The amount, cadence or billing day is not usable. |
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/memberships/plans \
-H "Authorization: Bearer $AERSCHEDULER_KEY" \
-H "Content-Type: application/json" \
-d '{"name":"…"}'/memberships/vocabularyCadences and statuses
The billing cadences and membership statuses this server accepts. A vocabulary, not a permission — any member may read it.
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/memberships/vocabulary \
-H "Authorization: Bearer $AERSCHEDULER_KEY"/memberships/{membershipId}/duesBill 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
membershipIdrequired | integer | The membership id. |
Responses
201 | Created | 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. |
409 | Nothing is owed, or that period has already been billed. | |
429 | Too Many Requests | Rate limited. Retry-After says how long to wait. |
curl -X POST https://api.aerscheduler.com/memberships/:membershipId/dues \
-H "Authorization: Bearer $AERSCHEDULER_KEY"/memberships/{membershipId}/joinFeeBill 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
membershipIdrequired | integer | The membership id. |
Responses
201 | Created | 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. |
409 | There is no join fee, or it has already been invoiced. | |
429 | Too Many Requests | Rate limited. Retry-After says how long to wait. |
curl -X POST https://api.aerscheduler.com/memberships/:membershipId/joinFee \
-H "Authorization: Bearer $AERSCHEDULER_KEY"/memberships/{membershipId}/planMove 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
membershipIdrequired | integer | The membership id. |
Request body
The new plan.
planIdrequired | integer |
Responses
200 | OK | Success.→ { data: object } |
400 | Bad Request | The membership has ended, or the plan is retired. |
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/memberships/:membershipId/plan \
-H "Authorization: Bearer $AERSCHEDULER_KEY" \
-H "Content-Type: application/json" \
-d '{"planId":1}'/memberships/{membershipId}/statusStart, 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
membershipIdrequired | integer | The membership id. |
Request body
The new status.
statusrequired | "pending" | "active" | "suspended" | "cancelled" | |
reason | string | null |
Responses
200 | OK | Success.→ { data: object } |
400 | Bad Request | That transition is 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. |
429 | Too Many Requests | Rate limited. Retry-After says how long to wait. |
curl -X POST https://api.aerscheduler.com/memberships/:membershipId/status \
-H "Authorization: Bearer $AERSCHEDULER_KEY" \
-H "Content-Type: application/json" \
-d '{"status":"pending"}'/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
orgUserIdrequired | integer | The member id. |
Responses
200 | OK | Success.→ { data: object | null } |
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/memberships/orgUser/:orgUserId \
-H "Authorization: Bearer $AERSCHEDULER_KEY"/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
planIdrequired | integer | The plan id. |
Request body
Fields to change. Omit a field to leave it alone; send null to clear it.
name | string | |
description | string | null | |
joinFeeCents | integer | null | |
duesCents | integer | null | |
duesInterval | "monthly" | "quarterly" | "annual" | |
duesDayOfMonth | integer | null | |
prorateFirstPeriod | boolean | |
autoBillDues | boolean | |
duesDueInDays | integer | null | |
bookingWindowDays | integer | null |
Responses
200 | OK | Success.→ { data: MembershipPlan } |
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 plan. |
429 | Too Many Requests | Rate limited. Retry-After says how long to wait. |
curl -X PATCH https://api.aerscheduler.com/memberships/plans/:planId \
-H "Authorization: Bearer $AERSCHEDULER_KEY" \
-H "Content-Type: application/json" \
-d '{"name":"…","description":"…"}'/memberships/plans/optionsPlans a member may be put on
Names and prices only, for a plan picker. Readable by any member.
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 | 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/memberships/plans/options \
-H "Authorization: Bearer $AERSCHEDULER_KEY"/memberships/{membershipId}/dues/skipWaive 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
membershipIdrequired | integer | The membership id. |
Request body
Why.
reason | string | null |
Responses
201 | Created | 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. |
409 | There are no dues to waive. | |
429 | Too Many Requests | Rate limited. Retry-After says how long to wait. |
curl -X POST https://api.aerscheduler.com/memberships/:membershipId/dues/skip \
-H "Authorization: Bearer $AERSCHEDULER_KEY" \
-H "Content-Type: application/json" \
-d '{"reason":"…"}'/memberships/plans/{planId}/archiveRetire 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
planIdrequired | integer | The plan id. |
Request body
Which way.
archived | boolean | Defaults to true. |
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. |
404 | Not Found | No such plan. |
429 | Too Many Requests | Rate limited. Retry-After says how long to wait. |
curl -X POST https://api.aerscheduler.com/memberships/plans/:planId/archive \
-H "Authorization: Bearer $AERSCHEDULER_KEY" \
-H "Content-Type: application/json" \
-d '{"archived":true}'/memberships/plans/{planId}/ratesA 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
planIdrequired | integer | The plan 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 | Success.→ { data: MembershipPlanRate[] } |
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/memberships/plans/:planId/rates \
-H "Authorization: Bearer $AERSCHEDULER_KEY"/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
planIdrequired | integer | The plan id. |
resourceIdrequired | integer | The aircraft's resource id. |
Request body
The rate, in cents per hour. Wet wins over dry, matching ordinary pricing.
wetRate | integer | null | |
dryRate | integer | null |
Responses
200 | OK | Success.→ { data: object | null } |
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 plan or aircraft. |
429 | Too Many Requests | Rate limited. Retry-After says how long to wait. |
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}'