These endpoints are live in production today, served by the FloKit payments gateway. They are separate from the v1 REST API, which is still in design-partner preview.
https://payments-gateway.flokitai.com
Authentication
These endpoints use request-scoped credentials instead of server API keys:x-app-keyheader — your app’s publishable key (pk_...), created per app in the FloKit dashboard. It scopes the request to your app and is safe to embed in your app build (it is not a secret and does not authenticate the user). Required on entitlement reads and funnel event writes.x-app-tokenheader — an optional short-lived app-session token minted from the publishable key viaPOST /api/paywall/token. Anywherex-app-keyis accepted,x-app-tokenworks instead — send one or the other.x-user-idheader — the user’s identity.userIdoranonymousIdquery parameters are accepted as a fallback where custom headers are inconvenient (the header takes precedence).
x-app-key enforcement is on in production. Requests without a valid app credential receive 401 on every endpoint marked as requiring it — there is no grace period. @flokitai/subscriptions-sdk v2.0+ sends it automatically — set appKey in initSubscriptionsSdk() and every call carries x-app-key (or x-app-token) for you.GET /api/paywall/config
Removed.GET /api/paywall/config returns 410 with {"code": "PAYWALL_CONFIG_REMOVED"}. Remote paywall configuration no longer exists — paywalls are Flow-owned and served with the Flow page. The gateway still proxies the path so older SDK builds receive an honest 410 rather than a 404.
Because the path is proxied, two non-410 outcomes are possible and are transport failures rather than
statements about the paywall: 503 with {"error": "Flows Gateway is not configured."} when the
gateway has no Flows upstream configured, and 502 when that upstream call fails. Treat both as
retryable; only 410 is the durable answer.
POST /api/iap/receipts
Renamed from
POST /api/paywall/receipt. The body schema is unchanged.Headers
Receipt verification is protected by the store signature on the receipt itself, so
x-app-key is not enforced here — but send it anyway for uniformity.
Request body
string
required
apple or google.string
Apple StoreKit 2 signed transaction (JWS). Required for
apple.string
Android package name. Required for
google.string
Google Play purchase token. Required for
google.Example
Response
200 returns the same canonical entitlement shape as
GET /api/entitlements/current:
source is
provider_verified and the response carries active, provider, state, expires_at, and
source only.
Errors
POST /api/paywall/events
Logs paywall funnel events — impressions, offer taps, purchases, conversions, cancellations — for paywall analytics. Accepts 1–50 events per request. The gateway resolves the request’s country at the edge; a server-resolved country takes precedence over any client-suppliedcountry value.
Headers
Every event’s
app_id must belong to the app the key was issued for — mismatches are rejected with 403.
Request body
array
required
1–50 event objects.
string
required
A name from the canonical event vocabulary. Unknown names are rejected with a non-retriable
400 that discards the whole batch, so validate before sending (the SDK does this on-device).string
required
Your application identifier.
string
The placement the event happened at, e.g.
onboarding_complete. Optional; slug
format ^[a-z0-9_]{1,64}$. Lets funnels be sliced by placement in reporting.object
required
Must include
paywall_id and variant_id for the six render-scoped events:
impression, offer_tap, purchase_start, trial_start, convert, and
cancel. purchase_failed and paywall_dismiss deliberately do not require
them, since purchase() can fire those with no paywall in context. All other
events may carry arbitrary properties.string
Client-minted idempotency key. The SDK’s retry queue stamps one on every event so a
re-delivered batch does not double-count; forwarded as-is.
string
ISO 3166-1 alpha-2 country code. Used only if server-side resolution fails.
string
Client platform, e.g.
ios or android.string
ISO 8601 timestamp of when the event occurred.
Example
Response
Errors
POST /api/paywall/token
Exchanges the publishable key for a short-lived app-session token bound to the requesting app and user. Use it when you’d rather not attach the rawpk_... key to every request: mint once at SDK init, send the token as x-app-token on subsequent calls, and re-mint when it expires.
Headers
Example
Response
x-user-id it was minted for — a token leaked from one user cannot read another user’s entitlements.
Errors
POST /api/paywall/checkout
Removed.POST /api/paywall/checkout was deleted along with the Offer/Offering entities. Web checkout is created from a published Flow’s paywall and checkout configuration and driven same-origin by @flokitai/checkout-js on the Flow page. The React Native SDK’s startWebCheckout() always throws CheckoutUnavailableError with code: 'WEB_CHECKOUT_MIGRATED'.
Other live gateway endpoints
The gateway serves the endpoints below in production today. They are listed here so the surface is complete; the SDK calls them for you, so most integrations never build these requests by hand. All of them resolve company, app, and environment server-side from the presented app credential (x-app-key or x-app-token) — a request body can never select the tenant.
Provider webhook passthrough
The gateway also exposes webhook receiver endpoints for subscription and attribution providers. Bodies are forwarded as raw bytes — provider signature headers are preserved and verified downstream, so configure these URLs directly in each provider’s dashboard.
If the downstream service cannot be reached, the gateway responds
502; if it times out (10 seconds), 504 — providers treat both as delivery failures and retry.