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.
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 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/instructorsGET /api/v1/activities, /experience-levels, /languages, and /age-ranges — the taxonomy lists used by the filtersInteractive 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:
Errors invert it: { "success": false, "error": { "message": "...", "status": 404 } }.
Keys start with the fass_ prefix and are passed in a header — either form works:_
Authorization: Bearer fass_xxxX-API-Key: fass_xxxQuery-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.
Three layers apply, all per minute unless stated:
/api/v1 works for anonymous reads but is limited to 60 requests/minute per IP./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.
When you exceed a key's limit you get HTTP 429 with a Retry-After header (in seconds) and:
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.
The codes you'll meet, and what they mean:
{ "error": "Invalid API key", "message": "The provided API key is invalid, expired, or has been revoked." }success: false envelopeThe 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:
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.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).
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.
Search French schools, five results per page, with a key:
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.
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.
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.
Still need help with this article?
Send the article URL and the step that needs more explanation.