Billing Session API
Issues a signed session token for the ADULT_BLIND compliance rail. Reserved for partners on this rail.
This endpoint is only available for organizations configured on the ADULT_BLIND compliance rail. Contact tech@zykay.com to enable this mode.
Endpoint
POST https://app.zykay.com/api/billing/sessionAuthentication
Same HMAC signature as POST /v1/exchange — identical headers:
| Header | Required | Description |
|---|---|---|
Content-Type | Yes | application/json |
x-partner-id | Yes | Your Partner ID |
x-partner-timestamp | Yes | Unix timestamp in seconds |
x-partner-nonce | Yes | Unique identifier per request (32-char hex recommended) |
x-partner-signature | Yes | HMAC-SHA256 signature (base64url) |
The canonical string and signature calculation are identical to those described in Grant Exchange API.
Request Body
{
"scopes": ["isAdult"],
"origin": "https://yoursite.com"
}| Field | Type | Required | Description |
|---|---|---|---|
origin | string | Yes | Your site's origin URL (must match your registered domain) |
scopes | string[] | No | Requested scopes. Default: ["isAdult"]. Available: isAdult, isFrench, isEU, isUnique |
Response (201 Created)
{
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"expires_in": 300
}| Field | Type | Description |
|---|---|---|
token | string | Signed token (JWS). Pass to the widget via data-session-token |
expires_in | integer | Validity duration in seconds (always 300 = 5 minutes) |
The token expires after 5 minutes. Call this endpoint on every page load — do not cache the token between requests.
Error Codes
| Code | HTTP | Description | Fix |
|---|---|---|---|
UNAUTHORIZED / INVALID_PARTNER | 401/403 | Invalid HMAC signature or unknown Partner ID | Check your credentials and signature calculation |
FORBIDDEN_RAIL | 403 | Organization is not on the ADULT_BLIND rail | Contact tech@zykay.com to enable the rail |
MISSING_BLIND_APP_ID | 400 | blindAppId not configured for the organization | Contact ZYKAY support |
MISSING_ORIGIN | 400 | origin field missing from body | Include "origin": "https://yoursite.com" |
INVALID_SCOPES | 400 | Scopes not supported for your tier | Check available scopes for your level |
INTERNAL_ERROR | 500 | Server error | Retry with exponential backoff |
Rate Limits
| Phase | Limit | Window | Key |
|---|---|---|---|
| Pre-auth (IP) | 30 req | 60s | Client IP |
| Post-auth (per partner) | 100 req | 60s | Partner ID |
The pre-auth limit protects against abuse before HMAC verification. The post-auth limit (100/min) is designed for normal server-to-server traffic.
Attestation Public Keys (JWKS)
To verify attestation signatures server-side without an API call:
GET https://app.zykay.com/api/billing/attestation-keysResponse:
{
"keys": [
{
"kty": "OKP",
"crv": "Ed25519",
"kid": "ak-2026-02",
"x": "...",
"use": "sig"
}
]
}Cache the JWKS response for up to 1 hour. Keys rotate infrequently (every few months). ZYKAY will notify you in advance of key changes.
Attestation Payload Structure
Once the JWS is decoded and the signature verified:
{
"jti": "abc123...",
"exp": 1708560000,
"scope_mask": 1,
"app_id": "blind_app_xxx",
"origin_hash": "sha256_of_origin",
"nullifier": "0x7a3b9c...",
"aud": "zykay-verifier",
"ver": "1.0"
}| Field | Description |
|---|---|
scope_mask | Bitmask of verified scopes. Bit 0 = isAdult, bit 1 = isFrench, bit 2 = isEU, bit 3 = isUnique |
nullifier | Privacy-safe unique identifier (specific to your app_id) |
exp | Unix expiry — verify that exp > now() |
Full Example
See the complete integration guide: Adult Sites (ADULT_BLIND)