Skip to main content

Authentication

The API binds to 0.0.0.0:8090 so anything on the same network can reach it. The PIN file at %APPDATA%\Seraph\pin.txt gates access. The PIN itself is printed at startup (PIN=<6 digits> at <path>) and rotates per process.

Flow

# 1. Exchange the PIN for a long-lived token.
curl -s -X POST http://localhost:8090/auth/pin \
-H 'content-type: application/json' \
-d '{"pin":"798465"}'
{ "token": "DLqXoY3WJmWqf3rL...0+9pjSjuBKP" }
# 2. Pass the token on every subsequent call.
curl -s http://localhost:8090/api/bots \
-H 'authorization: Bearer DLqXoY3WJmWqf3rL...0+9pjSjuBKP'

The token can also be sent as ?token=<token> on the query string — useful for <img> / EventSource callers that can't set headers.

Endpoints

GET /health

No auth required. Used by external monitors / load balancers to check the process is alive.

Response (200, text/plain):

ok

POST /auth/pin

Exchange the local PIN for a long-lived bearer token.

Body:

{ "pin": "798465" }

Response (200):

{ "token": "<base64-48-byte-token>" }

Errors:

StatusBody
401{"error":"wrong pin"}
429{"error":"locked, retry in 38s"}

GET /api-info

Bearer-protected helper that the embedded webview uses to discover its own port + token. Useful as a "did my token survive a restart?" ping from external tooling.

Response (200):

{
"port": 8090,
"token": "<the-same-token-you-just-sent>"
}

Rate limiting

A single token-bucket on /auth/pin slows down brute-force attempts. After enough wrong PINs the bucket locks and returns:

429 Too Many Requests
{"error":"locked, retry in 38s"}

The bucket is per-process; restarting Seraph resets it. The PIN itself is 6 digits = 1,000,000 candidates, but the bucket caps you at ~12 attempts/minute, so a real brute-force takes >50 days on average.