Authentication
The Mogplex API resolves bearer tokens, internal Playwright headers, and browser sessions in that order. This page covers PAT issuance, scopes, rate limits, and the Idempotency-Key requirement on mutations.
The hosted Mogplex API is shared by the web app, the CLI, and internal test workflows.
That means auth is resolved in priority order instead of assuming every caller is a browser.
Auth resolution order
The common control-plane helper resolves in this order:
Authorization: Bearer mog_...personal access token (PAT)- internal Playwright auth headers used in end-to-end testing
- browser session auth from the signed-in web app
The public /api/v1/mogplex/* surface accepts only PATs — the Playwright
and session paths are for internal callers. Use a PAT for anything outside the
browser.
Personal access tokens
PATs use the mog_ bearer format: mog_ prefix followed by 32 base62
characters. They are stored as a SHA-256 hash; the plaintext value is shown to
you exactly once at creation time.
Issuing a PAT
Through the web UI:
- Sign in at mogplex.com.
- Go to Settings → API Keys.
- Click Create token, give it a name, pick scopes and (optionally) an expiry, and copy the plaintext value.
Through the management API (this endpoint requires browser-session auth — PATs can't issue other PATs):
curl -sS \
-X POST \
--cookie "$YOUR_SESSION_COOKIE" \
-H "Content-Type: application/json" \
-d '{"name":"laptop CLI","scopes":["read","write"],"expiresInDays":90}' \
"$MOGPLEX_BASE_URL/api/settings/api-keys"Response (the plaintext token field is returned once):
{
"id": "key-uuid",
"token": "mog_AbCdEf1234567890aBcDeF1234567890aB",
"prefix": "mog_AbCdEf12",
"scopes": ["read", "write"],
"expiresAt": "2026-08-15T00:00:00.000Z"
}The plaintext token is shown only at creation. The server stores a SHA-256 hash and the first 12 characters as a display prefix — neither can be reversed. If you lose the token, revoke the row and create a new one.
Revoking a PAT
curl -sS \
-X DELETE \
--cookie "$YOUR_SESSION_COOKIE" \
"$MOGPLEX_BASE_URL/api/settings/api-keys/{id}"Revocation sets revoked_at on the row. The next request that uses the
revoked token returns UNAUTHORIZED (401) — there is no grace period.
Expiry
If a token has expiresAt, requests after that timestamp return
UNAUTHORIZED (401). The CLI does not refresh tokens automatically; issue a
new one when an old one nears expiry.
Scopes
Two scopes exist today:
| Scope | Grants |
|---|---|
read | All GET /api/v1/mogplex/* endpoints (repos, sandboxes, runs, run events) |
write | Mutating endpoints: POST /runs, POST /runs/{id}/cancel, future sandbox lifecycle POSTs |
Tokens default to ["read", "write"] unless you explicitly request a smaller
set. Tokens issued before scope enforcement landed were backfilled to
["read", "write"] so existing automation kept working.
Read-only tokens are useful for dashboards, CI assertions, or analytics collectors — anything that should never start a run.
When a read-only token hits a write endpoint, the server returns:
{
"ok": false,
"error": {
"code": "FORBIDDEN",
"message": "Missing required scope: write. Issue a new token with the 'write' scope at /settings/api-keys."
}
}HTTP status: 403. See Errors for the full code table.
Rate limits
Per-PAT request limit
60 requests per 60 seconds per PAT, rolling window. When exceeded, the server returns:
HTTP/1.1 429 Too Many Requests
Retry-After: 60
Content-Type: application/json
{"ok":false,"error":{"code":"RATE_LIMITED","message":"Rate limit exceeded. Retry after 60s."}}Per-user run-start limits
POST /api/v1/mogplex/runs additionally enforces user-level run-start budgets:
- 10 run starts per minute
- 30 run starts per hour
- 150 run starts per day
These are independent of the per-PAT limit. A user with multiple PATs shares
the same run-start budget across them. Hitting any of these returns
RATE_LIMITED (429) with a Retry-After header.
If the limit-check backend is temporarily unavailable, the server returns
SERVICE_UNAVAILABLE (503) with Retry-After: 60 so callers know not to
hammer.
Idempotency-Key (required on mutations)
POST /api/v1/mogplex/runs requires an Idempotency-Key header. The header
makes safe retries possible: the server records the key + a hash of the request
body, and replays the original result on a duplicate request.
KEY=$(uuidgen)
curl -sS \
-X POST \
-H "Authorization: Bearer $MOGPLEX_TOKEN" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $KEY" \
-d '{"repoId":"<repo-id>","prompt":"Fix the tests"}' \
"$MOGPLEX_BASE_URL/api/v1/mogplex/runs"Behavior:
- Missing key → 400
BAD_REQUEST"Idempotency-Key is required". - Key longer than 200 chars → 400
BAD_REQUEST. - Same key, same body → replays the original result with
replayed: truein the response data. - Same key, different body → 409
IDEMPOTENCY_CONFLICT.
Use a fresh UUID per logical operation; reuse the same UUID across retries of the same operation.
The CLI's mogplex run auto-generates an idempotency key via
crypto.randomUUID() when you don't pass --idempotency-key. Pass one
explicitly when you orchestrate your own retries.
CLI browser handoff
The browser-based CLI login runs through /cli-auth:
- The user runs
mogplexin the terminal and chooses browser login. - The CLI opens
/cli-authwith a localhost callback + nonce. - The page checks that the user is signed in (redirecting through
/loginif not), validates the callback, and shows a consent screen. - On consent, the server mints a PAT and POSTs it back to the CLI listener.
- The CLI writes the token to
~/.mogplex/auth.json.
The CLI never sees raw session cookies; the browser never sees the CLI's private localhost port.
Practical debugging
If a request fails, identify which auth path you're on:
- No
Authorizationheader → 401UNAUTHORIZED. Set the header. - Header present, 401 → the token is invalid, expired, or revoked.
- Header present, 403 → the token works but lacks the required scope. Re-issue with
writeif you're calling a mutation. - 403 on a token-management route → those routes require browser-session auth and reject PATs by design.
Read next
- Errors — the full error code table and retry guidance
- Runs — the most common write endpoint, exercises every auth check above
- Working Requests — copy-paste curl examples for setup-state routes