Authentication

Every Partner API request carries an API key in the X-API-Key header:

X-API-Key: msk_live_...

No bearer tokens, no OAuth. Keys are validated on every request.

Key prefixes

PrefixEnvironment
msk_live_Production
msk_test_Dev / preview / staging

A test key only works against app-api.dev.mobilytics.ai. A live key only works against app-api.mobilytics.ai. Swapping base URLs by accident returns 401 UNAUTHORIZED.

Scoping

Keys are scoped to one or more companies. Responses are filtered to those companies automatically:

  • List endpoints (e.g. /v1/partner/assets) return only resources owned by your scoped companies.
  • Detail endpoints (e.g. /v1/partner/assets/:id) return 404 NOT_FOUND if the resource is outside your scope — never 403. This prevents cross-tenant existence probing.
  • A key with empty scope is valid but sees nothing: list endpoints return empty pages, detail endpoints always 404.

Check your scope any time with /v1/partner/meta.

Permissions

Keys also carry a set of per-resource permissions:

PermissionGrants
partner:assets:read/v1/partner/assets list + detail
partner:sensors:read/v1/partner/sensors list + detail
partner:metrics:read/v1/partner/assets/:id/impressions/*
partner:demographics:read/v1/partner/assets/:id/demographics (+ /buckets), /v1/partner/demographics/*
partner:metrics:legacy:read/v1/metrics/* (Django-parity bridge; see Migrate from legacy)

Calling an endpoint your key isn't granted returns 403 FORBIDDEN.

/v1/partner/meta does not have its own permission, but it requires the key to hold at least one permission from the table above — a key scoped only to non-partner surfaces returns 403 when probing meta.

partner:metrics:legacy:read is a migration-only scope. It unlocks the legacy /v1/metrics/* shape so partners can cut over to Mobilytics-hosted infrastructure without changing their call sites. New integrations should use partner:metrics:read (+ the other modern scopes) instead; the legacy bridge will sunset once access logs show no traffic.

Rotation

Request rotation via support@mobilytics.com. Issuing a replacement key deactivates the prior key in the same transaction — the two keys are never live simultaneously. Plan the rollover accordingly: stage the new value in your config store first, then ask support to rotate, then deploy.

Deactivated keys remain in our audit log; access logs are attributed to the consumerCode rather than the key itself.