Client authentication, without embedded secrets.
Tierux separates server-to-server administration from the routes your shipped app calls. This guide explains which client routes are public, how identity is established, and when attestation changes the trust model.
Server entitlement lookup
GET /api/v1/entitlements/{userId}/{entitlementId} uses your secret Tierux API key in the Authorization header. Keep that key on a trusted server; never put it in an app bundle. Other server routes have their own, route-specific authentication — see the breakdown below.
Client: /api/client/**
The app-facing surface uses the public appId identifier and has no client API key. An appId selects a project; it is not a secret or an authorization credential.
Server routes don't share one blanket rule. Each group below authenticates independently, and none of the webhook routes accept the API key.
| Route group | Authentication |
|---|---|
/api/v1/entitlements/**, POST /api/v1/purchases/google-play/verify, POST /api/v1/purchases/apple/verify, POST /api/v1/apps/{appId}/connect-google-play | Secret Tierux API key in the Authorization header. |
/api/v1/auth/**, /api/v1/developer/** | Firebase developer ID token, not the API key. |
/api/v1/billing/** (checkout, session, portal, usage) | Firebase developer ID token. |
POST /api/v1/billing/webhook | Stripe's own webhook signature, not a token or an API key. |
GET /api/v1/sdk/source, GET /api/v1/sdk/download | Public — no authentication. Source is published for transparency and auditing. |
POST /api/v1/google-play/rtdn | Google Pub/Sub JWT audience verification, not the API key — in deployed runtimes; an unconfigured audience fails closed (503) only when K_SERVICE (Cloud Run) is set, and calls through unauthenticated elsewhere. |
POST /api/v1/apple/assn/{appId} | Apple's signed JWS notification payload, not the API key. |
POST /api/v1/stripe/webhook/{appId} | The developer's own Stripe webhook signing secret, not the API key. |
By default, published paywall reads and purchase verification are callable from the app without a Tierux secret. Tierux still verifies every submitted purchase with Google Play, Apple, or Stripe before granting access.
| Route | Default access | Identity behavior |
|---|---|---|
GET /api/client/apps/{appId}/paywalls/{paywallId} | Public | Returns only the published paywall snapshot. |
POST /api/client/apps/{appId}/purchases/google-play/verify | Public | Uses the submitted opaque userId when the body includes one — even if a valid ID token is also supplied. Falls back to the verified Firebase UID only when no userId is submitted. |
POST /api/client/apps/{appId}/purchases/apple/verify | Public | Uses the submitted opaque userId when the body includes one — even if a valid ID token is also supplied. Falls back to the verified Firebase UID only when no userId is submitted. |
POST /api/client/apps/{appId}/purchases/stripe/verify | Public | Uses the submitted opaque userId when the body includes one — even if a valid ID token is also supplied. Falls back to the verified Firebase UID only when no userId is submitted. |
GET /api/client/apps/{appId}/entitlements/{entitlementId} | Gated | Requires a valid Firebase ID token and derives userId from its verified UID. |
“Public” means no Tierux API key or end-user token is required by default. It does not mean purchase claims are trusted: the verify routes validate store evidence server-side, and all client routes are rate limited. Handle 429 RATE_LIMITED with bounded retry and backoff.
If you use the client entitlement GET, the body userId on every verification request must exactly equal the Firebase UID that the entitlement route derives from its ID token. Do not grant to an unrelated UUID and then read by Firebase UID; those are different entitlement records.
An opaque UUID is appropriate when purchase verification and server-side entitlement lookup both consistently use that same identifier. In this server-side pattern, make the identifier stable and non-enumerable so one customer cannot guess another customer’s identity or learn personal information.
// Good for consistent server-side verification + lookup "550e8400-e29b-41d4-a716-446655440000" // Bad: predictable or personally identifying "alex@example.com" // email address "customer-1042" // sequential identifier "alex" // predictable username
A submitted client userId must be nonblank, no more than 256 characters, and contain neither a slash nor control characters. These are input bounds, not a substitute for consistency or unpredictability.
What enforceAttestation changes
When enforceAttestation is enabled for an app, every app-scoped /api/client/apps/{appId}/** route for that app requires both a valid Firebase ID token and a valid Firebase App Check token. Production validates those tokens only against the Tierux Firebase project. That includes paywall reads and all three purchase-verification routes. The public bootstrap endpoint GET /api/client/firebase-config is not app-scoped, so it is unaffected by any app's enforceAttestation setting and stays public.
Identity is bound to the verified token
Tierux derives the client identity from the Firebase ID token UID. A verification body may omit userId; if the body includes userId, it must equal that verified UID or the request is rejected.
Current availability
Customer Firebase project tokens are not supported, and customer-project federation or self-serve attestation enrollment does not exist today. External customers should perform entitlement checks server-side through GET /api/v1/entitlements/{userId}/{entitlementId} with their Tierux API key until federation is available.
Free: 500 active subscribers
At the 500-subscriber cap, Tierux blocks net-new grants. Published paywalls, existing entitlements, and reverification for existing subscribers keep serving so current customers do not lose access.
Paid: 1,000 included
Paid plans include 1,000 active subscribers, then charge $30 per additional 1,000. This paid included quota is separate from the Free plan’s 500-subscriber grant cap.
Client SDKs
Initialize the supported clients and connect them to the client API.
Purchase validation
How store evidence is verified, hashed, and encrypted server-side.
Security
Platform-wide controls for credentials, tokens, webhooks, and data handling.
Ready to integrate?
Choose your client SDK and keep every Tierux secret on the server.
View client SDKs