Visão Geral
A Royalpay é uma API de pagamentos para receber e enviar Pix de forma simples e segura. A plataforma oferece:
Receber Pagamentos (Cash-In)
Gere cobranças Pix com copia e cola e link de pagamento para os seus clientes.
Realizar Saques (Cash-Out)
Envie o seu saldo para qualquer chave Pix ou para uma carteira USDT (BEP20).
Webhooks em Tempo Real
Receba notificações assinadas quando uma cobrança ou um saque muda de status.
Versão da API
https://useroyalpay.com.br/api/v1Limites e ambiente
- Limite de 100 requisições por minuto por chave e 40 criações por minuto por conta. Acima disso a API responde
429. - Não há ambiente de testes (sandbox): toda chave opera com dinheiro real. Valide a integração com o valor mínimo de cobrança.
- Valores são inteiros em centavos:
10000= R$ 100,00. - Requisições e respostas usam
application/json.
Primeiros passos
- Crie a conta e gere a chave. Crie sua conta e aguarde a aprovação. Depois, em Chaves de acesso, crie uma chave. Ela aparece uma vez só.
- Gere a primeira cobrança. Um Pix de R$ 10,00 com
POST /payments. A resposta traz o copia e cola e um link de pagamento. - Configure o webhook. Em Webhooks, cadastre a URL do seu sistema para saber na hora quando o Pix cair.
Exemplo de Requisição
curl -X POST 'https://useroyalpay.com.br/api/v1/payments' \
-H 'Authorization: Bearer SUA_CHAVE' \
-H 'Idempotency-Key: pedido-1001' \
-H 'Content-Type: application/json' \
-d '{
"amountCents": 1000,
"description": "Meu primeiro Pix"
}'Autenticação
Conceito
A API da Royalpay usa uma chave de acesso enviada no header Authorization em todas as chamadas. As chaves de produção começam com rp_live_.
Authorization: Bearer SUA_CHAVESegurança
Criar uma chave
No painel, abra Chaves de acesso e crie uma nova chave com um nome para reconhecê-la depois. Marque Permitir saques só se a integração for sacar: isso pede a sua senha e, com 2FA ativo, o código do app autenticador. A chave aparece uma única vez; se perder, revogue e crie outra.
Permissões
Uma chamada fora das permissões da chave responde 403.
| Permissão | O que permite | Na chave |
|---|---|---|
payments:read | Consultar cobranças, saques, saldo e checkouts. | Sempre |
payments:write | Criar cobranças. | Sempre |
withdrawals:write | Solicitar saques. Move dinheiro. | Se marcada na criação |
Valores e status
Toda rota enxerga só os dados da sua conta. Depois de gerada, a cobrança passa para COMPLETED quando o Pix é confirmado.
| Status | Significado |
|---|---|
APPROVAL | Saque com o total reservado, aguardando aprovação da Royalpay. Ainda não foi enviado. |
CREATED | Solicitação salva, aguardando envio. |
PROCESSING | Envio ao provedor iniciado. |
PENDING | Aguardando confirmação do provedor. |
COMPLETED | Confirmada. Só este status significa pagamento recebido ou saque concluído. |
FAILED | Falha confirmada. A reserva do saque volta ao saldo. |
REVIEW | Resultado inconclusivo. A reserva fica mantida até a conferência; não reenvie. |
Tarifas e limites
A tarifa vem da rota da sua conta. Enviar outra taxa no corpo não muda nada, e cada transação guarda a tarifa aplicada na criação.
| Operação | Tarifa | Exemplo de R$ 100 |
|---|---|---|
| Cobrança · Vendedor | 3% + R$ 1,50 | Credita R$ 95,50 |
| Cobrança · Ghost | 10% + R$ 1,50 | Credita R$ 88,50 |
| Saque Pix | R$ 1,50 | Debita R$ 101,50 e envia R$ 100,00 |
| Saque em USDT | 8% + R$ 1,50 | Debita R$ 109,50 e converte R$ 100,00 |
| Operação | Limite |
|---|---|
| Cobrança | De R$ 5,00 a R$ 1.000,00, e o valor precisa ser maior que a tarifa. |
| Saque Pix | A partir de R$ 1,00. |
| Saque em USDT | De R$ 20,00 a R$ 3.000,00. |
| Requisições | 100 por minuto por chave e 40 criações por minuto por conta. |
Idempotência
Toda criação de cobrança ou saque exige o header Idempotency-Key, com 8 a 100 letras, números, hífen ou sublinhado.
Idempotency-Key: pedido-1001Em caso de timeout, repita com a mesma chave: o mesmo corpo devolve a transação já criada, sem duplicar. Dados diferentes com a mesma chave respondem 409.
Erros
Toda resposta de erro traz error com a mensagem e code com um identificador. O status HTTP diz a categoria.
| Status | Nome | Descrição |
|---|---|---|
| 400 | Dados inválidos | Campo faltando, tipo errado ou Idempotency-Key ausente. code = VALIDATION_ERROR nos erros de campo. |
| 401 | Não autenticado | Chave ausente, inválida ou revogada. |
| 403 | Sem permissão | Conta não aprovada (code = ACCOUNT_NOT_APPROVED) ou chave sem a permissão da rota. |
| 404 | Não encontrado | O recurso não existe ou não pertence à sua conta. |
| 409 | Conflito | Idempotency-Key usada com outros dados. |
| 422 | Regra de negócio | Saldo insuficiente, limite da conta ou valor que não cobre a tarifa. |
| 429 | Muitas requisições | Limite atingido: espere antes de tentar de novo. |
| 500 | Erro interno | Erro inesperado do nosso lado (code = INTERNAL_ERROR). Consulte a transação antes de repetir. |
Exemplo de Resposta
{
"error": "Saldo insuficiente para o valor do saque e a tarifa de R$ 1,50.",
"code": "REQUEST_ERROR"
}Timeout em saque
REVIEW mantém a reserva até a conferência da Royalpay.Gerar cobrança
/payments
cashinAutenticação: chave de acesso (Bearer) com a permissão payments:write.
Cria uma cobrança Pix para receber pagamento de um cliente. Retorna o copia e cola e o link de pagamento. HTTP 201 indica que a solicitação existe; só COMPLETED significa pagamento confirmado.
Headers
| Parâmetro | Tipo | Descrição |
|---|---|---|
Idempotency-Key * | string | Identificador único da operação. Veja Idempotência. |
Parâmetros
| Parâmetro | Tipo | Descrição |
|---|---|---|
amountCents * | integer | Valor em centavos, de 500 a 100000. Ex.: 10000 |
description | string | Descrição, de 3 a 200 caracteres. Sem o campo, vale “Cobrança Pix”. |
payerName | string | Nome do pagador, de 3 a 120 caracteres. |
payerDocument | string | CPF válido do pagador. Sem pagador, o comprovante mostra “Pagador não identificado” até o pagamento trazer esse dado. |
checkout | string | Slug de um checkout publicado da sua conta. O checkoutUrl da resposta abre o Pix com a identidade visual dele. |
Exemplo de Requisição
curl -X POST 'https://useroyalpay.com.br/api/v1/payments' \
-H 'Authorization: Bearer SUA_CHAVE' \
-H 'Idempotency-Key: pedido-1001' \
-H 'Content-Type: application/json' \
-d '{
"amountCents": 10000,
"description": "Pedido 1001",
"payerName": "Nome do cliente",
"payerDocument": "52998224725"
}'Exemplo de Resposta
{
"data": {
"id": "UUID_DA_TRANSACAO",
"kind": "DEPOSIT",
"status": "PENDING",
"amount_cents": 10000,
"fee_cents": 450,
"description": "Pedido 1001",
"copy_paste": "CODIGO_PIX",
"created_at": "2026-11-01T12:00:00.000Z"
},
"checkoutUrl": "https://useroyalpay.com.br/pagar/UUID_DA_TRANSACAO"
}Respostas
| Status | Descrição |
|---|---|
| 201 | Cobrança criada, com copia e cola e checkoutUrl. |
| 400 | Dados inválidos ou Idempotency-Key ausente. |
| 401 | Chave ausente, inválida ou revogada. |
| 403 | Conta não aprovada ou chave sem essa permissão. |
| 409 | Idempotency-Key já usada com outros dados. |
| 422 | Valor não cobre a tarifa, limite da conta atingido ou checkout fora do ar. |
Listar cobranças
/payments
cashinAutenticação: chave de acesso (Bearer) com a permissão payments:read.
Lista as suas cobranças, 15 por página.
Parâmetros
| Parâmetro | Tipo | Descrição |
|---|---|---|
page | integer | Página, a partir de 1. |
status | string | CREATED, PROCESSING, PENDING, COMPLETED, FAILED ou REVIEW. |
search | string | Busca por nome, descrição ou ID. |
from | date | Data inicial, no formato AAAA-MM-DD. |
to | date | Data final, no formato AAAA-MM-DD. |
Exemplo de Requisição
curl 'https://useroyalpay.com.br/api/v1/payments?page=1&status=COMPLETED' \
-H 'Authorization: Bearer SUA_CHAVE'Exemplo de Resposta
{
"transactions": [
{
"id": "UUID_DA_TRANSACAO",
"kind": "DEPOSIT",
"status": "COMPLETED",
"amount_cents": 10000
}
],
"total": 1,
"page": 1,
"pages": 1
}Respostas
| Status | Descrição |
|---|---|
| 200 | Lista em transactions, com total, page e pages. |
| 400 | Filtro inválido. |
| 401 | Chave ausente, inválida ou revogada. |
| 403 | Conta não aprovada ou chave sem essa permissão. |
Consultar cobrança
/payments/:id
cashinAutenticação: chave de acesso (Bearer) com a permissão payments:read.
Consulta uma cobrança pelo id devolvido na criação. A resposta vem em data.
Parâmetros
| Parâmetro | Tipo | Descrição |
|---|---|---|
id * | uuid | ID devolvido na criação da cobrança (no caminho). |
Exemplo de Requisição
curl 'https://useroyalpay.com.br/api/v1/payments/UUID_DA_TRANSACAO' \
-H 'Authorization: Bearer SUA_CHAVE'Respostas
| Status | Descrição |
|---|---|
| 200 | Dados da cobrança. |
| 401 | Chave ausente, inválida ou revogada. |
| 403 | Conta não aprovada ou chave sem essa permissão. |
| 404 | O ID não existe ou não é da sua conta. |
Solicitar saque
/withdrawals
cashoutAutenticação: chave de acesso (Bearer) com a permissão withdrawals:write.
Solicita um saque para qualquer chave Pix. O valor mais a tarifa de R$ 1,50 são reservados na hora.
Aprovação manual
APPROVAL e só é enviado depois de aprovado pela Royalpay. Se for recusado, vira FAILED com o motivo em failure_reason, o total volta ao saldo e o evento withdrawal.failed é enviado.Headers
| Parâmetro | Tipo | Descrição |
|---|---|---|
Idempotency-Key * | string | Identificador único da operação. Veja Idempotência. |
Parâmetros
| Parâmetro | Tipo | Descrição |
|---|---|---|
amountCents * | integer | Valor em centavos, a partir de 100. Ex.: 10000 |
pixKeyType * | string | CPF, CNPJ, EMAIL, TELEFONE ou CHAVE_ALEATORIA. |
pixKey * | string | Chave Pix. CPF e CNPJ só com números, telefone como +5511999999999 e chave aleatória em UUID. |
description | string | Descrição, de 3 a 200 caracteres. |
Exemplo de Requisição
curl -X POST 'https://useroyalpay.com.br/api/v1/withdrawals' \
-H 'Authorization: Bearer SUA_CHAVE' \
-H 'Idempotency-Key: saque-1001' \
-H 'Content-Type: application/json' \
-d '{
"amountCents": 10000,
"pixKeyType": "EMAIL",
"pixKey": "financeiro@seunegocio.com",
"description": "Saque do pedido 1001"
}'Exemplo de Resposta
{
"data": {
"id": "UUID_DA_TRANSACAO",
"kind": "WITHDRAWAL",
"status": "APPROVAL",
"amount_cents": 10000,
"fee_cents": 150,
"pix_key_type": "EMAIL",
"pix_key": "financeiro@seunegocio.com",
"failure_reason": null,
"created_at": "2026-11-01T12:00:00.000Z"
},
"checkoutUrl": null
}Respostas
| Status | Descrição |
|---|---|
| 201 | Saque registrado em APPROVAL. |
| 400 | Dados inválidos, chave Pix que não bate com o tipo ou Idempotency-Key ausente. |
| 401 | Chave ausente, inválida ou revogada. |
| 403 | Conta não aprovada, chave sem withdrawals:write ou 2FA redefinido há menos de 24 horas. |
| 409 | Idempotency-Key já usada com outros dados. |
| 422 | Saldo insuficiente para o valor mais a tarifa, ou limite da conta atingido. |
Solicitar saque em USDT
/withdrawals
cashoutAutenticação: chave de acesso (Bearer) com a permissão withdrawals:write.
Mesma rota do saque Pix, para uma carteira na rede BEP20. Segue a mesma reserva e a mesma aprovação manual.
Headers
| Parâmetro | Tipo | Descrição |
|---|---|---|
Idempotency-Key * | string | Identificador único da operação. Veja Idempotência. |
Parâmetros
| Parâmetro | Tipo | Descrição |
|---|---|---|
amountCents * | integer | Valor em centavos, de 2000 a 300000. Ex.: 10000 |
pixKeyType * | string | Sempre USDT_BEP20. |
pixKey * | string | Carteira BEP20: 0x seguido de 40 caracteres hexadecimais. |
description | string | Descrição, de 3 a 200 caracteres. |
Confira a carteira
Exemplo de Requisição
curl -X POST 'https://useroyalpay.com.br/api/v1/withdrawals' \
-H 'Authorization: Bearer SUA_CHAVE' \
-H 'Idempotency-Key: saque-usdt-1001' \
-H 'Content-Type: application/json' \
-d '{
"amountCents": 10000,
"pixKeyType": "USDT_BEP20",
"pixKey": "0x0000000000000000000000000000000000000000"
}'Respostas
| Status | Descrição |
|---|---|
| 201 | Saque registrado em APPROVAL. |
| 400 | Carteira inválida ou valor fora da faixa. |
| 403 | Conta não aprovada, chave sem withdrawals:write ou 2FA redefinido há menos de 24 horas. |
| 422 | Saldo insuficiente ou limite da conta atingido. |
Listar saques
/withdrawals
cashoutAutenticação: chave de acesso (Bearer) com a permissão payments:read.
Lista os seus saques, 15 por página, com os mesmos filtros de Listar cobranças.
Exemplo de Requisição
curl 'https://useroyalpay.com.br/api/v1/withdrawals?page=1' \
-H 'Authorization: Bearer SUA_CHAVE'Exemplo de Resposta
{
"transactions": [
{
"id": "UUID_DA_TRANSACAO",
"kind": "WITHDRAWAL",
"status": "COMPLETED",
"amount_cents": 10000
}
],
"total": 1,
"page": 1,
"pages": 1
}Respostas
| Status | Descrição |
|---|---|
| 200 | Lista em transactions, com total, page e pages. |
| 401 | Chave ausente, inválida ou revogada. |
| 403 | Conta não aprovada ou chave sem essa permissão. |
Consultar saque
/withdrawals/:id
cashoutAutenticação: chave de acesso (Bearer) com a permissão payments:read.
Consulta um saque pelo id devolvido na criação. A resposta vem em data.
Parâmetros
| Parâmetro | Tipo | Descrição |
|---|---|---|
id * | uuid | ID devolvido na criação do saque (no caminho). |
Exemplo de Requisição
curl 'https://useroyalpay.com.br/api/v1/withdrawals/UUID_DA_TRANSACAO' \
-H 'Authorization: Bearer SUA_CHAVE'Respostas
| Status | Descrição |
|---|---|
| 200 | Dados do saque. |
| 401 | Chave ausente, inválida ou revogada. |
| 403 | Conta não aprovada ou chave sem essa permissão. |
| 404 | O ID não existe ou não é da sua conta. |
Consultar saldo
/balance
contaAutenticação: chave de acesso (Bearer) com a permissão payments:read.
Saldo individual da sua conta, em centavos.
| Campo | Descrição |
|---|---|
available_cents | Disponível para sacar. Fica negativo se um MED bloquear mais do que há disponível. |
reserved_cents | Comprometido com saques em andamento. |
blocked_cents | Bloqueado por MED em aberto. |
Exemplo de Requisição
curl 'https://useroyalpay.com.br/api/v1/balance' \
-H 'Authorization: Bearer SUA_CHAVE'Exemplo de Resposta
{
"data": {
"available_cents": 9550,
"reserved_cents": 0,
"blocked_cents": 0
},
"currency": "BRL"
}Respostas
| Status | Descrição |
|---|---|
| 200 | Saldo da conta. |
| 401 | Chave ausente, inválida ou revogada. |
| 403 | Conta não aprovada ou chave sem essa permissão. |
Listar checkouts
/checkouts
contaAutenticação: chave de acesso (Bearer) com a permissão payments:read.
Lista os checkouts publicados em Checkouts e os links deles. Pelo link público, o preço vem sempre da versão publicada.
Exemplo de Requisição
curl 'https://useroyalpay.com.br/api/v1/checkouts' \
-H 'Authorization: Bearer SUA_CHAVE'Exemplo de Resposta
{
"data": [
{
"slug": "k3m9x2pa",
"name": "Curso de março",
"url": "https://useroyalpay.com.br/c/k3m9x2pa",
"version": 3,
"product": "Curso completo",
"priceCents": 29700,
"offerActive": true,
"offerEndsAt": "2026-11-20T23:59:00.000Z"
}
]
}Respostas
| Status | Descrição |
|---|---|
| 200 | Checkouts publicados. |
| 401 | Chave ausente, inválida ou revogada. |
| 403 | Conta não aprovada ou chave sem essa permissão. |
Configurar webhook
A Royalpay chama a sua URL com POST quando uma cobrança ou um saque é concluído ou falha. É a forma recomendada de acompanhar as operações.
- No painel, abra Webhooks.
- Cadastre a URL do seu sistema: HTTPS público, na porta 443.
- Guarde o segredo de assinatura. Salvar o webhook de novo gera outro segredo.
Reenvio automático
Payload dos eventos
Exemplo de uma cobrança paga. Em saques, netCents vem como null.
| Evento | Quando |
|---|---|
payment.completed | Cobrança paga. |
payment.failed | Cobrança falhou. |
withdrawal.completed | Saque concluído. |
withdrawal.failed | Saque falhou ou foi recusado. O total voltou ao saldo. |
Exemplo de Payload
{
"id": "UUID_DO_EVENTO",
"event": "payment.completed",
"createdAt": "2026-11-01T12:00:00.000Z",
"data": {
"id": "UUID_DA_TRANSACAO",
"type": "DEPOSIT",
"status": "COMPLETED",
"amountCents": 10000,
"feeCents": 450,
"netCents": 9550,
"currency": "BRL"
}
}Validar assinatura
Valide a assinatura com o corpo bruto, antes de interpretar o JSON. Ela é um HMAC SHA-256 de timestamp.corpo com o segredo do webhook.
| Header | O que é |
|---|---|
X-Royalpay-Signature | Assinatura, no formato v1=hex. |
X-Royalpay-Timestamp | Momento do envio, em segundos. |
X-Royalpay-Event-Id | ID do evento, igual ao id do corpo. |
Exemplo de Validação
import { createHmac, timingSafeEqual } from "node:crypto";
const timestamp = request.headers["x-royalpay-timestamp"];
const signature = request.headers["x-royalpay-signature"];
if (typeof timestamp !== "string" || !/^\d+$/.test(timestamp)) {
throw new Error("Timestamp inválido");
}
if (Math.abs(Date.now() / 1000 - Number(timestamp)) > 300) {
throw new Error("Evento fora da janela de 5 minutos");
}
const expected = "v1=" + createHmac("sha256", WEBHOOK_SECRET)
.update(timestamp + "." + rawBody)
.digest("hex");
const a = Buffer.from(expected);
const b = Buffer.from(signature ?? "");
if (a.length !== b.length || !timingSafeEqual(a, b)) {
throw new Error("Assinatura inválida");
}
// Guarde o evento pelo id e responda 2xx.Boas práticas
- Valide a assinatura de toda notificação antes de usar os dados.
- Responda 2xx rápido e processe o pedido depois, numa fila ou tarefa em segundo plano.
- Trate repetições: use o
iddo evento para não entregar o mesmo pedido duas vezes. - Confirme em caso de dúvida com
GET /payments/:idantes de liberar o produto.
