Authenticate with OAuth 2.0 Authorization Code

Create a Vibe app and use the OAuth 2.0 Authorization Code flow to access a Vibe user's account.

Creating an App

  1. In the Vibe Developer tool, create an app and select OAuth as the authentication method.
  2. Register every redirect URI your app uses. Each URI must exactly match the redirect_uri in your authorization requests; register separate development and production URIs when needed.
  3. Select only the grant types and scopes your integration requires.
  4. After app creation, copy the client_id and client_secret. Store the secret only on your server; it is required for the token exchanges below.

For Marketplace requirements—including app information, required listing content, support materials, scope review, and submission—see Submit your app for review and Marketplace listing.



Base URL

All OAuth endpoints are available at:

https://api.vibe.co

💡

Developer note — Pick the right grant

For server-to-server integrations with no end user, such as cron jobs, exports, and backends, use client_credentials.

When a Vibe user is signing into your app and granting your app access to their accounts, use authorization_code.

Don't use client_credentials to act on a user's account.


Authorization Code Flow

Use this flow when your application needs access to resources owned by a specific Vibe user. The user is redirected to Vibe to authenticate and approve access, then returned to your app with an authorization code you exchange for a token.

Step 1 — Redirect the user to Vibe

Send the user to the Vibe authorization endpoint with the following query parameters:

GET https://api.vibe.co/oauth2/auth
ParameterRequiredDescription
client_idYesYour application's client ID
redirect_uriYesURL to redirect the user after authorization. Must match a registered redirect URI for your app.
response_typeYesMust be code
scopeYesSpace-separated list of scopes to request (e.g. campaigns:read)
stateYesAn opaque value you generate to prevent CSRF. You must verify this on the callback.

Example redirect URL:

https://api.vibe.co/oauth2/auth?client_id=<YOUR_CLIENT_ID>&redirect_uri=https%3A%2F%2Fyourapp.com%2Fcallback&response_type=code&scope=campaigns%3Aread&state=abc123xyz

Step 2 — Handle the callback

After the user authorizes your app, Vibe redirects them to your redirect_uri with two query parameters:

GET https://yourapp.com/callback?code=<AUTHORIZATION_CODE>&state=<YOUR_STATE>

Before proceeding, verify that state matches the value you sent in Step 1. If it does not match, reject the request.

If the user denies access or an error occurs, the redirect will include error and error_description parameters instead:

GET https://yourapp.com/callback?error=access_denied&error_description=The+user+denied+access

Step 3 — Exchange the code for a token

Make a server-side POST request to exchange the authorization code for an access token. Never make this request from client-side code, as it requires your client secret.

POST https://api.vibe.co/oauth2/token
Content-Type: application/x-www-form-urlencoded
Authorization: Basic <BASE64(YOUR_CLIENT_ID:YOUR_CLIENT_SECRET)>

grant_type=authorization_code
&code=<AUTHORIZATION_CODE>
&redirect_uri=https://yourapp.com/callback

The Authorization header value is Basic followed by the Base64 encoding of <client_id>:<client_secret>.

Example response:

{
  "access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
  "refresh_token": "ory_rt_...",
  "token_type": "Bearer",
  "expires_in": 3600
}

Store the refresh_token securely. You will use it to obtain new access tokens without requiring the user to re-authorize. The access token expires after 1 hour.

Step 4 — Call the API

Include the access token as a Bearer token in the Authorization header of every API request:

GET https://api.vibe.co/*
Authorization: Bearer <ACCESS_TOKEN>


Token Response Reference

FieldTypeDescription
access_tokenstringJWT token to use in API requests. TTL 1 hour.
refresh_tokenstringToken used to obtain a new access token. Only present in the Authorization Code flow. TTL 90 days.
token_typestringAlways Bearer
expires_inintegerAccess token lifetime in seconds

Access tokens are JWTs. You can inspect the payload by Base64-decoding the middle segment (between the two . characters). The payload contains standard claims such as sub, scope, iat, and exp. Do not rely on the token payload structure in your integration logic — use the API responses instead.

Tokens expire after the duration indicated by expires_in. Use the refresh_token from the Authorization Code flow to obtain a new access token without user interaction. The Client Credentials flow does not issue refresh tokens.


Refreshing Access Tokens

When an access token expires, use the refresh token to obtain a new one without requiring the user to re-authorize. This only applies to the Authorization Code flow — Client Credentials tokens cannot be refreshed.

POST https://api.vibe.co/oauth2/token
Content-Type: application/x-www-form-urlencoded
Authorization: Basic <BASE64(YOUR_CLIENT_ID:YOUR_CLIENT_SECRET)>

grant_type=refresh_token
&refresh_token=<YOUR_REFRESH_TOKEN>

Example response:

{
  "access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
  "refresh_token": "ory_rt_...",
  "token_type": "Bearer",
  "expires_in": 3600
}

Each refresh issues a new refresh token. Replace the stored refresh token with the one returned in the response — the previous token is invalidated.


Error Reference

Errors from the authorization endpoint and token endpoint follow OAuth 2.0 standard error codes.

⚠️

Gotcha — OAuth error envelope

400 and 401 responses from OAuth endpoints follow RFC 6749 §5.2: {'{'} "error": "invalid_grant", "error_description": "..." {'}'}.

They do not use the Vibe error envelope. Parse both shapes in code that handles OAuth and the rest of the Vibe API.

ErrorDescription
invalid_clientClient authentication failed. Check your client_id and client_secret.
invalid_grantThe authorization code is invalid, expired, or already used.
invalid_requestA required parameter is missing or malformed.
invalid_scopeOne or more of the requested scopes are invalid or not permitted for your client.
access_deniedThe user denied the authorization request.
unsupported_grant_typeThe requested grant type is not supported.

Error responses from the token endpoint are JSON:

{
  "error": "invalid_client",
  "error_description": "Client authentication failed."
}

Did this page help you?