Construa a sua própria integração
O seu catálogo, os seus lugares livres, as suas encomendas, os seus bilhetes e as suas leituras podem também ser obtidos por outro programa, que pode ainda criar encomendas por si próprio. Abaixo explicamos como funciona — primeiro em linguagem simples, depois com o código.
- Endereço base
- https://passavo.eu/api/v1
- Versão atual
- 2026-09-20
- A própria descrição
- openapi.json
O que é uma API, e precisa de uma?
Uma API é uma porta nas traseiras da sua conta. Onde clica no seu ecrã de gestão, um programa pode, por essa porta, obter ou escrever diretamente os seus dados — sem ninguém sentado em frente a um ecrã.
Só precisa de uma quando quer algo que o ecrã de gestão não faz: números no seu próprio sistema, lugares no seu próprio site, bilhetes a partir de uma caixa que já tem. Se o puder fazer com cliques, clicar é mais rápido.
Quem constrói uma integração destas — o seu programador, o seu software de contabilidade, alguém que saiba programar — precisa de duas coisas da sua parte: o endereço abaixo e uma chave criada por si.
O que pode construir com ela
Lugares livres no seu próprio site
Mostre na sua página inicial que visitas guiadas ainda têm lugar esta semana, com o seu próprio design e com os números corretos naquele momento.
Alimentar a sua contabilidade
Deixe o seu contabilista ou o seu software de contabilidade obter as vendas do mês anterior, em vez de enviar uma exportação todos os meses.
Um ecrã à entrada
Um tablet no átrio que mostra que horário vai começar e quantos lugares ainda estão livres. Basta um pedido por minuto.
Vender a partir do seu próprio sistema
Crie uma encomenda a partir do programa em que já trabalha, envie ao comprador uma ligação de pagamento e receba, através de um webhook, a informação de que ele pagou.
A API está incluída no plano Pro
As chaves criam-se em Definições → Acesso à API. Esse ecrã aparece no seu menu assim que a sua organização estiver nesse plano; a mudança de plano é feita por si no ecrã de gestão, em Assinatura.
Ver os planos →Experimentar primeiro em segurança
Além de uma chave normal (pv_live_), pode criar uma chave de teste (pv_test_). Funciona com o seu catálogo, horários e lotação reais, e também pode criar encomendas. Uma encomenda de teste nunca passa por um fornecedor de pagamentos — uma página de teste simula o pagamento —, não conta para a sua faturação e é removida após 24 horas. Até lá, retém lugares reais, por isso é preferível trabalhar com um produto criado para esse efeito. O que fica fora da sandbox, como gerir webhooks, é recusado a uma chave de teste com o código sandbox.
Início rápido em cinco passos
Do zero até uma integração que sabe que o pagamento foi feito. Cada passo demora minutos, não dias.
-
Crie uma chave
No seu ecrã de gestão, abra Definições → Acesso à API e crie uma chave apenas com as permissões de que precisa. O token completo só é mostrado uma vez; guarde-o como guarda uma palavra-passe.
-
Faça o seu primeiro pedido
Peça GET /me com a sua chave no cabeçalho Authorization. Recebe a sua organização, o seu plano e as permissões da sua chave. Se isto funcionar, o resto também funciona.
-
Crie uma encomenda
Envie por POST as linhas que quer vender para POST /orders, com uma Idempotency-Key — aqui é obrigatória. Se a ligação falhar a meio, o mesmo pedido repetido não gera uma segunda encomenda. O campo reserved_until indica até quando os lugares ficam retidos para si.
-
Envie o comprador para a ligação de pagamento
Peça a ligação de pagamento com POST /orders/{id}/checkout, juntamente com o endereço para onde o comprador vai depois de pagar. Envie o comprador para essa ligação ou mostre-a na sua própria página. O pagamento passa pelo fornecedor que já ligou; assim que for recebido, os bilhetes são criados e enviados.
-
Deixe um webhook avisá-lo
Prepare um endereço no seu próprio site e registe-o. Assim que houver um pagamento, um cancelamento ou uma leitura, recebe essa informação aí — não precisa de estar sempre a perguntar se já aconteceu alguma coisa.
curl
curl "https://passavo.eu/api/v1/me" \
-H "Authorization: Bearer pv_live_YOUR_API_KEY" \
-H "Accept: application/json"
PHP
use Illuminate\Support\Facades\Http;
$response = Http::acceptJson()
->withToken('pv_live_YOUR_API_KEY')
->get('https://passavo.eu/api/v1/me');
$data = $response->json('data');
JavaScript
const response = await fetch('https://passavo.eu/api/v1/me', {
method: 'GET',
headers: {
Accept: 'application/json',
Authorization: 'Bearer pv_live_YOUR_API_KEY',
},
});
const { data } = await response.json();
Python
import requests
headers = {"Accept": "application/json", "Authorization": "Bearer pv_live_YOUR_API_KEY"}
response = requests.get("https://passavo.eu/api/v1/me", headers=headers)
data = response.json()["data"]
Autenticação
Cada pedido leva a sua chave como bearer token. Uma chave pertence a uma única organização: essa organização é todo o universo desse pedido, e nunca poderá obter por engano dados de outra pessoa.
Authorization: Bearer pv_live_YOUR_API_KEY
Uma chave normal começa por pv_live_, uma chave de sandbox por pv_test_. Esse prefixo não é um segredo, mas uma ajuda: quem o vê num registo sabe logo de onde vem.
O token completo existe durante um único momento, quando é criado. Depois disso, guardamos apenas uma impressão irreversível (sha256). Se o perder, perdeu-o mesmo: revogue a chave e crie uma nova.
Permissões
Uma chave sem permissões não pode fazer nada. Isto é propositadamente o contrário do que seria de esperar: estas chaves são entregues pelos clientes a ferramentas de terceiros, e por isso a predefinição deve ser "nada" e não "tudo".
- read
- Consultar tudo: os seus locais, produtos, preços, lugares livres, descontos, vales-oferta e passes anuais, e também as suas encomendas, bilhetes, compradores e as leituras à entrada.
- write
- Criar encomendas, enviá-las para pagamento, cancelá-las e reembolsá-las; anular ou reenviar bilhetes; fazer o check-in de visitantes; emitir vales-oferta e passes anuais.
- webhooks
- Gerir os seus próprios destinos de webhooks.
- external_payment
- Marcar como paga, sem fornecedor de pagamentos, uma encomenda que custa dinheiro, por exemplo após uma transferência bancária ou um pagamento em dinheiro (POST /orders/{id}/mark-paid). É uma permissão separada de write, para que a atribua apenas a uma caixa ou a uma contabilidade gerida por si. Confirmar uma encomenda de zero euros também é possível sem ela.
Quando algo corre mal
Todos os erros têm a mesma forma, com um código fixo e um texto traduzido. Leia o código e não o texto: o texto pode ser reescrito, o código nunca.
{
"error": {
"code": "validation_failed",
"message": "…",
"details": {}
}
}
| Código | Estado | Quando |
|---|---|---|
| unauthenticated | 401 | Chave em falta, desconhecida, revogada ou expirada. |
| forbidden | 403 | A chave está correta, mas não tem permissão para isto. |
| plan_required | 403 | O plano desta organização não inclui a API. |
| sandbox | 403 | Uma chave de teste tenta fazer algo que fica fora da sandbox, como gerir webhooks. |
| not_found | 404 | Não existe, ou não existe nesta organização. |
| validation_failed | 422 | O próprio pedido não está correto: um filtro desconhecido, uma data inválida. |
| rate_limited | 429 | Demasiados pedidos num minuto. |
| conflict | 409 | A mesma Idempotency-Key já foi utilizada para outra coisa. |
| server_error | 500 | Ocorreu um erro do nosso lado. |
| slot_unavailable | 409 | O horário está cheio, já começou ou é desconhecido, ou não foi escolhido nenhum quando o produto o exige. |
| sold_out | 409 | O produto está esgotado ou já não está à venda. |
| discount_invalid | 422 | O código de desconto não existe, está esgotado ou não se aplica aqui. |
| payment_provider_missing | 409 | A organização não tem nenhum fornecedor de pagamentos ligado. |
| not_cancellable | 409 | A encomenda não pode ser cancelada no seu estado atual. |
| not_refundable | 409 | Não há nada (ou já não há nada) a reembolsar nesta encomenda, ou foi paga fora do fornecedor de pagamentos. |
| check_in_duplicate | 409 | Este código já fez check-in. |
| check_in_invalid | 404 | Este código é desconhecido. |
| check_in_wrong_day | 409 | Este código é válido, mas não hoje. |
| check_in_cancelled | 409 | Este código pertence a um bilhete cancelado ou reembolsado. |
Uma linha de outra organização devolve sempre not_found e nunca uma mensagem a dizer que não tem acesso. Se essa diferença fosse visível, qualquer pessoa com uma chave válida poderia descobrir quantos produtos tem o vizinho, percorrendo os números.
Paginação, ordenação e filtros
As listas chegam por páginas. Não pede a página três, mas o que vem depois da página anterior: a resposta inclui um cursor, que envia para continuar a ler. Assim, uma lista nunca perde linhas quando algo é acrescentado enquanto está a percorrê-la.
| Parâmetro | O que faz |
|---|---|
| page[size] | Quantas linhas por página; por omissão 25, no máximo 100. |
| page[cursor] | O next_cursor da resposta anterior. Se estiver vazio, essa era a última página. |
| sort | Por que campo se ordena. Um hífen antes inverte a ordem. |
| filter[…] | Filtrar por um campo que o endpoint permite. |
| include | Incluir relações na mesma resposta, separadas por vírgulas. |
Um parâmetro que o endpoint não conhece é um erro e não um silêncio. Quem se engana no nome de um filtro deve ser avisado — e não receber, sem dar por isso, a lista inteira sem filtro.
A resposta não inclui propositadamente um total: com dezenas de milhares de linhas, essa contagem custa mais do que a própria página.
{
"data": [ … ],
"meta": { "next_cursor": "…" }
}
Enviar duas vezes, executar uma vez
Em cada pedido que cria ou altera algo, envie uma Idempotency-Key — uma cadeia de carateres única e aleatória. Se o mesmo pedido chegar outra vez com a mesma chave, recebe exatamente a mesma resposta sem que nada aconteça uma segunda vez. Em POST /orders é obrigatória.
Idempotency-Key: 6f1c0b4a-6b2f-4a1b-9c7e-1f2d3e4a5b6c
A mesma chave com outro conteúdo devolve conflict e nada acontece. Uma chave guardada dura 24 horas e é válida por organização.
Versões
A versão está no caminho (/api/v1) e só muda quando há uma rutura; nesse caso, uma segunda versão funciona ao lado da primeira e não em vez dela. Cada pequena adição é datada no cabeçalho Passavo-Version, atualmente 2026-09-20.
O que pode ser acrescentado dentro desta versão: um campo, um endpoint, um novo valor de ordenação ou de filtro, um novo código de erro. Construa, portanto, a sua integração de forma a que um campo desconhecido não a deite abaixo.
O que nunca acontece dentro desta versão: remover ou mudar o nome de um campo, alterar um tipo, dar outro significado a um código ou tornar um parâmetro obrigatório.
Limite de pedidos
Uma chave pode fazer 120 pedidos por minuto. O limite aplica-se por chave e não por endereço, para que dois clientes atrás do mesmo fornecedor de cloud não se atrapalhem.
Cada resposta indica a sua situação em X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset. Se ultrapassar o limite, recebe rate_limited com um Retry-After; nesse caso, basta aguardar esse número de segundos.
Exemplos de código
O mesmo pedido em quatro linguagens, por grupo de endpoints. Substitua YOUR_API_KEY pela sua própria chave — e nunca a coloque em código que um visitante possa descarregar.
Conta
Quem sou e o que posso fazer.
GET /api/v1/me
curl
curl "https://passavo.eu/api/v1/me" \
-H "Authorization: Bearer pv_live_YOUR_API_KEY" \
-H "Accept: application/json"
PHP
use Illuminate\Support\Facades\Http;
$response = Http::acceptJson()
->withToken('pv_live_YOUR_API_KEY')
->get('https://passavo.eu/api/v1/me');
$data = $response->json('data');
JavaScript
const response = await fetch('https://passavo.eu/api/v1/me', {
method: 'GET',
headers: {
Accept: 'application/json',
Authorization: 'Bearer pv_live_YOUR_API_KEY',
},
});
const { data } = await response.json();
Python
import requests
headers = {"Accept": "application/json", "Authorization": "Bearer pv_live_YOUR_API_KEY"}
response = requests.get("https://passavo.eu/api/v1/me", headers=headers)
data = response.json()["data"]
Catálogo
Locais, produtos e preços.
GET /api/v1/events
curl
curl "https://passavo.eu/api/v1/events" \
-H "Authorization: Bearer pv_live_YOUR_API_KEY" \
-H "Accept: application/json"
PHP
use Illuminate\Support\Facades\Http;
$response = Http::acceptJson()
->withToken('pv_live_YOUR_API_KEY')
->get('https://passavo.eu/api/v1/events');
$data = $response->json('data');
JavaScript
const response = await fetch('https://passavo.eu/api/v1/events', {
method: 'GET',
headers: {
Accept: 'application/json',
Authorization: 'Bearer pv_live_YOUR_API_KEY',
},
});
const { data } = await response.json();
Python
import requests
headers = {"Accept": "application/json", "Authorization": "Bearer pv_live_YOUR_API_KEY"}
response = requests.get("https://passavo.eu/api/v1/events", headers=headers)
data = response.json()["data"]
Disponibilidade
Horários e lugares livres.
GET /api/v1/products/{id}/slots
curl
curl "https://passavo.eu/api/v1/products/12/slots" \
-H "Authorization: Bearer pv_live_YOUR_API_KEY" \
-H "Accept: application/json"
PHP
use Illuminate\Support\Facades\Http;
$response = Http::acceptJson()
->withToken('pv_live_YOUR_API_KEY')
->get('https://passavo.eu/api/v1/products/12/slots');
$data = $response->json('data');
JavaScript
const response = await fetch('https://passavo.eu/api/v1/products/12/slots', {
method: 'GET',
headers: {
Accept: 'application/json',
Authorization: 'Bearer pv_live_YOUR_API_KEY',
},
});
const { data } = await response.json();
Python
import requests
headers = {"Accept": "application/json", "Authorization": "Bearer pv_live_YOUR_API_KEY"}
response = requests.get("https://passavo.eu/api/v1/products/12/slots", headers=headers)
data = response.json()["data"]
Vendas
Descontos, vales-oferta e passes anuais.
GET /api/v1/discounts
curl
curl "https://passavo.eu/api/v1/discounts" \
-H "Authorization: Bearer pv_live_YOUR_API_KEY" \
-H "Accept: application/json"
PHP
use Illuminate\Support\Facades\Http;
$response = Http::acceptJson()
->withToken('pv_live_YOUR_API_KEY')
->get('https://passavo.eu/api/v1/discounts');
$data = $response->json('data');
JavaScript
const response = await fetch('https://passavo.eu/api/v1/discounts', {
method: 'GET',
headers: {
Accept: 'application/json',
Authorization: 'Bearer pv_live_YOUR_API_KEY',
},
});
const { data } = await response.json();
Python
import requests
headers = {"Accept": "application/json", "Authorization": "Bearer pv_live_YOUR_API_KEY"}
response = requests.get("https://passavo.eu/api/v1/discounts", headers=headers)
data = response.json()["data"]
Encomendas
Criar, pagar, cancelar e reembolsar encomendas.
GET /api/v1/orders
curl
curl "https://passavo.eu/api/v1/orders" \
-H "Authorization: Bearer pv_live_YOUR_API_KEY" \
-H "Accept: application/json"
PHP
use Illuminate\Support\Facades\Http;
$response = Http::acceptJson()
->withToken('pv_live_YOUR_API_KEY')
->get('https://passavo.eu/api/v1/orders');
$data = $response->json('data');
JavaScript
const response = await fetch('https://passavo.eu/api/v1/orders', {
method: 'GET',
headers: {
Accept: 'application/json',
Authorization: 'Bearer pv_live_YOUR_API_KEY',
},
});
const { data } = await response.json();
Python
import requests
headers = {"Accept": "application/json", "Authorization": "Bearer pv_live_YOUR_API_KEY"}
response = requests.get("https://passavo.eu/api/v1/orders", headers=headers)
data = response.json()["data"]
Bilhetes
Consultar, anular e reenviar bilhetes.
GET /api/v1/tickets
curl
curl "https://passavo.eu/api/v1/tickets" \
-H "Authorization: Bearer pv_live_YOUR_API_KEY" \
-H "Accept: application/json"
PHP
use Illuminate\Support\Facades\Http;
$response = Http::acceptJson()
->withToken('pv_live_YOUR_API_KEY')
->get('https://passavo.eu/api/v1/tickets');
$data = $response->json('data');
JavaScript
const response = await fetch('https://passavo.eu/api/v1/tickets', {
method: 'GET',
headers: {
Accept: 'application/json',
Authorization: 'Bearer pv_live_YOUR_API_KEY',
},
});
const { data } = await response.json();
Python
import requests
headers = {"Accept": "application/json", "Authorization": "Bearer pv_live_YOUR_API_KEY"}
response = requests.get("https://passavo.eu/api/v1/tickets", headers=headers)
data = response.json()["data"]
Entrada
Check-in à entrada.
GET /api/v1/check-ins
curl
curl "https://passavo.eu/api/v1/check-ins" \
-H "Authorization: Bearer pv_live_YOUR_API_KEY" \
-H "Accept: application/json"
PHP
use Illuminate\Support\Facades\Http;
$response = Http::acceptJson()
->withToken('pv_live_YOUR_API_KEY')
->get('https://passavo.eu/api/v1/check-ins');
$data = $response->json('data');
JavaScript
const response = await fetch('https://passavo.eu/api/v1/check-ins', {
method: 'GET',
headers: {
Accept: 'application/json',
Authorization: 'Bearer pv_live_YOUR_API_KEY',
},
});
const { data } = await response.json();
Python
import requests
headers = {"Accept": "application/json", "Authorization": "Bearer pv_live_YOUR_API_KEY"}
response = requests.get("https://passavo.eu/api/v1/check-ins", headers=headers)
data = response.json()["data"]
Clientes
Compradores, resumidos a partir das encomendas.
GET /api/v1/customers
curl
curl "https://passavo.eu/api/v1/customers" \
-H "Authorization: Bearer pv_live_YOUR_API_KEY" \
-H "Accept: application/json"
PHP
use Illuminate\Support\Facades\Http;
$response = Http::acceptJson()
->withToken('pv_live_YOUR_API_KEY')
->get('https://passavo.eu/api/v1/customers');
$data = $response->json('data');
JavaScript
const response = await fetch('https://passavo.eu/api/v1/customers', {
method: 'GET',
headers: {
Accept: 'application/json',
Authorization: 'Bearer pv_live_YOUR_API_KEY',
},
});
const { data } = await response.json();
Python
import requests
headers = {"Accept": "application/json", "Authorization": "Bearer pv_live_YOUR_API_KEY"}
response = requests.get("https://passavo.eu/api/v1/customers", headers=headers)
data = response.json()["data"]
Meta
A descrição da própria API.
GET /api/v1/openapi.json
curl
curl "https://passavo.eu/api/v1/openapi.json" \
-H "Accept: application/json"
PHP
use Illuminate\Support\Facades\Http;
$response = Http::acceptJson()
->get('https://passavo.eu/api/v1/openapi.json');
$data = $response->json('data');
JavaScript
const response = await fetch('https://passavo.eu/api/v1/openapi.json', {
method: 'GET',
headers: {
Accept: 'application/json',
},
});
const { data } = await response.json();
Python
import requests
headers = {"Accept": "application/json"}
response = requests.get("https://passavo.eu/api/v1/openapi.json", headers=headers)
data = response.json()["data"]
Webhooks
Mensagens que enviamos para o seu servidor.
GET /api/v1/webhook-deliveries
curl
curl "https://passavo.eu/api/v1/webhook-deliveries" \
-H "Authorization: Bearer pv_live_YOUR_API_KEY" \
-H "Accept: application/json"
PHP
use Illuminate\Support\Facades\Http;
$response = Http::acceptJson()
->withToken('pv_live_YOUR_API_KEY')
->get('https://passavo.eu/api/v1/webhook-deliveries');
$data = $response->json('data');
JavaScript
const response = await fetch('https://passavo.eu/api/v1/webhook-deliveries', {
method: 'GET',
headers: {
Accept: 'application/json',
Authorization: 'Bearer pv_live_YOUR_API_KEY',
},
});
const { data } = await response.json();
Python
import requests
headers = {"Accept": "application/json", "Authorization": "Bearer pv_live_YOUR_API_KEY"}
response = requests.get("https://passavo.eu/api/v1/webhook-deliveries", headers=headers)
data = response.json()["data"]
Webhooks
Um webhook é o contrário de um pedido: em vez de estar sempre a perguntar se já houve pagamento, enviamos uma mensagem para um endereço seu assim que acontece. Isso poupa milhares de pedidos por dia e fica a saber de imediato, em vez de só na ronda seguinte.
Gere os seus destinos no ecrã de gestão em Definições → Acesso à API, separador Webhooks, ou através da API com uma chave que tenha a permissão webhooks. Cada destino tem o seu próprio segredo; com ele, verifica que uma mensagem vem realmente de nós.
Verificar a assinatura
Cada mensagem leva o cabeçalho Passavo-Signature no formato t=<unix>,v1=<hmac-sha256>. t é o momento em que assinámos; v1 é um HMAC-SHA256 com o segredo desse destino sobre a marca temporal, um ponto e o body em bruto. Calcule-o por si e compare em tempo constante — uma comparação normal revela, pelo tempo que demora, quantos carateres estavam corretos. Recuse também uma mensagem cujo t se afaste mais de 300 segundos do seu próprio relógio: assim, ninguém pode reproduzir mais tarde uma mensagem intercetada.
Faça a verificação sobre o body EM BRUTO, antes de a sua framework o converter em json. Recompor o json muda a ordem das chaves e, nesse caso, nenhuma assinatura confere.
curl
# De handtekening narekenen vanaf de opdrachtregel.
# T is de waarde van t= uit de header Passavo-Signature,
# het resultaat hoort gelijk te zijn aan de waarde van v1=.
printf '%s.%s' "$T" "$BODY" | openssl dgst -sha256 -hmac "$SECRET"
PHP
// De RUWE body, niet $request->all().
$body = $request->getContent();
// "t=1758355200,v1=9f86d0…" uit elkaar halen.
$delen = [];
foreach (explode(',', (string) $request->header('Passavo-Signature')) as $stuk) {
[$sleutel, $waarde] = array_pad(explode('=', trim($stuk), 2), 2, '');
$delen[$sleutel] = $waarde;
}
$t = $delen['t'] ?? '';
$verwacht = hash_hmac('sha256', $t . '.' . $body, $secret);
// hash_equals vergelijkt in constante tijd; de tijdstempel
// houdt een opgevangen bericht tegen dat later opnieuw komt.
if (! ctype_digit($t) || abs(time() - (int) $t) > 300 || ! hash_equals($verwacht, $delen['v1'] ?? '')) {
abort(400);
}
JavaScript
import { createHmac, timingSafeEqual } from 'node:crypto';
// rawBody: de ruwe body als string, bv. via express.raw().
const header = request.headers['passavo-signature'] ?? '';
const delen = Object.fromEntries(header.split(',').map((s) => s.trim().split('=', 2)));
const verwacht = createHmac('sha256', secret).update(delen.t + '.' + rawBody).digest('hex');
const gekregen = delen.v1 ?? '';
const vers = /^\d+$/.test(delen.t ?? '')
&& Math.abs(Date.now() / 1000 - Number(delen.t)) <= 300;
const geldig = vers
&& verwacht.length === gekregen.length
&& timingSafeEqual(Buffer.from(verwacht), Buffer.from(gekregen));
Python
import hashlib, hmac, time
# raw_body: de ruwe body als bytes, bv. request.get_data() in Flask.
header = request.headers.get("Passavo-Signature", "")
delen = dict(stuk.strip().split("=", 1) for stuk in header.split(",") if "=" in stuk)
t = delen.get("t", "")
verwacht = hmac.new(secret.encode(), f"{t}.".encode() + raw_body, hashlib.sha256).hexdigest()
# compare_digest vergelijkt in constante tijd.
geldig = (t.isdigit()
and abs(time.time() - int(t)) <= 300
and hmac.compare_digest(verwacht, delen.get("v1", "")))
A lista completa de eventos e o respetivo conteúdo está na referência. →
O que muda
Cada alteração que valha a pena mencionar recebe uma nova versão datada. Se a sua integração ficar parada numa data antiga, continua a funcionar — a data diz apenas para que comportamento foi construída.
-
2026-09-20
A primeira versão
Chaves com permissões, uma sandbox, um único formato de resposta e paginação por cursor. Leitura: a sua organização, locais, produtos, horários, eventos, descontos, vales-oferta e passes anuais, encomendas, bilhetes, compradores e leituras. Escrita: criar, pagar, cancelar e reembolsar encomendas, anular bilhetes, fazer o check-in de visitantes, emitir vales-oferta e passes anuais. E webhooks de saída, assinados por destino.