OAuth 2.0 integration

YionStack uses the OAuth 2.0 authorization code flow to let third-party apps access user data securely. Users authorize your app, and you receive tokens to make API calls on their behalf.

Authorization code flow

  1. 01Register your app

    For a third-party integration, go to Settings → Developer to get a client_id and client_secret. (For a first-party Yionstack-family product, a platform admin registers the app at /platform/developer/apps so token tenancy resolves from the authenticating user's current business at consent time, not the app's owner.)

  2. 02Redirect the user-agent to /oauth/authorize

    This is the URL your app redirects the browser to. The API responds with a 303 to the web consent surface — your app does not render the consent UI itself.

    GET /api/v1/oauth/authorize
      ?response_type=code
      &client_id=yion_your_client_id
      &redirect_uri=https://yourapp.com/callback
      &scope=read:invoices read:contacts
      &state=random_csrf_token

    Always include a CSRF-safe state — YionStack echoes it back to your callback so you can match the response to the original request.

  3. 03User signs in and consents

    If the user isn't signed in, YionStack bounces them to /sign-in with the full OAuth URL preserved. Once signed in, the consent screen shows your app name, the requested scopes, and the current business + user. The user clicks Allow or Deny.

    On Allow, YionStack mints an authorization code and redirects to your callback:

    https://yourapp.com/callback?code=abc123...&state=random_csrf_token

    On Deny (or any validation failure), YionStack redirects with an error parameter per RFC 6749 §4.1.2.1:

    https://yourapp.com/callback?error=access_denied&state=random_csrf_token
  4. 04Exchange the code for tokens

    curl -X POST https://api.yionstack.co.uk/api/v1/oauth/token \
      -H "Content-Type: application/json" \
      -d '{
        "grant_type": "authorization_code",
        "code": "abc123...",
        "client_id": "yion_your_client_id",
        "client_secret": "ysk_your_secret",
        "redirect_uri": "https://yourapp.com/callback"
      }'
  5. 05Use the access token

    curl https://api.yionstack.co.uk/api/v1/accounting/invoices \
      -H "Authorization: Bearer your_access_token" \
      -H "x-business-id: business_uuid"

Silent sign-in & the consent screen

  • First-party (platform-scoped) apps skip consent. If your app is registered with ownerScope: 'platform' (YionStack-family products), YionStack does not render an Allow/Deny screen — it mints the code and returns it straight away, the way Google does for its own apps. Business-scoped third-party apps still show the consent screen on first authorisation.
  • prompt=none (OIDC Core §3.1.2.1) — attempt a silent sign-in without ever showing UI. If there's a live YionStack session it completes normally; if not, YionStack redirects back to your redirect_uri with error=login_required instead of dumping the user on a login page. Use it to probe for a session on load; on login_required fall back to an interactive (no-prompt) authorise request behind a user gesture.
  • prompt=login — force re-authentication even if a session exists.
  • The canonical sign-in / consent host is moving to account.yionstack.co.uk; always start the flow from https://api.yionstack.co.uk/api/v1/oauth/authorize and follow the 303 — don't hard-code the consent page's host.

Token lifecycle

TokenTTLNotes
Access token1 hourInclude in Authorization header
Refresh token30 daysUse to get a new access token without re-authorization
Authorization code10 minutesSingle-use — exchange immediately

Refreshing tokens

curl -X POST https://api.yionstack.co.uk/api/v1/oauth/token \
  -H "Content-Type: application/json" \
  -d '{
    "grant_type": "refresh_token",
    "refresh_token": "your_refresh_token",
    "client_id": "yion_your_client_id",
    "client_secret": "ysk_your_secret"
  }'

Revoking tokens

curl -X POST https://api.yionstack.co.uk/api/v1/oauth/revoke \
  -H "Content-Type: application/json" \
  -d '{ "token": "access_or_refresh_token" }'

Scopes

Request only the scopes your app needs. Scopes must be a subset of the scopes allowed on your developer app registration.

ScopeDescription
read:invoicesView invoices, line items, and payment status
write:invoicesCreate, update, and send invoices
read:contactsView CRM contacts and companies
write:contactsCreate and update contacts
read:dealsView CRM deals and pipeline
write:dealsCreate deals and change stages
read:expensesView expense claims and categories
read:reportsView financial reports and analytics
read:employeesView employee records (HR module)
read:ordersView ecommerce orders and fulfilment

JavaScript example

const response = await fetch('https://api.yionstack.co.uk/api/v1/oauth/token', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    grant_type: 'authorization_code',
    code: authorizationCode,
    client_id: 'yion_your_client_id',
    client_secret: 'ysk_your_secret',
    redirect_uri: 'https://yourapp.com/callback',
  }),
});

const { access_token, refresh_token, expires_in } = await response.json();