Universal API Guide

One endpoint, every platform β€” fan-out reads, normalized schema, targeted writes

🌐 Clio · Lawmatics · Filevine · Lead Docket
πŸ“‹

What is the Universal API?

The Universal API is a single normalized interface that sits on top of all connected legal platforms. Instead of calling Clio's /api/v4/contacts, Filevine's /api/core/persons, and Lead Docket's /api/contacts separately, you call one endpoint: /api/v1/universal/contacts β€” and LawLink routes, normalizes, and aggregates everything for you.

πŸ”€ Fan-out Reads (GET)

Omit platform_id on any GET β†’ LawLink fires requests to all connected platforms in parallel and merges the results. Every record includes a platform_id tag so you know its origin. Failures on one platform are returned in an errors array β€” others still succeed.

🎯 Targeted Writes (POST/PATCH/DELETE)

Write operations always require platform_id. This is a strict rule β€” writing to multiple platforms simultaneously is too dangerous to do implicitly. The adapter maps universal field names to each platform's native format automatically.

πŸ”— Single Integration

Connect once to LawLink. All 5 platforms are reachable through the same base URL, auth token, and schema.

πŸ”„ Normalized Schema

Every response uses the same field names regardless of platform. first_name is always first_name β€” never FirstName or attributes.first_name.

πŸ“¦ Platform Lineage

Every record carries platform_id and platform so you always know where data came from without extra calls.

πŸ›‘οΈ Partial Failure Safe

If Filevine is down but Clio responds, you still get Clio data. Platform errors are isolated in the errors[] array.

πŸ”€

Routing Rules

Method platform_id provided? Behaviour
GET ❌ Omitted Fan-out β€” queries all connected platforms in parallel, merges results
GET βœ… Provided Targeted read β€” queries only that platform
POST ❌ Omitted 400 error β€” write operations must be explicit
POST PATCH DELETE βœ… Provided Targeted write β€” routes to that platform only

Valid platform_id values: clio_manage  Β·  clio_grow  Β·  lawmatics  Β·  filevine  Β·  lead_docket

πŸ’‘ Tip: Use GET /api/v1/universal/connections first to see which platforms the current user has connected. Only connected platforms participate in fan-out.

πŸ“

Universal Schema

These are the normalized field names returned in every response regardless of which platform the record came from. Write operations accept the same names β€” the adapter translates them to each platform's native format.

Contact

Universal FieldTypeClioLawmaticsFilevineLead Docket
idstringcontact.iddata.idpersonId.nativeId
first_namestringfirst_nameattributes.first_namefirstNameFirstName
last_namestringlast_nameattributes.last_namelastNameLastName
namestringname (full)derivedfullNamederived
emailstringemail_addresses[0].addressattributes.emailemails[0].addressEmail
phonestringphone_numbers[0].numberattributes.phonephones[0].numberMobilePhone
companystringcompany.nameattributes.companycompanyNameβ€”
typestringtype (Person/Company)β€”β€”β€”
birth_datestringdate_of_birthattributes.birthdateBirthDateBirthdate
created_atstringcreated_atattributes.created_atcreatedDateCreatedOn
updated_atstringupdated_atattributes.updated_atmodifiedDateLastUpdatedDTM

Matter

Universal FieldTypeClioLawmaticsFilevineLead Docket
idstringmatter.iddata.idprojectId.nativeId / LeadId
descriptionstringdescriptionattributes.case_titleprojectNameDescription
statusstringstatusattributes.statusphaseNameStatus / StatusName
client_namestringclient.namederived first+lastβ€”FirstName + LastName
created_atstringcreated_atattributes.created_atcreatedDateDateCreated
updated_atstringupdated_atattributes.updated_atmodifiedDateDateModified

Task

Universal FieldTypeClioLawmaticsFilevineLead Docket
idstringtask.iddata.idtaskId.nativeId / TaskId
namestringnameattributes.namesubjectSummary
descriptionstringdescriptionattributes.descriptionbodyDetails
due_datestringdue_atattributes.due_datetargetDateTaskStartDate
prioritystringpriorityattributes.priorityβ€”β€”
statusstringis_completed β†’ open/completedattributes.statusisCompleted β†’ open/completedStatus

Note

Universal FieldTypeClioLawmaticsFilevineLead Docket
idstringnote.iddata.idnoteId.nativeId / NoteId
subjectstringsubjectattributes.namesubjectβ€”
detailstringdetail / bodyattributes.bodybodyText / Note
created_atstringcreated_atattributes.created_atcreatedDateDateCreated

Event

Universal FieldTypeClioLawmaticsFilevineLead Docket
idstringentry.iddata.idappointmentId.nativeId
summarystringsummary / nameattributes.nametitleSummary
start_atstring (ISO)start_atattributes.start_datestartUtcDate
end_atstring (ISO)end_atattributes.end_dateendUtcβ€”
descriptionstringdescriptionattributes.descriptionnotesβ€”
locationstringlocationattributes.locationlocationLocation
all_daybooleanall_dayattributes.all_dayallDayfalse (always)

Document (Clio Manage only)

Universal FieldTypeClio ManageLawmaticsFilevineLead Docket
idstringdocument.idβ€”β€”β€”
namestringname (filename)β€”β€”β€”
lockedbooleanlockedβ€”β€”β€”
matter_idstringparent.id (Matter)β€”β€”β€”
folder_idstringparent.id (Folder)β€”β€”β€”
contact_idstringparent.id (Contact)β€”β€”β€”
category_idstringdocument_category.idβ€”β€”β€”
latest_version_uuidstringlatest_document_version.uuidβ€”β€”β€”
latest_version_numberintegerlatest_document_version.version_numberβ€”β€”β€”
created_atstring (ISO)created_atβ€”β€”β€”
updated_atstring (ISO)updated_atβ€”β€”β€”
πŸ—ΊοΈ

Write Field Mapping

When you send a write request, you use universal field names. This table shows how each adapts them per platform. Fields not listed below can be passed in the extra object and will be forwarded as-is.

Contact β€” Create / Update

You sendClio ManageLawmaticsFilevineLead Docket
first_namefirst_namefirst_nameFirstNameFirstName
last_namelast_namelast_nameLastNameLastName
emailemail_addresses[0].addressemailEmails[0].AddressEmail
phonephone_numbers[0].numberphonePhones[0].NumberMobilePhone
companycompany_namecompanyCompanyNameβ€”
typetype (Person/Company)β€”β€”β€”
custom_fieldscustom_field_values[]custom_fields[]CustomFields{}ContactCustomFields{}

Matter β€” Create / Update

You sendClio ManageLawmaticsFilevineLead Docket
descriptiondescriptioncase_titleprojectName / DescriptionDescription
statusstatus stringstatus stringphase nameStatusId (int) or Status
client_idclient.idβ€”clientId.nativeβ€”
client_nameβ€”first_name/last_name splitβ€”β€”

Task β€” Create / Update

You sendClio ManageLawmaticsFilevineLead Docket
namenamenamesubjectSummary
descriptiondescriptiondescriptionbodyDetails
due_datedue_atdue_datetargetDateTaskStartDate
priorityprioritypriorityβ€”β€”
assignee_idassignee.idassignee_idteamMemberIds[0]UserAssigned (int)
matter_idmatter.idtaskable_idprojectId.nativeLeadId (int) β€” required
task_typeβ€”β€”β€”TaskType β€” required

Note β€” Create

You sendClio ManageLawmaticsFilevineLead Docket
subjectsubjectnamesubjectβ€”
detaildetailbodybodyText
matter_idmatter.idnotable_idprojectId.native β€” requiredlead_id β€” required
contact_idcontact.idnotable_id (when no matter)β€”β€”

Event β€” Create

You sendClio ManageLawmaticsFilevineLead Docket
summarysummarynametitleβ€”
start_atstart_atstart_datestartUtcDate β€” required
end_atend_atend_dateendUtcβ€”
locationlocationlocationlocationLocation β€” required
calendar_idcalendar.idβ€”β€”β€”
matter_idmatter.idβ€”projectId.native β€” requiredlead_id β€” required
user_idsβ€”user_ids[]β€”β€”
attendeesattendees[]β€”Attendees[{UserId:{Native}}]β€”

Document β€” Upload / Update (Clio Manage only)

You sendClio ManageNotes
filemultipart fileBinary upload via 3-step signed-URL flow (create β†’ PUT S3 β†’ PATCH complete)
namenameFilename shown in Clio. Defaults to the uploaded file's filename.
document_idversion of existing docIf provided, uploads as a new version of that document instead of creating a new one.
matter_idparent: {id, type:"Matter"}Attach to a matter on create; or move to a matter on update.
folder_idparent: {id, type:"Folder"}Attach to a folder. Mutually exclusive with matter_id and contact_id.
contact_idparent: {id, type:"Contact"}Attach to a contact. Mutually exclusive with the above.
lockedlocked (bool)Lock/unlock the document for editing.
restorerestore (bool)Pass true to restore a trashed document within its 30-day window.
βœ…

Platform Capability Matrix

Not every platform supports every operation. Unsupported operations are silently skipped in fan-out. Explicitly requesting an unsupported operation returns a 400 error.

Entity Β· Operation Clio Manage Clio Grow Lawmatics Filevine Lead Docket
Contacts listβœ“β€”βœ“βœ“βœ“
Contacts getβœ“β€”βœ“βœ“βœ“
Contacts createβœ“β€”βœ“βœ“βœ“
Contacts updateβœ“β€”βœ“βœ“βœ“
Contacts deleteβœ“β€”βœ“β€”β€”
Contacts check (conflict)βœ“β€”βœ“βœ“βœ“
Matters listβœ“β€”βœ“βœ“βœ“
Matters getβœ“β€”βœ“βœ“βœ“
Matters createβœ“β€”βœ“βœ“β€” no API
Matters updateβœ“β€”βœ“βœ“βœ“
Matters deleteβœ“β€”βœ“β€”β€”
Tasks listβœ“β€”βœ“βœ“β€” no list API
Tasks getβœ“β€”βœ“βœ“βœ“
Tasks createβœ“β€”βœ“βœ“βœ“ matter_id + task_type req
Tasks update / deleteβœ“β€”βœ“βœ“βœ“
Notes listβœ“β€”βœ“βœ“β€”
Notes createβœ“β€”βœ“βœ“βœ“ matter_id req
Notes update / deleteβœ“β€”βœ“βœ“β€”
Events listβœ“β€”βœ“βœ“ matter_id reqβ€”
Events createβœ“β€”βœ“βœ“ matter_id reqβœ“ matter_id + location req
Events update / deleteβœ“β€”βœ“βœ“β€”
Custom Fields listβœ“β€”βœ“βœ“βœ“ read-only
Documents listβœ“β€”β€”β€”β€”
Documents getβœ“β€”β€”β€”β€”
Documents uploadβœ“β€”β€”β€”β€”
Documents updateβœ“ rename/move/lock/restoreβ€”β€”β€”β€”
Documents deleteβœ“ soft-delete (30-day trash)β€”β€”β€”β€”
Documents get_download_linkβœ“β€”β€”β€”β€”
Documents read (stream bytes)βœ“β€”β€”β€”β€”
Documents list_versionsβœ“β€”β€”β€”β€”

⚠️ Clio Grow β€” not included in universal fan-out for most entities. Clio Grow only supports the lead inbox (POST /api/v1/clio/leads) which has no universal equivalent.

πŸ”Œ

All Universal Endpoints

Connections

GET /api/v1/universal/connections List platforms the current user is connected to

Contacts

GET/api/v1/universal/contactsList contacts β€” fan-out (or single platform with platform_id)
GET/api/v1/universal/contacts/{contact_id}?platform_id=Get a single contact
POST/api/v1/universal/contactsCreate contact β€” platform_id required
PATCH/api/v1/universal/contacts/{contact_id}Update contact β€” platform_id required
DELETE/api/v1/universal/contacts/{contact_id}Delete contact β€” platform_id required
POST/api/v1/universal/contacts/checkConflict check β€” platform_id required

Matters

GET/api/v1/universal/mattersList matters β€” fan-out (or single platform)
GET/api/v1/universal/matters/{matter_id}?platform_id=Get a single matter
POST/api/v1/universal/mattersCreate matter β€” platform_id required
PATCH/api/v1/universal/matters/{matter_id}Update matter β€” platform_id required
DELETE/api/v1/universal/matters/{matter_id}Delete matter β€” platform_id required

Tasks

GET/api/v1/universal/tasksList tasks β€” fan-out
GET/api/v1/universal/tasks/{task_id}?platform_id=Get a single task
POST/api/v1/universal/tasksCreate task β€” platform_id required
PATCH/api/v1/universal/tasks/{task_id}Update task β€” platform_id required
DELETE/api/v1/universal/tasks/{task_id}Delete task β€” platform_id required

Notes

GET/api/v1/universal/notesList notes β€” fan-out, optional matter_id filter
GET/api/v1/universal/notes/{note_id}?platform_id=Get a single note
POST/api/v1/universal/notesCreate note β€” platform_id required
PATCH/api/v1/universal/notes/{note_id}Update note β€” platform_id required
DELETE/api/v1/universal/notes/{note_id}Delete note β€” platform_id required

Events

GET/api/v1/universal/eventsList events β€” fan-out, optional matter_id
POST/api/v1/universal/eventsCreate event β€” platform_id required
PATCH/api/v1/universal/events/{event_id}Update event β€” platform_id required
DELETE/api/v1/universal/events/{event_id}Delete event β€” platform_id required

Custom Fields

GET/api/v1/universal/custom_fieldsList custom field definitions β€” fan-out, optional entity_type
PATCH/api/v1/universal/custom_fieldsUpdate custom field values on an entity β€” platform_id required

Documents (Clio Manage only)

GET/api/v1/universal/documentsList documents β€” platform_id=clio_manage required (no multi-platform fan-out)
GET/api/v1/universal/documents/{document_id}?platform_id=clio_manageGet document metadata
POST/api/v1/universal/documents/uploadUpload a file (multipart) β€” platform_id required; pass document_id to create a new version
PATCH/api/v1/universal/documents/{document_id}Rename, move, lock, or restore β€” platform_id required
DELETE/api/v1/universal/documents/{document_id}Soft-delete (trash) β€” platform_id required; restore with PATCH + restore=true
GET/api/v1/universal/documents/{document_id}/download-link?platform_id=clio_manageGet a time-limited signed download URL
GET/api/v1/universal/documents/{document_id}/raw?platform_id=clio_manageStream raw file bytes β€” proxied through LawLink
GET/api/v1/universal/documents/{document_id}/versions?platform_id=clio_manageList all versions of a document
POST/api/v1/universal/documents/{document_id}/versions/{version_id}/promotePromote a version to latest β€” platform_id required
DELETE/api/v1/universal/documents/{document_id}/versions/{version_id}Delete a specific version β€” platform_id required
GET/api/v1/universal/documents/{document_id}/versions/{version_id}/download-link?platform_id=clio_manageGet download URL for a specific version
πŸš€

Usage Examples

Fan-out: List contacts across all platforms

Omit platform_id to query every connected platform in parallel.

# Fan-out to all connected platforms curl -X GET \ "https://app.lawlink.ai/api/v1/universal/contacts?limit=20&query=Smith" \ -H "Authorization: Bearer YOUR_TOKEN"
// Normalized fan-out response { "items": [ { "platform_id": "clio_manage", "id": "12345", "first_name": "John", "last_name": "Smith", "email": "john@smith.com", "phone": "+15551234567" }, { "platform_id": "lead_docket", "id": "456", "first_name": "John", "last_name": "Smith", "email": "jsmith@firm.com", "phone": "+15559876543" } ], "total": 2 }

Targeted read: Get contacts from Filevine only

Pass platform_id=filevine to restrict the query to one platform.

curl -X GET \ "https://app.lawlink.ai/api/v1/universal/contacts?platform_id=filevine&limit=50" \ -H "Authorization: Bearer YOUR_TOKEN"

Targeted write: Create a contact in Clio Manage

platform_id is mandatory for writes. The adapter maps email β†’ email_addresses[0].address automatically.

curl -X POST \ "https://app.lawlink.ai/api/v1/universal/contacts" \ -H "Authorization: Bearer YOUR_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "platform_id": "clio_manage", "first_name": "Jane", "last_name": "Doe", "email": "jane.doe@example.com", "phone": "+15551234567" }'

Create a task on Lead Docket

Lead Docket tasks require matter_id (Lead ID), assignee_id (User ID), task_type, and due_date.

⚠️ Lead Docket only: task_type must be one of FollowUp · Mailing · Administrative

curl -X POST \ "https://app.lawlink.ai/api/v1/universal/tasks" \ -H "Authorization: Bearer YOUR_TOKEN" \ -d '{ "platform_id": "lead_docket", "name": "Follow up call", "matter_id": "78901", "assignee_id": "42", "task_type": "FollowUp", "due_date": "2026-04-01" }'

Create a note on Filevine (matter_id required)

Filevine and Lead Docket notes must be attached to a matter. matter_id is the projectId.native integer.

curl -X POST \ "https://app.lawlink.ai/api/v1/universal/notes" \ -H "Authorization: Bearer YOUR_TOKEN" \ -d '{ "platform_id": "filevine", "subject": "Client call summary", "detail": "Discussed timeline. Client agrees to proceed.", "matter_id": "123456" }'

Handling partial failures in fan-out

When one platform errors, the rest still succeed. Check the errors array alongside items.

// Partial failure response β€” Filevine errored, Clio succeeded { "items": [ { "platform_id": "clio_manage", "id": "111", "first_name": "Jane", ... } ], "total": 1, "errors": [ { "platform": "Filevine", "platform_id": "filevine", "error": "502: Platform returned an error" } ] }

List documents (Clio Manage)

Documents are only supported by Clio Manage β€” always pass platform_id=clio_manage. You can filter by matter, folder, or contact, and search by name.

ℹ️ No fan-out: The document endpoints do not fan-out to other platforms. Omitting platform_id will return a 400 error.

# List documents attached to a matter curl -X GET \ "https://app.lawlink.ai/api/v1/universal/documents?platform_id=clio_manage&matter_id=88231&limit=25" \ -H "Authorization: Bearer YOUR_TOKEN"
// Response { "platform": "clio_manage", "platform_id": "clio_manage", "data": [ { "id": "5012334", "name": "Settlement Agreement.pdf", "locked": false, "matter_id": "88231", "latest_version_number": 3, "created_at": "2026-03-10T09:15:00Z", "updated_at": "2026-04-01T14:22:00Z" } ] }

Upload a new document to Clio Manage

Use multipart/form-data. Optionally pass document_id to create a new version of an existing document instead of a brand-new one. The upload uses Clio's 3-step signed-URL flow internally.

# Upload a new document attached to matter 88231 curl -X POST \ "https://app.lawlink.ai/api/v1/universal/documents/upload" \ -H "Authorization: Bearer YOUR_TOKEN" \ -F "platform_id=clio_manage" \ -F "name=Engagement Letter.pdf" \ -F "matter_id=88231" \ -F "file=@/path/to/engagement_letter.pdf;type=application/pdf"
# Upload as a new version of document 5012334 curl -X POST \ "https://app.lawlink.ai/api/v1/universal/documents/upload" \ -H "Authorization: Bearer YOUR_TOKEN" \ -F "platform_id=clio_manage" \ -F "document_id=5012334" \ -F "file=@/path/to/settlement_v4.pdf;type=application/pdf"

Get a signed download URL

Returns a time-limited signed URL for direct download. The URL can be shared with clients or used in browser redirects β€” no LawLink token required to download the file.

curl -X GET \ "https://app.lawlink.ai/api/v1/universal/documents/5012334/download-link?platform_id=clio_manage" \ -H "Authorization: Bearer YOUR_TOKEN"
// Response β€” copy the URL to download or share { "platform": "clio_manage", "platform_id": "clio_manage", "data": { "download_url": "https://app.clio.com/api/v4/documents/5012334/download?token=eyJhb..." } }

Rename and move a document

Use PATCH to rename or move to a different matter/folder/contact. Only one parent target may be set per request β€” matter_id, folder_id, and contact_id are mutually exclusive.

⚠️ Single parent only: Providing more than one of matter_id, folder_id, contact_id in the same request returns a 400 error.

curl -X PATCH \ "https://app.lawlink.ai/api/v1/universal/documents/5012334" \ -H "Authorization: Bearer YOUR_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "platform_id": "clio_manage", "name": "Settlement Agreement v4.pdf", "matter_id": "88231" }'