Skip to main content
Connecting a provider account takes three steps:
  1. Create a pending connection and get a one-time connect_url
  2. Send the user to it—they consent at the provider
  3. Handle the return at your own URL, which now carries the connection id
Your server never sees an authorization code, an access token, or a refresh token.

Step 1: Create the connection

Endpoint
cURL
Response
The connection exists immediately with status pending. It becomes healthy only after the user finishes consent.

return_url rules

The URL is validated when you create the connection, not when the user comes back. A URL that fails these checks returns 400.
  • It must be absolute.
  • It must use https. localhost and 127.0.0.1 over http are accepted outside production.
  • It must not embed credentials (no user:password@host).
Case.dev appends a query parameter to whatever you supply, preserving your existing ones.
Treat return_url as a redirect target you own. Do not build it from unvalidated user input, and do not point it at a URL that forwards onward using a parameter an attacker controls.

Scope tiers

scope_tier selects a provider permission level. Both current providers expose a single tier (clio.us, drive), so omit the field and you get it by default. The tier is signed into the connect_url, so a user cannot broaden their own consent by editing the query string before they click through.

Step 2: Send the user to connect_url

Redirect the browser to connect_url. Case.dev builds the provider authorization URL, attaches HMAC-signed state and a PKCE challenge, and forwards the user to the provider’s consent screen.
connect_url is one-time and expires in 10 minutes. An expired link returns 410; a link that has already been used returns 404. Generate it when the user is about to click, not when the page loads.

Step 3: Handle the return

After consent, the provider redirects to Case.dev, which exchanges the code, stores the encrypted tokens, and sends the user to your return_url.
Success
Failure
Branch on which parameter is present. On success, confirm the connection is usable before you show it as connected:
cURL
Response
Do not trust connection_id from the query string on its own. Anyone can type it. Fetch the connection server-side with your API key and confirm it belongs to the tenant whose session you are serving.

Connection statuses

Subscribe to connection.reauth_required and connection.revoked instead of polling.

Reconnecting

Reconnection is the same flow. Create a new connection for the same provider and account, and send the user through connect_url again. When the account matches an existing connection, the callback returns you to return_url carrying that existing connection_id—so links built on it keep working, with their ledgers and cursors intact. This is what you should offer when a connection goes reauth_required. Nothing re-imports.

Disconnecting

Endpoint
cURL
Tokens are revoked at the provider and deleted. Documents already imported into vaults stay where they are. To remove those documents too, add ?purge=true. The purge runs as a durable background workflow and returns 202 rather than 204.
purge=true deletes vault documents that this connection’s import links brought in. It is not reversible—confirm with the user before you call it.

Turning a provider off without disconnecting

Endpoint
This stops new runs and scheduled syncs for one provider across the whole organization or installation. Credentials, links, and imported files are preserved, and runs already in flight are not interrupted. Because it is organization-wide, the body must include confirm_organization_wide: true.

Next steps

Import & Export

Browse the connected account and move files into a vault

Installations

Scope connections per customer tenant

Errors & Recovery

What each failure code means and which ones to retry