CorebanqCorebanq Developer Docs
FXv2

Create a new FX spread rule

Create a new FX spread rule with configurable bid/ask spreads

POST
/v2/fx/spreads

Authorization

bearerAuth
AuthorizationBearer <token>

In: header

Request Body

application/json

TypeScript Definitions

Use the request body type in TypeScript.

Request payload for creating or updating a spread rule

Response Body

application/json

application/json

application/json

application/json

application/json

application/json

application/json

application/json

curl -X POST "https://example.com/v2/fx/spreads" \  -H "Content-Type: application/json" \  -d '{    "bid_spread_bps": 50,    "ask_spread_bps": 50  }'
{
  "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  "fx_tariff_id": "f12d958c-c80c-4752-862c-9e0c09506488",
  "provider": "string",
  "base_currency": "string",
  "target_currency": "string",
  "rate_type": "BUY",
  "bid_spread_bps": 0,
  "ask_spread_bps": 0,
  "effective_from": "2019-08-24T14:15:22Z",
  "effective_to": "2019-08-24T14:15:22Z",
  "reason": "string",
  "active": true,
  "created_at": "2019-08-24T14:15:22Z",
  "created_by": "ee824cad-d7a6-4f48-87dc-e8461a9201c4",
  "modified_at": "2019-08-24T14:15:22Z",
  "modified_by": "e8d4374d-93a1-4e98-a6c6-fdcf00c5059f"
}
{
  "status": 409,
  "message": "Spread rule overlaps an existing rule",
  "code": "fx_m.spread_overlap",
  "class": "business",
  "retryable": false,
  "details": [
    {
      "field": "percent_fee",
      "rule": "lte",
      "param": "1",
      "message": "string"
    }
  ]
}
{
  "status": 409,
  "message": "Spread rule overlaps an existing rule",
  "code": "fx_m.spread_overlap",
  "class": "business",
  "retryable": false,
  "details": [
    {
      "field": "percent_fee",
      "rule": "lte",
      "param": "1",
      "message": "string"
    }
  ]
}
{
  "status": 409,
  "message": "Spread rule overlaps an existing rule",
  "code": "fx_m.spread_overlap",
  "class": "business",
  "retryable": false,
  "details": [
    {
      "field": "percent_fee",
      "rule": "lte",
      "param": "1",
      "message": "string"
    }
  ]
}
{
  "status": 409,
  "message": "Spread rule overlaps an existing rule",
  "code": "fx_m.spread_overlap",
  "class": "business",
  "retryable": false,
  "details": [
    {
      "field": "percent_fee",
      "rule": "lte",
      "param": "1",
      "message": "string"
    }
  ]
}
{
  "status": 429,
  "message": "Rate limit for 203.0.113.7 to GET:/v1/fx/rates exceeded.",
  "code": "rate_limits_m.exceeded",
  "class": "temporary",
  "retryable": true
}
{
  "status": 409,
  "message": "Spread rule overlaps an existing rule",
  "code": "fx_m.spread_overlap",
  "class": "business",
  "retryable": false,
  "details": [
    {
      "field": "percent_fee",
      "rule": "lte",
      "param": "1",
      "message": "string"
    }
  ]
}

{
  "overall_status": "unhealthy",
  "message": "Service is shutting down",
  "timestamp": "2026-08-27T15:04:05Z"
}

DELDelete FX tariff fee range

Deletes a fee range. Replies through apireply.Ok200.

GETConvert currency amount (v2)

Convert an amount between currencies. Only `amount` is strictly required — all other parameters fall back to operator-configured AppConfig defaults when omitted. Tariff is resolved via a four-step chain: fx_tariff_id query param → customer's assigned tariff (when customer_id provided) → convert.default_tariff_id AppConfig → the active tariff marked is_default = TRUE. THE APPCONFIG STEP CANNOT SUCCEED: getAppConfigFxTariff reads convert.default_tariff_id, unmarshals it into cfgID, and then queries Where("name = default AND active = true") — a literal with default unquoted, which PostgreSQL reads as the reserved word, so the statement is a syntax error rather than a lookup. The error is not ErrRecordNotFound, so the branch answers 500 common.database_error instead of falling through to the is_default row. The sample bundle ships the key set, so a convert that reaches this step on a default deployment fails; where the key is absent or inactive the step returns early and the is_default lookup is reached. FX date resolution is owned by the FX module business-date lookup policy, so omitted dates anchor to the current business date and optional lookback may resolve the most recent stored rate within the configured prior calendar-day window. Units: this surface carries the STORED fee range, so fee_range money fields are INTEGER MINOR units — unlike /v1/fx/rates/convert, which reports them in major units. amount_unit defaults to minor.