Skip to main content
Use OAuth when one application will be installed by multiple Perkstar businesses. Each merchant approves access to one organisation; your backend receives a scoped, short-lived access token and a rotating refresh token.

Supported profile

Perkstar does not support an implicit flow or a marketplace client_credentials grant. A merchant must approve access to their business.

1. Register the application

Marketplace applications are reviewed and registered by Perkstar. Send support@perkstar.co.uk:
  • application name, description, and HTTPS icon URL;
  • exact development, staging, and production redirect URIs;
  • the minimum scopes required;
  • a security/support contact and uninstall URL; and
  • whether the application is ready for test or live merchants.
Perkstar returns a client_id and shows the client_secret once. Store the secret in your backend’s secret manager. Dynamic client registration at /api/oauth/register is reserved for read-only MCP clients and cannot register a marketplace app or request REST API scopes.

2. Create state and PKCE

Create a fresh verifier, challenge, and state for every install attempt. Store the verifier and state in a short-lived, single-use server-side record tied to the browser session.
The merchant signs in, chooses an organisation they own or manage, and sees the requested permissions. Perkstar does not redirect to an unregistered URI when the request is invalid.

4. Validate the callback

On success, Perkstar redirects to the exact registered URI with code and the original state. On denial it returns error=access_denied and the state.
  1. Compare state in constant time with the stored, unused value.
  2. Refuse missing, mismatched, expired, or already-used state.
  3. Mark the install attempt consumed before exchanging the code.
  4. Never log the authorization code or callback query string.
Authorization codes are short-lived and single-use. A duplicate or delayed callback must start a fresh install.

5. Exchange the code

The token endpoint accepts form-encoded bodies, not JSON.
Store the organisation ID with the grant and enforce one active installation record per (application, organization_id) in your system.

6. Call the API

Treat a 401 as an authentication problem, not permission to switch to another merchant’s token. A 403 means the authenticated grant, scope, plan, or account state does not permit that action.

7. Rotate refresh tokens atomically

Every successful refresh invalidates the supplied refresh token and returns a new one. Use a lock or compare-and-swap around the installation row.
1

Lock one installation

Ensure two workers cannot refresh the same grant concurrently.
2

Exchange the current token

Send the token stored on the locked row. Do not retry an ambiguous refresh concurrently from another worker.
3

Commit both replacements

Replace the access token, refresh token, expiry, and scopes in one database transaction before releasing the lock.
4

Reconnect on invalid_grant

Refresh-token replay revokes the chain. Stop background jobs and send the merchant through authorization again; do not loop retries.

8. Revoke and uninstall

Revoking either token revokes the pair. After a successful uninstall:
  • stop polling, queue drains, and webhook side effects for the merchant;
  • remove active credentials from normal application storage;
  • delete copied personal data that is no longer required;
  • retain only the minimum audit or legal record required by your policy; and
  • make reinstall create a fresh grant rather than reviving old credentials.
Merchants can also revoke access in Settings → Connected apps. Your jobs must handle that without relying on your own uninstall screen being called.

Error handling

Launch checklist

  • Redirect URIs are exact and environment-specific.
  • State and PKCE are fresh, server-stored, expiring, and single-use.
  • Client secrets and tokens never reach browser or mobile code.
  • Refresh replacement is atomic and concurrency-tested.
  • invalid_grant, merchant denial, and revocation lead to a clear reconnect state.
  • Jobs are pinned to the stored organization_id.
  • Uninstall removes credentials and unnecessary cached personal data.
  • Test and live application credentials are separated.
  • The security and privacy review is complete.