---
updatedAt: 2026-06-17T17:50:44.000Z
---

Fetch the complete documentation index at: https://developers.pismo.io/pismo-docs/llms.txt. Use this file to discover all available pages before exploring further. Append .md to any documentation page URL to get its markdown version.

# Update account interest

Apply specific interest accrual options to an account by replacing its full interest
configuration.

This operation has full-replacement semantics: every request must redeclare the complete
configuration. Partial updates (sending only the fields you want to change) are not
supported and cause the validation to fail.

Although every property in the request body is independently optional, the body as a
whole must satisfy several conditional rules. See the request body schema description
for the full set of `benchmark`/`fixed_interest_rate`,
`tax_withholding`, and `taxes_exemption` rules.


# OpenAPI definition

```json
{
  "openapi": "3.1.0",
  "info": {
    "title": "Banking - Interest engine",
    "version": "1.0.0",
    "description": "API to handle interest-bearing account operations",
    "termsOfService": "https://developers.pismo.io/terms/",
    "contact": {
      "name": "API Support",
      "url": "https://developers.pismolabs.io/pismo-docs/docs/support"
    },
    "license": {
      "name": "Copyright Pismo"
    }
  },
  "servers": [
    {
      "url": "https://sandbox.pismolabs.io/interest-engine",
      "description": "Sandbox API server for testing"
    },
    {
      "url": "https://sandbox.pismolabs.io/passport/v2/s2s/access-token",
      "description": "Sandbox API for oauth2"
    }
  ],
  "tags": [
    {
      "name": "Account interest",
      "description": "Manage account interest"
    }
  ],
  "components": {
    "parameters": {
      "AccountId": {
        "name": "accountId",
        "in": "path",
        "description": "Account ID",
        "required": true,
        "example": "8080",
        "schema": {
          "type": "string"
        }
      }
    },
    "schemas": {
      "Amount": {
        "type": "number",
        "format": "double",
        "description": "Amount in the `interest_by_tier`",
        "example": 1000
      },
      "Benchmark": {
        "type": "string",
        "description": "Market index used to measure interest value over time. For fixed interest, this field must be null.\n  - `BOE`: Bank of England, UK\n  - `DI`: Interbank Deposit Contract, Brazil\n  - `FED`: Federal Reserve System, USA\n  - `RBA`: Reserve Bank of Australia\n  - `RBI`: Reserve Bank of India\n  - `TO`: Overnight Interbank Target Rate (Tasa Objetivo), Mexico\n",
        "enum": [
          "BOE",
          "DI",
          "FED",
          "RBA",
          "RBI",
          "TO"
        ],
        "example": "FED"
      },
      "CapitalizationFrequency": {
        "type": "string",
        "description": "Interest payout frequency",
        "enum": [
          "DAILY",
          "MONTHLY",
          "QUARTERLY",
          "HALF_YEARLY",
          "YEARLY",
          "MATURITY"
        ],
        "example": "DAILY"
      },
      "Days": {
        "type": "integer",
        "format": "int32",
        "description": "Number of days in `interest_by_tier`",
        "example": 30
      },
      "FeeProcessingCode": {
        "type": "string",
        "format": "number",
        "description": "Processing code configured in the [fee model](https://developers.pismo.io/pismo-docs/docs/fee-model) for charging a tax, penalty, or fee.",
        "example": "001100"
      },
      "TaxesExemption": {
        "type": "boolean",
        "description": "Is the account exempt from taxes?",
        "example": true
      },
      "WithholdingMoment": {
        "type": "string",
        "description": "Moment at which tax is withheld. When omitted, no withholding applies.",
        "enum": [
          "ACCRUAL",
          "CAPITALIZATION"
        ],
        "example": "ACCRUAL"
      },
      "TaxRule": {
        "type": "object",
        "description": "A single tax rule applied within a tax withholding configuration.",
        "required": [
          "description",
          "fixed_percentage"
        ],
        "properties": {
          "description": {
            "type": "string",
            "maxLength": 128,
            "description": "Description of the tax rule.",
            "example": "IOF"
          },
          "fixed_percentage": {
            "type": "number",
            "description": "Fixed percentage applied by the tax rule.",
            "example": 0.0038
          },
          "threshold_amount": {
            "type": "number",
            "description": "Amount threshold above which the tax rule applies.",
            "example": 1000
          }
        }
      },
      "TaxWithholding": {
        "type": "object",
        "description": "Tax withholding configuration. Replaces the standalone `fee_processing_code` field.\nConditional rules enforced at creation/update time:\n- `ACCRUAL`: `fee_processing_code` is required; `tax_rules` must be omitted.\n- `CAPITALIZATION`: `tax_rules` is required; `fee_processing_code` must be omitted.\n- Omitted `withholding_moment`: both `fee_processing_code` and `tax_rules` must be omitted.\nIn GET responses, legacy plans that predate this field may return `fee_processing_code` with a null `withholding_moment`.\n",
        "required": [
          "withholding_moment"
        ],
        "properties": {
          "withholding_moment": {
            "$ref": "#/components/schemas/WithholdingMoment"
          },
          "fee_processing_code": {
            "$ref": "#/components/schemas/FeeProcessingCode"
          },
          "tax_rules": {
            "type": "array",
            "maxItems": 100,
            "items": {
              "$ref": "#/components/schemas/TaxRule"
            }
          }
        }
      },
      "FixedInterestRate": {
        "type": "number",
        "format": "float",
        "description": "Fixed annual interest rate for investments or deposits. If a `benchmark` value is provided, this field must be `null`. Otherwise, this field is required.",
        "example": 0.1
      },
      "InterestAccountRequest": {
        "title": "Interest account request",
        "type": "object",
        "description": "Request body for `PUT /v1/interest/account/{accountId}`. The endpoint replaces the full\ninterest configuration of the account, partial updates are not supported. Every request\nmust redeclare a complete configuration that satisfies the rules below.\n\nInterest type. Exactly one of the two paths must be chosen:\n- **Benchmark-indexed rate:** If you pass `benchmark` and `margin_rate`., then `margin` is optional.\n  `fixed_interest_rate` must be omitted.\n- **Fixed rate:** If you pass `fixed_interest_rate`, then `benchmark`, `margin_rate`, and `margin`\n  must all be omitted.\n\nPassing neither `benchmark` nor `fixed_interest_rate` returns `400 Bad Request` with\n`fixed_interest_rate must be provided`. Passing both returns `400 Bad Request` with\n`fixed_interest_rate is not allowed when benchmark is passed`.\n\n**Tax-withholding rule**: Driven by `tax_withholding.withholding_moment`:\n- When `withholding_moment` is `ACCRUAL`, `fee_processing_code` is required and `tax_rules` must be omitted.\n- When `withholding_moment` is `CAPITALIZATION`, `tax_rules` is required and `fee_processing_code` must be omitted.\n- When `tax_withholding` is omitted, no withholding is configured.\n\n**Tax-exemption rule**: When `taxes_exemption` is `true`, `tax_withholding` must be null.\nWhen `taxes_exemption` is `false` or omitted, `tax_withholding` follows the rule above.\n\nNumeric fields (`fixed_interest_rate`, `margin_rate`) must have a positive value.\n`tax_withholding.fee_processing_code` is limited to 128 characters.\n",
        "properties": {
          "benchmark": {
            "$ref": "#/components/schemas/Benchmark"
          },
          "fixed_interest_rate": {
            "$ref": "#/components/schemas/FixedInterestRate"
          },
          "margin_rate": {
            "$ref": "#/components/schemas/MarginRate"
          },
          "margin": {
            "$ref": "#/components/schemas/Margin"
          },
          "taxes_exemption": {
            "type": "boolean",
            "description": "When true, the account is exempt from tax withholding and `tax_withholding` must be null."
          },
          "tax_withholding": {
            "$ref": "#/components/schemas/TaxWithholding"
          },
          "interest_by_tiers": {
            "$ref": "#/components/schemas/InterestByTiers"
          },
          "capitalization_frequency": {
            "$ref": "#/components/schemas/CapitalizationFrequency",
            "description": "Optional account-level capitalization frequency. When provided with a valid value, it overrides the capitalization frequency configured in the associated interest plan. If omitted or sent as null, the current account-level value remains unchanged. If there is no existing account-level value, then the associated interest plan value is used during processing."
          }
        },
        "example": {
          "benchmark": "FED",
          "margin_rate": 1.3,
          "margin": 0.05,
          "tax_withholding": {
            "withholding_moment": "ACCRUAL",
            "fee_processing_code": "001100"
          }
        }
      },
      "InterestAccountResponse": {
        "title": "Interest account response",
        "type": "object",
        "properties": {
          "benchmark": {
            "$ref": "#/components/schemas/Benchmark"
          },
          "fixed_interest_rate": {
            "$ref": "#/components/schemas/FixedInterestRate"
          },
          "margin_rate": {
            "$ref": "#/components/schemas/MarginRate"
          },
          "margin": {
            "$ref": "#/components/schemas/Margin"
          },
          "tax_withholding": {
            "$ref": "#/components/schemas/TaxWithholding"
          },
          "taxes_exemption": {
            "$ref": "#/components/schemas/TaxesExemption"
          },
          "interest_by_tiers": {
            "$ref": "#/components/schemas/InterestByTiers"
          },
          "capitalization_frequency": {
            "$ref": "#/components/schemas/CapitalizationFrequency"
          }
        }
      },
      "InterestByTiers": {
        "type": "object",
        "properties": {
          "type": {
            "$ref": "#/components/schemas/InterestByTiersType"
          },
          "tier_calculation": {
            "$ref": "#/components/schemas/TierCalculation"
          },
          "tiers": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/InterestByTiersArrayObject"
            }
          }
        },
        "required": [
          "type",
          "tier_calculation",
          "tiers"
        ],
        "description": "Interest by tiers configuration",
        "example": {
          "type": "TERM",
          "tier_calculation": "RETROACTIVE",
          "tiers": [
            {
              "days": 30,
              "amount": 1000,
              "margin_rate": 1,
              "fixed_interest_rate": 1.2
            },
            {
              "days": 60,
              "amount": 2000,
              "margin_rate": 1,
              "fixed_interest_rate": 1.3
            }
          ]
        }
      },
      "InterestByTiersArrayObject": {
        "type": "object",
        "properties": {
          "days": {
            "$ref": "#/components/schemas/Days"
          },
          "amount": {
            "$ref": "#/components/schemas/Amount"
          },
          "margin_rate": {
            "$ref": "#/components/schemas/MarginRate"
          },
          "fixed_interest_rate": {
            "$ref": "#/components/schemas/FixedInterestRate"
          }
        },
        "description": "Tier details for interest calculation"
      },
      "InterestByTiersType": {
        "type": "string",
        "description": "Interest type\n- `TERM`: Interest rate varies according to the period of time since the deposit was made.\n- `AMOUNT`: Interest rate varies according to the current balance.\n",
        "enum": [
          "TERM",
          "AMOUNT"
        ],
        "example": "TERM"
      },
      "Margin": {
        "type": "number",
        "format": "double",
        "description": "Also known as a spread, this is an incremental rate the clients receive on investments or deposits.\nIf a `benchmark` value is provided, this field is optional.\nIf `benchmark` is null, this field must be null also.\n",
        "example": 0.02
      },
      "MarginRate": {
        "type": "number",
        "format": "double",
        "description": "Rate linked to the benchmark rate. For example, for 110% FED, margin rate is 110%. If a `benchmark` value is not provided, this field must be `null`. Otherwise, this field is required.",
        "example": 1.1
      },
      "TierCalculation": {
        "type": "string",
        "description": "Tier calculation method\n- `RETROACTIVE`: Interest is recalculated from the beginning based on the new applicable rate.\n- `NON-RETROACTIVE`: Interest is calculated progressively based on each layer rate.\n",
        "enum": [
          "RETROACTIVE",
          "NON-RETROACTIVE"
        ],
        "example": "RETROACTIVE"
      },
      "ErrorResponse": {
        "type": "object",
        "description": "Standard error payload generated by the global exception handler.\n`message` is a single string for most errors and an array of strings\nwhen multiple bean-validation or request-binding errors occur in the same request.\n",
        "additionalProperties": false,
        "required": [
          "message"
        ],
        "properties": {
          "message": {
            "oneOf": [
              {
                "type": "string"
              },
              {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            ]
          }
        },
        "example": {
          "message": "interest account not found"
        }
      },
      "ErrorResponseDeserialization": {
        "type": "object",
        "description": "Error payload generated only when the request body fails JSON deserialization\n(unknown field or invalid JSON structure). Returned with HTTP 400.\n",
        "additionalProperties": false,
        "required": [
          "error",
          "status"
        ],
        "properties": {
          "error": {
            "type": "string",
            "description": "Short error category."
          },
          "message": {
            "type": "string",
            "description": "Details about the field or structure that causes the error."
          },
          "field": {
            "type": "string",
            "description": "Name of the invalid field. Present only for unknown-field errors."
          },
          "status": {
            "type": "integer",
            "description": "HTTP status code, always 400 for this shape."
          }
        },
        "example": {
          "error": "Invalid field in request",
          "message": "Field 'foo' is not allowed. Only the following fields can be updated: start_date, description, fixed_interest_rate, margin_rate, margin, interest_by_tiers, interest_thresholds",
          "field": "foo",
          "status": 400
        }
      }
    },
    "securitySchemes": {
      "BearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "JWT"
      }
    },
    "responses": {
      "400BadRequest": {
        "description": "Bad request",
        "content": {
          "application/json": {
            "schema": {
              "anyOf": [
                {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                {
                  "$ref": "#/components/schemas/ErrorResponseDeserialization"
                }
              ]
            },
            "examples": {
              "validation": {
                "summary": "Bean validation or binding errors",
                "value": {
                  "message": [
                    "fixed_interest_rate must be informed",
                    "margin_rate must be positive"
                  ]
                }
              },
              "requestBody": {
                "summary": "invalid or missing request value",
                "value": {
                  "message": "Failed to process your request. Validate the fields in your request."
                }
              },
              "tenantHeader": {
                "summary": "Tenant header missing or malformed",
                "value": {
                  "message": "x-tenant header is missing or malformed"
                }
              },
              "unknownField": {
                "summary": "Unknown field in request body",
                "value": {
                  "error": "Invalid field in request",
                  "message": "Field 'foo' is not allowed. Only the following fields can be updated: start_date, description, fixed_interest_rate, margin_rate, margin, interest_by_tiers, interest_thresholds",
                  "field": "foo",
                  "status": 400
                }
              },
              "invalidJson": {
                "summary": "Invalid JSON body",
                "value": {
                  "error": "Invalid JSON format",
                  "message": "Request contains invalid JSON structure or field types",
                  "status": 400
                }
              },
              "taxWithholdingAccrualFeeRequired": {
                "summary": "ACCRUAL withholding without fee_processing_code",
                "value": {
                  "message": [
                    "fee_processing_code is required when tax_withholding.withholding_moment is ACCRUAL."
                  ]
                }
              },
              "taxWithholdingAccrualTaxRulesNotAllowed": {
                "summary": "ACCRUAL withholding with tax_rules present",
                "value": {
                  "message": [
                    "tax_rules must be null when tax_withholding.withholding_moment is ACCRUAL."
                  ]
                }
              },
              "taxWithholdingCapitalizationFeeNotAllowed": {
                "summary": "CAPITALIZATION withholding with fee_processing_code present",
                "value": {
                  "message": [
                    "fee_processing_code must be null when tax_withholding.withholding_moment is CAPITALIZATION."
                  ]
                }
              },
              "taxWithholdingCapitalizationTaxRulesRequired": {
                "summary": "CAPITALIZATION withholding without tax_rules",
                "value": {
                  "message": [
                    "tax_rules is required when tax_withholding.withholding_moment is CAPITALIZATION."
                  ]
                }
              },
              "taxWithholdingNoneFieldsNotAllowed": {
                "summary": "NULL withholding_moment with fee_processing_code or tax_rules present",
                "value": {
                  "message": [
                    "fee_processing_code and tax_rules must be null when tax_withholding.withholding_moment is NULL."
                  ]
                }
              },
              "taxWithholdingNotAllowedWhenTaxesExemption": {
                "summary": "taxes_exemption is true with tax_withholding present",
                "value": {
                  "message": [
                    "tax_withholding must be null when taxes_exemption is true."
                  ]
                }
              }
            }
          }
        }
      },
      "401Unauthorized": {
        "description": "Unauthorized. The response body is produced by the upstream authentication gateway and is not defined by this service."
      },
      "404NotFound": {
        "description": "Not found",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            },
            "examples": {
              "interestAccountNotFound": {
                "summary": "Interest account not found",
                "value": {
                  "message": "interest account not found"
                }
              },
              "interestPlanNotFound": {
                "summary": "Interest plan not found",
                "value": {
                  "message": "interest plan not found"
                }
              },
              "benchmarkNotFound": {
                "summary": "Benchmark not found",
                "value": {
                  "message": "benchmark not found"
                }
              }
            }
          }
        }
      },
      "500InternalServerError": {
        "description": "Internal server error",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            },
            "example": {
              "message": "Failed to process your request"
            }
          }
        }
      }
    }
  },
  "security": [
    {
      "BearerAuth": []
    }
  ],
  "paths": {
    "/v1/interest/account/{accountId}": {
      "put": {
        "summary": "Update account interest",
        "description": "Apply specific interest accrual options to an account by replacing its full interest\nconfiguration.\n\nThis operation has full-replacement semantics: every request must redeclare the complete\nconfiguration. Partial updates (sending only the fields you want to change) are not\nsupported and cause the validation to fail.\n\nAlthough every property in the request body is independently optional, the body as a\nwhole must satisfy several conditional rules. See the request body schema description\nfor the full set of `benchmark`/`fixed_interest_rate`,\n`tax_withholding`, and `taxes_exemption` rules.\n",
        "tags": [
          "Account interest"
        ],
        "operationId": "put-v1-interest-account",
        "parameters": [
          {
            "$ref": "#/components/parameters/AccountId"
          }
        ],
        "requestBody": {
          "description": "Full interest configuration for the account. See the schema description for the\nconditional required-field rules in `benchmark`, `fixed_interest_rate`,\n`margin_rate`, `margin`, `tax_withholding`, and `taxes_exemption`.\n",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/InterestAccountRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InterestAccountResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/400BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/401Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/404NotFound"
          },
          "500": {
            "$ref": "#/components/responses/500InternalServerError"
          }
        }
      }
    }
  }
}
```