VUZDevelopers
Auth

OAuth 2.0

Authorization Code + PKCE — for a store plugin a merchant connects themselves.

VUZ runs a standard OAuth 2.0 Authorization Code flow with PKCE (RFC 7636), served by a dedicated oauth-server app — a separate NestJS service from the main API (client-api). This is the flow used by the WooCommerce plugin today.

Ask VUZ (developers@vuz.co.il) for the oauth-server base URL for your environment and to register your integration as an OAuth client (client_id / redirect URI). The examples below use an <oauth-base-url> placeholder — substitute the base URL you were given (locally the oauth-server defaults to http://localhost:3022).

The flow

Generate a PKCE pair

Create a code_verifier (random string) and its code_challenge (BASE64URL(SHA256(code_verifier))) client-side, per RFC 7636.

Redirect the merchant to /oauth/authorize

GET /oauth/authorize
  ?response_type=code
  &client_id=<your_client_id>
  &redirect_uri=<your_redirect_uri>
  &scope=documents:write%20clients:write%20business:read
  &code_challenge=<code_challenge>
  &code_challenge_method=S256
  &state=<random_csrf_token>

The merchant logs in (or is already logged in) to VUZ, picks which of their businesses to connect (if they have more than one), and sees a consent screen listing exactly the scopes you requested.

Merchant approves — VUZ redirects back with a code

GET <your_redirect_uri>?code=<authorization_code>&state=<same_state>

Verify state matches what you sent (CSRF protection) before proceeding.

Exchange the code for tokens

curl -X POST <oauth-base-url>/oauth/token \
  -d grant_type=authorization_code \
  -d code=<authorization_code> \
  -d redirect_uri=<your_redirect_uri> \
  -d client_id=<your_client_id> \
  -d client_secret=<your_client_secret> \
  -d code_verifier=<code_verifier>

Response:

{
  "access_token": "vuz_at_...",
  "refresh_token": "vuz_rt_...",
  "token_type": "Bearer",
  "expires_in": 3600,
  "scope": "documents:write clients:write business:read"
}

Call the API

curl https://api.vuz.co.il/api/v1/documents \
  -H "Authorization: Bearer vuz_at_..."

Refreshing

Access tokens expire in 1 hour. Exchange the refresh token before then:

curl -X POST <oauth-base-url>/oauth/token \
  -d grant_type=refresh_token \
  -d refresh_token=<your_refresh_token> \
  -d client_id=<your_client_id> \
  -d client_secret=<your_client_secret>

Refresh tokens rotate on every use — the response contains a new refresh token; the old one is invalidated. If you present an already-used (stale) refresh token, VUZ treats it as theft and revokes the entire token family — you must send the merchant through /oauth/authorize again.

Revoking

POST /oauth/revoke

The merchant can also revoke access from their own VUZ dashboard at any time — your integration must handle a sudden 401 token_revoked on any call and re-trigger the connect flow.

Scopes

Request only what you need — the consent screen shows the merchant exactly what you're asking for. See Auth → Scopes for the full list; it is the same canonical scope model (50 resource:action scopes) shared with API keys, enforced identically on every route.

On this page