Skip to main content

Authentication

The developer API is for server-side integrations. Scope-gated service endpoints authenticate with an API key that the integration's server exchanges for a short-lived access token.

Choose an Authentication Method​

  • API key and access token. Used by every scope-gated service endpoint. An Org Admin creates an API key with the permissions the integration needs, the integration exchanges it for an access token, then calls the endpoint with that token. See API key and access token.
  • Admin session. Used only by the API key management endpoints, which are the same operations the NeonNow Admin app uses to manage keys. See Managing keys through the API.

The generated API reference is the authoritative inventory of currently available operations, and each operation states the scope it requires.

A separate delegated OAuth flow exists for onboarded server-side integrations that act with a person's consent. It is not a public developer API operation. See Delegated server-side OAuth.

Both models keep credentials and token exchange on the integration's server. They must not be implemented in browser-only or mobile client code.

API Key and Access Token​

API keys are organisation-scoped credentials for unattended integrations. Each key is a client ID (starting nnpk_) plus a client secret (starting nnsk_), and carries the permissions, or scopes, that limit what its access tokens can do.

Create an API Key​

An Org Admin creates keys in the NeonNow Admin app under Organisation Settings > Security > API Keys, choosing a name, an expiry and the permissions the integration needs. See API Keys for the full steps.

The client secret is shown only once, when the key is created. The administrator should transfer it through an approved secure channel, and the integration should store it in a secret manager. If the secret is lost, create a replacement key; it cannot be retrieved later.

Exchange a Key for an Access Token​

The integration's server exchanges the client ID and secret for an access token at the token endpoint of the authentication service, in the same region as the endpoints it will call:

curl -X POST "https://auth-service.{region}.cw-neon.com/token" \
-H "Content-Type: application/json" \
-d '{
"grant_type": "client_credentials",
"client_id": "nnpk_CLIENT_ID",
"client_secret": "nnsk_CLIENT_SECRET",
"scope": "agentic-runtime-service:session:create agentic-runtime-service:session:update"
}'

The body must be JSON. grant_type is always client_credentials. scope is optional: send a space-separated list to narrow the token to some of the key's scopes, or omit it to receive all of them. See Scopes.

A successful exchange returns the token inside the standard response envelope:

{
"data": {
"accessToken": "eyJraWQiOi..."
},
"status": "Ok",
"requestId": "6f1c0d2e-..."
}

The access token is a JWT that is valid for five minutes. The response has no expires_in or token_type field, so read the expiry from the token's exp claim.

The exchange returns 400 when the body is malformed, and 403 when the client ID or secret is wrong, the key has expired or been deleted, or a requested scope is not one the key allows.

Call an Endpoint​

Send the access token with each request:

Authorization: Bearer ACCESS_TOKEN

Each request is checked against the token:

  • The {organisationId} in the path must be the organisation that owns the key.
  • The token must carry a scope that allows the operation. Each operation in the reference states the scope it requires.
  • The token must have been issued by the authentication service in the same region as the endpoint.

Any authentication or authorisation failure returns 403, including a missing or malformed Authorization header. The API does not return 401.

Cache and Refresh the Token​

The integration should cache the access token and reuse it until shortly before its exp time, rather than requesting a new token for every call. A reasonable approach is to request a new token about 30 seconds before expiry and, if a call returns 403, request a new token once and retry that call once. Retrying again will not help: the key itself has been changed, deleted, or lacks the scope.

Revocation and Expiry​

  • Editing a key revokes its tokens. Any change to a key, including its name or permissions, invalidates every access token already issued from it. The client ID and secret stay the same, so the integration only needs to request a new token.
  • Deleting a key invalidates its tokens immediately, and the key can no longer be exchanged.
  • A key's expiry is checked at exchange. Once a key expires no new tokens are issued, but a token issued shortly before expiry stays valid until its own exp, at most five minutes later.

Managing Keys Through the API​

The key management operations in the Authentication API reference are the ones the NeonNow Admin app uses:

  • POST /rest/v1/{organisationId}/key creates a key.
  • GET /rest/v1/{organisationId}/keys lists keys.
  • GET /rest/v1/{organisationId}/key/{id} reads a key.
  • PATCH /rest/v1/{organisationId}/key/{id} changes its name, description, expiry, or allowed scopes.
  • DELETE /rest/v1/{organisationId}/key/{id} deletes the key.

They are not scope-gated and do not accept access tokens. They authenticate with an Admin app session belonging to an Org Admin, so most organisations should manage keys in the Admin app instead.

Delegated Server-Side OAuth​

The delegated flow is a partial OAuth authorisation-code flow for onboarded integrations that act with a person's consent. The integration owns the user-facing redirect and callback. The platform-managed authentication service creates the provider consent URL and performs the code exchange.

The consent and exchange operations are available only to onboarded server-side integrations; they are not public developer API operations. Onboarding supplies the applicable service URLs and identity-provider name.

The integration's server requests a consent URL with:

  • identityProviderName: the configured provider.
  • redirectUri: an exact callback URI registered for the integration.
  • scopes: an array of provider scopes required for the integration.
  • state: a high-entropy, single-use value bound to the initiating browser session.

The authentication service returns a provider authorisation URL. The application redirects the person to this URL to review and approve access.

Only the minimum required scopes should be requested. The redirect URI used in this request must be reused unchanged during the token exchange.

2. Validate the Callback​

After consent, the provider redirects to the registered callback with a code and the original state.

The integration's server must reject the callback if state is missing, expired, already used, or does not exactly match the value stored for the initiating session. It must also handle provider error parameters when consent is denied or cannot be completed.

3. Exchange the Code​

The server sends the following values to the platform-managed token exchange:

{
"identityProviderName": "CONFIGURED_PROVIDER",
"redirectUri": "https://acme.example/oauth/callback",
"code": "AUTHORISATION_CODE"
}

The response contains the provider token set. Tokens must be encrypted at rest, excluded from logs, and associated with the correct organisation and user connection. If a refresh token is issued, the same token operation can refresh the token set without repeating consent.

4. Use and Revoke the Token​

Send the access token as a bearer token when calling the resource covered by the approved provider scopes:

Authorization: Bearer ACCESS_TOKEN

When a connection is removed, the server should revoke the token through the platform-managed revocation operation and delete its stored token set.

Scopes​

Scopes limit what an access token can do. They are enforced in two places:

  1. The key's permissions define the maximum scopes that its tokens can carry.
  2. The optional space-separated scope sent to /token narrows a single access token to some of those scopes.

A scope has the form service:resource:action. The available scopes are:

ProductResourceScopes
AgenticAgent configagentic-runtime-service:agent-config:read
AgenticSessionsagentic-runtime-service:session:create
agentic-runtime-service:session:read
agentic-runtime-service:session:update
CXOperational parameterscontact-flow-service:operational-parameter:create
contact-flow-service:operational-parameter:read
contact-flow-service:operational-parameter:update
contact-flow-service:operational-parameter:delete
CXCustom schedulescontact-flow-service:custom-schedule:create
contact-flow-service:custom-schedule:read
contact-flow-service:custom-schedule:update
contact-flow-service:custom-schedule:delete
CXSCIM configurationadmin-service:scim-config:create
admin-service:scim-config:read
admin-service:scim-config:update
admin-service:scim-config:delete

Wildcards grant broader access and cover actions added in future:

  • service:resource:* allows every action on one resource, for example contact-flow-service:custom-schedule:*.
  • service:* allows everything in one service, for example agentic-runtime-service:*.
  • * allows everything in every product.

A key only carries a wildcard when the administrator chose one in the Admin app (All, Everything in a product, or Full access). Ticking every action on a resource grants exactly those actions, not the wildcard.

For example, ACME could give a reporting integration only contact-flow-service:custom-schedule:read instead of broader write permissions. Separate keys should be used for separate integrations so each can be scoped, rotated, audited, and revoked independently.

For base URLs and reference conventions, see Getting Started.