> For the complete documentation index, see [llms.txt](https://docs.nexusglobalpayments.org/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.nexusglobalpayments.org/nexus-payments-apis/fees-and-amounts.md).

# Fees And Amounts

APIs for a Source PSP acting as its own FX Provider to either have settlement amounts and fees computed on its behalf, or retrieve the fee formula for independent computation.

## Get Fees and Interbank Settlement Amounts

> Retrieves the various fees and amounts based on specified parameters. Information can be used in the pacs.008 payment instruction.\
> \
> \---\
> \
> \#### Response validation rules\
> \
> \*\*200 OK\*\* — the body MUST conform to the response schema below. Response objects are open: additional properties may be introduced in later minor versions, and clients MUST ignore properties they do not recognise.\
> \
> \| Field | Type | Presence | Nullable | Constraints |\
> \|---|---|---|---|---|\
> \| \`debtorAgent\` | object | Required | N | — |\
> \| \`debtorAgent.interbankSettlementAmount\` | object | Required | N | — |\
> \| \`debtorAgent.interbankSettlementAmount.amount\` | number | Required | N | ≥ 0; > 0 |\
> \| \`debtorAgent.interbankSettlementAmount.currency\` | string | Required | N | pattern \`^\[A-Z]{3}$\`; length 3 |\
> \| \`creditorAgent\` | object | Required | N | — |\
> \| \`creditorAgent.interbankSettlementAmount\` | object | Required | N | — |\
> \| \`creditorAgent.interbankSettlementAmount.amount\` | number | Required | N | ≥ 0; > 0 |\
> \| \`creditorAgent.interbankSettlementAmount.currency\` | string | Required | N | pattern \`^\[A-Z]{3}$\`; length 3 |\
> \| \`creditorAgent.chargesAmount\` | object | Required | N | — |\
> \| \`creditorAgent.chargesAmount.amount\` | number | Required | N | ≥ 0 |\
> \| \`creditorAgent.chargesAmount.currency\` | string | Required | N | pattern \`^\[A-Z]{3}$\`; length 3 |\
> \| \`creditorAgent.creditorAccountAmount\` | number | Required | N | ≥ 0 |\
> \
> \*\*Cross-field rules\*\*\
> \
> \- \`debtorAgent.interbankSettlementAmount.currency\` = \`sourceCurrency\` (path parameter).\
> \- \`creditorAgent.interbankSettlementAmount.currency\` = \`creditorAgent.chargesAmount.currency\` = \`destinationCurrency\` (path parameter).\
> \- \`creditorAgent.creditorAccountAmount\` = \`creditorAgent.interbankSettlementAmount.amount\` − \`creditorAgent.chargesAmount.amount\`.\
> \- The response is a stateless calculation result: it never contains \`quoteRequestId\`, \`quoteId\`, \`issuedDateTime\`, \`expiryDateTime\` or intermediary agents.\
> \- Monetary amounts are rounded to the currency's ISO 4217 minor units (decimal places from the currency's Nexus configuration) using \`ROUND\_HALF\_UP\`.\
> \
> \*\*Response signature\*\* — every 200 response carries \`Signature-Input\` and \`Signature\` and \`Content-Digest\` per the Nexus HTTP Message Signature Profile v1, signed by the responding server. The client MUST verify the response signature before using the response and MUST discard a response that fails verification.\
> \
> \*\*Error responses (4xx/5xx with a body)\*\* — the body MUST conform to \`ErrorApiResponse\`: \`statusCode\` = \`RJCT\`; \`reasonCode\` matches \`^\[A-Z]{2}\[0-9]{3}$\`; \`name\` is UPPER\_SNAKE\_CASE (≤ 50); \`description\` ≤ 500 characters and MUST NOT contain PII. \`reasonCode\` values for this operation: \`TE001\`, \`BE007\`, \`BE008\`, \`BE010\`, \`BE012\`, \`BE009\`, \`AE001\`, \`AE002\`, \`AE003\`, \`AE005\`, \`AE006\`, \`AE004\`, \`TE099\`. Gateway errors (405, 429, 502, 503, 504) carry no body.

```json
{"openapi":"3.1.0","info":{"title":"Nexus Payments API","version":"v1"},"tags":[{"name":"Fees and Amounts","description":"APIs for a Source PSP acting as its own FX Provider to either have settlement amounts and fees computed on its behalf, or retrieve the fee formula for independent computation."}],"servers":[{"url":"https://{environment}.payments.nexus.net","description":"Nexus participant-facing API endpoint. Resolved via Nexus private DNS over the established IPsec IKEv2 tunnel and not reachable from the public Internet.","variables":{"environment":{"default":"prod","enum":["pat","prod"],"description":"Deployment environment subdomain."}}}],"security":[{"mutualTLS":[],"nexusOAuth":["quote.read"]}],"components":{"securitySchemes":{"mutualTLS":{"type":"mutualTLS","description":"Mutual TLS: the IPSO presents its X.509 client certificate on every connection, validated during the TLS handshake (fail-closed). The same certificate is the RFC 8705 binding anchor for the OAuth access token (see nexusOAuth)."}},"parameters":{"SignatureInputBodyless":{"name":"Signature-Input","in":"header","required":true,"description":"RFC 9421 signature metadata for a request without a body, per the Nexus HTTP Message Signature Profile v1 (RFC 9421, RFC 9530). One dictionary member labelled `nexus` whose covered components are exactly `\"@method\" \"@authority\" \"@path\" \"@query\"`, followed by `\"if-none-match\"` when that header is sent. `@query` is always covered; an empty query serialises as `?`, so query parameters cannot be added or removed undetected. Signature parameters, emitted in this order: `created` and `expires` (Unix seconds; `expires` = `created` + 300; the receiver rejects `created` more than ±5 minutes from its clock or a signature past `expires`), `keyid` (base64url SHA-256 thumbprint of the signer's signing public key, registered at onboarding; a missing, unknown, expired or revoked key id is rejected - never resolved to a default key), `alg` (always `rsa-pss-sha512`) and `tag` (always `nexus-v1`). The signature parameters are signed through the `@signature-params` line of the signature base. A missing, malformed or non-conforming value is rejected with AE005.","schema":{"type":"string","maxLength":512,"pattern":"^nexus=\\(\"@method\" \"@authority\" \"@path\" \"@query\"( \"if-none-match\")?\\);created=[0-9]{1,15};expires=[0-9]{1,15};keyid=\"[A-Za-z0-9_-]{43}\";alg=\"rsa-pss-sha512\";tag=\"nexus-v1\"$"}},"Signature":{"name":"Signature","in":"header","required":true,"description":"RFC 9421 signature value: one dictionary member labelled `nexus` holding an RFC 8941 byte sequence - the **standard base64** (not base64url) RSASSA-PSS signature using SHA-512 (`rsa-pss-sha512`), computed over the RFC 9421 signature base built from the components and parameters declared in `Signature-Input`. Produced with the sender's own signing private key; the receiver verifies it against the sender's registered signing public key resolved from `keyid`. With the minimum RSA-3072 key the signature is 384 bytes, i.e. 512 base64 characters. A missing, malformed or non-verifying signature is rejected with AE005.","schema":{"type":"string","minLength":520,"maxLength":1400,"pattern":"^nexus=:[A-Za-z0-9+/]+={0,2}:$"}}},"schemas":{"FeesAndAmountsResponse":{"type":"object","description":"Computed debtor and creditor amounts with fees.","properties":{"debtorAgent":{"$ref":"#/components/schemas/DebtorAgentAmounts","description":"Debtor-side amounts and fees."},"creditorAgent":{"$ref":"#/components/schemas/CreditorAgentAmounts","description":"Creditor-side amounts and fees."}},"required":["creditorAgent","debtorAgent"]},"DebtorAgentAmounts":{"type":"object","description":"Debtor-side amounts.","properties":{"interbankSettlementAmount":{"allOf":[{"$ref":"#/components/schemas/AmountDto"},{"properties":{"amount":{"exclusiveMinimum":0}}}],"description":"Interbank Settlement Amount in Source Currency. Amount is strictly greater than zero."}},"required":["interbankSettlementAmount"]},"AmountDto":{"type":"object","description":"Monetary amount with currency code.","properties":{"amount":{"type":"number","description":"Monetary amount. When copied into an ISO 20022 XML amount the value must have at most 5 fractional digits and at most 18 total digits; serialise as a plain decimal, never in exponent form.","minimum":0},"currency":{"type":"string","description":"ISO-4217 currency code.","maxLength":3,"minLength":3,"pattern":"^[A-Z]{3}$"}},"required":["amount","currency"]},"CreditorAgentAmounts":{"type":"object","description":"Creditor-side amounts.","properties":{"interbankSettlementAmount":{"allOf":[{"$ref":"#/components/schemas/AmountDto"},{"properties":{"amount":{"exclusiveMinimum":0}}}],"description":"Interbank Settlement Amount in Destination Currency. Amount is strictly greater than zero."},"chargesAmount":{"$ref":"#/components/schemas/AmountDto","description":"Destination Agent Fee."},"creditorAccountAmount":{"type":"number","description":"Net amount credited to the creditor account. When copied into an ISO 20022 XML amount the value must have at most 5 fractional digits and at most 18 total digits; serialise as a plain decimal, never in exponent form.","minimum":0}},"required":["chargesAmount","creditorAccountAmount","interbankSettlementAmount"]},"ErrorApiResponse":{"type":"object","description":"Standard structured rejection body. Returned for all non-2xx responses produced by the Nexus authentication layer or the application. Gateway level errors (405, 409, 413, 429, 502, 503, 504) do NOT carry this body.\n\n#### Validation rules\n\n- All four fields are required and never `null`.\n- `statusCode`: always `RJCT`.\n- `reasonCode`: 5 characters matching `^[A-Z]{2}[0-9]{3}$`; family prefix `TE` (technical), `AE` (authentication/authorisation, enforced at authentication) or `BE` (business); one of the values enumerated in the `reasonCode` schema.\n- `name`: UPPER_SNAKE_CASE, 1–50 characters; the name paired with `reasonCode` (e.g. `TE001` ↔ `INVALID_REQUEST`).\n- `description`: 1–500 characters; MUST NOT contain PII.\n- Gateway-level errors (405, 409, 413, 429, 502, 503, 504) do not carry this body.","properties":{"statusCode":{"type":"string","description":"Business-level status code. Always RJCT (Rejected) — the structured error body is only returned for rejection cases. Successful responses use HTTP status alone (200 OK for sync, 202 Accepted for async ingress) with no structured statusCode body.","enum":["RJCT"],"maxLength":4,"minLength":4},"reasonCode":{"type":"string","description":"Categorised reason code. Three families: TE (Technical Error, e.g. TE001/TE002/TE099), AE (Authentication / Authorization Error, AE001–AE006, enforced at authentication), BE (Business Error, BE001–BE031).","enum":["TE001","TE002","TE099","AE001","AE002","AE003","AE004","AE005","AE006","BE001","BE002","BE007","BE008","BE009","BE010","BE011","BE012","BE013","BE014","BE015","BE016","BE017","BE018","BE019","BE020","BE021","BE030","BE031"],"maxLength":5,"pattern":"^[A-Z]{2}[0-9]{3}$","minLength":5},"name":{"type":"string","description":"Machine-readable error name paired with the reason code.","maxLength":50,"pattern":"^[A-Z][A-Z0-9]*(?:_[A-Z0-9]+)*$","minLength":1},"description":{"type":"string","description":"Human-readable error description. MUST NOT contain PII.","maxLength":500,"minLength":1}},"required":["description","name","reasonCode","statusCode"]}},"headers":{"ResponseSignatureInput":{"description":"RFC 9421 signature metadata for a GET response, per the Nexus HTTP Message Signature Profile v1 (RFC 9421, RFC 9530). Signed by the responding server with its own signing private key. Covered components: `\"@status\" \"content-type\" \"content-digest\"` on 200, or `\"@status\" \"etag\"` on 304, followed in both cases by the request-bound components `\"@method\";req \"@path\";req \"@query\";req`, which tie the response to the resource that was requested. Same `created`, `expires`, `keyid`, `alg` and `tag` rules as requests. The client MUST verify the response signature before using the response and MUST discard a response that fails verification.","required":true,"schema":{"type":"string","maxLength":512,"pattern":"^nexus=\\(\"@status\" (\"content-type\" \"content-digest\"|\"etag\") \"@method\";req \"@path\";req \"@query\";req\\);created=[0-9]{1,15};expires=[0-9]{1,15};keyid=\"[A-Za-z0-9_-]{43}\";alg=\"rsa-pss-sha512\";tag=\"nexus-v1\"$"}},"ResponseSignature":{"description":"RFC 9421 response signature: one dictionary member labelled `nexus` holding the standard base64 `rsa-pss-sha512` signature produced by the responding server over the signature base declared in the response `Signature-Input`. Verified by the client against the server's registered signing public key.","required":true,"schema":{"type":"string","minLength":520,"maxLength":1400,"pattern":"^nexus=:[A-Za-z0-9+/]+={0,2}:$"}},"ResponseContentDigest":{"description":"RFC 9530 SHA-512 digest of the exact response body bytes, covered by the response signature.","required":true,"schema":{"type":"string","pattern":"^sha-512=:[A-Za-z0-9+/]{86}==:$"}}}},"paths":{"/v1/fees-and-amounts/{sourceCountry}/{sourceCurrency}/{destinationCountry}/{destinationCurrency}/{amountCurrency}/{amount}/{exchangeRate}":{"get":{"tags":["Fees and Amounts"],"summary":"Get Fees and Interbank Settlement Amounts","description":"Retrieves the various fees and amounts based on specified parameters. Information can be used in the pacs.008 payment instruction.\n\n---\n\n#### Response validation rules\n\n**200 OK** — the body MUST conform to the response schema below. Response objects are open: additional properties may be introduced in later minor versions, and clients MUST ignore properties they do not recognise.\n\n| Field | Type | Presence | Nullable | Constraints |\n|---|---|---|---|---|\n| `debtorAgent` | object | Required | N | — |\n| `debtorAgent.interbankSettlementAmount` | object | Required | N | — |\n| `debtorAgent.interbankSettlementAmount.amount` | number | Required | N | ≥ 0; > 0 |\n| `debtorAgent.interbankSettlementAmount.currency` | string | Required | N | pattern `^[A-Z]{3}$`; length 3 |\n| `creditorAgent` | object | Required | N | — |\n| `creditorAgent.interbankSettlementAmount` | object | Required | N | — |\n| `creditorAgent.interbankSettlementAmount.amount` | number | Required | N | ≥ 0; > 0 |\n| `creditorAgent.interbankSettlementAmount.currency` | string | Required | N | pattern `^[A-Z]{3}$`; length 3 |\n| `creditorAgent.chargesAmount` | object | Required | N | — |\n| `creditorAgent.chargesAmount.amount` | number | Required | N | ≥ 0 |\n| `creditorAgent.chargesAmount.currency` | string | Required | N | pattern `^[A-Z]{3}$`; length 3 |\n| `creditorAgent.creditorAccountAmount` | number | Required | N | ≥ 0 |\n\n**Cross-field rules**\n\n- `debtorAgent.interbankSettlementAmount.currency` = `sourceCurrency` (path parameter).\n- `creditorAgent.interbankSettlementAmount.currency` = `creditorAgent.chargesAmount.currency` = `destinationCurrency` (path parameter).\n- `creditorAgent.creditorAccountAmount` = `creditorAgent.interbankSettlementAmount.amount` − `creditorAgent.chargesAmount.amount`.\n- The response is a stateless calculation result: it never contains `quoteRequestId`, `quoteId`, `issuedDateTime`, `expiryDateTime` or intermediary agents.\n- Monetary amounts are rounded to the currency's ISO 4217 minor units (decimal places from the currency's Nexus configuration) using `ROUND_HALF_UP`.\n\n**Response signature** — every 200 response carries `Signature-Input` and `Signature` and `Content-Digest` per the Nexus HTTP Message Signature Profile v1, signed by the responding server. The client MUST verify the response signature before using the response and MUST discard a response that fails verification.\n\n**Error responses (4xx/5xx with a body)** — the body MUST conform to `ErrorApiResponse`: `statusCode` = `RJCT`; `reasonCode` matches `^[A-Z]{2}[0-9]{3}$`; `name` is UPPER_SNAKE_CASE (≤ 50); `description` ≤ 500 characters and MUST NOT contain PII. `reasonCode` values for this operation: `TE001`, `BE007`, `BE008`, `BE010`, `BE012`, `BE009`, `AE001`, `AE002`, `AE003`, `AE005`, `AE006`, `AE004`, `TE099`. Gateway errors (405, 429, 502, 503, 504) carry no body.","operationId":"getFeesAndAmounts","parameters":[{"name":"Accept","in":"header","description":"*/*","required":true,"schema":{"type":"string","default":"*/*"}},{"$ref":"#/components/parameters/SignatureInputBodyless"},{"$ref":"#/components/parameters/Signature"},{"name":"sourceCountry","in":"path","description":"ISO-3166 alpha-2 country code of the Source Country.","required":true,"schema":{"type":"string","maxLength":2,"minLength":2,"pattern":"^[A-Z]{2}$"}},{"name":"sourceCurrency","in":"path","description":"ISO-4217 3-letter code of the Source Currency.","required":true,"schema":{"type":"string","maxLength":3,"minLength":3,"pattern":"^[A-Z]{3}$"}},{"name":"destinationCountry","in":"path","description":"ISO-3166 alpha-2 country code of the Destination Country.","required":true,"schema":{"type":"string","maxLength":2,"minLength":2,"pattern":"^[A-Z]{2}$"}},{"name":"destinationCurrency","in":"path","description":"ISO-4217 3-letter code of the Destination Currency.","required":true,"schema":{"type":"string","maxLength":3,"minLength":3,"pattern":"^[A-Z]{3}$"}},{"name":"amountCurrency","in":"path","description":"ISO-4217 3-letter code of the currency in which amount is expressed.","required":true,"schema":{"type":"string","maxLength":3,"minLength":3,"pattern":"^[A-Z]{3}$"}},{"name":"amount","in":"path","description":"The amount in the specified amountCurrency. If defined in Source Currency, this\nmust be the Interbank Settlement Amount (after Source PSP deduction). If defined\nin Destination Currency, this is the CreditorAccountAmount to be credited to the\nRecipient.\n","required":true,"schema":{"type":"number","exclusiveMinimum":0}},{"name":"exchangeRate","in":"path","description":"The exchange rate from Source to Destination currency, as managed by the Source PSP.","required":true,"schema":{"type":"number","exclusiveMinimum":0}},{"name":"finInstIdType","in":"query","description":"Type ID of the Source PSP. Used together with finInstId to identify the Source\nPSP, which is treated as the FX Provider for the resulting payment. The\noriginating Source IPS is resolved separately from the authenticated caller\ncontext.\n\nOne of `BICFI`, `LEI` or `otherId`.\n","required":true,"schema":{"type":"string","enum":["BICFI","LEI","otherId"]}},{"name":"finInstId","in":"query","description":"ID of the Source PSP.\n\nFormat depends on the sibling `finInstIdType` parameter: `BICFI` is 8 or 11 characters, `LEI` is 20 characters, `otherId` is free text of up to 35 characters. The per-type format is enforced as a business validation (`BE019 FI_ID_TYPE_UNSUPPORTED` / `BE020 FI_NOT_FOUND`) rather than by this schema, because it cannot be expressed as a constraint on an independent parameter.\n","required":true,"schema":{"type":"string","minLength":1,"maxLength":35}},{"name":"destFinInstIdType","in":"query","description":"Type ID of the Destination PSP. Required when the destination country operates\nmultiple IPSes. Used to resolve which Destination IPS serves the Destination PSP\nfor the Source PSP's Destination-side settlement-account check.\n\nOne of `BICFI`, `LEI` or `otherId`.\n","required":false,"schema":{"type":"string","enum":["BICFI","LEI","otherId"]}},{"name":"destFinInstId","in":"query","description":"ID of the Destination PSP. Required when the destination country operates\nmultiple IPSes. If absent in a multi-IPS destination country, Nexus rejects the\nrequest with BE008 QUOTE_DESTINATION_PSP_REQUIRED.\n\nFormat depends on the sibling `destFinInstIdType` parameter: `BICFI` is 8 or 11 characters, `LEI` is 20 characters, `otherId` is free text of up to 35 characters. The per-type format is enforced as a business validation (`BE019 FI_ID_TYPE_UNSUPPORTED` / `BE020 FI_NOT_FOUND`) rather than by this schema, because it cannot be expressed as a constraint on an independent parameter.\n","required":false,"schema":{"type":"string","minLength":1,"maxLength":35}}],"responses":{"200":{"description":"Fees and amounts quote generated.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FeesAndAmountsResponse"}}},"headers":{"Signature-Input":{"$ref":"#/components/headers/ResponseSignatureInput"},"Signature":{"$ref":"#/components/headers/ResponseSignature"},"Content-Digest":{"$ref":"#/components/headers/ResponseContentDigest"}}},"400":{"description":"Invalid Request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorApiResponse"}}}},"401":{"description":"Authentication Failure","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorApiResponse"}}}},"403":{"description":"Authorization Failure","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorApiResponse"}}}},"404":{"description":"Resource Not Found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorApiResponse"}}}},"405":{"description":"Method Not Allowed. The HTTP method is not supported for this endpoint. Use the correct HTTP method.","headers":{"Allow":{"description":"Permitted HTTP methods for this endpoint","schema":{"type":"string"}}}},"429":{"description":"Too Many Requests. Rate limit exceeded. The Retry-After header indicates when to retry. Back off and retry after the indicated duration.","headers":{"Retry-After":{"description":"Duration after which the caller may retry","schema":{"type":"integer","minimum":0}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorApiResponse"}}}},"502":{"description":"Bad Gateway. The gateway received an invalid response from the upstream service. Retry with exponential backoff. If persistent, escalate."},"503":{"description":"Service Unavailable. The upstream service is temporarily unavailable, for example during rolling deployment. Retry with exponential backoff."},"504":{"description":"Gateway Timeout. The upstream service did not respond within the gateway's timeout window. Retry with exponential backoff."}}}}}}
```

## Get Destination Agent Fee Formula

> Returns the Destination Agent (Destination PSP) Fee FORMULA for a specified Destination Country, denominated in the Destination Currency. Supports HTTP conditional GET via If-None-Match header.\
> \
> \---\
> \
> \#### Response validation rules\
> \
> \*\*200 OK\*\* — the body MUST conform to the response schema below. Response objects are open: additional properties may be introduced in later minor versions, and clients MUST ignore properties they do not recognise.\
> \
> \| Field | Type | Presence | Nullable | Constraints |\
> \|---|---|---|---|---|\
> \| \`countryCode\` | string | Required | N | pattern \`^\[A-Z]{2}$\`; length 2 |\
> \| \`nominalFee\` | object | Conditional — present when the formula has a fixed component | Y | — |\
> \| \`nominalFee.amount\` | number | Required | N | ≥ 0 |\
> \| \`nominalFee.currency\` | string | Required | N | pattern \`^\[A-Z]{3}$\`; length 3 |\
> \| \`percentageFee\` | number | Conditional — present when the formula has a percentage component | Y | ≥ 0; ≤ 1 |\
> \| \`validTo\` | string | Required | N | format \`date-time\`; max length 32 |\
> \
> \*\*Cross-field rules\*\*\
> \
> \- \`countryCode\` equals the \`countryCode\` path parameter.\
> \- \`nominalFee\` is omitted or \`null\` when the formula has no fixed component; when present, \`nominalFee.amount\` ≥ 0 and \`nominalFee.currency\` equals the \`currencyCode\` path parameter (the Destination Currency).\
> \- \`percentageFee\` is omitted or \`null\` when the formula has no percentage component; when present it is a decimal ratio between 0 and 1 (0.1 = 10 %).\
> \- \`validTo\` is a future timestamp at the next Nexus-configured boundary (default \`23:59:59+08:00\`); participants MUST re-pull on or before it.\
> \
> \*\*Response signature\*\* — every 200 and 304 response carries \`Signature-Input\` and \`Signature\` (plus \`Content-Digest\` on 200) per the Nexus HTTP Message Signature Profile v1, signed by the responding server. The client MUST verify the response signature before using the response and MUST discard a response that fails verification.\
> \
> \*\*Error responses (4xx/5xx with a body)\*\* — the body MUST conform to \`ErrorApiResponse\`: \`statusCode\` = \`RJCT\`; \`reasonCode\` matches \`^\[A-Z]{2}\[0-9]{3}$\`; \`name\` is UPPER\_SNAKE\_CASE (≤ 50); \`description\` ≤ 500 characters and MUST NOT contain PII. \`reasonCode\` values for this operation: \`TE001\`, \`BE011\`, \`AE001\`, \`AE002\`, \`AE003\`, \`AE005\`, \`AE006\`, \`AE004\`, \`TE099\`. Gateway errors (405, 429, 502, 503, 504) carry no body.

```json
{"openapi":"3.1.0","info":{"title":"Nexus Payments API","version":"v1"},"tags":[{"name":"Fees and Amounts","description":"APIs for a Source PSP acting as its own FX Provider to either have settlement amounts and fees computed on its behalf, or retrieve the fee formula for independent computation."}],"servers":[{"url":"https://{environment}.payments.nexus.net","description":"Nexus participant-facing API endpoint. Resolved via Nexus private DNS over the established IPsec IKEv2 tunnel and not reachable from the public Internet.","variables":{"environment":{"default":"prod","enum":["pat","prod"],"description":"Deployment environment subdomain."}}}],"security":[{"mutualTLS":[],"nexusOAuth":["fees.read"]}],"components":{"securitySchemes":{"mutualTLS":{"type":"mutualTLS","description":"Mutual TLS: the IPSO presents its X.509 client certificate on every connection, validated during the TLS handshake (fail-closed). The same certificate is the RFC 8705 binding anchor for the OAuth access token (see nexusOAuth)."}},"parameters":{"SignatureInputBodyless":{"name":"Signature-Input","in":"header","required":true,"description":"RFC 9421 signature metadata for a request without a body, per the Nexus HTTP Message Signature Profile v1 (RFC 9421, RFC 9530). One dictionary member labelled `nexus` whose covered components are exactly `\"@method\" \"@authority\" \"@path\" \"@query\"`, followed by `\"if-none-match\"` when that header is sent. `@query` is always covered; an empty query serialises as `?`, so query parameters cannot be added or removed undetected. Signature parameters, emitted in this order: `created` and `expires` (Unix seconds; `expires` = `created` + 300; the receiver rejects `created` more than ±5 minutes from its clock or a signature past `expires`), `keyid` (base64url SHA-256 thumbprint of the signer's signing public key, registered at onboarding; a missing, unknown, expired or revoked key id is rejected - never resolved to a default key), `alg` (always `rsa-pss-sha512`) and `tag` (always `nexus-v1`). The signature parameters are signed through the `@signature-params` line of the signature base. A missing, malformed or non-conforming value is rejected with AE005.","schema":{"type":"string","maxLength":512,"pattern":"^nexus=\\(\"@method\" \"@authority\" \"@path\" \"@query\"( \"if-none-match\")?\\);created=[0-9]{1,15};expires=[0-9]{1,15};keyid=\"[A-Za-z0-9_-]{43}\";alg=\"rsa-pss-sha512\";tag=\"nexus-v1\"$"}},"Signature":{"name":"Signature","in":"header","required":true,"description":"RFC 9421 signature value: one dictionary member labelled `nexus` holding an RFC 8941 byte sequence - the **standard base64** (not base64url) RSASSA-PSS signature using SHA-512 (`rsa-pss-sha512`), computed over the RFC 9421 signature base built from the components and parameters declared in `Signature-Input`. Produced with the sender's own signing private key; the receiver verifies it against the sender's registered signing public key resolved from `keyid`. With the minimum RSA-3072 key the signature is 384 bytes, i.e. 512 base64 characters. A missing, malformed or non-verifying signature is rejected with AE005.","schema":{"type":"string","minLength":520,"maxLength":1400,"pattern":"^nexus=:[A-Za-z0-9+/]+={0,2}:$"}}},"headers":{"ResponseSignatureInput":{"description":"RFC 9421 signature metadata for a GET response, per the Nexus HTTP Message Signature Profile v1 (RFC 9421, RFC 9530). Signed by the responding server with its own signing private key. Covered components: `\"@status\" \"content-type\" \"content-digest\"` on 200, or `\"@status\" \"etag\"` on 304, followed in both cases by the request-bound components `\"@method\";req \"@path\";req \"@query\";req`, which tie the response to the resource that was requested. Same `created`, `expires`, `keyid`, `alg` and `tag` rules as requests. The client MUST verify the response signature before using the response and MUST discard a response that fails verification.","required":true,"schema":{"type":"string","maxLength":512,"pattern":"^nexus=\\(\"@status\" (\"content-type\" \"content-digest\"|\"etag\") \"@method\";req \"@path\";req \"@query\";req\\);created=[0-9]{1,15};expires=[0-9]{1,15};keyid=\"[A-Za-z0-9_-]{43}\";alg=\"rsa-pss-sha512\";tag=\"nexus-v1\"$"}},"ResponseSignature":{"description":"RFC 9421 response signature: one dictionary member labelled `nexus` holding the standard base64 `rsa-pss-sha512` signature produced by the responding server over the signature base declared in the response `Signature-Input`. Verified by the client against the server's registered signing public key.","required":true,"schema":{"type":"string","minLength":520,"maxLength":1400,"pattern":"^nexus=:[A-Za-z0-9+/]+={0,2}:$"}},"ResponseContentDigest":{"description":"RFC 9530 SHA-512 digest of the exact response body bytes, covered by the response signature.","required":true,"schema":{"type":"string","pattern":"^sha-512=:[A-Za-z0-9+/]{86}==:$"}}},"schemas":{"DestinationAgentFeeResponse":{"type":"object","description":"Destination agent fee configuration.","properties":{"countryCode":{"type":"string","description":"ISO-3166 alpha-2 country code of the Destination Country.","maxLength":2,"minLength":2,"pattern":"^[A-Z]{2}$"},"nominalFee":{"oneOf":[{"$ref":"#/components/schemas/AmountDto"},{"type":"null"}],"description":"Fixed nominal fee amount and currency in the Destination Currency. Omitted when the formula has no fixed component."},"percentageFee":{"type":["number","null"],"description":"Percentage fee expressed as a decimal ratio (e.g., 0.1 = 10%). Omitted when the formula has no percentage component.","minimum":0,"maximum":1},"validTo":{"type":"string","format":"date-time","description":"Timestamp at which the returned fee formula is scheduled to expire. Always set to the next 23:59:59 Singapore-time boundary (+08:00). PSPs/IPSs MUST refresh the formula on or before this time.","maxLength":32}},"required":["countryCode","validTo"]},"AmountDto":{"type":"object","description":"Monetary amount with currency code.","properties":{"amount":{"type":"number","description":"Monetary amount. When copied into an ISO 20022 XML amount the value must have at most 5 fractional digits and at most 18 total digits; serialise as a plain decimal, never in exponent form.","minimum":0},"currency":{"type":"string","description":"ISO-4217 currency code.","maxLength":3,"minLength":3,"pattern":"^[A-Z]{3}$"}},"required":["amount","currency"]},"ErrorApiResponse":{"type":"object","description":"Standard structured rejection body. Returned for all non-2xx responses produced by the Nexus authentication layer or the application. Gateway level errors (405, 409, 413, 429, 502, 503, 504) do NOT carry this body.\n\n#### Validation rules\n\n- All four fields are required and never `null`.\n- `statusCode`: always `RJCT`.\n- `reasonCode`: 5 characters matching `^[A-Z]{2}[0-9]{3}$`; family prefix `TE` (technical), `AE` (authentication/authorisation, enforced at authentication) or `BE` (business); one of the values enumerated in the `reasonCode` schema.\n- `name`: UPPER_SNAKE_CASE, 1–50 characters; the name paired with `reasonCode` (e.g. `TE001` ↔ `INVALID_REQUEST`).\n- `description`: 1–500 characters; MUST NOT contain PII.\n- Gateway-level errors (405, 409, 413, 429, 502, 503, 504) do not carry this body.","properties":{"statusCode":{"type":"string","description":"Business-level status code. Always RJCT (Rejected) — the structured error body is only returned for rejection cases. Successful responses use HTTP status alone (200 OK for sync, 202 Accepted for async ingress) with no structured statusCode body.","enum":["RJCT"],"maxLength":4,"minLength":4},"reasonCode":{"type":"string","description":"Categorised reason code. Three families: TE (Technical Error, e.g. TE001/TE002/TE099), AE (Authentication / Authorization Error, AE001–AE006, enforced at authentication), BE (Business Error, BE001–BE031).","enum":["TE001","TE002","TE099","AE001","AE002","AE003","AE004","AE005","AE006","BE001","BE002","BE007","BE008","BE009","BE010","BE011","BE012","BE013","BE014","BE015","BE016","BE017","BE018","BE019","BE020","BE021","BE030","BE031"],"maxLength":5,"pattern":"^[A-Z]{2}[0-9]{3}$","minLength":5},"name":{"type":"string","description":"Machine-readable error name paired with the reason code.","maxLength":50,"pattern":"^[A-Z][A-Z0-9]*(?:_[A-Z0-9]+)*$","minLength":1},"description":{"type":"string","description":"Human-readable error description. MUST NOT contain PII.","maxLength":500,"minLength":1}},"required":["description","name","reasonCode","statusCode"]}}},"paths":{"/v1/fee-formulas/destination-agent-fee/{countryCode}/{currencyCode}":{"get":{"tags":["Fees and Amounts"],"summary":"Get Destination Agent Fee Formula","description":"Returns the Destination Agent (Destination PSP) Fee FORMULA for a specified Destination Country, denominated in the Destination Currency. Supports HTTP conditional GET via If-None-Match header.\n\n---\n\n#### Response validation rules\n\n**200 OK** — the body MUST conform to the response schema below. Response objects are open: additional properties may be introduced in later minor versions, and clients MUST ignore properties they do not recognise.\n\n| Field | Type | Presence | Nullable | Constraints |\n|---|---|---|---|---|\n| `countryCode` | string | Required | N | pattern `^[A-Z]{2}$`; length 2 |\n| `nominalFee` | object | Conditional — present when the formula has a fixed component | Y | — |\n| `nominalFee.amount` | number | Required | N | ≥ 0 |\n| `nominalFee.currency` | string | Required | N | pattern `^[A-Z]{3}$`; length 3 |\n| `percentageFee` | number | Conditional — present when the formula has a percentage component | Y | ≥ 0; ≤ 1 |\n| `validTo` | string | Required | N | format `date-time`; max length 32 |\n\n**Cross-field rules**\n\n- `countryCode` equals the `countryCode` path parameter.\n- `nominalFee` is omitted or `null` when the formula has no fixed component; when present, `nominalFee.amount` ≥ 0 and `nominalFee.currency` equals the `currencyCode` path parameter (the Destination Currency).\n- `percentageFee` is omitted or `null` when the formula has no percentage component; when present it is a decimal ratio between 0 and 1 (0.1 = 10 %).\n- `validTo` is a future timestamp at the next Nexus-configured boundary (default `23:59:59+08:00`); participants MUST re-pull on or before it.\n\n**Response signature** — every 200 and 304 response carries `Signature-Input` and `Signature` (plus `Content-Digest` on 200) per the Nexus HTTP Message Signature Profile v1, signed by the responding server. The client MUST verify the response signature before using the response and MUST discard a response that fails verification.\n\n**Error responses (4xx/5xx with a body)** — the body MUST conform to `ErrorApiResponse`: `statusCode` = `RJCT`; `reasonCode` matches `^[A-Z]{2}[0-9]{3}$`; `name` is UPPER_SNAKE_CASE (≤ 50); `description` ≤ 500 characters and MUST NOT contain PII. `reasonCode` values for this operation: `TE001`, `BE011`, `AE001`, `AE002`, `AE003`, `AE005`, `AE006`, `AE004`, `TE099`. Gateway errors (405, 429, 502, 503, 504) carry no body.","operationId":"getDestinationAgentFee","parameters":[{"name":"Accept","in":"header","description":"*/*","required":true,"schema":{"type":"string","default":"*/*"}},{"name":"countryCode","in":"path","description":"ISO-3166 alpha-2 country code of the Destination Country. Example:`MY`","required":true,"schema":{"type":"string","maxLength":2,"minLength":2,"pattern":"^[A-Z]{2}$"}},{"name":"currencyCode","in":"path","description":"ISO-4217 3-letter code of the Destination Currency. Example:`MYR`","required":true,"schema":{"type":"string","maxLength":3,"minLength":3,"pattern":"^[A-Z]{3}$"}},{"name":"If-None-Match","in":"header","description":"Optional. ETag value from a previous response for conditional GET. If it matches the current entity tag, the server returns 304 Not Modified with no body.","required":false,"schema":{"type":"string"}},{"$ref":"#/components/parameters/SignatureInputBodyless"},{"$ref":"#/components/parameters/Signature"}],"responses":{"200":{"description":"Destination Agent Fee retrieved.","headers":{"ETag":{"description":"Entity tag for cache validation","style":"simple","schema":{"type":"string"}},"Cache-Control":{"description":"Caching guidance for this reference-data resource. Nexus invalidates the underlying cache immediately when the underlying configuration changes; responses may otherwise be cached for up to 300 seconds.","schema":{"type":"string"}},"Signature-Input":{"$ref":"#/components/headers/ResponseSignatureInput"},"Signature":{"$ref":"#/components/headers/ResponseSignature"},"Content-Digest":{"$ref":"#/components/headers/ResponseContentDigest"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DestinationAgentFeeResponse"}}}},"304":{"description":"Not Modified. The resource has not changed since the last request.","headers":{"ETag":{"description":"Entity tag for cache validation","style":"simple","schema":{"type":"string"}},"Signature-Input":{"$ref":"#/components/headers/ResponseSignatureInput"},"Signature":{"$ref":"#/components/headers/ResponseSignature"}}},"400":{"description":"Invalid Request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorApiResponse"}}}},"401":{"description":"Authentication Failure","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorApiResponse"}}}},"403":{"description":"Authorization Failure","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorApiResponse"}}}},"404":{"description":"Resource Not Found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorApiResponse"}}}},"405":{"description":"Method Not Allowed. The HTTP method is not supported for this endpoint. Use the correct HTTP method.","headers":{"Allow":{"description":"Permitted HTTP methods for this endpoint","schema":{"type":"string"}}}},"429":{"description":"Too Many Requests. Rate limit exceeded. The Retry-After header indicates when to retry. Back off and retry after the indicated duration.","headers":{"Retry-After":{"description":"Duration after which the caller may retry","schema":{"type":"integer","minimum":0}}}},"500":{"description":"Internal Server Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorApiResponse"}}}},"502":{"description":"Bad Gateway. The gateway received an invalid response from the upstream service. Retry with exponential backoff. If persistent, escalate."},"503":{"description":"Service Unavailable. The upstream service is temporarily unavailable, for example during rolling deployment. Retry with exponential backoff."},"504":{"description":"Gateway Timeout. The upstream service did not respond within the gateway's timeout window. Retry with exponential backoff."}}}}}}
```
