Developers

Authentication

Vestoris is its own OAuth 2.0 authorization server (RFC 6749). Its metadata is at https://vestoris.com/.well-known/oauth-authorization-server (RFC 8414). Every request is over HTTPS; the API sends HSTS, takes no cookies (a request with only the site's session cookie is refused with session_not_accepted) and needs no CSRF token: the bearer token is the credential.

GrantForActs as
Client credentialsA system (nightly jobs, integrations)The client's service account
Authorization code with PKCEAn app used by peopleThe person who signed in and consented
Personal access tokenYour own scriptsYou

Access tokens are opaque (vat_...), last one hour (or less, as the Admin sets), and are stored only as keyed hashes. Never put a token in a URL: Vestoris reads them only from the Authorization header.

Client credentials (service accounts)

An Admin creates a service account client on API clients and webhooks: a name, a role (its privileges), the scopes, and optionally an IP allow-list (CIDR). The client secret (vcs_...) is shown once.

curl -X POST https://vestoris.com/oauth/token \
  -u "$VESTORIS_CLIENT_ID:$VESTORIS_CLIENT_SECRET" \
  -d grant_type=client_credentials -d "scope=orders:read market:read"
{"access_token":"vat_...","token_type":"Bearer","expires_in":3600,"scope":"orders:read market:read"}

The secret can also be sent in the form (client_secret_post). Rotation: "Rotate secret" issues a new one; the old one keeps working for the overlap you choose (up to 7 days), so you can deploy without downtime.

private_key_jwt (RFC 7523): register your public key (RSA 2048+ or EC P-256) instead of using a secret, and authenticate with a signed assertion (iss and sub = your client_id, aud = the token endpoint URL, a unique jti, exp within 5 minutes):

curl -X POST https://vestoris.com/oauth/token \
  -d grant_type=client_credentials \
  -d client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer \
  -d "client_assertion=$SIGNED_JWT"

A service account can never sign off compliance or workflow rules, and it can approve orders and overrides only if an Admin ticked "may approve" (with a warning); four eyes still applies.

Authorization code with PKCE (apps for people)

An Admin registers an app with its exact HTTPS redirect URIs (no wildcards). PKCE with S256 is required.

  1. Make a random code_verifier and its code_challenge = BASE64URL(SHA-256(verifier)).
  2. Send the person to the consent screen:
https://vestoris.com/oauth/authorize?response_type=code&client_id=vc_...&redirect_uri=https%3A%2F%2Fapp.example.com%2Fcallback&scope=portfolio%3Aread%20orders%3Aread&state=xyz&code_challenge=...&code_challenge_method=S256
  1. The person signs in and sees what the app asks for. They grant only scopes their role and privileges can use: the token gets the intersection of the app's scopes and their entitlements. Vestoris returns them to your redirect URI with code and state.
  2. Exchange the code (once, within 10 minutes):
curl -X POST https://vestoris.com/oauth/token -u "$VESTORIS_CLIENT_ID:$VESTORIS_CLIENT_SECRET" \
  -d grant_type=authorization_code -d "code=$CODE" -d "code_verifier=$VERIFIER" \
  -d redirect_uri=https://app.example.com/callback

You get an access token and a refresh token (vrt_...). Refresh tokens rotate: each refresh returns a new one and the old one stops working. Using an old refresh token again is treated as theft: every token of that sign-in is revoked.

curl -X POST https://vestoris.com/oauth/token -u "$VESTORIS_CLIENT_ID:$VESTORIS_CLIENT_SECRET" \
  -d grant_type=refresh_token -d "refresh_token=$REFRESH_TOKEN"

People see and withdraw the apps they authorized on My API access; withdrawing revokes the app's tokens at once.

Personal access tokens

On My API access, choose a name, the scopes (only those your role can use) and an expiry (up to a year). The token (vpt_...) is shown once and acts as you.

Introspection and revocation

# RFC 7662: is this token active, and for what?
curl -X POST https://vestoris.com/oauth/introspect -u "$VESTORIS_CLIENT_ID:$VESTORIS_CLIENT_SECRET" -d "token=$TOKEN"
# RFC 7009: revoke an access or refresh token (a refresh token revokes its whole chain)
curl -X POST https://vestoris.com/oauth/revoke -u "$VESTORIS_CLIENT_ID:$VESTORIS_CLIENT_SECRET" -d "token=$TOKEN"

The token endpoint takes POST only; a GET is refused (credentials never travel in URLs).

API referenceAll developer pages