Enterprise: the API, webhooks and MCP server are live for schools on the Enterprise plan. The owner allows every key and AI connection. Ask about Enterprise
On this page
API Reference / Enrollments
Enrollments
Read canonical occurrence enrollments, request family-confirmed enrollment, or add a swimmer to one verified free occurrence. Integrations cannot charge a family or silently enroll them in a paid class.
Retry-After and X-RateLimit-RemainingPer key or agent connection, on the Enterprise plan.
/v1/enrollmentsList enrollments
Requires both class_id and instance_id. Results are occurrence participant records, not a school-wide subscription ledger. Child states include active, absent, scheduled_drop, transferred and canceled; enrollment_kind describes the enrollment source.
Access: classes:read · MCP: list_enrollments
Headers
- AuthorizationstringRequired
Bearer <token>: an API key or an agent OAuth access token. App subscription routes require a dedicated app key. - Swum-Versiondate
Pins the response shape. Default:
2026-10-25.
Query parameters
- updated_sincedate-time
Effective update time after an ISO 8601 timestamp with an explicit time zone. Follow every page, including the legacy-record suffix.
- limitinteger
1–200; default 50. Minimum 1. Maximum 200. Default: 50.
- cursorstring
Opaque next_cursor from the previous page. Keep the same filters.
- statusstring
Optional exact family enrollment status; all disables this filter.
- class_idstringRequired
At most 128 characters.
- instance_idstringRequired
The exact class occurrence id; a calendar date is not an instance id. At most 128 characters.
Pagination
Keep calling with cursor=next_cursor until next_cursor is null. A filtered page may be short or empty while a next cursor remains.
curl "${SWUM_API_BASE:-https://api.swum.ai}/v1/enrollments" \
-G \
--data-urlencode 'class_id=class_example' \
--data-urlencode 'instance_id=instance_example' \
-H "Authorization: Bearer ${SWUM_API_KEY}"{
"data": [
{
"id": "family_example",
"family_id": "family_example",
"class_id": "class_example",
"instance_id": "instance_example",
"swimmer_ids": [
"swimmer_example"
],
"status": "active",
"swimmers": [
{
"id": "swimmer_example",
"name": "Avery Rivera",
"status": "active",
"absent": false,
"enrollment_kind": "permanent",
"checked_in_at": null,
"scheduled_drop_date": null
}
],
"updated_at": null
}
],
"next_cursor": null
}/v1/classes/{id}/participants/{swimmerId}/removeRemove a class participant
Removes exactly the named swimmer from a supported series class. Refund choice is fixed to none. Existing class lifecycle checks may refuse legacy billing models or ambiguous swimmer names.
Access: classes:write
Headers
- Idempotency-KeystringRequired
Any unique string, like a UUID. Send the same key again and you get the first answer back instead of doing it twice. Keys last 24 hours.
Path parameters
- idstringRequired
The exact Swum document id.
- swimmerIdstringRequired
The exact Swum document id.
Body
- family_idstring
The family document id. Write bodies also accept parent_uid. At most 128 characters.
- parent_uidstring
Alias for family_id; use one family identifier. At most 128 characters.
- scopestring
Default instance. series covers upcoming dates. Allowed: "instance", "series". Default: "instance".
- instance_idstring
Required to select the occurrence when scope is instance unless an unambiguous date is supplied. At most 128 characters.
- datedate
Calendar date YYYY-MM-DD in the location's time zone.
- reasonstring
Approval and retries
Ask Me First waits for owner approval; API keys and Can Act connections can execute eligible operations directly. Preserve one Idempotency-Key for identical retries. A pending proposal or queued job is not completed work.
Errors
Every error has the same shape: a type, a code you can switch on, a plain message, and a request_id for support. A param identifies the field at fault when available.
| Status | Code | When |
|---|---|---|
| 400 | invalid_parameter | A required field is missing or malformed. |
| 401 | invalid_token | The key/token is invalid, revoked or expired. |
| 403 | insufficient_scope | The connection lacks the route’s access. |
| 404 | not_found | The school record is unavailable, including location-scoped reads. |
| 409 | idempotency_conflict | The same key was used for a different request. |
| 422 | proposal_refused | The existing Swum domain checks could not safely prepare this change. |
| 429 | rate_limit_exceeded | Wait the Retry-After interval. |
curl "${SWUM_API_BASE:-https://api.swum.ai}/v1/classes/class_example/participants/swimmer_example/remove" \
-X POST \
-H "Authorization: Bearer ${SWUM_API_KEY}" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: ${SWUM_IDEMPOTENCY_KEY}" \
--data '{"family_id":"family_example","scope":"instance","instance_id":"instance_example"}'{
"status": "executed",
"proposal_id": "7a1991ec-5e37-43a0-a581-84e817790e4b",
"result": {
"success": true,
"message": "Completed.",
"changes": {}
}
}{
"status": "pending_approval",
"proposalId": "7a1991ec-5e37-43a0-a581-84e817790e4b",
"proposal_id": "7a1991ec-5e37-43a0-a581-84e817790e4b"
}/v1/classes/{id}/waitlist/{swimmerId}/removeRemove from a waitlist
The underlying operation removes a family’s waitlist entry across upcoming dates. The API therefore permits only entries containing exactly the named swimmer; multi-swimmer entries must be managed in Swum.
Access: classes:write
Headers
- Idempotency-KeystringRequired
Any unique string, like a UUID. Send the same key again and you get the first answer back instead of doing it twice. Keys last 24 hours.
Path parameters
- idstringRequired
The exact Swum document id.
- swimmerIdstringRequired
The exact Swum document id.
Body
- family_idstring
The family document id. Write bodies also accept parent_uid. At most 128 characters.
- parent_uidstring
Alias for family_id; use one family identifier. At most 128 characters.
- reasonstring
Removes the verified single-swimmer family's upcoming waitlist entries; instance selectors are not applied.
Approval and retries
Ask Me First waits for owner approval; API keys and Can Act connections can execute eligible operations directly. Preserve one Idempotency-Key for identical retries. A pending proposal or queued job is not completed work.
Errors
Every error has the same shape: a type, a code you can switch on, a plain message, and a request_id for support. A param identifies the field at fault when available.
| Status | Code | When |
|---|---|---|
| 400 | invalid_parameter | A required field is missing or malformed. |
| 401 | invalid_token | The key/token is invalid, revoked or expired. |
| 403 | insufficient_scope | The connection lacks the route’s access. |
| 404 | not_found | The school record is unavailable, including location-scoped reads. |
| 409 | idempotency_conflict | The same key was used for a different request. |
| 422 | proposal_refused | The existing Swum domain checks could not safely prepare this change. |
| 429 | rate_limit_exceeded | Wait the Retry-After interval. |
curl "${SWUM_API_BASE:-https://api.swum.ai}/v1/classes/class_example/waitlist/swimmer_example/remove" \
-X POST \
-H "Authorization: Bearer ${SWUM_API_KEY}" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: ${SWUM_IDEMPOTENCY_KEY}" \
--data '{"family_id":"family_example"}'{
"status": "executed",
"proposal_id": "7a1991ec-5e37-43a0-a581-84e817790e4b",
"result": {
"success": true,
"message": "Completed.",
"changes": {}
}
}{
"status": "pending_approval",
"proposalId": "7a1991ec-5e37-43a0-a581-84e817790e4b",
"proposal_id": "7a1991ec-5e37-43a0-a581-84e817790e4b"
}/v1/enrollmentsRequest enrollment or add to a free occurrence
mode=request is the default: creates a canonical family enrollment request. Registered families receive the normal Swum request; manual families wait for verified account claim/onboarding. It does not enroll or charge the family. mode=free adds only the exact instance_id after proving tuition, registration and service fees are zero and rechecking capacity, eligibility and required evaluations.
Access: classes:write
Headers
- Idempotency-KeystringRequired
Any unique string, like a UUID. Send the same key again and you get the first answer back instead of doing it twice. Keys last 24 hours.
Body
- family_idstringRequired
At most 128 characters.
- swimmer_idstringRequired
At most 128 characters.
- class_idstringRequired
At most 128 characters.
- modestring
Allowed: "request", "free". Default: "request".
- instance_idstring
Required for free mode; adds only this verified occurrence. At most 128 characters.
A separate free-mode request
For a genuinely free class, send mode:free and instance_id with family_id, swimmer_id and class_id. Use a new operation key for that distinct payload. Missing prices are not proof of free tuition; fees, capacity, eligibility and evaluation requirements still apply. A 202 with result.changes.status=requested means the integration action ran but the family has not confirmed enrollment.
Current permission and roster checks
Both approval and persistence recheck the current school, roster and connection authority. Removed access, revoked or expired grants, changed records and narrowed locations can refuse a previously prepared proposal. Do not work around a refusal by starting a duplicate operation.
Approval and retries
Ask Me First waits for owner approval; API keys and Can Act connections can execute eligible operations directly. Preserve one Idempotency-Key for identical retries. A pending proposal or queued job is not completed work.
Errors
Every error has the same shape: a type, a code you can switch on, a plain message, and a request_id for support. A param identifies the field at fault when available.
| Status | Code | When |
|---|---|---|
| 400 | invalid_parameter | A required field is missing or malformed. |
| 401 | invalid_token | The key/token is invalid, revoked or expired. |
| 403 | insufficient_scope | The connection lacks the route’s access. |
| 404 | not_found | The school record is unavailable, including location-scoped reads. |
| 409 | idempotency_conflict | The same key was used for a different request. |
| 422 | proposal_refused | The current roster, class, entry or school policy refuses this change. |
| 429 | rate_limit_exceeded | Wait the Retry-After interval. |
curl "${SWUM_API_BASE:-https://api.swum.ai}/v1/enrollments" \
-X POST \
-H "Authorization: Bearer ${SWUM_API_KEY}" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: ${SWUM_IDEMPOTENCY_KEY}" \
--data '{"family_id":"family_example","swimmer_id":"swimmer_example","class_id":"class_example","mode":"request"}'{
"status": "executed",
"proposal_id": "7a1991ec-5e37-43a0-a581-84e817790e4b",
"result": {
"success": true,
"changes": {
"status": "requested",
"familyId": "family_example",
"kidId": "swimmer_example",
"classId": "class_example",
"requestId": "class_request_example",
"delivery": "message"
}
}
}{
"status": "pending_approval",
"proposalId": "7a1991ec-5e37-43a0-a581-84e817790e4b",
"proposal_id": "7a1991ec-5e37-43a0-a581-84e817790e4b"
}{
"status": "executed",
"proposal_id": "7a1991ec-5e37-43a0-a581-84e817790e4b",
"result": {
"success": true,
"changes": {
"familyId": "family_example",
"kidId": "swimmer_example",
"classId": "class_example",
"instanceId": "instance_example"
}
}
}