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.
{
"spot": "Carcavelos",
"date": "2026-06-22",
"time": "10:00",
"level": "iniciante",
"capacity": 6,
"vacancy": 4
}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.
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.
Ofrecen clases de surf como extra al huésped, con reserva en tiempo real — sin llamadas, sin coordinación manual.
Incluyen clases de surf en cualquier paquete, reservables directamente vía API, con idempotencia en peticiones repetidas.
Añaden surf a cualquier itinerario de grupo y confirman disponibilidad en tiempo real, con plazas libres en directo.
Muestran escuelas, spots y disponibilidad en directo. El scope forecast añade las condiciones por spot.
El alojamiento local y los apartamentos hacen upsell de surf en el checkout — confirmado en segundos vía API.
Una integración. Todas las escuelas de la plataforma. Plazas reales, precios reales, anti-overbooking — confirmado en milisegundos.
No es la misma API para todos. Cada clave está limitada (least-privilege) a lo que ese socio necesita — nunca más que eso.
Leen las clases disponibles y crean reservas en nombre del huésped/cliente. Camino v1 (OCTO). El acceso de quien distribuye clases.
Recomiendan la tabla/neopreno correctos y leen las condiciones del spot. Camino v2, con scope sizing y/o forecast — nunca tocan reservas.
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.
Todo en REST + JSON, autenticado con la clave de la escuela.
Las clases reales con día, hora, spot, nivel, plazas y precio. Filtra por fecha y nivel. Formatos sb · fh · bl · octo.
Los tipos de clase de la escuela (nivel, grupo/privada, rango de precio) — en nativo SB o como products OCTO.
Crea, consulta y cancela reservas en nombre del cliente final. Idempotente por externalRef, con revalidación de plazas y ratios.
El descriptor es público. Pégalo en el terminal:
# 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).
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:
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.
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.
JSON-RPC 2.0, protocolo MCP 2024-11-05. Cabecera Authorization: Bearer sbek_…. La escuela sale siempre de la clave, nunca de los argumentos.
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.
Revoca la clave y caduca las propuestas pendientes que pidió.
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
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: sbpk_xxxx… — el formato canónico de SurfBooking.
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.
Base: https://www.surfbooking.eu/api/partner/v1
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.
Clases reservables. Parámetros: from, to, level?, format? (sb·fh·bl·octo). Por defecto: from=hoy, to=+30 días.
Alias OCTO de /availabilities — asume format=octo por defecto (plug-and-play OCTO).
Tipos de clase de la escuela. format? (sb·octo) — en OCTO devuelve products.
Alias OCTO de /services — asume format=octo por defecto. Array de products OCTO.
Identidad del proveedor (descriptor OCTO supplier): id, name, endpoint, contact, locales, timeZone.
Crea una reserva. Cuerpo: lessonSlotId, customerName, customerEmail, customerPhone?, participants?, externalRef?, notes?.
Consulta el estado de una reserva.
Cancela una reserva.
El descriptor — GET /api/partner/v1 (sin clave):
{
"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):
{
"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": "…" }
}El cuerpo de una reserva y lo que recibes de vuelta — tal como la API responde hoy.
Crear una reserva — 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:
{
"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:
[
{
"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):
{
"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):
{
"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):
{
"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.
Cada error trae un cuerpo JSON { "error": "…" } — legible por máquina.
Clave ausente, demasiado corta, inválida o revocada. Incluye un hint cuando falta la cabecera.
Cuerpo incompleto, email mal formado, o intervalo de fechas inválido (máx 180 días, from ≤ to).
La clase o la reserva no existe en esta escuela — o, en el DELETE, ya había sido cancelada.
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).
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ó.
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.
Por encima de 120 peticiones/min por clave. Espera el Retry-After (60s). Cada respuesta trae X-RateLimit-Remaining.
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:
# 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:
# 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.
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.
El intervalo from–to 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.
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.
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.
Tabla recomendada por level + weight. Scope sizing.
Tabla ajustada al día: level, weight, swellPeriodS, swellDirectionDeg, bestSwellDirDeg. Scope sizing.
Talla de neopreno por weight + height. Scope sizing.
Leash por boardSize + category (board·soft_board). Scope sizing.
Botas por shoeSizeEu (ej.: 42). Scope sizing.
Lista los spots que puedes consultar — usa un id de aquí en /conditions/:spotId. Scope forecast.
Condiciones del spot — la misma shape pública, sanitizada (nunca expone el modelo ni las fuentes). Scope forecast.
Los mejores spots del país ahora mismo, ordenados por el score en directo — limit + level. Scope forecast.
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.
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:
curl -s "https://www.surfbooking.eu/api/partner/v2/sizing/board?level=beginner&weight=75" \
-H "X-Partner-API-Key: sbpd_xxxxxxxxxxxxxxxxxxxxxxxx"{ "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.
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.
<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).
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.
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.
Ofrece clases de verdad a tus huéspedes sin gestionar nada — la reserva y el pago se quedan en SurfBooking.
Sincroniza la disponibilidad en tiempo real, sin doble reserva. OCTO de fábrica.
Lista la oferta de las escuelas y encamina la reserva — con plazas y ratios siempre revalidados de nuestro lado.
Cada clave ve solo la oferta de su propia escuela. Revócala con un clic y el acceso muere al instante.
Cada reserva revalida plazas y ratios de instructor dentro de una transacción. Agotado es agotado.
El flujo de dinero se queda de nuestro lado — el socio encamina, SurfBooking confirma.
Solo sale lo necesario para la reserva. Los contactos de tus alumnos no acaban en la lista de nadie.
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