API Authentication
AppActor uses API keys to authenticate requests. There are two key types with different access levels.
API Key Typesโ
| Key Type | Prefix | Usage | Access Level |
|---|---|---|---|
| Public Key | pk_* | Client SDKs (mobile apps) | Read-only: offerings, purchases, customer info |
| Secret Key | sk_* | Server-side integrations | Full access: user CRUD, entitlement grant/revoke, app settings |
Public Keys (pk_*)โ
Public keys are safe to include in your app's client-side code. They can only:
- Identify users and manage sessions
- Fetch offerings and product catalogs
- Submit purchase receipts for validation
- Restore purchases
- Fetch customer info and entitlements
- Fetch remote config and experiment assignments
Used by: iOS SDK, Android SDK, Flutter SDK
Secret Keys (sk_*)โ
Secret keys have full access and must never be exposed in client-side code. They can:
- Everything public keys can do, plus:
- Create, update, and delete users
- Grant and revoke entitlements directly
- Manage app settings
- Access server-side admin APIs
Used by: Your backend server
Secret keys (sk_*) must never be included in mobile apps, client-side JavaScript, or any code that runs on user devices. Treat them like database passwords.
Authentication Headerโ
Include your API key in the Authorization header:
Authorization: Bearer pk_live_your_key_here
Or use the X-API-Key header:
X-API-Key: pk_live_your_key_here
Both headers are supported. Authorization: Bearer is recommended.
Key Securityโ
API keys are stored as HMAC-SHA256 hashes in the database โ the raw key is never stored. This means:
- If the database is compromised, API keys cannot be recovered
- You can only see the full key when it's first created
- Rotating a key generates a completely new key
Response Signingโ
In payment mode, the SDK verifies API responses using Ed25519 signatures to prevent tampering:
- v1 (Direct): Server signs responses with a static private key; SDK verifies with the pinned public key
- v2 (Intermediate Chain): Root key signs rotating intermediate keys; SDK only needs to pin the root public key
Response signing includes a nonce and timestamp to prevent replay attacks.
Rate Limitingโ
API requests are rate limited at two levels:
IP Rate Limitโ
All /v1/* endpoints are protected by an in-memory IP rate limiter:
- 50 requests per minute per IP address
- Returns
429 Too Many Requestswhen exceeded
App Rate Limitโ
Per-app, per-route rate limiting via Redis sliding window:
| Endpoint Group | Limit |
|---|---|
| Payment endpoints | 60-120 req/min |
| Customer endpoints | 60-120 req/min |
| Remote config | 120 req/min |
| Experiments | 120 req/min |
Rate limit headers are included in responses:
X-RateLimit-Limit: 120
X-RateLimit-Remaining: 118
X-RateLimit-Reset: 1706000000
Environmentsโ
| Environment | Key Prefix | Description |
|---|---|---|
| Live | pk_live_* / sk_live_* | Production environment |
| Test | pk_test_* / sk_test_* | Sandbox/testing environment |
Use test keys during development to avoid affecting production data.
Next Stepsโ
- API Reference โ Full REST API documentation
- Webhooks โ Receive real-time event notifications