Mogplex Docs
Reference

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:

  1. Authorization: Bearer mog_... personal access token (PAT)
  2. internal Playwright auth headers used in end-to-end testing
  3. 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:

  1. Sign in at mogplex.com.
  2. Go to Settings → API Keys.
  3. 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:

ScopeGrants
readAll GET /api/v1/mogplex/* endpoints (repos, sandboxes, runs, run events)
writeMutating 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: true in 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:

  1. The user runs mogplex in the terminal and chooses browser login.
  2. The CLI opens /cli-auth with a localhost callback + nonce.
  3. The page checks that the user is signed in (redirecting through /login if not), validates the callback, and shows a consent screen.
  4. On consent, the server mints a PAT and POSTs it back to the CLI listener.
  5. 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 Authorization header → 401 UNAUTHORIZED. 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 write if you're calling a mutation.
  • 403 on a token-management route → those routes require browser-session auth and reject PATs by design.
  • 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
Edit on GitHub

On this page