Skip to main content

Core Objects & Endpoints Reference

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 fields return a small set of common defaults (e.g. name, email)

  • ?fields=all on 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, descending

  • sort_order: asc or desc

  • sort_by: id, created_at, updated_at, or most fields shown in a fields=all response

  • If you set sort_order without sort_by, it defaults to sorting by id


Filtering — ?filter_by= / ?filter_on= / ?filter_with=

Param

Purpose

filter_by (alias: filter_field)

The field to filter on

filter_on (alias: filter_value)

The value to filter for

filter_with (alias: filter_operator)

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 _id appended, e.g. practice_area_id

  • A field doesn't need to be selected via fields= to be filterable

  • ilike is the default operator for String fields; use % in the value for fuzzy matching (URL-encoded as %25)

  • Using filter_by without filter_on returns 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: value pairs — 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) and referring_url can 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

documentable_type

Firm, Contact, or Matter — what the file attaches to

documentable_id

ID of that record

file

The binary file

path[]

Optional repeated param for nested folder path, e.g. path[]=Folder 1&path[]=Folder 2

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_type can point to a Prospect (Matter) or other supported record types

  • recurrence_rule.type supports at least daily (check fields=all for the complete set); frequency is the interval, endDate caps 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

billable (bool), completed_at (ISO8601 or Unix timestamp — only completed entries can be invoiced; incomplete ones only show in the app's timer), contactable_type, contactable_id, description

Expense

billable (bool), contactable_type, contactable_id, cost_cents (integer), description, optional billing_expense_type_id


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

/v1/contacts

Matters (Prospects)

/v1/prospects

Companies

/v1/companies

Addresses

/v1/addresses

Phone Numbers

/v1/phone_numbers

Email Addresses

/v1/email_addresses

Custom Fields

/v1/custom_fields

Custom Contact Types

/v1/custom_contact_types

Custom Forms

/v1/forms (see the Forms API guide for the unauthenticated submit endpoint)

Custom Emails

/v1/custom_emails

Email Campaigns / Stats

/v1/email_campaigns, /v1/email_campaign_stats

Events (Appointments)

/v1/events

Event Types / Locations

/v1/event_types, /v1/locations

Files

/v1/files (+ /v1/files/download/:id)

Folders

/v1/folders

Interactions

/v1/interactions

Marketing Campaigns / Sources

/v1/campaigns, /v1/sources

Pipelines / Stages

/v1/pipelines, /v1/stages

Practice Areas

/v1/practice_areas

Relationships / Relationship Types

/v1/relationships, /v1/relationship_types

Sub Statuses

/v1/sub_statuses

Notes

/v1/notes

Invoices

/v1/invoices

Expenses

/v1/expenses

Time Entries

/v1/time_entries

Transactions

/v1/transactions

Tags

/v1/tags (+ /attach, /detach)

Tasks (+ Subtasks, Comments)

/v1/tasks, /v1/tasks/:id/subtasks, /v1/tasks/:id/comments

Task Statuses

/v1/task_statuses

Timeline Activities

/v1/activities

Users

/v1/users (+ /v1/users/me)

Collections / Collection Items

/v1/collections, /v1/collection_items


Creating a Matter — Common Patterns

Matters (prospects) support several creation patterns worth knowing:

  • Basic create: POST /v1/prospects with contact fields (first_name, last_name, email, etc.) plus practice_area_id

  • Create a Matter for an existing Contact: pass contact_id, or match_contact_by to match on email/phone

  • Create 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 contact

  • Contact 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"]
}
Did this answer your question?