curl --request POST \
--url https://api.sandbox.z2pay.com/v1/checkout/links \
--header 'Content-Type: application/json' \
--header 'x-api-key: <api-key>' \
--data '
{
"name": "Apenas cartão",
"items": [
{
"name": "Produto Teste",
"quantity": 1,
"unitAmount": 19900
}
],
"paymentMethods": {
"card": {
"enabled": true,
"installments": {
"maxInstallments": 6,
"freeInstallments": 1
}
}
}
}
'{
"id": "chk_byd8p3p79re859jpkmr0j65n3",
"slug": "curso-marketing-digital",
"status": "active",
"mode": "payment",
"currency": "BRL",
"locale": "pt-BR",
"name": "Curso de Marketing Digital",
"description": "Acesso vitalício ao curso completo",
"sellable": true,
"config": {
"items": [
{
"name": "Curso de Marketing Digital",
"description": "Acesso vitalício",
"imageUrl": "https://cdn.z2pay.com/products/curso-mkt.png",
"quantity": 1,
"unitAmount": 49700,
"chargeType": "one_time"
}
],
"paymentMethods": {
"card": {
"enabled": true,
"installments": {
"maxInstallments": 12,
"freeInstallments": 1
}
},
"pix": {
"enabled": true,
"expiresIn": 3600
},
"boleto": {
"enabled": false
}
},
"branding": {
"primaryColor": "#5B21B6",
"merchantName": "Academia Online"
}
},
"requiredFields": [
"email",
"document",
"phone"
],
"customFields": null,
"successUrl": "https://academia.com/obrigado",
"cancelUrl": "https://academia.com/checkout",
"metadata": {
"campaign": "blackfriday"
},
"expirationMinutes": 1440,
"createdAt": "2025-06-29T13:45:30.000Z",
"updatedAt": "2025-06-29T13:45:30.000Z",
"url": "https://pay.z2pay.com/c/curso-marketing-digital"
}{
"error": {
"code": "VALIDATION_ERROR",
"message": "Validation failed",
"issues": [
{
"path": "status",
"message": "Status inválido. Valores aceitos: pending, waiting_payment, paid, refused, canceled, refunded"
},
{
"path": "startDate",
"message": "Data deve ser ISO 8601 com timezone (ex.: 2026-06-24T00:00:00Z)"
}
]
}
}{
"error": {
"code": "UNAUTHORIZED",
"message": "Invalid API key"
}
}{
"error": {
"code": "FORBIDDEN",
"message": "Forbidden — insufficient permissions"
}
}{
"error": "A request with this idempotency key is already being processed"
}{
"error": "Idempotency key already used with a different request body"
}Criar checkout link
Cria um template de cobrança reutilizável e devolve a URL pronta para divulgar.
curl --request POST \
--url https://api.sandbox.z2pay.com/v1/checkout/links \
--header 'Content-Type: application/json' \
--header 'x-api-key: <api-key>' \
--data '
{
"name": "Apenas cartão",
"items": [
{
"name": "Produto Teste",
"quantity": 1,
"unitAmount": 19900
}
],
"paymentMethods": {
"card": {
"enabled": true,
"installments": {
"maxInstallments": 6,
"freeInstallments": 1
}
}
}
}
'{
"id": "chk_byd8p3p79re859jpkmr0j65n3",
"slug": "curso-marketing-digital",
"status": "active",
"mode": "payment",
"currency": "BRL",
"locale": "pt-BR",
"name": "Curso de Marketing Digital",
"description": "Acesso vitalício ao curso completo",
"sellable": true,
"config": {
"items": [
{
"name": "Curso de Marketing Digital",
"description": "Acesso vitalício",
"imageUrl": "https://cdn.z2pay.com/products/curso-mkt.png",
"quantity": 1,
"unitAmount": 49700,
"chargeType": "one_time"
}
],
"paymentMethods": {
"card": {
"enabled": true,
"installments": {
"maxInstallments": 12,
"freeInstallments": 1
}
},
"pix": {
"enabled": true,
"expiresIn": 3600
},
"boleto": {
"enabled": false
}
},
"branding": {
"primaryColor": "#5B21B6",
"merchantName": "Academia Online"
}
},
"requiredFields": [
"email",
"document",
"phone"
],
"customFields": null,
"successUrl": "https://academia.com/obrigado",
"cancelUrl": "https://academia.com/checkout",
"metadata": {
"campaign": "blackfriday"
},
"expirationMinutes": 1440,
"createdAt": "2025-06-29T13:45:30.000Z",
"updatedAt": "2025-06-29T13:45:30.000Z",
"url": "https://pay.z2pay.com/c/curso-marketing-digital"
}{
"error": {
"code": "VALIDATION_ERROR",
"message": "Validation failed",
"issues": [
{
"path": "status",
"message": "Status inválido. Valores aceitos: pending, waiting_payment, paid, refused, canceled, refunded"
},
{
"path": "startDate",
"message": "Data deve ser ISO 8601 com timezone (ex.: 2026-06-24T00:00:00Z)"
}
]
}
}{
"error": {
"code": "UNAUTHORIZED",
"message": "Invalid API key"
}
}{
"error": {
"code": "FORBIDDEN",
"message": "Forbidden — insufficient permissions"
}
}{
"error": "A request with this idempotency key is already being processed"
}{
"error": "Idempotency key already used with a different request body"
}POST /checkout/links
Faz parte do recurso Links — o conceito, a Session gerada e os estados
estão lá.
Cria o template e devolve 201 com o Link inteiro, já com a url de pagamento. São obrigatórios os
itens e os métodos de pagamento; o resto tem default ou é opcional. O Link nasce active e
passa a vender na hora — cada abertura da URL materializa uma Session nova.
9990. Enviar 9.90 é recusado com 400
(integer requerido), mas 9 passa e vira nove centavos. Veja
Convenções.percentage somam 100 (tolerância de
±0.01 para arredondamento) e um único item do array tem liable: true — nenhum ou mais de um
é recusado com 400. O responsável é obrigatório porque chargeback sempre precisa de um dono; não
existe divisão em que o prejuízo fique sem endereço.slug é único globalmente, não só na sua conta. Se outra conta já usa aquele texto, a
resposta é 409 com key: "errors.checkout.slug_taken". Quando você envia um slug, a url da
resposta já vem como /c/{slug} em vez de /c/{id}.select sem options é aceito, e quebra na página. A API não recusa um campo customizado do
tipo select sem opções — ele é criado e o comprador vê um dropdown vazio, sem como responder.
Confira antes de publicar.requiredFields
mesmo que você não os liste — por isso a resposta nunca traz o campo vazio —, e confere o dígito
verificador do documento. address é o único opt-in: só entra se você o listar. O nome o
comprador informa na página, mas não há como torná-lo obrigatório — name não é um valor aceito
em requiredFields.items, paymentMethods, splits e
branding no topo do corpo. Na leitura (GET /checkout/links/{id})
esses quatro voltam dentro de config. Os demais campos ficam no topo nos dois sentidos. O
detalhe importa ao
espelhar um Link numa venda rápida.code. Todo 409 de regra responde code: "CONFLICT" — o
que distingue um caso do outro é a key, com o prefixo inteiro
(errors.checkout.slug_taken). Comparar error.code === "slug_taken" nunca casa. Veja
Erros de domínio.Idempotency-Key para que um retry por timeout não crie dois Links.
Veja Convenções.Exemplo
curl -X POST https://api.sandbox.z2pay.com/v1/checkout/links \
-H "x-api-key: SUA_CHAVE_DE_SANDBOX" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: 7c9e6679-7425-40de-944b-e07fc1f90ae7" \
-d '{
"name": "Curso de Backend",
"description": "Link para divulgação no Instagram",
"items": [
{ "name": "Curso de Backend — vitalício", "quantity": 1, "unitAmount": 49900 }
],
"paymentMethods": {
"card": { "enabled": true, "installments": { "maxInstallments": 12, "freeInstallments": 3 } },
"pix": { "enabled": true, "expiresIn": 3600 }
},
"branding": { "primaryColor": "#1e3b79", "merchantName": "Henrique Cursos" },
"metadata": { "campaign": "instagram-bio-2026-05" }
}'
{
"id": "chk_byd8p3p79re859jpkmr0j65n3",
"name": "Curso de Backend",
"description": "Link para divulgação no Instagram",
"slug": null,
"status": "active",
"sellable": true,
"mode": "payment",
"currency": "BRL",
"locale": "pt-BR",
"config": {
"items": [
{ "name": "Curso de Backend — vitalício", "quantity": 1, "unitAmount": 49900 }
],
"paymentMethods": { "...": "..." },
"splits": null,
"branding": { "primaryColor": "#1e3b79", "merchantName": "Henrique Cursos" }
},
"requiredFields": ["email", "document", "phone"],
"customFields": null,
"successUrl": null,
"cancelUrl": null,
"metadata": { "campaign": "instagram-bio-2026-05" },
"expirationMinutes": 1440,
"createdAt": "2026-06-24T12:00:00.000Z",
"updatedAt": "2026-06-24T12:00:00.000Z",
"url": "https://pay.sandbox.z2pay.com/c/chk_byd8p3p79re859jpkmr0j65n3"
}
url da resposta é o link pronto para compartilhar. Cada abertura materializa uma Session nova.Authorizations
API key unificada (z2_{live|test}{sk|pk}...) — secret (sk) para integração backend, publishable (pk) para uso no frontend público
Body
Métodos de pagamento habilitados (card/pix/boleto/combined); ao menos um enabled.
Show child attributes
Show child attributes
Nome do link de checkout.
255Descrição exibida no checkout.
2000Slug único global usado na URL pública /c/{slug} (a-z, 0-9 e hífen).
3 - 100^[a-z0-9-]+$'payment' (default) para pagamento único; 'subscription' exige o objeto subscription populado.
payment, subscription Moeda da cobrança. Só BRL — os gateways liquidam em real.
BRL Idioma do checkout (default 'pt-BR').
pt-BR, en-US, es-ES Itens do carrinho (unitAmount em centavos); ao menos 1 quando mode=payment.
Show child attributes
Show child attributes
Divisão de receita por percentual; a soma deve ser exatamente 100.
Show child attributes
Show child attributes
Customização visual do checkout.
Show child attributes
Show child attributes
Configuração de recorrência; obrigatória (e exclusiva) quando mode=subscription. Sem startAt: um Link é template reutilizável, então não há como adiar "o início" de algo que cada comprador ativa em um momento diferente — disponível apenas na venda rápida.
Show child attributes
Show child attributes
Campos do comprador exigidos no checkout (email, document, phone, address).
email, document, phone, address Campos customizados do formulário (máx. 20).
20Show child attributes
Show child attributes
URL de redirecionamento após pagamento aprovado.
2000URL de redirecionamento quando o comprador cancela.
2000Metadados do seller (string → string), consultáveis no próprio link. Não são propagados à Transaction; para correlacionar vendas ao link nos webhooks, use o additionalInfo.checkoutLinkId da Transaction.
Show child attributes
Show child attributes
Expiração da sessão em minutos (5 a 43200 = 30 dias).
5 <= x <= 43200Response
Link criado
Identificador único do registro.
Slug único global usado na URL pública /c/{slug}.
Estado atual do registro.
Modo do checkout: 'payment' (pagamento único) ou 'subscription' (assinatura).
Moeda no padrão ISO 4217 (ex.: BRL).
Idioma do checkout (ex.: pt-BR, en-US, es-ES).
Nome de exibição do registro.
Descrição exibida no checkout.
Se o Link pode vender agora. É false quando um recebedor do splits, ou o dono da conta, não está ativo no PSP — o comprador vê uma página de indisponível. Independente do status.
Snapshot da configuração do checkout (formas de pagamento, itens e personalização visual).
Campos do comprador exigidos no checkout (ex.: email, document, phone, address).
Definições dos campos personalizados solicitados no checkout.
URL de redirecionamento após o pagamento ser concluído com sucesso.
URL de redirecionamento quando o comprador cancela o checkout.
Metadados livres (pares chave-valor) para uso do integrador; não afeta o processamento.
Tempo de validade da sessão de checkout, em minutos.
Data e hora de criação do registro (ISO 8601).
Data e hora da última atualização do registro (ISO 8601).
URL pública do checkout para o comprador finalizar o pagamento.