Starkscan

Self-serve account routes

Session-authenticated routes for the signed-in user's personal Starkscan workspace and self-serve API keys.

Self-serve account routes

Use /v1/me/* when you are acting as the signed-in operator of your personal Starkscan workspace rather than as an external API-key caller.

These routes back the hosted /api-key experience and expose the same personal-workspace self-serve control plane over HTTP.

Auth

Do not send X-Starkscan-Api-Key to this lane.

Authenticate with a Better Auth session instead:

  • hosted browser flow: safe reads (GET / HEAD / OPTIONS) can use the Starkscan session cookies
  • server or CLI flow: send Authorization: Bearer <better_auth_session_token>

If the session is missing or invalid, Starkscan returns 401 Unauthorized. That body is deliberately generic and carries docSlug: "api/self-serve"; it does not disclose whether a supplied credential was missing, expired, or revoked. Programmatic API-key callers should discover their active scopes, route classes, and quota contract from GET /v1/meta/capabilities's caller object instead of calling /v1/me/*. If you try to POST or DELETE with cookies only, Starkscan returns 403 Forbidden with a WWW-Authenticate: Bearer header.

Routes

RouteWhat it does
GET /v1/me/api-keyslist self-serve keys for the authenticated personal workspace
POST /v1/me/api-keysissue or rotate the default live read + batch + write key
DELETE /v1/me/api-keys/{public_id}revoke one self-serve key
POST /v1/me/redeem-codeatomically redeem a single-use workspace-plan access code
GET /v1/me/usageload recent usage, failures, and per-key aggregates for the authenticated personal workspace

Rules

  • GET /v1/me/api-keys returns metadata only. It never returns plaintext secrets.
  • GET /v1/me/api-keys returns a bounded newest-first slice plus truncated=true when older historical keys exist outside the response.
  • POST /v1/me/api-keys returns the plaintext key once for the new or rotated default key.
  • If a default live key already exists, POST /v1/me/api-keys revokes it in the same operation and returns action=rotated.
  • DELETE /v1/me/api-keys/{public_id} revokes the selected key and returns its final metadata snapshot.
  • POST /v1/me/redeem-code accepts { "code": "..." }, atomically updates the authenticated workspace plan, and consumes the code. Expired, revoked, already-used, missing, and malformed codes all return the same invalid-code error.
  • GET /v1/me/usage is a recent operational window, not a billing export, and it surfaces truncation flags on every bounded list.
  • POST and DELETE on /v1/me/* are bearer-only on purpose. Starkscan rejects cookie-only mutations to avoid CSRF on key rotation/revocation.
  • These routes are Cache-Control: no-store on purpose.
  • Every newly issued authenticated self-serve key receives read, batch, and write. There is no per-key scope picker or invite gate. Submitted scope, tier, or invite fields do not change that server-owned default.
  • write is an entitlement, not a promise that forwarding is active. Execution requires rpcProvider.writeBeta.enabled, the forwarding flag, structural payload validation, a dedicated write upstream, plan rate and credit capacity, and the global kill switch. Structural validation rejects malformed payload shapes; it does not vouch for signature authority or funds.
  • Existing keys are not backfilled or downgraded: their stored scopes, status, and policy remain unchanged until the owner explicitly rotates or revokes them.
  • Some scopes remain deliberately outside self-serve: prove, which grants STRK20 prover relay access, and trace are operator-issued only and are refused on this lane even if requested explicitly. Existing operator-scoped keys still appear in GET /v1/me/api-keys with their scopes.

Examples

Export a session token if you are calling this lane outside the hosted browser:

export STARKSCAN_SESSION_TOKEN="<better_auth_session_token>"
# Optional: only set this for preview or self-hosted hosts.
# export STARKSCAN_BASE_URL="https://preview.example.com/api"

List keys:

curl \
  -H "Authorization: Bearer $STARKSCAN_SESSION_TOKEN" \
  "${STARKSCAN_BASE_URL:-https://api.starkscan.co}/v1/me/api-keys"

Issue or rotate the default key:

curl -X POST \
  -H "Authorization: Bearer $STARKSCAN_SESSION_TOKEN" \
  "${STARKSCAN_BASE_URL:-https://api.starkscan.co}/v1/me/api-keys"

Revoke one key:

curl -X DELETE \
  -H "Authorization: Bearer $STARKSCAN_SESSION_TOKEN" \
  "${STARKSCAN_BASE_URL:-https://api.starkscan.co}/v1/me/api-keys/<public_id>"

Redeem a workspace-plan access code:

read -r -s STARKSCAN_ACCESS_CODE
printf '\n'
printf '%s' "$STARKSCAN_ACCESS_CODE" |
  python3 -c 'import json, sys; print(json.dumps({"code": sys.stdin.read()}))' |
curl -X POST \
  -H "Authorization: Bearer $STARKSCAN_SESSION_TOKEN" \
  -H "Content-Type: application/json" \
  --data-binary @- \
  "${STARKSCAN_BASE_URL:-https://api.starkscan.co}/v1/me/redeem-code"
unset STARKSCAN_ACCESS_CODE

Inspect recent usage:

curl \
  -H "Authorization: Bearer $STARKSCAN_SESSION_TOKEN" \
  "${STARKSCAN_BASE_URL:-https://api.starkscan.co}/v1/me/usage"

Response shape highlights

  • key list items include environment, scopes, status, masked key, rate-limit policy, and lifecycle timestamps
  • issue/rotate responses include plaintextKey, apiKey, and revokedPublicIds
  • usage snapshots include:
    • totalRequests
    • totalFailures
    • perKey
    • perKeyTruncated
    • recentRequests
    • recentRequestsTruncated
    • recentFailures
    • recentFailuresTruncated
  • recent usage events include request id, status, app-observed latencyMs, API key public id, key label, key environment, and key scopes so support can trace client traffic by key/workspace without exposing secrets or raw auth-provider subject identifiers

See the API reference for the exact fields and schemas.

On this page