tenantId, and every API request is scoped to exactly one tenant via the key pair you send.
Mental model
Single-product apps
One tenant per environment (test + live). Your entire company’s data lives inside it.
Platforms / marketplaces
One tenant per merchant, broker, or sub-account. Each gets its own keys and webhooks.
White-label resellers
One tenant per reseller customer. Ideal for keeping data, branding, and keys fully isolated.
Isolation guarantees
- Data: Queries are scoped to
tenantIdat the database layer. A key from tenant A can never read or mutate tenant B’s data. - Webhooks: Each tenant has its own webhook endpoints and signing secret. Events emitted for tenant A are never sent to tenant B’s URL.
- Keys: Revoking a tenant’s key doesn’t affect other tenants. Rotating a webhook secret doesn’t affect other tenants.
- Rate limits: Each tenant has its own quota. A noisy neighbor can’t starve other tenants.
Creating a tenant
Tenants can be created from the dashboard or via API (admin-only).secretKey and webhookSecret in a secrets manager immediately. If you lose them, you’ll need to regenerate - which invalidates the old ones.
Resolving the current tenant
Your backend doesn’t need to tracktenantId - the key pair resolves it automatically. Every response includes it so your application can stamp logs and traces:
tenantId → secretKey mapping in your own database and load the right key before each outgoing call.
The x-tenant-id header (user-auth only)
When a request is authenticated with a user JWT instead of API keys - rare for integrators - the tenant is resolved from the user’s profile, or from the x-tenant-id header if the user has access to multiple tenants. You don’t need to set this for API-key requests.
TL;DR for integrators: use API keys, don’t set
x-tenant-id, trust the tenantId in responses.