Começar
Primeira cobrança
Do zero ao primeiro Pix pago em cinco passos, com exemplos em cURL, Node.js, Python e PHP.
Este guia leva você da chave de API até a confirmação do pagamento. Os exemplos usam a variável de ambiente KOKU_API_KEY; troque pelos seus valores.
- Gere a chave. No painel, em Desenvolvedores › Chaves de API, crie uma chave com
charges:write,charges:read,webhooks:readewebhooks:write. Guarde-a emKOKU_API_KEYno seu servidor. Veja Chaves de API. - Cadastre o webhook. Informe a URL HTTPS que vai receber os eventos e guarde o segredo de assinatura.
- Crie a cobrança. Envie valor, pedido e os dados do pagador com uma
Idempotency-Key. - Mostre o Pix. Exiba o QR Code e o copia e cola de
pix.qr_code_payload. - Confirme o pagamento. Receba
charge.paid, confira a assinatura, consulte a cobrança e libere o pedido.
1. Confira a chave
Antes de tudo, confirme que a chave funciona e tem os escopos certos:
curl -X GET 'https://api.kokupay.com/v1/api-keys/current' \
-H "Authorization: Bearer $KOKU_API_KEY"const response = await fetch('https://api.kokupay.com/v1/api-keys/current', {
method: 'GET',
headers: {
Authorization: `Bearer ${process.env.KOKU_API_KEY}`,
},
});
const data = await response.json();
console.log(response.status, data);import os
import requests
response = requests.request(
"GET",
"https://api.kokupay.com/v1/api-keys/current",
headers={
"Authorization": f"Bearer {os.environ['KOKU_API_KEY']}",
},
timeout=30,
)
print(response.status_code, response.json())<?php
$ch = curl_init('https://api.kokupay.com/v1/api-keys/current');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . getenv('KOKU_API_KEY'),
],
]);
$data = json_decode(curl_exec($ch), true);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
echo $status, PHP_EOL;
print_r($data);{
"id": "a9d4e2f7-0b31-4c6e-8f52-3e7a1d9c6b04",
"name": "Checkout da loja",
"prefix": "koku_live_3f9a1c2b4d5e",
"gateway_id": "5f0c2a9e-1b7d-4c3e-9a51-2d8e6f4b7c10",
"environment": "production",
"scopes": [
"charges:read",
"charges:write",
"refunds:write",
"balance:read",
"statement:read",
"payouts:read",
"webhooks:read",
"webhooks:write"
],
"expires_at": null,
"created_at": "2026-10-07T14:00:00.000Z"
}Se a resposta for 401, a chave está errada, revogada ou expirada. Se algum escopo faltar, gere outra chave.
2. Cadastre o endpoint de webhook
O segredo de assinatura (signing_secret) aparece só nesta resposta. Guarde-o em KOKU_WEBHOOK_SECRET. Também é possível cadastrar pelo painel, em Desenvolvedores › Webhooks.
curl -X POST 'https://api.kokupay.com/v1/webhooks/endpoints' \
-H "Authorization: Bearer $KOKU_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://loja.example.com/webhooks/koku",
"event_types": [
"charge.paid",
"charge.expired",
"charge.failed",
"charge.refunded"
]
}'const response = await fetch('https://api.kokupay.com/v1/webhooks/endpoints', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.KOKU_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
url: 'https://loja.example.com/webhooks/koku',
event_types: ['charge.paid', 'charge.expired', 'charge.failed', 'charge.refunded'],
}),
});
const data = await response.json();
console.log(response.status, data);import os
import requests
response = requests.request(
"POST",
"https://api.kokupay.com/v1/webhooks/endpoints",
headers={
"Authorization": f"Bearer {os.environ['KOKU_API_KEY']}",
},
json={
"url": "https://loja.example.com/webhooks/koku",
"event_types": ["charge.paid", "charge.expired", "charge.failed", "charge.refunded"],
},
timeout=30,
)
print(response.status_code, response.json())<?php
$ch = curl_init('https://api.kokupay.com/v1/webhooks/endpoints');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . getenv('KOKU_API_KEY'),
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => json_encode([
'url' => 'https://loja.example.com/webhooks/koku',
'event_types' => [
'charge.paid',
'charge.expired',
'charge.failed',
'charge.refunded',
],
]),
]);
$data = json_decode(curl_exec($ch), true);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
echo $status, PHP_EOL;
print_r($data);{
"id": "71c3e9a5-4f2d-4b8e-a06c-9d5e2f1b7a38",
"signing_secret": "whsec_Zq4m8Tn2Vb7Lk1Xc9Rd5Hs3Wf6Jp0Ga2Ye8Ui4Ko7"
}3. Crie a cobrança Pix
Use o identificador do pedido do seu sistema em order_reference e uma Idempotency-Key única por pedido. Se a rede falhar no meio, repita a mesma chamada com a mesma chave: você recebe a mesma cobrança, sem duplicar.
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
}4. Mostre o Pix ao comprador
Com status: "pending", a resposta traz:
pix.qr_code_payload: o código copia e cola. Gere a imagem do QR Code a partir dele no seu front-end.pix.expires_at: até quando o QR vale. Mostre um contador e, ao expirar, ofereça gerar uma nova cobrança.
Se vier status: "created" sem pix, a emissão ainda está em andamento: consulte a cobrança em alguns segundos. Não crie outra cobrança para o mesmo pedido. Veja QR Code e copia e cola.
5. Receba a confirmação
Quando o comprador paga, a Koku envia charge.paid para o seu endpoint:
charge.paid{
"id": "evt_2f6b1c9e8a4d4e7f9b3c5a1d0e6f8b27",
"type": "charge.paid",
"version": "v1",
"created_at": "2026-10-07T15:32:11.000Z",
"environment": "production",
"data": {
"charge_id": "8d3f6a12-4b9e-4c71-a2d5-6e0f1b3c9a47",
"order_reference": "PEDIDO-1001",
"amount_cents": "15990",
"fee_cents": "320",
"net_cents": "15670",
"reserve_cents": "0",
"paid_at": "2026-10-07T15:32:10.000Z",
"end_to_end_id": "E12345678202610071532a1B2c3D4e5F",
"late_payment": false,
"case_id": null
}
}Responda 2xx rapidamente, confira a assinatura e, antes de liberar o pedido, consulte a cobrança:
curl -X GET 'https://api.kokupay.com/v1/pix/charges/8d3f6a12-4b9e-4c71-a2d5-6e0f1b3c9a47' \
-H "Authorization: Bearer $KOKU_API_KEY"const response = await fetch('https://api.kokupay.com/v1/pix/charges/8d3f6a12-4b9e-4c71-a2d5-6e0f1b3c9a47', {
method: 'GET',
headers: {
Authorization: `Bearer ${process.env.KOKU_API_KEY}`,
},
});
const data = await response.json();
console.log(response.status, data);import os
import requests
response = requests.request(
"GET",
"https://api.kokupay.com/v1/pix/charges/8d3f6a12-4b9e-4c71-a2d5-6e0f1b3c9a47",
headers={
"Authorization": f"Bearer {os.environ['KOKU_API_KEY']}",
},
timeout=30,
)
print(response.status_code, response.json())<?php
$ch = curl_init('https://api.kokupay.com/v1/pix/charges/8d3f6a12-4b9e-4c71-a2d5-6e0f1b3c9a47');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . getenv('KOKU_API_KEY'),
],
]);
$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": "paid",
"fee_percent_bps": 200,
"fee_fixed_cents": "0",
"fee_cents": "320",
"net_cents": "15670",
"reserve_cents": "0",
"refunded_cents": "0",
"expires_at": "2026-10-07T16:00:00.000Z",
"paid_at": "2026-10-07T15:32:10.000Z",
"late_payment": false,
"is_simulated": false,
"created_at": "2026-10-07T15:30:00.000Z",
"updated_at": "2026-10-07T15:32:11.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": "E12345678202610071532a1B2c3D4e5F",
"payments_count": 1,
"failure_message": null
}Pronto: com status: "paid", libere o pedido. fee_cents é a tarifa da Koku e net_cents é o que entra no seu saldo.