Skip to main content
Before you can trade a pair, someone has to be offering it. This guide finds who, checks how much they can fill, reads the rate, and hands you what you need to create a quote. The order matters. A rate existing for a pair does not mean anyone will trade it, and a provider being listed does not mean they can cover your size.

What you’ll need

  • Your secret key.
  • A currency pair in mind.
Listings live on the exchange service, rates on the main service:
  • https://api.hyperrails.io/exchange/api/v1 — marketplace listings
  • https://api.hyperrails.io/api/v1 — rates
Listings answer on both base URLs, but treat the exchange one as canonical.

The shape of the flow

1

List who is offering

See every live listing, its pair, its rate, and how much it can fill.
2

Check the published rate

The reference rate for the pair.
3

Reconcile the two

They will differ. Work out which one you actually get.
4

Price a quote against it

Turn a listing into a real trade.

Step 1: List who is offering

availableBalance is the real constraint, and it is often small. The NGN/GHS listing above could fill only 3,080.27 NGN — about 26 GHS at its own rate. The NGN/USD listing next to it had 99 billion. Two listings on the same screen, four orders of magnitude apart.Ask for more than a provider holds and the quote fails with 400:
Check availableBalance before you size a trade, not after.
Liquidity is consumed as trades settle, and the list is a snapshot. A single trade of 5 GHS moved the NGN/GHS listing from 768.27 to 190.27. Re-read the listings immediately before quoting; do not cache this.
The whole marketplace was two listings. There is no guarantee any given pair has a provider at all — if your pair is absent here, no rate will save you.

Step 2: Check the published rate

The parameters are base and quote, not source and destination — even though the quote and intent endpoints use sourceCurrency and destinationCurrency. Getting it wrong returns 400:
Note it names only base, the first missing parameter. Fixing that one alone then fails on quote.
A pair with no rate returns 404 with an empty body. Not a JSON error object — nothing at all. Parsing the body unconditionally will throw. Branch on the status code first.
timestamp can be months old — the GHS/NGN rate above was set in April and read in September. These are administered reference rates, not a live market feed. Do not treat the rate as fresh, and do not poll it expecting movement.

Step 3: Reconcile the two

This is the step that surprises people. The published rate and the rate you actually trade at are different numbers, and the published rate is not even symmetric: Three numbers for one pair. What each is for:
  • The listing rate is what you get. It is the provider’s own price. A real quote for 5 GHS → NGN allocated against the NGN/GHS listing at exactly 115.60, and settled 578.00 NGN.
  • The published rate is a reference. Use it to sanity-check and to display an indicative price before you quote.
  • Direction changes the published rate, because each direction is administered separately. inverseRate is the true inverse of the rate you asked for — 1 / 128.77 = 0.0077657840. It is not the rate for the reverse pair. Never invert a rate yourself to price the other direction; ask for it.
Quote off the listing, not the published rate. Pricing a customer at 128.77 when the liquidity fills at 115.60 is a 10% error in your favour that the trade will not honour.
The authoritative answer comes back in the quote itself, as allocationResult.weightedAverageRate. When liquidity spans several listings you get a blend, so read it from the quote rather than computing it.

Step 4: Price a quote against it

You now have a pair with a real provider and a size that fits inside availableBalance. Create the quote:
The allocation tells you which listing filled it:
Note that no payment block is needed to price a quote — you can get a real, allocated price before you have any payment details from the customer. poolId and clientId match the listing from Step 1 exactly — that is how you confirm you got the provider you priced against.
allocations is an array because a large trade can be split across several providers at different rates. weightedAverageRate is the blend. A single-provider fill, as above, has one entry and the rate matches the listing.
A rate existing does not mean a provider exists. GHS→USDT returns a valid rate of 11.55, but quoting it returns 400 "No providers available for the given intent configuration" — there is no USDT listing in the marketplace. Always check Step 1 before trusting Step 2.

When things go wrong

What to do next