Pular para o conteúdo

Desenvolvedores

API e webhooks do Volta

Leia os reembolsos da sua empresa de dentro de outro sistema e receba um aviso no instante em que algo muda. Pensado para ligar o Volta à contabilidade, ao ERP ou a uma automação.

Começando

  1. O administrador da empresa abre Integrações no painel e cria uma chave de API. A chave aparece uma única vez.
  2. Envie a chave no cabeçalho Authorization: Bearer vlt_live_… (ou X-API-Key).
  3. Faça um GET em https://voltareembolso.com.br/api/v1/me para conferir.
curl https://voltareembolso.com.br/api/v1/reembolsos?status=pago&limite=20 \
  -H "Authorization: Bearer vlt_live_SUA_CHAVE"

Segurança e limites

  • Cada chave só enxerga a própria empresa. A API v1 é somente de leitura: POST, PUT, PATCH e DELETE respondem 405.
  • Chaves comuns não trazem dados pessoais. Uma chave criada com “dados pessoais” também devolve e-mail, WhatsApp e chave Pix dos colaboradores e um link temporário (1 hora) para cada comprovante.
  • Limite de 120 pedidos por minuto por chave. Passou disso, vem 429 com o cabeçalho Retry-After.
  • Guarde a chave como senha. Perdeu ou vazou? Revogue em Integrações e crie outra.

Endpoints

GET /meEmpresa e chave que estão sendo usadas.
GET /reembolsosLista de reembolsos, dos mais novos para os mais antigos, com filtros e paginação.
GET /reembolsos/{id}Um reembolso.
GET /colaboradoresColaboradores da empresa (id, nome, cargo, ativo, gestor).
GET /categoriasCategorias com limite e prazo.
GET /centros-de-custoCentros de custo com o orçamento mensal.

Filtros e paginação

Em /reembolsos:

  • status: pendente, em_analise, aprovado, recusado, pago, cancelado.
  • desde e ate: data de criação, no formato AAAA-MM-DD (o ate inclui o dia). pago_desde e pago_ate fazem o mesmo com a data do pagamento.
  • centro_de_custo, categoria e colaborador: o id (uuid).
  • limite (1 a 200, padrão 50) e cursor: repita a chamada com o proximo_cursor da resposta anterior até ele vir null. A paginação não repete nem pula itens, mesmo que cheguem reembolsos novos no meio.
{
  "dados": [
    {
      "id": "905d859e-8158-48b4-b608-7ffa462abfc2",
      "codigo": "R-0004",
      "status": "pago",
      "valor": 180.0,
      "valor_adiantamento_abatido": 30.0,
      "valor_a_pagar": 150.0,
      "data_despesa": "2026-10-08",
      "criado_em": "2026-10-08T12:00:00Z",
      "pago_em": "2026-10-15T12:00:00Z",
      "estabelecimento": "Posto Ipiranga Norte",
      "cnpj_estabelecimento": "45.678.901/0001-32",
      "descricao": "Visita a fornecedor",
      "politica": "ok",
      "avisos": [],
      "categoria": { "id": "…", "nome": "Combustível" },
      "centro_de_custo": { "id": "…", "nome": "Administrativo" },
      "colaborador": { "id": "…", "nome": "Marina Lopes" }
    }
  ],
  "proximo_cursor": "eyJ0IjoiMjAyNi0xMC0wOFQxMjowMDowMFoiLCJpZCI6Ii4uLiJ9"
}

Erros vêm assim: {"erro":{"codigo":"chave_invalida","mensagem":"…"}} com o status HTTP adequado (400, 401, 403, 404, 405, 429).

Webhooks

Em vez de perguntar toda hora, deixe o Volta avisar. Em Integrações, cadastre um endereço https público e escolha os eventos. Para cada mudança, o Volta faz um POST com JSON:

{
  "id": "369aaa5d-1689-4a09-8f12-be9f5195038b",
  "tipo": "reembolso.pago",
  "criado_em": "2026-10-15T12:00:00Z",
  "dados": { "reembolso": { "id": "…", "codigo": "R-0004", "status": "pago", "valor": 180.0, "…": "…" } }
}

Eventos disponíveis: reembolso.criado, reembolso.em_analise, reembolso.aprovado, reembolso.recusado, reembolso.pago, reembolso.cancelado. O evento teste.ping sai quando você clica em “Enviar teste”. Os avisos não trazem dados pessoais dos colaboradores além do nome; para o resto, consulte a API.

  • Cabeçalhos: Volta-Event, Volta-Delivery (id da entrega) e Volta-Signature.
  • Responda com 2xx em até 8 segundos. Sem sucesso, o Volta tenta de novo depois de 1 min, 5 min, 30 min, 2 h e 12 h (6 tentativas). Depois de 10 entregas seguidas sem sucesso, o endereço é desativado.
  • O mesmo evento pode chegar mais de uma vez. Use o campo id do evento para ignorar repetidos.
  • O Volta não segue redirecionamentos (3xx contam como falha) e só entrega em endereços https públicos, na porta 443.

Conferindo a assinatura

Cada endereço tem um segredo (whsec_…), mostrado uma vez ao cadastrar. O cabeçalho Volta-Signature vem como t=<segundos>,v1=<hex>, em que hex é o HMAC-SHA256 de "<t>.<corpo bruto>". Confira sempre antes de confiar no evento e recuse os que tenham t a mais de 5 minutos do horário atual.

Node.js

import crypto from "node:crypto";

// corpo = texto bruto da requisição (antes de fazer JSON.parse)
export function confere(corpo, cabecalho, segredo) {
  const t = Number(/t=(\d+)/.exec(cabecalho)?.[1]);
  const v1 = /v1=([0-9a-f]{64})/.exec(cabecalho)?.[1];
  if (!t || !v1 || Math.abs(Date.now() / 1000 - t) > 300) return false; // evento antigo
  const esperado = crypto.createHmac("sha256", segredo).update(t + "." + corpo).digest("hex");
  return crypto.timingSafeEqual(Buffer.from(esperado), Buffer.from(v1));
}

Python

import hmac, hashlib, re, time

def confere(corpo: bytes, cabecalho: str, segredo: str) -> bool:
    t = re.search(r"t=(\d+)", cabecalho or "")
    v1 = re.search(r"v1=([0-9a-f]{64})", cabecalho or "")
    if not t or not v1 or abs(time.time() - int(t.group(1))) > 300:
        return False  # evento antigo
    esperado = hmac.new(segredo.encode(), t.group(1).encode() + b"." + corpo, hashlib.sha256).hexdigest()
    return hmac.compare_digest(esperado, v1.group(1))

Para assistentes de IA

O arquivo /llms.txt resume a API num texto só, e a especificação OpenAPI traz todos os formatos. Peça a ChatGPT, Claude ou ao assistente do seu editor: “leia https://voltareembolso.com.br/llms.txt e monte a integração com o Volta”.

Dúvida ou algo que falta na API? Fale com a gente pelo WhatsApp. Ainda não tem conta? Crie a sua grátis.