Skip to content

Exchange a customer magic-link token for a first-party person session

POST
/customer-login/sessions
curl --request POST \
--url https://quikstik-core.fly.dev/customer-login/sessions \
--header 'Content-Type: application/json' \
--data '{ "token": "example", "device": { "name": "example", "platform": "ios" } }'

Consumes the token (single-use) and mints a local-person session whose subject is the Person id. Expired/consumed/unknown/unresolvable are one indistinguishable 404.

Media typeapplication/json
object
token
required
string
>= 32 characters
device

Supplied by a device that wants a refresh credential (staff POST /login/sessions only).

object
name
required

Human label (“Wilton’s iPhone”); trimmed.

string
>= 1 characters <= 100 characters
platform
required
string
Allowed values: ios ipados macos android web

Person session minted

Media typeapplication/json
object
scopes
required

The effective permission tokens of the session’s membership, sorted (empty when the membership is not active).

Array<string>
role
required

The highest role the scopes imply. Open (see contracts/openapi/README.md); the app reads ownership here, not from GET /team.

string
session_token
required

First-party bearer session; present as Authorization: Bearer.

string
refresh_token

Present only when a device was supplied. 32 random bytes, hex encoded. Shown exactly once; only its SHA-256 digest persists.

string
refresh_expires_at_ms

Present with refresh_token; now + 90 days, epoch ms.

integer format: int64

Example generated

{
"scopes": [
"example"
],
"role": "example",
"session_token": "example",
"refresh_token": "example",
"refresh_expires_at_ms": 1
}

Malformed body

Media typeapplication/json
object
reason
required
string

Example generated

{
"reason": "example"
}

Expired, consumed, unknown, or unresolvable — indistinguishable by design

Media typeapplication/json
object
reason
required
string

Example generated

{
"reason": "example"
}

No durable backend is wired for this operation (fail-closed)

Media typeapplication/json
object
reason
required

Stable, machine-readable reason code (e.g. “sold_out”, “processor_not_configured”, “rail_refused”).

string

Example

{
"reason": "sold_out"
}