Explanation

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

Authentication flow

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_id identifies the tenant credential.
  • client_secret proves 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 data
  • read:enduseraccounts: list end-user accounts
  • update:enduseraccount: modify an end-user account
  • update: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

DecisionRationaleImplication for you
UrbanFox OAuth token serviceProvide a standard token endpoint while keeping implementation details behind UrbanFoxYour integration calls POST /v2/oauth/token with client_id and client_secret
No API keysTokens expire and carry scopes; API keys are static and overprivilegedYour integration manages token renewal instead of sending a permanent key
Per-tenant credentialsIsolation, so one compromised credential doesn't expose other tenantsMulti-tenant integrators manage one credential set per tenant
Scopes on tokensScopes are stable API contractsA 403 response usually points to a missing scope or a tenant mismatch

See also