> 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/apis/fxp-rates.md).

# FXP Rates

## Create or replace a rate

> Creates a new rate record identified by the FXP's source and destination IA account references. Nexus resolves source currency, destination currency, source IPS, and destination IPS from the IA account records registered for the submitting FXP. If a live rate already exists for the same (sourceIAAccount, destinationIAAccount) pair, Nexus marks the prior record as superseded (isExpired=true — a historical marker, not time-based expiry) and creates the new rate.

```json
{"openapi":"3.1.0","info":{"title":"Nexus API","version":"v1"},"tags":[{"name":"FXP Rates","description":"Manage FXP exchange rates. Rates are one-directional, identified by source and destination IA account references, and remain live until replaced by a new rate for the same account pair or voluntarily withdrawn. Nexus does not impose time-based expiry on rates; isExpired marks superseded or voluntarily withdrawn records only."}],"servers":[{"url":"http://localhost:8080","description":"Local simulator (make run / make docker-run)"},{"url":"https://nexus-ai-simulator-683365449922.asia-southeast1.run.app","description":"Deployed simulator (Cloud Run, asia-southeast1) - indicative, not authoritative"}],"security":[{"nexusClientCert":[],"nexusOAuth":["rates.write"]}],"components":{"securitySchemes":{"nexusClientCert":{"type":"mutualTLS","description":"Nexus issued X.509 client certificate presented during the TLS handshake and validated at the Akamai global edge. The FXP generates its own key pair and submits a CSR during onboarding; Vault PKI (edge intermediate CA) signs it and the private key never leaves FXP infrastructure. Fail closed: a missing, expired, revoked or untrusted certificate causes the TLS handshake to fail at the edge and no HTTP response is produced. The certificate is not forwarded to the origin as an HTTP header."}},"schemas":{"RateRequest":{"type":"object","required":["sourceIAAccount","destinationIAAccount","rate"],"description":"Request body for creating or replacing a rate.","properties":{"sourceIAAccount":{"$ref":"#/components/schemas/IAAccountReference"},"destinationIAAccount":{"$ref":"#/components/schemas/IAAccountReference"},"rate":{"type":"number","format":"double","exclusiveMinimum":0,"description":"Exchange rate: number of destination currency units per one source currency unit."}}},"IAAccountReference":{"type":"object","required":["addressTypeCode","fields"],"description":"Reference to an IA account by address type and its identifying fields.","properties":{"addressTypeCode":{"type":"string","description":"Nexus address type code identifying the account addressing scheme (e.g. IBAN, AU-BSB)."},"fields":{"type":"object","additionalProperties":{"type":"string"},"description":"Map of address fields as defined by the address type schema."}}},"RateResponse":{"type":"object","description":"A single FXP rate record.","properties":{"id":{"type":"string","format":"uuid","description":"Nexus-assigned unique identifier for the rate record."},"fxpId":{"type":"string","description":"Nexus internal identifier for the FXP that owns this rate."},"sourceIAAccount":{"$ref":"#/components/schemas/IAAccountReference"},"destinationIAAccount":{"$ref":"#/components/schemas/IAAccountReference"},"sourceCurrency":{"type":"string","maxLength":3,"minLength":3,"description":"ISO 4217 source currency code resolved from sourceIAAccount."},"destinationCurrency":{"type":"string","maxLength":3,"minLength":3,"description":"ISO 4217 destination currency code resolved from destinationIAAccount."},"sourceIps":{"type":"string","description":"Source IPS identifier resolved from sourceIAAccount."},"destinationIps":{"type":"string","description":"Destination IPS identifier resolved from destinationIAAccount."},"rate":{"type":"number","format":"double","description":"The exchange rate."},"createdDateTime":{"type":"string","format":"date-time","description":"ISO 8601 UTC timestamp when this rate record was created."},"isExpired":{"type":"boolean","description":"If true, this rate has been superseded by a newer rate for the same account pair, or voluntarily withdrawn. Not a time-based expiry."},"expiryDateTime":{"type":["string","null"],"format":"date-time","description":"ISO 8601 UTC timestamp when this rate was superseded or withdrawn. Null if still live."}}},"ErrorApiResponse":{"type":"object","description":"Standard structured rejection body. Returned for all non-2xx responses produced by the auth sidecar or the application. 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},"reasonCode":{"type":"string","description":"Categorised reason code. Three families: TE (Technical Error, e.g. TE001/TE002/TE099), AE (Authentication / Authorization Error, e.g. AE001–AE004, sidecar-enforced), BE (Business Error). BE001–BE020 are raised by the Payments endpoints; BE021–BE027 are raised by the FXP endpoints.","enum":["AE001","AE002","AE003","AE004","BE001","BE002","BE005","BE006","BE007","BE008","BE009","BE011","BE012","BE016","BE017","BE018","BE019","BE020","BE021","BE022","BE023","BE024","BE025","BE026","BE027","TE001","TE002","TE099"],"maxLength":5,"pattern":"[A-Z]{2}[0-9]{3}"},"name":{"type":"string","description":"Machine-readable business error name from the reason code catalogue.","maxLength":50,"pattern":"[A-Z][A-Z0-9]*(?:_[A-Z0-9]+)*"},"description":{"type":"string","description":"Human-readable error description. MUST NOT contain PII (CD-INV-09).","maxLength":500}},"required":["description","name","reasonCode","statusCode"]}}},"paths":{"/v1/rates":{"post":{"tags":["FXP Rates"],"summary":"Create or replace a rate","description":"Creates a new rate record identified by the FXP's source and destination IA account references. Nexus resolves source currency, destination currency, source IPS, and destination IPS from the IA account records registered for the submitting FXP. If a live rate already exists for the same (sourceIAAccount, destinationIAAccount) pair, Nexus marks the prior record as superseded (isExpired=true — a historical marker, not time-based expiry) and creates the new rate.","operationId":"createRate","parameters":[{"name":"Accept","in":"header","description":"application/json","required":true,"schema":{"type":"string","default":"application/json"}}],"requestBody":{"description":"Rate creation request.","required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateRequest"}}}},"responses":{"200":{"description":"Rate created successfully. Returns the new rate record.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateResponse"}}}},"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"}}}},"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"}}}},"409":{"description":"Conflict. The rate could not be created due to a conflicting state.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorApiResponse"}}}},"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,"description":"Number of seconds to wait before retrying"}}}},"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."}}}}}}
```

## List FXP rates

> Returns the authenticated FXP's current (live, non-superseded) rates, optionally filtered by currency pair and IPSs. When includeExpired=true, historical rates from the last 13 months are included and limit is required (maximum 100). Nexus does not impose time-based expiry on rates; isExpired marks superseded or voluntarily withdrawn records only.

```json
{"openapi":"3.1.0","info":{"title":"Nexus API","version":"v1"},"tags":[{"name":"FXP Rates","description":"Manage FXP exchange rates. Rates are one-directional, identified by source and destination IA account references, and remain live until replaced by a new rate for the same account pair or voluntarily withdrawn. Nexus does not impose time-based expiry on rates; isExpired marks superseded or voluntarily withdrawn records only."}],"servers":[{"url":"http://localhost:8080","description":"Local simulator (make run / make docker-run)"},{"url":"https://nexus-ai-simulator-683365449922.asia-southeast1.run.app","description":"Deployed simulator (Cloud Run, asia-southeast1) - indicative, not authoritative"}],"security":[{"nexusClientCert":[],"nexusOAuth":["rates.read"]}],"components":{"securitySchemes":{"nexusClientCert":{"type":"mutualTLS","description":"Nexus issued X.509 client certificate presented during the TLS handshake and validated at the Akamai global edge. The FXP generates its own key pair and submits a CSR during onboarding; Vault PKI (edge intermediate CA) signs it and the private key never leaves FXP infrastructure. Fail closed: a missing, expired, revoked or untrusted certificate causes the TLS handshake to fail at the edge and no HTTP response is produced. The certificate is not forwarded to the origin as an HTTP header."}},"schemas":{"RatesPageResponse":{"type":"object","description":"Paginated list of rate records.","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/RateResponse"},"description":"Rate records for the current page."},"cursor":{"type":["string","null"],"description":"Opaque cursor for the next page. Null if this is the last page."}}},"RateResponse":{"type":"object","description":"A single FXP rate record.","properties":{"id":{"type":"string","format":"uuid","description":"Nexus-assigned unique identifier for the rate record."},"fxpId":{"type":"string","description":"Nexus internal identifier for the FXP that owns this rate."},"sourceIAAccount":{"$ref":"#/components/schemas/IAAccountReference"},"destinationIAAccount":{"$ref":"#/components/schemas/IAAccountReference"},"sourceCurrency":{"type":"string","maxLength":3,"minLength":3,"description":"ISO 4217 source currency code resolved from sourceIAAccount."},"destinationCurrency":{"type":"string","maxLength":3,"minLength":3,"description":"ISO 4217 destination currency code resolved from destinationIAAccount."},"sourceIps":{"type":"string","description":"Source IPS identifier resolved from sourceIAAccount."},"destinationIps":{"type":"string","description":"Destination IPS identifier resolved from destinationIAAccount."},"rate":{"type":"number","format":"double","description":"The exchange rate."},"createdDateTime":{"type":"string","format":"date-time","description":"ISO 8601 UTC timestamp when this rate record was created."},"isExpired":{"type":"boolean","description":"If true, this rate has been superseded by a newer rate for the same account pair, or voluntarily withdrawn. Not a time-based expiry."},"expiryDateTime":{"type":["string","null"],"format":"date-time","description":"ISO 8601 UTC timestamp when this rate was superseded or withdrawn. Null if still live."}}},"IAAccountReference":{"type":"object","required":["addressTypeCode","fields"],"description":"Reference to an IA account by address type and its identifying fields.","properties":{"addressTypeCode":{"type":"string","description":"Nexus address type code identifying the account addressing scheme (e.g. IBAN, AU-BSB)."},"fields":{"type":"object","additionalProperties":{"type":"string"},"description":"Map of address fields as defined by the address type schema."}}},"ErrorApiResponse":{"type":"object","description":"Standard structured rejection body. Returned for all non-2xx responses produced by the auth sidecar or the application. 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},"reasonCode":{"type":"string","description":"Categorised reason code. Three families: TE (Technical Error, e.g. TE001/TE002/TE099), AE (Authentication / Authorization Error, e.g. AE001–AE004, sidecar-enforced), BE (Business Error). BE001–BE020 are raised by the Payments endpoints; BE021–BE027 are raised by the FXP endpoints.","enum":["AE001","AE002","AE003","AE004","BE001","BE002","BE005","BE006","BE007","BE008","BE009","BE011","BE012","BE016","BE017","BE018","BE019","BE020","BE021","BE022","BE023","BE024","BE025","BE026","BE027","TE001","TE002","TE099"],"maxLength":5,"pattern":"[A-Z]{2}[0-9]{3}"},"name":{"type":"string","description":"Machine-readable business error name from the reason code catalogue.","maxLength":50,"pattern":"[A-Z][A-Z0-9]*(?:_[A-Z0-9]+)*"},"description":{"type":"string","description":"Human-readable error description. MUST NOT contain PII (CD-INV-09).","maxLength":500}},"required":["description","name","reasonCode","statusCode"]}}},"paths":{"/v1/rates":{"get":{"tags":["FXP Rates"],"summary":"List FXP rates","description":"Returns the authenticated FXP's current (live, non-superseded) rates, optionally filtered by currency pair and IPSs. When includeExpired=true, historical rates from the last 13 months are included and limit is required (maximum 100). Nexus does not impose time-based expiry on rates; isExpired marks superseded or voluntarily withdrawn records only.","operationId":"listRates","parameters":[{"name":"Accept","in":"header","description":"application/json","required":true,"schema":{"type":"string","default":"application/json"}},{"name":"sourceCurrency","in":"query","description":"ISO 4217 3-letter source currency code (uppercase). Filters to rates for this source currency.","required":false,"schema":{"type":"string","maxLength":3,"minLength":3,"pattern":"^[A-Z]{3}$"}},{"name":"destinationCurrency","in":"query","description":"ISO 4217 3-letter destination currency code (uppercase). Filters to rates for this destination currency.","required":false,"schema":{"type":"string","maxLength":3,"minLength":3,"pattern":"^[A-Z]{3}$"}},{"name":"sourceIps","in":"query","description":"Source IPS identifier. Filters to rates where the FXP receives source currency via this IPS.","required":false,"schema":{"type":"string"}},{"name":"destinationIps","in":"query","description":"Destination IPS identifier. Filters to rates where the FXP pays out destination currency via this IPS.","required":false,"schema":{"type":"string"}},{"name":"includeExpired","in":"query","description":"If true, include historical (withdrawn or superseded) rates from the last 13 months. Default: false. When true, limit is required.","required":false,"schema":{"type":"boolean","default":false}},{"name":"limit","in":"query","description":"Max items to return. Default 50. Maximum 100. Required when includeExpired=true.","required":false,"schema":{"type":"integer","default":50,"minimum":1,"maximum":100}},{"name":"cursor","in":"query","description":"Pagination cursor; omit for first page. This endpoint is limited to a maximum of 100 records.","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Rates retrieved successfully.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RatesPageResponse"}}}},"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"}}}},"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,"description":"Number of seconds to wait before retrying"}}}},"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 rate count

> Returns the count of rates for the authenticated FXP. includeExpired controls whether historical (withdrawn or superseded) rates are included in the count.

```json
{"openapi":"3.1.0","info":{"title":"Nexus API","version":"v1"},"tags":[{"name":"FXP Rates","description":"Manage FXP exchange rates. Rates are one-directional, identified by source and destination IA account references, and remain live until replaced by a new rate for the same account pair or voluntarily withdrawn. Nexus does not impose time-based expiry on rates; isExpired marks superseded or voluntarily withdrawn records only."}],"servers":[{"url":"http://localhost:8080","description":"Local simulator (make run / make docker-run)"},{"url":"https://nexus-ai-simulator-683365449922.asia-southeast1.run.app","description":"Deployed simulator (Cloud Run, asia-southeast1) - indicative, not authoritative"}],"security":[{"nexusClientCert":[],"nexusOAuth":["rates.read"]}],"components":{"securitySchemes":{"nexusClientCert":{"type":"mutualTLS","description":"Nexus issued X.509 client certificate presented during the TLS handshake and validated at the Akamai global edge. The FXP generates its own key pair and submits a CSR during onboarding; Vault PKI (edge intermediate CA) signs it and the private key never leaves FXP infrastructure. Fail closed: a missing, expired, revoked or untrusted certificate causes the TLS handshake to fail at the edge and no HTTP response is produced. The certificate is not forwarded to the origin as an HTTP header."}},"schemas":{"CountResponse":{"type":"object","description":"Count of records matching the query.","properties":{"count":{"type":"integer","minimum":0,"description":"Total count of matching records."}}},"ErrorApiResponse":{"type":"object","description":"Standard structured rejection body. Returned for all non-2xx responses produced by the auth sidecar or the application. 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},"reasonCode":{"type":"string","description":"Categorised reason code. Three families: TE (Technical Error, e.g. TE001/TE002/TE099), AE (Authentication / Authorization Error, e.g. AE001–AE004, sidecar-enforced), BE (Business Error). BE001–BE020 are raised by the Payments endpoints; BE021–BE027 are raised by the FXP endpoints.","enum":["AE001","AE002","AE003","AE004","BE001","BE002","BE005","BE006","BE007","BE008","BE009","BE011","BE012","BE016","BE017","BE018","BE019","BE020","BE021","BE022","BE023","BE024","BE025","BE026","BE027","TE001","TE002","TE099"],"maxLength":5,"pattern":"[A-Z]{2}[0-9]{3}"},"name":{"type":"string","description":"Machine-readable business error name from the reason code catalogue.","maxLength":50,"pattern":"[A-Z][A-Z0-9]*(?:_[A-Z0-9]+)*"},"description":{"type":"string","description":"Human-readable error description. MUST NOT contain PII (CD-INV-09).","maxLength":500}},"required":["description","name","reasonCode","statusCode"]}}},"paths":{"/v1/rates/count":{"get":{"tags":["FXP Rates"],"summary":"Get rate count","description":"Returns the count of rates for the authenticated FXP. includeExpired controls whether historical (withdrawn or superseded) rates are included in the count.","operationId":"getRateCount","parameters":[{"name":"Accept","in":"header","description":"application/json","required":true,"schema":{"type":"string","default":"application/json"}},{"name":"includeExpired","in":"query","description":"If true, include historical (withdrawn or superseded) rates in the count. Default: false.","required":false,"schema":{"type":"boolean","default":false}}],"responses":{"200":{"description":"Count retrieved successfully.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CountResponse"}}}},"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"}}}},"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,"description":"Number of seconds to wait before retrying"}}}},"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."}}}}}}
```
