Developer docs menu

Authentication

The Scalar360 API uses OAuth 2.0. Your app gets a short-lived access token for each user, scoped to what it needs.

1. Register your client

Open Super Intelligence → Developer API → API Console in Scalar360 and choose Add client:

Client typeUse it forHow users authorise
Server-based applicationWeb apps and services that other Scalar360 users connect toA consent screen (authorization code flow)
Self clientYour own scripts, back-office jobs and integrations for your organisationYou generate a grant code in the API Console

You receive a Client ID and a Client Secret. The secret is shown once — store it securely on your server and never in a browser or mobile app. You can regenerate it at any time.

Server-based applications also register one or more authorized redirect URIs (https://, or http://localhost for development).

2a. Server-based applications: get a grant code

Send the user to the authorization endpoint:

GET https://api.scalar360.com/oauth/v2/auth
  ?response_type=code
  &client_id={client_id}
  &scope=Scalar360.invoices.READ,Scalar360.customers.ALL
  &redirect_uri={redirect_uri}
  &access_type=offline
  &state={random_value}
ParameterDescription
response_typeAlways code.
client_idYour Client ID.
scopeComma-separated scopes.
redirect_uriMust exactly match a registered redirect URI.
access_typeoffline to also receive a refresh token; online (default) for a one-hour access token only.
stateRecommended. Returned unchanged so you can match the response to the request and prevent CSRF.

The user signs in to Scalar360 (if needed), sees the app name, the organisation and the access requested, and chooses Accept or Deny. Scalar360 then redirects to your redirect URI:

{redirect_uri}?code={grant_code}&state={random_value}
{redirect_uri}?error=access_denied&error_description=The+user+declined+access&state={random_value}

The grant code is valid for 10 minutes and can be used once.

2b. Self clients: generate a grant code

On your self client choose Generate code, select the scopes, a time duration (3, 5, 7 or 10 minutes) and an optional description. Copy the code and exchange it before it expires. Self-client codes always come with a refresh token.

3. Exchange the grant code for tokens

Request
curl -X POST "https://api.scalar360.com/oauth/v2/token" \
  -d "grant_type=authorization_code" \
  -d "client_id={client_id}" \
  -d "client_secret={client_secret}" \
  -d "redirect_uri={redirect_uri}" \
  -d "code={grant_code}"

redirect_uri is required for server-based applications and omitted for self clients. Client credentials can also be sent with HTTP Basic authentication.

Response
{
  "access_token": "s360_api_at_…",
  "refresh_token": "s360_api_rt_…",
  "scope": "Scalar360.invoices.READ,Scalar360.customers.ALL",
  "api_domain": "https://api.scalar360.com",
  "token_type": "Bearer",
  "expires_in": 3600
}

refresh_token is only returned for access_type=offline and self clients.

4. Call the API

curl "https://api.scalar360.com/api/v1/customers" \
  -H "Authorization: Scalar360-oauthtoken {access_token}"

The Bearer scheme works too. Use the api_domain from the token response as the base URL.

5. Refresh the access token

Access tokens expire after one hour. Exchange the refresh token for a new access token whenever you get a 401 INVALID_OAUTHTOKEN or before the hour is up:

Request
curl -X POST "https://api.scalar360.com/oauth/v2/token" \
  -d "grant_type=refresh_token" \
  -d "client_id={client_id}" \
  -d "client_secret={client_secret}" \
  -d "refresh_token={refresh_token}"
Response
{
  "access_token": "s360_api_at_…",
  "scope": "Scalar360.invoices.READ,Scalar360.customers.ALL",
  "api_domain": "https://api.scalar360.com",
  "token_type": "Bearer",
  "expires_in": 3600
}
The refresh token stays the same and does not expire until it is revoked. A new access token replaces the previous one. Each user can hold up to 20 refresh tokens per client; creating a 21st revokes the oldest.

6. Revoke a token

curl -X POST "https://api.scalar360.com/oauth/v2/token/revoke" -d "token={refresh_token}"

Revoking a refresh (or access) token ends that whole authorisation immediately. Users can also revoke an app in Developer API → Authorized apps, and deleting a client revokes all of its tokens.

Organisation context

A token belongs to the user, and works in every organisation that user is an active member of. Choose the organisation for each call with the organization_id query parameter (or the X-Scalar360-Organization-Id header). Leave it out and the call runs in the organisation the token was authorised in, so existing integrations keep working.

List the organisations the user can work in
curl "https://api.scalar360.com/api/v1/organizations" \
  -H "Authorization: Scalar360-oauthtoken $ACCESS_TOKEN"
Call the API in a specific organisation
curl "https://api.scalar360.com/api/v1/invoices?organization_id=$ORGANIZATION_ID&page=1&pageSize=20" \
  -H "Authorization: Scalar360-oauthtoken $ACCESS_TOKEN"

Every call runs with the user's role, module permissions and plan in that organisation — an admin in one organisation who has limited access in another gets the limited access there. An organisation the user isn't an active member of returns 403 ORGANIZATION_ACCESS_DENIED; a malformed id returns 400 INVALID_ORGANIZATION_ID.

Token endpoint errors

HTTPerrorMeaning
401invalid_clientUnknown Client ID or wrong Client Secret.
400invalid_codeThe grant code or refresh token is invalid, expired, already used or revoked.
400invalid_redirect_uriredirect_uri does not match the authorization request.
400unsupported_grant_typeUse authorization_code or refresh_token.
{ "error": "invalid_code", "error_description": "The grant code is invalid, expired or already used" }