Skip to content

Partner Authentication

Partner Authentication lets your application access the Rho API on behalf of Rho customers using OAuth 2.0.

Rho uses the standard Authorization Code flow with PKCE. The authorization server is https://auth.rho.co.

If you are building an internal integration for your own account, you don't need OAuth - use an API Access Token instead.

Getting access

OAuth clients are registered by Rho. To onboard as a partner, email the following details to api-partner-request@rho.co:

FieldNotes
Client / app nameShown to customers on the consent screen.
Company nameYour legal entity name.
LogoYour app's logo image. Shown on the consent screen.
Redirect URI(s)All URIs you need, production, development, local.
Requested scopesThe scopes your app needs, e.g. accounts:read transactions:read offline_access (see Scopes).
Privacy policy URILinked from the consent screen.
Terms of Service URILinked from the consent screen.
Support / contact emailUsed for operational and security notices about your integration.

After review, Rho registers your OAuth client and sends you your client_id and client_secret. Treat the secret like a password: store it in a secret manager and never share it with anyone.

Authorization flow

Step 1: Redirect the customer to Rho

Send the customer's browser to the Rho authorization URL:

GET https://auth.rho.co/oauth2/auth?
  response_type=code&
  client_id=<your_client_id>&
  redirect_uri=<registered_redirect_uri>&
  scope=accounts:read%20transactions:read%20offline_access&
  state=<opaque_state>&
  code_challenge=<pkce_challenge>&
  code_challenge_method=S256&
  audience=https%3A%2F%2Frhoapi.rho.co
  • response_type - always code.
  • client_id - issued during onboarding.
  • redirect_uri - must exactly match a registered redirect URI.
  • scope - space-separated subset of your registered scopes. Include offline_access if you need refresh tokens.
  • state - an opaque value your app verifies on the redirect back.
  • code_challenge, code_challenge_method - required. PKCE with S256.
  • audience - the Rho API your app will call: https://rhoapi.rho.co.

Step 2: The customer approves your app

The customer signs in to Rho, selects the business they want to connect, and grants the requested access on the consent screen. Only Account Owners and Admins can perform this action.

A business can have at most one active grant per app - approving again updates the existing connection.

Step 3: Receive the authorization code

After approval, the customer's browser is redirected to your redirect_uri with an authorization code:

https://yourapp.example.com/callback?code=<authorization_code>&state=<opaque_state>

Verify that state matches the value you sent. Authorization codes are single-use and expire after a few minutes.

If the customer declines, or has no business where they are allowed to approve integrations, the redirect carries error=access_denied instead of a code.

Step 4: Exchange the code for tokens

Exchange the authorization code at the token endpoint:

POST /oauth2/token HTTP/1.1
Host: auth.rho.co
Content-Type: application/x-www-form-urlencoded
Authorization: Basic <base64(client_id:client_secret)>

grant_type=authorization_code&
code=<authorization_code>&
redirect_uri=<registered_redirect_uri>&
code_verifier=<pkce_verifier>

The response contains a bearer access token and, if offline_access was granted, a refresh token:

{
  "access_token": "<access_token>",
  "token_type": "bearer",
  "expires_in": 900,
  "refresh_token": "<refresh_token>",
  "scope": "accounts:read transactions:read offline_access"
}

Step 5: Call the API

Send the access token in the standard HTTP Authorization header using the Bearer scheme:

curl https://rhoapi.rho.co/api/v1/transactions \
  -H "Authorization: Bearer $ACCESS_TOKEN"

Step 6: Refresh tokens

When the access token expires, use the refresh token to get a new one:

POST /oauth2/token HTTP/1.1
Host: auth.rho.co
Content-Type: application/x-www-form-urlencoded

grant_type=refresh_token&
refresh_token=<refresh_token>

Refresh tokens are single-use and rotate on every refresh: each response includes a new refresh token, and the old one stops working. Persist the new token immediately.

Access tokens expire after 15 minutes. Refresh tokens last 30 days on a rolling basis - each refresh starts a new 30-day window. The grant itself lasts 1 year; after that the customer must re-approve your app.

All auth.rho.co endpoint URLs are also published at https://auth.rho.co/.well-known/openid-configuration for OAuth libraries that support discovery.

Revoking access

Your app can revoke its own tokens at any time:

POST /oauth2/revoke HTTP/1.1
Host: auth.rho.co
Content-Type: application/x-www-form-urlencoded

token=<access_or_refresh_token>&
client_id=<your_client_id>&
client_secret=<your_client_secret>

Customers can also disconnect your app from their Rho business settings. Customer revocation is immediate and invalidates all tokens for the grant, including refresh tokens - your next API request returns 401 Unauthorized. Handle this gracefully by sending the customer through the authorization flow again.