Authentication
API keys and sign-in (OAuth) access tokens, choose access for your integration.
Every request to https://api.vyg.app needs a credential in the Authorization header, except these
public discovery routes, which you call without one:
GET /healthGET /v1/openapi.json, the OpenAPI documentGET /.well-known/oauth-protected-resource, the metadata an OAuth client reads before it has a token
For everything else, send:
Authorization: Bearer <credential>The same credentials work on the REST API (/v1) and on the MCP server (/mcp). There are two kinds.
| Credential | Looks like | Who gets it | Brand |
|---|---|---|---|
| API key | vyg_… or vyg_ba_… | Created by a brand admin, for server-to-server use. | Fixed to the brand that created it. |
| Sign-in (OAuth) access token | A JWT issued for https://api.vyg.app | A person who signs in with their VYG account and picks a brand. | The brand picked at sign-in. |
API keys
An API key carries the scopes chosen when it is created. New vyg_… keys support
VYG read access. Existing vyg_ba_… keys support conversations, contacts and providers. See
API keys for how to create, rotate and revoke them, and
Scopes for available permissions.
curl -sS https://api.vyg.app/v1/customers \
-H "Authorization: Bearer $VYG_API_KEY"Sign-in (OAuth) access tokens
A sign-in token represents a person. MCP clients get one for you: the first time the client calls a VYG tool, a browser opens, you sign in to VYG, pick a brand and approve the requested access. Your password is entered on the VYG sign-in page only and is never passed to the client.
The flow is standard OAuth 2.1 with PKCE:
- The API publishes its protected-resource metadata at
https://api.vyg.app/.well-known/oauth-protected-resource. It names the authorization server (https://vyg.app) and the scopes a client may request. - A
401from/mcpcarries aWWW-Authenticateheader that points to that metadata. - Access tokens are short-lived. Clients refresh them with a refresh token, so you do not sign in again during normal use.
- The token carries the brand you picked. To work with another brand, disconnect and sign in again.
Requested scopes
A client that asks for no scope, or for mcp:tools, is granted every non-admin scope that an MCP tool
uses. mcp:read narrows that to the :read scopes and mcp:write to the :write scopes. A client can
also ask for individual scopes such as customers:read. Admin scopes (keys:manage, *:admin) are
granted only when the person signing in is a brand admin. See
Scopes.
Operations that need a sign-in
Some operations require a sign-in token. They answer 403 with
insufficient_scope when called with a key. This covers:
- the Shopify and Klaviyo tools, and key management (
keys:manage); - operations that make changes to campaigns, message variants, discounts and segments, which require an OAuth connection.
The REST reference marks each of these operations with "Requires sign-in (OAuth)", and the tool catalog marks the tools.
Failures
| Status | error.code | Cause |
|---|---|---|
401 | unauthorized | No Authorization header, a malformed one, or an unknown, revoked or expired credential. |
401 | legacy_credential_not_supported | A vyg_live_ credential. These are not accepted; create a vyg_ba_ key instead. |
403 | insufficient_scope | The credential is valid but lacks a scope the operation needs, or the operation needs a sign-in. |
503 | unavailable | The credential could not be checked just now. Retry; the credential may be fine. |
Do not retry a 401 or 403 unchanged. Check the credential and required permissions.