DashboardDeveloper Portal

OAuth 2.0

Implement the Authorization Code flow to access the ElevatedPOS API on behalf of merchant accounts. OAuth apps can act on a merchant's data with the exact permissions they approve — no need to handle merchant credentials.

Authorization Code Flow

  Your App                   Auth Server                  Merchant (User)
     │                            │                               │
     │  1. Redirect to /authorize  │                               │
     │ ─────────────────────────► │                               │
     │                            │  2. Show consent screen       │
     │                            │ ─────────────────────────────►│
     │                            │                               │
     │                            │  3. Merchant approves          │
     │                            │ ◄─────────────────────────────│
     │                            │                               │
     │  4. Redirect with ?code=…  │                               │
     │ ◄───────────────────────── │                               │
     │                            │                               │
     │  5. POST /oauth/token      │                               │
     │    {code, client_secret}   │                               │
     │ ─────────────────────────► │                               │
     │                            │                               │
     │  6. {access_token,         │                               │
     │      refresh_token}        │                               │
     │ ◄───────────────────────── │                               │
     │                            │                               │
     │  7. API calls with Bearer  │                               │
     │ ─────────────────────────► │                               │
1

Register your app

Create an OAuth app in the developer dashboard to receive a client_id and client_secret.

2

Redirect the merchant

Send the merchant to the ElevatedPOS authorization URL with your client_id, requested scopes, and redirect_uri.

GET https://app.elevatedpos.com.au/oauth/authorize
3

Merchant approves

The merchant reviews requested permissions on the ElevatedPOS consent screen and approves or denies.

4

Exchange the code

ElevatedPOS redirects to your redirect_uri with a code parameter. Exchange it for tokens immediately — codes expire in 60 seconds.

POST https://api.elevatedpos.com.au/api/v1/oauth/token
5

Access the API

Use the access_token as a Bearer token. It expires in 900 seconds — refresh using refresh_token before expiry.

Authorization URL

https://app.elevatedpos.com.au/oauth/authorize
  ?response_type=code
  &client_id=YOUR_CLIENT_ID
  &redirect_uri=https%3A%2F%2Fyourapp.com%2Fcallback
  &scope=catalog%3Aread+orders%3Aread+customers%3Awrite
  &state=RANDOM_CSRF_STATE_TOKEN
response_typecodeAlways "code" for Authorization Code flow.
client_idYOUR_CLIENT_IDFrom your registered OAuth app.
redirect_urihttps://yourapp.com/callbackMust match a registered URI exactly.
scopecatalog:read orders:readSpace-separated list of requested scopes.
staterandom_stringCSRF protection token. Verify on callback to prevent CSRF attacks.

Token Exchange

Node.js — exchange authorization code for tokens

async function exchangeCodeForTokens(code: string) {
  const response = await fetch('https://api.elevatedpos.com.au/api/v1/oauth/token', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
      grant_type: 'authorization_code',
      code,
      client_id: process.env.ELEVATEDPOS_CLIENT_ID,
      client_secret: process.env.ELEVATEDPOS_CLIENT_SECRET,
      redirect_uri: 'https://yourapp.com/callback',
    }),
  });

  if (!response.ok) {
    const err = await response.json();
    throw new Error(`Token exchange failed: ${err.error_description}`);
  }

  return response.json() as Promise<TokenResponse>;
}

Node.js — refresh an expired access token

async function refreshAccessToken(refreshToken: string) {
  const response = await fetch('https://api.elevatedpos.com.au/api/v1/oauth/token', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
      grant_type: 'refresh_token',
      refresh_token: refreshToken,
      client_id: process.env.ELEVATEDPOS_CLIENT_ID,
      client_secret: process.env.ELEVATEDPOS_CLIENT_SECRET,
    }),
  });

  if (!response.ok) throw new Error('Failed to refresh token — re-authorize required');
  return response.json() as Promise<TokenResponse>;
}

Token response format

interface TokenResponse {
  access_token: string;    // Bearer token for API requests
  refresh_token: string;   // Use to obtain a new access_token
  token_type: 'Bearer';
  expires_in: 900;         // Seconds until access_token expires (15 min)
  scope: string;           // Approved scopes (may differ from requested)
  org_id: string;          // The merchant's organisation ID
}

// Example JSON response:
{
  "access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
  "refresh_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
  "token_type": "Bearer",
  "expires_in": 900,
  "scope": "catalog:read orders:read customers:write",
  "org_id": "org_01HXXXXXXXXXXXXXXXX"
}

Scopes Reference

Request only the scopes your integration needs. Merchants are more likely to approve minimal permission sets.

ScopeAccessDescription
catalog:readReadRead products, categories, modifiers, and price lists.
catalog:writeWriteCreate and update products, categories, and price lists.
orders:readReadList and retrieve orders and line items.
orders:writeWriteCreate orders, update status, initiate refunds.
customers:readReadSearch and retrieve customer profiles.
customers:writeWriteCreate and update customer records.
loyalty:readReadView programs, members, and point balances.
loyalty:writeWriteAccrue and redeem loyalty points.
payments:readReadView payment records and methods.
payments:writeWriteCreate payment intents, capture, and void.
inventory:readReadRead stock levels, movements, and alerts.
inventory:writeWriteAdjust stock and create transfers.
reports:readReadAccess sales, inventory, and financial reports.
webhooks:writeWriteRegister and manage webhook subscriptions.
automations:readReadRead automation rules and execution history.
automations:writeWriteCreate and modify automation rules.

Token Revocation

Tokens can be revoked by the merchant (via the ElevatedPOS dashboard) or programmatically by your app:

// Revoke a token (access or refresh)
await fetch('https://api.elevatedpos.com.au/api/v1/oauth/revoke', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    token: accessTokenOrRefreshToken,
    client_id: process.env.ELEVATEDPOS_CLIENT_ID,
    client_secret: process.env.ELEVATEDPOS_CLIENT_SECRET,
  }),
});
// Returns 200 OK on success (even if token was already expired)

Revoking an access token immediately invalidates it. Revoking a refresh token invalidates all access tokens derived from it.

Token Lifecycle

Access Token

15 minutes

Short-lived. Include as Authorization: Bearer <token> on every API request.

Refresh Token

30 days

Long-lived. Use to obtain a new access token. Rotating — each use issues a new refresh token.

Authorization Code

60 seconds

One-time use. Exchange immediately after receiving. Codes are invalidated after first use.

Security Best Practices

Keep client_secret server-side only

Never expose your client_secret in frontend JavaScript, mobile binaries, or public repositories. It should only live in server-side environment variables.

Always validate the state parameter

Generate a cryptographically random state value before redirecting. Verify it matches on callback. This prevents CSRF attacks where a malicious site tricks a user into authorizing your app.

Request minimal scopes

Request only the scopes your integration actually needs. Merchants are more likely to approve minimal permissions, and a narrower token minimises damage if compromised.

Implement PKCE for public clients

For mobile apps and SPAs where client_secret cannot be kept secret, implement PKCE (Proof Key for Code Exchange, RFC 7636). Generate a code_verifier and send its SHA256 hash as code_challenge.

Rotate refresh tokens on every use

ElevatedPOS issues a new refresh token each time you use one. Always store and use the latest refresh token. If a previous refresh token is presented, ElevatedPOS will revoke the entire token family.

Store tokens encrypted at rest

Encrypt stored access and refresh tokens using AES-256-GCM or a KMS-managed key. Never store tokens in plaintext in your database.

Handle merchant-initiated revocation gracefully

Merchants can disconnect your app at any time from their dashboard. Handle 401 responses from the API by detecting invalid_grant errors and re-initiating the OAuth flow.