Pix
Criar cobrança
Como criar uma cobrança Pix, quais dados enviar e o que fazer com a resposta.
POST /v1/pix/charges cria uma cobrança Pix e devolve o QR Code e o código copia e cola. Escopo: charges:write. Referência completa: Criar cobrança Pix.
curl -X POST 'https://api.kokupay.com/v1/pix/charges' \
-H "Authorization: Bearer $KOKU_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: pedido-1001" \
-d '{
"order_reference": "PEDIDO-1001",
"amount_cents": 15990,
"description": "Pedido 1001 - Loja Exemplo",
"payer": {
"name": "Maria Souza",
"document": "12345678909",
"email": "maria.souza@example.com",
"phone": "11987654321"
},
"expires_in_seconds": 1800,
"metadata": {
"canal": "checkout-web"
}
}'const response = await fetch('https://api.kokupay.com/v1/pix/charges', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.KOKU_API_KEY}`,
'Content-Type': 'application/json',
'Idempotency-Key': 'pedido-1001',
},
body: JSON.stringify({
order_reference: 'PEDIDO-1001',
amount_cents: 15990,
description: 'Pedido 1001 - Loja Exemplo',
payer: {
name: 'Maria Souza',
document: '12345678909',
email: 'maria.souza@example.com',
phone: '11987654321',
},
expires_in_seconds: 1800,
metadata: {
canal: 'checkout-web',
},
}),
});
const data = await response.json();
console.log(response.status, data);import os
import requests
response = requests.request(
"POST",
"https://api.kokupay.com/v1/pix/charges",
headers={
"Authorization": f"Bearer {os.environ['KOKU_API_KEY']}",
"Idempotency-Key": "pedido-1001",
},
json={
"order_reference": "PEDIDO-1001",
"amount_cents": 15990,
"description": "Pedido 1001 - Loja Exemplo",
"payer": {
"name": "Maria Souza",
"document": "12345678909",
"email": "maria.souza@example.com",
"phone": "11987654321",
},
"expires_in_seconds": 1800,
"metadata": {
"canal": "checkout-web",
},
},
timeout=30,
)
print(response.status_code, response.json())<?php
$ch = curl_init('https://api.kokupay.com/v1/pix/charges');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . getenv('KOKU_API_KEY'),
'Content-Type: application/json',
'Idempotency-Key: pedido-1001',
],
CURLOPT_POSTFIELDS => json_encode([
'order_reference' => 'PEDIDO-1001',
'amount_cents' => 15990,
'description' => 'Pedido 1001 - Loja Exemplo',
'payer' => [
'name' => 'Maria Souza',
'document' => '12345678909',
'email' => 'maria.souza@example.com',
'phone' => '11987654321',
],
'expires_in_seconds' => 1800,
'metadata' => [
'canal' => 'checkout-web',
],
]),
]);
$data = json_decode(curl_exec($ch), true);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
echo $status, PHP_EOL;
print_r($data);{
"id": "8d3f6a12-4b9e-4c71-a2d5-6e0f1b3c9a47",
"gateway_id": "5f0c2a9e-1b7d-4c3e-9a51-2d8e6f4b7c10",
"environment": "production",
"order_reference": "PEDIDO-1001",
"amount_cents": "15990",
"currency": "BRL",
"description": "Pedido 1001 - Loja Exemplo",
"status": "pending",
"fee_percent_bps": 200,
"fee_fixed_cents": "0",
"fee_cents": null,
"net_cents": null,
"reserve_cents": null,
"refunded_cents": "0",
"expires_at": "2026-10-07T16:00:00.000Z",
"paid_at": null,
"late_payment": false,
"is_simulated": false,
"created_at": "2026-10-07T15:30:00.000Z",
"updated_at": "2026-10-07T15:30:01.000Z",
"pix": {
"qr_code_payload": "00020101021226850014br.gov.bcb.pix2563qr.exemplo.com.br/pix/v2/8d3f6a124b9e4c71a2d56e0f1b3c9a475204000053039865406159.905802BR5913LOJA EXEMPLO6009SAO PAULO62070503***6304A1B2",
"txid": "8d3f6a124b9e4c71a2d56e0f1b3c9a47",
"expires_at": "2026-10-07T16:00:00.000Z"
},
"end_to_end_id": null,
"payments_count": 0,
"failure_message": null
}Campos do pedido
| Campo | Obrigatório | Descrição |
|---|---|---|
order_reference | sim | Identificador do pedido no seu sistema (1 a 120 caracteres). Único na sua conta: não pode se repetir em outra cobrança. |
amount_cents | sim | Valor em centavos, inteiro positivo. 15990 = R$ 159,90. |
payer.name | sim | Nome completo do pagador. |
payer.document | sim | CPF (11 dígitos) ou CNPJ (14 dígitos), só números. |
payer.email | sim | E-mail do pagador. |
payer.phone | sim | Telefone com DDD, só dígitos, com ou sem +55. |
description | não | Descrição para você (até 500 caracteres). |
expires_in_seconds | não | Validade do QR: de 60 segundos a 7 dias. Padrão: 1 hora. |
metadata | não | Até 20 pares chave/valor de texto para o seu controle. |
currency | não | Só BRL. |
Cabeçalho obrigatório: Idempotency-Key (8 a 200 caracteres). Veja Idempotência.
Campos fora desta lista são recusados com 422: a API não ignora campo desconhecido, para que um erro de digitação não passe despercebido.
Dados do pagador
Os quatro dados do pagador são obrigatórios na prática: a emissão do Pix exige nome, CPF ou CNPJ, e-mail e telefone do comprador. A API aceita o pedido sem eles, mas a emissão pode ser recusada; nesse caso a cobrança volta com status: "failed" e o motivo em failure_message.
- Valide os dados no seu checkout antes de chamar a API (CPF/CNPJ com dígitos verificadores, e-mail e telefone com DDD).
- A Koku usa e-mail e telefone só para emitir o Pix e não os grava. Nome e documento ficam registrados na cobrança; o documento aparece mascarado no painel.
A resposta
| Situação | O que fazer |
|---|---|
201 com status: "pending" e pix preenchido | Mostre o QR Code e o copia e cola. Aguarde o webhook. |
201 com status: "created" e pix: null | A emissão ainda não terminou. Consulte a cobrança em alguns segundos; não crie outra. |
201 com status: "failed" | A emissão foi recusada. failure_message traz o motivo em texto fixo da Koku (lista em Estados da cobrança). Permita nova tentativa com outro order_reference. |
200 com cabeçalho Idempotent-Replayed: true | Você repetiu a mesma chamada: esta é a mesma cobrança de antes. |
409 idempotency_conflict | A mesma Idempotency-Key foi usada com outro corpo. Gere uma chave nova para um pedido novo. |
409 conflict com order_reference_in_use | Já existe cobrança para este pedido. Consulte-a com Listar cobranças filtrando por order_reference. |
422 validation_error | Algum campo está inválido; veja details.fields. |
503 provider_unavailable com details.reason = "processing_unavailable" | Rede de processamento indisponível no momento; nada foi criado. Repita com a mesma Idempotency-Key. |
503 provider_unavailable com details.reason = "account_not_enabled" | O recebimento Pix ainda não está habilitado para a sua conta. Repetir não resolve: fale com a Koku. |
503 service_unavailable | Instabilidade momentânea. Repita com a mesma Idempotency-Key. |
Cobrança recusada na emissão:
{
"id": "e41a9c7b-2d58-4e06-b3f1-7c9d0a2e5b18",
"gateway_id": "5f0c2a9e-1b7d-4c3e-9a51-2d8e6f4b7c10",
"environment": "production",
"order_reference": "PEDIDO-1003",
"amount_cents": "15990",
"currency": "BRL",
"description": "Pedido 1003 - Loja Exemplo",
"status": "failed",
"fee_percent_bps": 200,
"fee_fixed_cents": "0",
"fee_cents": null,
"net_cents": null,
"reserve_cents": null,
"refunded_cents": "0",
"expires_at": null,
"paid_at": null,
"late_payment": false,
"is_simulated": false,
"created_at": "2026-10-07T15:30:00.000Z",
"updated_at": "2026-10-07T15:30:01.000Z",
"pix": null,
"end_to_end_id": null,
"payments_count": 0,
"failure_message": "Emissão recusada pela análise de risco."
}Boas práticas
- Crie a cobrança só quando o comprador escolher Pix, para o QR não expirar à toa.
- Uma cobrança por pedido. Para "gerar outro QR" depois da expiração, crie uma nova cobrança com outro
order_reference(ex.:PEDIDO-1001-2). - Guarde o
idda cobrança junto do pedido: é com ele que você consulta e pede devolução.