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, or paying per request with x402.

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 credential

To initiate a trade — to create or swap a position through the API — present either an API key (issued after a short review) or an x402 payment (pay-per-request, no account, no key to hold). Either way it 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=&from=&wallet=Quote for one strategy. from is an optional taker address used as msg.sender for the simulation. wallet asks for an executable Fusion price when the maker gated the position. Nothing is signed.
GET/api/badge?metric=…shields.io endpoint payload for READMEs.
POST/v1/positions key / x402Prepare a position — returns unsigned transactions for your own wallet to sign. Nothing is broadcast.
POST/v1/swaps key / x402Prepare a swap against a maker position already shipped. Simulated first; 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": <int>, "volume_30d_usd": <number>, … }, … },
  "meta": {
    "requestId": "<hex string>…",
    "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 write path also takes x402 — no key

A caller with no key can instead pay per request with x402. Call POST /v1/positions (or /v1/swaps) with no credential and the route answers 402 Payment Required with the payment terms (x402Version: 2, an accepts[] list, and a bazaar extension — the same JSON base64-encoded in the PAYMENT-REQUIRED header). Two rails: Base USDC (eip155:8453, settled by Coinbase's CDP facilitator) and Arc USDC (eip155:5042, settled by our own). The fee is a flat 0.02 USDC per request — additional to, and separate from, the 0.05 % protocol fee inside the position.

Pay with your own wallet and retry the same call with the encoded payment in a PAYMENT-SIGNATURE header (x402 v2; the deprecated v1 X-PAYMENT is still accepted); the reply carries meta.payment and a PAYMENT-RESPONSE header. A refused payment returns 402 PAYMENT_INVALID (never a fresh challenge, which would invite a double payment). A position prepared this way has no key and is not visible through the key-scoped GET /v1/positions/<hash>.

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.

For agents. The read surface is also exposed as a remote MCP server at /mcp — ten keyless tools, all prefixed trdefi_: trdefi_stats, trdefi_chains, trdefi_positions, trdefi_position_detail, trdefi_position_inventory, trdefi_quote, trdefi_fusion_quote, trdefi_fusion_prepare, trdefi_fusion_submit, trdefi_badge, so an agent can call the catalogue without writing HTTP. Transport: JSON-RPC 2.0 over POST — there is no browsable page at that path, so a browser GET returns 405 with "Use POST for the MCP endpoint.". That is expected; connect it as an MCP client.

In Replit Agent? Add it with one click: replit.com/integrations.

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, POST /v1/swaps) key / x402agreed 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": "<hex string, echoed per request>",
    "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"

Listings

Where this API is indexed, and what a third party has actually verified by paying for it.

SurfaceLinkVerified
PayAPI Marketpayapi.market/api/trdefi-liquidityPOST /v1/positions — settled payment, 0.02 USDC on Base, block 52475755
Payforapipayforapi.com/catalog/trdefi-liquidity-positionsBoth prepare endpoints listed; 402 verified live, 0.02 USDC on Base and Arc. Cards in English and Russian.
Coinbase x402 BazaarGET /v2/x402/discovery/search?query=trdefiBoth prepare endpoints indexed, return 402
MCP Registryio.github.TRDEFI/liquiditystatus: active, v1.0.0
Glamaglama.ai/mcp/connectors/io.github.TRDEFI/liquiditylisted
Smitherysmithery.ai/server/@trdefi/liquiditylisted
M8venm8ven.ai/mcp/trdefi-mcp-server-wq7ly5listed
mcpservers.orgmcpservers.org/servers/trdefi/mcp-serverlisted

Agents can search the PayAPI marketplace at https://payapi.market/mcp:

{ "mcpServers": { "payapi": { "url": "https://payapi.market/mcp" } } }
About the paid-verification badge

The badge currently sits on POST /v1/positions only — that is the route a third party has actually paid for. POST /v1/swaps is listed and callable and has no such badge. Quote simulation works on any pair the position trades, not only stablecoins; GET /api/strategies?quote_ready=true returns the positions on a network that has a quote route (the count changes hourly — read /api/stats for the live split). A 422 is a real answer, not a refusal: Strategy is gated means the maker requires the caller to hold an access token, Quote simulation is unavailable means the order bytes are not stored, No quote path for this network means the network has no quote RPC. Pass from=<address> — without it the call runs as address(0) and every gated strategy looks gated. Note GET /api/strategies ignores offset and page — there is no pagination, use the filters.

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. (If you would rather not hold a key, the same routes accept an x402 payment — pay-per-request, no account.)