Skip to main content
The Vendaze API uses OAuth 2.1 Authorization Code flow with client_secret. This is a server-side integration: all token exchanges must happen on your back-end. The client_secret must never be exposed in browser code, mobile app binaries, or any environment the end user can inspect. Before continuing, you need a client_id and client_secret. See Register your app.

How it works

1

Redirect the user to the authorization endpoint

Your server builds the authorization URL and redirects the user’s browser to it.
2

User logs in and approves

The user selects a workspace and reviews the requested scopes on the Vendaze consent screen. They can only approve or deny access in full, with no option to select individual scopes.
3

Receive the authorization code

Vendaze redirects the browser back to your redirect_uri with a short-lived code.
4

Exchange the code for tokens

Your server exchanges the code for an access_token and refresh_token via a back-end request.
5

Make API calls

Include the access_token as a Bearer token in every request.
6

Refresh when expired

Access tokens expire after 1 hour. Use the refresh_token to get a new one without user interaction.

Step 1 - Redirect the user

Build the authorization URL and redirect the user’s browser to it. This must be a browser navigation, not a server-side HTTP request. Do not use fetch, axios, curl, or any HTTP client to call this endpoint. The user must be redirected so they can log in and approve access on the Vendaze consent screen.
GET https://api.vendaze.com/oauth/authorize
  ?client_id=YOUR_CLIENT_ID
  &redirect_uri=https://yourapp.com/oauth/callback
  &response_type=code
  &state=RANDOM_CSRF_TOKEN
Example redirect in a web app:
const params = new URLSearchParams({
  client_id: 'YOUR_CLIENT_ID',
  redirect_uri: 'https://yourapp.com/oauth/callback',
  response_type: 'code',
  state: crypto.randomUUID(),
});

// Store state for CSRF verification on callback
sessionStorage.setItem('oauth_state', params.get('state'));

// Navigate the browser. Never use fetch/axios here.
window.location.href = `https://api.vendaze.com/oauth/authorize?${params}`;
ParameterRequiredDescription
client_idYesYour app’s client ID.
redirect_uriYesMust exactly match a registered URI.
response_typeYesMust be code.
stateNoRandom string you generate. Returned unchanged. Strongly recommended to prevent CSRF.
Always include state and verify it on the callback. Reject any callback where the received state does not match what you sent. This protects against CSRF attacks.

Step 2 - User authorizes

The user selects a workspace and reviews the requested scopes on the Vendaze consent screen. They can only approve or deny access in full, with no option to select individual scopes. No action required on your side during this step.

Step 3 - Handle the callback

After approval, the user is redirected to your redirect_uri:
https://yourapp.com/oauth/callback?code=AUTH_CODE&state=YOUR_STATE
Verify state matches what you stored, then proceed to exchange the code. If the user denies authorization:
https://yourapp.com/oauth/callback?error=access_denied&state=YOUR_STATE
Handle the error parameter and show an appropriate message to the user.

Step 4 - Exchange code for tokens

Authorization codes expire in 10 minutes and can only be used once. Exchange immediately after receiving the callback.
This request must be made from your server, never from the browser.
curl -X POST https://api.vendaze.com/oauth/token \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "grant_type=authorization_code&code=AUTH_CODE_FROM_CALLBACK&client_id=YOUR_CLIENT_ID&client_secret=YOUR_CLIENT_SECRET"
Response (200):
{
  "access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
  "refresh_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
  "token_type": "Bearer",
  "expires_in": 3600,
  "workspace_slug": "acme-corp"
}
FieldDescription
access_tokenUse this in every API request. Expires in 1 hour.
refresh_tokenUse this to get a new access token. Valid for 60 days if used regularly.
token_typeAlways Bearer.
expires_inSeconds until the access token expires. Always 3600.
workspace_slugSlug of the workspace the user authorized. Use this to identify the connected account in your app.

Token storage

Store both tokens securely on your server. The following practices apply:
  • access_token: short-lived (1 hour). Store in memory or a fast cache. Never in localStorage or cookies accessible to JavaScript.
  • refresh_token: long-lived (60 days). Store encrypted in your database, associated with the user and workspace. This is the credential that allows you to maintain access without user interaction.
  • Never log either token. Never include them in URLs or query strings.
  • Never expose them in API responses to your own front-end. Your front-end should call your back-end, which calls Vendaze.

Step 5 - Make API calls

Include the access_token in every request as a Bearer token:
curl https://api.vendaze.com/v1/people \
  -H "Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9..."
The workspace context is resolved automatically from the token. You never send a workspace identifier in requests.

Step 6 - Refresh the access token

Access tokens expire after 1 hour. Refresh them using the refresh token before the expiry, or reactively when you receive a token_expired error.
curl -X POST https://api.vendaze.com/oauth/token \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "grant_type=refresh_token&refresh_token=YOUR_REFRESH_TOKEN&client_id=YOUR_CLIENT_ID&client_secret=YOUR_CLIENT_SECRET"
The response is identical to Step 4. Replace both tokens on your side. A new refresh_token is issued on every refresh and the previous one is immediately invalidated.
Refresh tokens expire if unused for 60 days. Each time you use a refresh token, the 60-day window resets. If a refresh token expires, the user must go through the full authorization flow again.

Revoking access

To disconnect a workspace from your app, revoke the access token:
curl -X POST https://api.vendaze.com/oauth/revoke \
  -H "Content-Type: application/json" \
  -d '{
    "token": "ACCESS_TOKEN",
    "client_id": "YOUR_CLIENT_ID",
    "client_secret": "YOUR_CLIENT_SECRET"
  }'
Always send the access_token, not the refresh_token. The revoke endpoint requires a JWT to identify the user and remove the authorization grant.
After revoking, delete both tokens from your storage. The user will need to re-authorize if they want to reconnect.
Next: Make your first request to use your access token in a real API call.