Custom LP Routing (NEW)

The optional routing object on POST /requests and POST /public/quote allows you to constrain which liquidity providers (LPs) can fulfill your order or quote.

By default, requests are automatically load-balanced across all eligible LPs. Use routing to filter candidates based on pricing, uptime, or reliability, prioritize specific LPs, or enforce strict matching requirements.

Note:

  • Routing criteria apply to initial quote and order creation.
  • If targetNodeId is explicitly provided, it overrides the routing configuration.

Request Fields

FieldTypeDefaultDescription
rate.min, rate.maxnumber ≥ 0—Acceptable bounds for the LP's effective exchange rate.
rate.relativebooleanfalseWhen false, bounds represent absolute rates (e.g., 1370 to 1395 NGN per USDC). When true, bounds represent percentage deviations from the market rate (e.g., -1.0 to 0.0).
uptimenumber (0–100)—Minimum node uptime percentage required.
reliabilitynumber (0–100)—Minimum fulfillment success rate percentage required.
preferredLpsstring[] (UUIDs, max 100)—Ordered list of preferred LP node IDs. Prioritized ahead of general rotation.
fallbackbooleantrueDetermines behavior when no eligible LP satisfies all criteria. See Fallback Behavior.
  • Filter Evaluation: All provided criteria are combined using AND logic—an LP must satisfy every specified condition to qualify. Passing an empty object ("routing": {}) is invalid.
  • Rate Modes:
    • Absolute (relative: false): Evaluates the direct rate offered.
      Example: { "min": 1370, "max": 1395 } requires the effective rate to be between 1370 and 1395 NGN per USDC.
    • Relative (relative: true): Evaluates the LP's rate as a percentage spread against the current market rate.
      Example: { "min": -1, "max": 0, "relative": true } accepts rates between 1% below market rate and exactly market rate.

Selection Logic

When routing is enabled, LPs are evaluated in the following order:

  1. Preferred LPs: If preferredLps is provided, the API checks each listed node in order. The first LP that is active and satisfies all routing filters is selected immediately.
  2. Fair Rotation: If no preferred LPs are defined (or none match the criteria), the request is distributed across all remaining qualifying LPs using balanced round-robin rotation.
  3. Multi-LP / Split Orders: If the transaction volume exceeds a single LP’s available capacity, the split is allocated exclusively among qualifying LPs.

Fallback Behavior

When no liquidity providers meet your criteria, routing behaves according to the fallback flag:

fallbackBehavior
true (default)Falls back to standard round-robin selection across all active LPs (the resulting rate/LP may not meet your filters).
falseThe request is rejected immediately with a 400 Bad Request error (No liquidity provider matched the provided routing criteria).

Examples

1. Performance and Rate Constraints with Fallback

Matches LPs within a specific exchange rate window, requiring at least 99% uptime and 95% reliability. Falls back to standard LP pool if no match is found:

{
  "fromAsset": "USDC",
  "toAsset": "NGN",
  "amount": 150,
  "beneficiary": {
    "externalId": "user_ng_991",
    "destination": {
      "type": "BANK",
      "bankCode": "044",
      "accountNumber": "0123456789",
      "accountName": "John Doe"
    }
  },
  "routing": {
    "rate": { "min": 1370, "max": 1395, "relative": false },
    "uptime": 99,
    "reliability": 95,
    "fallback": true
  }
}

2. Strict Preferred LP List (No Fallback)

Attempts to route exclusively to specified nodes in priority order; fails if neither qualifies:

{
  "fromAsset": "NGN",
  "toAsset": "USDC",
  "amount": 50000,
  "destinationAddress": "GCFXH5C3YQBAW7OKL2AVZFYJ6IHLZN4SXKTWRVQPQG3E5QJWZ7M2UW3K",
  "routing": {
    "preferredLps": [
      "123e4567-e89b-12d3-a456-426614174000",
      "223e4567-e89b-12d3-a456-426614174001"
    ],
    "fallback": false
  }
}

3. Market-Relative Spread Bound

Accepts any LP offering a rate between 1% below market rate and market rate:

{
  "routing": {
    "rate": { "min": -1, "max": 0, "relative": true }
  }
}

Did this page help you?