Skip to content

feat(clio): support regional OAuth hosts and credentials - #103

Open
roboli wants to merge 1 commit into
nextfrom
feat/clio-regional-oauth
Open

roboli wants to merge 1 commit into
nextfrom
feat/clio-regional-oauth

Conversation

@roboli

@roboli roboli commented Oct 6, 2026 •

Copy link
Copy Markdown

Why

Clio runs each region (US, EU, CA, AU) as a separate instance. Per Clio's docs, each region needs its own developer application (different client ID/secret), and "a token issued in one region is not valid against another region's API" (Regions, Applications).

The module hardcoded OAuth to app.clio.com with the US app's credentials and ignored the region sent at authorization time, so non-US accounts couldn't connect. Quo is adding a "Clio (Canada)" app that sends { entityType: "clio", data: { code, region: "ca" } }.

What changed

  • api.ts: one host per region; setRegion() now switches the API base URL, OAuth authorize/token URLs and client credentials together. The constructor goes through setRegion(), so an entity persisted with region: "ca" loads (and refreshes tokens) against ca.app.clio.com.
  • definition.ts: getToken honours params.region before exchanging the code. New CLIO_{EU,CA,AU}_CLIENT_ID / CLIO_{EU,CA,AU}_CLIENT_SECRET env vars, passed to the Api as regional_credentials. A region without its own credentials falls back to CLIO_CLIENT_ID/CLIO_CLIENT_SECRET.
  • A persisted region of null or '' is treated as us (core's get() only defaults on undefined).
  • First unit tests for the package (test/regions.test.ts, 10 tests): US default, persisted region, credential fallback, switching back to US, invalid region, code exchange with/without region, token refresh in the persisted region. The 4 region tests fail against the previous code.

Compatibility

US behaviour is unchanged: same URLs, same CLIO_CLIENT_ID/SECRET, no new env vars required. Checked the consuming app's data read-only: all Clio entities in dev (4) and prod (171) are persisted with region: "us".

Testing

  • npx tsc -p tsconfig.json and npx vitest run in packages/v1-ready/clio (10/10).
  • Live test against a Clio Canada trial account will run against this PR's canary build. Note: Clio doesn't document the Manage OAuth host for non-US regions explicitly; ca.app.clio.com/oauth/* follows from the API host and will be confirmed by that test.

🤖 Generated with Claude Code

📦 Published PR as canary version: Canary Versions

✨ Test out this PR locally via:

npm install @friggframework/api-module-clio@1.1.0-canary.103.daa1c68.0
# or 
yarn add @friggframework/api-module-clio@1.1.0-canary.103.daa1c68.0

Each Clio region is a separate instance with its own OAuth server and
developer app, and tokens are not valid across regions. The module sent
every OAuth exchange to app.clio.com with the US app's credentials, so
non-US accounts could not connect.

- setRegion() now switches the API base URL, OAuth authorize/token URLs
  and client credentials together; the constructor goes through it
- getToken honours params.region so the code is exchanged in the region
  that issued it (Quo sends { code, region: "ca" })
- new CLIO_{EU,CA,AU}_CLIENT_ID/SECRET env vars; a region without its
  own credentials falls back to CLIO_CLIENT_ID/SECRET
- a saved region of null or '' is treated as US
- first unit tests for the package (region routing, exchange, refresh)

US behaviour is unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@roboli roboli added prerelease This change is available in a prerelease. release labels Oct 6, 2026
@roboli

roboli commented Oct 7, 2026

Copy link
Copy Markdown
Author

Live test against a Clio Canada account

Tested 1.1.0-canary.103.daa1c68.0 from a consuming Frigg app (local stack), against a Clio Manage trial account hosted at ca.app.clio.com, with a developer app registered in that account's region.

Check Result
Authorize with { code, region: "ca" }: code exchanged at https://ca.app.clio.com/oauth/token using the CA app's credentials ✅ entity persisted with region: "ca"
who_am_i / API calls against https://ca.app.clio.com/api/v4 ✅
Webhook + custom action created in the CA instance ✅
Contacts read from the CA instance ✅
Inbound and outbound call communications written to the CA instance ✅
Forced token refresh (access token invalidated): refresh sent to the CA token endpoint, request retried ✅ new token persisted, call logged

This also confirms the OAuth host for Clio Manage in Canada is ca.app.clio.com/oauth/*. The docs only list regional OAuth hosts for Clio Platform.

Credential probes with a dummy code back up the per-region setup: the CA app's credentials return invalid_grant (accepted) at ca.app.clio.com and invalid_client at app.clio.com, and a US app's credentials do the reverse. So both the token host and the client credentials have to follow the region, which is what this PR does.

US behaviour unchanged: default region, same URLs, same CLIO_CLIENT_ID/CLIO_CLIENT_SECRET.

🤖 Generated with Claude Code

@roboli
roboli requested a review from d-klotz October 7, 2026 01:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

prerelease This change is available in a prerelease. release

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants