savrsoft

Documentação da API

Uma API REST simples para ler e escrever os seus dados de catering, além de webhooks assinados para eventos em tempo real. Crie uma chave em Developer na aplicação.

Autenticação

Todos os pedidos à API utilizam uma chave de API como bearer token. Crie uma em Developer → API keys. As chaves são apenas de leitura ou leitura/escrita.

curl https://savrsoft.com/api/v1/events \
  -H "Authorization: Bearer savr_live_your_key_here"

URL base: https://savrsoft.com/api/v1 · Todas as respostas são em JSON. Os erros devolvem { "error": "…" } com um estado 4xx/5xx.

Códigos de estado

CódigoQuando o recebe
200Leitura bem-sucedida.
201Criado com sucesso. O corpo é { "id": 42 } — obtenha o registo se precisar do resto da informação.
400Falta um campo obrigatório, por exemplo { "error": "name is required" }, ou não foi possível ler um cursor de paginação.
401Sem chave de API, uma malformada, ou uma chave que foi revogada.
403Foi utilizada uma chave só de leitura para uma escrita. Crie uma chave de leitura/escrita em Developer → API keys.
404O registo não existe, ou pertence a outra organização — as duas situações são deliberadamente indistinguíveis. Também é devolvido para um caminho ou método não reconhecido.

Âmbito desta API

A API é apenas de leitura e criação. Não existem endpoints DELETE, PUT ou PATCH — um pedido que utilize um destes devolve 404 Unknown endpoint, tal como qualquer caminho não reconhecido. A eliminação e edição fazem-se na aplicação, para que uma integração não possa destruir os registos de um caterer. Se precisar de acesso de escrita além da criação, diga-nos o que está a construir.

Paginação

Todos os endpoints de listagem são paginados. Passe limit (predefinição 100, máximo 500) e siga next_cursor até que has_more seja false:

{
  "data": [ ... ],
  "has_more": true,
  "next_cursor": "eyJuYW1lIjoiQWNtZSIsImlkIjo0Mn0"
}

Passe o cursor diretamente de volta para obter a página seguinte. Trate-o como opaco — a codificação pode mudar:

curl "https://savrsoft.com/api/v1/clients?limit=100&cursor=eyJuYW1lIjoiQWNtZSIsImlkIjo0Mn0" \
  -H "Authorization: Bearer savr_live_your_key_here"

A paginação está ancorada à última linha recebida, e não a um offset, pelo que as linhas criadas ou eliminadas enquanto percorre as páginas não farão com que salte ou repita um registo. Um cursor mantém-se válido indefinidamente.

ParâmetroComportamento
limit1–500. Se estiver ausente, for zero, negativo ou não numérico, assume 100; qualquer valor superior a 500 é limitado a 500.
cursornext_cursor da página anterior. Omita-o para a primeira página. Um cursor que não possa ser lido — corrompido ou proveniente de um endpoint diferente — devolve 400 Invalid cursor em vez de recomeçar silenciosamente do início.

Ordenação: /events e /invoices mais recentes primeiro; /recipes e /clients por nome, com os empates resolvidos pelo id para que a paginação se mantenha estável quando os nomes se repetem.

Endpoints

GET/v1/me

A sua organização (id, nome, moeda).

GET/v1/events

Lista de eventos, mais recentes primeiro. Paginado — ver Paginação acima.

GET/v1/events/{id}

Um evento com os seus pratos.

POST/v1/events · requer leitura/escrita

Criar um evento. Corpo:

{ "name": "Acme holiday party", "event_date": "2026-12-18",
  "guests": 120, "price_per_head": 55, "event_type": "corporate" }
GET/v1/recipes · GET/v1/recipes/{id}

Listar receitas (com alergénios & indicações dietéticas), ou uma receita com ingredientes. A lista é paginada e ordenada por nome.

GET/v1/clients · POST/v1/clients

Listar clientes (paginados, por nome) ou criar um. Corpo de criação: { "name": "...", "email": "...", "phone": "...", "company": "..." }

GET/v1/invoices · GET/v1/invoices/{id}

Listar faturas com totais calculados, das mais recentes às mais antigas, ou uma fatura com as linhas de detalhe. A lista é paginada.

Webhooks

Registe um endpoint em Developer → Webhooks. Nós enviamos um POST com um payload JSON quando ocorrem eventos:

{
  "id": "evt_abc123",
  "type": "event.inquiry",
  "created_at": "2026-07-17T18:20:00.000Z",
  "data": { "id": 42, "name": "Corporate lunch — Dana Ruiz", ... }
}

Tipos de eventos

TipoAtiva quando
event.createdUm evento é criado
event.inquiryChega um novo pedido de catering online
invoice.sentUma fatura é marcada como enviada
invoice.paidUma fatura é marcada como paga
proposal.approvedUm cliente aprova uma proposta
client.createdUm cliente é criado

Verificação de assinaturas

Cada envio inclui um cabeçalho x-savrsoft-signature : o HMAC-SHA256 do corpo bruto do pedido, assinado com a sua chave secreta de assinatura do webhook. Calcule o mesmo valor e compare:

// Node.js
const crypto = require('crypto');
const sig = crypto.createHmac('sha256', SIGNING_SECRET)
  .update(rawBody).digest('hex');
if (sig !== req.headers['x-savrsoft-signature']) reject();
Privacidade · Segurança · Termos · Dúvidas? savrsoft.com · Crie integrações de catering em minutos.