Trade a device refresh token for a fresh session JWT
const url = 'https://quikstik-core.fly.dev/login/refresh';const options = { method: 'POST', headers: {'Content-Type': 'application/json'}, body: '{"refresh_token":"example"}'};
try { const response = await fetch(url, options); const data = await response.json(); console.log(data);} catch (error) { console.error(error);}curl --request POST \ --url https://quikstik-core.fly.dev/login/refresh \ --header 'Content-Type: application/json' \ --data '{ "refresh_token": "example" }'Unauthenticated by design — the refresh token is the credential. Mints a session JWT with
the same claims as the original establish but kind = device, and records the use
(last_used_at_ms). Does not rotate the refresh token. Rate-limited with the same limiter
as POST /login/requests (keyed on the credential’s digest + client IP); over the limit
is 429. The three 401 reasons are stable machine strings.
Request Bodyrequired
Section titled “Request Bodyrequired”object
Example generated
{ "refresh_token": "example"}Responses
Section titled “Responses”Fresh device session minted
object
Session JWT with kind = device; accepted anywhere a session is.
The effective permission tokens of the session’s membership, sorted (empty when the membership is not active).
The highest role the scopes imply. Open (see contracts/openapi/README.md); the app reads ownership here, not from GET /team.
Example generated
{ "session_token": "example", "scopes": [ "example" ], "role": "example"}Malformed body
object
Example generated
{ "reason": "example"}Refresh refused; reason is one of refresh_revoked, refresh_expired, refresh_unknown
object
Example generated
{ "reason": "example"}Rate limited (reason = rate_limited)
object
Example generated
{ "reason": "example"}No durable backend is wired for this operation (fail-closed)
object
Stable, machine-readable reason code (e.g. “sold_out”, “processor_not_configured”, “rail_refused”).
Example
{ "reason": "sold_out"}