API Key Security
Production: no key in the binary
In production builds the Qafka SDK does not ship an API key. Every request is authenticated by a short-lived session token issued by the backend after a successful device attestation (App Attest on iOS, Play Integrity on Android). The backend identifies the project from the attestation certificate against the registered Apps table — the SDK never needs to carry a project identifier in your bundle.
This means:
- There is no value to extract from your binary. Reverse-engineering the IPA / APK yields no usable key.
- Requests from an emulator, a jailbroken device, or a forged bundle ID fail at attestation. The backend never reaches the key-validation path.
- Replay attacks against a captured session token fail because tokens are short-lived and budget-bounded — once exhausted the token must be refreshed via a fresh attestation.
Development: key delivered via the CLI
In development builds the SDK still needs to talk to the backend before attestation is set up. The Qafka CLI handles this without checking secrets into your repository:
qafka init(orqafka project/qafka refresh) pulls your project’s development key from the dashboard.- The CLI writes a generated
qafka.config.jsinsidenode_modules/@qafka/react-native/. The file is regenerated on every CLI run. - The SDK reads this runtime config on mount — no
apiKeyprop is needed.
Because the file lives inside node_modules/, it is never tracked in version control. The CLI also patches .gitignore to keep .qafka/ out of commits before writing anything to it.
If a development key is leaked, revoke it from the dashboard (Dashboard › API Keys) and run qafka refresh to pick up the new value. Development keys carry the same restrictions as production keys (platform, bundle ID, attestation when available) — they are not a bypass.
Validation chain
Every authenticated request is validated against:
- Session token — Was the attestation chain (cert validation + challenge) accepted?
- Budget — Has the token’s request budget been exhausted?
- Project identity — Does the attestation certificate map to a registered project?
- Platform & bundle ID — Do they match the registered app for this project?
- API key (if present) — When the SDK is in development mode and an
x-api-keyheader is attached, key existence, active status, expiry, platform, and bundle ID restrictions are checked.
Rate limits and quotas are enforced per project based on the active subscription plan, not per key. See Error Handling › Throttling for the 429 response shape and recommended client behavior.
Headless usage
The headless path (QafkaSDK.initialize({ apiKey })) accepts an explicit API key for callers that aren’t using the React component or the CLI scaffold. Treat that key with the same care as any backend credential — it should be loaded from environment configuration, not committed. See Headless Usage for the full pattern.
Best practices
- Use the CLI for app integration — keys never enter your source tree.
- Use TEST keys during development so production traffic counters stay clean.
- Always set bundle ID restrictions on production keys, even though attestation already covers most of the spoofing surface.
- Use separate keys per platform so iOS and Android can have independent restrictions and rate-limit allocations.
- Rotate keys periodically and revoke unused ones.
- Treat all keys as sensitive in CI logs, support tickets, and screenshots — even when the validation chain would block misuse.