---
title: Apply for an API Token
description: Two paths to a MobiusQuant API token — 7-day anonymous trial or permanent token for logged-in users.
---

# API Token

`api.mobiusquant.ai` runs in a **tiered rate-limit model**:

- **Anonymous** (no `Authorization` header) — **10 req/min per IP**. Useful for quick exploration without registration.
- **With Bearer token** — **60 req/min per token**. Recommended for any non-trivial integration.

If you send an `Authorization` header but the token is invalid/expired/revoked, the API returns `401` (it does **not** fall back to anonymous — fix the token first).

This page covers **how to get a token**, how to use it, and how to handle errors.

## Two acquisition modes

| Mode | URL | TTL | Per-user cap | Use when |
|---|---|---|---|---|
| **Anonymous trial** | [/apply-token](https://www.mobiusquant.ai/zh/apply-token) | **7 days** | unlimited | Evaluation, prototyping, throwaway |
| **Permanent (logged-in)** | [/account](https://www.mobiusquant.ai/zh/account) → "API Tokens" | **never expires** | up to **10 active** per account | Production, long-running integrations |

Both token types are functionally identical at call time — same endpoints, same 60 req/min rate limit.

::: warning Plaintext is shown ONLY at creation
The plaintext `mq_<43 chars>` is returned once when you create the token. The server stores only `sha256(token)`. **Copy it immediately** to a password manager or `.env` file. If you lose it, you must create a new one — there is no recovery.
:::

## Anonymous trial (7 days)

For evaluating the API without registering an account.

1. Open <https://www.mobiusquant.ai/zh/apply-token>
2. (Optional) Give the token a recognizable name for your records
3. Pass the Cloudflare Turnstile human-verification check
4. Click "Apply for Token"
5. **Immediately copy** the `mq_xxx` value shown

The token expires automatically 7 days after creation. Calls with an expired token return `401 invalid, expired or revoked token`. Need another one? Just apply again — no per-email or per-IP cap.

## Permanent (logged-in)

For production. Tokens never expire, and you can see usage statistics per token.

1. Open <https://www.mobiusquant.ai/zh/account>
2. Sign in (Telegram or email; email accounts can also bind Telegram)
3. Find the "API Tokens" panel, click "New Token"
4. Pick a recognizable name (required, e.g. `production-2026`)
5. Immediately copy the `mq_xxx` value from the modal, click "I have saved it"

### Managing your tokens

| Action | How |
|---|---|
| List all tokens | Account → "API Tokens" panel. Revoked tokens hidden by default; toggle to show. |
| View usage history | Click "📊 Usage" on a token row. Last 50 calls + 7-day daily aggregate. |
| Revoke a token | Click "🗑 Revoke" on the row. Propagates to the engine within ~60 seconds. |

Each account can hold up to **10 active** (not-revoked, not-expired) tokens. Hitting the cap returns:

```http
HTTP/1.1 400 Bad Request
{"detail": "未吊销 token 已达上限 10,请先吊销旧的"}
```

## Using the token

Add an `Authorization` header to every request:

```bash
curl -H "Authorization: Bearer mq_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
     "https://api.mobiusquant.ai/api/markets"
```

```python
import requests

TOKEN = "mq_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
resp = requests.get(
    "https://api.mobiusquant.ai/api/klines",
    params={"exchange": "binance", "market": "perp",
            "symbol": "BTCUSDT", "interval": "5m", "limit": 100},
    headers={"Authorization": f"Bearer {TOKEN}"},
)
resp.raise_for_status()
print(resp.json())
```

```javascript
const TOKEN = "mq_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
const r = await fetch(
  "https://api.mobiusquant.ai/api/indicators",
  {
    method: "POST",
    headers: {
      "Content-Type":  "application/json",
      "Authorization": `Bearer ${TOKEN}`,
    },
    body: JSON.stringify({
      exchange: "binance", market: "perp", symbol: "BTCUSDT",
      interval: "5m", limit: 100,
      calc: [{ name: "ema", params: { period: 20 } }],
    }),
  },
);
const json = await r.json();
```

## Rate limit

- **Anonymous: 10 req/min per IP** (CF-Connecting-IP is the limit key — Cloudflare's real-client header).
- **With Bearer token: 60 req/min per token**.
- Token-bucket algorithm — burst = full minute's quota, you can fire all of it in one second then wait the full minute for the bucket to refill.
- **Exempt paths** (no token, no quota): `/api/health`, `/agents.md`, `/docs`, `/redoc`, `/openapi.json`.

When the bucket is empty:

```http
HTTP/1.1 429 Too Many Requests
Retry-After: 7
X-RateLimit-Limit: 30
X-RateLimit-Remaining: 0

{"detail": "rate limit exceeded (60/min); consider batching requests."}
```

**Honor `Retry-After`.** Tight retry loops will keep the bucket empty.

## Error codes

| HTTP | Meaning | What to do |
|---|---|---|
| `401` | You sent an `Authorization` header but the token is invalid / expired / revoked | Fix the token (no fallback to anonymous tier — must be correct or omitted entirely) |
| `429` | Rate-limit exceeded (10/min anonymous or 60/min with token) | Honor `Retry-After`; batch calls; apply a token to upgrade |
| `400` | Business-level parameter error | Read the `detail` field. **Do not blindly retry.** |
| `422` | Request structure invalid (missing required field, wrong type, unknown field) | Read the validation array, fix the request shape |
| `404` | Symbol not on venue, or cache empty (crypto cold-start) | Probe `/api/health` first; check `/api/markets/<venue>/symbols` |
| `502` | Upstream container restart | Retry in 30 seconds |

## Security recommendations

- **Never commit tokens** to public repos. Use environment variables or a secret manager. Add `.env` to `.gitignore`.
- If you suspect a leak, **revoke immediately** in the Account page and create a new token.
- Use **separate tokens per environment** (dev / staging / prod) to limit the blast radius of a leak.
- Front-end / browser code should call your own backend, which forwards to MobiusQuant — never put a token in client-side JavaScript.
