ZingaConnectSign in

Authentication

Authentication

Every request to the Zingasuite API is authenticated with an API key sent as a
bearer token. The key identifies which entity you are acting on and which
operations you are allowed to perform — there is no entity id in the URL.

API keys

Keys are created in the console (Settings → API Keys). A key
looks like this:

zk_live_xxxxxxxxxxxxxxxxxxxxxxxx    # production
zk_test_xxxxxxxxxxxxxxxxxxxxxxxx    # sandbox / testing

The full key is shown once, at creation time. Store it securely — only a
short prefix (for example zk_live_abc1…) is retained for display afterwards,
and a lost key cannot be recovered (create a new one and revoke the old).

Sending the key

Send the key in the Authorization header on every request:

curl https://api-v1.zingasuite.com/papi/v1/products \
  -H "Authorization: Bearer zk_live_xxxxxxxxxxxxxxxxxxxxxxxx"

If the header is missing or malformed you receive 401 with
{"detail": "missing_bearer_token"} or {"detail": "invalid_token"}. An
unknown, revoked or expired key returns 401 invalid_or_revoked_key.

Scopes

Each key carries a set of scopes that limit what it can do. Grant the
minimum a key needs.

Scope Grants
data:read Read any object your role can read
data:write:* Create/update/delete any object your role can write
billing:read Read billing information
messaging:read Read messaging channels and message status (ZingaConnect)
messaging:send Send messages (ZingaConnect)
messaging:webhooks Manage delivery/inbound webhooks (ZingaConnect)

These are the only scopes you can attach to a key; any other value is rejected
at creation with 400 scope_not_allowed:<scope>.

Notes:

  • Writes are all-or-nothing at the key level. data:write:* lets a key
    write any object type — there is no per-object write scope you attach to the
    key. To limit a key to, say, only products, create it under a user whose
    role is restricted to products (see below); the key can never exceed that
    role.
  • Messaging scopes are separate from data scopes on purpose: data:write:*
    does not grant the ability to send messages, and a messaging key needs no
    data access.
  • Internally the API checks a granular scope per object type (for example it
    requires data:write:products to write a product); data:write:* satisfies
    all of them. A request that lacks the required access returns 403 with
    {"detail": "insufficient_scope:<scope>"}, e.g.
    insufficient_scope:data:write:products.

Keys never exceed your permissions

A key's effective permissions are the intersection of the scopes you grant
it and the permissions of the user who created it:

effective permissions = (creator's role permissions) ∩ (key scopes)

A key can never do more than its creator's role allows. If your role loses
access to an object type — or your membership in the entity is revoked — keys
you created lose that access too (a revoked membership returns
403 membership_revoked). Beyond the scope check, each write is also validated
against the creator's object-level permissions and may return
403 permission_denied:<operation>:<model>.

Test vs live keys

Use zk_test_ keys while developing and zk_live_ keys in production. Both
authenticate the same way; keep them in separate configuration so test traffic
never touches live data.

Was this helpful?