Skip to main content

Build a Connect with Rivo integration with OAuth apps

Create an OAuth app and implement a secure Connect with Rivo flow for your integration.

Written by Stuart Chaney

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

  1. In Rivo admin, go to Settings.

  2. Open OAuth Applications.

  3. Click New Application.

  4. Fill in:

    • Name: shown to merchants on the consent screen

    • Redirect URI: one or more callback URLs (one URI per line)

    • Confidential: enable for server-side apps that can securely store a client secret

  5. Save the app.

After creation, copy and store:

  • Client ID

  • Client Secret (store securely)

The app details page also shows Authorize → test links for each redirect URI.




OAuth endpoints

Production OAuth base URL: https://developer-api.rivo.io

Use these endpoints:

For OAuth discovery (RFC 8414), use:

OAuth apps created in this flow use the developer_api scope.




Authorization code flow (recommended with PKCE)

  1. Redirect the merchant to the authorize endpoint with:

    • client_id

    • redirect_uri

    • response_type=code

    • scope

    • state

    • code_challenge and code_challenge_method=S256 (recommended)

  2. Merchant approves access.

  3. Rivo redirects to your redirect_uri with:

    • code

    • state

  4. Exchange the code at the token endpoint.

  5. Call Rivo APIs with Authorization: Bearer <access_token>.


Why state and PKCE matter

  • state protects against request forgery and lets you match responses to requests.

  • PKCE protects the authorization code exchange from interception.




Minimal Node.js example

This example is for a confidential app (server-side) and includes client_secret in the token exchange.

import crypto from "node:crypto";import express from "express";import fetch from "node-fetch";const app = express();const RIVO_BASE = process.env.RIVO_BASE || "https://developer-api.rivo.io";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: "developer_api",    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_in from 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/revoke when 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:

Did this answer your question?