Core Objects & Endpoints Reference
The Lawmatics REST API exposes ~30 resource types, all following the same conventions for structure, field selection, pagination, sorting, and filtering. This article covers those shared conventions plus a directory of available resources.
All requests require an Authorization: Bearer <access_token> header — see API Authentication: OAuth2 Setup Guide if you haven't set that up yet.
Response Structure (JSON:API style)
Every response wraps records in a data object with id, type, attributes, and relationships:
{
"data": {
"id": "25",
"type": "prospect",
"attributes": {
"first_name": "Jane",
"last_name": "Doe",
"status": "active"
},
"relationships": {
"source": { "data": { "id": "3", "type": "source" } }
}
}
}Association fields only return the related record's id and type — query that resource's own endpoint to get its full attributes.
Field Selection — ?fields=
Shape the response to only include the attributes/relationships you need (one level deep). Fields are returned in the order you list them.
Requests without
fieldsreturn a small set of common defaults (e.g.name,email)?fields=allon any endpoint reveals every available attribute/relationship — useful for exploring what's there
?fields=first_name,last_name,source,custom_fields
Example — drilling into a relationship:
curl -H "Authorization: Bearer <access_token>" \
https://api.lawmatics.com/v1/prospects/74?fields=source
Returns the Source's id — then query /v1/sources/3?fields=all to get its full data.
Pagination — ?page=
List endpoints are paginated. Pagination metadata appears at the bottom of the response.
?page=3
Sorting — ?sort_by= / ?sort_order=
Default sort:
id, descendingsort_order:ascordescsort_by:id,created_at,updated_at, or most fields shown in afields=allresponseIf you set
sort_orderwithoutsort_by, it defaults to sorting byid
Filtering — ?filter_by= / ?filter_on= / ?filter_with=
Param | Purpose |
| The field to filter on |
| The value to filter for |
| Optional operator, defaults to |
Valid operators: =, !=, <=, <, >=, >, like, ilike
Presence operators (no filter_on needed): null, not_null (aliases: empty, present, blank)
Notes:
Only one filter is supported per request
Currency fields are filtered in cents
Association fields need
_idappended, e.g.practice_area_idA field doesn't need to be selected via
fields=to be filterableilikeis the default operator for String fields; use%in the value for fuzzy matching (URL-encoded as%25)Using
filter_bywithoutfilter_onreturns an error
Examples:
# Matters in a specific practice area
GET /v1/prospects?fields=practice_area,first_name&filter_by=practice_area_id&filter_on={practice_area_id}
# Matters with actual value > 0, sorted ascending
GET /v1/prospects?fields=first_name,actual_value_cents&filter_by=actual_value_cents&filter_on=0&filter_with=>&sort_by=actual_value_cents&sort_order=asc
# Matters where status is not PNC
GET /v1/prospects?fields=first_name,status&filter_by=status&filter_on=pnc&filter_with=!=
Custom Fields
Custom Fields let firms extend standard objects (Matters, Contacts, Companies, Practice Areas, etc.) with their own attributes. GET /v1/custom_fields?fields=all returns every custom field defined on the account, including its field_type (e.g. string, date, datetime, time, boolean, lookup), the record type it applies to (Prospect, Contact, PracticeArea, etc.), and visibility.
On the parent record's payload, custom field values appear with type-specific attribute keys, e.g. value_string, value_int, value_datetime — match the key to the field's field_type.
Custom Forms — Submitting Entries
Custom Forms can be submitted two ways — as multipart form data or as JSON — to POST /v1/forms/:custom_form_uuid/submit. This endpoint is unauthenticated (no Bearer token needed); see Connecting Your Webform to Lawmatics via API for the full guide.
Key details:
Standard fields are submitted by name:
first_name,last_name, etc.Custom form fields are submitted as
field_id: valuepairs — the specific field UUID/key is found in Lawmatics under the form builder's API Details panel for that field.Optional UTM tracking fields (
utm_source,utm_campaign) andreferring_urlcan be passed to preserve attribution — these can be pulled from the cookie set by the Lawmatics tracking pixel if you have one installed.
Example (JSON body):
{
"first_name": "{first_name}",
"last_name": "{last_name}",
"utm_source": "{utm_source}",
"utm_campaign": "{utm_campaign}",
"{custom_field_key}": "{value}"
}Files
Uploads use multipart/form-data on POST /v1/files:
Field | Description |
|
|
| ID of that record |
| The binary file |
| Optional repeated param for nested folder path, e.g. |
Retrieve the binary via GET /v1/files/download/:id.
Tasks, Subtasks & Comments
Tasks support recurrence, tagging, and nested subtasks/comments:
POST /v1/tasks
{
"name": "{task_name}",
"description": "{description}",
"due_date": "MM/DD/YYYY",
"user_ids": [{user_id}],
"priority": "low",
"taskable_id": {prospect_id},
"taskable_type": "Prospect",
"done": false,
"tag_ids": [{tag_id}],
"assigned_by_id": {user_id},
"recurrence_rule": {
"type": "daily",
"frequency": 2,
"endDate": "MM/DD/YYYY"
}
}
taskable_typecan point to a Prospect (Matter) or other supported record typesrecurrence_rule.typesupports at leastdaily(checkfields=allfor the complete set);frequencyis the interval,endDatecaps recurrence
Subtasks (POST /v1/tasks/:task_id/subtasks) and comments (POST /v1/tasks/:task_id/comments) are simple nested resources:
Subtask
{ "body": "{subtask_text}", "done": false }Comment
{ "body": "{comment_text}", "user_id": {user_id}, "mentioned_user_ids": [{user_id}] }Tags — Attach/Detach
Tags have dedicated bulk attach/detach endpoints rather than requiring a full record update:
Attach
POST /v1/tags/attach
{ "matter_id": {prospect_id}, "tags": ["Existing Tag", "Tag to Create"] }
Detach
POST /v1/tags/detach
{ "matter_id": {prospect_id}, "tags": ["Tag to Remove"] }
Attaching a tag name that doesn't exist yet creates it automatically. Tags can also be listed filtered by Matter, Contact, or Company via the standard filter params.
Collections & Collection Items
Collections are firm-defined custom data structures (e.g. "Bank Accounts," "Vehicles") attached to a Matter or Contact, with their own custom field schema:
POST /v1/collections
{
"name": "{collection_name}",
"custom_fields": [
{ "name": "Name", "field_type": "text" },
{ "name": "Balance", "field_type": "currency" },
{
"name": "Type",
"field_type": "list",
"list_options": [ { "name": "Option A" }, { "name": "Option B" } ]
}
]
}
Collection Items are individual records within a Collection, attached to a specific Matter/Contact:
POST /v1/collection_items
{
"contactable_type": "Prospect",
"contactable_id": {prospect_id},
"collection_id": {collection_id},
"custom_field_values": [
{ "id": {custom_field_id}, "value": "{value}" }
]
}
Time Entries & Expenses (Billing)
Both use multipart/form-data and attach to a Matter/Contact via a polymorphic contactable_type / contactable_id pair (accepts Matter, Prospect, or Contact):
Resource | Key fields |
Time Entry |
|
Expense |
|
Transactions
POST /v1/transactions?fields=all
{
"invoice_number": {invoice_id},
"transaction_type": "credit",
"bank_account_type": "operating",
"payment_method": "credit_card",
"executed_at": "YYYY-MM-DD HH:MM:SS.000",
"amount_cents": 5000,
"note": "",
"transactable_id": {prospect_id},
"transactable_type": "Prospect"
}
Events (Appointments)
POST /v1/events
{
"name": "{event_name}",
"description": "{description}",
"start_date": "YYYY-MM-DDTHH:MM:SS-07:00",
"end_date": "YYYY-MM-DDTHH:MM:SS-07:00",
"user_ids": [{user_id}],
"all_day": false,
"eventable_type": "Prospect",
"eventable_id": {prospect_id},
"event_type_id": {event_type_id},
"location_id": {location_id},
"reminder_delay_length": 10,
"reminder_type": "minutes",
"send_invites": true,
"no_show": false,
"time_zone": "America/Los_Angeles"
}
Cancel via DELETE /v1/events/:event_id?notify_attendees=true to notify attendees of the cancellation.
Companies
Companies support multiple emails/phones/addresses via _attributes arrays, alongside a single primary email/phone/address:
POST /v1/companies?fields=all
{
"name": "{company_name}",
"email": "{primary_email}",
"emails_attributes": [
{ "info": "{email_2}" },
{ "label": "Home", "info": "{email_3}" }
],
"phone": "{primary_phone}",
"phone_numbers_attributes": [
{ "info": "{phone_2}" },
{ "label": "Home", "info": "{phone_3}" }
],
"street": "{street}",
"city": "{city}",
"state": "{state}",
"country": "{country}",
"zipcode": "{zip}",
"addresses_attributes": [
{ "street": "{street_2}", "city": "{city_2}" }
]
}
Interactions
POST /v1/interactions
{
"happened_at": "YYYY-MM-DDTHH:MM:SS-07:00",
"prospect_id": {prospect_id},
"body": "{interaction_notes}",
"interaction_type": "{type}"
}
Timeline Activities
Activities are a read-only feed of everything that happened on a record (status changes, tasks completed, emails sent, etc.). Filter by the owning record:
GET /v1/activities?filter_by=matter_id&filter_on={prospect_id}Practice Areas, Relationships & Sub Statuses
Practice Area
POST /v1/practice_areas
{ "name": "{practice_area_name}", "color": "#hexcode", "statute_of_limitations_enabled": true }
Relationship
Links a Contact to a Matter with a defined relationship type:
POST /v1/relationships
{ "prospect_id": "{prospect_id}", "contact_id": "{contact_id}", "relationship_type_id": "{relationship_type_id}" }
Relationship Type
POST /v1/relationship_types
{ "name": "{relationship_name}", "is_repeatable": false }
Sub Status
Custom stage-level statuses beneath the top-level Matter status:
POST /v1/sub_statuses
{ "name": "{sub_status_name}", "status": "hired" }
status on a Sub Status must map to one of the top-level Matter statuses (e.g. hired, pnc, lost).
Users
GET /v1/users/me returns the authenticated user's own record — a quick way to confirm which account/token you're operating as.
Finder Endpoints
Contacts, Matters, and Companies each support "finder" endpoints to look up a record by phone, email, or name without knowing its ID:
GET /v1/contacts/find_by_phone/:phone_number
GET /v1/contacts/find_by_email/:email_address
GET /v1/contacts/find_by_name/:name
Matters use the same pattern under /v1/prospects/find_by_..., Companies under /v1/companies/find_by_....
Resource Directory
All resources below support the same field selection / pagination / sorting / filtering conventions above (GET list + GET single; most also support POST/PUT/DELETE — see docs.lawmatics.com for exact verbs per resource).
Resource | Base path |
Contacts |
|
Matters (Prospects) |
|
Companies |
|
Addresses |
|
Phone Numbers |
|
Email Addresses |
|
Custom Fields |
|
Custom Contact Types |
|
Custom Forms |
|
Custom Emails |
|
Email Campaigns / Stats |
|
Events (Appointments) |
|
Event Types / Locations |
|
Files |
|
Folders |
|
Interactions |
|
Marketing Campaigns / Sources |
|
Pipelines / Stages |
|
Practice Areas |
|
Relationships / Relationship Types |
|
Sub Statuses |
|
Notes |
|
Invoices |
|
Expenses |
|
Time Entries |
|
Transactions |
|
Tags |
|
Tasks (+ Subtasks, Comments) |
|
Task Statuses |
|
Timeline Activities |
|
Users |
|
Collections / Collection Items |
|
Creating a Matter — Common Patterns
Matters (prospects) support several creation patterns worth knowing:
Basic create:
POST /v1/prospectswith contact fields (first_name,last_name,email, etc.) pluspractice_area_idCreate a Matter for an existing Contact: pass
contact_id, ormatch_contact_byto match on email/phoneCreate a Company Matter: pass
company_name(creates the company) or an existing company ID. Any contact info passed (email/phone/address) is set on the found/created Contact as the Company Matter's primary point of contactContact deduplication happens automatically on create if a match is found on email or phone
Example create body:
{
"first_name": "Lawmatics",
"last_name": "Example",
"email": "[email protected]",
"phone": "123-123-1234",
"practice_area_id": 4,
"sub_status_id": 12,
"notes": [
{ "name": "Example Note", "body": "Intake notes here..." }
],
"tags": ["Tag 1", "Tag 2"]
}Questions? [email protected]
