School Owners9 min readLast updated

How do I use the public API and MCP server?

A public REST API at /api/v1 gives developers read access to school, resort, and instructor data, with scoped API keys, per-key rate limits, and a documented error shape. The MCP server at /mcp lets AI assistants search the platform — and, with a school-scoped key, manage your school's profile, lessons, bookings, and reviews.

Quick answer

The REST API lives at /api/v1 (Swagger docs at /api/v1/docs) and accepts keys via the Authorization: Bearer or X-API-Key header. MCP uses /mcp over Streamable HTTP: public discovery needs no key; private school reads and writes need a school-scoped bearer key with the matching scopes on every request. Default shared REST/MCP key limits: 60 requests/minute, 10,000/day.

How do I use the public API and MCP server?

For technical teams who want programmatic access to platform data — building custom dashboards, integrating with internal systems, or making your school workable by AI agents — the platform provides a public REST API and an MCP (Model Context Protocol) server.

The REST API at a glance

The API is versioned under /api/v1 (every response carries an X-API-Version header). Read endpoints:

  • GET /api/v1/schools and GET /api/v1/schools/{slug} — search and detail, with filters for country, resort, activity, level, language, school type, certified, and featured, plus page and limit (max 100 per page)
  • GET /api/v1/resorts and GET /api/v1/resorts/{slug}
  • GET /api/v1/countries and GET /api/v1/countries/{slug}
  • GET /api/v1/instructors
  • GET /api/v1/activities, /experience-levels, /languages, and /age-ranges — the taxonomy lists used by the filters

Interactive documentation lives at /api/v1/docs (Swagger UI), the machine-readable spec at /api/v1/openapi.json, and a developer guide at /api-docs on the main site. For AI agents there are also /llms.txt and /llms-full.txt site descriptions.

Every response uses one envelope:

json

Errors invert it: { "success": false, "error": { "message": "...", "status": 404 } }.

Authentication and API keys

Keys start with the fass_ prefix. For REST requests, either header works:_

  • Authorization: Bearer fass_xxx
  • X-API-Key: fass_xxx

Query-string keys (?api_key=) are deliberately not supported — they leak long-lived credentials into proxy logs and browser history.

MCP uses Authorization: Bearer on every authenticated request. The REST X-API-Key alternative is not the MCP authentication contract.

Each key carries: a name and description, a set of scopes, optional per-minute and per-day rate limits, an optional expiry date, and optionally a school link. Scopes follow a resource:read / resource:write pattern — schools:read, instructors:read, lessons:write, bookings:write, reviews:write, analytics:read, and so on. The scope model fails closed: a request needs the matching scope for its resource and method, and endpoints outside the documented surface are denied outright.

School owners and co-owners can approve short-lived school MCP keys at /account/school-mcp-access, choosing only the necessary scopes. These keys require a verified active account, explicit consent, and the issuer's current ownership access; they expire within 30 days and can be rotated or revoked from that page. Inbox permission is a separate opt-in. Administrator-issued service keys remain available from the dashboard's API keys panel and retain their separate lifetime. The full key is shown once; only its hash is stored. Delegated school/customer credentials must be replaced through their consent pages; generic administrator edits cannot widen or restore their consent. Usage records include endpoint, status, and response time.

Rate limits

Three layers apply, all per minute unless stated:

  • With an API key — the key's shared REST/MCP budget: by default 60 requests/minute and 10,000/day. Higher limits can be set per key (this is the "contact us for high volume" path).
  • Without a key — /api/v1 works for anonymous reads but is limited to 60 requests/minute per IP.
  • A broad outer fence of 1,000 requests/minute per IP protects the whole /api surface against runaway clients.

Keyed responses include live quota headers: X-RateLimit-Limit-Minute, X-RateLimit-Remaining-Minute, X-RateLimit-Limit-Day, and X-RateLimit-Remaining-Day. Watch the remaining counts and back off before you hit zero.

What a 429 looks like

When you exceed a key's limit you get HTTP 429 with a Retry-After header (in seconds) and:

json

The outer per-IP fence uses a shorter body: { "error": "rate_limited", "retryAfter": 60 }, also with Retry-After. Honour the header — sleeping for retryAfter seconds and retrying is the correct client behaviour. If you hit limits routinely, that's usually a polling pattern that should be a cache.

REST error handling

The codes you'll meet, and what they mean:

  • 401 — no key where one is required, or an invalid, expired, or revoked key: { "error": "Invalid API key", "message": "The provided API key is invalid, expired, or has been revoked." }
  • 403 — your key is valid but lacks the scope: the body names the missing scope and lists what the key was granted, so the fix is self-evident
  • 404 — resource not found, in the standard success: false envelope
  • 429 — rate limited, as above
  • 500 — server error. Read requests can normally be retried with backoff. For a write, first read the current record to establish whether the change completed; retrying blindly can duplicate work. Honour any documented idempotency rules for the operation.

The MCP server

The MCP server is the API's equivalent for AI agents. It runs at:

using the Streamable HTTP transport (POST for JSON-RPC requests, GET for the notification stream, DELETE to close a session — your MCP client handles all of that). A discovery document at /mcp/info lists every tool, and the full developer guide is at /mcp-docs.

For school users, the main tool groups are:

  • Public tools — no key needed: search_schools, get_school_detail, search_resorts, get_resort_detail, list_countries, list_activities, search_instructors, compare_schools, search_lessons, get_lesson_detail, get_lesson_availability, and get_lesson_quote. These expose public school, resort, instructor, and lesson information. Lesson search shares the website's filters. Availability is provisional: typical school times do not establish remaining capacity, and quotes reserve no places. The booking form rechecks eligibility, capacity, and price.
  • Management tools — school-scoped key required: get and update basic school contact/profile details, list/add/update/remove instructors, list/add/update/delete basic lessons, list/read/confirm/cancel/complete school bookings, list and respond to reviews, and pull analytics and dashboard summaries. Read and write scopes are both enforced. get_my_school requires schools:read, instructors:read, and lessons:read; get_my_dashboard requires analytics:read, bookings:read, reviews:read, and instructors:read.

Additional platform-administration and content tools have separate restricted keys and scopes; a school key does not grant that access.

Four operational read tools are also available. get_my_calendar and get_instructor_availability read up to 31 school-local days with the required booking/instructor/availability scopes and omit learner contact, medical, and payment fields. list_school_conversations and get_school_conversation require messages:read, current owner/co-owner inbox permission, and the account's existing history cutoff. Administrator observer powers are not delegated through school keys. Message text is included only on explicit request, is bounded, and reading does not mark a thread read.

Customers can grant separate, short-lived personal access at /account/mcp-access after signing in with a verified email. The customer scopes are customer:bookings:read and customer:bookings:write; they cannot be combined with school or administration scopes. list_my_customer_bookings and get_customer_booking_status read only the customer's account-owned bookings. prepare_customer_booking returns a signed handoff for the same customer to continue in the browser. It creates no booking or capacity hold until the customer submits the booking form with participant details, policy acceptance, and CAPTCHA; online checkout then uses the existing browser payment flow where supported. Keys expire within 30 days and can be revoked or rotated from the same account page.

To connect an MCP-capable client, add a remote server with the URL above. For management access, send your key as an Authorization: Bearer fass_xxx header on every request, including session POST, GET, and DELETE requests. A session ID alone does not authenticate the client. Start a new session when changing keys or scopes. Public access needs no authentication header.

MCP has its own limits: 60 requests/minute per IP, 30 authenticated tool calls/minute per key, and a deliberately tight 5/minute throttle on failed key attempts. Authenticated requests also consume the shared REST/MCP key budget described above. Invalid-key failures come back as JSON-RPC errors — code -32001 (HTTP 401), or -32002 when failed attempts are throttled (HTTP 429). Tool-level scope or ownership refusals are returned as MCP tool errors.

Native clients that omit Origin are supported. Browser clients that supply Origin must match the deployment's configured trusted origins. Sessions have idle timeouts and count limits; reconnect if a session expires, and close unused sessions.

Reading school bookings

list_my_bookings accepts optional status, start_date (inclusive), and end_date (exclusive) filters. Dates are ISO 8601 timestamps with a timezone. Pagination uses limit (default 50, maximum 100) and offset (default 0). The result includes total, limit, offset, nextOffset, and bookings. Repeat the same filters with offset set to nextOffset until it is null.

get_my_booking accepts booking_id to retrieve one booking belonging to your school. Both booking read tools require bookings:read.

What still needs the website

Customer booking confirmation, participant details, consent, CAPTCHA, and payment require the browser. Selected-instructor slots may report observed 0/1 session capacity; unverified staffing and remaining group seats remain unknown. Availability reserves no capacity. Customer cancellation/refunds, school inbox replies, calendar/availability changes, rescheduling, instructor assignments, refunds, photo galleries, school policies/FAQs, support tickets, and full lesson configuration still require the website. cancel_booking changes booking status; it does not issue a refund. update_my_school accepts description, website, email, phone, and default currency, rather than school name, hours, or pricing.

Using an AI assistant safely

An Ask ChatGPT or Ask Claude link can open a prepared prompt about a public guide. It does not automatically connect the assistant to your FASS account, grant a key, or give it access to a private dashboard. Provider support for prefilled prompts and remote MCP depends on the client and account.

To act on school data, configure an MCP-capable client separately using the current MCP guide and a school-scoped key. Start with the minimum read permissions you need. Review proposed changes before authorising write actions; an AI answer is not proof the change was saved.

Keep API keys in the connector's secure configuration, never in a prompt, guide URL, screenshot, or public message. Do not paste private learner details into an external assistant unless you are authorised to share them. Public guide links can help explain a process without disclosing account data.

A worked example

Search French schools, five results per page, with a key:

bash

The response's data array contains school objects (slug, name, type, description, country, resort, contact details, private and group lesson prices, currency, and canonical URL), with pagination in meta. Drop the header and the same call still works under the anonymous per-IP limit — useful for trying things out before a key is issued.

Webhooks

Outbound webhooks currently cover support-ticket events only: ticket.created, ticket.replied, ticket.status_changed, and ticket.resolved, configured from the dashboard's ticket webhooks tab. Payloads are signed with HMAC-SHA256 in an X-Ticket-Signature header so your handler can verify authenticity. There are no booking or review webhooks yet; use the school's MCP read tools at a sensible polling interval.

Support

API and MCP support is best-effort for Starter and Independent Instructor plans, and prioritised for School and Multi-School plans. For most integrations the Swagger docs and /mcp-docs are enough; for edge cases or higher rate limits, contact us through the dashboard support channel.

Was this article helpful?Your feedback helps us improve the Help Centre.

Still need help with this article?

Tell us what is missing.

Send the article URL and the step that needs more explanation.

Contact support