Clio Developer Documentation
Technical reference for the CaseHug–Clio Manage integration. API endpoints, data models, webhooks, and authentication flow.
Authentication Flow
CaseHug uses OAuth 2.0 Authorization Code flow to connect to Clio Manage.
┌──────────┐ ┌──────────┐ ┌──────────┐
│ Browser │ │ CaseHug │ │ Clio │
└────┬─────┘ └────┬─────┘ └────┬─────┘
│ │ │
│ 1. Click │ │
│ "Connect" │ │
│───────────────►│ │
│ │ │
│ 2. Generate │ │
│ CSRF state │ │
│ │ │
│ 3. Redirect │ │
│◄───────────────│ │
│ │ │
│ 4. Authorize ──────────────────►│
│ │ │
│ 5. Redirect with code ◄─────────│
│───────────────►│ │
│ │ │
│ │ 6. Exchange │
│ │ code for token │
│ │───────────────►│
│ │ │
│ │ 7. Token │
│ │◄───────────────│
│ │ │
│ │ 8. Store token │
│ │ in DB │
│ │ │
│ 9. Redirect to │ │
│ dashboard │ │
│◄───────────────│ │
│ │ │Authorize URL: https://app.clio.com/oauth/authorize
Token URL: https://app.clio.com/oauth/token
Redirect URI: https://calmintake.com/api/v1/integrations/clio/callback
Scopes: matters:read matters:write contacts:read contacts:write documents:read documents:write
Token refresh: Automatic, 5 minutes before expiration. Uses refresh_token grant.
API Endpoints
/api/v1/integrations/clio/connectInitiates OAuth flow. Generates CSRF state, stores in DB, redirects to Clio authorize URL.
302 Redirect to Clio/api/v1/integrations/clio/callbackOAuth callback. Validates CSRF state, exchanges authorization code for tokens, stores in firm_integrations, redirects to dashboard.
302 Redirect to dashboard/api/v1/integrations/clio/disconnectRevokes Clio OAuth access, removes tokens from DB, deactivates integration.
{ "success": true }/api/v1/integrations/clio/statusReturns connection status, Clio user info, last sync time, and sync settings.
{ "connected": true, "clio_user": {...}, "last_sync": {...} }/api/v1/integrations/clio/syncSync a specific matter to Clio. Body: { "matter_id": "uuid", "action": "sync_matter" | "pull_matters" }
{ "success": true, "clioMatterId": 12345, "documentsUploaded": 3 }/api/v1/integrations/clio/syncGet sync history for the firm (last 50 syncs). Optional query: ?matter_id=uuid
{ "logs": [...] }/api/v1/integrations/clio/webhooksReceives Clio webhook events. Handles X-Hook-Secret handshake and processes matter/contact/document events.
{ "received": true }/api/v1/integrations/clio/deauthorizeClio deauthorization callback. Called by Clio when a user revokes access from Clio settings.
{ "ok": true }Data Models
firm_integrations
Stores OAuth tokens and integration settings per firm
| Column | Type | Description |
|---|---|---|
| id | UUID | Primary key |
| firm_id | UUID | References firms(id) |
| platform | TEXT | 'clio' | 'smokeball' | 'mycase' | 'lawmatics' |
| access_token | TEXT | Clio OAuth access token (encrypted at rest) |
| refresh_token | TEXT | Clio OAuth refresh token |
| token_expires_at | TIMESTAMPTZ | Token expiration time |
| settings | JSONB | Integration settings (auto_sync, mappings) |
| webhook_secret | TEXT | Secret for verifying Clio webhooks |
| is_active | BOOLEAN | Whether integration is active |
| last_sync_at | TIMESTAMPTZ | Last successful sync timestamp |
| sync_status | TEXT | 'idle' | 'syncing' | 'error' |
integration_sync_logs
Audit log of all sync operations
| Column | Type | Description |
|---|---|---|
| id | UUID | Primary key |
| firm_id | UUID | References firms(id) |
| integration_id | UUID | References firm_integrations(id) |
| matter_id | UUID | CaseHug matter (nullable) |
| upload_id | UUID | CaseHug upload (nullable) |
| action | TEXT | 'sync_matter' | 'sync_document' | 'pull_matters' |
| status | TEXT | 'pending' | 'success' | 'failed' | 'skipped' |
| external_id | TEXT | Clio resource ID |
| error_message | TEXT | Error details (nullable) |
| details | JSONB | Additional metadata |
clio_webhook_events
Raw webhook events from Clio for audit trail
| Column | Type | Description |
|---|---|---|
| id | UUID | Primary key |
| firm_id | UUID | Matched firm (nullable) |
| event_type | TEXT | 'matter.update' | 'contact.update' | etc. |
| resource_type | TEXT | 'matter' | 'contact' | 'document' |
| resource_id | BIGINT | Clio resource ID |
| payload | JSONB | Raw webhook payload |
| processed | BOOLEAN | Whether event has been processed |
| error_message | TEXT | Processing error (nullable) |
Webhook Events
Webhook endpoint: POST https://calmintake.com/api/v1/integrations/clio/webhooks
Registration: Clio sends X-Hook-Secret header on first request. CaseHug echoes it back to confirm.
| Event | Description | CaseHug Action |
|---|---|---|
| matter.create | New matter created in Clio | Logged; no CaseHug action (Clio-origin matters not auto-imported) |
| matter.update | Matter updated in Clio | If matter is linked in CaseHug, status is updated (Open→active, Closed→closed) |
| contact.create | New contact created in Clio | Logged for audit |
| contact.update | Contact updated in Clio | Logged; future: update linked CaseHug client |
| document.create | Document uploaded to Clio | Logged for audit |
Field Mapping Schema
CaseHug maps its case types to Clio practice areas. Default mappings are built-in; firms can override via integration settings.
// firm_integrations.settings schema
{
"auto_sync_on_approval": true,
"auto_sync_on_matter_created": false,
"case_type_mappings": {
"divorce_standard": "Family Law",
"custody_only": "Family Law",
"immigration_asylum": "Immigration",
"personal_injury_auto": "Personal Injury",
"estate_planning_will": "Estate Planning"
// ... override any CaseHug case type → Clio practice area name
}
}Sync Data Mapping
| CaseHug Field | Clio Field | Notes |
|---|---|---|
| client.first_name | contact.first_name | Person type contact |
| client.last_name | contact.last_name | |
| client.email | contact.email_addresses[0] | Name: "Work" |
| client.phone | contact.phone_numbers[0] | Name: "Mobile" |
| matter.title | matter.description | |
| matter.case_number | matter.custom_number | |
| matter.case_type | matter.practice_area | Via mapping table |
| upload.file | document → matter | Uploaded to Clio matter |
Error Codes
| Code | Meaning | Resolution |
|---|---|---|
| 401 | Unauthorized — access token expired or revoked | CaseHug auto-refreshes tokens. If persistent, disconnect and reconnect Clio. |
| 403 | Forbidden — insufficient Clio permissions | Reconnect Clio with a user that has matters/contacts/documents permissions. |
| 404 | Resource not found — Clio matter or contact deleted | The linked Clio resource was deleted. Sync again to create a new one. |
| 422 | Validation error — invalid data sent to Clio | Check sync log details for the specific validation error from Clio. |
| 429 | Rate limited — too many API requests | CaseHug implements exponential backoff. Wait a few minutes and retry. |
| 500/503 | Clio server error or maintenance | Retry after Clio resolves the issue. Check status.clio.com. |
Rate Limits
Clio enforces rate limits via HTTP headers. CaseHug respects these automatically.
Headers: X-RateLimit-Limit, X-RateLimit-Remaining, Retry-After
Strategy: Sequential sync per matter. One matter at a time. Document uploads are serialized.
Backoff: On 429 response, CaseHug waits the Retry-After duration, then retries up to 3 times.
Pagination: List endpoints use limit=200 (Clio max per page) with offset-based pagination.
Need Technical Help?
Reach out to our engineering team for integration support.
