School Owners7 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. The MCP server is at /mcp over Streamable HTTP — public search tools need no key; management tools need a school-scoped key. Default 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 and are passed in a header — either form 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.

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.

Keys are issued from the dashboard's API keys panel (under Tools & settings, in the admin area). The full key is shown once at creation — copy it then, because only a hash is stored server-side. If your account doesn't have access to the panel, contact support and a key will be issued and scoped to your school. From the same panel a key can be revoked instantly or rotated — rotation revokes the old key and issues a fresh one with identical scopes, limits, and school link. Every key's usage is logged (endpoint, status, response time), so leaked-key investigations have a paper trail.

Rate limits

Three layers apply, all per minute unless stated:

  • With an API key — the key's own 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.

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; safe to retry with backoff

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, and compare_schools. This is what makes your school discoverable when someone asks their AI assistant to "find a ski school in Morzine that teaches kids in English" — keep your profile current and the agents see it.
  • Management tools — school-scoped key required: get and update your school profile, list/add/update/remove instructors, list/add/update/delete lessons, list/confirm/cancel/complete bookings, list and respond to reviews, and pull your analytics and dashboard summary. Write tools also check the key's scopes, so you can issue an agent a read-only key.

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

To connect an MCP-capable client (Claude, Cursor, and others), add a remote server with the URL above; for management access, send your key as an Authorization: Bearer fass_xxx header. Public access needs no header at all.

MCP has its own limits: 60 requests/minute per IP, and a deliberately tight 5/minute throttle on failed key attempts. Auth failures come back as JSON-RPC errors — code -32001 for an invalid key (HTTP 401) and -32002 when failed attempts are being throttled (HTTP 429).

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 [blocked] 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 — for those, poll the API at a sensible interval or use the MCP booking tools.

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