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
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.
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.
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.
| Method | Path | What it returns |
|---|---|---|
| GET | /api/stats | Catalogue totals, per-chain breakdown, top pairs by volume and by position count. |
| GET | /api/chains | The live set of supported chains and their counts. Treat as a catalog — never hardcode it. |
| GET | /api/strategies | Open 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 key | Prepare a position — returns unsigned transactions for your own wallet to sign. Nothing is broadcast. |
| GET | /v1/positions/<strategyHash> key | Track a position you prepared: prepared → shipped → filled. Only what we have actually observed on-chain. |
| GET | /api/pilot demo | Live state of the public test network demo. Same-origin only. |
| GET | /api/balances?addresses=… demo | Demo wallet balances on a test network. Same-origin only. |
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
}
}
The read surface above needs no key. It is rate-limited and the limits are advertised in the headers of every reply.
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 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.
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.
| Bucket | Limit | Window |
|---|---|---|
stats | 120 | 60 s |
badge | 120 | 60 s |
chains | 60 | 60 s |
quote | 60 | 60 s |
strategy-detail | 60 | 60 s |
strategies | 20 | 60 s |
pilot demo | 30 | 60 s |
balances demo | 30 | 60 s |
ship, swap (write) | 6 | 60 s |
prepare (POST /v1/positions) key | agreed per key, default 6 | 60 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.
Branch on code, never on message. retryable is part of the contract.
| Code | HTTP | Retryable | Meaning |
|---|---|---|---|
BAD_REQUEST | 400 | no | The request could not be parsed. |
INVALID_PARAMETER | 400 | no | A parameter is missing or out of range. |
UNAUTHORIZED | 401 | no | Missing or invalid credential on a protected path. |
FORBIDDEN | 403 | no | Origin or scope not allowed. |
NOT_FOUND | 404 | no | No such resource. |
METHOD_NOT_ALLOWED | 405 | no | Wrong HTTP method. |
UNSUPPORTED_CHAIN | 422 | no | Chain not in the live catalog. |
UNPROCESSABLE | 422 | no | Understood, but cannot be executed as asked. |
RATE_LIMITED | 429 | yes | Back off using Retry-After. |
INTERNAL | 500 | yes | Unexpected error on our side. |
UPSTREAM_UNAVAILABLE | 503 | yes | Our data source is briefly unavailable. |
UPSTREAM_TIMEOUT | 504 | yes | Our data source did not answer in time. |
{
"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.
| Change | Breaking? | How it ships |
|---|---|---|
| New field in a response | no | Any time |
| New endpoint | no | Any time |
| New value in an enum | no | Any time — handle unknown values gracefully |
New error code | no | Any time — branch on known codes, fall back on the rest |
| Field removed or renamed | yes | New path version + 90-day notice |
| Field type or meaning changed | yes | New path version + 90-day notice |
| Endpoint removed | yes | Replacement published first + 90-day notice |
| Rate limit tightened | — | Headers change; limits are documented, never silent |
# 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"
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.