API reference

OAuth

Issue, introspect and revoke access tokens, plus discovery metadata.

Issue an access token

POSTapi.niucore.com/api/oauth/token

No bearer

Exchanges client_id and client_secret for a short-lived access token. It is the only supported grant: client_credentials (RFC 6749 §4.4).

Credentials go in Authorization: Basic (client_secret_basic) or in the body (client_secret_post), but never both at once: sending them through both channels returns invalid_request, because it leaves ambiguous which one wins.

The scope parameter is optional and only narrows: asking for a scope the credential does not hold returns invalid_scope. Without scope, the token is issued with every scope the credential currently holds.

There is no refresh token

Client Credentials does not use one: when the access token expires, you request another with the same credentials. Keep the token in memory and refresh it slightly before expires_in.

Request body

grant_typestringrequired

The only supported grant. Any other value returns unsupported_grant_type.

client_credentials

client_idstring

Public identifier of the credential (nc_…). Required unless you use Authorization: Basic.

client_secretstring

Credential secret (ncs_…). Required unless you use Authorization: Basic.

scopestring

Space-separated subset of scopes. Omitting it requests every scope currently in force.

Returns

access_tokenstring

Signed JWT. Used as Bearer.

token_typestring

Always Bearer.

expires_ininteger

Lifetime in seconds. Never exceeds the credential's remaining lifetime.

scopestring

Scopes actually granted, space separated. It may be narrower than requested if the user's role changed.

Errors

  • 400unsupported_grant_typegrant_type is not client_credentials.
  • 400invalid_scopeA nonexistent scope was requested, or one the credential no longer holds.
  • 400invalid_requestCredentials were sent through Basic and the body at the same time.
  • 401invalid_clientNonexistent credential, wrong secret, revoked or expired credential, inactive user or disabled company. One single error for every case, by design.
  • 413invalid_requestThe form exceeds 8 KB.
  • 429rate_limit_exceededThe per-IP or per-client_id bucket was exceeded.
curl -sS -X POST 'https://api.niucore.com/api/oauth/token' \
  -H 'Content-Type: application/x-www-form-urlencoded' \
  -u "$NIUCORE_CLIENT_ID:$NIUCORE_CLIENT_SECRET" \
  -d 'grant_type=client_credentials' \
  -d 'scope=chat:read chat:write'
Response
{
  "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "token_type": "Bearer",
  "expires_in": 3600,
  "scope": "chat:read chat:write"
}

Introspect a token

POSTapi.niucore.com/api/oauth/introspect

No bearer

Returns the state and claims of an access token (RFC 7662). It authenticates the credential, not the token: you introspect your own.

Note

It answers 200 whenever the client authenticates. An expired, revoked, unreadable, or foreign token returns {"active": false} — without telling which, so the endpoint is not an oracle.

Request body

tokenstringrequired

The access token to introspect.

Returns

activeboolean

false when the token is unusable. It is the only guaranteed field.

scopestring

Token scopes.

client_idstring

Issuing credential.

usernamestring

Email of the owning user.

expinteger

Expiry (epoch).

iatinteger

Issued at (epoch).

jtistring

Token identifier.

company_idinteger

Company of the credential.

Errors

  • 401invalid_clientThe client did not authenticate. It is the only possible error.
curl -sS -X POST 'https://api.niucore.com/api/oauth/introspect' \
  -H 'Content-Type: application/x-www-form-urlencoded' \
  -u "$NIUCORE_CLIENT_ID:$NIUCORE_CLIENT_SECRET" \
  -d "token=$NIUCORE_ACCESS_TOKEN"
Response
{
  "active": true,
  "scope": "chat:read chat:write",
  "client_id": "nc_7f3c1a9b8e2d4056",
  "username": "integraciones@acme.com",
  "token_type": "Bearer",
  "exp": 1767225600,
  "iat": 1767222000,
  "nbf": 1767222000,
  "sub": "integraciones@acme.com",
  "aud": "niucore-public-api",
  "iss": "https://api.niucore.com",
  "jti": "0f2f5a52-9c1e-4f7a-9c3e-1c2b3d4e5f60",
  "tid": 412,
  "company_id": 2149
}

Revoke an access token

POSTapi.niucore.com/api/oauth/revoke

No bearer

Invalidates the presented access token (RFC 7009). It does not revoke the credential: for that, revoke it from the application.

Note

It always answers 200 — even for an unknown or already expired token — as the RFC requires, and so it cannot be used to learn whether a token exists. Only the owner can revoke its token: one from another credential is silently ignored.

Request body

tokenstringrequired

The access token to revoke.

Errors

  • 401invalid_clientThe client did not authenticate.
curl -sS -X POST 'https://api.niucore.com/api/oauth/revoke' \
  -H 'Content-Type: application/x-www-form-urlencoded' \
  -u "$NIUCORE_CLIENT_ID:$NIUCORE_CLIENT_SECRET" \
  -d "token=$NIUCORE_ACCESS_TOKEN"
Response
HTTP/1.1 200 OK
Cache-Control: no-store

Authorization server metadata

GETapi.niucore.com/.well-known/oauth-authorization-server

No bearer

RFC 8414 discovery: endpoints, grants, authentication methods and the scope catalog. A generic OAuth client can configure itself from this alone.

Tip

It is public and cacheable (max-age=3600). No credentials required.

curl -sS 'https://api.niucore.com/.well-known/oauth-authorization-server'
Response
{
  "issuer": "https://api.niucore.com",
  "token_endpoint": "https://api.niucore.com/api/oauth/token",
  "introspection_endpoint": "https://api.niucore.com/api/oauth/introspect",
  "revocation_endpoint": "https://api.niucore.com/api/oauth/revoke",
  "grant_types_supported": ["client_credentials"],
  "token_endpoint_auth_methods_supported": [
    "client_secret_basic",
    "client_secret_post"
  ],
  "scopes_supported": [
    "chat:read", "chat:write", "areas:read", "skills:read", "skills:write",
    "rules:read", "rules:write", "permissions:read", "libraries:read",
    "libraries:write", "connectors:use", "profile:read", "profile:write",
    "analytics:read"
  ],
  "response_types_supported": [],
  "service_documentation": "https://api.niucore.com/api/v1/docs"
}