Criar pagamento
Como criar uma cobrança pela API única da Allya Payments.
Use POST /v1/payments para criar um pagamento.
Pix e cartão podem ser roteados para Abacate Pay, Asaas ou Pagar.me. Pix pode retornar QR Code quando o gateway disponibiliza esse dado. Cartão usa checkout/fatura hospedada do gateway e retorna checkoutUrl; não envie CVV nem número completo de cartão para a Allya.
Requisitos antes da chamada
No painel, configure:
- Projeto.
- Ambiente.
- Gateway ativo com credenciais válidas.
- Regra de roteamento para o método desejado (em Pagamentos avulsos).
- API key do mesmo ambiente.
Pedido mínimo viável
Para Pix, o menor body aceito é:
{
"amount": 1990,
"currency": "BRL",
"method": "pix",
"externalId": "pedido_001",
"customer": {
"name": "Cliente Teste",
"email": "cliente@example.com",
"document": "00000000000"
}
}Para cartão (qualquer gateway):
{
"amount": 12990,
"currency": "BRL",
"method": "card",
"externalId": "pedido_001",
"customer": {
"name": "Cliente Teste",
"email": "cliente@example.com",
"document": "00000000000",
"phone": "11999999999"
}
}externalId é exigido em todas as chamadas (idempotência). phone só é obrigatório quando method=card no Pagar.me: manter sempre cobre todos os casos sem código condicional.
Criar Pix
type PaymentStatus =
| "created"
| "pending"
| "processing"
| "paid"
| "failed"
| "canceled"
| "expired";
type CreatePaymentResponse = {
id: string;
status: PaymentStatus;
method: "pix" | "card";
gateway: "abacate_pay" | "asaas" | "pagarme";
amount: number;
currency: "BRL";
externalId: string | null;
gatewayRef: string | null;
customer: {
name: string | null;
email: string | null;
documentLast4: string | null;
} | null;
checkoutUrl: string | null;
pix: {
qrCode?: string;
qrCodeText?: string;
} | null;
card: {
brand?: string;
last4?: string;
} | null;
};
const response = await fetch("https://payments-api.allyasolutions.com/v1/payments", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.ALLYA_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
amount: 4990,
currency: "BRL",
method: "pix",
externalId: "pedido_123",
customer: {
name: "Cliente Teste",
email: "cliente@example.com",
document: "00000000000",
},
metadata: {
orderId: "pedido_123",
description: "Pedido 123",
},
}),
});
if (!response.ok) {
const error = await response.json();
throw new Error(error.error);
}
const payment = (await response.json()) as CreatePaymentResponse;
console.log(payment.pix?.qrCodeText);Criar cartão com checkout hospedado
const response = await fetch("https://payments-api.allyasolutions.com/v1/payments", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.ALLYA_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
amount: 12990,
currency: "BRL",
method: "card",
externalId: "pedido_124",
customer: {
name: "Cliente Teste",
email: "cliente@example.com",
document: "00000000000",
phone: "11999999999",
},
metadata: {
orderId: "pedido_124",
description: "Pedido 124",
},
}),
});
const payment = (await response.json()) as CreatePaymentResponse;
console.log(payment.checkoutUrl);Campos principais
| Campo | Tipo | Descrição |
|---|---|---|
amount | number | Valor em centavos. 4990 representa R$ 49,90. |
currency | string | Moeda. Use BRL. |
method | string | pix ou card. |
externalId | string | Obrigatório em todos os gateways. Identificador único do seu sistema (ex.: pedido_42). Funciona como chave de idempotência: reenviar a mesma chamada com o mesmo externalId retorna o pagamento já criado, sem disparar nova cobrança no gateway. Máx. 255 caracteres. |
customer.name | string | Nome do cliente. |
customer.email | string | E-mail do cliente. |
customer.document | string | CPF/CNPJ usado pelo gateway. |
customer.phone | string | Telefone com DDD (10+ dígitos). Obrigatório quando method=card e o gateway resolvido é Pagar.me: caso ausente, a API retorna 400 invalid_input. Opcional nos demais casos. |
metadata | object | Dados livres para correlação interna. Aceita apenas JSON (string, number, boolean, null, objetos e arrays), até 4 KiB serializados e profundidade máxima 4. Evite enviar PII ou segredos. |
card.installments | number | Número de parcelas para checkout hospedado de cartão. Opcional; default 1. Limite real depende do gateway: veja tabela abaixo. |
A Allya não usa header Idempotency-Key. A chave idempotente é o campo externalId do body, obrigatório e único por ambiente. Reenviar o mesmo externalId retorna o pagamento já criado, mesmo que o retry venha depois de timeout.
Retorno por método
| Campo | Quando aparece | Descrição |
|---|---|---|
customer.name | Sempre que salvo no pagamento | Nome do cliente enviado na criação. |
customer.email | Sempre que salvo no pagamento | E-mail do cliente enviado na criação. |
customer.documentLast4 | Sempre que salvo no pagamento | Últimos 4 dígitos do CPF/CNPJ. O documento completo não é retornado nem persistido em plaintext. |
pix.qrCodeText | Pix | Código Pix copia e cola, quando retornado pelo gateway. |
pix.qrCode | Pix | Imagem ou URL do QR Code, quando retornada pelo gateway. |
checkoutUrl | Cartão | URL hospedada pelo gateway para o cliente concluir o pagamento. |
No Asaas, o QR Code Pix é obtido em uma segunda chamada após criar o pagamento. Se essa chamada falhar (timeout, 5xx), o pagamento é retornado sem pix.qrCode/pix.qrCodeText e a Allya registra um warning. Use POST /v1/payments/:id/sync para consultar o gateway e recuperar o QR depois: o pagamento já existe e é cobrável.
Parcelamento por gateway
card.installments é aceito de 1 a 24 no schema da Allya. O limite efetivo depende do gateway resolvido pelo roteamento:
| Gateway | Limite | Comportamento da Allya |
|---|---|---|
| Abacate Pay | 1 a 12 | Acima de 12 → 400 invalid_input antes de chamar o gateway. |
| Asaas | 1 a 24 | 1x vira cobrança simples (value); 2x+ vira installmentCount + totalValue (parcelada). |
| Pagar.me | 1 a 24 | Passado direto como max_installments no payment link. |
Em assinatura recorrente (POST /v1/subscriptions), card.installments é ignorado: assinatura não parcela.
Rate limit
POST /v1/payments aplica um limite de requisições por API key, em janela deslizante de 60 segundos. O default é 30 requisições por minuto. Quando o limite é ultrapassado a resposta é 429 rate_limit_exceeded.
Toda resposta da rota inclui os headers:
| Header | Descrição |
|---|---|
X-RateLimit-Limit | Limite atual da janela. |
X-RateLimit-Remaining | Quantas requisições ainda cabem na janela. |
X-RateLimit-Reset | Unix timestamp (segundos) em que o slot mais antigo expira. |
Retry-After | Apenas em 429: segundos para tentar novamente. |
const res = await fetch("https://payments-api.allyasolutions.com/v1/payments", options);
if (res.status === 429) {
const retryAfter = Number(res.headers.get("Retry-After") ?? "1");
await new Promise((r) => setTimeout(r, retryAfter * 1000));
// ...retry
}Idempotência
A Allya usa o campo externalId como chave de idempotência por ambiente: enviar o mesmo externalId duas vezes retorna o pagamento já criado, sem disparar nova cobrança no gateway. Cobre retentativas por timeout, jobs duplicados e chamadas concorrentes (race-safe).
Veja Idempotência para regras detalhadas, limitações e exemplo de retentativa segura com backoff.
Consultar pagamento depois
Para checar o status de um pagamento criado, use GET /v1/payments/:id (pelo id retornado aqui) ou GET /v1/payments?externalId=... (pelo seu identificador idempotente).
Se um webhook não chegou e você precisa consultar o gateway diretamente, use POST /v1/payments/:id/sync. Para links de cartão do Pagar.me, a Allya também considera total_paid_sessions > 0 no payment link como pagamento aprovado. Para cancelar uma cobrança de cartão ainda não paga, use POST /v1/payments/:id/cancel.
Veja também
- Status de pagamento: significado de cada
status. - Webhooks: recebimento de eventos
payment.*. - Idempotência: comportamento com mesmo
externalId. - Erros: códigos de erro retornados pela rota.
- Rate limiting: cotas e headers.