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
- In the Vibe Developer tool, create an app and select OAuth as the authentication method.
- Register every redirect URI your app uses. Each URI must exactly match the
redirect_uriin your authorization requests; register separate development and production URIs when needed. - Select only the grant types and scopes your integration requires.
- After app creation, copy the
client_idandclient_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_credentialsto 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
| Parameter | Required | Description |
|---|---|---|
client_id | Yes | Your application's client ID |
redirect_uri | Yes | URL to redirect the user after authorization. Must match a registered redirect URI for your app. |
response_type | Yes | Must be code |
scope | Yes | Space-separated list of scopes to request (e.g. campaigns:read) |
state | Yes | An 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
| Field | Type | Description |
|---|---|---|
access_token | string | JWT token to use in API requests. TTL 1 hour. |
refresh_token | string | Token used to obtain a new access token. Only present in the Authorization Code flow. TTL 90 days. |
token_type | string | Always Bearer |
expires_in | integer | Access 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
400and401responses 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.
| Error | Description |
|---|---|
invalid_client | Client authentication failed. Check your client_id and client_secret. |
invalid_grant | The authorization code is invalid, expired, or already used. |
invalid_request | A required parameter is missing or malformed. |
invalid_scope | One or more of the requested scopes are invalid or not permitted for your client. |
access_denied | The user denied the authorization request. |
unsupported_grant_type | The requested grant type is not supported. |
Error responses from the token endpoint are JSON:
{
"error": "invalid_client",
"error_description": "Client authentication failed."
}Updated 20 days ago