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.
OAuth clients are registered by Rho. To onboard as a partner, email the following details to api-partner-request@rho.co:
| Field | Notes |
|---|---|
| Client / app name | Shown to customers on the consent screen. |
| Company name | Your legal entity name. |
| Logo | Your app's logo image. Shown on the consent screen. |
| Redirect URI(s) | All URIs you need, production, development, local. |
| Requested scopes | The scopes your app needs, e.g. accounts:read transactions:read offline_access (see Scopes). |
| Privacy policy URI | Linked from the consent screen. |
| Terms of Service URI | Linked from the consent screen. |
| Support / contact email | Used 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.
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.coresponse_type- alwayscode.client_id- issued during onboarding.redirect_uri- must exactly match a registered redirect URI.scope- space-separated subset of your registered scopes. Includeoffline_accessif you need refresh tokens.state- an opaque value your app verifies on the redirect back.code_challenge,code_challenge_method- required. PKCE withS256.audience- the Rho API your app will call:https://rhoapi.rho.co.
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.
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.
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"
}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"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.
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.