Authentication
API keys, scopes, rate limits, and the app session — how requests are identified.
API keys
Create keys on the API keys page after signing in with your wallet (Sign-In
with Ethereum, EIP-4361). A key looks like tp_live_… on production and tp_test_… on
staging; the prefix tells you — and any secret scanner — which deployment it belongs to.
A test key is refused by production before it is even looked up.
Send it on every request as either header:
X-API-Key: tp_live_a1b2c3…
Authorization: Bearer tp_live_a1b2c3…The full key is shown once, when it is created. Only a hash is stored. Disable a key the moment you suspect it leaked; re-enable it later if you were wrong — nothing is deleted, so usage stays attributable.
Scopes
| Scope | Grants |
|---|---|
read | Your own resting and closed orders, order status, and everything public data already allows at a higher rate limit. |
write | Placing and cancelling limit orders, market orders, Solana transaction builders. The wallet signature on each order is still required — the key identifies the caller, the signature authorises the trade. |
A wallet may hold five enabled keys at a time.
What needs a credential
| Data | Credential |
|---|---|
Public market data — /markets, /markets/{market}, /ticker, /book, /trades, bridge /quote | None required. Anonymous callers share a per-address ceiling; a key lifts it to the key's own limit. |
A wallet's orders — /users/{user}/orders, /users/{user}/orders/closed, ?user= filters | read, and the credential must belong to that wallet. |
Placing, cancelling, market orders, /tx/* | write. |
/settlements/report, /markets/{market}/close, /propose, /resolve | Operator tokens. Not issued to integrators. |
Rate limits
Limits are per key, per minute, in two budgets: reads at the key's limit (default 120), writes at the smaller of that and the venue's order budget. Every response carries:
RateLimit-Limit: 120
RateLimit-Remaining: 117
RateLimit-Reset: 42On refusal you get 429 with Retry-After (seconds) and a body
{ "error": "rate_limited", "retryAfterSeconds": 42 }. Back off for that long; a client
that retries in a tight loop only extends the window.
Migration timeline
Authentication is being introduced in three stages, switched per environment:
- observe — every call is identified and recorded; nothing is refused.
- warn — calls that will be refused receive
Deprecation: true, aSunsetdate and aLinkheader pointing here. Nothing is refused yet. - required — unidentified calls to protected routes get
401with adocslink.
If your integration sees a Deprecation header, add a key before the Sunset date.
The app session
The Daejin web app authenticates to these APIs with an httpOnly cookie it receives at login. That is for the app; integrations use API keys. There is no way to obtain the cookie outside a browser session and no reason to try.