S

SyntraPay

API Reference

Voltar ao painel

Documentação da API

Integre pagamentos PIX à sua aplicação com a API da SyntraPay. Cobranças, saques, consulta de saldo, webhooks e monitoramento de infrações MED, tudo via REST.

URL base
https://api.syntrapay.com.br

Todos os valores monetários são inteiros em centavos (ex.: 1490 = R$ 14,90). As respostas usam JSON.

Autenticação

Autentique cada requisição enviando sua chave de API no header Authorization, sem o prefixo Bearer. Gere e gerencie suas chaves no painel em Integrações → Credenciais.

Authorization: sk_live_sua_chave_aqui

Exemplo: primeira cobrança

curl -X POST https://api.syntrapay.com.br/transactions \
  -H "Authorization: sk_live_sua_chave_aqui" \
  -H "Content-Type: application/json" \
  -d '{ "amount": 1490 }'

Escopos

Cada chave de API possui escopos que definem quais ações ela pode executar. Selecione os escopos ao criar a chave e conceda apenas o necessário.

payments.createCriar cobranças PIX.
payments.readConsultar cobranças e transações.
transfers.readConsultar transferências.
withdrawals.createCriar saques PIX.
withdrawals.readConsultar saques.
webhooks.manageGerenciar webhooks.

Cobranças (PIX)

Crie e consulte cobranças PIX. Todos os valores são inteiros em centavos (ex.: 1490 = R$ 14,90).

POST/transactions payments.create

Criar cobrança

Cria uma cobrança PIX e retorna o QR Code (base64) e o código copia-e-cola para o pagador. O valor é sempre em centavos.

Parâmetros

amountbodyobrigatório
integer: Valor em centavos (mín. 50). Ex.: 1490 = R$ 14,90.
webhookbody
string: URL para notificar quando o pagamento for aprovado (sobrescreve o webhook global desta cobrança).
split_emailbody
string: E-mail de outra conta SyntraPay para dividir o valor (split).
split_taxbody
integer: Percentual destinado ao parceiro no split (1 a 99, padrão 50).
customerbody
object: Dados do pagador para rastreio (name, document). Opcional.
productsbody
array: Itens da venda, usados por integrações de tracking (ex.: Utmify).
trackingParametersbody
object: UTMs da campanha (utm_source, utm_medium, etc.).
Idempotency-Keyheader
string: Chave única sua para evitar cobranças duplicadas em reenvios. A resposta é repetida por 24h para a mesma chave.

Campos da resposta

id
string: Identificador único da cobrança.
status
string: Status inicial (pending).
amount
integer: Valor da cobrança em centavos.
qrCodeBase64
string: Imagem do QR Code em data URI (base64).
copyPaste
string: Código PIX copia-e-cola.
expiresAt
string: Data/hora de expiração (ISO 8601).
fee
integer: Taxa aplicada em centavos.
storeId
string: Identificador da sua conta.

Requisição

curl -X POST "https://api.syntrapay.com.br/transactions" \
  -H "Authorization: sk_live_sua_chave_aqui" \
  -H "Content-Type: application/json" \
  -d '{"amount":1490}'

Resposta

201 Created
{
  "message": "Transaction created successfully",
  "status": "pending",
  "id": "9c1e7b2a-3f4d-4a8b-bc12-5e6f7a8b9c0d",
  "amount": 1490,
  "qrCodeBase64": "data:image/png;base64,iVBORw0KGgoAAA...",
  "copyPaste": "00020126580014br.gov.bcb.pix...6304ABCD",
  "expiresAt": "2026-07-18T15:30:00.000Z",
  "fee": 44,
  "storeId": "usr_a1b2c3"
}
400 Bad Request
{
  "status": "error",
  "code": "BAD_REQUEST",
  "message": "400: Amount must be greater than 50 cents"
}
GET/transactions/:id payments.read

Consultar cobrança

Consulta os detalhes e o status atual de uma cobrança pelo seu ID. Ao fazer polling do status, use nocache=1 para ler sempre direto do banco.

Parâmetros

idpathobrigatório
string: ID da transação retornado na criação.
nocachequery
string: Defina como 1 para ignorar o cache (útil em polling de status).

Campos da resposta

id
string: Identificador da cobrança.
status
string: PENDING, PAID, FAILED, CANCELED ou EXPIRED.
amount
integer: Valor em centavos.
fee
integer: Taxa em centavos.
payer
object: Dados do pagador ({ name, document }).
paidAt
string: Data/hora do pagamento (ISO) ou null.

Requisição

curl -X GET "https://api.syntrapay.com.br/transactions/9c1e7b2a-3f4d-4a8b-bc12-5e6f7a8b9c0d" \
  -H "Authorization: sk_live_sua_chave_aqui" \
  -H "Content-Type: application/json"

Resposta

200 OK
{
  "id": "9c1e7b2a-3f4d-4a8b-bc12-5e6f7a8b9c0d",
  "status": "PAID",
  "type": "DEPOSIT",
  "reason": "PIX_PAYMENT",
  "amount": 1490,
  "fee": 44,
  "payer": { "name": "João da Silva", "document": "***.456.789-**" },
  "storeId": "usr_a1b2c3",
  "createdAt": "2026-07-18T14:30:00.000Z",
  "paidAt": "2026-07-18T14:31:12.000Z"
}
404 Not Found
{
  "status": "error",
  "code": "NOT_FOUND",
  "message": "404: Not Found - Transaction not found"
}
GET/transactions payments.read

Listar transações

Lista as transações da sua conta (cobranças e saques), com paginação e filtros opcionais.

Parâmetros

startquery
integer: Posição inicial (paginação). Padrão 1.
limitquery
integer: Itens por página. Padrão 50.
statusquery
string: Filtra por status (ex.: PENDING, PAID).
typequery
string: Filtra por tipo (DEPOSIT, WITHDRAWAL).
searchquery
string: Busca por ID ou nome do pagador.

Requisição

curl -X GET "https://api.syntrapay.com.br/transactions?limit=50&status=PAID" \
  -H "Authorization: sk_live_sua_chave_aqui" \
  -H "Content-Type: application/json"

Resposta

200 OK
{
  "status": "success",
  "total": 128,
  "start": 1,
  "limit": 50,
  "count": 50,
  "transactions": [
    {
      "id": "9c1e7b2a-3f4d-4a8b-bc12-5e6f7a8b9c0d",
      "status": "PAID",
      "type": "DEPOSIT",
      "amount": 1490,
      "fee": 44,
      "createdAt": "2026-07-18T14:30:00.000Z"
    }
  ]
}

Saques (PIX)

Envie saques PIX e consulte o histórico. Aceita CPF, CNPJ, e-mail, telefone, chave aleatória (EVP) ou copia-e-cola.

POST/withdrawals withdrawals.create

Criar saque

Realiza um saque via PIX para uma chave. O valor é em centavos e é descontado do seu saldo disponível junto com a taxa.

Parâmetros

pixKeybodyobrigatório
string: Chave de destino: CPF, CNPJ, e-mail, telefone, EVP ou copia-e-cola.
amountbodyobrigatório
integer: Valor em centavos (mín. 50). Opcional só quando o copia-e-cola já traz o valor.
descriptionbody
string: Descrição que aparece para o recebedor.
webhookbody
string: URL para notificar quando o saque mudar de status.
Idempotency-Keyheader
string: Chave única sua para evitar saques duplicados em reenvios. A resposta é repetida por 24h para a mesma chave.

Campos da resposta

id
string: Identificador do saque.
status
string: Status inicial (pending).
amount
integer: Valor em centavos.
pixKey
string: Chave PIX de destino.
pixKeyType
string: Tipo detectado: CPF, CNPJ, EMAIL, TELEFONE, CHAVE_ALEATORIA ou COPIA_E_COLA.
fee
integer: Taxa do saque em centavos.

Requisição

curl -X POST "https://api.syntrapay.com.br/withdrawals" \
  -H "Authorization: sk_live_sua_chave_aqui" \
  -H "Content-Type: application/json" \
  -d '{"pixKey":"cliente@email.com","amount":5000}'

Resposta

201 Created
{
  "message": "Withdraw request created successfully",
  "status": "pending",
  "id": "f1e2d3c4-b5a6-4789-9c0d-1a2b3c4d5e6f",
  "amount": 5000,
  "pixKey": "cliente@email.com",
  "pixKeyType": "EMAIL",
  "fee": 250
}
400 Bad Request
{
  "status": "error",
  "code": "INSUFFICIENT_FUNDS",
  "message": "400: Saldo insuficiente para realizar o saque"
}
GET/withdrawals withdrawals.read

Listar saques

Lista os saques da sua conta, com paginação.

Parâmetros

startquery
integer: Posição inicial (paginação). Padrão 1.
limitquery
integer: Itens por página. Padrão 50.

Requisição

curl -X GET "https://api.syntrapay.com.br/withdrawals" \
  -H "Authorization: sk_live_sua_chave_aqui" \
  -H "Content-Type: application/json"

Resposta

200 OK
{
  "status": "success",
  "total": 12,
  "start": 1,
  "limit": 50,
  "count": 12,
  "withdrawals": [
    {
      "id": "f1e2d3c4-b5a6-4789-9c0d-1a2b3c4d5e6f",
      "type": "WITHDRAWAL",
      "status": "PAID",
      "amount": 5000,
      "fee": 250,
      "payer": { "pixKey": "cliente@email.com", "pixKeyType": "EMAIL" },
      "end_to_end": "E12345678202607181430...",
      "createdAt": "2026-07-18T14:30:00.000Z",
      "paidAt": "2026-07-18T14:30:20.000Z"
    }
  ]
}
GET/withdrawals/:id withdrawals.read

Consultar saque

Consulta os detalhes e o status de um saque pelo seu ID.

Parâmetros

idpathobrigatório
string: ID do saque retornado na criação.

Campos da resposta

id
string: Identificador do saque.
status
string: PENDING, PAID, FAILED, CANCELED ou EXPIRED.
amount
integer: Valor em centavos.
taxes
integer: Taxa cobrada em centavos.
pixKey
string: Chave PIX de destino.
pixKeyType
string: Tipo da chave.
receiver
object: Dados do recebedor ({ name, document }).
paidAt
string: Data/hora da liquidação (ISO) ou null.

Requisição

curl -X GET "https://api.syntrapay.com.br/withdrawals/f1e2d3c4-b5a6-4789-9c0d-1a2b3c4d5e6f" \
  -H "Authorization: sk_live_sua_chave_aqui" \
  -H "Content-Type: application/json"

Resposta

201 Created
{
  "id": "f1e2d3c4-b5a6-4789-9c0d-1a2b3c4d5e6f",
  "withdrawStatusId": "Successfull",
  "status": "PAID",
  "amount": 5000,
  "taxes": 250,
  "pixKey": "cliente@email.com",
  "pixKeyType": "EMAIL",
  "receiver": { "name": "Maria Souza", "document": "***.123.456-**" },
  "paidAt": "2026-07-18T14:30:20.000Z"
}
404 Not Found
{
  "status": "error",
  "code": "NOT_FOUND",
  "message": "404: Not Found - Withdrawal not found"
}

Saldo

POST/balance

Consultar saldo

Consulta o saldo da sua conta: disponível, bloqueado, em análise (MED) e total. Não requer corpo na requisição.

Campos da resposta

balance_available
number: Saldo disponível para saque.
balance_locked
number: Saldo bloqueado (lock de tempo).
balance_infractions
number: Saldo retido por infrações MED.
netBalance
number: Saldo líquido.

Requisição

curl -X POST "https://api.syntrapay.com.br/balance" \
  -H "Authorization: sk_live_sua_chave_aqui" \
  -H "Content-Type: application/json"

Resposta

200 OK
{
  "codeStatus": 200,
  "balance": {
    "id": "usr_a1b2c3",
    "balance": 1530.50,
    "balance_available": 1530.50,
    "balance_locked": 0,
    "balance_infractions": 0,
    "totalBalances": 8240.00,
    "netBalance": 1530.50,
    "fees": { "saque": 250 }
  }
}

MED: Infrações PIX

Consulte as infrações MED (Mecanismo Especial de Devolução) registradas nas suas transações. Valores em centavos.

GET/infractions

Listar infrações

Lista as infrações MED da sua conta, com um resumo agregado e paginação por intervalo (from/to).

Parâmetros

fromquery
integer: Índice inicial (0-based). Padrão 0.
toquery
integer: Índice final (inclusivo). Padrão 10.
statusquery
string: Filtra por status (ex.: WAITING_PSP, COMPLETED) ou "all".

Campos da resposta

summary.totalCount
integer: Total de infrações.
summary.totalAmount
integer: Soma dos valores (centavos).
summary.waitingPsp
integer: Infrações aguardando o PSP.
summary.completed
integer: Infrações concluídas.
data[].infractionId
string: ID da infração.
data[].type
string: Tipo (ex.: FRAUD, SCAM).
data[].status
string: Status atual da infração.
data[].endToEndId
string: E2E do PIX relacionado.
data[].amount
integer: Valor em centavos.
data[].payerName
string: Nome do pagador (quando disponível).
data[].linkedTransactionId
string: ID da transação vinculada.

Requisição

curl -X GET "https://api.syntrapay.com.br/infractions?from=0&to=10&status=all" \
  -H "Authorization: sk_live_sua_chave_aqui" \
  -H "Content-Type: application/json"

Resposta

200 OK
{
  "status": "success",
  "summary": {
    "totalCount": 3,
    "totalAmount": 45000,
    "waitingPsp": 1,
    "completed": 2
  },
  "range": { "total": 3, "from": 0, "to": 10 },
  "data": [
    {
      "infractionId": "inf_9a8b7c6d",
      "type": "FRAUD",
      "status": "WAITING_PSP",
      "endToEndId": "E12345678202607181430...",
      "reportedBy": "PACS",
      "amount": 15000,
      "currency": "BRL",
      "creationDate": "2026-07-18T12:00:00.000Z",
      "payerName": "João da Silva",
      "linkedTransactionId": "9c1e7b2a-3f4d-4a8b-bc12-5e6f7a8b9c0d"
    }
  ]
}

Webhooks

Configure endpoints para receber eventos em tempo real. Ao criar, enviamos um POST de teste. Sua URL deve responder 200/201/202. Cada disparo inclui o header syntrapay-webhook-secret.

Eventos disponíveis

payment.approvedUma cobrança PIX foi paga e o valor creditado.
payment.failedA cobrança falhou, expirou ou foi cancelada.
transfer-approvedUm saque PIX foi concluído com sucesso.
transfer-failedUm saque PIX falhou ou foi rejeitado.
pix.infractionUma infração MED foi registrada em uma transação sua.

Cada disparo inclui os headers syntrapay-signature (sha256=…), syntrapay-timestamp e syntrapay-webhook-secret. A assinatura é o HMAC-SHA256 de `${timestamp}.${corpo_bruto}` usando o signing secret do webhook: valide-a e rejeite timestamps antigos (replay).

Verificar a assinatura (Node.js)

import crypto from "crypto"

function verifyWebhook(rawBody, headers, secret) {
  const ts = headers["syntrapay-timestamp"]
  const sig = (headers["syntrapay-signature"] || "").replace("sha256=", "")
  const expected = crypto
    .createHmac("sha256", secret)
    .update(ts + "." + rawBody)   // HMAC de `${ts}.${corpo}`
    .digest("hex")
  const ok =
    sig.length === expected.length &&
    crypto.timingSafeEqual(Buffer.from(sig), Buffer.from(expected))
  // Rejeite se !ok ou se |agora - ts| > 300s (replay)
  const fresh = Math.abs(Date.now() / 1000 - Number(ts)) < 300
  return ok && fresh
}
GET/webhooks webhooks.manage

Listar webhooks

Lista os webhooks da sua conta. O signing secret é retornado mascarado.

Requisição

curl -X GET "https://api.syntrapay.com.br/webhooks" \
  -H "Authorization: sk_live_sua_chave_aqui" \
  -H "Content-Type: application/json"

Resposta

200 OK
{
  "status": "success",
  "webhooks": [
    {
      "id": "665fbe1c9a2d4e0012ab34cd",
      "url": "https://seusite.com/webhooks/syntrapay",
      "events": ["payment.approved", "payment.failed"],
      "active": true,
      "secret": "whsec_ab12...cd34",
      "createdAt": "2026-07-01T10:00:00.000Z"
    }
  ]
}
POST/webhooks webhooks.manage

Criar webhook

Cria um webhook. O signing secret completo é retornado apenas na criação (também pode ser revelado depois com sua senha no painel). Máximo de 10 webhooks por conta.

Parâmetros

urlbodyobrigatório
string: Endpoint HTTPS que receberá os eventos.
eventsbodyobrigatório
array: Lista de eventos (ver tabela de eventos abaixo).

Requisição

curl -X POST "https://api.syntrapay.com.br/webhooks" \
  -H "Authorization: sk_live_sua_chave_aqui" \
  -H "Content-Type: application/json" \
  -d '{"url":"https://seusite.com/webhooks/syntrapay","events":["payment.approved","payment.failed"]}'

Resposta

201 Created
{
  "status": "success",
  "webhook": {
    "id": "665fbe1c9a2d4e0012ab34cd",
    "url": "https://seusite.com/webhooks/syntrapay",
    "events": ["payment.approved", "payment.failed"],
    "active": true,
    "secret": "a1b2c3...64-char-hex-secret",
    "createdAt": "2026-07-18T10:00:00.000Z"
  }
}
400 Bad Request
{
  "status": "error",
  "code": "WEBHOOK_TEST_FAILED",
  "message": "A URL não respondeu ao POST de teste."
}
PATCH/webhooks webhooks.manage

Editar webhook

Atualiza a URL, os eventos ou o status (ativo/inativo) de um webhook. Só os campos enviados são alterados.

Parâmetros

webhookIdbodyobrigatório
string: ID do webhook a editar.
urlbody
string: Nova URL do endpoint.
eventsbody
array: Nova lista de eventos.
activebody
boolean: Ativa ou desativa o webhook.

Requisição

curl -X PATCH "https://api.syntrapay.com.br/webhooks" \
  -H "Authorization: sk_live_sua_chave_aqui" \
  -H "Content-Type: application/json" \
  -d '{"webhookId":"665fbe1c9a2d4e0012ab34cd","active":false}'

Resposta

200 OK
{
  "status": "success",
  "webhook": {
    "id": "665fbe1c9a2d4e0012ab34cd",
    "url": "https://seusite.com/webhooks/syntrapay",
    "events": ["payment.approved", "payment.failed"],
    "active": false,
    "createdAt": "2026-07-01T10:00:00.000Z"
  }
}
DELETE/webhooks webhooks.manage

Remover webhook

Remove um webhook permanentemente.

Parâmetros

webhookIdbodyobrigatório
string: ID do webhook a remover.

Requisição

curl -X DELETE "https://api.syntrapay.com.br/webhooks" \
  -H "Authorization: sk_live_sua_chave_aqui" \
  -H "Content-Type: application/json" \
  -d '{"webhookId":"665fbe1c9a2d4e0012ab34cd"}'

Resposta

200 OK
{
  "status": "success",
  "message": "Webhook removido com sucesso"
}

Erros

Erros retornam um envelope consistente com status, code e message.

{
  "status": "error",
  "code": "BAD_REQUEST",
  "message": "Descrição do erro em português."
}
UNAUTHORIZED401Chave/token ausente ou inválido no header Authorization.
ACCESS_FORBIDDEN200/403Sem permissão para acessar o recurso.
FORBIDDEN_SCOPE403A chave de API não possui o escopo necessário para a ação.
FORBIDDEN403Conta ainda não ativada.
BAD_REQUEST400Parâmetros ausentes ou inválidos.
INSUFFICIENT_FUNDS400Saldo insuficiente para o saque.
INVALID_PIX_KEY400Chave PIX inválida ou não encontrada.
TOO_MANY_REQUESTS429Limite de requisições atingido. Aguarde e tente novamente.
NOT_FOUND404Recurso não encontrado.
INTERNAL_ERROR500Erro interno do servidor.