Skip to main content

Sessions

A session is a short-lived RS256 JWT minted by your backend so the end-customer's browser can call the widget API safely.

Never expose the store API key to the browser. Mint a session instead.

Mint a session

POST /api/v1/customers/{customerId}/sessions
Authorization: Bearer <store_api_key>
Content-Type: application/json
{ "expires_in": 900 }
FieldDefaultRange
expires_in900 (15 min)60 – 3600 seconds

Response:

{
"token": "eyJhbGciOiJSUzI1NiIs...",
"token_type": "Bearer",
"expires_in": 900,
"expires_at": 1745812345,
"customer": {
"id": "ec_abc",
"external_id": "user_42",
"plan_id": "pln_xxxx",
"plan_name": "Pro",
"monthly_try_ons": 100,
"period_start": "...",
"period_end": "..."
}
}

If the customer is paused or cancelled, you get 403 customer_inactive and no token.

Token shape

header.payload.signature

Header:

{ "alg": "RS256", "kid": "gv-xxxx", "typ": "JWT" }

Payload:

{
"sub": "ec_abc",
"sid": "user_xyz",
"pid": "pln_xxxx",
"iss": "https://genvoris.org",
"aud": "genvoris-widget",
"iat": 1745811445,
"exp": 1745812345,
"jti": "ec_abc-1745811445-rand"
}

Verifying tokens (offline)

For plugin code that wants to introspect a token without an extra round-trip, fetch our JWKS:

GET https://genvoris.org/.well-known/jwks.json
Cache-Control: public, max-age=3600

Use any JOSE library (Node jose, Python python-jose, PHP firebase/php-jwt) to verify with iss=https://genvoris.org and aud=genvoris-widget.

Rotation

When we rotate signing keys, the kid changes but old tokens stay valid until their natural exp. Cache the JWKS for at most one hour to pick up new keys quickly.