> 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 an FX rate

> Creates a new exchange rate for a currency pair. If a live rate already exists for the same currency pair, it is automatically marked as superseded and kept as a historical record. Quotes already issued against the previous rate remain valid for 10 minutes, known as the NQVT window. Nexus may throttle this endpoint, and an idempotency key header is recommended so that retried submissions are not duplicated. Requires the scope rates.write. Used by: FX Providers (FXPs)

```json
{"openapi":"3.1.0","info":{"title":"Nexus APIs","version":"0.3.1"},"tags":[{"name":"FXP Rates","description":"Rate management for FX Providers on the Nexus Config and Admin Portal. FXPs push exchange rates to Nexus for each currency pair; Nexus does not pull rates. Nexus uses these rates, together with any applicable improvements, to generate quotes for PSPs, and quotes are honoured for 10 minutes, known as the NQVT window. Nexus does not expire rates based on time and does not require periodic refresh. A rate stays live until it is replaced by a newer rate for the same currency pair or voluntarily withdrawn; the isExpired and expiryDateTime fields are historical markers only. Keeping rates current is the FXP's contractual responsibility under the Scheme Rulebook, and Nexus monitors corridor health without blocking payments to detect stale rates."}],"servers":[{"url":"http://localhost:8080","description":"Local development"},{"url":"https://nexus-ai-simulator-683365449922.asia-southeast1.run.app","description":"Nexus simulator"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT"}},"schemas":{"RateInputDto":{"type":"object","description":"Request body for creating a rate. Any live rate that already exists for the same FXP and currency pair is automatically superseded.","properties":{"sourceCurrency":{"type":"string","pattern":"^[A-Z]{3}$","description":"ISO 4217 currency code of the source currency, three uppercase letters."},"destinationCurrency":{"type":"string","pattern":"^[A-Z]{3}$","description":"ISO 4217 currency code of the destination currency, three uppercase letters."},"rate":{"type":"number","exclusiveMinimum":0,"description":"Exchange rate, where UnitCcyAmount multiplied by rate equals QtyCcyAmount. Must be greater than 0."}},"required":["sourceCurrency","destinationCurrency","rate"]},"RateDto":{"type":"object","description":"An exchange rate provided by an FXP for a specific currency pair. Each rate applies in one direction only, and the rate for the opposite direction is configured separately. A rate stays live until it is replaced by a newer rate for the same currency pair or withdrawn. Nexus does not expire rates based on time.","properties":{"id":{"type":"string","description":"Unique ID of the rate record."},"sourceCurrency":{"type":"string","pattern":"^[A-Z]{3}$","description":"ISO 4217 currency code of the source currency, three uppercase letters."},"destinationCurrency":{"type":"string","pattern":"^[A-Z]{3}$","description":"ISO 4217 currency code of the destination currency, three uppercase letters."},"rate":{"type":"number","exclusiveMinimum":0,"description":"Exchange rate, where UnitCcyAmount multiplied by rate equals QtyCcyAmount. Must be greater than 0."},"createdDateTime":{"type":"string","format":"date-time","description":"Timestamp at which the rate record was created."},"isExpired":{"type":"boolean","description":"Historical marker set to true when the rate is replaced or withdrawn. It does not mean the rate expired with time."},"expiryDateTime":{"type":["string","null"],"format":"date-time","description":"Timestamp at which the rate was replaced or withdrawn. A historical marker only."}},"required":["id","sourceCurrency","destinationCurrency","rate","createdDateTime","isExpired"]},"ErrorResultDto":{"type":"object","description":"Structured business rejection returned for all error responses. This response is only returned for rejection cases; the statusCode is always RJCT.","properties":{"statusCode":{"type":"string","enum":["RJCT"],"description":"Business level status code indicating the outcome. Always RJCT (Rejected)."},"reasonCode":{"type":"string","pattern":"^(TE|AE|BE)[A-Z0-9]*$","description":"Categorised reason code with a prefix indicating the error category: TE for Technical Error, AE for Authentication Error, BE for Business Error."},"name":{"type":"string","description":"Machine readable business error name from the error catalogue."},"description":{"type":"string","description":"Human readable error description."}},"required":["statusCode","reasonCode","name","description"]}}},"paths":{"/v1/rates":{"post":{"summary":"Create an FX rate","description":"Creates a new exchange rate for a currency pair. If a live rate already exists for the same currency pair, it is automatically marked as superseded and kept as a historical record. Quotes already issued against the previous rate remain valid for 10 minutes, known as the NQVT window. Nexus may throttle this endpoint, and an idempotency key header is recommended so that retried submissions are not duplicated. Requires the scope rates.write. Used by: FX Providers (FXPs)","operationId":"createRate","tags":["FXP Rates"],"parameters":[{"name":"Idempotency-Key","in":"header","required":false,"description":"Recommended for POST requests. A UUID used to deduplicate retried submissions.","schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateInputDto"}}}},"responses":{"200":{"description":"The created rate record.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateDto"}}}},"400":{"description":"Invalid request — syntax, schema, or field-level validation failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResultDto"}}}},"401":{"description":"Missing or invalid bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResultDto"}}}},"403":{"description":"Caller lacks permission for this resource or operation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResultDto"}}}},"409":{"description":"Update rejected due to conflicting state.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResultDto"}}}},"429":{"description":"Rate limit exceeded. Returned by the API gateway and carries no structured Nexus body. The Retry-After response header indicates when to retry."},"500":{"description":"Unexpected server fault; caller may retry.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResultDto"}}}}}}}}}
```

## List FX rates

> Returns your current live exchange rates, with optional filters for currency pair. Rate records are kept for up to 13 months and a maximum of 100 records is returned. When includeExpired is true, the limit parameter must be provided. Rates do not expire with time. A rate stays live until you replace it with a new rate for the same currency pair or withdraw it. Keeping rates up to date is your responsibility under the Scheme Rulebook. Requires the scope rates.read. Used by: FX Providers (FXPs)

```json
{"openapi":"3.1.0","info":{"title":"Nexus APIs","version":"0.3.1"},"tags":[{"name":"FXP Rates","description":"Rate management for FX Providers on the Nexus Config and Admin Portal. FXPs push exchange rates to Nexus for each currency pair; Nexus does not pull rates. Nexus uses these rates, together with any applicable improvements, to generate quotes for PSPs, and quotes are honoured for 10 minutes, known as the NQVT window. Nexus does not expire rates based on time and does not require periodic refresh. A rate stays live until it is replaced by a newer rate for the same currency pair or voluntarily withdrawn; the isExpired and expiryDateTime fields are historical markers only. Keeping rates current is the FXP's contractual responsibility under the Scheme Rulebook, and Nexus monitors corridor health without blocking payments to detect stale rates."}],"servers":[{"url":"http://localhost:8080","description":"Local development"},{"url":"https://nexus-ai-simulator-683365449922.asia-southeast1.run.app","description":"Nexus simulator"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT"}},"schemas":{"RateListDto":{"type":"object","description":"List of rate records belonging to the FXP.","properties":{"rates":{"type":"array","items":{"$ref":"#/components/schemas/RateDto"}}},"required":["rates"]},"RateDto":{"type":"object","description":"An exchange rate provided by an FXP for a specific currency pair. Each rate applies in one direction only, and the rate for the opposite direction is configured separately. A rate stays live until it is replaced by a newer rate for the same currency pair or withdrawn. Nexus does not expire rates based on time.","properties":{"id":{"type":"string","description":"Unique ID of the rate record."},"sourceCurrency":{"type":"string","pattern":"^[A-Z]{3}$","description":"ISO 4217 currency code of the source currency, three uppercase letters."},"destinationCurrency":{"type":"string","pattern":"^[A-Z]{3}$","description":"ISO 4217 currency code of the destination currency, three uppercase letters."},"rate":{"type":"number","exclusiveMinimum":0,"description":"Exchange rate, where UnitCcyAmount multiplied by rate equals QtyCcyAmount. Must be greater than 0."},"createdDateTime":{"type":"string","format":"date-time","description":"Timestamp at which the rate record was created."},"isExpired":{"type":"boolean","description":"Historical marker set to true when the rate is replaced or withdrawn. It does not mean the rate expired with time."},"expiryDateTime":{"type":["string","null"],"format":"date-time","description":"Timestamp at which the rate was replaced or withdrawn. A historical marker only."}},"required":["id","sourceCurrency","destinationCurrency","rate","createdDateTime","isExpired"]},"ErrorResultDto":{"type":"object","description":"Structured business rejection returned for all error responses. This response is only returned for rejection cases; the statusCode is always RJCT.","properties":{"statusCode":{"type":"string","enum":["RJCT"],"description":"Business level status code indicating the outcome. Always RJCT (Rejected)."},"reasonCode":{"type":"string","pattern":"^(TE|AE|BE)[A-Z0-9]*$","description":"Categorised reason code with a prefix indicating the error category: TE for Technical Error, AE for Authentication Error, BE for Business Error."},"name":{"type":"string","description":"Machine readable business error name from the error catalogue."},"description":{"type":"string","description":"Human readable error description."}},"required":["statusCode","reasonCode","name","description"]}}},"paths":{"/v1/rates":{"get":{"summary":"List FX rates","description":"Returns your current live exchange rates, with optional filters for currency pair. Rate records are kept for up to 13 months and a maximum of 100 records is returned. When includeExpired is true, the limit parameter must be provided. Rates do not expire with time. A rate stays live until you replace it with a new rate for the same currency pair or withdraw it. Keeping rates up to date is your responsibility under the Scheme Rulebook. Requires the scope rates.read. Used by: FX Providers (FXPs)","operationId":"listRates","tags":["FXP Rates"],"parameters":[{"name":"sourceCurrency","in":"query","required":false,"description":"ISO 4217 currency code of the source currency, three uppercase letters.","schema":{"type":"string","pattern":"^[A-Z]{3}$"}},{"name":"destinationCurrency","in":"query","required":false,"description":"ISO 4217 currency code of the destination currency, three uppercase letters.","schema":{"type":"string","pattern":"^[A-Z]{3}$"}},{"name":"includeExpired","in":"query","required":false,"description":"If true, include historical records that were replaced or withdrawn in the last 13 months. Default is false. When true, the limit parameter is required. Note that the word expired in field names is historical naming only; records are never expired based on time.","schema":{"type":"boolean","default":false}},{"name":"limit","in":"query","required":false,"description":"Maximum number of items to return. Default is 50 and the maximum is 100. Required when includeExpired is true.","schema":{"type":"integer","default":50,"maximum":100,"minimum":1}}],"responses":{"200":{"description":"The FXP's rates.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateListDto"}}}},"400":{"description":"Invalid request — syntax, schema, or field-level validation failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResultDto"}}}},"401":{"description":"Missing or invalid bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResultDto"}}}},"403":{"description":"Caller lacks permission for this resource or operation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResultDto"}}}},"429":{"description":"Rate limit exceeded. Returned by the API gateway and carries no structured Nexus body. The Retry-After response header indicates when to retry."},"500":{"description":"Unexpected server fault; caller may retry.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResultDto"}}}}}}}}}
```

## Withdraw an FX rate

> Withdraws a rate so it is no longer offered to PSPs. The response returns the withdrawn record with isExpired set to true as a historical marker. Quotes issued against this rate in the last 10 minutes remain valid. Requires the scope rates.write. Used by: FX Providers (FXPs)

```json
{"openapi":"3.1.0","info":{"title":"Nexus APIs","version":"0.3.1"},"tags":[{"name":"FXP Rates","description":"Rate management for FX Providers on the Nexus Config and Admin Portal. FXPs push exchange rates to Nexus for each currency pair; Nexus does not pull rates. Nexus uses these rates, together with any applicable improvements, to generate quotes for PSPs, and quotes are honoured for 10 minutes, known as the NQVT window. Nexus does not expire rates based on time and does not require periodic refresh. A rate stays live until it is replaced by a newer rate for the same currency pair or voluntarily withdrawn; the isExpired and expiryDateTime fields are historical markers only. Keeping rates current is the FXP's contractual responsibility under the Scheme Rulebook, and Nexus monitors corridor health without blocking payments to detect stale rates."}],"servers":[{"url":"http://localhost:8080","description":"Local development"},{"url":"https://nexus-ai-simulator-683365449922.asia-southeast1.run.app","description":"Nexus simulator"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT"}},"schemas":{"RateDto":{"type":"object","description":"An exchange rate provided by an FXP for a specific currency pair. Each rate applies in one direction only, and the rate for the opposite direction is configured separately. A rate stays live until it is replaced by a newer rate for the same currency pair or withdrawn. Nexus does not expire rates based on time.","properties":{"id":{"type":"string","description":"Unique ID of the rate record."},"sourceCurrency":{"type":"string","pattern":"^[A-Z]{3}$","description":"ISO 4217 currency code of the source currency, three uppercase letters."},"destinationCurrency":{"type":"string","pattern":"^[A-Z]{3}$","description":"ISO 4217 currency code of the destination currency, three uppercase letters."},"rate":{"type":"number","exclusiveMinimum":0,"description":"Exchange rate, where UnitCcyAmount multiplied by rate equals QtyCcyAmount. Must be greater than 0."},"createdDateTime":{"type":"string","format":"date-time","description":"Timestamp at which the rate record was created."},"isExpired":{"type":"boolean","description":"Historical marker set to true when the rate is replaced or withdrawn. It does not mean the rate expired with time."},"expiryDateTime":{"type":["string","null"],"format":"date-time","description":"Timestamp at which the rate was replaced or withdrawn. A historical marker only."}},"required":["id","sourceCurrency","destinationCurrency","rate","createdDateTime","isExpired"]},"ErrorResultDto":{"type":"object","description":"Structured business rejection returned for all error responses. This response is only returned for rejection cases; the statusCode is always RJCT.","properties":{"statusCode":{"type":"string","enum":["RJCT"],"description":"Business level status code indicating the outcome. Always RJCT (Rejected)."},"reasonCode":{"type":"string","pattern":"^(TE|AE|BE)[A-Z0-9]*$","description":"Categorised reason code with a prefix indicating the error category: TE for Technical Error, AE for Authentication Error, BE for Business Error."},"name":{"type":"string","description":"Machine readable business error name from the error catalogue."},"description":{"type":"string","description":"Human readable error description."}},"required":["statusCode","reasonCode","name","description"]}}},"paths":{"/v1/rates/{rateId}":{"delete":{"summary":"Withdraw an FX rate","description":"Withdraws a rate so it is no longer offered to PSPs. The response returns the withdrawn record with isExpired set to true as a historical marker. Quotes issued against this rate in the last 10 minutes remain valid. Requires the scope rates.write. Used by: FX Providers (FXPs)","operationId":"withdrawRate","tags":["FXP Rates"],"parameters":[{"name":"rateId","in":"path","required":true,"description":"UUID of the rate record to withdraw.","schema":{"type":"string"}}],"responses":{"200":{"description":"The withdrawn rate record.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateDto"}}}},"400":{"description":"Invalid request — syntax, schema, or field-level validation failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResultDto"}}}},"401":{"description":"Missing or invalid bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResultDto"}}}},"403":{"description":"Caller lacks permission for this resource or operation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResultDto"}}}},"404":{"description":"Rate not found for the specified id (or not configured for this FXP).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResultDto"}}}},"429":{"description":"Rate limit exceeded. Returned by the API gateway and carries no structured Nexus body. The Retry-After response header indicates when to retry."},"500":{"description":"Unexpected server fault; caller may retry.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResultDto"}}}}}}}}}
```

## Count FX rates

> Returns the number of rate records you have configured. Set includeExpired to true to include historical records that were replaced or withdrawn. Requires the scope rates.read. Used by: FX Providers (FXPs)

```json
{"openapi":"3.1.0","info":{"title":"Nexus APIs","version":"0.3.1"},"tags":[{"name":"FXP Rates","description":"Rate management for FX Providers on the Nexus Config and Admin Portal. FXPs push exchange rates to Nexus for each currency pair; Nexus does not pull rates. Nexus uses these rates, together with any applicable improvements, to generate quotes for PSPs, and quotes are honoured for 10 minutes, known as the NQVT window. Nexus does not expire rates based on time and does not require periodic refresh. A rate stays live until it is replaced by a newer rate for the same currency pair or voluntarily withdrawn; the isExpired and expiryDateTime fields are historical markers only. Keeping rates current is the FXP's contractual responsibility under the Scheme Rulebook, and Nexus monitors corridor health without blocking payments to detect stale rates."}],"servers":[{"url":"http://localhost:8080","description":"Local development"},{"url":"https://nexus-ai-simulator-683365449922.asia-southeast1.run.app","description":"Nexus simulator"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT"}},"schemas":{"CountDto":{"type":"object","description":"A simple record count.","properties":{"count":{"type":"integer","description":"The number of records."}},"required":["count"]},"ErrorResultDto":{"type":"object","description":"Structured business rejection returned for all error responses. This response is only returned for rejection cases; the statusCode is always RJCT.","properties":{"statusCode":{"type":"string","enum":["RJCT"],"description":"Business level status code indicating the outcome. Always RJCT (Rejected)."},"reasonCode":{"type":"string","pattern":"^(TE|AE|BE)[A-Z0-9]*$","description":"Categorised reason code with a prefix indicating the error category: TE for Technical Error, AE for Authentication Error, BE for Business Error."},"name":{"type":"string","description":"Machine readable business error name from the error catalogue."},"description":{"type":"string","description":"Human readable error description."}},"required":["statusCode","reasonCode","name","description"]}}},"paths":{"/v1/rates/count":{"get":{"summary":"Count FX rates","description":"Returns the number of rate records you have configured. Set includeExpired to true to include historical records that were replaced or withdrawn. Requires the scope rates.read. Used by: FX Providers (FXPs)","operationId":"getRatesCount","tags":["FXP Rates"],"parameters":[{"name":"includeExpired","in":"query","required":false,"description":"If true, include historical records that were replaced or withdrawn in the last 13 months. Default is false. When true, the limit parameter is required. Note that the word expired in field names is historical naming only; records are never expired based on time.","schema":{"type":"boolean","default":false}}],"responses":{"200":{"description":"The rate record count.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CountDto"}}}},"400":{"description":"Invalid request — syntax, schema, or field-level validation failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResultDto"}}}},"401":{"description":"Missing or invalid bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResultDto"}}}},"403":{"description":"Caller lacks permission for this resource or operation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResultDto"}}}},"429":{"description":"Rate limit exceeded. Returned by the API gateway and carries no structured Nexus body. The Retry-After response header indicates when to retry."},"500":{"description":"Unexpected server fault; caller may retry.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResultDto"}}}}}}}}}
```
