Autenticação
Gere suas credenciais no painel em Desenvolvedores > API Keys. Você receberá duas chaves:
| Chave | Formato | Uso | Permissões |
|---|---|---|---|
| Secret Key | sk_live_... |
Apenas no backend | Acesso total: criar, consultar, listar, configurar splits |
| Public Key | pk_live_... |
Frontend (browser) | Somente leitura: consultar e listar transações |
Envie a chave no header x-api-key em todas as requisições:
# Backend (Secret Key - acesso total)
curl -H "x-api-key: sk_live_sua_chave_secreta" \
https://api.owynd.com/api/v1/api-gateway/v1/transactions
# Frontend (Public Key - somente consulta)
curl -H "x-api-key: pk_live_sua_chave_publica" \
https://api.owynd.com/api/v1/api-gateway/v1/transactions/uuid
Erros e HTTP Codes
| Code | Significado | Quando ocorre |
|---|---|---|
| 200 | Sucesso | Requisição processada com sucesso |
| 400 | Bad Request | Dados inválidos ou campos obrigatórios ausentes |
| 401 | Unauthorized | API Key inválida, expirada ou ausente |
| 404 | Not Found | Transação ou recurso não encontrado |
| 429 | Rate Limited | Limite de 5 requisições/segundo excedido |
| 500 | Server Error | Erro interno (contate o suporte) |
Formato de Erro
{
"success": false,
"error": {
"message": "Valor mínimo: R$ 5,00 (500 centavos)",
"statusCode": 400
}
}
Status das Transações
| Status | Descrição |
|---|---|
| pending | Aguardando pagamento PIX (QR Code gerado) |
| processing | Pagamento em processamento pelo banco |
| paid | Pagamento confirmado — produto pode ser liberado |
| failed | Falha no pagamento |
| expired | QR Code expirou (30 minutos) |
| refunded | Valor devolvido ao cliente |
Criar Transação PIX
Cria uma cobrança PIX. Retorna o QR Code para o cliente pagar.
500 centavos). O mínimo é definido nas configurações da plataforma e esta página mostra sempre o valor atual; abaixo dele a API responde 400 com o valor mínimo na mensagem.
Headers
| Header | Tipo | Descrição | |
|---|---|---|---|
x-api-key |
string | obrigatório | Sua Secret Key (sk_live_...) |
x-idempotency-key |
string | opcional | Chave única para evitar cobranças duplicatas |
Body (JSON)
| Campo | Tipo | Descrição | |
|---|---|---|---|
amount |
integer | obrigatório | Valor em centavos. Ex: R$ 100,00 = 10000. Mínimo: 500 (R$ 5,00), definido pela plataforma. |
paymentMethod |
string | obrigatório | Método de pagamento: "pix" |
customer |
object | obrigatório | Dados do cliente (veja abaixo) |
customer.name |
string | obrigatório | Nome completo do cliente |
customer.email |
string | opcional | E-mail do cliente |
customer.phone |
string | opcional | Telefone com DDD |
customer.document |
object | opcional | { "type": "cpf", "number": "12345678900" } |
items |
array | opcional | [{ "title": "Produto", "unitPrice": 10000, "quantity": 1 }] |
split |
array | opcional novo | Split inline: [{ "email": "parceiro@email.com", "percentage": "10" }] |
postbackUrl |
string | opcional | URL HTTPS para webhook de confirmação |
externalId |
string | opcional | Seu ID interno para referência |
description |
string | opcional | Descrição da cobrança |
tracking |
object | opcional | UTMs do clique para atribuição de campanha na UTMify: { "utm_source", "utm_campaign", "utm_medium", "utm_content", "utm_term", "src", "sck" }. Se omitido, a venda é enviada à UTMify sem origem. |
Exemplo
curl -X POST https://api.owynd.com/api/v1/api-gateway/v1/transactions \
-H "Content-Type: application/json" \
-H "x-api-key: sk_live_sua_chave_secreta" \
-d '{
"paymentMethod": "pix",
"amount": 10000,
"customer": {
"name": "João Silva",
"email": "joao@email.com",
"phone": "11999999999",
"document": { "type": "cpf", "number": "12345678900" }
},
"items": [
{ "title": "Assinatura Premium", "unitPrice": 10000, "quantity": 1 }
],
"postbackUrl": "https://meusite.com/webhook/owynd",
"externalId": "pedido-123",
"tracking": {
"utm_source": "facebook",
"utm_campaign": "campanha-verao",
"utm_medium": "cpc",
"utm_content": "criativo-a"
}
}'
Resposta (200)
{
"success": true,
"data": {
"id": "uuid-da-transacao",
"status": "pending",
"amount": 10000,
"paymentMethod": "pix",
"customer": {
"name": "João Silva",
"email": "joao@email.com"
},
"pixQrCode": "00020126580014br.gov.bcb.pix...",
"pixQrCodeImage": "https://api.owynd.com/qrcode/xxx.png",
"expiresAt": "2026-01-15T11:00:00.000Z",
"createdAt": "2026-01-15T10:30:00.000Z"
},
"meta": {
"timestamp": "2026-01-15T10:30:00.000Z",
"version": "v1"
}
}
Consultar Transação
Consulta status e dados de uma transação. Aceita Secret Key ou Public Key.
curl https://api.owynd.com/api/v1/api-gateway/v1/transactions/uuid \
-H "x-api-key: sk_live_sua_chave_secreta"
Resposta
{
"success": true,
"data": {
"id": "uuid-da-transacao",
"externalId": "pedido-123",
"status": "paid",
"amount": 10000,
"paymentMethod": "pix",
"customerName": "João Silva",
"customerEmail": "joao@email.com",
"expiresAt": "2026-01-15T11:00:00.000Z",
"createdAt": "2026-01-15T10:30:00.000Z"
}
}
Listar Transações
Lista suas transações com paginação. Aceita Secret Key ou Public Key.
| Query Param | Tipo | Padrão | Descrição |
|---|---|---|---|
page | integer | 1 | Número da página |
limit | integer | 20 | Itens por página (máx: 100) |
Saques (Withdrawals) novo
A API de saques permite que sellers solicitem transferências PIX diretamente via API, sem precisar acessar o painel. Por padrão, os saques são criados como PENDING e processados após aprovação manual do administrador. Se o admin ativar a auto-aprovação de saque via API para a sua conta, o saque é processado e enviado na hora (veja abaixo).
1. Saque via API habilitado — precisa ser ativado pelo admin em Usuários > (seu usuário) > Ações > Saque via API
2. Destino do saque — configurar uma conta bancária cadastrada em Financeiro > Conta Bancária, OU enviar uma chave PIX externa diretamente na requisição (
pixKey, pixKeyType, holderName, holderDocument).3. CPF/CNPJ do titular — obrigatório em todo saque. As adquirentes validam o documento contra o dono da chave PIX. No modo PIX externo, envie
holderDocument. No modo conta bancária, cadastre o CPF/CNPJ no seu perfil (ou na conta bancária) — sem um documento válido a requisição é recusada com 400.4. IP na whitelist — o IP que faz a requisição deve estar cadastrado em Desenvolvedores > IPs Autorizados
Modo padrão — envie apenas
amount; o saque é direcionado para a conta bancária cadastrada do seller. O CPF/CNPJ do titular é obtido do cadastro (conta bancária ou perfil) e precisa estar preenchido e válido.Modo PIX externo — envie
amount + pixKey + pixKeyType + holderName + holderDocument; o saque é direcionado para a chave PIX informada (independente da conta bancária cadastrada). Funciona com todas as adquirentes configuradas na plataforma.
Quando o admin ativa Auto-aprovar saque para a sua conta (em Usuários > (seu usuário) > Ações > ↳ Auto-aprovar saque, logo abaixo de Saque via API), cada saque criado via
POST /v1/withdrawals é processado e enviado imediatamente, sem passar por aprovação manual — o retorno já vem com status: "PAID" ou "PROCESSING" (e o campo autoApproved: true). Requisitos: saque via API habilitado, senha de saque configurada na plataforma e CPF/CNPJ válido do titular. Se algum requisito faltar, o saque cai no fluxo normal e fica PENDING para aprovação manual. Sem esse recurso ativo, todo saque continua PENDING.
O campo
amount é o valor bruto do saque: é o que sai do seu saldo. A taxa de saque sai de dentro dele, e o que cai no PIX de destino é o netAmount (amount − fee). Exemplo: se você solicitar R$ 50,00 e a taxa for R$ 2,00, serão debitados R$ 50,00 do saldo e você receberá R$ 48,00. Se a taxa for igual ou maior que o valor, a resposta é 400 com a taxa e o menor valor aceito.
Status dos Saques
| Status | Descrição |
|---|---|
| PENDING | Aguardando aprovação do administrador |
| PROCESSING | Enviado à adquirente, aguardando confirmação (aparece na auto-aprovação) |
| PAID | Saque aprovado e PIX enviado para sua conta |
| REJECTED | Saque reprovado pelo admin (ver campo rejectionReason) |
| FAILED | Recusado pela adquirente — o valor é devolvido ao saldo automaticamente |
| UNDER_REVIEW | Envio sem confirmação (timeout) — em conferência; sem reenvio nem estorno até resolver |
Criar Saque
Solicita um saque. O valor de amount (bruto, com a taxa dentro) é debitado imediatamente do saldo disponível. O saque fica como PENDING até aprovação manual pelo admin (ou é processado na hora, com a auto-aprovação descrita acima).
Headers
| Header | Tipo | Descrição | |
|---|---|---|---|
x-api-key |
string | obrigatório | Sua Secret Key (sk_live_...). Public Key não é aceita aqui. |
Content-Type |
string | obrigatório | application/json |
Body (JSON)
pixKey), envie no campo holderDocument abaixo. No modo conta bancária (só amount), o documento não vai no body mas precisa estar cadastrado e válido no seu perfil ou na conta bancária — sem ele o saque é recusado com 400. Os badges condicional abaixo se referem ao que vai no corpo da requisição, não à obrigatoriedade do documento em si.
| Campo | Tipo | Descrição | |
|---|---|---|---|
amount |
integer | obrigatório | Valor bruto do saque em centavos, debitado do saldo (a taxa sai de dentro; o que cai é o netAmount). Ex: R$ 50,00 = 5000. Mínimo da API: 100 (R$ 1,00). O mínimo de saque da sua conta pode ser maior ou menor que o padrão da plataforma; abaixo dele a resposta é 400 com o valor. O máximo é definido pela plataforma; acima dele a resposta também é 400 com o valor. |
pixKey |
string | opcional | Chave PIX de destino. Quando presente, ativa o modo PIX externo e os 3 campos abaixo passam a ser obrigatórios. Sem este campo, o saque vai para a conta bancária cadastrada do seller. |
pixKeyType |
enum | condicional | Obrigatório quando pixKey é enviado. Valores: CPF · CNPJ · EMAIL · PHONE · RANDOM |
holderName |
string | condicional | Nome completo do titular da chave PIX. Obrigatório quando pixKey é enviado. Apenas letras, espaços e pontuação simples (. , - '). Mín. 3, máx. 120 caracteres. |
holderDocument |
string | condicional | CPF (11 dígitos) ou CNPJ (14 dígitos) do titular, somente números. Obrigatório quando pixKey é enviado. No modo conta bancária (sem pixKey) o documento não vai no body, mas precisa estar cadastrado e válido no seu perfil ou na conta bancária — o saque é recusado se não houver. |
postbackUrl |
string | opcional | URL HTTPS que recebe o webhook deste saque (withdrawal.paid / withdrawal.rejected). Se ausente, o webhook vai para os endpoints configurados em Desenvolvedores > Webhooks que escutam esses eventos. |
externalReference |
string | opcional | Chave de idempotência (recomendado; pode também ser enviada no header x-idempotency-key). 6–64 caracteres: letras, números, hífen, underscore. Única por conta. Retry com a mesma chave retorna o MESMO saque (campo idempotentReplay: true na resposta) em vez de criar — e debitar — outro. Use sempre que sua integração tiver retry automático/timeout. |
Validação de pixKey por tipo
| pixKeyType | Formato exigido | Exemplo |
|---|---|---|
CPF | Exatamente 11 dígitos. Validado com algoritmo de dígitos verificadores. | "12345678909" |
CNPJ | Exatamente 14 dígitos. Validado com algoritmo de dígitos verificadores. | "12345678000190" |
EMAIL | E-mail válido, máx. 100 caracteres. Convertido para minúsculas. | "joao@email.com" |
PHONE | 10 a 13 dígitos. Números BR sem código de país recebem prefixo +55 automaticamente. | "+5511999998888" |
RANDOM | UUID v4 — 32 hex sem hífens, ou 36 chars no formato 8-4-4-4-12. | "550e8400-e29b-41d4-a716-446655440000" |
Exemplo 1 — Saque para conta bancária cadastrada
curl -X POST https://api.owynd.com/api/v1/api-gateway/v1/withdrawals \
-H "Content-Type: application/json" \
-H "x-api-key: sk_live_sua_chave_secreta" \
-d '{ "amount": 5000 }'
Exemplo 2 — Saque para chave PIX externa
curl -X POST https://api.owynd.com/api/v1/api-gateway/v1/withdrawals \
-H "Content-Type: application/json" \
-H "x-api-key: sk_live_sua_chave_secreta" \
-d '{
"amount": 5000,
"pixKey": "joao@email.com",
"pixKeyType": "EMAIL",
"holderName": "João da Silva",
"holderDocument": "12345678909"
}'
Resposta (200) — Modo padrão (conta bancária)
{
"success": true,
"data": {
"id": "uuid-do-saque",
"amount": 50.00,
"fee": 2.00,
"netAmount": 48.00,
"status": "PENDING",
"destination": "BANK_ACCOUNT",
"pixKey": null,
"pixKeyType": null,
"holderName": null,
"holderDocument": null,
"createdAt": "2026-05-04T12:00:00.000Z",
"updatedAt": "2026-05-04T12:00:00.000Z",
"paidAt": null,
"rejectionReason": null,
"autoApproved": false
}
}
/* amount = total debitado do saldo (bruto solicitado)
fee = taxa de saque cobrada (sai de dentro de amount)
netAmount = valor líquido que será creditado no PIX (amount − fee)
autoApproved = true quando a auto-aprovação processou o saque na hora (status vem "PAID"/"PROCESSING") */
Resposta (200) — Modo PIX externo
{
"success": true,
"data": {
"id": "uuid-do-saque",
"amount": 50.00,
"fee": 2.00,
"netAmount": 48.00,
"status": "PENDING",
"destination": "EXTERNAL_PIX",
"pixKey": "joao@email.com",
"pixKeyType": "EMAIL",
"holderName": "João da Silva",
"holderDocument": "12345678909",
"createdAt": "2026-05-04T12:00:00.000Z",
"updatedAt": "2026-05-04T12:00:00.000Z",
"paidAt": null,
"rejectionReason": null,
"autoApproved": false
}
}
"status": "PAID" (ou "PROCESSING" enquanto a adquirente confirma) e "autoApproved": true, com paidAt preenchido. Nenhuma ação manual é necessária. Se a adquirente recusar, o status volta "FAILED" e o valor é devolvido ao saldo automaticamente.
401 Unauthorized. Você pode adicionar até 10 IPs por conta.
pixKey, holderName e holderDocument são validados contra:
- caracteres de controle (newline, null byte, tab) — bloqueia log forging;
- caracteres invisíveis (zero-width, RTL/LTR override, BOM) — bloqueia homoglyph attacks;
- tags HTML (
<,>) e padrões script-like (javascript:,vbscript:,data:,<script>,on*=); - backticks e template literals (
`,${}); - tamanhos máximos:
pixKey140,holderName120,holderDocument18.
400 Bad Request com mensagem específica.
Erros comuns
| HTTP | Mensagem | Causa |
|---|---|---|
| 400 | É necessário um CPF/CNPJ válido do titular para saque via API... | Modo conta bancária sem CPF/CNPJ válido no perfil nem na conta bancária. Cadastre o documento ou use o modo PIX externo com holderDocument. |
| 400 | Para saque em chave PIX externa, os campos são obrigatórios: pixKeyType, holderName... | Você enviou pixKey mas faltou algum dos demais campos do holder. |
| 400 | pixKey do tipo CPF deve conter exatamente 11 dígitos | Formato da chave PIX não bate com o pixKeyType declarado. |
| 400 | CPF/CNPJ informado em holderDocument é inválido | Documento falhou na validação de dígitos verificadores. |
| 400 | Nome do titular inválido | O holderName contém caracteres fora da whitelist (números, símbolos, etc.). |
| 400 | Campo X contém caracteres de controle não permitidos | Algum campo trouxe newline, null byte ou outro caractere de controle. |
| 400 | Saldo insuficiente | Saldo disponível menor que amount. |
| 401 | IP não autorizado para esta conta | Adicione o IP em Desenvolvedores > IPs Autorizados. |
| 403 | Saque via API não está habilitado | Pedir ao admin para habilitar em Usuários > (seu usuário) > Ações > Saque via API. |
Listar Saques
Lista todos os saques da conta com paginação. Aceita Secret Key ou Public Key.
| Query Param | Tipo | Padrão | Descrição |
|---|---|---|---|
page | integer | 1 | Número da página |
limit | integer | 20 | Itens por página (máx: 100) |
curl "https://api.owynd.com/api/v1/api-gateway/v1/withdrawals?page=1&limit=20" \
-H "x-api-key: sk_live_sua_chave_secreta"
Resposta (200)
{
"success": true,
"data": [
{
"id": "uuid-do-saque",
"amount": 52.00,
"fee": 2.00,
"netAmount": 50.00,
"status": "PENDING",
"createdAt": "2026-04-13T12:00:00.000Z",
"paidAt": null,
"rejectionReason": null
}
],
"meta": {
"total": 5,
"page": 1,
"limit": 20
}
}
Consultar Saque
Consulta detalhes de um saque específico. Aceita Secret Key ou Public Key.
curl "https://api.owynd.com/api/v1/api-gateway/v1/withdrawals/uuid-do-saque" \
-H "x-api-key: sk_live_sua_chave_secreta"
Resposta (200)
{
"success": true,
"data": {
"id": "uuid-do-saque",
"amount": 52.00,
"fee": 2.00,
"netAmount": 50.00,
"status": "PAID",
"createdAt": "2026-04-13T12:00:00.000Z",
"updatedAt": "2026-04-13T14:30:00.000Z",
"paidAt": "2026-04-13T14:30:00.000Z",
"rejectionReason": null
}
}
Split de Pagamento novo
O Split de Pagamento permite dividir automaticamente o valor de cada venda com parceiros, afiliados ou sócios. Ao criar uma transação, envie o campo split com os destinatários e porcentagens. Quando o pagamento é confirmado, os valores são creditados automaticamente.
1. Ao criar a transação, envie o campo
split com e-mail e porcentagem de cada destinatário2. O cliente paga normalmente via PIX
3. Após a taxa da plataforma, o valor líquido é dividido automaticamente
4. Parceiro recebe sua porcentagem e você recebe o restante — tudo automático
Split na Transação
Envie o campo split ao criar uma transação para dividir o valor automaticamente:
Exemplo com Split Inline
curl -X POST https://api.owynd.com/api/v1/api-gateway/v1/transactions \
-H "Content-Type: application/json" \
-H "x-api-key: sk_live_sua_chave_secreta" \
-d '{
"paymentMethod": "pix",
"amount": 10000,
"customer": {
"name": "João Silva",
"email": "joao@email.com"
},
"split": [
{ "email": "parceiro@email.com", "percentage": "10" },
{ "email": "afiliado@email.com", "percentage": "5" }
],
"postbackUrl": "https://meusite.com/webhook",
"externalId": "pedido-456"
}'
Campos do Split
| Campo | Tipo | Descrição | |
|---|---|---|---|
split[].email |
string | obrigatório | E-mail do destinatário (deve ter conta na plataforma) |
split[].percentage |
string | obrigatório | Porcentagem do valor líquido. Ex: "10" = 10% |
Exemplo de divisão:
Venda: R$ 100,00
Taxa plataforma (6%): - R$ 6,00
Valor líquido: R$ 94,00
Split parceiro (10%): R$ 9,40 → creditado para parceiro@email.com
Split afiliado (5%): R$ 4,70 → creditado para afiliado@email.com
Você recebe (85%): R$ 79,90
Assinaturas
Cobrança recorrente no cartão de crédito ou no Pix Automático. Você cria um link de assinatura pela API e envia ao cliente; ele abre o checkout Owynd e assina. No cartão, informa o cartão, que nunca passa pelo seu servidor. No Pix Automático, paga o 1º ciclo com um QR Code e, no mesmo passo, autoriza os débitos seguintes no app do banco. A cada ciclo a cobrança é automática e você recebe um webhook.
403. Fale com o suporte para ativar.
Regras
- Escolha a forma em
paymentMethod:credit_card(padrão) oupix_automatico. O link vale só para a forma escolhida. - Valores em centavos. Mínimo:
500. Máximo:300000por ciclo. - Períodos:
weekly(só Pix Automático),monthly,quarterly,semiannual,annual. - A primeira cobrança acontece quando o cliente assina. Se for recusada, ou se o QR não for pago, o link continua válido para nova tentativa até expirar.
- Cartão: renovação recusada é tentada de novo pela operadora. Pix Automático: débito sem saldo é tentado de novo até 3 vezes em 7 dias. Esgotadas as tentativas, a assinatura é cancelada.
- No Pix Automático o cliente pode cancelar pelo app do banco: você recebe
subscription.canceledcomcancelReason: "pagador". - Cada ciclo pago entra no seu saldo como uma venda, com as taxas e os prazos da forma de pagamento.
- Use a Secret Key (
sk_...) em todas as rotas de assinatura. externalIdé idempotente: repetir a criação com os mesmos dados devolve o mesmo link.
Status do link
| Status | Descrição |
|---|---|
open | Aguardando o cliente assinar. |
expired | Passou do prazo, ou foi cancelado, sem assinatura. |
pending | Cliente assinou; primeira cobrança em análise. |
active | Assinatura ativa, cobrando a cada ciclo. |
canceled | Assinatura encerrada; não cobra mais. |
Cria um link de checkout para o cliente assinar. Envie o checkoutUrl ao cliente.
Body (JSON)
| Campo | Tipo | Descrição | |
|---|---|---|---|
amount | integer | obrigatório | Valor de cada ciclo em centavos. |
period | string | obrigatório | weekly (só pix_automatico), monthly, quarterly, semiannual ou annual. |
name | string | obrigatório | Nome do plano, de 2 a 64 caracteres. Aparece no checkout e no app do banco do cliente. |
paymentMethod | string | opcional | credit_card (padrão) ou pix_automatico. |
description | string | opcional | Descrição do plano. |
externalId | string | opcional | Seu ID, usado para idempotência. |
postbackUrl | string | opcional | URL http(s) que recebe os eventos subscription.*. |
returnUrl | string | opcional | Para onde o cliente volta depois de assinar. |
expiresInHours | integer | opcional | Validade do link, de 1 a 720. Padrão: 72. |
customer | object | opcional | Pré-preenche o checkout: { name, email, phone }. |
Exemplo
curl -X POST https://api.owynd.com/api/v1/api-gateway/v1/subscriptions \
-H "Content-Type: application/json" \
-H "x-api-key: sk_live_sua_chave_secreta" \
-d '{
"amount": 4990,
"period": "monthly",
"name": "Clube VIP",
"paymentMethod": "pix_automatico",
"externalId": "cliente-123",
"postbackUrl": "https://seu-site.com/webhooks/owynd",
"returnUrl": "https://seu-site.com/obrigado",
"customer": { "name": "João da Silva", "email": "joao@email.com" }
}'
Resposta (200)
{
"success": true,
"data": {
"id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
"status": "open",
"checkoutUrl": "https://checkout.owynd.com/pay/ass-3f9a1c2b7d4e?assinatura=7c9e6679-7425-40de-944b-e07fc1f90ae7",
"name": "Clube VIP",
"amount": 4990,
"period": "monthly",
"paymentMethod": "pix_automatico",
"externalId": "cliente-123",
"expiresAt": "2026-09-30T18:00:00.000Z",
"createdAt": "2026-09-27T18:00:00.000Z",
"subscription": null
}
}
Erros
| HTTP | Quando |
|---|---|
400 | Campo inválido (valor, período, URL...). |
401 | x-api-key ausente, inválida ou pública. |
403 | A forma de pagamento escolhida não está habilitada na conta. |
409 | externalId já usado com outro valor, período ou forma de pagamento. |
Modo direto (Pix Automático): com mode: "direct" a assinatura nasce na hora e a resposta traz o QR Code, sem link de checkout. Você mostra o QR ao seu cliente no seu app, site ou bot.
503. Use o modo link, descrito acima, que já funciona no Pix Automático.
Campos do modo direto
| Campo | Tipo | Descrição | |
|---|---|---|---|
mode | string | obrigatório | direct. Exige paymentMethod: "pix_automatico". |
customer.name | string | obrigatório | Nome completo do cliente, de 2 a 140 caracteres. |
customer.document | string | obrigatório | CPF ou CNPJ válido do cliente. |
customer.email | string | obrigatório | E-mail real do cliente. |
customer.address | object | obrigatório | Endereço completo do cliente: zipCode (8 dígitos), street, number, district, city, state (UF com 2 letras) e complement (opcional). |
expiresInMinutes | integer | opcional | Prazo do QR, de 5 a 60 minutos. Padrão: 60. É o prazo que informamos, não uma garantia de validade. |
Exemplo
curl -X POST https://api.owynd.com/api/v1/api-gateway/v1/subscriptions \
-H "Content-Type: application/json" \
-H "x-api-key: sk_live_sua_chave_secreta" \
-d '{
"mode": "direct",
"paymentMethod": "pix_automatico",
"amount": 4990,
"period": "monthly",
"name": "Clube VIP",
"externalId": "pedido-123",
"customer": {
"name": "João da Silva",
"document": "12345678909",
"email": "joao@email.com",
"address": {
"zipCode": "01310100", "street": "Avenida Paulista", "number": "1000",
"district": "Bela Vista", "city": "São Paulo", "state": "SP"
}
}
}'
Resposta: campos a mais
| Campo | Descrição |
|---|---|
data.status | pending até o QR ser pago, depois active. |
data.mode | direct. Nesse modo não há checkoutUrl. |
data.pix | { qrCode, qrCodeImage, expiresAt }: copia-e-cola, imagem PNG em data URL e prazo do QR. Vem null se você repetir a chamada e o QR já foi pago. |
data.firstAutomaticDebit | Data (AAAA-MM-DD) do 1º débito automático, depois do ciclo pago agora. |
O que você precisa fazer
- Aviso ao cliente (obrigatório): exiba, junto do QR, algo como "Ao pagar, você autoriza a cobrança automática de R$ X/<período>; pode cancelar no app do seu banco."
- Exiba só o QR mais recente. Um QR antigo pode continuar pagável depois que você gerou outro. Se ele for pago, o dinheiro entra e você recebe
subscription.paid, com o status da assinatura no corpo, que pode vircanceled. Concilie pelo seuexternalId. externalId: repetir a chamada com os mesmos dados devolve o mesmo QR enquanto ele vale. Se o QR venceu sem pagamento ou a tentativa falhou, o mesmoexternalIdgera uma tentativa nova. Com outro valor, período ou documento, responde409. Duas chamadas ao mesmo tempo resultam numa só assinatura, e a segunda responde409"em processamento".- Acompanhe o resultado pelo webhook ou consultando a assinatura, respeitando o limite de 10 consultas por segundo.
Erros do modo direto
| HTTP | Quando |
|---|---|
400 | Dado inválido ou faltando, como CPF, e-mail ou endereço. |
403 | Pix Automático não habilitado na conta. |
409 | Mesmo externalId com outros dados, ou chamada anterior ainda em processamento. |
429 | Limite de 5 criações por segundo por chave, ou teto de assinaturas diretas atingido. |
503 | Modo indisponível, ou não foi possível gerar o Pix Automático agora. Nenhuma assinatura fica criada para o cliente pagar. Tente de novo; quando houver prazo sugerido, ele vem no cabeçalho Retry-After, em segundos. |
Consulta uma assinatura. Aceita o id do link, recebido na criação, ou o id da assinatura, recebido no webhook.
{
"success": true,
"data": {
"id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
"status": "active",
"amount": 4990,
"period": "monthly",
"externalId": "cliente-123",
"subscription": {
"id": "b1f0c2d3-0000-4000-8000-000000000001",
"status": "active",
"amount": 4990,
"period": "monthly",
"paidCycles": 3,
"currentPeriodEnd": "2026-10-27T23:59:59.000Z",
"paymentMethod": "pix_automatico",
"card": null,
"customer": { "name": "João da Silva", "email": "joao@email.com" }
}
}
}
Lista os links criados pela API, do mais recente para o mais antigo. Parâmetros: page (padrão 1), limit (padrão 20, máximo 100) e externalId.
Assinatura ativa: para as próximas cobranças, sem estornar o que já foi pago, e dispara subscription.canceled. Link ainda aberto: invalida o link. Se a operadora recusar o cancelamento, a resposta é erro e a assinatura continua ativa; tente de novo.
No Pix Automático, um QR já emitido pode continuar pagável por um curto período, então esconda-o do seu cliente. Se ele for pago, o dinheiro entra e você recebe subscription.paid com o status canceled no corpo.
Webhook de assinatura
Enviado ao postbackUrl do link e aos webhooks cadastrados no painel que escutam o evento. Use estes eventos para liberar ou bloquear o acesso do seu cliente.
| Evento | Descrição |
|---|---|
subscription.paid | Ciclo cobrado, inclusive o primeiro. Traz data.cycle, data.renewal e data.orderId. |
subscription.payment_failed | Renovação recusada. Traz data.failureReason e data.willRetry (true = vai tentar de novo). |
subscription.canceled | Assinatura encerrada. Bloqueie o acesso ao fim de data.currentPeriodEnd. |
O corpo traz event e data, com os campos da assinatura mostrados na consulta, mais data.linkId e o seu data.externalId. data.cancelReason pode ser seller, inadimplencia, pagarme, admin ou pagador.
Infrações (MED) novo
Uma infração (MED, Mecanismo Especial de Devolução) é aberta quando o pagador contesta um PIX no banco dele. Nossa equipe faz a defesa por você, 24 horas por dia: você não precisa contestar nada. Pela API você acompanha as suas infrações no seu sistema, com as mesmas informações da tela MEDs do painel.
sk_live_.... Use sempre do seu servidor, nunca do navegador.
Status da infração
| status | statusTexto | O que significa |
|---|---|---|
em_analise | Em análise | MED aberto. Nossa equipe cuida da defesa. Se houver valor em valorBloqueado, ele fica preso no seu saldo até a decisão. |
defendida | Defendida | Defesa aceita: a venda continua sua e o valor bloqueado volta para o saldo. |
devolvida | Devolvido ao pagador | MED perdido: o valor foi devolvido ao pagador e saiu do seu saldo. |
encerrada | Encerrada | A infração foi cancelada ou encerrada sem devolução. |
Campos da infração
| Campo | Tipo | Descrição |
|---|---|---|
id | string | Id da infração na Owynd |
status / statusTexto | string | Status (tabela acima) e o texto que aparece no painel |
valor | number | Valor contestado, em reais (ex.: 49.90) |
valorBloqueado | number | Quanto desta infração está preso no seu saldo agora, em reais. 0 quando nada está retido ou a infração já foi decidida |
motivo / detalheMotivo | string | null | Motivo da contestação |
e2eId | string | null | End-to-end do PIX contestado. null enquanto ainda não foi informado |
venda.id | string | null | Id da venda na Owynd. Para venda feita pela API, é o mesmo id de /v1/transactions |
venda.origem | string | api, checkout, telegram, deposito ou manual |
venda.criadaEm / venda.pagaEm | ISO 8601 | null | Quando a venda foi criada e paga |
pagador | object | null | nome, email e documento (cada um pode ser null). null quando a venda não tem esses dados |
contestadaEm | ISO 8601 | Quando o pagador abriu a contestação |
defesa | object | null | texto e enviadaEm da defesa feita pela nossa equipe |
decisao | object | null | observacao e decididaEm, depois do desfecho |
taxaDefesa | object | null | valor e pagaEm da taxa de defesa, só depois de paga |
criadaEm / atualizadaEm | ISO 8601 | Registro da infração na Owynd |
Listar Infrações
Lista as infrações da sua conta, da contestação mais recente para a mais antiga. Só Secret Key.
| Query Param | Tipo | Padrão | Descrição |
|---|---|---|---|
status | string | todos | Um ou mais, separados por vírgula: em_analise, defendida, devolvida, encerrada |
origem | string | todas | Um ou mais, separados por vírgula: api, checkout, telegram, deposito, manual |
desde | data | — | Contestadas a partir de. AAAA-MM-DD (dia no horário de Brasília) ou data ISO 8601 |
ate | data | — | Contestadas até. AAAA-MM-DD inclui o dia inteiro |
page | integer | 1 | Número da página |
limit | integer | 20 | Itens por página (máx: 100) |
Um parâmetro inválido responde 400 com a explicação (ele nunca é ignorado em silêncio).
curl "https://api.owynd.com/api/v1/api-gateway/v1/infracoes?status=em_analise&desde=2026-11-01" \
-H "x-api-key: sk_live_sua_chave_secreta"
Resposta (200)
{
"success": true,
"data": [
{
"id": "b3f1c2a4-7d1e-4c55-9a3b-1f2e3d4c5b6a",
"status": "em_analise",
"statusTexto": "Em análise",
"valor": 49.90,
"valorBloqueado": 49.90,
"motivo": "Contestação do pagador (MED)",
"detalheMotivo": null,
"e2eId": "E1234567820261108123456789012345",
"venda": {
"id": "uuid-da-transacao",
"origem": "api",
"criadaEm": "2026-11-05T14:02:11.000Z",
"pagaEm": "2026-11-05T14:03:40.000Z"
},
"pagador": { "nome": "João Silva", "email": "joao@email.com", "documento": "123.456.789-00" },
"contestadaEm": "2026-11-07T09:15:00.000Z",
"defesa": { "texto": "Produto entregue conforme combinado.", "enviadaEm": "2026-11-07T09:16:02.000Z" },
"decisao": null,
"taxaDefesa": null,
"criadaEm": "2026-11-07T09:15:30.000Z",
"atualizadaEm": "2026-11-07T09:16:02.000Z"
}
],
"meta": { "page": 1, "limit": 20, "total": 1, "totalPages": 1 }
}
Consultar Infração
Uma infração da sua conta. Só Secret Key. Id que não existe (ou de outra conta) responde 404.
curl "https://api.owynd.com/api/v1/api-gateway/v1/infracoes/b3f1c2a4-7d1e-4c55-9a3b-1f2e3d4c5b6a" \
-H "x-api-key: sk_live_sua_chave_secreta"
Resposta (200) — infração defendida
{
"success": true,
"data": {
"id": "b3f1c2a4-7d1e-4c55-9a3b-1f2e3d4c5b6a",
"status": "defendida",
"statusTexto": "Defendida",
"valor": 49.90,
"valorBloqueado": 0,
"motivo": "Contestação do pagador (MED)",
"detalheMotivo": null,
"e2eId": "E1234567820261108123456789012345",
"venda": { "id": "uuid-da-transacao", "origem": "api", "criadaEm": "2026-11-05T14:02:11.000Z", "pagaEm": "2026-11-05T14:03:40.000Z" },
"pagador": { "nome": "João Silva", "email": "joao@email.com", "documento": "123.456.789-00" },
"contestadaEm": "2026-11-07T09:15:00.000Z",
"defesa": { "texto": "Produto entregue conforme combinado.", "enviadaEm": "2026-11-07T09:16:02.000Z" },
"decisao": { "observacao": null, "decididaEm": "2026-11-09T18:00:00.000Z" },
"taxaDefesa": { "valor": 2.00, "pagaEm": "2026-11-09T18:00:00.000Z" },
"criadaEm": "2026-11-07T09:15:30.000Z",
"atualizadaEm": "2026-11-09T18:00:00.000Z"
}
}
Webhook de Infração
Cadastre a URL em Desenvolvedores > Webhooks e marque os eventos de Infrações (MED) que quiser receber. A assinatura, o X-Webhook-Event-Id e as novas tentativas são os mesmos dos outros webhooks (veja Webhooks). O aviso sai em até 1 minuto depois da mudança.
| Evento | Quando |
|---|---|
infracao.aberta | Um MED novo chegou na sua conta |
infracao.defesa_enviada | Nossa equipe enviou a defesa (o status continua em_analise; o texto vem em data.defesa) |
infracao.saldo_retido | O valor do MED ficou bloqueado no seu saldo (data.valorBloqueado) |
infracao.saldo_liberado | O valor bloqueado voltou para o saldo e o MED continua em análise |
infracao.defendida | Defesa aceita: a venda continua sua |
infracao.devolvida | MED perdido: o valor foi devolvido ao pagador e saiu do saldo |
infracao.encerrada | Infração cancelada ou encerrada |
Quando várias coisas mudam juntas, os eventos chegam nesta ordem (ex.: infracao.aberta e logo depois infracao.saldo_retido). Em todo evento, data traz a infração inteira e atualizada, igual à consulta. Para saber o estado atual, use sempre data.status.
Exemplo — infracao.aberta
{
"event": "infracao.aberta",
"data": {
"id": "b3f1c2a4-7d1e-4c55-9a3b-1f2e3d4c5b6a",
"status": "em_analise",
"statusTexto": "Em análise",
"valor": 49.90,
"valorBloqueado": 0,
"motivo": "Contestação do pagador (MED)",
"detalheMotivo": null,
"e2eId": "E1234567820261108123456789012345",
"venda": { "id": "uuid-da-transacao", "origem": "api", "criadaEm": "2026-11-05T14:02:11.000Z", "pagaEm": "2026-11-05T14:03:40.000Z" },
"pagador": { "nome": "João Silva", "email": "joao@email.com", "documento": "123.456.789-00" },
"contestadaEm": "2026-11-07T09:15:00.000Z",
"defesa": null,
"decisao": null,
"taxaDefesa": null,
"criadaEm": "2026-11-07T09:15:30.000Z",
"atualizadaEm": "2026-11-07T09:15:30.000Z"
}
}
Exemplo — infracao.devolvida
{
"event": "infracao.devolvida",
"data": {
"id": "b3f1c2a4-7d1e-4c55-9a3b-1f2e3d4c5b6a",
"status": "devolvida",
"statusTexto": "Devolvido ao pagador",
"valor": 49.90,
"valorBloqueado": 0,
"decisao": { "observacao": null, "decididaEm": "2026-11-09T18:00:00.000Z" },
"...": "demais campos iguais à consulta"
}
}
Exemplo — tratando no seu servidor
app.post('/webhook/owynd', express.raw({ type: 'application/json' }), (req, res) => {
if (!assinaturaValida(req.body, req.get('X-Webhook-Signature'), 'whsec_seu_secret')) {
return res.status(401).end();
}
const { event, data } = JSON.parse(req.body.toString('utf8'));
if (event.startsWith('infracao.')) {
// Guarde pelo id; um mesmo X-Webhook-Event-Id pode chegar mais de uma vez.
salvarInfracao(data.id, data.status, data.valor, data.valorBloqueado);
}
res.status(200).json({ received: true });
});
Webhooks
Receba notificações em tempo real quando transações mudam de status. Configure via painel (Desenvolvedores > Webhooks) ou envie postbackUrl na transação.
Payload do Webhook
{
"event": "transaction.paid",
"data": {
"id": "uuid-da-transacao",
"externalId": "pedido-123",
"amount": 10000,
"status": "paid",
"paymentMethod": "pix",
"customerName": "João Silva",
"paidAt": "2026-01-15T10:35:00.000Z"
}
}
Eventos disponíveis
| Evento | Categoria | Descrição |
|---|---|---|
transaction.paid | PIX | Pagamento PIX confirmado |
transaction.created | PIX | Cobrança PIX criada |
withdrawal.paid | Saque | Saque aprovado e PIX enviado para sua conta |
withdrawal.rejected | Saque | Saque reprovado pelo administrador |
subscription.paid / .payment_failed / .canceled | Assinatura | Ver Webhook de Assinatura |
infracao.* | Infração (MED) | Aberta, defesa enviada, saldo retido/liberado, defendida, devolvida, encerrada. Ver Webhook de Infração |
Payload — withdrawal.paid / withdrawal.rejected
{
"event": "withdrawal.paid",
"data": {
"id": "uuid-do-saque",
"amount": 52.00,
"fee": 2.00,
"netAmount": 50.00,
"status": "PAID",
"paidAt": "2026-04-13T14:30:00.000Z",
"rejectionReason": null,
"createdAt": "2026-04-13T12:00:00.000Z",
"updatedAt": "2026-04-13T14:30:00.000Z"
}
}
/* Para withdrawal.rejected:
"event": "withdrawal.rejected",
"data.status": "REJECTED",
"data.paidAt": null,
"data.rejectionReason": "Dados bancários inválidos" */
Validação de Assinatura (HMAC-SHA256)
O corpo do webhook é { "event": "...", "data": { ... } }. Cada webhook cadastrado no painel tem um segredo (whsec_...). Todo envio leva os cabeçalhos:
| Cabeçalho | Descrição |
|---|---|
X-Webhook-Signature | sha256= + HMAC-SHA256 em hexadecimal do corpo inteiro, exatamente como chegou, com o segredo do webhook |
X-Webhook-Event-Id | Id único do envio. O mesmo evento pode chegar mais de uma vez: use este id para não processar em dobro |
Calcule a assinatura sobre os bytes recebidos, antes de converter o JSON: reconverter (JSON.stringify) pode mudar espaços e acentos e a conta deixa de bater. O envio para o postbackUrl de uma transação não tem segredo, então não leva assinatura: confirme consultando a transação pela API.
const crypto = require('crypto');
function assinaturaValida(corpoBruto, cabecalho, segredo) {
const esperado = 'sha256=' + crypto.createHmac('sha256', segredo).update(corpoBruto).digest('hex');
const a = Buffer.from(esperado);
const b = Buffer.from(String(cabecalho || ''));
return a.length === b.length && crypto.timingSafeEqual(a, b);
}
// Express.js — express.raw() guarda o corpo exatamente como chegou
app.post('/webhook/owynd', express.raw({ type: 'application/json' }), (req, res) => {
if (!assinaturaValida(req.body, req.get('X-Webhook-Signature'), 'whsec_seu_secret')) {
return res.status(401).json({ error: 'Invalid signature' });
}
const { event, data } = JSON.parse(req.body.toString('utf8'));
if (event === 'transaction.paid') {
// Pagamento confirmado! Liberar produto.
console.log(`Pago: ${data.id} - R$ ${(data.amount/100).toFixed(2)}`);
}
res.status(200).json({ received: true });
});
Exemplo Completo
Fluxo de integração ponta a ponta com Node.js + Express:
1. Criar cobrança PIX (com split)
const axios = require('axios');
const API_KEY = 'sk_live_sua_chave_secreta';
const BASE_URL = 'https://api.owynd.com/api/v1/api-gateway';
app.post('/criar-pagamento', async (req, res) => {
const { nome, email, valor } = req.body;
const { data } = await axios.post(`${BASE_URL}/v1/transactions`, {
paymentMethod: 'pix',
amount: Math.round(valor * 100),
customer: { name: nome, email },
items: [{ title: 'Meu Produto', unitPrice: Math.round(valor * 100), quantity: 1 }],
split: [
{ email: 'parceiro@email.com', percentage: '10' }
],
postbackUrl: 'https://meusite.com/webhook/owynd',
externalId: `pedido-${Date.now()}`,
}, {
headers: { 'x-api-key': API_KEY },
});
res.json({
transactionId: data.data.id,
pixCode: data.data.pixQrCode,
pixImage: data.data.pixQrCodeImage,
expiresAt: data.data.expiresAt,
});
});
2. Receber webhook de pagamento
app.post('/webhook/owynd', express.raw({ type: 'application/json' }), (req, res) => {
// Validar assinatura (recomendado) — assinaturaValida() está em "Webhooks"
if (!assinaturaValida(req.body, req.get('X-Webhook-Signature'), 'whsec_...')) {
return res.status(401).end();
}
const { event, data } = JSON.parse(req.body.toString('utf8'));
if (event === 'transaction.paid') {
console.log('Pagamento confirmado:', data.id);
console.log('Valor:', (data.amount / 100).toFixed(2));
console.log('Pedido:', data.externalId);
// Liberar acesso ao produto/serviço
liberarAcesso(data.externalId);
}
res.status(200).json({ received: true });
});
3. Exibir QR Code no frontend
<div id="pix-container">
<h2>Escaneie o QR Code para pagar</h2>
<img id="qr-image" src="" alt="QR Code PIX" />
<p>Ou copie o código PIX:</p>
<input id="pix-code" type="text" readonly />
<button onclick="navigator.clipboard.writeText(
document.getElementById('pix-code').value
)">Copiar</button>
</div>
<script>
async function checkPayment(transactionId) {
const res = await fetch(
`/api/check-payment/${transactionId}`
);
const data = await res.json();
if (data.status === 'paid') {
window.location.href = '/obrigado';
} else {
setTimeout(() => checkPayment(transactionId), 3000);
}
}
</script>
Owynd © 2026 · Voltar ao painel · Testar Transação