Permite aos teus clientes reservar aulas de surf diretamente na tua plataforma. REST · JSON · OCTO — disponibilidade real de cada escola, legível por qualquer marketplace ou channel manager. Liga uma vez, chega a muitos.
{
"spot": "Carcavelos",
"date": "2026-06-22",
"time": "10:00",
"level": "iniciante",
"capacity": 6,
"vacancy": 4
}Sem protocolo fechado. Falamos OCTO — o standard aberto das reservas de atividades. Integras uma vez, chegas a toda a gente.
OCTO (octo.travel) é como os sistemas de reservas, channel managers e marketplaces de atividades falam entre si. Uma integração contra a SurfBooking, e a oferta fica legível por qualquer comprador OCTO. Para quem prefere, também devolvemos o formato nativo SB e variantes para adaptadores existentes.
Se distribuis experiências — um hotel, uma agência, um DMC, uma app de turismo ou uma plataforma de alojamento — a API da SurfBooking coloca disponibilidade real de aulas de surf nas tuas mãos.
Oferecem aulas de surf como extra ao hóspede, com reserva em tempo real — sem telefonemas, sem coordenação manual.
Incluem aulas de surf em qualquer pacote, diretamente reserváveis via API, com idempotência em pedidos repetidos.
Adicionam surf a qualquer roteiro e confirmam disponibilidade em tempo real, com vagas ao vivo.
Mostram escolas, spots e disponibilidade ao vivo. Scope forecast adiciona condições por spot.
Alojamento local e apartamentos fazem upsell de surf no checkout — confirmado em segundos via API.
Uma integração. Todas as escolas da plataforma. Vagas reais, preços reais, anti-overbooking — confirmado em milissegundos.
Não é a mesma API para todos. Cada chave é limitada (least-privilege) ao que esse parceiro precisa — nunca mais do que isso.
Lêem as aulas disponíveis e criam reservas em nome do hóspede/cliente. Caminho v1 (OCTO). O acesso de quem distribui aulas.
Recomendam a prancha/fato certos e lêem as condições do spot. Caminho v2, com scope sizing e/ou forecast — nunca tocam em reservas.
Trazem clientes e recebem comissão via /aff + cookie de 90 dias. Sem chave, sem integração técnica.
As chaves de plataforma carregam scopes. Uma chave de sizing só abre os endpoints de sizing — tudo o resto devolve 403 insufficient_scope.
Tudo em REST + JSON, autenticado por chave da escola.
As aulas reais com dia, hora, spot, nível, vagas e preço. Filtra por data e nível. Formatos sb · fh · bl · octo.
Os tipos de aula da escola (nível, grupo/privada, intervalo de preço) — em nativo SB ou como products OCTO.
Cria, consulta e cancela reservas em nome do cliente final. Idempotente por externalRef, com revalidação de vagas e rácios.
O descritor é público. Cola no terminal:
# ver a API (sem chave) curl -s https://www.surfbooking.eu/api/partner/v1
Contrato completo, máquina-legível — pensado para agentes de IA e geradores de SDK auto-descobrirem a API: /openapi.json (OpenAPI 3.1) · referência interativa em /docs (Swagger UI).
Reserva em 2 passos com 2 chamadas — segura a vaga enquanto o teu cliente paga, depois 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"
Com a chave da escola, lês a disponibilidade — aqui em 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"Limite: 120 pedidos/min por chave. Cada resposta traz X-RateLimit-Limit e X-RateLimit-Remaining; ao exceder recebes 429 com Retry-After: 60.
Além da API de parceiros, cada escola pode ligar um assistente MCP à sua própria operação. Está desligado por defeito e ainda não foi validado com um cliente real.
JSON-RPC 2.0, protocolo MCP 2025-06-18. Cabeçalho Authorization: Bearer sbek_…. A escola vem sempre da chave, nunca dos argumentos.
Gera a chave com a sessão do dono. Corpo: label, role, staffId?, scopes (read, ou read e propose), expiresInDays (30, 90 ou 365). A chave vem uma única vez.
Revoga a chave e expira as propostas pendentes que ela pediu.
Só o dono. Envia o payloadHash que viu; a mudança passa pelo mesmo caminho do painel, e uma aula que mudou entretanto fica em conflito.
Ferramentas: 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
Limites: 60 chamadas por minuto por chave e 2000 por dia. Sem ferramentas de dinheiro, e nada se aplica sem a confirmação do dono. O detalhe está na página MCP. /mcp
Cada escola gera a sua própria chave no Centro de Controlo — e revoga-a quando quiser. A chave segue num cabeçalho, em qualquer um dos dois formatos:
X-Partner-API-Key: sbpk_xxxx… — o formato canónico da SurfBooking.
Authorization: Bearer sbpk_xxxx… — para clientes que falam OCTO. A mesma chave.
Gera e revoga chaves em Centro de Controlo → Canais de venda → API Parceiros. Nunca guardamos a chave em claro — só o seu resumo.
Base: https://www.surfbooking.eu/api/partner/v1
Descritor da API (raiz, sem chave). Devolve name, version, auth, octo e o mapa completo de endpoints. Abrir no browser redireciona para esta página.
Aulas reserváveis. Parâmetros: from, to, level?, format? (sb·fh·bl·octo). Defaults: from=hoje, to=+30 dias.
Alias OCTO de /availabilities — assume format=octo por defeito (plug-and-play OCTO).
Tipos de aula da escola. format? (sb·octo) — em OCTO devolve products.
Alias OCTO de /services — assume format=octo por defeito. Array de products OCTO.
Identidade do fornecedor (descritor OCTO supplier): id, name, endpoint, contact, locales, timeZone.
Cria reserva. Corpo: lessonSlotId, customerName, customerEmail, customerPhone?, participants?, externalRef?, notes?.
Consulta o estado de uma reserva.
Cancela uma reserva.
O descritor — GET /api/partner/v1 (sem chave):
{
"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" }
}
} Identidade do fornecedor — 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": "…" }
}O corpo de uma reserva e o que recebes de volta — tal como a API responde hoje.
Criar uma 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": "EXT-7782",
"notes": "Primeira aula"
}'Resposta — 201 Created:
{
"ok": true,
"bookingId": "f1e2d3c4-…",
"createdAt": "2026-06-21T11:42:00.000Z",
"lessonSlotId": "a1b2c3d4-…",
"schoolId": "…",
"status": "confirmed",
"participants": 2,
"totalAmountCents": 7000,
"currency": "EUR"
}Disponibilidade em OCTO — GET /availabilities?format=octo devolve um 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/…" }
}
]Preços em cents (minor units) — 3500 = 35,00 €, conforme currencyPrecision: 2 do OCTO. As datas vêm em hora local da escola (Europe/Lisbon).
A mesma disponibilidade noutros formatos. Nativo SB — ?format=sb (envelope com _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" }
}Outro sistema de reservas — ?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" }
}
]
}Outro sistema de reservas — ?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" }
}
]
}Em octo a resposta é um array simples (sem envelope). Em sb/fh vem em availabilities; em bl, em data.
Cada erro traz um corpo JSON { "error": "…" } — legível por máquina.
Chave ausente, demasiado curta, inválida ou revogada. Inclui hint quando falta o cabeçalho.
Corpo incompleto, email malformado, ou intervalo de datas inválido (máx 180 dias, from ≤ to).
A aula ou a reserva não existe nesta escola — ou, no DELETE, já tinha sido cancelada.
Conflito de estado: sem vagas, aula no passado, fechada à venda, rácio de instrutor excedido, ou externalRef repetido (idempotência — devolve o bookingId que já existe).
A chave é válida mas não alcança esse recurso: a reserva ou a aula é de outra escola. Uma chave só vê o que é da escola que a criou.
A reserva estava a aguardar confirmação e a janela passou. Não é um erro do teu lado: o lugar foi devolvido a quem o quiser. Cria outra vez.
Acima de 120 pedidos/min por chave. Espera o Retry-After (60s). Cada resposta traz X-RateLimit-Remaining.
Falhámos nós. Volta a tentar com o mesmo externalRef: a criação de reservas é idempotente por essa chave, portanto repetir não duplica nada.
Chave em falta ou inválida — 401:
# sem cabeçalho de chave { "error": "missing_api_key", "hint": "Set X-Partner-API-Key header (or Authorization: Bearer)" } # chave inexistente ou revogada { "error": "invalid_api_key" }
Sem vagas suficientes (anti-overbooking) — 409:
# a aula já não tem lugares para o nº de participantes { "error": "insufficient_spots", "remaining": 1 } # externalRef repetido → idempotência: devolve o bookingId existente { "error": "external_ref_exists", "bookingId": "f1e2d3c4-…" }
A revalidação de vagas e rácios corre dentro de uma transação com SELECT … FOR UPDATE — esgotado é esgotado, nunca há dupla-marcação.
Cada resposta traz X-RateLimit-Limit e X-RateLimit-Remaining. Ao passar, um 429 com Retry-After: 60. Não é preciso adivinhar: os números vêm em todas as respostas.
O intervalo from–to é o que limita a resposta; acima de 180 dias devolve 400. Não há paginação por cursor de propósito: uma aula tem data, e pedir por datas é a paginação natural deste domínio. Se precisares de mais, são dois pedidos.
Revoga as que não usas antes de criar novas. Uma chave revogada deixa de servir no pedido seguinte, sem espera.
Estes três números são lidos do código que serve a API, não escritos aqui à mão: se mudarem lá, esta página fica errada e há uma prova a dizê-lo.
O caminho v2 para marcas de equipamento, apps e IA. Chave de plataforma com scope sizing, forecast e/ou brand:read — determinístico, sem dados pessoais, nunca toca em reservas. Descobre os teus scopes em /api/partner/v2/meta. Base: https://www.surfbooking.eu/api/partner/v2.
Prancha recomendada por level + weight. Scope sizing.
Prancha afinada ao dia: level, weight, swellPeriodS, swellDirectionDeg, bestSwellDirDeg. Scope sizing.
Tamanho de fato por weight + height. Scope sizing.
Leash por boardSize + category (board·soft_board). Scope sizing.
Botas por shoeSizeEu (ex.: 42). Scope sizing.
Lista os spots que podes consultar — usa um id daqui em /conditions/:spotId. Scope forecast.
Condições do spot — a mesma shape pública, sanitizada (nunca expõe modelo nem fontes). Scope forecast.
Os melhores spots do país agora, ordenados pelo score ao vivo — limit + level. Scope forecast.
Para marcas de equipamento: quantas vezes cada tamanho da tua marca foi usado em aulas, por month (YYYY-MM). Só os teus dados. Scope brand:read.
Em que spots o equipamento da tua marca foi mais usado, últimos months (1–12). Scope brand:read.
Recomendação de prancha — 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" } }As chaves de plataforma (sbpd_…) são emitidas pela SurfBooking, não pela escola. Scope errado → 403 insufficient_scope. Limite 240 pedidos/min por chave, com Retry-After: 60 ao exceder.
Uma página iframe self-contained, "Powered by SurfBooking". Mostra as condições do pico, recomenda a prancha pelo peso e nível, e leva o cliente a reservar uma aula — com o teu link de parceiro premium embutido. PII-free, sem cookies de seguimento.
<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 = a tua chave de plataforma (scope sizing, e forecast se quiseres as condições no topo). spot e slug são opcionais — o slug liga as reservas geradas ao teu /aff (cookie de 90 dias).
A base é /api/partner/v1. Mudanças que quebram compatibilidade entram numa versão nova (/v2) — a v1 não tem depreciação prevista. Podemos acrescentar campos sem aviso, por isso lê de forma tolerante: ignora o que ainda não conheces.
Qualquer parceiro que queira vender ou mostrar aulas de surf reais. Desenhado no padrão aberto OCTO, que muitos sistemas de reservas e channel managers já falam.
Oferece aulas reais aos hóspedes sem gerir nada — a reserva e o pagamento ficam na SurfBooking.
Sincroniza a disponibilidade em tempo real, sem dupla-marcação. OCTO de fábrica.
Lista a oferta das escolas e encaminha a reserva — com vagas e rácios sempre revalidados do nosso lado.
Cada chave vê só a oferta da própria escola. Revoga num clique e o acesso morre na hora.
Cada reserva revalida vagas e rácios de instrutor dentro de uma transação. Esgotado é esgotado.
O fluxo de dinheiro fica do nosso lado — o parceiro encaminha, a SurfBooking confirma.
Só sai o necessário para a reserva. Os contactos dos teus alunos não viram lista de ninguém.
A API está viva. Se tens uma escola de surf, geras a tua própria chave no Centro de Controlo. Se és parceiro externo — marca de equipamento, app, IA ou hotel — pedes uma chave de plataforma (emitida pela SurfBooking).
Sou escola · Abrir o Centro de Controlo Sou parceiro externo · Pedir acesso Ver o descritor