---
title: "Plan Token Endpoint"
method: POST
path: "/api/auth/plan_token"
---

# Plan Token Endpoint

`POST /api/auth/plan_token`

Issue a signed plan claim. The caller is already authenticated
via the session bearer token; we read their `plan_code` from the
database (NOT from the request body — that's the whole point of
signing it). 24h TTL by default; configurable via
OMICOS_PLAN_TOKEN_TTL_SECONDS for staging.

Auth resolution is inlined here (rather than `Depends(current_user)`)
so this endpoint can attach a machine-readable `code` to its 401/403
bodies. omicos-core's plan_token renewer maps any 401/403 from this
route to RenewReason::SessionExpired purely on status code (see the
cross-repo contract); the `code:"session_expired"` field is an
additive diagnostic so SPAs/clients can match without status-only
inference. The 503 signing/key-failure path below stays as-is and
core maps it to RenewReason::ServerSigningError. The HTTP status
codes and `detail` strings are UNCHANGED from the shared
`current_user` dependency, so behavior for status-only consumers is
identical.

## Headers

- `authorization` string, nullable

## Response `200`

Successful Response

- object

## Other responses

- `422` — Validation Error

---

[API](https://skmtc.dev/omicos/apis/omicos-server.md) · [All operations](https://skmtc.dev/omicos/apis/omicos-server/llms.txt) · [OpenAPI document](https://skmtc-service-production.skmtc.workers.dev/v1/apis/omicos/omicos-server/revisions/a00b94573ffe/schema)
