Skip to content
flypod
Concepts

Tokens & ownership

Understand flypod account sessions, per-site manage tokens, claim tokens, and how each credential changes ownership and expiry.

A flypod site is either temporary (deployed without an account, expires in 14 days) or yours (attached to an account, no expiry). Three credentials move a site between those states: an account session proves who you are, a per-site manage token proves you may change one specific site, and a claim token converts one anonymous site into an owned one. The CLI stores and sends all three for you; you almost never handle one by hand.

How ownership works

There are two states and one action:

StateWhat it means
TemporaryAnonymous deploy. Live immediately, expires in 14 days.
YoursAttached to an account. No expiry, listed on your account page.
flypod ./dist     # → temporary
flypod login      # → everything you deployed on this machine becomes yours

That is the whole model. flypod login claims every anonymous site this machine remembers, not just the last one — so "deploy now, log in whenever" is a real workflow, not a hopeful one. You never have to learn what a token is, and the happy path never shows you one.

Then why do tokens exist?

With no account there is nothing else that can prove a site is yours, so each site gets a manage_token: possession is ownership. It's plumbing, not something you handle. flypod writes it to projects.json (mode 0600), keyed by the folder you deployed from — which is how update, rollback, and versions work with no arguments, and how flypod login proves ownership of every remembered site at once. In the normal case the token is created, used, and retired without you ever seeing it.

The server stores only its SHA-256 hash, so it can't be re-issued or rotated. A leaked token keeps working until the site expires, is deleted, or is claimed: once a site belongs to an account, only that account's session can manage it and the manage_token stops working. That is exactly why it isn't printed.

The one case where flypod does show you a token

Hiding a credential is only safe while the system is holding it for you. So:

If flypod cannot remember a site for you, it tells you, and it gives you the token. It never creates a site it can't get back to, silently.

If the config directory is read-only or ephemeral (a CI container, a locked-down FLYPOD_CONFIG_DIR), the registry write fails while the deploy still succeeds — the site is live and nobody is holding its credential. flypod warns loudly and prints the manage_token, and emits it on stderr even under -q (and includes it in the --json receipt, which otherwise carries no token). That is the one moment you genuinely need it.

Otherwise, flypod token reveals it on demand — for the rare case of acting on a site from a machine that doesn't remember it. Rarer than it sounds: if the site is yours, logging in on the second machine is the better path, because a session can be replaced and a manage_token cannot.

Credential map

CredentialScopeUsed for
Account session tokenOne accountOwned deploys, account site listing, and managing sites owned by that account. Created by the flypod login device flow.
manage_tokenOne anonymous siteReading metadata, adding versions, rolling back, switching the version timeline, and proving control during login auto-attach. Stops working once the site is claimed.
claim_tokenOne anonymous siteCross-machine fallback for attaching an anonymous site to an account.

Account session token

flypod login obtains a Better Auth session token after you approve a device in the browser. The CLI saves it outside the project and sends it as a bearer token. For stateless automation, FLYPOD_TOKEN can supply an existing session directly (flypod login --token <session_token> saves one you already hold). There is no separate CI-token button: a session is account-wide.

The CLI picks one credential per request, in this order: an explicit --token, the site's stored manage_token, FLYPOD_TOKEN, the saved flypod login session, then the legacy FLYPOD_API_KEY. With none, a deploy is anonymous. A credential that is sent but not accepted fails with token_rejected; it never silently downgrades to an anonymous deploy.

Treat this token like a password: it represents the whole account. The separate custom API-key system — and its key-creation subcommand — is retired; FLYPOD_API_KEY remains only as a legacy environment-variable fallback.

A note on prefixes, since the retired API keys used one too: fk_ is the current prefix for per-site capability tokens. Both manage_token and claim_token are 32 random bytes rendered as fk_<base64url>. Seeing fk_ tells you nothing about which credential you're holding, only that it's a site-scoped capability token rather than an account session.

manage_token

Every deploy returns a manage_token. While the site is anonymous it authorizes the version loop for that specific site: reading metadata, adding versions, rolling back. Anonymous CLI deploys store it in projects.json so flypod update and flypod rollback work without flags — you don't handle it.

Claiming supersedes it. On an owned site the server accepts only the owning account's session, so a manage_token that leaked while the site was anonymous stops working the moment it is claimed — which is also the way to revoke one.

A manage_token cannot delete a site. There is no delete route that accepts one; deletion is account-only, from the signed-in account page (or the delete_site tool of a signed-in chat-app connector).

If you use the HTTP API or the library directly, the calculus flips — there is no registry holding the token for you, so you must save what the response returns. The CLI is the surface that saves it on your behalf.

claim_token

Anonymous deploys also return a claim_token, valid for exactly one route: POST /sites/:id/claim, behind flypod claim <site_id> <claim_token>. It's a cross-machine fallback, and it is not the recommended path — flypod login is. It can't re-point a site that already belongs to someone else: that route returns 409 (already_claimed) if the site has a different owner, and 401 (invalid_claim) for a wrong token.

A site published from a chat app has no folder on disk to hold its token, so the deploy_site result carries a keep_url (/keep#<site_id>.<claim_token>) instead: open it, sign in, and press one button. The token sits in the URL fragment, so it never reaches a server log.

Don't have agents or CI jobs stash a claim_token for later. Authenticate the job, or log in on the machine.

Anonymous vs owned

AnonymousOwned
Created byDeploy with no account sessionDeploy with a saved login or FLYPOD_TOKEN
Managed viamanage_tokenThe owning account's session only
Deleted viaNothing — it expiresAccount page
Expiry14 daysNone
Search indexingnoindexIndexable
URL<site_id>.flypod.page<site_id>.flypod.page — claiming never moves a site

Claiming through the CLI — flypod login or flypod claim — also clears the 14-day expiry on the local folder link, so it doesn't quietly self-destruct on day 14 and leave your next flypod making a second site on a new URL. The browser flow can't reach local files, so a site claimed from the dashboard is permanent server-side while this machine's folder link still ages out; re-running flypod update from that folder after it lapses is the case to watch for.

On this page