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.
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)
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
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
| Field | Type | Description | Max. Char. |
|---|---|---|---|
amortization_type* | string | Amortization type | Amortization Type Enumerators |
reference_date* | string | Reference date for present value calculation (must be D+1) | 10 |
discount_percentage | float | Discount percentage on the present value ((1 - percentage) x Present Value) | 10 |
discount_amount | float | Discount amount applied on the present value | 10 |
operations* | array | List of operations to be renegotiated | Operations Object |
Operations Object
| Field | Type | Description | Max. Char. |
|---|---|---|---|
debt_key* | string | Unique key of the credit operation (DEBT-KEY) | UUID |
discount_validation | string | Discount validation rule. When set to "only_interest_discount", the applied discount cannot exceed the interest portion. | Discount Validation Enumerators |
installments* | array | Installments to be renegotiated | Installments Object |
Installments Object
| Field | Type | Description | Max. Char. |
|---|---|---|---|
installment_key* | string | Key of the installment to be renegotiated | UUID |
paid_amount | float | Amount paid (or allocated) on the installment, in BRL (R$). Required when amortization_type is present_amount. | 15,2 |
discount_amount | float | Discount 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
| Field | Description |
|---|---|
only_interest_discount | Validates 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
| Field | Description |
|---|---|
| installment_payment | Renegotiation for payment of specific installments sent in the payload. Requires the installment_key of each installment. |
| overdue_installment_payment | Renegotiation targeted at overdue installment payment. Requires the installment_key of each installment. |
| present_amount | Simulation with per-installment present value. In each installments[], installment_key, paid_amount and discount_amount are required. |
Response
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
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
| Field | Type | Description | Max. Char. |
|---|---|---|---|
amortization_type* | string | Amortization type | Amortization Type Enumerators |
reference_date* | string | Reference date for present value calculation (D+1) | 10 |
proposal_due_date* | string | Due date for the renegotiation proposal | 10 |
payment_type* | string | Payment type | Payment Type Enumerators |
request_control_key | string | Control key for tracking and unique identification (optional) | UUID |
discount_percentage | float | Discount percentage on the present value | 10 |
discount_amount | float | Discount amount on the present value | 10 |
operations* | array | List of operations to be renegotiated | Operations Object |
Operations Object
| Field | Type | Description | Max. Char. |
|---|---|---|---|
debt_key* | string | Unique key of the credit operation (DEBT-KEY) | UUID |
discount_validation | string | Discount validation rule. When set to "only_interest_discount", the applied discount cannot exceed the interest portion. | Discount Validation Enumerators |
installments* | array | Installments to be renegotiated | Installments Object |
Installments Object
| Field | Type | Description | Max. Char. |
|---|---|---|---|
installment_key* | string | Key of the installment to be renegotiated | UUID |
paid_amount | float | Amount paid (or allocated) on the installment, in BRL (R$). Required when amortization_type is present_amount. | 15,2 |
discount_amount | float | Discount 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
| Field | Description |
|---|---|
only_interest_discount | Validates 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
| Field | Description |
|---|---|
bank_slip | Payment via bank slip (generates bank slip and Pix) |
pix | Payment via Pix (generates Pix only) |
manual | Manual payment (does not generate a payment method) |
Amortization Type Enumerators
| Field | Description |
|---|---|
| installment_payment | Renegotiation for payment of specific installments. Requires the installment_key of each installment. |
| overdue_installment_payment | Renegotiation targeted at overdue installment payment. Requires the installment_key of each installment. |
| present_amount | Renegotiation with per-installment present value composition. In each item of installments[], installment_key, paid_amount and discount_amount are required. |
Response
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"
}
}
}
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
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.