Ask for an invitation
Menu

Endpoint

Request a conversion

POST/v1/conversions

Requests a conversion of one of your balances into another asset or network, wallet to wallet, through the venue you chose from the offers. Nothing is converted until an Owner or Finance member approves it in the dashboard with a passkey; the offer is quoted again then, and the conversion is refused if the fresh output is below its minimum. The answer is 202 with the conversion awaiting_approval. See money out.

Scope a restricted key needs
conversions:write
Publishable key
Not allowed: secret or restricted key only
Idempotency-Key
Required. A request without it is refused.

Parameters

Parameters of Request a conversion
ParameterType and placeMeaning
Orrerie-VersionstringheaderAPI version date. Default: the version the key was created with. Example 2026-10-11.
Idempotency-KeyrequiredstringheaderRequired here: a person at your business approves what this request asks for (money out, or a new saved address), and a retry with the same key never asks for it twice. 1 to 255 characters.

Request body

A JSON object. The body is required. A field the call does not list is refused with parameter_unknown.

Request body of Request a conversion
FieldTypeMeaning
fromrequiredobject{asset, amount}; amount may be max.
to_assetrequiredstringThe asset id to convert into, as in the offer you chose.
venuerequiredstringThe venue you chose from the offers. One of relay, kyberswap, thorchain, sideshift, rubic, across.
max_slippage_bpsinteger10 to 300 (0.1% to 3%). Default 50. KyberSwap accepts at most 50.
metadataobjectYour own key-value data (rules in Metadata).

Example request

curl

curl https://api.orrerie.com/v1/conversions \
  -H "Authorization: Bearer $ORRERIE_SECRET_KEY" \
  -H "Idempotency-Key: 8f14e45f-ceea-467f-a9d2-6f1c2b3d4e5a" \
  -H "Content-Type: application/json" \
  -d '{
  "from": {
    "asset": "bitcoin:btc",
    "amount": "0.01"
  },
  "to_asset": "base:usdc",
  "venue": "relay"
}'

JavaScript

const response = await fetch("https://api.orrerie.com/v1/conversions", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.ORRERIE_SECRET_KEY}`,
    "Idempotency-Key": "8f14e45f-ceea-467f-a9d2-6f1c2b3d4e5a",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    "from": {
      "asset": "bitcoin:btc",
      "amount": "0.01"
    },
    "to_asset": "base:usdc",
    "venue": "relay"
  }),
});
const result = await response.json();
if (!response.ok) throw new Error(`${result.error.code}: ${result.error.message}`);
console.log(result);

Python

import os
import requests

response = requests.post(
    "https://api.orrerie.com/v1/conversions",
    headers={"Authorization": f"Bearer {os.environ['ORRERIE_SECRET_KEY']}", "Idempotency-Key": "8f14e45f-ceea-467f-a9d2-6f1c2b3d4e5a"},
    json={
        "from": {
            "asset": "bitcoin:btc",
            "amount": "0.01",
        },
        "to_asset": "base:usdc",
        "venue": "relay",
    },
    timeout=30,
)
result = response.json()
if not response.ok:
    raise RuntimeError(f"{result['error']['code']}: {result['error']['message']}")
print(result)

PHP

<?php
$request = curl_init('https://api.orrerie.com/v1/conversions');
curl_setopt_array($request, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_CUSTOMREQUEST => 'POST',
    CURLOPT_HTTPHEADER => [
        'Authorization: Bearer ' . getenv('ORRERIE_SECRET_KEY'),
        'Idempotency-Key: 8f14e45f-ceea-467f-a9d2-6f1c2b3d4e5a',
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => json_encode([
        'from' => [
            'asset' => 'bitcoin:btc',
            'amount' => '0.01',
        ],
        'to_asset' => 'base:usdc',
        'venue' => 'relay',
    ]),
]);
$body = curl_exec($request);
if ($body === false) {
    throw new RuntimeException(curl_error($request));
}
$result = json_decode($body, true);
if (curl_getinfo($request, CURLINFO_HTTP_CODE) >= 400) {
    throw new RuntimeException($result['error']['code'] . ': ' . $result['error']['message']);
}
print_r($result);

Responses

202 Accepted

The request was accepted and is waiting: for a person to approve it in the dashboard, or to be built in the background. Nothing has been signed or sent. The answer is the conversion object. Headers: Orrerie-Request-Id.

Example response, 202

{
  "id": "cv_ban2ezvpwf4j4d09h4htv42j",
  "object": "conversion",
  "livemode": true,
  "created": "2026-10-12T11:00:30.000Z",
  "updated": "2026-10-12T11:00:30.000Z",
  "status": "awaiting_approval",
  "pending_reason": null,
  "venue": "relay",
  "venue_progress": null,
  "from": {
    "wallet": "wal_zjdztygt4g73zm0cdcjjf43k",
    "asset": "bitcoin:btc",
    "amount": "0.01000000"
  },
  "to": {
    "wallet": "wal_bsfw07hymawmda7gg8jsyy3g",
    "asset": "base:usdc",
    "amount_estimated": "1168.420000",
    "amount_minimum": "1162.577900",
    "amount_received": null
  },
  "rate": "116842.00",
  "max_slippage_bps": 50,
  "fees": [
    {
      "kind": "route_fee",
      "amount": "1.38",
      "currency": "USD"
    },
    {
      "kind": "network_fee",
      "amount": "0.61",
      "currency": "USD"
    }
  ],
  "in_transit_notice": "While a conversion is being routed it is held by Relay, a separate company. Orrerie never holds it.",
  "requested_by": {
    "type": "api_key",
    "id": "key_6e3gg2c6ea176xxdek2nar6v"
  },
  "approved_by": null,
  "approval_url": "https://merchant.orrerie.com/approve/cv_ban2ezvpwf4j4d09h4htv42j",
  "approval_expires_at": "2026-10-19T11:00:30.000Z",
  "send_transaction_hash": null,
  "receive_transaction_hash": null,
  "failure_code": null,
  "cancellation_reason": null,
  "approved_at": null,
  "sent_at": null,
  "confirmed_at": null,
  "metadata": {}
}

Any other status: an error

A status of 400 or above answers with the error object. Branch on its code, never on its message.

Errors

Beside the errors every call can answer with (a bad key, a missing scope, the rate limit), this call answers with:

Errors of Request a conversion
CodeHTTPMeaning
idempotency_key_required400The endpoint moves money on approval (refunds, payouts, batches, conversions, saved addresses) and needs an Idempotency-Key.
conversion_no_route409The chosen venue has no route for this pair or amount now. error.offers_url lists what every venue says.
insufficient_balance409The available balance (amount minus reserved) of the source asset is too low; error.available gives it.
fee_account_low409The fee account cannot pay the network fee. error.needed says how much of which coin on which network must be held, for example {"asset": "tron:trx", "amount": "30"}.
rail_unavailable503The rail cannot be used now. error.reason is the exact refusal: relay_unavailable, relay_no_route, relay_amount_too_low, relay_low_liquidity, relay_paused, route_fee_over_cap, provider_route_mismatch, provider_deposit_mismatch, refund_wallet_unavailable, recipient_not_attested, or asset_not_covered; error.available_assets lists what can be used instead. Nothing was created at the provider and nothing was switched.
merchant_restricted403The merchant is restricted: new orders, payouts to others and conversions are off. Reads and withdrawals to saved addresses work.
wallet_needs_review409The wallet holds less than Orrerie's records show, because money left it that nothing recorded. Money out from it waits until an Owner has reviewed the wallet in the dashboard.
balance_changed409The balance moved after the amount was worked out, so the amount no longer holds. Ask again for a fresh one.