OAuth2 setup
For public apps that need users to grant xuly.io access without pasting API keys.
If you're building an app that acts on behalf of xuly.io users — a BI dashboard, a Slack bot, a Zapier-style integration — OAuth2 is the right auth model. For internal scripts or one-off automations, use an API key instead.
Register your app
Go to Settings → OAuth apps (Business plan and above) and click New app. You'll need:
- A display name and logo (shown to users on the consent screen).
- A redirect URL — we only redirect to URLs you register explicitly.
- A set of scopes you want to request — keep it minimal for better consent rates.
On creation you receive a client ID (safe to embed in frontends) and a client secret (never embed in frontends).
The authorization flow
xuly.io implements the standard Authorization Code Flow with PKCE.
Step 1 — Send user to the authorize URL
https://app.xuly.io/oauth/authorize?
response_type=code
&client_id=<your_client_id>
&redirect_uri=<your_redirect>
&scope=stats:read%20integrations:read
&state=<random_csrf_token>
&code_challenge=<pkce_challenge>
&code_challenge_method=S256Step 2 — Exchange the code for tokens
POST https://api.xuly.io/oauth/token
Content-Type: application/x-www-form-urlencoded
grant_type=authorization_code
&code=<code_from_redirect>
&redirect_uri=<same_as_before>
&client_id=<your_client_id>
&client_secret=<your_client_secret>
&code_verifier=<pkce_verifier>You get back an access token (valid 1h), a refresh token (valid 30 days, single-use), and a user context describing which workspace the user authorised.
Step 3 — Call the API
GET https://api.xuly.io/v1/stats
Authorization: Bearer <access_token>Refreshing tokens
POST https://api.xuly.io/oauth/token
grant_type=refresh_token&refresh_token=<refresh>&client_id=...&client_secret=...Refresh tokens are single-use — each refresh returns a fresh pair. The old refresh token is invalidated immediately, so save the new one.
Scopes
Request the narrowest scopes you need. Users are more likely to approve minimal-access apps.
stats:read— read aggregated statsintegrations:read,integrations:writecampaigns:read,campaigns:writeinvoices:read,invoices:writewebhooks:manage