{"openapi":"3.0.3","info":{"title":"StarlyPay API","description":"API pública da StarlyPay, o gateway de pagamento. Gere cobranças PIX, gerencie seus webhooks e consulte o status dos pagamentos.\n\n**Autenticação:** rotas seller usam `Authorization: Bearer sk_live_…` (API key com escopos) **ou** cookie de sessão do painel. Rotas buyer anônimas (checkout hospedado) não aparecem neste spec.\n\n## Primeiros passos\n\nEste guia cobre o mínimo para a primeira chamada à API da StarlyPay: autenticação,\nbase URL e o formato das respostas.\n\n## Base URL\n\nTodas as chamadas usam a URL base da sua conta. Nos exemplos abaixo ela aparece como\no placeholder `${SERVER_URL}`. Substitua pelo host da sua conta no ambiente em que\nestiver integrando (teste ou produção). Nunca fixe um host no seu código: leia-o de\numa variável de ambiente.\n\n## Autenticação\n\nAs rotas seller aceitam dois modos de autenticação:\n\n- **Chave de API** no header `Authorization: Bearer sk_live_...` (produção) ou\n  `Authorization: Bearer sk_test_...` (teste). Cada chave tem escopos (por exemplo\n  `payments:write`, `payments:read`); a rota exige o escopo correspondente.\n- **Cookie de sessão** do painel, para chamadas feitas pela própria interface logada.\n\nO prefixo da chave define o ambiente: `sk_test_` opera em modo teste (sem cobrança\nreal), `sk_live_` opera em produção. Use sempre a chave do ambiente correto.\n\n## Envelope de resposta\n\nToda resposta segue o mesmo envelope. Em sucesso:\n\n```json\n{ \"success\": true, \"data\": { } }\n```\n\nEm erro:\n\n```json\n{ \"success\": false, \"error\": { \"code\": \"BAD_REQUEST\", \"message\": \"...\" } }\n```\n\nO campo `error.code` é estável (por exemplo `UNAUTHORIZED`, `NOT_FOUND`,\n`UNPROCESSABLE_ENTITY`, `TOO_MANY_REQUESTS`) e mapeia para o status HTTP. Trate\no `code`, não o texto de `message`.\n\n## Idempotência\n\nAs rotas que criam uma cobrança exigem o header `Idempotency-Key` (uma string única\npor tentativa, por exemplo um UUID). Um retry com a MESMA chave e o MESMO corpo não\ncobra duas vezes: você recebe de volta o mesmo resultado da primeira chamada. Gere\numa chave nova a cada nova cobrança.\n\n## Exemplo mínimo\n\n```bash\ncurl -X POST \"${SERVER_URL}/v1/checkout/pix-charge\" \\\n  -H \"Authorization: Bearer sk_test_sua_chave\" \\\n  -H \"Idempotency-Key: 3f1c...unico\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{ \"amountCents\": 5000, \"customerName\": \"Fulano de Tal\", \"customerEmail\": \"fulano@exemplo.com\", \"customerDocument\": \"00000000000\", \"customerPhone\": \"+5511999999999\" }'\n```\n\n\n## Cobrança PIX\n\nHá dois caminhos para gerar uma cobrança PIX, com semânticas diferentes. Escolher o\ncaminho certo importa principalmente para as suas métricas por oferta.\n\n## Caminho 1: vender uma oferta existente\n\n`POST ${SERVER_URL}/v1/checkout/pix`\n\nVende uma oferta da sua conta. O valor cobrado é o preço da oferta (definido no\npainel), não um valor enviado no corpo. O campo `offerId` deve ser o `publicId` real\nde uma oferta ativa da sua conta. A venda fica agrupada nessa oferta, então as\nmétricas por oferta ficam corretas.\n\n## Caminho 2: cobrar um valor definido na hora\n\n`POST ${SERVER_URL}/v1/checkout/pix-charge`\n\nGera uma cobrança com o valor definido na hora, pelo campo `amountCents` (em\ncentavos). Aqui o `offerId` é **opcional** e tem uma semântica que costuma enganar:\n\n- Se você informar um `offerId` que corresponde a uma oferta **ativa** da sua conta,\n  a venda é agrupada nessa oferta.\n- Se você **omitir** o `offerId`, ou informar uma string que **não corresponde** a uma\n  oferta ativa (por exemplo um identificador arbitrário como `\"manuscrito-sagrado\"`),\n  a cobrança é criada normalmente e ancorada na sua oferta avulsa canônica. Você\n  recebe HTTP 200, mas a venda **NÃO** é agrupada pela string informada.\n\nEm outras palavras: uma string livre em `offerId` não cria nem nomeia uma oferta.\nEla é silenciosamente ignorada para fins de agrupamento, e a venda cai na oferta\navulsa (\"Cobranças avulsas\") da sua conta.\n\n## Como obter métricas por oferta\n\nSe você quer que as vendas fiquem agrupadas e mensuráveis por oferta:\n\n1. Crie a oferta no seu painel.\n2. Copie o `offerId` real (o `publicId`) que o painel mostra.\n3. Use esse `offerId` real no caminho `/v1/checkout/pix` ou em `/v1/checkout/pix-charge`.\n\nNão existe uma forma pública de \"criar oferta\" só passando uma string nova no\n`offerId` da cobrança: a oferta se cria no painel, e a cobrança usa o `offerId` dela.\n\n## Campos principais\n\n- `amountCents` (só em `/pix-charge`): valor em centavos, inteiro.\n- `offerId`: `publicId` de uma oferta ativa (obrigatório em `/pix`, opcional em\n  `/pix-charge`).\n- `customerName`, `customerEmail`, `customerDocument`, `customerPhone`: dados do\n  comprador, validados e normalizados na borda. Dados inválidos retornam um erro\n  4xx claro, nunca um 500.\n- `description` (opcional em `/pix-charge`): descrição livre da cobrança.\n- `expiresInSeconds` (opcional): janela de expiração do PIX.\n\nA resposta de sucesso traz a instrução de pagamento (QR Code e copia-e-cola) e o\nidentificador da cobrança, usado depois para consultar o status.\n\n\n## Webhooks\n\nWebhooks avisam o seu sistema quando algo acontece com uma cobrança (por exemplo,\nquando ela é paga). Você registra um endpoint de recebimento e a StarlyPay envia um\nPOST para ele a cada evento.\n\n## Gerenciar endpoints (CRUD)\n\nTodas as rotas exigem autenticação seller (chave de API ou sessão do painel).\n\n- `GET ${SERVER_URL}/v1/webhooks/endpoints` : lista seus endpoints.\n- `POST ${SERVER_URL}/v1/webhooks/endpoints` : cria um endpoint.\n- `PATCH ${SERVER_URL}/v1/webhooks/endpoints/:id` : atualiza (URL, eventos,\n  descrição, habilitar/desabilitar).\n- `DELETE ${SERVER_URL}/v1/webhooks/endpoints/:id` : remove.\n- `GET ${SERVER_URL}/v1/webhooks/endpoints/:id/deliveries` : histórico de entregas.\n\nCorpo para criar:\n\n```json\n{\n  \"url\": \"https://SEU_DOMINIO/webhooks/starlypay\",\n  \"events\": [\"sale.paid\", \"sale.refused\"],\n  \"description\": \"Notificacoes da minha loja\"\n}\n```\n\nUm `events` vazio (`[]`) recebe todos os eventos. A resposta da criação inclui um\n`secret` (mostrado apenas nesse momento): guarde-o para validar as entregas.\n\n## Autenticidade das entregas\n\nCada entrega chega no seu endpoint com estes headers:\n\n- `X-Webhook-Signature: sha256=<hex>` : HMAC SHA-256 do corpo CRU da requisição,\n  usando o `secret` do endpoint como chave. Recompute o HMAC no seu lado e compare\n  em tempo constante para confirmar que a entrega é autêntica.\n- `X-Webhook-Event`: o tipo do evento (o mesmo que vem em `type` no corpo).\n\nComo reforço opcional, você pode registrar a `url` já com um `?token=...` na\nquerystring (um segredo escolhido por você) e recusar qualquer POST que não o traga.\nA verificação da assinatura continua sendo a checagem principal.\n\n## Formato do evento\n\nO corpo de todo evento tem esta forma:\n\n```json\n{\n  \"id\": \"01922...\",\n  \"type\": \"sale.paid\",\n  \"createdAt\": \"2026-07-05T12:00:00.000Z\",\n  \"data\": { }\n}\n```\n\nTipos de evento e o conteúdo de `data`:\n\n- `sale.paid` : venda paga. `data` traz `saleId`, `amountCents`, `currency`,\n  `status`, `paymentMethod` e `customer` (`name`, `email`, `phone`, `document`).\n- `sale.refused` : pagamento recusado. Mesmo formato de `data` de uma venda, com\n  `status` indicando a recusa.\n- `refund` : cobrança estornada. `data` traz `saleId`, `refundId`, `amountCents`,\n  `currency` e `status`.\n- `chargeback` : contestação. `data` traz `saleId`, `amountCents`, `currency` e\n  `status`.\n\nO `data` carrega apenas campos da venda voltados a você e ao seu comprador. Responda\ncom um status HTTP 2xx para confirmar o recebimento; entregas sem 2xx são\nreentregues com retentativas em backoff.\n\n\n## Status da cobrança\n\nDepois de gerar uma cobrança PIX, você acompanha o desfecho consultando o status\npor polling. Os webhooks (guia Webhooks) avisam de forma assíncrona; o polling é o\ncomplemento síncrono para telas que aguardam o pagamento.\n\n## Consulta\n\n`GET ${SERVER_URL}/v1/checkout/buyer/status/:invoiceId`\n\nO `:invoiceId` é o identificador da cobrança retornado na criação. Esta rota é\nenxuta de propósito: devolve apenas o status, sem valores nem dados sensíveis.\n\nResposta:\n\n```json\n{ \"success\": true, \"data\": { \"status\": \"pending\" } }\n```\n\n## Estados possíveis\n\n- `pending` : aguardando pagamento (o PIX ainda está dentro da janela de expiração).\n- `paid` : pago.\n- `expired` : a janela do PIX passou sem pagamento.\n- `refused` : o pagamento foi recusado.\n\n`paid`, `expired` e `refused` são desfechos finais: uma vez atingidos, não voltam\npara `pending`.\n\n## Polling recomendado\n\nConsulte a cada poucos segundos enquanto o status for `pending`, com um teto de\ntentativas (ou pare quando a janela do PIX expirar). Assim que o status virar `paid`,\n`expired` ou `refused`, pare de consultar e trate o desfecho. Para não depender só do\npolling, registre também um webhook `sale.paid`.\n\n\n## Tokens e metering\n\nA API de tokens serve para cobrar seus clientes por uso (unidades), separada do\nsaldo em dinheiro da sua conta. Voce cria um medidor, credita unidades para um\ncliente e debita a cada uso. Tudo por chamada de API, com sua chave `sk_`.\n\n## O que e um medidor\n\nUm medidor (meter) representa uma coisa que voce mede, identificada por uma\n`key` (por exemplo `api_calls`, `sms`, `mensagens`). Voce cria os medidores no\nseu painel ou pela API de medidores. Cada saldo pertence a um par\n(medidor, cliente).\n\nO cliente e identificado por `ref` (o id dele no seu sistema) ou por `email`.\nPrefira o `ref`: ele e estavel mesmo que o cliente troque de e-mail.\n\n## Os dois baldes: allowance e topup\n\nCada cliente tem, por medidor, dois baldes de saldo:\n\n- `allowance`: a cota do plano. E o que o cliente recebe no ciclo e costuma\n  resetar a cada renovacao.\n- `topup`: recarga avulsa. Nunca expira e fica somada por cima da cota.\n\nO consumo gasta o `allowance` primeiro e so recorre ao `topup` quando a cota\nacaba. O `total` de um medidor e a soma dos dois.\n\n## Consumir: `POST ${SERVER_URL}/v1/tokens/consume`\n\nDebita unidades do cliente. Escopo exigido na chave: `tokens:consume`.\n\n```json\n{\n  \"meter\": \"api_calls\",\n  \"amount\": 5,\n  \"customer\": { \"ref\": \"user_9812\" },\n  \"idempotencyKey\": \"req_2026-07-16_abc123\"\n}\n```\n\nResposta de sucesso:\n\n```json\n{\n  \"success\": true,\n  \"data\": {\n    \"consumed\": 5,\n    \"meter\": \"api_calls\",\n    \"customer\": \"user_9812\",\n    \"allowanceRemaining\": 995,\n    \"topupRemaining\": 0\n  }\n}\n```\n\n## Idempotencia: uma chave por unidade de consumo\n\nO campo `idempotencyKey` e obrigatorio no consume e no grant. A regra:\n\n- Gere uma chave NOVA para cada unidade de consumo (cada cobranca distinta).\n- Reuse a MESMA chave SOMENTE quando estiver repetindo a MESMA cobranca (um\n  retry apos timeout de rede, por exemplo).\n\nUm retry com a mesma chave devolve o mesmo resultado e NAO debita de novo. Assim\nvoce nunca cobra duas vezes um cliente so porque a resposta se perdeu no caminho.\nUse algo unico e reproduzivel por cobranca, como o id do pedido no seu sistema.\n\n## Quando vem o 402\n\nSaldo insuficiente e um bloqueio duro: nao existe overage. Se o cliente nao tem\nunidades suficientes, o consume retorna HTTP 402 com o code `INSUFFICIENT_TOKENS`\ne nao debita nada:\n\n```json\n{\n  \"success\": false,\n  \"error\": {\n    \"code\": \"INSUFFICIENT_TOKENS\",\n    \"message\": \"Saldo de tokens insuficiente para o consumo.\",\n    \"details\": { \"meter\": \"api_calls\", \"requested\": 5, \"available\": 2 }\n  }\n}\n```\n\nLeia `details.available` para saber quanto o cliente ainda tinha e decidir se\noferece uma recarga. Depois de creditar, repita o consume (com uma chave nova).\n\n## Consultar saldo: `GET ${SERVER_URL}/v1/tokens/balance`\n\nEscopo exigido: `tokens:read`. Identifique o cliente por `ref` ou `email` e,\nopcionalmente, filtre por `meter`.\n\n`GET ${SERVER_URL}/v1/tokens/balance?meter=api_calls&ref=user_9812`\n\n```json\n{\n  \"success\": true,\n  \"data\": [\n    {\n      \"meter\": \"api_calls\",\n      \"allowanceRemaining\": 995,\n      \"topupRemaining\": 1000,\n      \"total\": 1995\n    }\n  ]\n}\n```\n\n## Creditar recarga: `POST ${SERVER_URL}/v1/tokens/grant`\n\nEscopo exigido: `tokens:grant`. Credita unidades no balde `topup` (nunca expira),\nsem mexer na cota do plano. Tambem e idempotente.\n\n```json\n{\n  \"meter\": \"api_calls\",\n  \"amount\": 1000,\n  \"customer\": { \"ref\": \"user_9812\" },\n  \"idempotencyKey\": \"topup_2026-07-16_xyz789\",\n  \"reason\": \"Recarga avulsa comprada no plano Pro\"\n}\n```\n\nResposta de sucesso:\n\n```json\n{\n  \"success\": true,\n  \"data\": {\n    \"granted\": 1000,\n    \"meter\": \"api_calls\",\n    \"customer\": \"user_9812\",\n    \"allowanceRemaining\": 995,\n    \"topupRemaining\": 1000\n  }\n}\n```\n\nDados invalidos (por exemplo `amount` menor que 1, ou cliente sem `ref` nem\n`email`) retornam um erro 4xx claro, nunca um 500.\n","version":"1.0.0"},"servers":[{"url":"https://api.starlypay.com"}],"tags":[{"name":"Public","description":"Rotas públicas da API StarlyPay."}],"paths":{"/v1/billing/pix":{"post":{"tags":["Public"],"summary":"Criar cobrança PIX","responses":{"200":{"description":"Cobranca PIX criada.","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","enum":[true]},"data":{"type":"object","properties":{"invoiceId":{"type":"string"},"qrCode":{"type":"string","description":"Codigo PIX copia e cola."},"qrCodeUrl":{"type":"string","description":"URL da imagem do QR Code."},"expiresAt":{"type":"string","format":"date-time"},"amountCents":{"type":"integer"},"currency":{"type":"string"}},"required":["invoiceId","qrCode","qrCodeUrl","expiresAt","amountCents","currency"]}},"required":["success","data"]}}}},"400":{"description":"Requisicao invalida (por exemplo, plano invalido).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"422":{"description":"Dados do comprador invalidos.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/CustomerInput"},{"type":"object","properties":{"planId":{"type":"string"},"billingInterval":{"type":"string","enum":["monthly","yearly"]},"expiresInSeconds":{"type":"number"}},"required":["planId","billingInterval"]}]}},"application/x-www-form-urlencoded":{"schema":{"allOf":[{"$ref":"#/components/schemas/CustomerInput"},{"type":"object","properties":{"planId":{"type":"string"},"billingInterval":{"type":"string","enum":["monthly","yearly"]},"expiresInSeconds":{"type":"number"}},"required":["planId","billingInterval"]}]}},"multipart/form-data":{"schema":{"allOf":[{"$ref":"#/components/schemas/CustomerInput"},{"type":"object","properties":{"planId":{"type":"string"},"billingInterval":{"type":"string","enum":["monthly","yearly"]},"expiresInSeconds":{"type":"number"}},"required":["planId","billingInterval"]}]}}}},"operationId":"postV1BillingPix","security":[{"ApiKeyAuth":[]}]}},"/v1/checkout/pix":{"post":{"tags":["Public"],"summary":"Vender oferta via PIX","description":"Vende uma oferta existente da sua conta via PIX, cobrando o preço da oferta. Para acompanhar métricas por oferta, crie a oferta no seu painel e informe o `offerId` real dela.","parameters":[{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string"},"description":"Chave de idempotência da cobrança. Um retry com a mesma chave e o mesmo corpo nao cobra duas vezes."}],"responses":{"200":{"description":"Cobranca PIX criada.","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","enum":[true]},"data":{"type":"object","properties":{"invoiceId":{"type":"string"},"qrCode":{"type":"string","description":"Codigo PIX copia e cola."},"qrCodeUrl":{"type":"string","description":"URL da imagem do QR Code."},"expiresAt":{"type":"string","format":"date-time"},"amountCents":{"type":"integer"},"currency":{"type":"string"}},"required":["invoiceId","qrCode","qrCodeUrl","expiresAt","amountCents","currency"]}},"required":["success","data"]}}}},"400":{"description":"Requisicao invalida (por exemplo, header Idempotency-Key ausente).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"422":{"description":"Dados do comprador invalidos.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/CustomerInput"},{"type":"object","properties":{"offerId":{"minLength":1,"maxLength":128,"type":"string"},"couponCode":{"minLength":1,"maxLength":128,"type":"string"},"acceptedBumpPublicIds":{"type":"array","items":{"minLength":1,"maxLength":128,"type":"string"}},"anonymousId":{"minLength":1,"maxLength":128,"type":"string"},"attribution":{"$ref":"#/components/schemas/AttributionInfo"},"expiresInSeconds":{"type":"number"}},"required":["offerId"]}]}},"application/x-www-form-urlencoded":{"schema":{"allOf":[{"$ref":"#/components/schemas/CustomerInput"},{"type":"object","properties":{"offerId":{"minLength":1,"maxLength":128,"type":"string"},"couponCode":{"minLength":1,"maxLength":128,"type":"string"},"acceptedBumpPublicIds":{"type":"array","items":{"minLength":1,"maxLength":128,"type":"string"}},"anonymousId":{"minLength":1,"maxLength":128,"type":"string"},"attribution":{"$ref":"#/components/schemas/AttributionInfo"},"expiresInSeconds":{"type":"number"}},"required":["offerId"]}]}},"multipart/form-data":{"schema":{"allOf":[{"$ref":"#/components/schemas/CustomerInput"},{"type":"object","properties":{"offerId":{"minLength":1,"maxLength":128,"type":"string"},"couponCode":{"minLength":1,"maxLength":128,"type":"string"},"acceptedBumpPublicIds":{"type":"array","items":{"minLength":1,"maxLength":128,"type":"string"}},"anonymousId":{"minLength":1,"maxLength":128,"type":"string"},"attribution":{"$ref":"#/components/schemas/AttributionInfo"},"expiresInSeconds":{"type":"number"}},"required":["offerId"]}]}}}},"operationId":"postV1CheckoutPix","security":[{"ApiKeyAuth":[]}]}},"/v1/checkout/pix-charge":{"post":{"tags":["Public"],"summary":"Cobrar PIX com valor informado (venda)","description":"Gera uma cobrança PIX com o valor definido na hora pelo campo `amountCents`. O campo `offerId` é opcional: quando informado e correspondente a uma oferta ativa da sua conta, a venda é agrupada nessa oferta; quando ausente ou sem correspondência (por exemplo, um identificador arbitrário), a cobrança é criada normalmente e ancorada na sua oferta avulsa canônica, sem agrupar pelo valor informado. Para obter métricas por oferta, crie a oferta no seu painel e use o `offerId` real dela nesta rota ou em `/v1/checkout/pix`.","parameters":[{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string"},"description":"Chave de idempotência da cobrança. Um retry com a mesma chave e o mesmo corpo nao cobra duas vezes."}],"responses":{"200":{"description":"Cobranca PIX criada.","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","enum":[true]},"data":{"type":"object","properties":{"invoiceId":{"type":"string"},"qrCode":{"type":"string","description":"Codigo PIX copia e cola."},"qrCodeUrl":{"type":"string","description":"URL da imagem do QR Code."},"expiresAt":{"type":"string","format":"date-time"},"amountCents":{"type":"integer"},"currency":{"type":"string"}},"required":["invoiceId","qrCode","qrCodeUrl","expiresAt","amountCents","currency"]}},"required":["success","data"]}}}},"400":{"description":"Requisicao invalida (por exemplo, header Idempotency-Key ausente).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"422":{"description":"Dados do comprador invalidos.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/CustomerInput"},{"type":"object","properties":{"offerId":{"minLength":1,"maxLength":128,"type":"string"},"amountCents":{"minimum":500,"maximum":1000000,"anyOf":[{"format":"integer","default":0,"type":"string"},{"minimum":500,"maximum":1000000,"type":"integer"}]},"description":{"minLength":1,"maxLength":256,"type":"string"},"expiresInSeconds":{"minimum":300,"maximum":86400,"anyOf":[{"format":"integer","default":0,"type":"string"},{"minimum":300,"maximum":86400,"type":"integer"}]},"attribution":{"$ref":"#/components/schemas/AttributionInfo"}},"required":["amountCents"]}]}},"application/x-www-form-urlencoded":{"schema":{"allOf":[{"$ref":"#/components/schemas/CustomerInput"},{"type":"object","properties":{"offerId":{"minLength":1,"maxLength":128,"type":"string"},"amountCents":{"minimum":500,"maximum":1000000,"anyOf":[{"format":"integer","default":0,"type":"string"},{"minimum":500,"maximum":1000000,"type":"integer"}]},"description":{"minLength":1,"maxLength":256,"type":"string"},"expiresInSeconds":{"minimum":300,"maximum":86400,"anyOf":[{"format":"integer","default":0,"type":"string"},{"minimum":300,"maximum":86400,"type":"integer"}]},"attribution":{"$ref":"#/components/schemas/AttributionInfo"}},"required":["amountCents"]}]}},"multipart/form-data":{"schema":{"allOf":[{"$ref":"#/components/schemas/CustomerInput"},{"type":"object","properties":{"offerId":{"minLength":1,"maxLength":128,"type":"string"},"amountCents":{"minimum":500,"maximum":1000000,"anyOf":[{"format":"integer","default":0,"type":"string"},{"minimum":500,"maximum":1000000,"type":"integer"}]},"description":{"minLength":1,"maxLength":256,"type":"string"},"expiresInSeconds":{"minimum":300,"maximum":86400,"anyOf":[{"format":"integer","default":0,"type":"string"},{"minimum":300,"maximum":86400,"type":"integer"}]},"attribution":{"$ref":"#/components/schemas/AttributionInfo"}},"required":["amountCents"]}]}}}},"operationId":"postV1CheckoutPix-charge","security":[{"ApiKeyAuth":[]}]}},"/v1/checkout/buyer/status/{invoiceId}":{"get":{"tags":["Public"],"summary":"Status da cobrança (buyer, poll)","responses":{"200":{"description":"Status atual da cobranca.","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","enum":[true]},"data":{"type":"object","properties":{"status":{"type":"string","enum":["paid","pending","expired","refused"]}},"required":["status"]}},"required":["success","data"]}}}},"404":{"description":"Cobranca nao encontrada.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"parameters":[{"name":"invoiceId","in":"path","required":true,"schema":{"minLength":1,"type":"string"}}],"operationId":"getV1CheckoutBuyerStatusByInvoiceId","security":[{"ApiKeyAuth":[]}]}},"/v1/checkout/buyer/card-config/{offerPublicId}":{"get":{"tags":["Public"],"summary":"Config de tokenização de cartão por oferta (buyer)","responses":{"200":{"description":"Configuracao de tokenizacao por oferta.","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","enum":[true]},"data":{"type":"array","items":{"type":"object","properties":{"scheme":{"type":"string"},"publicKey":{"type":"string"}},"required":["scheme","publicKey"]}}},"required":["success","data"]}}}},"404":{"description":"Oferta nao encontrada.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"parameters":[{"name":"offerPublicId","in":"path","required":true,"schema":{"minLength":1,"type":"string"}}],"operationId":"getV1CheckoutBuyerCard-configByOfferPublicId","security":[{"ApiKeyAuth":[]}]}},"/v1/checkout/buyer/installments":{"post":{"tags":["Public"],"summary":"Cotar parcelas no cartão (buyer)","responses":{"200":{"description":"Opcoes de parcelamento cotadas pelo servidor.","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","enum":[true]},"data":{"type":"object","properties":{"options":{"type":"array","items":{"type":"object","properties":{"parcelas":{"type":"integer"},"totalCents":{"type":"integer"},"valorParcelaCents":{"type":"integer"}},"required":["parcelas","totalCents","valorParcelaCents"]}}},"required":["options"]}},"required":["success","data"]}}}},"400":{"description":"Requisicao invalida.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Oferta nao encontrada.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["offerId"],"properties":{"offerId":{"minLength":1,"type":"string"},"acceptedBumpPublicIds":{"type":"array","items":{"minLength":1,"type":"string"}},"couponCode":{"minLength":1,"type":"string"}},"additionalProperties":false}},"application/x-www-form-urlencoded":{"schema":{"type":"object","required":["offerId"],"properties":{"offerId":{"minLength":1,"type":"string"},"acceptedBumpPublicIds":{"type":"array","items":{"minLength":1,"type":"string"}},"couponCode":{"minLength":1,"type":"string"}},"additionalProperties":false}},"multipart/form-data":{"schema":{"type":"object","required":["offerId"],"properties":{"offerId":{"minLength":1,"type":"string"},"acceptedBumpPublicIds":{"type":"array","items":{"minLength":1,"type":"string"}},"couponCode":{"minLength":1,"type":"string"}},"additionalProperties":false}}}},"operationId":"postV1CheckoutBuyerInstallments","security":[{"ApiKeyAuth":[]}]}},"/v1/webhooks/endpoints/":{"get":{"tags":["Public"],"summary":"Listar endpoints de webhook","responses":{"200":{"description":"Endpoints de webhook do seller.","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","enum":[true]},"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"url":{"type":"string"},"events":{"type":"array","items":{"type":"string"}},"productIds":{"type":"array","items":{"type":"string"}},"enabled":{"type":"string"},"description":{"type":"string"},"createdAt":{"type":"string","format":"date-time"}},"required":["id","url","events","createdAt"]}}},"required":["success","data"]}}}},"401":{"description":"Nao autenticado.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"operationId":"getV1WebhooksEndpoints","security":[{"ApiKeyAuth":[]}]},"post":{"tags":["Public"],"summary":"Criar endpoint de webhook","responses":{"200":{"description":"Endpoint criado (com o segredo de assinatura).","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","enum":[true]},"data":{"type":"object","properties":{"id":{"type":"string"},"url":{"type":"string"},"events":{"type":"array","items":{"type":"string"}},"productIds":{"type":"array","items":{"type":"string"}},"enabled":{"type":"string"},"description":{"type":"string"},"createdAt":{"type":"string","format":"date-time"},"secret":{"type":"string"}},"required":["id","url","events","secret","createdAt"]}},"required":["success","data"]}}}},"422":{"description":"Dados do endpoint invalidos.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["url","events"],"properties":{"url":{"format":"uri","type":"string"},"events":{"type":"array","items":{"type":"string"}},"productIds":{"type":"array","items":{"type":"string"}},"description":{"type":"string"}}}},"application/x-www-form-urlencoded":{"schema":{"type":"object","required":["url","events"],"properties":{"url":{"format":"uri","type":"string"},"events":{"type":"array","items":{"type":"string"}},"productIds":{"type":"array","items":{"type":"string"}},"description":{"type":"string"}}}},"multipart/form-data":{"schema":{"type":"object","required":["url","events"],"properties":{"url":{"format":"uri","type":"string"},"events":{"type":"array","items":{"type":"string"}},"productIds":{"type":"array","items":{"type":"string"}},"description":{"type":"string"}}}}}},"operationId":"postV1WebhooksEndpoints","security":[{"ApiKeyAuth":[]}]}},"/v1/webhooks/endpoints/{id}":{"patch":{"tags":["Public"],"summary":"Atualizar endpoint de webhook","responses":{"200":{"description":"Endpoint atualizado.","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","enum":[true]},"data":{"type":"object","properties":{"id":{"type":"string"},"url":{"type":"string"},"events":{"type":"array","items":{"type":"string"}},"productIds":{"type":"array","items":{"type":"string"}},"enabled":{"type":"string"},"description":{"type":"string"},"createdAt":{"type":"string","format":"date-time"}},"required":["id","url","events","createdAt"]}},"required":["success","data"]}}}},"404":{"description":"Endpoint nao encontrado.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"422":{"description":"Dados do endpoint invalidos.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"enabled":{"type":"boolean"},"events":{"type":"array","items":{"type":"string"}},"productIds":{"type":"array","items":{"type":"string"}},"url":{"format":"uri","type":"string"},"description":{"type":"string"}}}},"application/x-www-form-urlencoded":{"schema":{"type":"object","properties":{"enabled":{"type":"boolean"},"events":{"type":"array","items":{"type":"string"}},"productIds":{"type":"array","items":{"type":"string"}},"url":{"format":"uri","type":"string"},"description":{"type":"string"}}}},"multipart/form-data":{"schema":{"type":"object","properties":{"enabled":{"type":"boolean"},"events":{"type":"array","items":{"type":"string"}},"productIds":{"type":"array","items":{"type":"string"}},"url":{"format":"uri","type":"string"},"description":{"type":"string"}}}}}},"operationId":"patchV1WebhooksEndpointsById","security":[{"ApiKeyAuth":[]}]},"delete":{"tags":["Public"],"summary":"Remover endpoint de webhook","responses":{"200":{"description":"Endpoint removido.","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","enum":[true]},"data":{"type":"object","properties":{"success":{"type":"boolean"}},"required":["success"]}},"required":["success","data"]}}}},"404":{"description":"Endpoint nao encontrado.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"operationId":"deleteV1WebhooksEndpointsById","security":[{"ApiKeyAuth":[]}]}},"/v1/webhooks/endpoints/{id}/deliveries":{"get":{"tags":["Public"],"summary":"Listar entregas de webhook","responses":{"200":{"description":"Entregas do endpoint.","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","enum":[true]},"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"eventType":{"type":"string"},"status":{"type":"string"},"responseStatus":{"type":"integer"},"attemptCount":{"type":"integer"},"deliveredAt":{"type":"string","format":"date-time"},"createdAt":{"type":"string","format":"date-time"}},"required":["id","eventType","status","attemptCount","createdAt"]}}},"required":["success","data"]}}}},"404":{"description":"Endpoint nao encontrado.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"operationId":"getV1WebhooksEndpointsByIdDeliveries","security":[{"ApiKeyAuth":[]}]}},"/v1/tokens/consume":{"post":{"tags":["Public"],"summary":"Consumir tokens de um cliente","description":"Debita unidades do saldo de um cliente em um medidor.\n\nO consumo gasta o balde de cota do plano (allowance) primeiro e só recorre a\nrecargas avulsas (topup) quando a cota acaba. Saldo insuficiente e bloqueio\nduro: a chamada retorna HTTP 402 com o code INSUFFICIENT_TOKENS e\ndetails.available, sem debitar nada.\n\nIdempotencia (obrigatoria): envie uma idempotencyKey nova por unidade de\nconsumo. Um retry com a MESMA chave devolve o mesmo resultado sem debitar de\nnovo, entao voce nunca cobra duas vezes por um timeout de rede.\n\nExemplo de corpo:\n```json\n{\n  \"meter\": \"api_calls\",\n  \"amount\": 5,\n  \"customer\": { \"ref\": \"user_9812\" },\n  \"idempotencyKey\": \"req_2026-07-16_abc123\"\n}\n```","responses":{"200":{"description":"Consumo debitado.","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","enum":[true]},"data":{"type":"object","properties":{"consumed":{"type":"integer","description":"Unidades debitadas nesta chamada."},"meter":{"type":"string","description":"Chave do medidor."},"customer":{"type":"string","description":"Identificador do cliente (o ref informado ou o e-mail normalizado)."},"allowanceRemaining":{"type":"integer","description":"Saldo restante da cota do plano (allowance)."},"topupRemaining":{"type":"integer","description":"Saldo restante de recarga avulsa (topup)."}},"required":["consumed","meter","customer","allowanceRemaining","topupRemaining"]}},"required":["success","data"]},"example":{"success":true,"data":{"consumed":5,"meter":"api_calls","customer":"user_9812","allowanceRemaining":995,"topupRemaining":0}}}}},"400":{"description":"Identificacao do cliente ausente (informe ref ou email).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"402":{"description":"Saldo de tokens insuficiente (bloqueio duro, sem overage).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"example":{"success":false,"error":{"code":"INSUFFICIENT_TOKENS","message":"Saldo de tokens insuficiente para o consumo.","details":{"meter":"api_calls","requested":5,"available":2}}}}}},"404":{"description":"Medidor nao encontrado para a sua conta.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"422":{"description":"Dados invalidos (por exemplo, amount menor que 1).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["meter","amount","customer","idempotencyKey"],"properties":{"meter":{"minLength":1,"maxLength":64,"type":"string"},"amount":{"minimum":1,"anyOf":[{"format":"integer","default":0,"type":"string"},{"minimum":1,"type":"integer"}]},"customer":{"type":"object","properties":{"email":{"format":"email","maxLength":320,"type":"string"},"ref":{"minLength":1,"maxLength":200,"type":"string"}}},"idempotencyKey":{"minLength":1,"maxLength":200,"type":"string"}}}},"application/x-www-form-urlencoded":{"schema":{"type":"object","required":["meter","amount","customer","idempotencyKey"],"properties":{"meter":{"minLength":1,"maxLength":64,"type":"string"},"amount":{"minimum":1,"anyOf":[{"format":"integer","default":0,"type":"string"},{"minimum":1,"type":"integer"}]},"customer":{"type":"object","properties":{"email":{"format":"email","maxLength":320,"type":"string"},"ref":{"minLength":1,"maxLength":200,"type":"string"}}},"idempotencyKey":{"minLength":1,"maxLength":200,"type":"string"}}}},"multipart/form-data":{"schema":{"type":"object","required":["meter","amount","customer","idempotencyKey"],"properties":{"meter":{"minLength":1,"maxLength":64,"type":"string"},"amount":{"minimum":1,"anyOf":[{"format":"integer","default":0,"type":"string"},{"minimum":1,"type":"integer"}]},"customer":{"type":"object","properties":{"email":{"format":"email","maxLength":320,"type":"string"},"ref":{"minLength":1,"maxLength":200,"type":"string"}}},"idempotencyKey":{"minLength":1,"maxLength":200,"type":"string"}}}}}},"operationId":"postV1TokensConsume","security":[{"ApiKeyAuth":[]}]}},"/v1/tokens/balance":{"get":{"tags":["Public"],"summary":"Consultar saldo de tokens de um cliente","description":"Consulta o saldo de tokens de um cliente, por medidor.\n\nRetorna, para cada medidor com saldo, os dois baldes (allowance do plano e\ntopup avulso) e o total. Identifique o cliente por ref (id no seu sistema) ou\npor email. Informe um meter para filtrar a um unico medidor.\n\nExemplo de querystring: `?meter=api_calls&ref=user_9812`","responses":{"200":{"description":"Saldo por medidor.","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","enum":[true]},"data":{"type":"array","items":{"type":"object","properties":{"meter":{"type":"string","description":"Chave do medidor."},"allowanceRemaining":{"type":"integer","description":"Saldo da cota do plano (allowance)."},"topupRemaining":{"type":"integer","description":"Saldo de recarga avulsa (topup)."},"total":{"type":"integer","description":"Soma dos dois baldes."}},"required":["meter","allowanceRemaining","topupRemaining","total"]}}},"required":["success","data"]},"example":{"success":true,"data":[{"meter":"api_calls","allowanceRemaining":995,"topupRemaining":1000,"total":1995}]}}}},"400":{"description":"Identificacao do cliente ausente (informe ref ou email).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"422":{"description":"Parametros de consulta invalidos.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"parameters":[{"name":"meter","in":"query","required":false,"schema":{"minLength":1,"maxLength":64,"type":"string"}},{"name":"email","in":"query","required":false,"schema":{"format":"email","maxLength":320,"type":"string"}},{"name":"ref","in":"query","required":false,"schema":{"minLength":1,"maxLength":200,"type":"string"}}],"operationId":"getV1TokensBalance","security":[{"ApiKeyAuth":[]}]}},"/v1/tokens/grant":{"post":{"tags":["Public"],"summary":"Creditar recarga de tokens para um cliente","description":"Credita unidades de recarga avulsa (topup) no saldo de um cliente.\n\nO credito vai para o balde topup (nunca expira) e nao altera a cota do plano\n(allowance). E idempotente: uma idempotencyKey ja usada devolve o mesmo\nresultado sem creditar de novo.\n\nExemplo de corpo:\n```json\n{\n  \"meter\": \"api_calls\",\n  \"amount\": 1000,\n  \"customer\": { \"ref\": \"user_9812\" },\n  \"idempotencyKey\": \"topup_2026-07-16_xyz789\",\n  \"reason\": \"Recarga avulsa comprada no plano Pro\"\n}\n```","responses":{"200":{"description":"Recarga creditada.","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","enum":[true]},"data":{"type":"object","properties":{"granted":{"type":"integer","description":"Unidades creditadas nesta chamada."},"meter":{"type":"string","description":"Chave do medidor."},"customer":{"type":"string","description":"Identificador do cliente (o ref informado ou o e-mail normalizado)."},"allowanceRemaining":{"type":"integer","description":"Saldo da cota do plano (allowance), intocado pelo credito."},"topupRemaining":{"type":"integer","description":"Saldo de recarga avulsa (topup) apos o credito."}},"required":["granted","meter","customer","allowanceRemaining","topupRemaining"]}},"required":["success","data"]},"example":{"success":true,"data":{"granted":1000,"meter":"api_calls","customer":"user_9812","allowanceRemaining":995,"topupRemaining":1000}}}}},"400":{"description":"Identificacao do cliente ausente (informe ref ou email).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Medidor nao encontrado para a sua conta.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"422":{"description":"Dados invalidos (por exemplo, amount menor que 1).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["meter","amount","customer","idempotencyKey"],"properties":{"meter":{"minLength":1,"maxLength":64,"type":"string"},"amount":{"minimum":1,"anyOf":[{"format":"integer","default":0,"type":"string"},{"minimum":1,"type":"integer"}]},"customer":{"type":"object","properties":{"email":{"format":"email","maxLength":320,"type":"string"},"ref":{"minLength":1,"maxLength":200,"type":"string"}}},"idempotencyKey":{"minLength":1,"maxLength":200,"type":"string"},"reason":{"maxLength":500,"type":"string"}}}},"application/x-www-form-urlencoded":{"schema":{"type":"object","required":["meter","amount","customer","idempotencyKey"],"properties":{"meter":{"minLength":1,"maxLength":64,"type":"string"},"amount":{"minimum":1,"anyOf":[{"format":"integer","default":0,"type":"string"},{"minimum":1,"type":"integer"}]},"customer":{"type":"object","properties":{"email":{"format":"email","maxLength":320,"type":"string"},"ref":{"minLength":1,"maxLength":200,"type":"string"}}},"idempotencyKey":{"minLength":1,"maxLength":200,"type":"string"},"reason":{"maxLength":500,"type":"string"}}}},"multipart/form-data":{"schema":{"type":"object","required":["meter","amount","customer","idempotencyKey"],"properties":{"meter":{"minLength":1,"maxLength":64,"type":"string"},"amount":{"minimum":1,"anyOf":[{"format":"integer","default":0,"type":"string"},{"minimum":1,"type":"integer"}]},"customer":{"type":"object","properties":{"email":{"format":"email","maxLength":320,"type":"string"},"ref":{"minLength":1,"maxLength":200,"type":"string"}}},"idempotencyKey":{"minLength":1,"maxLength":200,"type":"string"},"reason":{"maxLength":500,"type":"string"}}}}}},"operationId":"postV1TokensGrant","security":[{"ApiKeyAuth":[]}]}},"/v1/oneclick/links":{"post":{"tags":["Public"],"summary":"Criar um link de pagamento de 1 toque","description":"Cria um link de pagamento de 1 toque para um comprador que já tem cartão salvo na sua conta.\n\nO comprador abre a `url` devolvida, confere o produto e o valor, e confirma o pagamento sem digitar o cartão de novo. Se ele não tiver cartão salvo, a própria tela o leva ao checkout normal da oferta.\n\nDois pontos que evitam surpresa:\n\n- `offerId` é o id PÚBLICO da oferta, o mesmo que você já usa no link de checkout.\n- `ttlMinutes` acima do teto do perfil é RECUSADO, nunca ajustado em silêncio. Cada perfil tem o próprio teto: \"upsell\" é uma janela curta, para a hora da venda, e \"rebuy\" é uma janela larga, para recompra.\n\nO link é a credencial: quem tem a url pode confirmar a cobrança. Trate-o como um segredo e revogue-o se ele vazar.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["offerId","buyerRef","purpose"],"properties":{"offerId":{"minLength":1,"maxLength":64,"description":"Id público da oferta, o mesmo que você usa no link de checkout.","type":"string"},"buyerRef":{"format":"email","maxLength":320,"description":"E-mail do comprador que já tem cartão salvo na sua conta.","type":"string"},"purpose":{"type":"string","enum":["upsell","rebuy"]},"ttlMinutes":{"minimum":1,"description":"Prazo do link, em minutos. Cada perfil tem o próprio teto: acima dele a chamada é recusada, nunca ajustada em silêncio.","anyOf":[{"format":"integer","default":0,"type":"string"},{"minimum":1,"description":"Prazo do link, em minutos. Cada perfil tem o próprio teto: acima dele a chamada é recusada, nunca ajustada em silêncio.","type":"integer"}]}}}},"application/x-www-form-urlencoded":{"schema":{"type":"object","required":["offerId","buyerRef","purpose"],"properties":{"offerId":{"minLength":1,"maxLength":64,"description":"Id público da oferta, o mesmo que você usa no link de checkout.","type":"string"},"buyerRef":{"format":"email","maxLength":320,"description":"E-mail do comprador que já tem cartão salvo na sua conta.","type":"string"},"purpose":{"type":"string","enum":["upsell","rebuy"]},"ttlMinutes":{"minimum":1,"description":"Prazo do link, em minutos. Cada perfil tem o próprio teto: acima dele a chamada é recusada, nunca ajustada em silêncio.","anyOf":[{"format":"integer","default":0,"type":"string"},{"minimum":1,"description":"Prazo do link, em minutos. Cada perfil tem o próprio teto: acima dele a chamada é recusada, nunca ajustada em silêncio.","type":"integer"}]}}}},"multipart/form-data":{"schema":{"type":"object","required":["offerId","buyerRef","purpose"],"properties":{"offerId":{"minLength":1,"maxLength":64,"description":"Id público da oferta, o mesmo que você usa no link de checkout.","type":"string"},"buyerRef":{"format":"email","maxLength":320,"description":"E-mail do comprador que já tem cartão salvo na sua conta.","type":"string"},"purpose":{"type":"string","enum":["upsell","rebuy"]},"ttlMinutes":{"minimum":1,"description":"Prazo do link, em minutos. Cada perfil tem o próprio teto: acima dele a chamada é recusada, nunca ajustada em silêncio.","anyOf":[{"format":"integer","default":0,"type":"string"},{"minimum":1,"description":"Prazo do link, em minutos. Cada perfil tem o próprio teto: acima dele a chamada é recusada, nunca ajustada em silêncio.","type":"integer"}]}}}}}},"operationId":"postV1OneclickLinks","security":[{"ApiKeyAuth":[]}]},"get":{"tags":["Public"],"summary":"Listar os links de um comprador","description":"Lista os links que você criou para um comprador, do mais recente para o mais antigo, com o estado de cada um: \"active\", \"charged\", \"expired\" ou \"revoked\".\n\nA resposta traz a `url` de cada link, e é por isso que esta consulta exige escopo de escrita (`payments:write`) mesmo sendo uma leitura: a url é a credencial que confirma a cobrança, então ler a lista é obter essa capacidade.\n\nUm comprador sem link nenhum devolve uma lista vazia, não um erro.","parameters":[{"name":"buyerRef","in":"query","required":true,"schema":{"format":"email","maxLength":320,"description":"E-mail do comprador cujos links você quer consultar.","type":"string"}}],"operationId":"getV1OneclickLinks","security":[{"ApiKeyAuth":[]}]}},"/v1/oneclick/links/{linkId}":{"delete":{"tags":["Public"],"summary":"Revogar um link de pagamento","description":"Revoga um link de pagamento. É a sua defesa se um link vazar: a partir daqui ele recusa qualquer cobrança.\n\nÉ idempotente: revogar de novo devolve o carimbo original, com 200. Um link que não existe, ou que não é seu, devolve 404.","parameters":[{"name":"linkId","in":"path","required":true,"schema":{"minLength":1,"maxLength":64,"type":"string"}}],"operationId":"deleteV1OneclickLinksByLinkId","security":[{"ApiKeyAuth":[]}]}}},"components":{"schemas":{"ErrorEnvelope":{"description":"Envelope padrão de erro da API.","type":"object","required":["success","error"],"properties":{"success":{"const":false,"type":"boolean"},"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}}}}},"CustomerInput":{"description":"Dados do comprador (nome, e-mail, documento e telefone).","type":"object","required":["customerName","customerEmail","customerDocument","customerPhone"],"properties":{"customerName":{"minLength":2,"maxLength":256,"type":"string"},"customerEmail":{"minLength":3,"maxLength":320,"type":"string"},"customerDocument":{"minLength":11,"maxLength":18,"type":"string"},"customerPhone":{"minLength":10,"maxLength":32,"type":"string"}}},"AttributionInfo":{"description":"Sinais de origem do checkout (opcionais).","type":"object","properties":{"utm":{"type":"object","properties":{"source":{"maxLength":128,"type":"string"},"medium":{"maxLength":128,"type":"string"},"campaign":{"maxLength":128,"type":"string"},"content":{"maxLength":128,"type":"string"},"term":{"maxLength":128,"type":"string"}}},"click":{"type":"object","patternProperties":{"^(.*)$":{"maxLength":512,"type":"string"}}},"pixel":{"type":"object","patternProperties":{"^(.*)$":{"maxLength":512,"type":"string"}}},"referrer":{"maxLength":1024,"type":"string"},"landingPage":{"maxLength":1024,"type":"string"}}},"WebhookSalePayload":{"description":"Payload enviado ao seu endpoint nos eventos de venda.","type":"object","required":["saleId","productId","amountCents","currency","status","paymentMethod","customer","shipping","createdAt"],"properties":{"saleId":{"type":"string"},"productId":{"anyOf":[{"type":"string"},{"type":"null"}]},"amountCents":{"anyOf":[{"format":"integer","default":0,"type":"string"},{"type":"integer"}]},"currency":{"type":"string"},"status":{"type":"string"},"paymentMethod":{"anyOf":[{"type":"string"},{"type":"null"}]},"customer":{"type":"object","required":["name","email","phone","document"],"properties":{"name":{"anyOf":[{"type":"string"},{"type":"null"}]},"email":{"anyOf":[{"type":"string"},{"type":"null"}]},"phone":{"anyOf":[{"type":"string"},{"type":"null"}]},"document":{"anyOf":[{"type":"string"},{"type":"null"}]}}},"shipping":{"description":"Endereço de entrega informado no checkout. null quando a venda não pede entrega.","anyOf":[{"type":"object","required":["zipCode","street","number","complement","neighborhood","city","state"],"properties":{"zipCode":{"type":"string"},"street":{"type":"string"},"number":{"type":"string"},"complement":{"anyOf":[{"type":"string"},{"type":"null"}]},"neighborhood":{"type":"string"},"city":{"type":"string"},"state":{"type":"string"}}},{"type":"null"}]},"createdAt":{"anyOf":[{"format":"date-time","type":"string"},{"type":"null"}]}}},"WebhookRefundPayload":{"description":"Payload enviado ao seu endpoint no evento de estorno.","type":"object","required":["saleId","productId","refundId","amountCents","currency","status"],"properties":{"saleId":{"type":"string"},"productId":{"anyOf":[{"type":"string"},{"type":"null"}]},"refundId":{"type":"string"},"amountCents":{"anyOf":[{"format":"integer","default":0,"type":"string"},{"type":"integer"}]},"currency":{"type":"string"},"status":{"type":"string"}}},"WebhookChargebackPayload":{"description":"Payload enviado ao seu endpoint no evento de chargeback.","type":"object","required":["saleId","productId","amountCents","currency","status"],"properties":{"saleId":{"type":"string"},"productId":{"anyOf":[{"type":"string"},{"type":"null"}]},"amountCents":{"anyOf":[{"format":"integer","default":0,"type":"string"},{"type":"integer"}]},"currency":{"type":"string"},"status":{"type":"string"}}}},"securitySchemes":{"ApiKeyAuth":{"type":"http","scheme":"bearer","description":"Chave de API do seller (`sk_live_…` ou `sk_test_…`). Escopos exigidos variam por rota (ex.: `payments:read`, `products:write`)."}}}}