Saques
Pedir um saque
https://api.kokupay.com/v1/payouts Pede a transferência de parte do saldo disponível para uma conta de destino verificada da sua empresa. O valor pedido (amount_cents) sai do disponível na hora e fica reservado; a taxa de saque é descontada dele e a resposta mostra requested_cents (pedido), fee_cents (taxa) e amount_cents (o que chega à conta). O pedido nasce com approval_status = "pending": a Koku analisa, aprova e transfere, e você acompanha por Consultar um saque ou pelos eventos payout.approved, payout.rejected e payout.paid. Pode ser pedido a qualquer hora, inclusive em fins de semana e feriados; cada saque vai até R$ 15.000,00 (para valores maiores, faça mais de um pedido).
curl -X POST 'https://api.kokupay.com/v1/payouts' \
-H "Authorization: Bearer $KOKU_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: saque-2026-10-10-01" \
-d '{
"amount_cents": 5000,
"beneficiary_account_id": "e7a2c5f1-3b8d-4e60-a9c4-1f5b7d3e9a28"
}'const response = await fetch('https://api.kokupay.com/v1/payouts', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.KOKU_API_KEY}`,
'Content-Type': 'application/json',
'Idempotency-Key': 'saque-2026-10-10-01',
},
body: JSON.stringify({
amount_cents: 5000,
beneficiary_account_id: 'e7a2c5f1-3b8d-4e60-a9c4-1f5b7d3e9a28',
}),
});
const data = await response.json();
console.log(response.status, data);import os
import requests
response = requests.request(
"POST",
"https://api.kokupay.com/v1/payouts",
headers={
"Authorization": f"Bearer {os.environ['KOKU_API_KEY']}",
"Idempotency-Key": "saque-2026-10-10-01",
},
json={
"amount_cents": 5000,
"beneficiary_account_id": "e7a2c5f1-3b8d-4e60-a9c4-1f5b7d3e9a28",
},
timeout=30,
)
print(response.status_code, response.json())<?php
$ch = curl_init('https://api.kokupay.com/v1/payouts');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . getenv('KOKU_API_KEY'),
'Content-Type: application/json',
'Idempotency-Key: saque-2026-10-10-01',
],
CURLOPT_POSTFIELDS => json_encode([
'amount_cents' => 5000,
'beneficiary_account_id' => 'e7a2c5f1-3b8d-4e60-a9c4-1f5b7d3e9a28',
]),
]);
$data = json_decode(curl_exec($ch), true);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
echo $status, PHP_EOL;
print_r($data);201 · Pedir um saque
{
"id": "a4c81e5d-7f2b-4d39-9e06-3b5f8c1d2e74",
"gateway_id": "5f0c2a9e-1b7d-4c3e-9a51-2d8e6f4b7c10",
"environment": "production",
"requested_cents": "5000",
"fee_cents": "500",
"amount_cents": "4500",
"currency": "BRL",
"beneficiary_account_id": "e7a2c5f1-3b8d-4e60-a9c4-1f5b7d3e9a28",
"destination": {
"holder_name": "Loja Exemplo Ltda",
"holder_document_masked": "**********0001",
"pix_key_masked": "**********0001",
"bank_ispb": null
},
"approval_status": "pending",
"approval_mode": null,
"approval_reason": null,
"approval_decided_at": null,
"execution_status": "reserved",
"scheduled_for": null,
"submitted_at": null,
"confirmed_at": null,
"end_to_end_id": null,
"failure_reason": null,
"awaiting_second_approval": false,
"waiting_reason": null,
"next_attempt_at": null,
"execution_channel": "manual_transfer",
"transfer_reference": null,
"created_at": "2026-10-10T17:00:00.000Z"
}200 · Repetição com a mesma chave
{
"id": "a4c81e5d-7f2b-4d39-9e06-3b5f8c1d2e74",
"gateway_id": "5f0c2a9e-1b7d-4c3e-9a51-2d8e6f4b7c10",
"environment": "production",
"requested_cents": "5000",
"fee_cents": "500",
"amount_cents": "4500",
"currency": "BRL",
"beneficiary_account_id": "e7a2c5f1-3b8d-4e60-a9c4-1f5b7d3e9a28",
"destination": {
"holder_name": "Loja Exemplo Ltda",
"holder_document_masked": "**********0001",
"pix_key_masked": "**********0001",
"bank_ispb": null
},
"approval_status": "pending",
"approval_mode": null,
"approval_reason": null,
"approval_decided_at": null,
"execution_status": "reserved",
"scheduled_for": null,
"submitted_at": null,
"confirmed_at": null,
"end_to_end_id": null,
"failure_reason": null,
"awaiting_second_approval": false,
"waiting_reason": null,
"next_attempt_at": null,
"execution_channel": "manual_transfer",
"transfer_reference": null,
"created_at": "2026-10-10T17:00:00.000Z"
}409 · Saldo disponível insuficiente
{
"error": {
"code": "insufficient_funds",
"message": "Saldo disponível insuficiente para reservar o valor pedido.",
"details": {
"requested_cents": "1400000"
},
"correlation_id": "2f7c1e9a-5b3d-4a86-9c0e-7d4b2f8a1c35"
}
}Autenticação
Authorization: Bearer <sua chave de API>
Escopo exigido: payouts:write. Veja Chaves de API.
Cabeçalhos
Idempotency-KeystringobrigatórioChave única por operação (8 a 200 caracteres ASCII visíveis). Repetir com o mesmo corpo devolve o mesmo resultado.
8 a 200 caracteres
Veja Idempotência.
Corpo da requisição
JSON (Content-Type: application/json). Campos não listados são recusados com 422.
amount_centsinteiro ou stringobrigatórioValor pedido, em centavos (inteiro ou string decimal). Sai do saldo disponível; a taxa de saque é descontada dele. Precisa ser maior que a taxa e, no máximo, o limite por saque.
beneficiary_account_idstring (uuid)obrigatórioConta de destino verificada da sua empresa (veja Listar contas de destino).
Resposta 201
201 na criação; 200 com o mesmo recurso quando a requisição é repetida com a mesma Idempotency-Key e o mesmo corpo (cabeçalho Idempotent-Replayed: true).
idstring (uuid)Identificador do saque.
gateway_idstring (uuid)Identificador da sua conta na Koku.
environmentstringAmbiente: production (sandbox está reservado para o ambiente de testes, em preparação).
Valores: sandbox, production
requested_centsstring (centavos)Valor pedido, em centavos. É o que saiu do saldo disponível.
fee_centsstring (centavos)Taxa de saque descontada do valor pedido, em centavos.
amount_centsstring (centavos)Valor enviado à conta de destino (pedido − taxa), em centavos.
currencystringMoeda (BRL).
Valores: BRL
beneficiary_account_idstring (uuid)Conta de destino do saque.
destinationobjetoDados da conta de destino no momento do pedido (mudar o cadastro depois não altera o saque).
destination.holder_namestringNome do titular da conta de destino.
destination.holder_document_maskedstringCNPJ do titular, mascarado.
destination.pix_key_maskedstring ou nullChave Pix de destino, mascarada; null quando a conta não tem chave Pix cadastrada.
destination.bank_ispbstring ou nullCódigo ISPB do banco de destino; null quando a conta não tem dados bancários cadastrados.
approval_statusstringAnálise da Koku: pending (aguardando), approved ou rejected. Um saque que você cancelou antes da análise continua pending aqui: use execution_status = "cancelled" para saber que ele foi encerrado.
approval_modestring ou nullComo foi decidido: manual (uma pessoa da Koku) ou automatic. null enquanto pendente.
approval_reasonstring ou nullObservação da Koku na decisão (por exemplo, o motivo da recusa). null enquanto pendente.
approval_decided_atstring (data e hora) ou nullMomento da decisão. null enquanto pendente.
execution_statusstringSituação da transferência: reserved (valor reservado, aguardando a análise), queued (aprovado, aguardando a transferência da Koku), submitted, processing, unknown, paid, failed ou cancelled (recusado ou cancelado: o valor voltou ao disponível).
scheduled_forstring (data e hora) ou nullQuando o envio está agendado, se houver agendamento. null nos saques pagos por transferência da Koku.
submitted_atstring (data e hora) ou nullMomento em que o envio automático foi encaminhado, quando houver. null nos saques pagos por transferência da Koku.
confirmed_atstring (data e hora) ou nullMomento em que o saque foi pago.
end_to_end_idstring ou nullIdentificador fim a fim do Pix, quando o envio é automático. Nos saques pagos por transferência da Koku, use transfer_reference.
failure_reasonstring ou nullPor que o saque foi encerrado sem pagamento: o motivo que você informou ao cancelar (ou um texto padrão), o motivo da recusa da Koku ou, no envio automático, um texto fixo da Koku. null enquanto o saque segue em andamento ou foi pago.
awaiting_second_approvalbooleanotrue quando o valor exige uma segunda aprovação na Koku e a primeira já foi dada.
waiting_reasonstring ou nullSaque aprovado e ainda não pago: por que está esperando. awaiting_manual_transfer (a Koku vai fazer a transferência), in_review (transferência em análise), outside_window, daily_limit_reached ou monthly_limit_reached. null nos demais estados.
next_attempt_atstring (data e hora) ou nullQuando o saque em espera será reavaliado, quando houver previsão.
execution_channelstringComo o saque é pago: manual_transfer (transferência feita pela Koku) ou partner (envio automático).
transfer_referencestring ou nullSaque pago por transferência da Koku: identificador da transferência (por exemplo, o fim a fim do Pix). A mesma referência aparece no extrato em payout.paid.
created_atstring (data e hora)Momento do pedido.
Erros
| Status | Código | Quando |
|---|---|---|
| 401 | unauthorized | Chave ausente, inválida, revogada ou expirada. |
| 403 | forbidden | A chave não tem o escopo exigido (details.reason = "missing_scope"). |
| 403 | forbidden | A conta de destino ainda não foi verificada pela Koku (details.reason = "beneficiary_not_verified") ou a sua conta não está ativa para saques (details.reason = "gateway_not_active"). |
| 404 | not_found | beneficiary_account_id não é uma conta de destino da sua empresa. |
| 409 | idempotency_conflict | A mesma Idempotency-Key foi usada com um corpo diferente. |
| 409 | insufficient_funds | O saldo disponível não cobre o valor pedido. Nada é reservado. |
| 409 | conflict | A conta ainda não tem tarifa contratada vigente (details.reason = "no_pricing_policy"); fale com a Koku. |
| 422 | validation_error | Valor inválido, menor ou igual à taxa de saque (details.reason = "amount_does_not_cover_fee"), acima do limite por saque, diário ou mensal (details.reason = "payout_limit_per_payout", "payout_limit_daily" ou "payout_limit_monthly"; no limite por saque, também details.limit_cents e details.requested_cents), ou Idempotency-Key ausente. |
| 429 | rate_limited | Limite de requisições excedido. Aguarde o tempo de Retry-After. |
| 500 | internal_error | Falha inesperada. Repita com a mesma Idempotency-Key; persistindo, envie o correlation_id à Koku (veja Suporte). |
Formato do corpo de erro em Erros.