Supported profile
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.
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.3. Send the merchant to consent
4. Validate the callback
On success, Perkstar redirects to the exact registered URI withcode and the
original state. On denial it returns error=access_denied and the state.
- Compare
statein constant time with the stored, unused value. - Refuse missing, mismatched, expired, or already-used state.
- Mark the install attempt consumed before exchanging the code.
- Never log the authorization code or callback query string.
5. Exchange the code
The token endpoint accepts form-encoded bodies, not JSON.(application, organization_id) in your system.
6. Call the API
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
- 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.
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.

