Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.capy.ai/llms.txt

Use this file to discover all available pages before exploring further.

What session identity tokens are for

Session identity tokens let code running inside a Captain VM prove which Capy session it came from. Typical uses include enforcing per-session limits, binding external resources to a specific session, or accepting requests only from active sessions you expect. Each token represents one Captain session. Capy signs the token, refreshes it while the session stays active, and invalidates it when the session ends.
Treat the token as an opaque bearer-style string. It is a JWT, but customers should not parse or verify it locally.

Where to read the token

You can get the current token in either place:
  • Inside the Captain VM at /etc/capy/session-token (chmod 600)
  • Via GET /v1/threads/{threadId}/session-token
If your code is already running inside the session VM, read the file directly instead of calling the API from inside the agent.

Token lifecycle

  • Minted when the session starts
  • Expires 30 minutes after issuance
  • Refreshed automatically in the background on each Captain VM heartbeat, typically about every 15 minutes before expiry
  • Cleared when the session stops or is archived
As long as the session stays active, the token at /etc/capy/session-token and the value returned by GET /v1/threads/{threadId}/session-token stay current. When a service receives a session token from agent-controlled code:
  1. Send the token to POST /v1/sessions/verify
  2. Confirm the response has valid: true
  3. Confirm projectId matches the project you expected
  4. Optionally confirm threadId matches the specific session you expected
  5. Trust the session identity only after those checks pass
Do not trust a session token based only on its shape, header, or decoded JWT claims. Always call the verify endpoint before making authorization or routing decisions.

Security model

Capy signs session identity tokens with a Capy-managed key that is separate from internal infrastructure secrets. Customers must never attempt to verify the JWT cryptographically themselves. POST /v1/sessions/verify is the only authoritative verification path. It confirms that the token matches a real session and that the session is still valid for the caller’s project access. Failure responses are intentionally opaque:
  • expired means the token was valid but is no longer current
  • invalid covers malformed tokens, signature failures, wrong issuer, wrong audience, wrong purpose, and other verification failures
This prevents the verify endpoint from becoming a useful oracle for attackers.
The caller of POST /v1/sessions/verify must have API access to the project that owns the session. This prevents cross-project and cross-tenant enumeration.

End-to-end example

curl "$CAPY_API_BASE/v1/threads/$THREAD_ID/session-token" \
  -H "Authorization: Bearer $CAPY_API_TOKEN"
A successful verify response looks like:
{
  "valid": true,
  "threadId": "jam_123",
  "projectId": "proj_123",
  "orgId": "org_123",
  "userId": "user_123",
  "instanceId": "vm_123",
  "issuedAt": "2026-04-28T12:00:00.000Z",
  "expiresAt": "2026-04-28T12:30:00.000Z"
}