Skip to content

API of Exchanges 📝

Introduction

The Exchanges API is the core swap surface of p3p. Use it to discover what's tradable, get the best quote across every aggregated liquidity source, lock that quote into an on chain swap, and track it to completion.

All endpoints below require an api-key header.

http
api-key: YOUR_P3P_API_KEY

Partner key = your fee

If you authenticate with your partner key (from the Partner Dashboard), the trade is attributed to you and your fee is automatically deducted from amount_to — on both /exchange/rate and /exchange/create. A generic developer key works for calling the endpoints but applies no fee and earns nothing. opts.partner_id in the body is not used for identity — only the key matters. See Earn revenue.

Endpoints


1. Get Chains

GET /chains api-key required

Returns every chain currently enabled on p3p.

bash
curl https://api.p3p.xyz/chains \
  -H "api-key: YOUR_P3P_API_KEY"
ts
const chains = await fetch("https://api.p3p.xyz/chains", {
  headers: { "api-key": "YOUR_P3P_API_KEY" },
}).then((r) => r.json());
json
{
  "status": 200,
  "message": "ok",
  "data": [
    {
      "id": 0,
      "key": "btc",
      "name": "Bitcoin",
      "display": "BTC Chain",
      "color": "#F7931A",
      "logo": "",
      "icon": "token:btc",
      "explorer": {
        "address": "https://mempool.space/address/%s",
        "tx": "https://mempool.space/tx/%s"
      },
      "website": "https://bitcoin.org",
      "vm": "BVM",
      "validation": [
        "^(1[1-9A-HJ-NP-Za-km-z]{25,34}|3[1-9A-HJ-NP-Za-km-z]{25,34}|bc1[qpzry9x8gf2tvdw0s3jn54khce6mua7l]{8,87})$"
      ],
      "defaults": ["btc"],
      "tags": ["bitcoin", "btc", "xbt", "satoshi"],
      "enabled": true
    },
    {
      "id": 1,
      "key": "eth",
      "name": "Ethereum",
      "display": "ETH Chain",
      "color": "#627EEA",
      "logo": "",
      "icon": "token:eth",
      "explorer": {
        "address": "https://etherscan.io/address/%s",
        "tx": "https://etherscan.io/tx/%s"
      },
      "website": "https://ethereum.org",
      "vm": "EVM",
      "validation": [
        "^(0x)[0-9A-Fa-f]{40}$"
      ],
      "defaults": ["eth", "usdt", "usdc", "dai"],
      "tags": ["ethereum", "eth", "eht", "vitalik"],
      "enabled": true
    }
  ]
}

2. Get Tokens

GET /tokens api-key required

Returns enabled tokens grouped by chain.

bash
curl https://api.p3p.xyz/tokens \
  -H "api-key: YOUR_P3P_API_KEY"
json
{
  "eth": [
    { "key": "eth", "name": "Ether", "symbol": "ETH", "decimals": 18, "rate": "3421.8", "address": "", "native": true, "enabled": true },
    { "key": "usdt", "name": "Tether", "symbol": "USDT", "decimals": 6, "rate": "1.0", "address": "0xdac17f958d2ee523a2206206994597c13d831ec7", "native": false, "enabled": true }
  ],
  "ton": [
    { "key": "ton", "name": "Toncoin", "symbol": "TON", "decimals": 9, "rate": "5.23", "address": "", "native": true, "enabled": true },
    { "key": "usdt", "name": "USDT (TON)", "symbol": "USDT", "decimals": 6, "rate": "1.0", "address": "EQCxE6mUtQJKFnGfaROTKOt1lZbDiiX1kCixRv7Nw2Id_sDs", "native": false, "enabled": true }
  ]
}

3. Get Rates

GET /rates api-key required

Returns live market reference rates for every supported asset, sourced from on chain oracles.

bash
curl https://api.p3p.xyz/rates \
  -H "api-key: YOUR_P3P_API_KEY"
json
{
  "btc": 98234.56,
  "eth": 3421.8,
  "ton": 5.23,
  "usdt": 1.0,
  "usdc": 1.0,
  "sol": 142.35
}

4. Quote Exchange Rate

POST /exchange/rate api-key required

Aggregate rates from every active liquidity source and return the best (or all of them).

Body

FieldTypeRequiredDescription
chain_fromstringyesSource chain key
token_fromstringyesSource token key
amount_fromstringyesAmount in display units
chain_tostringyesDestination chain key
token_tostringyesDestination token key
opts.bestbooleannoSort by best rate (default)
opts.fastestbooleannoSort by fastest rate instead of best
opts.partner_idstringnoIgnored for attribution — your fee/identity come from the partner api-key header. See Earn revenue.
bash
curl -X POST https://api.p3p.xyz/exchange/rate \
  -H "Content-Type: application/json" \
  -H "api-key: YOUR_P3P_API_KEY" \
  -d '{
    "chain_from": "eth",
    "token_from": "eth",
    "amount_from": "0.1",
    "chain_to": "ton",
    "token_to": "ton",
    "opts": { "best": true }
  }'
ts
const rate = await fetch("https://api.p3p.xyz/exchange/rate", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "api-key": "YOUR_P3P_API_KEY",
  },
  body: JSON.stringify({
    chain_from: "eth",
    token_from: "eth",
    amount_from: "0.1",
    chain_to: "ton",
    token_to: "ton",
    opts: { best: true },
  }),
}).then((r) => r.json());
json
{
  "type": "crypto",
  "path_from": "eth.eth",
  "path_to": "ton.ton",
  "amount_from": "0.1",
  "amount_to": "342.18",
  "direction": "exact_input",
  "amount_from_unit": 0.1,
  "amount_to_unit": 342.18,
  "rate": "3421.8",
  "impact": "0.01",
  "duration": 90,
  "boosted": false
}

5. Create Exchange

POST /exchange/create api-key required

Lock a rate, create an exchange and receive a deposit address.

Body

FieldTypeRequiredDescription
chain_fromstringyesSource chain key
token_fromstringyesSource token key
amount_fromstringyesAmount in display units
chain_tostringyesDestination chain key
token_tostringyesDestination token key
wallet_tostringyesRecipient address on the destination chain
wallet_refundstringnoRefund address if the swap cannot complete
wallet_fromstringnoThe user's source address (some chains need it)
opts.bestbooleannoSort by best rate (default)
opts.fastestbooleannoSort by fastest rate instead of best
opts.tg.idstringnoTelegram user/chat ID. Stored with the exchange so you can correlate it back to your own user.
opts.tg.usernamestringnoTelegram username. Stored with the exchange.
opts.partner_idstringnoIgnored for attribution — your fee/identity come from the partner api-key header. See Earn revenue.

Address Validation

All provided addresses (wallet_to, wallet_refund, wallet_from) are validated against the respective chain's validation rules. Use the validation regex patterns from Get Chains to validate user input on your client before submitting to the API. Each chain supports specific address formats (e.g. Bitcoin: p2pkh, p2sh, bech32; EVM chains: 40 hex characters prefixed with 0x; Solana: 43-44 base58 characters).

bash
curl -X POST https://api.p3p.xyz/exchange/create \
  -H "Content-Type: application/json" \
  -H "api-key: YOUR_P3P_API_KEY" \
  -d '{
    "chain_from": "eth", "token_from": "eth", "amount_from": "0.1",
    "chain_to":   "ton", "token_to":   "ton",
    "wallet_to":     "UQAbc...XYZ",
    "wallet_refund": "0xRefund...address",
    "opts": { "tg": { "id": "123456789", "username": "alice" } }
  }'
# Authenticate with your PARTNER api-key (above) to attribute the trade and apply your fee.
ts
const exchange = await fetch("https://api.p3p.xyz/exchange/create", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "api-key": "YOUR_P3P_API_KEY",
  },
  body: JSON.stringify({
    chain_from: "eth",
    token_from: "eth",
    amount_from: "0.1",
    chain_to: "ton",
    token_to: "ton",
    wallet_to: "UQAbc...XYZ",
    wallet_refund: "0xRefund...address",
    opts: { tg: { id: "123456789", username: "alice" } }, // your own identifier, stored with the exchange
  }),
}).then((r) => r.json()); // attribution + fee come from the partner api-key header above
json
{
  "created_at": "2026-05-24T10:30:00Z",
  "id": "ex_8f4c2a...",
  "type": "crypto",
  "chain_from": "eth",
  "token_from": "eth",
  "amount_from": "0.1",
  "chain_to": "ton",
  "token_to": "ton",
  "amount_to": "342.18",
  "amount_to_unit": 342.18,
  "wallet_refund": "0xRefund...address",
  "wallet_from": "",
  "wallet_to": "UQAbc...XYZ",
  "deposit_address": "0xDepositAddressGeneratedForYou",
  "rate": "3421.8",
  "impact": "0.01",
  "duration": 90
}

For partner exchanges (when using api-key header): The response returns hash instead of id:

json
{
  "created_at": "2026-05-24T10:30:00Z",
  "hash": "A7K2M9X5B3C1D8F4",
  "type": "crypto",
  "chain_from": "eth",
  "token_from": "eth",
  "amount_from": "0.1",
  "chain_to": "ton",
  "token_to": "ton",
  "amount_to": "342.18",
  "amount_to_unit": 342.18,
  "wallet_to": "UQAbc...XYZ",
  "deposit_address": "0xDepositAddressGeneratedForYou",
  "rate": "3421.8",
  "impact": "0.01",
  "duration": 90
}

Send amount_from of token_from from your wallet to deposit_address to start the swap. Track progress with Check Exchange Status below.

Partner exchanges are private

Partner exchanges (identified by hash) are only accessible by passing the hash as the ID with your api-key header. They cannot be queried by normal transaction ID.

Deposit window

The deposit must match amount_from exactly and arrive within ~6 minutes. After timeout you can retry with ?bump=true on the status endpoint.


6. Check Exchange Status

GET /check/:txId api-key required

Get the current state of a single exchange or invoice.

QueryTypeDescription
bumpbooleanIf true, retries a stalled/timed out exchange
bash
curl https://api.p3p.xyz/check/ex_8f4c2a... \
  -H "api-key: YOUR_P3P_API_KEY"
json
{
  "id": "ex_8f4c2a...",
  "created_at": "2026-05-24T10:30:00Z",
  "status": "exchanging",
  "type": "internal",
  "invoice": false,
  "chain_from": "eth",
  "token_from": "eth",
  "amount_from": "0.1",
  "chain_to": "ton",
  "token_to": "ton",
  "amount_to": "342.18",
  "amount_to_unit": 342.18,
  "wallet_to": "UQAbc...XYZ",
  "deposit_address": "0xDepositAddressGeneratedForYou",
  "checkpoint": 3,
  "checkpoints": 5
}

Status values

StatusMeaning
newWaiting for the user deposit
depositedDeposit detected, preparing the swap
processingSwap submitted to the liquidity source, awaiting confirmation
exchangingSwap confirmed, funds are being exchanged
completeDone — recipient has received the funds
timeoutDeposit window expired; call with ?bump=true to reset and retry
errorExchange encountered an error; call with ?bump=true to retry
expiredExchange has expired and can no longer be retried

Bump retry

If a trade times out (no deposit detected within the deposit window), call the endpoint again with ?bump=true to reset the window:

bash
curl "https://api.p3p.xyz/check/ex_8f4c2a...?bump=true" \
  -H "api-key: YOUR_P3P_API_KEY"

Partner exchanges (created with api-key header) can be queried by passing the hash as the ID. If an api-key header is present, the system automatically tries to match it as a hash first:

bash
# Using partner api-key — looks up by hash
curl https://api.p3p.xyz/check/A7K2M9X5B3C1D8F4 \
  -H "api-key: YOUR_PARTNER_API_KEY"
json
{
  "hash": "A7K2M9X5B3C1D8F4",
  "created_at": "2026-05-24T10:30:00Z",
  "status": "complete",
  "type": "internal",
  "invoice": false,
  "chain_from": "eth",
  "token_from": "eth",
  "amount_from": "0.1",
  "chain_to": "ton",
  "token_to": "ton",
  "amount_to": "342.18",
  "amount_to_unit": 342.18,
  "wallet_to": "UQAbc...XYZ",
  "deposit_address": "0xDepositAddressGeneratedForYou",
  "checkpoint": 5,
  "checkpoints": 5
}

Hash format

By default, hashes are 40 alphanumeric characters (a-z, A-Z, 0-9). Partners can customize the format via the Partner Dashboard.


7. Check Multiple Exchanges

POST /check api-key required

Check several trades in one call.

Body

FieldTypeRequiredDescription
hashesstring[]yesArray of exchange IDs hashes
bash
curl -X POST https://api.p3p.xyz/check \
  -H "Content-Type: application/json" \
  -H "api-key: YOUR_P3P_API_KEY" \
  -d '{ "hashes": ["ex_8f4c2a...", "ex_aa11bb..."] }'

Returns an array of minified exchange status objects:

json
[
  {
    "hash": "ex_8f4c2a...",
    "status": "complete",
    "type": "crypto",
    "invoice": false,
    "chain_from": "eth",
    "token_from": "eth",
    "amount_from": "0.1",
    "chain_to": "ton",
    "token_to": "ton",
    "amount_to": "342.18",
    "checkpoint": 4,
    "checkpoints": 4
  },
  {
    "hash": "A7K2M9X5B3C1D8F4",
    "status": "exchanging",
    "type": "crypto",
    "invoice": false,
    "chain_from": "ton",
    "token_from": "usdt",
    "amount_from": "100",
    "chain_to": "eth",
    "token_to": "usdc",
    "amount_to": "99.5",
    "checkpoint": 2,
    "checkpoints": 4
  }
]