Skip to main content

Renegotiation with IOF Spread and Interest-Only Discount - BNPL

Overview

This page documents the batch renegotiation flow for BNPL operations where the credit operation was created with iof_charge_method: "spread". In this model, the IOF is not financed in the installments — it is calculated normally but added to the assignment_amount (assignment value), not to the borrower's installments.

Additionally, the field discount_validation: "only_interest_discount" can be used in each operation within the operations[] array to restrict discounts to the interest portion only. If the discount exceeds the interest and reaches the principal or fine, the API will return the error InvalidDiscountAmountOnlyInterestDiscount.

The flow uses the batch endpoints: simulation (POST /renegotiation/batch_proposal_simulation) followed by the proposal (POST /renegotiation/batch_proposal). The discount_validation field is set per operation in the operations[] array, not at the root level of the payload.

Note — iof_charge_method

The iof_charge_method field is set at the time of credit operation creation (credit-operation-api), not during renegotiation. When iof_charge_method: "spread":

  • The IOF is calculated normally (base IOF + additional IOF), but is not deducted from the borrower's installments
  • The IOF is added to the assignment_amount — meaning the IOF cost is reflected in the assignment value
  • The borrower's installments are "clean" of IOF

The three possible values are:

  • "financed" (default) — IOF is financed in the installments (deducted from the amount credited to the borrower)
  • "spread" — IOF is added to the assignment value (assignment_amount), not to the installments
  • "free" — No IOF (total_iof = 0)
Attention — discount_validation

When discount_validation: "only_interest_discount" is set on an operation, the system validates that the discount applied to each installment does not include principal amortization (discount_principal_amortization_amount) or fine (discount_fine_amount). Only interest (prefixed interest) can be discounted.

If any installment has a discount that reaches the principal or fine, the API returns the error InvalidDiscountAmountOnlyInterestDiscount and the entire request fails.

Step 1: Batch Simulation

ENDPOINT
/renegotiation/batch_proposal_simulation
METHOD
POST
Attention

The fields discount_amount and discount_percentage CANNOT be sent together in the same payload (root level).

Request Body
{
"amortization_type": "installment_payment",
"reference_date": "2026-04-20",
"discount_percentage": 0.0,
"operations": [
{
"debt_key": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"discount_validation": "only_interest_discount",
"installments": [
{
"installment_key": "f9e8d7c6-b5a4-3210-fedc-ba9876543210"
}
]
}
]
}

Body Params

FieldTypeDescriptionMax. Char.
amortization_type*stringAmortization typeAmortization Type Enumerators
reference_date*stringReference date for present value calculation (must be D+1)10
discount_percentagefloatDiscount percentage on the present value ((1 - percentage) x Present Value)10
discount_amountfloatDiscount amount applied on the present value10
operations*arrayList of operations to be renegotiatedOperations Object

Operations Object

FieldTypeDescriptionMax. Char.
debt_key*stringUnique key of the credit operation (DEBT-KEY)UUID
discount_validationstringDiscount validation rule. When set to "only_interest_discount", the applied discount cannot exceed the interest portion.Discount Validation Enumerators
installments*arrayInstallments to be renegotiatedInstallments Object

Installments Object

FieldTypeDescriptionMax. Char.
installment_key*stringKey of the installment to be renegotiatedUUID
paid_amountfloatAmount paid (or allocated) on the installment, in BRL (R$). Required when amortization_type is present_amount.15,2
discount_amountfloatDiscount amount in BRL (R$) on the installment. Required when amortization_type is present_amount (use 0 if there is no discount). Optional for other types.15,2

Discount Validation Enumerators

FieldDescription
only_interest_discountValidates that the discount applied to each installment does not exceed the interest amount. If the discount reaches the principal or fine, the API returns the error InvalidDiscountAmountOnlyInterestDiscount.

Amortization Type Enumerators

FieldDescription
installment_paymentRenegotiation for payment of specific installments sent in the payload. Requires the installment_key of each installment.
overdue_installment_paymentRenegotiation targeted at overdue installment payment. Requires the installment_key of each installment.
present_amountSimulation with per-installment present value. In each installments[], installment_key, paid_amount and discount_amount are required.

Response

STATUS
200
Response Body
{
"batch_proposal_key": "7423c701-3578-4733-8f30-81ab60afdb6d",
"discount_percentage": 0,
"discount_amount": 0,
"amortization_type": "installment_payment",
"payment_amount": 517.88,
"requester_name": "Empresa Exemplo Ltda",
"requester_key": "78287247-947d-4730-9bd1-7efb068175b6",
"issuer_name": "João da Silva",
"reference_date": "2026-04-20",
"issuer_document_number": "31057466093",
"operations": [
{
"requester_key": "78287247-947d-4730-9bd1-7efb068175b6",
"contract_number": "DWF1761222116",
"payment_amount": 517.88,
"discount_amount": 0,
"origin_key": null,
"affected_installments": [
{
"installment_key": "f9e8d7c6-b5a4-3210-fedc-ba9876543210",
"due_date": "2026-05-07",
"principal_amount": 491.49,
"interest_amount": 52.40,
"fine_amount": 0,
"total_amount": 543.89,
"present_amount": 517.88,
"paid_amount": 517.88,
"principal_amortization_payment_amount": 491.49,
"prefixed_interest_payment_amount": 26.39,
"fine_payment_amount": 0,
"discount_amount": 0
}
],
"remaining_installments": [
{
"installment_key": "370e73d1-55d8-431e-9b22-d08fb8297999",
"due_date": "2026-06-07",
"principal_amount": 516.13,
"interest_amount": 27.76,
"fine_amount": 0,
"total_amount": 543.89
}
],
"debt_key": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
}
]
}

Step 2: Batch Proposal

ENDPOINT
/renegotiation/batch_proposal
METHOD
POST
Attention

The fields discount_amount and discount_percentage CANNOT be sent together in the same payload (root level).

Request Body
{
"amortization_type": "installment_payment",
"reference_date": "2026-04-20",
"proposal_due_date": "2026-04-27",
"payment_type": "pix",
"discount_percentage": 0.0,
"request_control_key": "94b31045-c8e7-45be-a88d-2ae25c5df5db",
"operations": [
{
"debt_key": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"discount_validation": "only_interest_discount",
"installments": [
{
"installment_key": "f9e8d7c6-b5a4-3210-fedc-ba9876543210"
}
]
}
]
}

Body Params

FieldTypeDescriptionMax. Char.
amortization_type*stringAmortization typeAmortization Type Enumerators
reference_date*stringReference date for present value calculation (D+1)10
proposal_due_date*stringDue date for the renegotiation proposal10
payment_type*stringPayment typePayment Type Enumerators
request_control_keystringControl key for tracking and unique identification (optional)UUID
discount_percentagefloatDiscount percentage on the present value10
discount_amountfloatDiscount amount on the present value10
operations*arrayList of operations to be renegotiatedOperations Object

Operations Object

FieldTypeDescriptionMax. Char.
debt_key*stringUnique key of the credit operation (DEBT-KEY)UUID
discount_validationstringDiscount validation rule. When set to "only_interest_discount", the applied discount cannot exceed the interest portion.Discount Validation Enumerators
installments*arrayInstallments to be renegotiatedInstallments Object

Installments Object

FieldTypeDescriptionMax. Char.
installment_key*stringKey of the installment to be renegotiatedUUID
paid_amountfloatAmount paid (or allocated) on the installment, in BRL (R$). Required when amortization_type is present_amount.15,2
discount_amountfloatDiscount amount in BRL (R$) applied to the installment. Required when amortization_type is present_amount (use 0 if there is no discount). For other amortization types, it remains optional per installment.15,2

Discount Validation Enumerators

FieldDescription
only_interest_discountValidates that the discount applied to each installment does not exceed the interest amount. If the discount reaches the principal or fine, the API returns the error InvalidDiscountAmountOnlyInterestDiscount.

Payment Type Enumerators

FieldDescription
bank_slipPayment via bank slip (generates bank slip and Pix)
pixPayment via Pix (generates Pix only)
manualManual payment (does not generate a payment method)

Amortization Type Enumerators

FieldDescription
installment_paymentRenegotiation for payment of specific installments. Requires the installment_key of each installment.
overdue_installment_paymentRenegotiation targeted at overdue installment payment. Requires the installment_key of each installment.
present_amountRenegotiation with per-installment present value composition. In each item of installments[], installment_key, paid_amount and discount_amount are required.

Response

STATUS
201
Response Body
{
"batch_proposal_key": "ff5ad6dd-2087-4850-a3e8-b37634448b4e",
"discount_percentage": 0,
"discount_amount": 0,
"amortization_type": "installment_payment",
"payment_amount": 517.88,
"requester_name": "Empresa Exemplo Ltda",
"requester_key": "78287247-947d-4730-9bd1-7efb068175b6",
"issuer_name": "João da Silva",
"reference_date": "2026-04-20",
"issuer_document_number": "31057466093",
"batch_proposal_status": "pending_payment",
"proposal_due_date": "2026-04-27",
"payment_type": "pix",
"request_control_key": "94b31045-c8e7-45be-a88d-2ae25c5df5db",
"origin_key": null,
"operations": [
{
"requester_key": "78287247-947d-4730-9bd1-7efb068175b6",
"contract_number": "DWF1761222116",
"payment_amount": 517.88,
"discount_amount": 0,
"origin_key": null,
"affected_installments": [
{
"installment_key": "f9e8d7c6-b5a4-3210-fedc-ba9876543210",
"due_date": "2026-05-07",
"principal_amount": 491.49,
"interest_amount": 52.40,
"fine_amount": 0,
"total_amount": 543.89,
"present_amount": 517.88,
"paid_amount": 517.88,
"principal_amortization_payment_amount": 491.49,
"prefixed_interest_payment_amount": 26.39,
"fine_payment_amount": 0,
"discount_amount": 0
}
],
"remaining_installments": [
{
"installment_key": "370e73d1-55d8-431e-9b22-d08fb8297999",
"due_date": "2026-06-07",
"principal_amount": 516.13,
"interest_amount": 27.76,
"fine_amount": 0,
"total_amount": 543.89
}
],
"debt_key": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
}
],
"payment": {
"digitable_line": null,
"qr_code_url": "00020126930014br.gov.bcb.pix2571qrcode-h.sandbox.qitech.app/bacen/cobv/acaeb341e1264cde99b93e247e12b3725204000053039865802BR5925QISOCIEDADEDECREDITODIRET6008SaoPaulo61080145200062070503***63043AD0",
"qr_code_key": "acaeb341-e126-4cde-99b9-3e247e12b372",
"bank_slip_key": null,
"paid_method_type": "pix",
"source_account_key": null,
"payment_data": {
"creditor_bank_account_key": "6108dd45-580d-48c4-b3bb-74c1e843be49",
"batch_renegotiation_proposal_key": "ff5ad6dd-2087-4850-a3e8-b37634448b4e"
}
}
}
Important

Save the batch_proposal_key returned in the response. It will be needed to check the batch renegotiation status and to receive payment webhooks.

Error: Discount Exceeds Interest

When discount_validation: "only_interest_discount" is set on an operation and the applied discount amount exceeds the interest portion, the API returns the following error:

Error Response
{
"code": "InvalidDiscountAmountOnlyInterestDiscount",
"message": "Discount amount must be only interest discount"
}

The validation is performed per installment during amortization processing. If any individual installment has a discount whose value includes principal amortization (discount_principal_amortization_amount > 0) or fine (discount_fine_amount > 0), the entire request is rejected.

Assignment

Note

After the proposal is paid, the assignment step (POST /credit_operations/assign) creates a formal transfer of the credit operation. This is a separate endpoint from the credit-operation-api.

When the credit operation has iof_charge_method: "spread", the calculated assignment_amount includes the IOF that was not financed in the installments. In other words, the assignment value reflects the total cost including the separate IOF.