REST · JSON · OCTO. A disponibilidade real das tuas aulas, 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.
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).
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.
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 Externos → 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": "BOKUN-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/aulas/…" }
}
]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/aulas/a1b2c3d4-…"
}
],
"_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/aulas/a1b2c3d4-…" }
}
]
}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/aulas/a1b2c3d4-…" }
}
]
}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).
Acima de 120 pedidos/min por chave. Espera o Retry-After (60s). Cada resposta traz X-RateLimit-Remaining.
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.
O caminho v2 para marcas de equipamento, apps e IA. Chave de plataforma com scope sizing e/ou forecast — determinístico, sem dados pessoais, nunca toca em reservas. 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.
Condições do spot — a mesma shape pública, sanitizada (nunca expõe modelo nem fontes). Scope forecast.
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 afiliado 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. Já desenhado para falar com adaptadores existentes (FareHarbor, Booking Layer) e com qualquer comprador OCTO — Bókun e os marketplaces que ele alimenta.
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. Gera a chave da tua escola no Centro de Controlo e faz a primeira chamada hoje.
Abrir o Centro de Controlo Ver o descritor