Skip to content

Amounts

Every financial event carries one principal amount in amount. Invoices and settlements also say how that amount is made up — subtotal and tax, gross and fees — in amountBreakdown. This guide explains how to choose the principal amount, how to build the breakdown, and which amount types each financial type accepts.

amount, together with currencyCode and isNegative, is the event’s principal amount:

  • It is the amount that reconciles. Reconciliation compares the principal amount of each event and nothing else. The breakdown is never used for matching.
  • You decide which figure it is. TreasuryHub does not derive it from the breakdown, and does not check that the components add up to it. Choose one convention per financial type and keep it: every match, report and later process uses the figure you send.
  • It is always greater than 0. The direction goes in isNegative. amount: 0 returns 400 ERR-3005 (only ACCOUNT_BALANCE accepts zero).
TypeSuggested amountWhy
SALE_INVOICE, SALE_INVOICE_LINETotal: what the customer has to pay (subtotal + tax − discount − withholding)The customer’s payment carries the total, so it is the figure the payment matches against.
PSP_SETTLEMENTNet: what the PSP deposits (gross − fees and their tax − holds − refunds + released holds)The deposit on the bank statement carries the net, so it is the figure the BANK_MOVEMENT matches against.

The choice matters most for invoices. If you later use them to drive payments — for example, in a payment dispersion — the amount that moves is the principal amount, so it must be what is actually paid: the total. With the subtotal as principal, every invoice would fall short by its tax. Changing the convention later means sending the events already loaded again.

amountBreakdown lists the components that make up amount, for reporting. It is required for SALE_INVOICE, SALE_INVOICE_LINE and PSP_SETTLEMENT.

FieldTypeDescription
amountTypestringCode of the component. Must be allowed for the event’s type (see the table below).
currencyCodestringISO 4217 currency code of the component. Usually the event’s currencyCode.
amountnumberAmount of the component. Always greater than 0.
isNegativebooleantrue when the component subtracts from the principal (a deduction), false when it adds to it.

Never include the principal itself. The net (or the total) is amount; there is no NET amount type. The breakdown only carries the parts the principal is made of.

The breakdown is not the same as multiCurrencyAmounts: that list is the same amount expressed in other currencies, while the breakdown is the parts the amount is made of.

RuleError
amountType is allowed for the event’s typeERR-3047 AmountTypeNotAllowed
Each amountType + currencyCode pair appears at most onceERR-3048 AmountBreakdownDuplicate
Each component’s amount is greater than 0 (the sign goes in isNegative)ERR-3049 AmountBreakdownAmountMustBePositive
Each component’s currencyCode is a valid ISO 4217 codeERR-3050 InvalidAmountBreakdownCurrencyCode

Each failure names the offending item in errors[].field: AmountBreakdown[<index>].AmountType, .Amount or .CurrencyCode, and AmountBreakdown[<index>] for a duplicate. See Error Handling.

TreasuryHub does not check that the components add up to amount, nor that their currency matches multiCurrencyAmounts. Keeping the breakdown consistent with the principal is your responsibility: reports read the components exactly as you send them.

Each financial type accepts its own amount types. A deduction subtracts from the principal and is sent with isNegative: true.

TypeamountTypeMeaningDeduction
PSP_SETTLEMENTGROSSTotal of the payments the settlement covers, before any deduction—
FEECommission the PSP kept✓
FEE_TAXTax on the PSP’s commission (for example, VAT on the fee)✓
DISPUTE_HOLDAmount the PSP held back for disputes or chargebacks✓
REFUND_DISCOUNTRefunds the PSP deducted from the settlement✓
RELEASED_HOLDAmount held in an earlier settlement and released in this one—
SALE_INVOICE, SALE_INVOICE_LINESUBTOTALAmount before taxes and discounts—
TAXTaxes charged on the invoice (for example, VAT)—
DISCOUNTDiscount granted to the customer✓
WITHHOLDINGTaxes the customer withholds (for example, withheld income tax or VAT)✓

FEE_TAX is kept apart from TAX on purpose: the tax a PSP charges on its fee and the tax on an invoice are different concepts, and reports keep them apart.

Every other financial type has no amount type enabled yet: any breakdown item sent for it returns ERR-3047, so omit the field. New amount types can be enabled for a type without an API change — when you read events, treat an unknown amountType as valid.

  • amount is always positive, in the event and in every component. The direction goes in isNegative.
  • Deductions (✓ in the table) are sent with isNegative: true; the other components with isNegative: false. A fee travels as "amount": 387.93, "isNegative": true — never as -387.93.
  • If a component goes against its usual direction (for example, a fee the PSP gives back), flip isNegative for that item.
  • The components then add up to the principal: amount = sum of the items with isNegative: false − sum of the items with isNegative: true.

The PSP collected 10,500.00 MXN, kept a 387.93 fee plus 62.07 of tax on it, and deposited the rest. The principal amount is the net deposited:

GROSS − FEE − FEE_TAX = 10500.00 − 387.93 − 62.07 = 10050.00 = amount

{
"externalId": "STL-2026-10-15-0001",
"type": "PSP_SETTLEMENT",
"countryCode": "MX",
"currencyCode": "MXN",
"amount": 10050.00,
"isNegative": false,
"status": "BOOKED",
"amountBreakdown": [
{ "amountType": "GROSS", "currencyCode": "MXN", "amount": 10500.00, "isNegative": false },
{ "amountType": "FEE", "currencyCode": "MXN", "amount": 387.93, "isNegative": true },
{ "amountType": "FEE_TAX", "currencyCode": "MXN", "amount": 62.07, "isNegative": true }
],
"payload": {
"partnerIdentifier": "PSP-001",
"partnerName": "Pasarela de Pagos MX",
"settlementDate": "2026-10-15",
"periodFrom": "2026-10-08",
"periodTo": "2026-10-14",
"payoutReference": "PO-20261015-8841",
"transactionCount": 42
}
}

The settlement’s own id is the event’s externalId. The PSP_PAYIN events it pays out reference it in their relatedIds.

Two units at 500.00, a 50.00 discount, and 16% VAT on the discounted subtotal. The principal amount is the line total:

SUBTOTAL + TAX − DISCOUNT = 1000.00 + 152.00 − 50.00 = 1102.00 = amount

{
"externalId": "INV-A-10234-L1",
"type": "SALE_INVOICE_LINE",
"countryCode": "MX",
"currencyCode": "MXN",
"amount": 1102.00,
"isNegative": false,
"status": "BOOKED",
"amountBreakdown": [
{ "amountType": "SUBTOTAL", "currencyCode": "MXN", "amount": 1000.00, "isNegative": false },
{ "amountType": "TAX", "currencyCode": "MXN", "amount": 152.00, "isNegative": false },
{ "amountType": "DISCOUNT", "currencyCode": "MXN", "amount": 50.00, "isNegative": true }
],
"payload": {
"invoiceNumber": "A-10234",
"customerIdentifier": "CUST-0042",
"customerName": "Comercializadora del Norte SA de CV",
"customerTaxId": "CNO010101AB1",
"lineNumber": 1,
"productCode": "SKU-7781",
"description": "Licencia anual de software",
"quantity": 2,
"unitPrice": 500.00,
"taxRate": 16
}
}

quantity, unitPrice and taxRate describe the line; they are not amounts. The amounts that make up the line go in amountBreakdown.

On PUT /api/h2h/ingestion/financial-events/{id}, amountBreakdown is updated as a whole:

  • Present: it replaces every component the event had. Send all of them, not only the ones that changed. An empty array ([]) clears the breakdown.
  • Omitted or null: the breakdown is left untouched.

When you read the event back (GET), amountBreakdown is null if the event never carried a breakdown, and [] if a PUT cleared it.

The new breakdown is validated against the stored event’s type, with the same rules as on create. An amountType not allowed for that type returns ERR-3047 as a single error, without an errors array; the other breakdown errors come inside errors, as on create. TreasuryHub does not recompute amount: if the components change the principal, send the new amount in the same request. Each successful PUT creates a new version of the event.

For example, the PSP later held 500.00 of the settlement above for a dispute:

{
"amount": 9550.00,
"amountBreakdown": [
{ "amountType": "GROSS", "currencyCode": "MXN", "amount": 10500.00, "isNegative": false },
{ "amountType": "FEE", "currencyCode": "MXN", "amount": 387.93, "isNegative": true },
{ "amountType": "FEE_TAX", "currencyCode": "MXN", "amount": 62.07, "isNegative": true },
{ "amountType": "DISPUTE_HOLD", "currencyCode": "MXN", "amount": 500.00, "isNegative": true }
]
}

See Error Handling for the error codes, and the Financial Events API reference for the full schemas.

Todo evento financiero lleva un único monto principal en amount. Las facturas y los settlements además indican cómo se compone ese monto —subtotal e impuestos, bruto y comisiones— en amountBreakdown. Esta guía explica cómo elegir el monto principal, cómo armar el desglose y qué tipos de monto acepta cada tipo financiero.

amount, junto con currencyCode e isNegative, es el monto principal del evento:

  • Es el monto que concilia. La conciliación compara el monto principal de cada evento y nada más. El desglose nunca se usa para el matching.
  • Tú decides qué cifra es. TreasuryHub no lo deriva del desglose ni verifica que los componentes sumen ese monto. Elige una convención por tipo financiero y mantenla: cada match, reporte y proceso posterior usa la cifra que envías.
  • Siempre es mayor que 0. El sentido va en isNegative. amount: 0 devuelve 400 ERR-3005 (solo ACCOUNT_BALANCE acepta cero).
Tipoamount sugeridoPor qué
SALE_INVOICE, SALE_INVOICE_LINETotal: lo que el cliente tiene que pagar (subtotal + impuestos − descuento − retenciones)El pago del cliente llega por el total, así que es la cifra contra la que concilia el pago.
PSP_SETTLEMENTNeto: lo que deposita el PSP (bruto − comisiones y su impuesto − retenciones por disputas − reembolsos + liberaciones)El depósito en el extracto bancario llega por el neto, así que es la cifra contra la que concilia el BANK_MOVEMENT.

La elección importa sobre todo en las facturas. Si más adelante las usas para mover pagos —por ejemplo, en una dispersión de pagos—, el monto que se mueve es el principal: tiene que ser lo que realmente se paga, el total. Con el subtotal como principal, a cada factura le faltarían sus impuestos. Cambiar la convención después implica volver a enviar los eventos ya cargados.

amountBreakdown lista los componentes que forman amount, para reporting. Es obligatorio en SALE_INVOICE, SALE_INVOICE_LINE y PSP_SETTLEMENT.

CampoTipoDescripción
amountTypestringCódigo del componente. Debe estar permitido para el type del evento (ver la tabla más abajo).
currencyCodestringCódigo de moneda ISO 4217 del componente. Normalmente el currencyCode del evento.
amountnumberMonto del componente. Siempre mayor que 0.
isNegativebooleantrue cuando el componente resta del principal (una deducción), false cuando suma.

Nunca incluyas el principal. El neto (o el total) es amount; no existe el tipo de monto NET. El desglose solo lleva las partes que forman el principal.

El desglose no es lo mismo que multiCurrencyAmounts: esa lista es el mismo monto expresado en otras monedas, mientras que el desglose son las partes que forman el monto.

ReglaError
amountType está permitido para el type del eventoERR-3047 AmountTypeNotAllowed
Cada par amountType + currencyCode aparece como máximo una vezERR-3048 AmountBreakdownDuplicate
El amount de cada componente es mayor que 0 (el signo va en isNegative)ERR-3049 AmountBreakdownAmountMustBePositive
El currencyCode de cada componente es un código ISO 4217 válidoERR-3050 InvalidAmountBreakdownCurrencyCode

Cada fallo señala el componente con el problema en errors[].field: AmountBreakdown[<índice>].AmountType, .Amount o .CurrencyCode, y AmountBreakdown[<índice>] para un duplicado. Consulta Manejo de Errores.

TreasuryHub no verifica que los componentes sumen amount, ni que su moneda coincida con multiCurrencyAmounts. Mantener el desglose coherente con el principal es tu responsabilidad: los reportes leen los componentes tal como los envías.

Cada tipo financiero acepta sus propios tipos de monto. Una deducción resta del principal y se envía con isNegative: true.

TipoamountTypeSignificadoDeducción
PSP_SETTLEMENTGROSSTotal de los pagos que cubre el settlement, antes de cualquier deducción—
FEEComisión que se quedó el PSP✓
FEE_TAXImpuesto sobre la comisión del PSP (por ejemplo, el IVA de la comisión)✓
DISPUTE_HOLDMonto que el PSP retuvo por disputas o contracargos✓
REFUND_DISCOUNTReembolsos que el PSP descontó del settlement✓
RELEASED_HOLDMonto retenido en un settlement anterior y liberado en este—
SALE_INVOICE, SALE_INVOICE_LINESUBTOTALMonto antes de impuestos y descuentos—
TAXImpuestos cobrados en la factura (por ejemplo, IVA)—
DISCOUNTDescuento otorgado al cliente✓
WITHHOLDINGImpuestos que retiene el cliente (por ejemplo, ISR o IVA retenido)✓

FEE_TAX está separado de TAX a propósito: el impuesto que cobra un PSP sobre su comisión y el impuesto de una factura son conceptos distintos, y los reportes los mantienen separados.

El resto de los tipos financieros todavía no tiene tipos de monto habilitados: cualquier componente que se envíe para ellos devuelve ERR-3047, así que omite el campo. Se pueden habilitar tipos de monto nuevos para un tipo sin cambios en la API: cuando leas eventos, trata un amountType desconocido como válido.

  • amount siempre es positivo, en el evento y en cada componente. El sentido va en isNegative.
  • Las deducciones (✓ en la tabla) se envían con isNegative: true; el resto de los componentes con isNegative: false. Una comisión viaja como "amount": 387.93, "isNegative": true, nunca como -387.93.
  • Si un componente va en contra de su sentido habitual (por ejemplo, una comisión que el PSP devuelve), invierte isNegative en ese componente.
  • Así los componentes suman el principal: amount = suma de los componentes con isNegative: false − suma de los componentes con isNegative: true.

El PSP cobró 10,500.00 MXN, se quedó una comisión de 387.93 más 62.07 de impuesto sobre ella, y depositó el resto. El monto principal es el neto depositado:

GROSS − FEE − FEE_TAX = 10500.00 − 387.93 − 62.07 = 10050.00 = amount

{
"externalId": "STL-2026-10-15-0001",
"type": "PSP_SETTLEMENT",
"countryCode": "MX",
"currencyCode": "MXN",
"amount": 10050.00,
"isNegative": false,
"status": "BOOKED",
"amountBreakdown": [
{ "amountType": "GROSS", "currencyCode": "MXN", "amount": 10500.00, "isNegative": false },
{ "amountType": "FEE", "currencyCode": "MXN", "amount": 387.93, "isNegative": true },
{ "amountType": "FEE_TAX", "currencyCode": "MXN", "amount": 62.07, "isNegative": true }
],
"payload": {
"partnerIdentifier": "PSP-001",
"partnerName": "Pasarela de Pagos MX",
"settlementDate": "2026-10-15",
"periodFrom": "2026-10-08",
"periodTo": "2026-10-14",
"payoutReference": "PO-20261015-8841",
"transactionCount": 42
}
}

El id del settlement es el externalId del evento. Los eventos PSP_PAYIN que liquida lo referencian en sus relatedIds.

Dos unidades a 500.00, un descuento de 50.00 e IVA del 16% sobre el subtotal con descuento. El monto principal es el total de la línea:

SUBTOTAL + TAX − DISCOUNT = 1000.00 + 152.00 − 50.00 = 1102.00 = amount

{
"externalId": "INV-A-10234-L1",
"type": "SALE_INVOICE_LINE",
"countryCode": "MX",
"currencyCode": "MXN",
"amount": 1102.00,
"isNegative": false,
"status": "BOOKED",
"amountBreakdown": [
{ "amountType": "SUBTOTAL", "currencyCode": "MXN", "amount": 1000.00, "isNegative": false },
{ "amountType": "TAX", "currencyCode": "MXN", "amount": 152.00, "isNegative": false },
{ "amountType": "DISCOUNT", "currencyCode": "MXN", "amount": 50.00, "isNegative": true }
],
"payload": {
"invoiceNumber": "A-10234",
"customerIdentifier": "CUST-0042",
"customerName": "Comercializadora del Norte SA de CV",
"customerTaxId": "CNO010101AB1",
"lineNumber": 1,
"productCode": "SKU-7781",
"description": "Licencia anual de software",
"quantity": 2,
"unitPrice": 500.00,
"taxRate": 16
}
}

quantity, unitPrice y taxRate describen la línea; no son montos. Los montos que forman la línea van en amountBreakdown.

En PUT /api/h2h/ingestion/financial-events/{id}, amountBreakdown se actualiza completo:

  • Presente: reemplaza todos los componentes que tenía el evento. Envíalos todos, no solo los que cambiaron. Un array vacío ([]) borra el desglose.
  • Omitido o null: el desglose no se toca.

Al volver a leer el evento (GET), amountBreakdown es null si el evento nunca llevó desglose, y [] si un PUT lo borró.

El nuevo desglose se valida contra el type del evento almacenado, con las mismas reglas que en la creación. Un amountType no permitido para ese tipo devuelve ERR-3047 como error simple, sin array errors; el resto de los errores del desglose llegan dentro de errors, como en la creación. TreasuryHub no recalcula amount: si los componentes cambian el principal, envía el nuevo amount en la misma solicitud. Cada PUT exitoso crea una nueva versión del evento.

Por ejemplo, el PSP retuvo después 500.00 del settlement anterior por una disputa:

{
"amount": 9550.00,
"amountBreakdown": [
{ "amountType": "GROSS", "currencyCode": "MXN", "amount": 10500.00, "isNegative": false },
{ "amountType": "FEE", "currencyCode": "MXN", "amount": 387.93, "isNegative": true },
{ "amountType": "FEE_TAX", "currencyCode": "MXN", "amount": 62.07, "isNegative": true },
{ "amountType": "DISPUTE_HOLD", "currencyCode": "MXN", "amount": 500.00, "isNegative": true }
]
}

Consulta Manejo de Errores para los códigos de error, y la referencia de la API de Financial Events para los esquemas completos.