Build a Connect with Rivo integration with OAuth apps
This guide is for app developers building integrations with Rivo.
If you are a merchant connecting an existing app, use that app's setup flow instead.
What OAuth apps are for
OAuth apps let you add a Connect with Rivo flow to your app so merchants can authorize access without sharing API keys.
With OAuth, your app gets:
Merchant-approved access tokens
Scope-based permissions
Refresh tokens for long-lived connections
Standard authorization code flow with PKCE support
Create your OAuth app in Rivo
Open the OAuth Applications dashboard in your Rivo admin:
Then:
Click New Application.
Fill in:
Name: shown to merchants on the consent screen
Redirect URI: one or more callback URLs (space-separated)
Confidential: enable for server-side apps that can securely store a client secret
Scopes: space-separated scopes your app needs
Save the app.
After creation, copy and store:
Client ID (
uid)Client Secret (store securely)
The app details page also shows Authorize → test links for each redirect URI.
OAuth endpoints
Use these endpoints:
Authorize:
GET /api/oauth/v1/oauth/authorizeToken:
POST /api/oauth/v1/oauth/tokenRevoke:
POST /api/oauth/v1/oauth/revokeIntrospect:
POST /api/oauth/v1/oauth/introspect
Application management in the dashboard uses:
GET /developer/oauth/applications
Supported scopes
Rivo supports these configured scopes:
identity_basic_read: basic read access for identity/shop dataidentity_basic_write: basic write access for identity/shop datamcp_read: read access used for MCP toolingdeveloper_api: access for developer API usage
Request only the minimum scopes your integration needs.
Authorization code flow (recommended with PKCE)
Redirect the merchant to the authorize endpoint with:
client_idredirect_uriresponse_type=codescopestatecode_challengeandcode_challenge_method=S256(recommended)
Merchant approves access.
Rivo redirects to your
redirect_uriwith:codestate
Exchange the code at the token endpoint.
Call Rivo APIs with
Authorization: Bearer <access_token>.
Why state and PKCE matter
stateprotects against request forgery and lets you match responses to requests.PKCE protects the authorization code exchange from interception.
Minimal Node.js example
import crypto from "node:crypto";import express from "express";import fetch from "node-fetch";const app = express();const RIVO_BASE = "https://your-rivo-host";const CLIENT_ID = process.env.RIVO_CLIENT_ID;const CLIENT_SECRET = process.env.RIVO_CLIENT_SECRET;const REDIRECT_URI = "https://your-app.com/oauth/rivo/callback";const stateStore = new Map();function base64url(buffer) { return buffer.toString("base64").replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/g, "");}app.get("/oauth/rivo/start", (req, res) => { const state = crypto.randomBytes(16).toString("hex"); const codeVerifier = base64url(crypto.randomBytes(32)); const codeChallenge = base64url(crypto.createHash("sha256").update(codeVerifier).digest()); stateStore.set(state, { codeVerifier, createdAt: Date.now() }); const params = new URLSearchParams({ client_id: CLIENT_ID, redirect_uri: REDIRECT_URI, response_type: "code", scope: "identity_basic_read", state, code_challenge: codeChallenge, code_challenge_method: "S256" }); res.redirect(`${RIVO_BASE}/api/oauth/v1/oauth/authorize?${params.toString()}`);});app.get("/oauth/rivo/callback", async (req, res) => { const { code, state } = req.query; const session = stateStore.get(state); if (!code || !state || !session) { return res.status(400).send("Invalid OAuth callback"); } const tokenRes = await fetch(`${RIVO_BASE}/api/oauth/v1/oauth/token`, { method: "POST", headers: { "Content-Type": "application/x-www-form-urlencoded" }, body: new URLSearchParams({ grant_type: "authorization_code", client_id: CLIENT_ID, client_secret: CLIENT_SECRET, redirect_uri: REDIRECT_URI, code: String(code), code_verifier: session.codeVerifier }) }); const token = await tokenRes.json(); // token includes access_token, refresh_token (if issued), token_type, scope, expires_in // Store token securely per merchant, then call Rivo APIs with Bearer access_token. res.json(token);});
Token refresh and revocation
Store token response values securely per merchant account.
Use
expires_infrom the token response to track access token expiry.Use the refresh token flow when your stored access token expires.
Revoke tokens with
POST /api/oauth/v1/oauth/revokewhen disconnecting a merchant.
OAuth vs API keys
Use OAuth apps when:
You are building a multi-merchant SaaS integration
You need a self-serve Connect button
You need merchant-level consent and revocation
Use API keys when:
You are building internal tooling for a single merchant
The merchant manages credentials directly
Related guides:
