Enterprise — Authentication

Every call to the Enterprise API carries an OAuth 2.0 bearer token. This page covers getting one, the scopes that gate the enterprise surface, and revoking a token.

Credentials

You need a client ID and client secret issued for your enterprise account. These are machine credentials — there is no browser redirect and no user login.

The client secret authenticates your whole organisation. Keep it server-side. Never ship it in a mobile app or browser bundle.

Getting a token

Kesk supports exactly one grant: client_credentials. Authenticate with HTTP Basic — client ID as username, secret as password — and send the grant type as JSON.

A successful response:

Enterprise credentials authenticate against enterprise.apis.kesk.app. The same endpoint answers on the vendor host, but a token minted there carries no enterprise_id claim and reaches nothing on this surface.

Read scope and expires_in from the response rather than assuming either. The values above are illustrative — the granted scope can be narrower than what you asked for, and the token lifetime is set server-side. Never hardcode a lifetime.

Using the token

Cache the token for its expires_in and refresh on a margin.

Enterprise scopes

ScopeGrants
enterprise:core:read
Read the enterprise record and dashboard stats
enterprise:core:write
Update the enterprise record
enterprise:users:read
List and fetch members
enterprise:users:write
Invite, update, suspend, activate, remove, reset passwords
enterprise:settings:read
Read the settings record
enterprise:settings:write
Create, update, delete and bulk-update settings
enterprise:billing:read
Read billing info, usage summaries and invoices
enterprise:vouchers:read
Read vouchers, templates and analytics
enterprise:vouchers:write
Create, update and delete vouchers and templates
enterprise:scim:read
Read the directory over SCIM
enterprise:scim:write
Provision and deprovision members over SCIM

Scopes match exactly, or by an enterprise:* wildcard on the : boundary. enterprise:* is not a synonym for the coarse grant enterprise — the wildcard grants the whole surface including the sensitive scopes the coarse grant withholds.

The coarse grant enterprise does not cover everything in the table above. The registry withholds eight scopes from coarse grants, and three of them are on this surface: enterprise:users:write, enterprise:scim:read and enterprise:scim:write. Each administers the membership of your organisation, which a consent granted for spending data must not silently carry.

So a coarse enterprise grant cannot invite, suspend or remove a member, and reaches no SCIM endpoint. Request those three by name, or use enterprise:*. See OAuth 2.0 for the full withheld list.

Read the granted scope back from the token response regardless; it is the record of what you were actually given.

The complete scope registry is published as scopes_supported at accounts.kesk.app/.well-known/oauth-authorization-server. Note the host: that is the authorization server, not the API host, so the path does not resolve on enterprise.apis.kesk.app. The table above is the subset that gates the enterprise surface; the registry also lists the scopes of every other surface. The scope in your token response remains the record of what you were actually granted.

Errors

SituationStatusBody
Missing Authorization header
401
{"title":"Unauthorized","message":"Authentication required.","status":401,"type":"unauthorized"}
Wrong client ID or secret
401
{"error":"invalid_client","error_description":"Client authentication failed."}
Unsupported grant_type
400
{"error":"unsupported_grant_type","error_description":"Only 'client_credentials' grant type is supported."}
Scope not on your registration
400
{"error":"invalid_scope","error_description":"Scope exceeds the client's registered grant: ..."}
Form-encoded body on /token
400
{"error":"Bad Request","message":"invalid content type ..., expect: application/json"}

Validation order is grant_type → client → scope.

The missing-header and wrong-content-type cases return plain text — parsing either as JSON will throw.

Revoking a token

The token endpoint takes JSON; the revoke endpoint takes application/x-www-form-urlencoded. Sending JSON here returns 415.

token_type_hint is optional and ignored, and access_token is the only value the endpoint will parse — any other string is a 400. Revocation applies to access tokens: passing a refresh token returns 200 and revokes nothing.

Revocation kills the entire token family, not just the string you passed.

Per RFC 7009 the endpoint returns 200 even for an unknown token, so a 200 means "not valid any more" rather than "existed and was revoked". Treat it as idempotent and safe to retry.

Reference

Generated reference — every type, field and argument, built from the live schema.

Built with