en
How-to guidesBuild a multi-tenant integration with OAuth 2.1

Build a multi-tenant integration with OAuth 2.1

Let your users connect their own Crisphive business to your product — OAuth 2.1 with a consent screen, no API key ever copied.

API keys authenticate your own business. When you build a product that other Crisphive businesses plug into — a CRM sync, a booking widget, an AI-agent connector — use the built-in OAuth 2.1 Authorization Server instead: each business owner approves your app on a consent screen, and your app receives tokens bound to their tenant.

OAuth access tokens work against both surfaces — the REST /v1 API and the /mcp endpoint. Send Authorization: Bearer <access_token> exactly like an API key.

The flow

The server implements the current OAuth 2.1 draft: PKCE (S256) is required, clients are public (no secret), and registration is dynamic — no manual app-review step:

StepRequest
1. Discover the ASGET /.well-known/oauth-authorization-server (RFC 8414) → endpoint URLs, supported grants
2. RegisterPOST /oauth/register (RFC 7591 Dynamic Client Registration) → client_id
3. AuthorizeGET /oauth/authorize?… — the business owner signs in to Crisphive and consents
4. ExchangePOST /oauth/token (grant_type=authorization_code, code, code_verifier) → { access_token, refresh_token, expires_in }
5. RefreshPOST /oauth/token (grant_type=refresh_token) → a rotated token pair (the old refresh token is single-use)

Tokens

The token is bound to the consenting owner’s business, region, and environment — it can never reach another tenant or flip live↔sandbox. Request a narrower scope (space-separated permission codes, e.g. customers_view job_requests_view) to limit access; omit it for full business access. Access tokens live ~1 hour; refresh with the single-use refresh token to stay connected.

Connection lifetime

A connection is governed by two independent clocks. An integration in daily use is never disconnected on a schedule; one that is forgotten expires on its own.

  • Idle window — 30 days. Every token refresh issues a new refresh token good for another 30 days. Keep using the connection and it rolls forward indefinitely; go quiet for 30 days and it lapses.
  • Absolute cap — 90 days. Regardless of activity, a connection ends 90 days after the business owner approved it. The business can set this to anything from 1 to 365 days per connection under Developers → MCP connections; the countdown is measured from the original approval, not from the change.

When either clock runs out, refreshing fails (OAUTH_GRANT_EXPIRED) and the owner must approve the app again from the consent screen. Treat any failed refresh as “restart the authorization flow”, never as a retryable error. The business’s Owners and Administrators are emailed 14 days before a connection expires — re-approving needs the owner in a browser, so the warning comes earlier than for keys.

Refresh tokens are single-use: each refresh returns a new one, and presenting an already-used token revokes the entire connection as suspected token theft. Always store only the newest refresh token you received.

Calling the API

curl "https://api.crisphive.com/v1/customers" \
  -H "Authorization: Bearer <access_token>"

Building an AI-agent connector instead? The MCP server uses this exact flow — compliant MCP clients run it automatically, so you normally write no OAuth code at all.