curl --request POST \
--url https://api.sandbox.z2pay.com/v1/subscriptions/{id}/extra-items/settle \
--header 'Content-Type: application/json' \
--header 'x-api-key: <api-key>' \
--data '
{
"dueAt": "2023-11-07T05:31:56Z",
"reasonDetails": "<string>",
"allowedPaymentMethods": [],
"installmentsConfig": {
"maxInstallments": 6,
"freeInstallments": 6,
"interestRate": 50
}
}
'const options = {
method: 'POST',
headers: {'x-api-key': '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
dueAt: '2023-11-07T05:31:56Z',
reasonDetails: '<string>',
allowedPaymentMethods: [],
installmentsConfig: {maxInstallments: 6, freeInstallments: 6, interestRate: 50}
})
};
fetch('https://api.sandbox.z2pay.com/v1/subscriptions/{id}/extra-items/settle', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));import requests
url = "https://api.sandbox.z2pay.com/v1/subscriptions/{id}/extra-items/settle"
payload = {
"dueAt": "2023-11-07T05:31:56Z",
"reasonDetails": "<string>",
"allowedPaymentMethods": [],
"installmentsConfig": {
"maxInstallments": 6,
"freeInstallments": 6,
"interestRate": 50
}
}
headers = {
"x-api-key": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text){
"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": "NOT_FOUND",
"message": "Resource not found"
}
}{
"error": {
"code": "CONFLICT",
"message": "No refundable payment found"
}
}{
"error": "Idempotency key already used with a different request body"
}Fechar as cobranças extras agora
Emite uma fatura separada com as cobranças extras pendentes da assinatura, sem esperar a virada do ciclo.
curl --request POST \
--url https://api.sandbox.z2pay.com/v1/subscriptions/{id}/extra-items/settle \
--header 'Content-Type: application/json' \
--header 'x-api-key: <api-key>' \
--data '
{
"dueAt": "2023-11-07T05:31:56Z",
"reasonDetails": "<string>",
"allowedPaymentMethods": [],
"installmentsConfig": {
"maxInstallments": 6,
"freeInstallments": 6,
"interestRate": 50
}
}
'const options = {
method: 'POST',
headers: {'x-api-key': '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
dueAt: '2023-11-07T05:31:56Z',
reasonDetails: '<string>',
allowedPaymentMethods: [],
installmentsConfig: {maxInstallments: 6, freeInstallments: 6, interestRate: 50}
})
};
fetch('https://api.sandbox.z2pay.com/v1/subscriptions/{id}/extra-items/settle', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));import requests
url = "https://api.sandbox.z2pay.com/v1/subscriptions/{id}/extra-items/settle"
payload = {
"dueAt": "2023-11-07T05:31:56Z",
"reasonDetails": "<string>",
"allowedPaymentMethods": [],
"installmentsConfig": {
"maxInstallments": 6,
"freeInstallments": 6,
"interestRate": 50
}
}
headers = {
"x-api-key": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text){
"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": "NOT_FOUND",
"message": "Resource not found"
}
}{
"error": {
"code": "CONFLICT",
"message": "No refundable payment found"
}
}{
"error": "Idempotency key already used with a different request body"
}POST /subscriptions/:id/extra-items/settle
Faz parte do recurso Assinaturas. Os itens são criados em
Lançar cobrança extra e a fila inteira está em
Listar cobranças extras.
Emite uma fatura avulsa com todas as cobranças extras pending da assinatura, sem esperar a
próxima fatura de ciclo — que, numa recorrência anual, pode estar a doze meses.
Os itens passam a consumed, com consumedInvoiceId apontando para a fatura emitida, e não entram
mais na fatura do ciclo. O contrato não muda: nem o ciclo, nem a data da próxima fatura, nem o valor
da mensalidade.
O corpo é opcional — as linhas e o valor vêm da fila. Sem corpo, a fatura vence hoje e a cobrança
dispara no ato.
O vencimento decide quando a cobrança acontece
A fatura resultante é uma avulsa como qualquer outra: a cobrança dispara emdueAt - chargeLeadTimeDays da assinatura. Com dueAt no futuro, a fatura nasce scheduled; sem
dueAt, nasce open.
O que acontece na abertura depende da forma de pagamento da assinatura:
| Forma de pagamento | Na abertura da fatura |
|---|---|
| Cartão | O cartão salvo é cobrado. Nenhum e-mail é enviado |
| PIX ou boleto | Nada é cobrado: sai um e-mail com o link da página de pagamento |
chargeLeadTimeDays antes do vencimento —, e não no momento desta chamada. Para que ele saia
agora, omita o dueAt.Recusas
409. Não há o que faturar quando nenhum item está pending.404. dueAt no passado responde 400.
Depois de emitida
A fatura participa do split da assinatura, dispara os mesmos webhooksinvoice.* e tem a mesma
página de pagamento hospedada. Cada item recolhido dispara um
extra_item.billed.
Anular a fatura devolve os itens para a fila — eles voltam a pending e entram no próximo
fechamento, seja o do ciclo ou outra chamada desta rota.
Exemplo
curl -X POST https://api.sandbox.z2pay.com/v1/subscriptions/sub_x33m4yn6brazh71en4mki6f5c/extra-items/settle \
-H "x-api-key: SUA_CHAVE_DE_SANDBOX" \
-H "Content-Type: application/json" \
-d '{
"dueAt": "2026-09-05T23:59:59.000Z",
"reasonDetails": "Fechamento antecipado pedido pelo cliente"
}'
{
"id": "inv_c3qahi4qnkc258lfc14gplupt",
"number": { "year": 2026, "sequence": 128 },
"customerId": "cust_c72q6ogr9iko0we85mqal04te",
"customerEmail": "maria.silva@example.com",
"customerName": "Maria Silva",
"currency": "BRL",
"subscriptionId": "sub_x33m4yn6brazh71en4mki6f5c",
"status": "scheduled",
"kind": "manual",
"periodStart": null,
"periodEnd": null,
"chargeAt": "2026-09-05T23:59:59.000Z",
"dueAt": "2026-09-05T23:59:59.000Z",
"issuedAt": "2026-08-21T13:10:00.000Z",
"subtotal": 34980,
"total": 34980,
"amountPaid": 0,
"amountRemaining": 34980,
"metadata": {
"manualInvoice": true,
"reason": "extra_items_settlement",
"reasonDetails": "Fechamento antecipado pedido pelo cliente"
},
"createdAt": "2026-08-21T13:10:00.000Z"
}
total desta resposta já é o
definitivo; a composição aparece em GET /invoices/{id}, que pode devolver items vazio nos
instantes seguintes. O webhook invoice.issued marca o momento em que ela está completa.Authorizations
API Key da Credential (gerada no Backoffice)
Headers
Chave única para garantir idempotência da requisição
Path Parameters
ID da assinatura
Body
Vencimento da fatura de fechamento (ISO 8601 com timezone), estritamente no futuro. Ausente = vence hoje, e a cobrança dispara no ato.
Justificativa do fechamento antecipado, para a trilha de auditoria (1 a 500 caracteres). Ausente = texto padrão. O pagador não vê — o que ele vê é a description de cada item.
1 - 500Formas de pagamento oferecidas na página desta fatura. Ausente = o método padrão da assinatura.
1 - 3 elementscard, pix, boleto Parcelamento oferecido ao pagador no cartão — só faz sentido com card em allowedPaymentMethods. Ausente/null = à vista.
Show child attributes
Show child attributes
Response
Fatura de fechamento emitida