Intempt Docs
Developer Docs

API Overview & Authentication

Base URLs, request format, and the three ways to authenticate with the Intempt API: JWT bearer tokens, API keys, and SCIM bearer tokens.

API Overview & Authentication

The Intempt Platform API is versioned under /v1 and served from a single origin per environment. There's no separate auth.intempt.com host: that string only appears as the iss claim inside issued JWTs.


Base URLs

EnvironmentBase URL
Productionhttps://api.intempt.com
Staginghttps://api.staging.intempt.com
Local development (auth service)http://localhost:8090

Authentication schemes

SchemeHeaderUsed for
JWT bearerAuthorization: Bearer <jwt>Console and CLI sessions. Required on nearly every /v1/** endpoint.
API keyAuthorization: Bearer <api_key>Server-to-server integrations calling the platform API. Issued and managed via /v1/{orgName}/api-keys.
SCIM bearer tokenAuthorization: Bearer <scim_token>SCIM 2.0 provisioning at /scim/v2/{slug}/*, called by an identity provider, not by application code.
None (public)NoneOAuth/OIDC endpoints, .well-known discovery, OTP send/verify, passkey authentication, SSO callbacks (/sso/**), and public invite/share links.

📘 Good to know

/v1/auth/otp/*, /v1/auth/mfa/challenge/verify, and /v1/auth/passkeys/authenticate/* are public endpoints. The OTP code, challenge token, or WebAuthn assertion in the request body is the proof of identity, so no bearer token is sent.


JWT bearer tokens

JWTs are issued by the token endpoint, POST /oauth/token, using one of three grant types:

Grant typeUsed for
authorization_codeExchanging a code from a completed login (OTP, social, or passkey) for tokens. Requires a PKCE code_verifier.
refresh_tokenGetting a new access token without a full login.
urn:ietf:params:oauth:grant-type:device_codeCLI or headless devices completing the device code flow.

The token response:

FieldTypeDescription
access_tokenstringRS256 JWT, signed by the auth service.
refresh_tokenstringOpaque token used to get a new access token. Valid for 12 hours.
token_typestringAlways Bearer.
expires_inintegerAccess token lifetime in seconds (900).

📘 Good to know

Refresh tokens are single-use: exchanging one issues a new one and invalidates the old one. If a used-up refresh token is presented again, the auth service treats it as a replay and revokes the whole session.

Verify a JWT's signature against the public key set at GET /.well-known/jwks.json.


API keys

API keys are managed at the organization level.

MethodPathPurpose
GET/v1/{orgName}/api-keysList API keys
POST/v1/{orgName}/api-keysCreate an API key
PATCH/v1/{orgName}/api-keys/{keyId}Update an API key's name or project assignments
PATCH/v1/{orgName}/api-keys/{keyId}/activeEnable or disable an API key
POST/v1/{orgName}/api-keys/{keyId}/regenerateRotate an API key's secret
DELETE/v1/{orgName}/api-keys/{keyId}Delete an API key

Creating a key requires a name and a level (admin, public, or private), and accepts an optional projectIds array to scope the key to specific projects.

Each key in a list response has these fields:

FieldTypeDescription
idstring (uuid)Key identifier
namestringLabel you gave the key
levelstringOne of admin, public, private
projectIdsarray of integerProjects the key is scoped to
prefixstringNon-secret identifier used to tell keys apart in a list
createdAtstring (date-time)Creation timestamp
lastUsedAtstring (date-time)Last time the key authenticated a request
activebooleanWhether the key currently authenticates requests

The full key value is only ever returned once: in the response to POST /v1/{orgName}/api-keys (as fullKey) and again if you regenerate it (as newFullKey from POST /v1/{orgName}/api-keys/{keyId}/regenerate). Store it when you create or regenerate it. Regenerating replaces the secret but keeps the key's name, level, and project assignments.


SCIM bearer tokens

SCIM 2.0 endpoints at /scim/v2/{slug}/* authenticate with a static bearer token, not a JWT, because identity providers like Okta and Azure AD only support static bearer tokens for SCIM outbound connections. SCIM tokens are SHA-256 hashed at rest.


Use cases

  1. A frontend app tracking events in the browser. Use a public API key. It's designed to be visible in client-side code.
  2. A backend job syncing data on a schedule. Use a private API key, kept out of any client-side code.
  3. A script that manages keys or projects across your whole org. Use an admin API key.
  4. The Intempt console or CLI. Use a JWT obtained through a real login (OTP, social, or passkey), not an API key. A JWT represents a signed-in person.
  5. A CLI or device with no browser available. Use the device code grant to get a JWT without a redirect-based login.
  6. A long-running session that shouldn't force a re-login. Exchange the refresh token at /oauth/token instead of starting the login flow over.
  7. Connecting an identity provider, like Okta or Azure AD, for user provisioning. Use a SCIM bearer token, generated separately from any API key or JWT.
  8. A key you suspect is compromised. Regenerate it rather than deleting and recreating it, so existing project assignments and the key's name stay intact.

Error responses

Failed requests return a JSON body:

FieldTypeDescription
errorstringMachine-readable error code
messagestringHuman-readable description
detailsobjectAdditional context (optional)

Some endpoints apply their own limits on top of standard auth checks. For example, POST /v1/auth/otp/send returns 429 if you request more than 3 codes per minute for the same email.


Where to go next

  • API keys for creating, revealing, and rotating keys from Org Settings.
  • How Intempt works for how authenticated requests fit into the wider tracking model.
  • JavaScript SDK for the client-side reference that uses a public API key under the hood.
  • Track Data API for the first endpoint most server-side integrations call after authenticating.

On this page