Authentication Model
How UrbanFox API access tokens work, why credentials are tenant-scoped, and how scopes map to permissions
Every UrbanFox Customer API request uses a Bearer access token. Your backend obtains that token from the UrbanFox OAuth token service, then sends it to tenant-scoped API endpoints in the Authorization header.
This page explains the design model behind API authentication: why UrbanFox uses short-lived tokens, how tenant-bound credentials protect data, and how scopes limit what each integration can do.
API authentication at a glance
UrbanFox built the Customer API for server-to-server integrations. Your service uses the client_id and client_secret issued for your tenant to request an access token from POST /v2/oauth/token.
That token represents one tenant and a set of allowed scopes. API endpoints validate the token, check the requested tenant, and enforce the scopes required by the operation.
The same tenant slug appears in the API host and path. In the API reference, {tenant_slug} appears in the host and in tenant-scoped endpoint paths. For example, tenant demo-retail uses https://api.demo-retail.urbanfox.io/v2/demo-retail/....
The web app's human login is separate from Customer API authentication. Your team may sign in to the UrbanFox web app in a browser, but programmatic API access uses the OAuth token endpoint and machine-to-machine credentials.
Why tokens instead of API keys?
Static API keys are easy to copy, hard to scope precisely, and often live longer than intended. UrbanFox uses access tokens because they:
- expire automatically
- carry explicit permissions
- support separate credentials for each tenant
- support credential rotation without changing every API call
For your integration, this means authentication is a small token-management workflow rather than a permanent shared secret in every request.
How the token flow works

Your backend sends its tenant credentials to the UrbanFox OAuth token service. The token service returns a Bearer access token with an expiry time. Your backend presents that token when it calls tenant-scoped Customer API endpoints.
UrbanFox validates the token and returns data only for the token's tenant. A valid token for one tenant slug cannot read or modify another tenant's data.
Credential model
Each tenant has its own API credential set:
client_ididentifies the tenant credential.client_secretproves your backend can use that credential.- The returned token belongs to that tenant.
Because client_secret proves that your backend can use the tenant credential, it belongs in server-side secret storage rather than browser code, mobile apps, GTM tags, or any client-side bundle.
Scope model
Scopes define what a token can do. They follow the pattern action:resource:
read:metrics: query metrics dataread:enduseraccounts: list end-user accountsupdate:enduseraccount: modify an end-user accountupdate:tenant_auth_secret: rotate the tenant's auth secret
Scopes are additive. A token with read:metrics and read:enduseraccounts can do both operations. A token without update:enduseraccount cannot modify an end-user account, even if it is valid for the tenant.
Why explicit scopes?
The alternative, a single full-access credential, is simpler but creates unnecessary risk. Explicit scopes mean:
- A metrics dashboard token cannot modify user accounts (even if compromised)
- You can audit exactly what each integration component can do
- Each integration can use credentials with only the scopes it needs
- A leaked token has a limited blast radius
Token lifecycle
Tokens expire. The OAuth token response includes expires_in, which tells your integration how long the access token remains valid.
Most integrations renew tokens before the current token expires. A 401 response usually means the token is invalid or expired, so it becomes a renewal signal in the integration's normal retry policy.
Tenant binding
Every token belongs to one tenant. UrbanFox rejects requests where the token and the tenant slug in the URL do not match. This is the enforcement mechanism for tenant isolation.
Multi-tenant integrations therefore use separate credentials and separate tokens for each tenant. There is no cross-tenant token.
Design decisions and their implications
| Decision | Rationale | Implication for you |
|---|---|---|
| UrbanFox OAuth token service | Provide a standard token endpoint while keeping implementation details behind UrbanFox | Your integration calls POST /v2/oauth/token with client_id and client_secret |
| No API keys | Tokens expire and carry scopes; API keys are static and overprivileged | Your integration manages token renewal instead of sending a permanent key |
| Per-tenant credentials | Isolation, so one compromised credential doesn't expose other tenants | Multi-tenant integrators manage one credential set per tenant |
| Scopes on tokens | Scopes are stable API contracts | A 403 response usually points to a missing scope or a tenant mismatch |
See also
- Tenancy Model: how tenant isolation works at the data level
- How to authenticate: step-by-step token acquisition
- How to rotate your tenant auth secret: credential rotation procedure