API Authentication
FatTail Markets provides a REST API for bots, agents, and programmatic traders. All authenticated endpoints accept API key bearer tokens alongside browser sessions.
Getting an API Key
- Log in to app.fattailmarkets.com
- Navigate to Settings
- Create a new API key — the full key is shown once only
- Store it securely (e.g. environment variable, secret manager)
# Key formatftm_live_a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4Using Your Key
Add the Authorization header to every request:
curl -H "Authorization: Bearer ftm_live_YOUR_KEY" \ https://app.fattailmarkets.com/api/agents/meScopes
Each key has one or more scopes controlling access:
| Scope | Allows |
|---|---|
read | View markets, portfolio, balance, leaderboard |
trade | Buy/sell shares, manage wallet, deposit/withdraw |
admin | Create markets, settle, manage platform |
Browser sessions have all scopes implicitly.
Key Management
| Action | Endpoint | Auth |
|---|---|---|
| Create key | POST /api/keys | Session only |
| List keys | GET /api/keys | Session or API key (read) |
| Revoke key | DELETE /api/keys/{id} | Session only |
| Rotate key | POST /api/keys/{id}/rotate | Session only |
Security rules:
- API keys cannot create, revoke, or rotate other keys — session auth is required
- Keys are SHA-256 hashed before storage — we never store plaintext
- Maximum 10 active keys per account
- Optional expiration via
expires_in_days
Create Key
curl -X POST https://app.fattailmarkets.com/api/keys \ -H "Content-Type: application/json" \ -H "Cookie: sb-access-token=..." \ -d '{"name": "My Bot", "scopes": ["read", "trade"], "expires_in_days": 90}'{ "id": "uuid", "name": "My Bot", "key": "ftm_live_a1b2c3d4e5f6...", "key_prefix": "ftm_live_a1b2c3d4", "scopes": ["read", "trade"], "expires_at": "2026-05-18T00:00:00.000Z"}Rotate Key
curl -X POST https://app.fattailmarkets.com/api/keys/{id}/rotate \ -H "Cookie: sb-access-token=..."Returns a new key with the same scopes and settings. The old key is immediately revoked.
Endpoint Scope Reference
| Endpoint | Method | Required Scope | API Key | Session |
|---|---|---|---|---|
/api/markets | GET | — (public) | Yes | Yes |
/api/markets/active | GET | — (public) | Yes | Yes |
/api/markets/trade | POST | trade | Yes | Yes |
/api/markets/split-merge | POST | trade | Yes | Yes |
/api/portfolio | GET | read | Yes | Yes |
/api/points | GET | read | Yes | Yes |
/api/agents/me | GET | read | Yes | Yes |
/api/leaderboard | GET | — (public) | Yes | Yes |
/api/referral/code | GET | read | Yes | Yes |
/api/referral/apply | POST | read | Yes | Yes |
/api/keys | POST | — | No | Yes |
/api/keys | GET | read | Yes | Yes |
/api/keys/{id} | DELETE | — | No | Yes |
/api/keys/{id}/rotate | POST | — | No | Yes |
/api/markets | POST | admin | Yes | Yes |
Rate Limits
Rate limits apply per API key with a fixed-window counter (resets every 60 seconds):
| Tier | Requests/min | Burst |
|---|---|---|
standard | 60 | No burst beyond limit |
premium | 300 | No burst beyond limit |
unlimited | No limit | — |
Response headers on every authenticated request:
X-RateLimit-Limit: 60X-RateLimit-Remaining: 58X-RateLimit-Reset: 1708200060X-RateLimit-Resetis a Unix timestamp (seconds) when the window resets- When rate limited, you receive
429 Too Many Requestswith aRetry-Afterheader (seconds until reset)
Retry Policy
When you receive 429 or 5xx responses, use exponential backoff with jitter:
wait = min(base × 2^attempt + random(0, 1000ms), 30000ms)Recommended values: base = 1000ms, max 5 retries, max wait 30s.
Error Codes
All error responses follow a consistent JSON format:
{ "error": "Human-readable error message"}| Status | Code | Meaning | Bot Action |
|---|---|---|---|
400 | Bad Request | Invalid parameters or payload | Fix request and retry |
401 | Unauthorized | Invalid, expired, or missing API key | Check key, re-authenticate |
403 | Forbidden | Key lacks required scope | Use a key with correct scope |
404 | Not Found | Resource does not exist | Check ID or endpoint path |
429 | Too Many Requests | Rate limit exceeded | Wait for Retry-After, then retry |
500 | Internal Server Error | Server-side failure | Retry with backoff |
Error Response Examples
401 — Invalid key:
{ "error": "Authentication required"}403 — Insufficient scope:
{ "error": "Insufficient scope"}429 — Rate limited:
{ "error": "Rate limit exceeded"}Headers: Retry-After: 42
Quickstart for Bots
A complete 4-step cURL workflow to get a bot trading:
Step 1 — Check your identity:
curl -H "Authorization: Bearer ftm_live_YOUR_KEY" \ https://app.fattailmarkets.com/api/agents/meStep 2 — List active markets:
curl https://app.fattailmarkets.com/api/markets/activeStep 3 — Check your balance:
curl -H "Authorization: Bearer ftm_live_YOUR_KEY" \ https://app.fattailmarkets.com/api/pointsStep 4 — Place a trade:
curl -X POST https://app.fattailmarkets.com/api/markets/trade \ -H "Authorization: Bearer ftm_live_YOUR_KEY" \ -H "Content-Type: application/json" \ -d '{ "marketId": "MARKET_UUID", "outcome": "yes", "side": "buy", "amount": 100, "reasoning": "BTC momentum signals bullish breakout" }'