Work with this as data
Every API here is available over the APIs.io API and to AI agents over MCP.
MCP server
One button, every client — Claude, Cursor, VS Code and the rest.
https://apis.io/mcp
Tools for apis
7 MCP tools reach this
find_apisBrowse and filter every API in the catalog.get_api_artifactsOne API's artifacts, grouped by type.get_openapiThe primary OpenAPI for this API.find_similar_apisAPIs that look like this one.apis_io_searchSTART HERE — APIs, providers and tags for one query, each with its total.resolveTurn a domain, URL or GitHub org into the provider it belongs to.find_cohortsEvery scored population of providers in the catalog.
Call it yourself
curl for this page
This API
curl "https://apis.io/api/v1/apis/extralingo-com:extralingo-com-schools-api"
All apis
curl "https://apis.io/api/v1/apis?limit=25"
Calls without X-API-Key need no key. Calls with it need a paid plan — get a key.
Get an API key
Free tier, no form to fill in. Signing in shares your email address with us — we store it to create your key and to recognise you if you sign in with another provider. See our Privacy Policy and Terms.
A second provider on the same verified email joins the account you already have.
OpenAPI Specification
openapi: 3.2.0
info:
title: Extralingo Public Schools API
version: 1.0.0
summary: Search language schools, configure trips, and submit unpaid bookings.
description: 'Version **1.0.0** of the Extralingo agent REST API. All paths below are relative to **`https://www.extralingo.com/api/v1`** (the documented base). The same routes also work under unversioned `/api/*` and remain fully supported. Breaking changes ship under `/api/v2` with at least 6 months'' notice; deprecated endpoints will eventually send `Deprecation` and `Sunset` headers before removal. **Read** endpoints need no authentication. **Write** endpoints require OAuth 2.1 (authorization code + PKCE S256; scopes `trips`, `requests`, `bookings`; discover the resource at /.well-known/oauth-protected-resource; see /auth.md). Create endpoints accept optional **`Idempotency-Key`** (IETF draft): same key + same authenticated user + same JSON body within 24 hours returns the original response; same key + different body returns **422**. When OAuth is enabled, `POST /trips` is gated like MCP `save_trip`. Finder prices are indicative; call `POST /trips/{trip_id}/price` for a live quote. create_booking is unpaid: the school still confirms, Extralingo emails the student, and payment is only via Extralingo after confirmation. Prefer POST /mcp (MCP) if you can use tools. Keep request volumes reasonable; usage may be rate-limited. Developer overview: /en/developers. Site index: /llms.txt.'
contact:
name: Extralingo
url: https://www.extralingo.com/en/contact
servers:
- url: https://www.extralingo.com/api/v1
description: Agent REST API v1 (production)
tags:
- name: schools
description: Search and compare language schools
paths:
/school-finder/search:
get:
tags:
- schools
operationId: searchSchoolsGet
summary: Search language schools (GET)
description: Same search as POST. Agents may GET. Limit is capped at 20. Each hit includes `school_id` (Craft id) for later calls. Prices are indicative.
parameters:
- $ref: '#/components/parameters/Locale'
- name: query
in: query
schema:
type: string
- name: language
in: query
schema:
type: string
- name: country
in: query
schema:
type: string
- name: cities
in: query
schema:
type: string
description: Comma-separated city names.
- name: limit
in: query
schema:
type: integer
minimum: 1
maximum: 20
default: 10
responses:
'200':
description: Ranked search results
content:
application/json:
schema:
$ref: '#/components/schemas/SchoolSearchResponse'
post:
tags:
- schools
operationId: searchSchools
summary: Search and rank language schools
description: Typo-tolerant search over approved language schools, ranked by match against the supplied preferences. Free-text `query` plus optional structured filters. Each hit includes a school URL on Extralingo for booking/details.
requestBody:
required: false
content:
application/json:
schema:
$ref: '#/components/schemas/SchoolSearchRequest'
examples:
spanish-in-barcelona:
summary: Spanish courses in Barcelona, 3 results
value:
query: ''
language: spanish
cities:
- Barcelona
limit: 3
locale: en
responses:
'200':
description: Ranked search results
content:
application/json:
schema:
$ref: '#/components/schemas/SchoolSearchResponse'
/school-finder/filters:
get:
tags:
- schools
operationId: getSchoolFilters
summary: List available school search filters
description: Returns the facet values (languages, countries, cities, course types, accommodation types, atmosphere tags, school/class sizes, etc.) that can be used as filters in POST /api/school-finder/search.
parameters:
- $ref: '#/components/parameters/Locale'
responses:
'200':
description: Available filter options
content:
application/json:
schema:
type: object
properties:
success:
type: boolean
data:
type: object
additionalProperties: true
/schools/{schoolId}:
get:
tags:
- schools
operationId: getSchool
summary: School profile, images and booking flags
description: Pass include_hero_image=1 to also receive a compressed JPEG (base64) for chat display. Image URLs are always included.
parameters:
- name: schoolId
in: path
required: true
schema:
type: integer
description: Craft school id from search hits (`school_id`).
- $ref: '#/components/parameters/Locale'
- name: include_hero_image
in: query
schema:
type: boolean
default: false
responses:
'200':
description: OK
content:
application/json:
schema:
type: object
additionalProperties: true
'400':
description: Bad request
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'401':
description: Email verification required
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: Not found
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'422':
description: Validation failed or idempotency key reused with a different payload
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'429':
description: Rate limited
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/schools/{schoolId}/courses:
get:
tags:
- schools
operationId: listCourses
summary: Live course catalogue
parameters:
- name: schoolId
in: path
required: true
schema:
type: integer
description: Craft school id from search hits (`school_id`).
- $ref: '#/components/parameters/Locale'
- name: currency
in: query
schema:
type: string
default: EUR
- name: startDate
in: query
schema:
type: string
responses:
'200':
description: OK
content:
application/json:
schema:
type: object
additionalProperties: true
'400':
description: Bad request
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'401':
description: Email verification required
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: Not found
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'422':
description: Validation failed or idempotency key reused with a different payload
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'429':
description: Rate limited
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/schools/{schoolId}/starting-dates:
get:
tags:
- schools
operationId: listStartingDates
summary: Allowed course start dates
parameters:
- name: schoolId
in: path
required: true
schema:
type: integer
description: Craft school id from search hits (`school_id`).
- $ref: '#/components/parameters/Locale'
responses:
'200':
description: OK
content:
application/json:
schema:
type: object
additionalProperties: true
'400':
description: Bad request
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'401':
description: Email verification required
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: Not found
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'422':
description: Validation failed or idempotency key reused with a different payload
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'429':
description: Rate limited
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/schools/{schoolId}/accommodations:
get:
tags:
- schools
operationId: listAccommodations
summary: Accommodation groups
parameters:
- name: schoolId
in: path
required: true
schema:
type: integer
description: Craft school id from search hits (`school_id`).
- $ref: '#/components/parameters/Locale'
- name: currency
in: query
schema:
type: string
default: EUR
- name: startDate
in: query
schema:
type: string
responses:
'200':
description: OK
content:
application/json:
schema:
type: object
additionalProperties: true
'400':
description: Bad request
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'401':
description: Email verification required
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: Not found
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'422':
description: Validation failed or idempotency key reused with a different payload
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'429':
description: Rate limited
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
components:
schemas:
Error:
type: object
properties:
success:
type: boolean
examples:
- false
error:
type: string
code:
type: string
hint:
type: string
retryAfter:
type: integer
description: Seconds until the daily account-school limit resets (Europe/Amsterdam midnight).
SchoolSearchResponse:
type: object
properties:
success:
type: boolean
data:
type: object
properties:
hits:
type: array
description: Ranked schools. Each hit includes school_id, title, location, Extralingo URL, and indicative pricing. Prices are not a booking quote.
items:
type: object
additionalProperties: true
totalHits:
type: integer
query:
type: string
facetDistribution:
type: object
additionalProperties: true
SchoolSearchRequest:
type: object
description: All fields optional. Omitted fields are not constrained.
properties:
query:
type: string
description: Free-text query (school name, keywords).
locale:
type: string
enum:
- en
- nl
- da
- sv
default: en
language:
type: string
description: Language slug, e.g. "spanish".
country:
type: string
description: Country name as returned by /filters.
cities:
type: array
items:
type: string
description: City names as returned by /filters.
course_type_titles:
type: array
items:
type: string
accommodation_type_titles:
type: array
items:
type: string
atmosphere_tags:
type: array
items:
type: string
accreditations:
type: array
items:
type: string
class_size:
type: string
school_size:
type: string
age:
type: string
facets:
type: array
items:
type: string
description: Facet fields to return distributions for.
limit:
type: integer
minimum: 1
maximum: 200
default: 50
offset:
type: integer
minimum: 0
default: 0
parameters:
Locale:
name: Locale
in: query
required: false
schema:
type: string
description: Referenced by this document but never defined in it. API Evangelist added this empty placeholder so the document resolves; the shape is unknown and is NOT a claim about the API.
x-ae-placeholder: true
securitySchemes:
agentToken:
type: http
scheme: bearer
description: OAuth 2.1 access token from POST /oauth/token (authorization code + PKCE). See /auth.md.