TRDEFI Liquidity API

Public, read-first API over the live non-custodial liquidity catalogue — and a prepare-only write path for integrators holding a key.

v1 base: https://yield.trdefi.com the API never signs

✓ Reading is free — no key

Every GET /api/* endpoint is open to anyone. Browse the catalogue, price a trade with /api/quote, pull stats, embed a badge. No signup, no credit card, no key. Machine-readable contract: openapi.json.

🔑 Creating a position needs a key

To initiate a trade — to create or swap a position through the API — you need an API key. The key prepares unsigned transactions; your own wallet signs them. The API never signs, never broadcasts and never holds funds.

Request API access →

The contract. Every response carries X-Request-Id. Every endpoint advertises RateLimit-Limit, RateLimit-Remaining, RateLimit-Reset and RateLimit-Policy — on success and on failure. Every error uses the same envelope.

Endpoints

MethodPathWhat it returns
GET/api/statsCatalogue totals, per-chain breakdown, top pairs by volume and by position count.
GET/api/chainsThe live set of supported chains and their counts. Treat as a catalog — never hardcode it.
GET/api/strategiesOpen liquidity positions. Filters: pair, chain, q.
GET/api/strategy-detail?hash=…A single position in detail.
GET/api/quote?hash=&chain=&amount=Indicative quote for one strategy. Nothing is signed.
GET/api/badge?metric=…shields.io endpoint payload for READMEs.
POST/v1/positions keyPrepare a position — returns unsigned transactions for your own wallet to sign. Nothing is broadcast.
GET/v1/positions/<strategyHash> keyTrack a position you prepared: prepared → shipped → filled. Only what we have actually observed on-chain.
GET/api/pilot demoLive state of the public test network demo. Same-origin only.
GET/api/balances?addresses=… demoDemo wallet balances on a test network. Same-origin only.

Response shape

Read endpoints return { data, meta }. The meta block is where freshness lives:

{
  "data": { "totals": { "strategies": 4685, "volume_30d_usd": 205811838.49, … }, … },
  "meta": {
    "requestId": "9f2c1d4e…",
    "generatedAt": "2026-09-24T02:11:05.376Z",
    "apiVersion": "v1",
    "freshnessSeconds": 10800,
    "cached": false
  }
}

Authentication

The read surface above needs no key. It is rate-limited and the limits are advertised in the headers of every reply.

The write path is prepare-only

Creating a position needs a key. The API never signs and never broadcasts. It returns the complete set of unsigned transactions, and your own wallet signs them from your own address. There is no signing grant, no delegated key, and no moment at which a credential of ours can move value.

POST /v1/positions
Authorization: Bearer trd_live_<keyId>_<secret>
Idempotency-Key: 8f14e45f-ea2b-4c1a-9b3e-1d2c3b4a5f60

{
  "chain": "arc",
  "wallet": "0xYourOwnWalletThatWillSign",
  "deposits": [
    { "symbol": "USDC", "amount": "1000000" },
    { "symbol": "EURC", "amount": "900000" }
  ],
  "makerFeeBps": 30000,
  "checkBalances": true
}

← 200 { data: {
          status: "prepared",            ← nothing has happened yet
          strategyHash: "0x9f71222e…",   ← identity of the position
          transactions: [ {step, purpose, to, value, data, description}, … ],
          fee: { protocolFeePercent: "0.05", removable: false },
          preflight: { status: "ready", checks: [ … ] }
        } }

You supply both amounts, so we never have to guess a price. The approve steps appear only where your live allowance is short — so the same position can come back as one transaction or three. Sign them in order with your own wallet, then broadcast. Add an Idempotency-Key and a retry returns the same strategyHash instead of creating a second position.

A key is always trd_live_<keyId>_<secret> (or trd_test_… for test networks), held server-side only — a key in client-side code is treated as compromised. Keys are scoped, origin-restricted and revocable at any time. Request one here.

The fee is inside the position. Every newly created position carries a 0.05 % protocol fee embedded in the signed order data — the same whether the position is created through the web app or the API. It is not a separate transfer, it cannot be removed by the integrator, and positions created before this rule keep their original on-chain terms. Reading data is free and always has been.

The two demo endpoints back the public test-network demo and are additionally restricted to TRDEFI's own pages (Origin/Referer). They are not general-purpose APIs and carry a tighter limit.

Rate limits

Limits are per path bucket and per credential. Read buckets are per client, so issuing more keys does not raise them; the prepare bucket is per key. Splitting one integration across many keys to raise an effective ceiling is a breach of the acceptable-use rules — ask for a raised bucket instead.

BucketLimitWindow
stats12060 s
badge12060 s
chains6060 s
quote6060 s
strategy-detail6060 s
strategies2060 s
pilot demo3060 s
balances demo3060 s
ship, swap (write)660 s
prepare (POST /v1/positions) keyagreed per key, default 660 s

Read the numbers from the response, not from this table — the headers are authoritative and may change before this page does:

curl -sD - -o /dev/null https://yield.trdefi.com/api/stats | grep -i ratelimit
ratelimit-limit: 120
ratelimit-remaining: 119
ratelimit-reset: 42
ratelimit-policy: stats;w=60;limit=120

On 429, Retry-After is always present. The limit resets on a fixed window.

Error codes

Branch on code, never on message. retryable is part of the contract.

CodeHTTPRetryableMeaning
BAD_REQUEST400noThe request could not be parsed.
INVALID_PARAMETER400noA parameter is missing or out of range.
UNAUTHORIZED401noMissing or invalid credential on a protected path.
FORBIDDEN403noOrigin or scope not allowed.
NOT_FOUND404noNo such resource.
METHOD_NOT_ALLOWED405noWrong HTTP method.
UNSUPPORTED_CHAIN422noChain not in the live catalog.
UNPROCESSABLE422noUnderstood, but cannot be executed as asked.
RATE_LIMITED429yesBack off using Retry-After.
INTERNAL500yesUnexpected error on our side.
UPSTREAM_UNAVAILABLE503yesOur data source is briefly unavailable.
UPSTREAM_TIMEOUT504yesOur data source did not answer in time.

Envelope

{
  "error": {
    "code": "RATE_LIMITED",
    "message": "Rate limit exceeded for stats",
    "requestId": "9f2c1d4e7a8b3c5d6e0f1a2b3c4d5e6f",
    "retryable": true,
    "documentation": "https://yield.trdefi.com/docs/api/errors#rate_limited"
  }
}

Client-fixable problems (an allowance too low, a balance too low, an unsupported chain) additionally carry a structured issues[] array with expected / actual, so you can correct them without contacting us.

Versioning & deprecation

Policy. Resources are path-versioned. Breaking changes ship under a new path version and are announced on the public calendar with a minimum 90 days' notice. Nothing is removed without a documented replacement. Additive fields — a new key in a response, a new value in an enum — may appear at any time and are not breaking; ignore what you do not recognise.
ChangeBreaking?How it ships
New field in a responsenoAny time
New endpointnoAny time
New value in an enumnoAny time — handle unknown values gracefully
New error codenoAny time — branch on known codes, fall back on the rest
Field removed or renamedyesNew path version + 90-day notice
Field type or meaning changedyesNew path version + 90-day notice
Endpoint removedyesReplacement published first + 90-day notice
Rate limit tightened—Headers change; limits are documented, never silent

Try it

# totals
curl -s https://yield.trdefi.com/api/stats | head -c 400

# which chains are live
curl -s https://yield.trdefi.com/api/chains

# a README badge
curl -s "https://yield.trdefi.com/api/badge?metric=volume30"

Request API access

Reading needs no key. To create positions through the API you need a key, and keys are issued after a short review — we need to know who you are, what you are building, and roughly what volume to expect.