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 / Lessons

Lessons

Read school lessons or book a single swimmer using prepaid time credits or no charge. Lesson cancellations and reschedules always wait for the owner in Swummy.

3,000requests per UTC hour
10requests a second, in bursts
429when over, with Retry-After and X-RateLimit-Remaining

Per key or agent connection, on the Enterprise plan.

GET/v1/lessons

List lessons

Lists lessons in the owner’s lesson directory, excluding unfinished checkouts. Date bounds filter the lesson start time.

Access: lessons:read

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.

  • start_atdate-time

    Inclusive start bound.

  • end_atdate-time

    Inclusive end bound.

  • coach_idstring

    At most 128 characters.

  • location_idstring

    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.

Request
curl "${SWUM_API_BASE:-https://api.swum.ai}/v1/lessons" \
  -G \
  --data-urlencode 'start_at=2026-11-01T00:00:00Z' \
  --data-urlencode 'end_at=2026-11-30T23:59:59Z' \
  -H "Authorization: Bearer ${SWUM_API_KEY}"
200Responseapplication/json
{
  "data": [
    {
      "id": "lesson_example",
      "family_id": "family_example",
      "coach_id": "owner_example",
      "location_id": "pool_example",
      "start_at": "2026-11-07T14:00:00.000Z",
      "end_at": "2026-11-07T14:30:00.000Z",
      "status": "booked",
      "swimmer_ids": [
        "swimmer_example"
      ],
      "updated_at": null
    }
  ],
  "next_cursor": null
}
POST/v1/lessons

Book a lesson

Books using the owner’s existing manual-booking checks. package spends prepaid time-bank minutes; no_charge bills nothing. Saved-card charges, invoice and plan bookings are unavailable.

Access: lessons: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_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.

  • swimmer_idstringRequired

    At most 128 characters.

  • datedateRequired

    YYYY-MM-DD at the selected location.

  • timestringRequired

    HH:MM or a supported AM/PM time.

  • duration_minutesintegerRequired

    15–240 minutes. Minimum 15. Maximum 240.

  • payment_sourcestringRequired

    Prepaid time credits or no-charge only. Saved-card charges are unavailable. Allowed: "package", "no_charge".

  • location_idstring

    Must resolve to an owner location. At most 128 characters.

  • lesson_typestring

    Default individual; the current proposal selects one participant. Allowed: "individual", "semi-private". Default: "individual".

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.

StatusCodeWhen
400invalid_parameterA required field is missing or malformed.
401invalid_tokenThe key/token is invalid, revoked or expired.
403insufficient_scopeThe connection lacks the route’s access.
404not_foundThe school record is unavailable, including location-scoped reads.
409idempotency_conflictThe same key was used for a different request.
422proposal_refusedThe existing Swum domain checks could not safely prepare this change.
429rate_limit_exceededWait the Retry-After interval.
Request
curl "${SWUM_API_BASE:-https://api.swum.ai}/v1/lessons" \
  -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","date":"2026-11-07","time":"09:00","duration_minutes":30,"location_id":"pool_example","payment_source":"no_charge"}'
200Executedapplication/json
{
  "status": "executed",
  "proposal_id": "7a1991ec-5e37-43a0-a581-84e817790e4b",
  "result": {
    "success": true,
    "message": "Completed.",
    "changes": {}
  }
}
202Pending owner approvalapplication/json
{
  "status": "pending_approval",
  "proposalId": "7a1991ec-5e37-43a0-a581-84e817790e4b",
  "proposal_id": "7a1991ec-5e37-43a0-a581-84e817790e4b"
}
POST/v1/lessons/{id}/reschedule

Reschedule a lesson

Prepares a move; the owner’s own app session executes it after approval. Domain checks may refuse unsupported lesson types, stale times or occupied slots.

Access: lessons: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.

Body

  • datedateRequired

    New date in the lesson’s time zone.

  • timestringRequired

    New local start time.

  • reasonstring

Approval and retries

Always requires owner approval in Swum, including for API keys and Can Act agents. 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.

StatusCodeWhen
400invalid_parameterA required field is missing or malformed.
401invalid_tokenThe key/token is invalid, revoked or expired.
403insufficient_scopeThe connection lacks the route’s access.
404not_foundThe school record is unavailable, including location-scoped reads.
409idempotency_conflictThe same key was used for a different request.
422proposal_refusedThe existing Swum domain checks could not safely prepare this change.
429rate_limit_exceededWait the Retry-After interval.
Request
curl "${SWUM_API_BASE:-https://api.swum.ai}/v1/lessons/lesson_example/reschedule" \
  -X POST \
  -H "Authorization: Bearer ${SWUM_API_KEY}" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: ${SWUM_IDEMPOTENCY_KEY}" \
  --data '{"date":"2026-11-14","time":"10:00"}'
202Pending owner approvalapplication/json
{
  "status": "pending_approval",
  "proposalId": "7a1991ec-5e37-43a0-a581-84e817790e4b",
  "proposal_id": "7a1991ec-5e37-43a0-a581-84e817790e4b"
}
POST/v1/lessons/{id}/cancel

Cancel a lesson

Prepares a cancellation without requesting a refund. The owner approves in Swummy and the normal lesson endpoint applies the school’s current policy. Integration callers cannot request refunds.

Access: lessons: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.

Body

  • reasonstring
  • refund_choicestring

    Optional; none is the only accepted value. Allowed: "none". Default: "none".

Approval and retries

Always requires owner approval in Swum, including for API keys and Can Act agents. 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.

StatusCodeWhen
400invalid_parameterA required field is missing or malformed.
401invalid_tokenThe key/token is invalid, revoked or expired.
403insufficient_scopeThe connection lacks the route’s access.
404not_foundThe school record is unavailable, including location-scoped reads.
409idempotency_conflictThe same key was used for a different request.
422proposal_refusedThe existing Swum domain checks could not safely prepare this change.
429rate_limit_exceededWait the Retry-After interval.
Request
curl "${SWUM_API_BASE:-https://api.swum.ai}/v1/lessons/lesson_example/cancel" \
  -X POST \
  -H "Authorization: Bearer ${SWUM_API_KEY}" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: ${SWUM_IDEMPOTENCY_KEY}" \
  --data '{"refund_choice":"none","reason":"Pool closed"}'
202Pending owner approvalapplication/json
{
  "status": "pending_approval",
  "proposalId": "7a1991ec-5e37-43a0-a581-84e817790e4b",
  "proposal_id": "7a1991ec-5e37-43a0-a581-84e817790e4b"
}
GET/v1/proposals/{id}

Get a proposal status

Only the key or agent connection that requested the proposal can read it. approved means execution started, not that it completed.

Access: same connection

Path parameters

  • idstringRequired

    The exact Swum document id.

Request
curl "${SWUM_API_BASE:-https://api.swum.ai}/v1/proposals/7a1991ec-5e37-43a0-a581-84e817790e4b" \
  -H "Authorization: Bearer ${SWUM_API_KEY}"
200Responseapplication/json
{
  "id": "7a1991ec-5e37-43a0-a581-84e817790e4b",
  "action_type": "LESSONS_CANCEL_LESSON",
  "status": "executed",
  "created_at": "2026-10-25T14:00:00.000Z",
  "result": {
    "message": "Lesson canceled."
  }
}

The lesson object

  • idstring
  • family_idstring | null
  • coach_idstring | null
  • location_idstring | null
  • start_attimestamp | null
  • end_attimestamp | null
  • swimmer_idsstring[]
  • statusstring
  • updated_attimestamp | null