Surf Booking.PTAPI
ManifiestoAgentCapa InteligenteTecnologíaConstituciónIAMCPPartner API
API para socios

Una integración.Mil canales.

Permite a tus clientes reservar clases de surf directamente en tu plataforma. REST · JSON · OCTO — disponibilidad real de cada escuela, legible por cualquier marketplace o channel manager. Conecta una vez, llega a muchos.

API activa · Bearer / X-Partner-API-Key
surfbooking.eu/developers
/api/partner/v1/availabilities
GET
{
  "spot":     "Carcavelos",
  "date":     "2026-06-22",
  "time":     "10:00",
  "level":    "iniciante",
  "capacity": 6,
  "vacancy":  4
}
Plataforma abierta

Sin protocolo cerrado. Hablamos OCTO — el estándar abierto de las reservas de actividades. Integras una vez, llegas a todo el mundo.

OCTO (octo.travel) es como los sistemas de reservas, channel managers y marketplaces de actividades hablan entre sí. Una integración contra SurfBooking, y la oferta queda legible por cualquier comprador OCTO. Para quien lo prefiera, también devolvemos el formato nativo SB y variantes para adaptadores existentes.

Quién se conecta

Cinco tipos de socio. Una API.

Si distribuyes experiencias — un hotel, una agencia, un DMC, una app de turismo o una plataforma de alojamiento — la API de SurfBooking pone disponibilidad real de clases de surf en tus manos.

Hoteles

Experiencia en el check-in

Ofrecen clases de surf como extra al huésped, con reserva en tiempo real — sin llamadas, sin coordinación manual.

Agencias de viajes

Paquetes con surf

Incluyen clases de surf en cualquier paquete, reservables directamente vía API, con idempotencia en peticiones repetidas.

DMCs

Surf en el itinerario

Añaden surf a cualquier itinerario de grupo y confirman disponibilidad en tiempo real, con plazas libres en directo.

Apps de turismo

Listados + disponibilidad en directo

Muestran escuelas, spots y disponibilidad en directo. El scope forecast añade las condiciones por spot.

Alojamiento

Upsell de experiencias

El alojamiento local y los apartamentos hacen upsell de surf en el checkout — confirmado en segundos vía API.

Cómo funciona

En 5 segundos, cualquier CTO lo entiende.

Tu plataforma
Hotel · OTA · Agencia · App
SurfBooking API
REST · JSON · OCTO
Escuelas
Disponibilidad
Pagos
Reservas

Una integración. Todas las escuelas de la plataforma. Plazas reales, precios reales, anti-overbooking — confirmado en milisegundos.

Socios diferentes, accesos diferentes

Cada socio se conecta solo a lo que le sirve.

No es la misma API para todos. Cada clave está limitada (least-privilege) a lo que ese socio necesita — nunca más que eso.

Hoteles · OTAs · channel managers

Disponibilidad + reservas

Leen las clases disponibles y crean reservas en nombre del huésped/cliente. Camino v1 (OCTO). El acceso de quien distribuye clases.

Marcas de material · apps · IA

Tallas + condiciones

Recomiendan la tabla/neopreno correctos y leen las condiciones del spot. Camino v2, con scope sizing y/o forecast — nunca tocan reservas.

Partners

Atribución, sin API

Traen clientes y cobran comisión vía /aff + cookie de 90 días. Sin clave, sin integración técnica.

Las claves de plataforma llevan scopes. Una clave de sizing solo abre los endpoints de sizing — todo lo demás devuelve 403 insufficient_scope.

Qué hace la API

Tres cosas. Disponibilidad, servicios, reservas.

Todo en REST + JSON, autenticado con la clave de la escuela.

availabilities

Leer disponibilidad

Las clases reales con día, hora, spot, nivel, plazas y precio. Filtra por fecha y nivel. Formatos sb · fh · bl · octo.

services

Listar servicios

Los tipos de clase de la escuela (nivel, grupo/privada, rango de precio) — en nativo SB o como products OCTO.

bookings

Crear y gestionar reservas

Crea, consulta y cancela reservas en nombre del cliente final. Idempotente por externalRef, con revalidación de plazas y ratios.

En curso

Una llamada y ves la API responder.

El descriptor es público. Pégalo en el terminal:

terminal · descriptor de la API
# ver la API (sin clave)
curl -s https://www.surfbooking.eu/api/partner/v1

Contrato completo, legible por máquina — pensado para que agentes de IA y generadores de SDK autodescubran la API: /openapi.json (OpenAPI 3.1) · referencia interactiva en /docs (Swagger UI).

OCTO
Para OTAs y revendedores
Productos, disponibilidad y reserva en 2 pasos (hold → confirm). Plug-and-play estilo Bókun/Rezdy.
iCal
Universal, en los dos sentidos
Importa el feed de cualquier canal al calendario SB — y exporta el calendario SB (con cancelaciones) de vuelta al canal.
MCP
Para agentes de IA
11 herramientas — buscar clases, score de surf en directo por spot, tallas de material — vía Model Context Protocol.

Reserva en 2 pasos con 2 llamadas — bloquea la plaza mientras tu cliente paga, luego confirma:

# 1 — hold (expira sozinho; a vaga fica segura)
curl -X POST https://www.surfbooking.eu/api/partner/v1/bookings   -H "X-Partner-API-Key: A_TUA_CHAVE" -H "Content-Type: application/json"   -d '{"lessonSlotId":"…","customerName":"…","customerEmail":"…",
       "status":"ON_HOLD","expirationMinutes":30}'

# 2 — confirm (idempotente; hold expirado devolve 410 e liberta a vaga)
curl -X POST https://www.surfbooking.eu/api/partner/v1/bookings/{id}/confirm   -H "X-Partner-API-Key: A_TUA_CHAVE"

Con la clave de la escuela, lees la disponibilidad — aquí en formato OCTO:

terminal · disponibilidad (OCTO)
curl -s "https://www.surfbooking.eu/api/partner/v1/availabilities?format=octo&from=2026-07-01&to=2026-07-07" \
  -H "Authorization: Bearer sbpk_xxxxxxxxxxxxxxxxxxxxxxxx"

Límite: 120 peticiones/min por clave. Cada respuesta trae X-RateLimit-Limit y X-RateLimit-Remaining; al excederlo recibes 429 con Retry-After: 60.

Conector privado de escuela

Un asistente dentro de tu escuela, con una clave solo tuya.

Además de la API de socios, cada escuela puede conectar un asistente MCP a su propia operación. Está desactivado por defecto y aún no se ha validado con un cliente real.

POST

/api/mcp/escola

JSON-RPC 2.0, protocolo MCP 2024-11-05. Cabecera Authorization: Bearer sbek_…. La escuela sale siempre de la clave, nunca de los argumentos.

POST

/api/schools/:id/conector/tokens

Genera la clave con la sesión del propietario. Cuerpo: label, role, staffId?, scopes (read, o read y propose), expiresInDays (30, 90 o 365). La clave se devuelve una sola vez.

DELETE

/api/schools/:id/conector/tokens/:tokenId

Revoca la clave y caduca las propuestas pendientes que pidió.

POST

/api/schools/:id/conector/propostas/:pid/confirmar

Solo el propietario. Envía el payloadHash que vio; el cambio pasa por el mismo camino que el panel, y una clase que cambió entretanto queda en conflicto.

Herramientas: list_my_schools · get_school_schedule · get_bookings_summary · get_lesson_roster · get_stock_summary · get_conditions_for_my_lessons · prepare_lesson_move · prepare_stock_change · list_pending_proposals

Límites: 60 llamadas por minuto por clave y 2000 al día. Sin herramientas de dinero, y nada se aplica sin la confirmación del propietario. El detalle está en la página MCP. /mcp

Autenticación

Una clave por escuela. Tú mandas.

Cada escuela genera su propia clave en SurfBooking OS — y la revoca cuando quiera. La clave va en una cabecera, en cualquiera de los dos formatos:

X-Partner-API-Key

Cabecera nativa SB

X-Partner-API-Key: sbpk_xxxx… — el formato canónico de SurfBooking.

Authorization: Bearer

Compatible con OCTO

Authorization: Bearer sbpk_xxxx… — para clientes que hablan OCTO. La misma clave.

Genera y revoca claves en SurfBooking OS → Canales Externos → API Socios. Nunca guardamos la clave en claro — solo su resumen.

Referencia

Los endpoints.

Base: https://www.surfbooking.eu/api/partner/v1

GET

/

Descriptor de la API (raíz, sin clave). Devuelve name, version, auth, octo y el mapa completo de endpoints. Abrirlo en el navegador redirige a esta página.

GET

/availabilities

Clases reservables. Parámetros: from, to, level?, format? (sb·fh·bl·octo). Por defecto: from=hoy, to=+30 días.

GET

/availability

Alias OCTO de /availabilities — asume format=octo por defecto (plug-and-play OCTO).

GET

/services

Tipos de clase de la escuela. format? (sb·octo) — en OCTO devuelve products.

GET

/products

Alias OCTO de /services — asume format=octo por defecto. Array de products OCTO.

GET

/supplier

Identidad del proveedor (descriptor OCTO supplier): id, name, endpoint, contact, locales, timeZone.

POST

/bookings

Crea una reserva. Cuerpo: lessonSlotId, customerName, customerEmail, customerPhone?, participants?, externalRef?, notes?.

GET

/bookings/:id

Consulta el estado de una reserva.

DELETE

/bookings/:id

Cancela una reserva.

El descriptor — GET /api/partner/v1 (sin clave):

respuesta · descriptor
{
  "name": "SurfBooking Partner API v1",
  "version": "1.0.0",
  "auth": "X-Partner-API-Key header, ou Authorization: Bearer  (compatível OCTO).",
  "octo": {
    "supported": true,
    "formatParam": "octo",
    "supplierEndpoint": "/api/partner/v1/supplier"
  },
  "endpoints": {
    "availabilities": { "method": "GET", "path": "/api/partner/v1/availabilities" },
    "services":       { "method": "GET", "path": "/api/partner/v1/services" },
    "supplier":       { "method": "GET", "path": "/api/partner/v1/supplier" },
    "createBooking":  { "method": "POST", "path": "/api/partner/v1/bookings" },
    "getBooking":     { "method": "GET", "path": "/api/partner/v1/bookings/:id" },
    "cancelBooking":  { "method": "DELETE", "path": "/api/partner/v1/bookings/:id" }
  }
}

Identidad del proveedor — GET /supplier (OCTO):

respuesta · supplier (OCTO)
{
  "id": "school-uuid-…",
  "name": "Nome da Escola",
  "endpoint": "https://www.surfbooking.eu/api/partner/v1",
  "contact": { "website": "https://www.surfbooking.eu", "email": null, "telephone": null, "address": null },
  "locales": ["pt", "en"],
  "timeZone": "Europe/Lisbon",
  "_sb": { "description": "…", "logoUrl": "…" }
}
Ejemplos

Petición y respuesta, de verdad.

El cuerpo de una reserva y lo que recibes de vuelta — tal como la API responde hoy.

Crear una reserva — POST /bookings:

petición · POST /bookings
curl -s -X POST https://www.surfbooking.eu/api/partner/v1/bookings \
  -H "Authorization: Bearer sbpk_xxxxxxxxxxxxxxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{
    "lessonSlotId": "a1b2c3d4-…",
    "customerName": "Ana Silva",
    "customerEmail": "[email protected]",
    "customerPhone": "+351912345678",
    "participants": 2,
    "externalRef": "BOKUN-7782",
    "notes": "Primeira aula"
  }'

Respuesta — 201 Created:

respuesta · 201
{
  "ok": true,
  "bookingId": "f1e2d3c4-…",
  "createdAt": "2026-06-21T11:42:00.000Z",
  "lessonSlotId": "a1b2c3d4-…",
  "schoolId": "…",
  "status": "confirmed",
  "participants": 2,
  "totalAmountCents": 7000,
  "currency": "EUR"
}

Disponibilidad en OCTO — GET /availabilities?format=octo devuelve un array:

respuesta · availabilities (OCTO)
[
  {
    "id": "a1b2c3d4-…",
    "localDateTimeStart": "2026-07-02T10:00:00",
    "localDateTimeEnd": "2026-07-02T12:00:00",
    "available": true,
    "status": "AVAILABLE",
    "vacancies": 4,
    "capacity": 6,
    "maxUnits": 4,
    "pricing": {
      "original": 3500, "retail": 3500, "net": 3500,
      "currency": "EUR", "currencyPrecision": 2
    },
    "_sb": { "level": "beginner", "spotName": "…", "bookingUrl": "https://www.surfbooking.eu/aula/…" }
  }
]

Precios en céntimos (minor units) — 3500 = 35,00 €, conforme al currencyPrecision: 2 de OCTO. Las fechas vienen en hora local de la escuela (Europe/Lisbon).

La misma disponibilidad en otros formatos. Nativo SB — ?format=sb (envelope con _meta):

respuesta · availabilities (SB)
{
  "availabilities": [
    {
      "id": "a1b2c3d4-…",
      "date": "2026-07-02",
      "startTime": "10:00",
      "endTime": "12:00",
      "level": "beginner",
      "spotsTotal": 6,
      "spotsRemaining": 4,
      "pricePerPerson": 3500,
      "currency": "EUR",
      "instructorName": "…",
      "spotName": "…",
      "schoolId": "…",
      "schoolName": "…",
      "bookingUrl": "https://www.surfbooking.eu/aula/9f3c1a2b7d"
    }
  ],
  "_meta": { "format": "sb", "total": 1, "from": "2026-07-01", "to": "2026-07-07" }
}

FareHarbor — ?format=fh (envelope availabilities):

respuesta · availabilities (FH)
{
  "availabilities": [
    {
      "pk": "a1b2c3d4-…",
      "start_at": "2026-07-02T10:00:00",
      "end_at": "2026-07-02T12:00:00",
      "capacity": 6,
      "num_remaining": 4,
      "is_available": true,
      "customer_type_rates": [
        { "pk": "a1b2c3d4-…_default", "total": { "amount": "35.00", "currency": "EUR" } }
      ],
      "_sb_meta": { "level": "beginner", "bookingUrl": "https://www.surfbooking.eu/aula/9f3c1a2b7d" }
    }
  ]
}

Booking Layer — ?format=bl (envelope data):

respuesta · availabilities (BL)
{
  "data": [
    {
      "id": "a1b2c3d4-…",
      "date": "2026-07-02",
      "startTime": "10:00",
      "endTime": "12:00",
      "serviceName": "Surf beginner",
      "capacity": 6,
      "spotsLeft": 4,
      "pricePerPerson": 3500,
      "currency": "EUR",
      "_sb_meta": { "level": "beginner", "bookingUrl": "https://www.surfbooking.eu/aula/9f3c1a2b7d" }
    }
  ]
}

En octo la respuesta es un array simple (sin envelope). En sb/fh viene en availabilities; en bl, en data.

Errores

Códigos de estado.

Cada error trae un cuerpo JSON { "error": "…" } — legible por máquina.

401

missing_api_key · invalid_api_key

Clave ausente, demasiado corta, inválida o revocada. Incluye un hint cuando falta la cabecera.

400

missing_fields · invalid_email · invalid_date_range

Cuerpo incompleto, email mal formado, o intervalo de fechas inválido (máx 180 días, from ≤ to).

404

slot_not_found · booking_not_found · booking_not_found_or_already_cancelled

La clase o la reserva no existe en esta escuela — o, en el DELETE, ya había sido cancelada.

409

insufficient_spots · slot_expired · slot_not_purchasable · ratio_exceeded · external_ref_exists

Conflicto de estado: sin plazas, clase en el pasado, cerrada a la venta, ratio de instructor excedido, o externalRef repetido (idempotencia — devuelve el bookingId que ya existe).

403

forbidden · not_owner

La clave es válida pero no alcanza ese recurso: la reserva o la clase es de otra escuela. Una clave solo ve lo de la escuela que la creó.

410

hold_expired

La reserva estaba esperando confirmación y la ventana pasó. No es un error tuyo: la plaza volvió a quien la quiera. Créala de nuevo.

429

rate_limit_exceeded

Por encima de 120 peticiones/min por clave. Espera el Retry-After (60s). Cada respuesta trae X-RateLimit-Remaining.

500

internal_error

Ese es nuestro. Reintenta con el mismo externalRef: crear reservas es idempotente por esa clave, así que repetir no duplica nada.

Clave ausente o inválida — 401:

respuesta · 401
# sin cabecera de clave
{
  "error": "missing_api_key",
  "hint": "Set X-Partner-API-Key header (or Authorization: Bearer)"
}

# clave inexistente o revocada
{ "error": "invalid_api_key" }

Sin plazas suficientes (anti-overbooking) — 409:

respuesta · 409
# la clase ya no tiene plazas para el nº de participantes
{
  "error": "insufficient_spots",
  "remaining": 1
}

# externalRef repetido → idempotencia: devuelve el bookingId existente
{
  "error": "external_ref_exists",
  "bookingId": "f1e2d3c4-…"
}

La revalidación de plazas y ratios corre dentro de una transacción con SELECT … FOR UPDATE — agotado es agotado, nunca hay doble reserva.

Límites

Lo que puedes pedir, y cuánto.

120 / min

Por clave, no por socio

Cada respuesta trae X-RateLimit-Limit y X-RateLimit-Remaining. Al pasarte, un 429 con Retry-After: 60. Sin adivinar: los números viajan en cada respuesta.

180 días

Esa es la página, y no hay cursor

El intervalo fromto es lo que limita la respuesta; por encima de 180 días devuelve 400. No hay paginación por cursor a propósito: una clase tiene fecha, y pedir por fechas es la paginación natural de este dominio. Si necesitas más, son dos peticiones.

50

Claves activas por escuela

Revoca las que no usas antes de crear nuevas. Una clave revocada deja de servir en la petición siguiente, sin espera.

Estos tres números se leen del código que sirve la API, no se escriben aquí a mano: si cambian allí, esta página queda mal y hay una prueba que lo dice.

Tallas + condiciones · v2

Recomienda el equipo correcto. Sin tocar las reservas.

El camino v2 para marcas de equipamiento, apps e IA. Clave de plataforma con scope sizing, forecast y/o brand:read — determinista, sin datos personales, nunca toca reservas. Descubre tus scopes en /api/partner/v2/meta. Base: https://www.surfbooking.eu/api/partner/v2.

GET

/sizing/board

Tabla recomendada por level + weight. Scope sizing.

GET

/sizing/board/conditions

Tabla ajustada al día: level, weight, swellPeriodS, swellDirectionDeg, bestSwellDirDeg. Scope sizing.

GET

/sizing/wetsuit

Talla de neopreno por weight + height. Scope sizing.

GET

/sizing/leash

Leash por boardSize + category (board·soft_board). Scope sizing.

GET

/sizing/boots

Botas por shoeSizeEu (ej.: 42). Scope sizing.

GET

/spots

Lista los spots que puedes consultar — usa un id de aquí en /conditions/:spotId. Scope forecast.

GET

/conditions/:spotId

Condiciones del spot — la misma shape pública, sanitizada (nunca expone el modelo ni las fuentes). Scope forecast.

GET

/intelligence/surf-now

Los mejores spots del país ahora mismo, ordenados por el score en directo — limit + level. Scope forecast.

GET

/brand/equipment-stats

Para marcas de equipamiento: cuántas veces se usó en clases cada talla de tu marca, por month (YYYY-MM). Solo tus datos. Scope brand:read.

GET

/brand/spot-activity

En qué spots se usó más el equipamiento de tu marca, últimos months (1–12). Scope brand:read.

Recomendación de tabla — GET /sizing/board:

terminal · sizing (v2)
curl -s "https://www.surfbooking.eu/api/partner/v2/sizing/board?level=beginner&weight=75" \
  -H "X-Partner-API-Key: sbpd_xxxxxxxxxxxxxxxxxxxxxxxx"
respuesta · sizing
{ "recommendation": { "category": "soft_board", "size": "8'0" } }

Las claves de plataforma (sbpd_…) las emite SurfBooking, no la escuela. Scope equivocado → 403 insufficient_scope. Límite 240 peticiones/min por clave, con Retry-After: 60 al excederlo.

Widget integrable

Tallas en tu web. Una línea.

Una página iframe autocontenida, "Powered by SurfBooking". Muestra las condiciones del spot, recomienda la tabla por peso y nivel, y lleva al cliente a reservar una clase — con tu enlace de socio premium incorporado. Sin PII, sin cookies de seguimiento.

Ejemplo en directo — esto es exactamente lo que ven tus visitantes:
html · embed
<iframe
  src="https://www.surfbooking.eu/w/surf?key=sbpd_xxxx&spot=SPOT_ID&slug=O_TEU_SLUG"
  width="360" height="520" frameborder="0"></iframe>

key = tu clave de plataforma (scope sizing, y forecast si quieres las condiciones arriba). spot y slug son opcionales — el slug liga las reservas generadas a tu /aff (cookie de 90 días).

Versiones

v1 — estable.

La base es /api/partner/v1. Los cambios que rompen compatibilidad entran en una versión nueva (/v2) — la v1 no tiene depreciación prevista. Podemos añadir campos sin aviso, así que lee de forma tolerante: ignora lo que aún no conozcas.

Para quién

Channel managers, marketplaces, hoteles.

Cualquier socio que quiera vender o mostrar clases de surf reales. Diseñado sobre el estándar abierto OCTO, que muchos sistemas de reservas y channel managers ya hablan.

Hoteles & resorts

Ofrece clases de verdad a tus huéspedes sin gestionar nada — la reserva y el pago se quedan en SurfBooking.

Channel managers

Sincroniza la disponibilidad en tiempo real, sin doble reserva. OCTO de fábrica.

Marketplaces

Lista la oferta de las escuelas y encamina la reserva — con plazas y ratios siempre revalidados de nuestro lado.

Tu seguridad

La escuela manda. Siempre.

CLAVE

Por escuela, revocable

Cada clave ve solo la oferta de su propia escuela. Revócala con un clic y el acceso muere al instante.

PLAZAS

Nunca hay overbooking

Cada reserva revalida plazas y ratios de instructor dentro de una transacción. Agotado es agotado.

PAGO

Confirmado en SurfBooking

El flujo de dinero se queda de nuestro lado — el socio encamina, SurfBooking confirma.

ALUMNOS

Datos protegidos

Solo sale lo necesario para la reserva. Los contactos de tus alumnos no acaban en la lista de nadie.

Listo para conectar

Consigue una clave y empieza.

La API está viva. Si tienes una escuela de surf, generas tu propia clave en el SurfBooking OS. Si eres socio externo — marca de material, app, IA u hotel — pides una clave de plataforma (emitida por SurfBooking).

Soy escuela · Abrir el SurfBooking OS Soy socio externo · Pedir acceso Ver el descriptor