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/session

Authentication

Same HMAC signature as POST /v1/exchange — identical headers:

HeaderRequiredDescription
Content-TypeYesapplication/json
x-partner-idYesYour Partner ID
x-partner-timestampYesUnix timestamp in seconds
x-partner-nonceYesUnique identifier per request (32-char hex recommended)
x-partner-signatureYesHMAC-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"
}
FieldTypeRequiredDescription
originstringYesYour site's origin URL (must match your registered domain)
scopesstring[]NoRequested scopes. Default: ["isAdult"]. Available: isAdult, isFrench, isEU, isUnique

Response (201 Created)

{
  "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "expires_in": 300
}
FieldTypeDescription
tokenstringSigned token (JWS). Pass to the widget via data-session-token
expires_inintegerValidity 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

CodeHTTPDescriptionFix
UNAUTHORIZED / INVALID_PARTNER401/403Invalid HMAC signature or unknown Partner IDCheck your credentials and signature calculation
FORBIDDEN_RAIL403Organization is not on the ADULT_BLIND railContact tech@zykay.com to enable the rail
MISSING_BLIND_APP_ID400blindAppId not configured for the organizationContact ZYKAY support
MISSING_ORIGIN400origin field missing from bodyInclude "origin": "https://yoursite.com"
INVALID_SCOPES400Scopes not supported for your tierCheck available scopes for your level
INTERNAL_ERROR500Server errorRetry with exponential backoff

Rate Limits

PhaseLimitWindowKey
Pre-auth (IP)30 req60sClient IP
Post-auth (per partner)100 req60sPartner 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-keys

Response:

{
  "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"
}
FieldDescription
scope_maskBitmask of verified scopes. Bit 0 = isAdult, bit 1 = isFrench, bit 2 = isEU, bit 3 = isUnique
nullifierPrivacy-safe unique identifier (specific to your app_id)
expUnix expiry — verify that exp > now()

Full Example

See the complete integration guide: Adult Sites (ADULT_BLIND)