PagnovoPagnovodocs

Referência da API

Criar cupom

Cria um cupom de desconto. **V2:** o cupom só funciona nas Offers da whitelist (passe `offerIds` para já criar com a whitelist preenchida). Códigos são normalizados pra UPPERCASE — `verao2026` é salvo como `VERAO2026`. Cupom só tem efeito em Offers recorrentes (que geram Invoice). QuickLink e Checkout one-time **não aceitam cupom**. A chave de API precisa da permissão `isInvoiceAvailable`.

POST/v2/coupons
Unidades dependem do tipo
discountValue Quando `discountType: PERCENTAGE`, `discountValue` está em **basis points** (1.000 = 10%, 10.000 = 100%). Quando `discountType: FIXED`, está em **centavos** (100 = R$ 1,00). `minPurchaseAmount` também é em centavos. Veja a seção 'Cupons (visão geral)' para a tabela completa.

Autenticação

HTTP Basic Auth. Envie sua secret key no header:

Authorization: Basic {base64(secret:SUA_SECRET_KEY)}

Parâmetros

codestringobrigatório

Código do cupom. 3-30 caracteres. Aceita apenas `A-Z`, `0-9`, `-` e `_`. É normalizado pra UPPERCASE no servidor (você pode mandar minúsculo). Único por conta.

Exemplo: VERAO2026

descriptionstringopcional

Descrição interna do cupom (não é mostrada ao cliente).

Exemplo: Promoção de verão — 15% off

discountType'PERCENTAGE' | 'FIXED'obrigatório

Tipo do desconto. `PERCENTAGE` desconta uma porcentagem; `FIXED` desconta um valor absoluto. Esse campo fica **imutável** depois do primeiro uso do cupom.

Exemplo: PERCENTAGE

discountValuenumber (integer)obrigatório

Valor do desconto. Para `PERCENTAGE`: basis points entre 1 (0,01%) e 10.000 (100%). Para `FIXED`: centavos entre 100 (R$ 1,00) e 5.000.000 (R$ 50.000,00). Imutável após primeiro uso.

Exemplo: 1500

maxUsesnumber | nullopcional

Limite global de usos do cupom. `null` ou ausente = ilimitado. O limite é respeitado mesmo em corrida de checkouts simultâneos. Máximo: 1.000.000.

Exemplo: 500

validFromstring (ISO 8601)opcional

Data a partir da qual o cupom é válido. Pode estar no passado (não é validado). Se omitido, é válido desde sempre.

Exemplo: 2026-06-01T00:00:00.000Z

validUntilstring (ISO 8601)opcional

Data de expiração. **Não pode estar no passado** — o servidor rejeita com 400. Se omitido, o cupom nunca expira.

Exemplo: 2026-12-31T23:59:59.000Z

minPurchaseAmountnumber | nullopcional

Valor mínimo da fatura (em **centavos**) para o cupom ser aplicável. `null` = sem mínimo. Ex: `5000` = R$ 50,00.

Exemplo: 5000

offerIdsstring[]opcional

IDs das Offers onde o cupom funciona. Sem isso, o cupom existe mas não funciona em lugar nenhum até você adicionar via `POST /v2/coupons/:id/offers`. Todos os IDs precisam pertencer à sua conta.

Exemplo: ["off_plano_mensal", "off_plano_anual"]

metadataobjectopcional

Objeto JSON arbitrário para anexar informação do seu sistema.

Exemplo: { "campaign": "summer-launch" }

Body da requisição

Content-Type: application/json

JSON
// Cupom de 15% off, válido até 31/dez, mínimo R$ 50:
{
  "code": "VERAO2026",
  "description": "Promoção de verão — 15% off",
  "discountType": "PERCENTAGE",
  "discountValue": 1500,
  "maxUses": 500,
  "validFrom": "2026-06-01T00:00:00.000Z",
  "validUntil": "2026-12-31T23:59:59.000Z",
  "minPurchaseAmount": 5000,
  "offerIds": ["off_plano_mensal", "off_plano_anual"],
  "metadata": { "campaign": "summer-launch" }
}

// Cupom de R$ 10 fixo, ilimitado, sem mínimo:
{
  "code": "BEM_VINDO",
  "discountType": "FIXED",
  "discountValue": 1000,
  "maxUses": null,
  "offerIds": ["off_plano_mensal"]
}

Respostas

201

Cupom criado. Note que o response não inclui a whitelist — para ver as Offers vinculadas, faça GET /v2/coupons/:id.

JSON
{
  "id": "cpn_a8f3d2e1-9b4c-4e5f-8a7d-2e5f6c1d4b9a",
  "createdByUserId": "u-1234",
  "code": "VERAO2026",
  "description": "Promoção de verão — 15% off",
  "discountType": "PERCENTAGE",
  "discountValue": 1500,
  "status": "ACTIVE",
  "maxUses": 500,
  "currentUses": 0,
  "validFrom": "2026-06-01T00:00:00.000Z",
  "validUntil": "2026-12-31T23:59:59.000Z",
  "minPurchaseAmount": 5000,
  "metadata": { "campaign": "summer-launch" },
  "deletedAt": null,
  "createdAt": "2026-05-26T14:32:01.923Z",
  "updatedAt": "2026-05-26T14:32:01.923Z"
}
400

Erro de validação. Causas comuns: código já existe, formato inválido, discountValue fora do range, validUntil no passado, ou alguma offerId não pertence à sua conta.

JSON
{
  "status": 400,
  "error": "Ja existe um cupom com codigo \"VERAO2026\""
}

Exemplos

cURL
curl -X POST "https://api.pagnovo.com/v2/coupons" \
  -H "Authorization: Basic $(echo -n 'secret:SUA_SECRET_KEY' | base64)" \
  -H "Content-Type: application/json" \
  -d '{
    "code": "VERAO2026",
    "discountType": "PERCENTAGE",
    "discountValue": 1500,
    "maxUses": 500,
    "validUntil": "2026-12-31T23:59:59.000Z",
    "offerIds": ["off_plano_mensal"]
  }'
JavaScript
const token = Buffer.from("secret:" + process.env.PAGNOVO_SECRET_KEY).toString("base64");
 
// 15% off, máximo 500 usos, expira 31/dez
const res = await fetch("https://api.pagnovo.com/v2/coupons", {
  method: "POST",
  headers: {
    Authorization: `Basic ${token}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    code: "verao2026",                       // será normalizado pra VERAO2026
    discountType: "PERCENTAGE",
    discountValue: 1500,                     // 15% (basis points!)
    maxUses: 500,
    validUntil: "2026-12-31T23:59:59.000Z",
    offerIds: ["off_plano_mensal"],
  }),
});
 
if (!res.ok) {
  const err = await res.json();
  console.error(err.error);
  return;
}
 
const coupon = await res.json();
console.log("criado:", coupon.code, "id:", coupon.id);