Skip to main content
This page explains the security decisions built into the Vendaze API itself: why they were made, what they protect against, and what they mean for your integration. Operational practices like token storage and secret rotation are covered in Authentication and Register your app.

Authorization model

The Vendaze API uses OAuth 2.1 Authorization Code flow with client_secret. This means:
  • Your app is a confidential client. It has a client_secret that must stay on your server.
  • All token exchanges happen server-side. The browser never touches a token directly.
  • Users authorize access to a specific workspace. Your token is scoped to that workspace only.
This is not an integration for SPAs, mobile apps without a back-end, or any environment where the end user can inspect the running code. If your app has no server-side component, you need to build one before integrating.

PKCE is handled internally

OAuth 2.1 recommends PKCE (Proof Key for Code Exchange) for all authorization flows. The Vendaze API implements PKCE, but manages it entirely on the server side. Your integration does not need to generate or send a code_verifier. Here is what happens when a user authorizes your app:
  1. Your server redirects the browser to /oauth/authorize with client_id, redirect_uri, response_type=code, and state
  2. The Vendaze API generates and manages the PKCE parameters internally
  3. After the user approves, the authorization_code is returned to your redirect_uri
  4. When you call /oauth/token, the API completes the PKCE exchange transparently
What this protects against: if an attacker intercepts the authorization_code in transit, they cannot exchange it for tokens. The PKCE verification happens server-side and is never exposed. Combined with client_secret validation, two independent proofs of identity are required to complete the exchange. Why you do not manage it: PKCE was designed for public clients (mobile apps, SPAs) that cannot store a client_secret. For confidential clients like yours, the client_secret already provides equivalent protection. Exposing PKCE parameters to integrators would add complexity without adding security. The Vendaze API handles it internally so the authorization flow stays clean and compatible with any standard OAuth library.

Token validation is asymmetric

Access tokens are signed using asymmetric cryptography. The API verifies every token against a public key. There is no shared secret involved in token validation. This means:
  • There is no symmetric key that could be leaked and used to forge tokens
  • Only the authorization server can issue valid tokens
  • Key rotation on the authorization server side does not require any changes to your integration
Every request to /v1/* validates the token’s presence, expiry, signature, and workspace claims before any business logic runs. A revoked token is invalidated immediately and cannot be used again, even if it has not expired yet.

The authorization_code is single-use and short-lived

Authorization codes expire in 10 minutes and can only be used once. After a successful token exchange, the code is consumed and cannot be reused.

The client_secret is never returned in any response

The client_secret is generated once and delivered exclusively via a secure link sent to the registered email address. The link expires in 15 minutes and is invalidated on first view. It is never:
  • Returned in any API response body
  • Logged by the API
  • Accessible after the initial delivery window
If the link expires before you open it, you must rotate credentials to receive a new one. See Rotate app credentials.

Credential rotation uses email, not client_secret

To rotate credentials, you send client_id and the registered email address. The client_secret is not required. This is an intentional security decision. If the client_secret is compromised, requiring it for rotation would give the attacker who already has the secret the ability to rotate and take over the app. The registered email address is never returned by any API endpoint. Only Vendaze and the legitimate owner know what it is. Even if an attacker has the client_id (which is public) and discovers the email, the new client_secret is never returned in the response: it is sent as a one-time link to that email address. Completing the rotation requires access to the registered inbox, which is outside the scope of what the API can protect.

workspace_id comes from the token, never from the request

The workspace context for every API call is extracted from the access_token claims. Your integration never sends a workspace identifier in request parameters, headers, or body. This means:
  • An integrator cannot access data from a workspace they were not authorized for, even if they know the workspace ID
  • There is no way to escalate access by manipulating request parameters
  • Multi-tenant isolation is enforced at the token level, not at the application level

Rate limiting is layered

Two independent rate limiting layers apply: Per IP (OAuth endpoints): /oauth/authorize, /oauth/token, /oauth/revoke, and /v1/auth/* are rate-limited by IP address. Per client_id (resource endpoints): all /v1/* endpoints are rate-limited by the client_id extracted from the token. Limits vary by HTTP method: 1,000 req/min for GET, 200 req/min for POST/PATCH, 100 req/min for DELETE. This layering means a compromised token has a bounded blast radius. An attacker cannot use a single token to exhaust the API for other integrators.

What this means for your integration

The security model above means your integration has a well-defined responsibility boundary: The API handles: PKCE, asymmetric token signing and verification, workspace isolation, token revocation, rate limiting, credential delivery security. You handle: storing the client_secret in a secrets manager, storing tokens encrypted server-side, validating the state parameter on the OAuth callback, revoking tokens when users disconnect, rotating credentials if compromised.

Authentication

Token storage, refresh flow, and revocation.

Register your app

Credential delivery and the 15-minute link window.

Rotate app credentials

When and how to rotate the client_secret.

Rate limits

Limits by method and endpoint type.

Incident response

If you suspect your client_secret or tokens have been compromised:
  • Revoke all active tokens via POST /oauth/revoke for each affected workspace
  • Rotate credentials immediately via POST /v1/auth/rotate-app
  • Update your secrets manager with the new client_secret
  • Contact security@vendaze.com with the request_id of any suspicious requests
  • Notify affected users that they need to re-authorize
  • Review your logs for unauthorized data access during the exposure window