8am MyCase MCP Server — Tool Catalog

This catalog documents the 130 tools the MyCase MCP Server can expose — the same name, description, parameter, and annotation data an MCP client receives for them from tools/list — organized by domain. Tools badged beta are enabled per firm, so a connection that is not enrolled receives fewer tools than are listed here.

Write tools (beta)

Some of the tools below change MyCase data: they create a record, add a record to a case, or update fields on a record. Each one is badged beta. Write tools are in a limited beta and are off by default, so connecting Claude to MyCase does not turn them on.

A firm has to be enrolled before its connection can use them. Until your firm is enrolled the write tools are not in the tool list Claude receives, so Claude does not show them and does not offer to use them. Asked for one by name, it comes back with a message saying your firm is not enrolled. Nothing is broken and there is nothing to fix. Read tools work the same either way.

Enrollment is per firm, not per user: it covers every user who connects, still limited to what that user can do in MyCase. To ask about enrolling your firm, email MyCase Support at support@mycase.com.

Before you enroll, know these limits:

  • Writes cannot be undone from Claude. A write takes effect in MyCase as soon as the tool runs, and the connector exposes no delete tools, so a record created by mistake has to be removed in the MyCase app.
  • Claude asks you to approve a write before it runs, but that prompt comes from Claude, not from MyCase. Automations, scheduled tasks and Claude's own "always allow" setting can skip it. Do not rely on being asked for anything that needs an attorney's judgment.
  • convert_lead cannot be undone. It converts the lead into a client and opens its potential case as a real case, approving a lead still pending review as part of the conversion. MyCase has no un-convert.
  • Some update tools replace a list rather than add to it. On update_case, update_client, update_company, update_document, update_event and update_task, sending a list of people or records replaces that whole list: anyone left out is unassigned, with no error and no warning. Use the matching add tool where one exists — there is none for case contacts or document staff, so those can only be changed by replacing the list.
  • Addresses behave two ways. The street, city, state, ZIP and country fields must be sent together or the call is rejected. A second address line left out of an otherwise complete address is cleared without an error.
  • Adding a document takes two steps, and the first one already creates the record. create_document, create_case_document and create_document_version register the document and return a URL to upload the file to. If the upload never happens, the record stays in MyCase with no file attached, and the connector has no tool to remove it.

Connect Claude to MyCase

MyCase isn't listed in Claude's connector directory, so add it as a custom connector. The install links below open Claude's own dialog with the connector name and URL already filled in; the URL is spelled out further down if you'd rather enter it yourself. One connector covers everywhere you use Claude — the web app, Claude Desktop, and Cowork — because connectors are configured on your Claude account rather than per device.

Install link for your firm

If you administer your firm's Claude organization, this link prefills the connector for everyone in it. Claude flags that the values arrived from an external link and adds nothing until you review them and confirm.

As a Claude organization owner, open the prefilled install link for a Claude organization.

Install link for one person

If your Claude plan lets you add your own connectors, this link prefills the same dialog for your account alone. Where connectors are administered centrally, an organization owner adds the connector once and it then appears in your own connector settings for you to turn on.

For your own Claude account, open the prefilled install link for a single Claude account.

Connector URL

The links above only prefill Claude's dialog. If one doesn't open it, add this URL as a custom connector by hand instead:

https://mcp.mycase.com/mcp

You sign in with your own MyCase account, and every tool call runs as your MyCase user, held to that user's permissions.

For the steps in Claude, see Anthropic's guide to adding a custom connector.

What Claude Can Access

Connecting the connector grants Claude access to the following, for the individual MyCase user who authorizes it and only what that user can already see or do in MyCase.

Information Claude can read

  • Cases & matters
  • Documents
  • Billing & trust accounts
  • Clients, contacts, & leads
  • Time & expenses
  • Notes
  • Calendar
  • Client messages
  • Staff directory
  • Custom fields
  • Tasks
  • Call log
  • Text message conversations
  • Internal staff chats
  • Comments on records

Actions Claude can take (beta only)

  • Create & update tasks
  • Create & update time & expenses
  • Create & update notes
  • Create & update contacts & leads
  • Create & update cases
  • Create & edit documents
  • Create & send messages
  • Create & update calendar events
  • Set up custom fields
  • Log & update calls

Billing

get_case_billing_summary

Get Case Billing Summary read-only

Get a case's billing snapshot: fee_structure, totals (billed/collected/outstanding/overdue), balances (trust/credit funds held), aging, bills_by_status, unbilled work in progress, most_recent_payment, and most_recent_bill. Sections the user may not view are OMITTED, not zeroed: totals, balances, aging, bills_by_status, and most_recent_* require permissions.view_bills; unbilled is omitted only when the user has neither view_bills nor view_time_expenses (or the token lacks read_expenses). The permissions block is always present — use it to tell 'no access' from 'no billing on this case'. fee_structure (billing_type, agreed flat_fee, billing_contact) is the only source of the case's fee arrangement; unbilled.flat_fees is the flat-fee amount REMAINING to bill, distinct from the agreed fee_structure.flat_fee (itemized flat-fee line items come from list_case_billing_flat_fees). totals.outstanding counts invoiced balances only (draft invoices included), so flat-fee money not yet invoiced is in unbilled.flat_fees, not there. balances are client funds held, separate from the bill-side totals — a client can owe outstanding and still hold trust/credit; report both, never net them. credit is a per-contact, firm-wide snapshot with no provenance surface — do not sum a contact's credit across their cases, and do not claim where it came from. totals, aging, and bills_by_status exclude balance-forwarded bills, which list_case_invoices includes (status 'forwarded') — counts may legitimately differ. These billing tools do not surface retainer requests, payment plans or installment schedules, saved payment methods, failed or declined payment attempts, or write-off/discount line-item detail beyond get_case_invoice_line_items — direct the user to the MyCase app for those.

ParameterTypeRequiredDescription
case_idintegeryes

get_case_invoice_line_items

Get Case Invoice Line Items read-only

Get the line items that compose one invoice, grouped by kind — time_entries, expenses, flat_fees, discounts — plus balances_forwarded (prior invoices whose unpaid balance rolled into this one) and the invoice header. Reconciliation: total_amount = billable time_entries' total + billable expenses' total + billable flat_fees' amount + all SIGNED discount amounts + balances_forwarded amounts, clamped at zero; nonbillable items appear with billable false and contribute nothing, and some firms fold payment surcharges into total_amount that are not itemized here. discounts rows are not all reductions: type discount/write_off is stored NEGATIVE, interest/tax/addition POSITIVE — sum amounts as-is, never flip signs by label. flat_fees are the BILLED flat-fee line items, distinct from the agreed fee_structure.flat_fee and from summary unbilled.flat_fees (remaining to bill). Visibility is the invoice's: a user without billing permission gets not_found (the invoice is invisible), so cross-check get_case_billing_summary's permissions.view_bills before concluding the invoice does not exist; unlike the case billing time/expense feeds, no read_expenses scope is needed because items are read as parts of the invoice document. Not paginated — one response carries the invoice's full contents.

ParameterTypeRequiredDescription
case_idintegeryes
invoice_idintegeryes

list_case_billing_expenses

List Case Billing Expenses read-only

List a case's expenses. Each expense carries a server-computed total; the response has no list-level total, so to total the case sum each expense's total across every page. A non-billable expense still carries a nonzero total, so leave billable=false rows out of a billable total. filter_billed reflects actual invoice association (the same definition the billing summary uses); billed=false does NOT imply billable — also check the billable field when reconciling against summary.unbilled. Requires the read_expenses token scope (same as list_all_expenses) plus the time-entries-and-expenses OR billing user permission, and returns 403 without them — given the scope, a billing-permission-only user can use this tool even where list_all_expenses is denied.

ParameterTypeRequiredDescription
case_idintegeryes
filter_updated_afterstringnoOnly records updated strictly after this ISO8601 timestamp (exclusive bound, unlike the inclusive entry-date filters)
filter_entry_date_afterstringnoOnly expenses dated on or after this date-only ISO8601 date (YYYY-MM-DD); the bound is inclusive
filter_entry_date_beforestringnoOnly expenses dated on or before this date-only ISO8601 date (YYYY-MM-DD); the bound is inclusive
filter_billedbooleannotrue → only expenses already on an invoice; false → only expenses not yet invoiced
page_sizeintegernoItems per page (default 25, max 1000)
page_tokenstringnopagination.next_page_token from the previous page. It carries that page's filters, so other args may be omitted; changing a filter mid-walk is rejected.

list_case_billing_flat_fees

List Case Billing Flat Fees read-only

List a case's flat-fee billing line items: fixed-amount charges with no activity, rate, or duration — the third line-item type alongside time entries and expenses. Flat fees never appear in the time-entry feed, and BILLED flat fees appear in get_case_invoice_line_items (its flat_fees group); but UNBILLED flat fees appear only here, so a work-in-progress total built without this tool misses unbilled flat-fee revenue. They are also distinct from flat-RATE time entries, which list_case_billing_time_entries does include. amount is the charge (total is the same value, for symmetry with the sibling feeds). filter_billed reflects actual invoice association, and billed=false does NOT imply billable — also check the billable field. Do not reconcile this feed against summary.unbilled.flat_fees: that rollup is the agreed fee_structure.flat_fee minus billed billable items, not a sum of the unbilled rows here. Requires the read_expenses token scope plus the time-entries-and-expenses OR billing user permission, and returns 403 without them — given the scope, a billing-permission-only user can use this tool even where list_all_time_entries is denied.

ParameterTypeRequiredDescription
case_idintegeryes
filter_updated_afterstringnoOnly records updated strictly after this ISO8601 timestamp (exclusive bound, unlike the inclusive entry-date filters)
filter_entry_date_afterstringnoOnly flat fees dated on or after this date-only ISO8601 date (YYYY-MM-DD); the bound is inclusive
filter_entry_date_beforestringnoOnly flat fees dated on or before this date-only ISO8601 date (YYYY-MM-DD); the bound is inclusive
filter_billedbooleannotrue → only flat fees already on an invoice; false → only flat fees not yet invoiced
page_sizeintegernoItems per page (default 25, max 1000)
page_tokenstringnopagination.next_page_token from the previous page. It carries that page's filters, so other args may be omitted; changing a filter mid-walk is rejected.

list_case_billing_payments

List Case Billing Payments read-only

List successful payments applied to a case's bills. Bill payments only: retainer, subscription, and quick-bill receipts are excluded, and so are pending/failed transactions — never infer 'no failed charges' from this feed. For any of those (all payable types, all statuses) scoped to this same case, use list_all_payments with filter_case_id. amount is SIGNED: refunds/voids are negative with is_refund true, so summing the list gives the correct net — do not count refunds as income. client on each payment is the bill's billing contact, never the staff member who recorded it. Requires the caller's billing permission and returns 403 without it, so an empty list means the case genuinely has no matching payments.

ParameterTypeRequiredDescription
case_idintegeryes
filter_updated_afterstringnoOnly records updated strictly after this ISO8601 timestamp (exclusive bound)
page_sizeintegernoItems per page (default 25, max 1000)
page_tokenstringnopagination.next_page_token from the previous page. It carries that page's filters, so other args may be omitted; changing a filter mid-walk is rejected.

list_case_billing_time_entries

List Case Billing Time Entries read-only

List a case's time entries. Each entry carries a server-computed total that prices flat-rate entries correctly — prefer it over hours x rate math. The response has no list-level total: to total the case, sum each entry's total across every page. A non-billable entry still carries a nonzero total, so leave billable=false rows out of a billable total. Flat-FEE billing line items are separate records that NEVER appear in any time-entry feed — include list_case_billing_flat_fees when totaling case billing (flat-RATE time entries, by contrast, are ordinary rows here). filter_billed reflects actual invoice association (the same definition the billing summary uses); billed=false does NOT imply billable — also check the billable field when reconciling against summary.unbilled. Requires the read_expenses token scope (same as list_all_time_entries) plus the time-entries-and-expenses OR billing user permission, and returns 403 without them — given the scope, a billing-permission-only user can use this tool even where list_all_time_entries is denied.

ParameterTypeRequiredDescription
case_idintegeryes
filter_updated_afterstringnoOnly records updated strictly after this ISO8601 timestamp (exclusive bound, unlike the inclusive entry-date filters)
filter_entry_date_afterstringnoOnly entries dated on or after this date-only ISO8601 date (YYYY-MM-DD); the bound is inclusive
filter_entry_date_beforestringnoOnly entries dated on or before this date-only ISO8601 date (YYYY-MM-DD); the bound is inclusive
filter_billedbooleannotrue → only entries already on an invoice; false → only entries not yet invoiced
page_sizeintegernoItems per page (default 25, max 1000)
page_tokenstringnopagination.next_page_token from the previous page. It carries that page's filters, so other args may be omitted; changing a filter mid-walk is rejected.

list_case_invoices

List Case Invoices read-only

List a case's invoices (bills), scoped to the case server-side. On a case the caller can see, list_all_invoices with filter_case_id at its default only_allowed_online_payments=false returns the same rows for the same caller; on a case they cannot see, this tool 404s while that one applies no case check at all and returns whatever bills on it are shared with them. Each invoice carries balance_due, and its due_date is the bill's actual next payment due date (payment-plan aware, matching the UI's overdue math). Includes balance-forwarded bills (status 'forwarded'), which the billing summary's totals exclude — counts may legitimately differ. Requires the caller's billing permission and returns 403 without it, so an empty list is never a permission artifact — but it is still not proof the case has no invoices: a caller who cannot view all firm cases sees only the bills shared with them, and the billing summary's bill-side sections are narrowed by that same rule, so neither tool can reveal the rest. Send the user to the MyCase app when a bill they expect is missing.

ParameterTypeRequiredDescription
case_idintegeryes
filter_updated_afterstringnoOnly records updated strictly after this ISO8601 timestamp (exclusive bound)
page_sizeintegernoItems per page (default 25, max 1000)
page_tokenstringnopagination.next_page_token from the previous page. It carries that page's filters, so other args may be omitted; changing a filter mid-walk is rejected.

Calls

create_call

Create Call write beta

Create a new call log entry. Must provide exactly one of: client_id, lead_id, or caller_name.

ParameterTypeRequiredDescription
called_atstringyesCall time (ISO8601)
caller_phone_numberstringyes
call_for_idintegeryesStaff member ID the call was for
messagestringyesCall message/notes
client_idintegernoClient ID (mutually exclusive with lead_id and caller_name)
lead_idintegernoLead ID (mutually exclusive with client_id and caller_name)
caller_namestringnoCaller name (mutually exclusive with client_id and lead_id)
case_idintegernoCase ID to associate the call with (independent of the caller)
call_typestringnoCall direction (defaults to incoming). One of: incoming, outgoing.
resolvedbooleannoWhether the call has been resolved/answered (defaults to false)

get_call

Get Call read-only

Get a specific call log entry by ID.

ParameterTypeRequiredDescription
call_idintegeryes

list_callers

List Callers read-only

List all callers (clients and leads that can appear in call logs).

ParameterTypeRequiredDescription
filter_updated_afterstringno
page_sizeintegernoItems per page (default 25, max 1000)
page_tokenstringnopagination.next_page_token from the previous page. It carries that page's filters, so other args may be omitted; changing a filter mid-walk is rejected.

list_calls

List Calls read-only

List all call log entries, most recent call first.

ParameterTypeRequiredDescription
filter_updated_afterstringno
page_sizeintegernoItems per page (default 25, max 1000)
page_tokenstringnopagination.next_page_token from the previous page. It carries that page's filters, so other args may be omitted; changing a filter mid-walk is rejected.

update_call

Update Call write destructive beta

Update a call log entry.

ParameterTypeRequiredDescription
call_idintegeryes
called_atstringno
caller_phone_numberstringno
call_for_idintegerno
messagestringno
client_idintegerno
lead_idintegerno
caller_namestringno
case_idintegerno
call_typestringnoOne of: incoming, outgoing.
resolvedbooleanno

Case Stages

create_case_stage

Create Case Stage write beta

Create a new case stage. Name must be unique within the firm.

ParameterTypeRequiredDescription
namestringyesCase stage name (must be unique)

get_case_stage

Get Case Stage read-only

Get a specific case stage by ID.

ParameterTypeRequiredDescription
case_stage_idintegeryes

list_case_stages

List Case Stages read-only

List all case stages.

ParameterTypeRequiredDescription
filter_updated_afterstringno
search_starts_withstringno
page_sizeintegernoItems per page (default 25, max 1000)
page_tokenstringnopagination.next_page_token from the previous page. It carries that page's filters, so other args may be omitted; changing a filter mid-walk is rejected.

update_case_stage

Update Case Stage write destructive beta

Update a case stage name.

ParameterTypeRequiredDescription
case_stage_idintegeryes
namestringno

Cases

add_clients_to_case

Add Clients To Case write beta

Add clients to a case. Additive — existing case members are preserved (unlike update_case, whose list params replace).

ParameterTypeRequiredDescription
case_idintegeryes
client_idsarray[integer]yesClient IDs to add
rolestringnoThe party's role on this case (e.g. Adverse Party, Judge), applied to every ID in this call, including IDs already on the case, whose current role it replaces; make one call per role to give different roles. It must be an existing role name from list_case_roles (matched case-insensitively). An unknown name is refused and nothing is added, since MyCase roles are firm-wide and created only in MyCase settings. Omit to add without a role.

add_companies_to_case

Add Companies To Case write beta

Add companies to a case. Additive — existing case members are preserved (unlike update_case, whose list params replace).

ParameterTypeRequiredDescription
case_idintegeryes
company_idsarray[integer]yesCompany IDs to add
rolestringnoThe party's role on this case (e.g. Adverse Party, Judge), applied to every ID in this call, including IDs already on the case, whose current role it replaces; make one call per role to give different roles. It must be an existing role name from list_case_roles (matched case-insensitively). An unknown name is refused and nothing is added, since MyCase roles are firm-wide and created only in MyCase settings. Omit to add without a role.

add_staff_to_case

Add Staff To Case write beta

Add staff members to a case, optionally making one of them the lead or originating lawyer. Additive — existing case members are preserved (unlike update_case, whose list params replace).

ParameterTypeRequiredDescription
case_idintegeryes
staff_idsarray[integer]yesStaff IDs to add. Staff already on the case may be included; they stay on it once.
lead_lawyer_idintegernoStaff ID to make the case's lead lawyer, taking the role from whoever holds it. Must also be one of the staff_ids in this call, or the call is refused. If the new holder is already on the case, MyCase can refuse the move with a 'can only be set for one user per case' error. Do not remove the current holder or drop them from staff_ids to get around it; tell the user to reassign the role in MyCase.
originating_lawyer_idintegernoStaff ID to record as the case's originating lawyer, taking the role from whoever holds it. Must also be one of the staff_ids in this call, or the call is refused. If the new holder is already on the case, MyCase can refuse the move with a 'can only be set for one user per case' error. Do not remove the current holder or drop them from staff_ids to get around it; tell the user to reassign the role in MyCase.

create_case

Create Case write beta

Create a new case in MyCase.

ParameterTypeRequiredDescription
namestringyesCase name
case_numberstringno
descriptionstringno
statusstringnoOne of: open, closed.
case_stage_idintegernoCase stage ID
case_stage_namestringnoCase stage by name (mutually exclusive with case_stage_id)
practice_area_idintegernoPractice area ID
practice_area_namestringnoPractice area by name (mutually exclusive with practice_area_id)
office_idintegernoOffice ID to assign the case to. Find valid IDs in get_firm's offices list. If omitted, MyCase assigns the firm's primary office when one is configured. Assigning an office matters: a case with no office is hidden from MyCase's default case view.
client_idsarray[integer]noClient IDs to associate
staff_idsarray[integer]noStaff IDs to assign. If omitted, MyCase adds the connected user to the case's staff (not as lead or originating lawyer) so the case shows in their My Cases. A list you pass is used exactly as given, and an empty list leaves the case with no staff.
lead_lawyer_idintegernoStaff ID to make the case's lead lawyer. Must also be one of the staff_ids in this call, or the call is refused.
originating_lawyer_idintegernoStaff ID to record as the case's originating lawyer. Must also be one of the staff_ids in this call, or the call is refused.
contact_idsarray[integer]noContact IDs to associate
company_idsarray[integer]noCompany IDs to associate
billing_contact_idintegerno
outstanding_balancenumbernoAmount the client already owes on this case at the moment it is created, e.g. 2500.00 — MyCase stores it as the case's agreed flat fee and reads it back as outstanding_balance on get_case and list_cases. Setting it also sets the case's billing type to 'mixed' (hourly work plus a flat amount), so omit it to leave the firm's default billing configuration in place, and pass 0 only if you actually want a mixed-billing case with a zero balance. A negative value is rejected. Not available on update_case: it cannot be corrected through these tools once the case exists.
opened_datestringnoDate case was opened (ISO8601)
closed_datestringno
sol_datestringnoStatute of limitations date
custom_field_valuesstringnoValues for the custom fields that apply to a case, set on the new case. Pass a JSON array encoded as a string, e.g. '[{"custom_field":{"id":42},"value":"Acme"},{"custom_field":{"id":43},"value":"2026-01-05"}]' — each element is an object with a custom_field object holding the field's integer id plus that field's value. Get ids from list_custom_fields with filter_parent_type='case'; a field defined for another record type is rejected. Values go in as strings: dates as ISO8601 (YYYY-MM-DD), currency/numeric as decimal strings such as '1250.00', booleans as 'true'/'false', and a list field's value must match one of its options exactly (list_custom_field_options). A custom field may appear at most once per call — a repeated id is rejected. Case custom fields are also scoped by practice area, which list_custom_fields does not report: a value for a field that is not enabled for the practice area the case has after this call is rejected with a validation error naming that field. Drop that field and retry, and tell the user that field is not enabled for the case's practice area. A case with no practice area accepts every case field.

create_case_document

Create Case Document write beta

Create a new document record in a case's folder and get a presigned upload URL — step 1 of a two-step upload. This call sends metadata only (no file content). The response includes the new document's id plus top-level put_url and put_headers fields. Step 2: upload the file content yourself with an HTTP PUT of the raw bytes to put_url, sending every header in put_headers exactly as returned; if put_headers does not include a Content-Type, also send 'Content-Type: application/octet-stream' (the content type the URL is signed for). The document is visible via get_document or list_case_documents once created.

ParameterTypeRequiredDescription
case_idintegeryes
pathstringnoFolder path within the case's Documents folder, e.g. 'Pleadings' or 'Discovery/Depositions'; missing folders are created. Omit to file the document at the case root.
filenamestringyesDocument filename
descriptionstringno
assigned_datestringnoThe document's own date, as an ISO8601 date, e.g. '2026-01-05'. Despite the name this is the document's datestamp — the date the document itself carries — and NOT a date on which the document was assigned to anyone. Only ISO8601 parses: any other format, including the US-style 01/05/2026, is rejected with a 422, 'assigned_date is invalid'. This field is date-only: a full ISO8601 timestamp is accepted rather than rejected, but its time and offset are silently discarded instead of converted, so a UTC-normalized datetime can land on the wrong calendar day — send the bare date.

create_case_note

Create Case Note write beta

Create a note on a case.

ParameterTypeRequiredDescription
case_idintegeryes
notestringyesNote content
datestringyesNote date (ISO8601 date). MyCase requires it and has no default; for a note written now, pass today's date in the user's own time zone.
subjectstringno

create_case_status_update

Create Case Status Update write beta

Post a new Status update on a case: a short free-text write-up of where the matter stands, shown as the newest entry in the case's Status updates panel with the connected user as author. Firm-internal: clients never see them. Requires permission to edit the case. Like posting in MyCase, it adds a firm notification. Use list_case_status_updates to read the history, and create_case_note for a note with its own subject and date.

ParameterTypeRequiredDescription
case_idintegeryes
descriptionstringyesThe status update text, 500 characters at most. Leading and trailing whitespace is trimmed.

create_case_subfolder

Create Case Subfolder write beta

Create a subfolder in a case's document folder.

ParameterTypeRequiredDescription
case_idintegeryes
pathstringyesRelative path for the new subfolder

get_case

Get Case read-only

Get a specific case by ID. Includes the full staff roster (per-staff lead_lawyer, originating_lawyer, and rate details) and latest_status_update — the newest free-text status write-up firm staff keep on the matter, or null if there is none. Status updates are firm-internal: clients never see them, so do not quote one into client-facing text. Use list_case_status_updates for the full history. outstanding_balance is the case's full flat-fee amount (the same value as get_case_billing_summary's fee_structure.flat_fee): the agreed flat fee, or a balance entered when the case was created or imported. It does not go down as that fee is invoiced or paid, so do not report it as the current balance. For what is owed on a case, use get_case_billing_summary: unbilled.flat_fees is the part of the flat fee not yet invoiced, and totals.outstanding is the unpaid balance on the case's invoices. The Outstanding Balance Total on a MyCase client or company page adds both up across that contact's open cases, plus unpaid retainer requests, and leaves out draft invoices, which totals.outstanding includes (list_case_invoices shows each invoice's status and balance_due). A case that came from a converted lead keeps the lead's referral_source (name), referral_source_reference ({id}) and referred_by ({id} of the referring client or company; the id does not say which, so try get_client, then get_company). Each is null when the case did not come from a lead or the lead had no value for it; all three are omitted when the user cannot view leads.

ParameterTypeRequiredDescription
case_idintegeryes
field_clientarray[string]noClient fields to add to every nested client reference on the case — the contacts and clients entries, and billing_contact when the case is billed to a client. Nested records are returned as {id} only; each name listed here is added to them. This grows the response — it cannot be used to drop fields. Use it to read client details straight off the case instead of calling get_client once per client id. Cost: each field is serialized once per reference, so twice for every client on the case plus once more for its billing contact. Request only the fields you will use; id is always present. If your MyCase user cannot view clients, these names are not added and each nested client stays {id} only; the case fields themselves are unchanged. One of: id, first_name, last_name, middle_initial, middle_name, email, contact_group, birthdate, cell_phone_number, work_phone_number, home_phone_number, fax_phone_number, updated_at, created_at.

get_case_folder

Get Case Folder read-only

Get the root document folder for a case.

ParameterTypeRequiredDescription
case_idintegeryes

list_case_documents

List Case Documents read-only

List documents for a case.

ParameterTypeRequiredDescription
case_idintegeryes
filter_updated_afterstringno
page_sizeintegernoItems per page (default 25, max 1000)
page_tokenstringnopagination.next_page_token from the previous page. It carries that page's filters, so other args may be omitted; changing a filter mid-walk is rejected.

list_case_notes

List Case Notes read-only

List notes for a case. Case notes are a distinct record type from Status updates, with their own subject, date and archived state — use list_case_status_updates for the running status write-ups. For notes on a lead's potential case, use list_lead_notes.

ParameterTypeRequiredDescription
case_idintegeryes
filter_statusstringnoOne of: active, archived.
filter_updated_afterstringno
page_sizeintegernoItems per page (default 25, max 1000)
page_tokenstringnopagination.next_page_token from the previous page. It carries that page's filters, so other args may be omitted; changing a filter mid-walk is rejected.

list_case_roles

List Case Roles read-only

List all case roles.

ParameterTypeRequiredDescription
filter_updated_afterstringno
page_sizeintegernoItems per page (default 25, max 1000)
page_tokenstringnopagination.next_page_token from the previous page. It carries that page's filters, so other args may be omitted; changing a filter mid-walk is rejected.

list_case_status_updates

List Case Status Updates read-only

List a case's Status update history, newest first. These are the short free-text write-ups firm staff keep on a matter — outreach attempts, investigator contact details, next steps. Each carries its author and timestamps; updated_by is null until an update is edited. Firm-internal: clients never see them. get_case returns only the newest one. Not an audit trail: any staffer who can edit the case can overwrite an entry in place, and deleted entries leave no trace.

ParameterTypeRequiredDescription
case_idintegeryes
page_sizeintegernoItems per page (default 25, max 100)
page_tokenstringnopagination.next_page_token from the previous page. It carries that page's filters, so other args may be omitted; changing a filter mid-walk is rejected.

list_cases

List Cases read-only

List all cases. Supports filtering by status, updated_after, and text search. Each case carries a staff summary (staff_count and lead_lawyer) instead of the full staff roster, and office_reference ({id}) instead of the full office; use get_case for full staff assignments and office details, or get_firm for the firm's offices. outstanding_balance is the case's full flat-fee amount (the same value as get_case_billing_summary's fee_structure.flat_fee): the agreed flat fee, or a balance entered when the case was created or imported. It does not go down as that fee is invoiced or paid, so do not report it as the current balance. For what is owed on a case, use get_case_billing_summary: unbilled.flat_fees is the part of the flat fee not yet invoiced, and totals.outstanding is the unpaid balance on the case's invoices. The Outstanding Balance Total on a MyCase client or company page adds both up across that contact's open cases, plus unpaid retainer requests, and leaves out draft invoices, which totals.outstanding includes (list_case_invoices shows each invoice's status and balance_due). A case that came from a converted lead keeps the lead's referral_source (name), referral_source_reference ({id}) and referred_by ({id} of the referring client or company; the id does not say which, so try get_client, then get_company). Each is null when the case did not come from a lead or the lead had no value for it; all three are omitted when the user cannot view leads.

ParameterTypeRequiredDescription
filter_statusstringnoFilter by case status. One of: open, closed.
filter_updated_afterstringnoISO8601 datetime
search_starts_withstringnoText search on case name
field_clientarray[string]noClient fields to add to every nested client reference on each case — the contacts and clients entries, and billing_contact when the case is billed to a client. Nested records are returned as {id} only; each name listed here is added to them. This grows the response — it cannot be used to drop fields. Use it to read client details straight off a page of cases instead of calling get_client once per client id. Cost: each field is serialized once per reference, so twice for every client on the case plus once more for its billing contact — on a full page of cases, asking for six fields makes a very large response. Request only the fields you will use; id is always present. If your MyCase user cannot view clients, these names are not added and each nested client stays {id} only; the case fields themselves are unchanged. One of: id, first_name, last_name, middle_initial, middle_name, email, contact_group, birthdate, cell_phone_number, work_phone_number, home_phone_number, fax_phone_number, updated_at, created_at.
field_custom_fieldarray[string]noCustom-field attributes to add to the nested custom_field reference inside each custom_field_values entry. Nested records are returned as {id} only; each name listed here is added to them. This grows the response — it cannot be used to drop fields. field_type is the only value MyCase accepts here, so this widens {id} to {id, field_type} and no further — for a custom field's name, parent type, or list options, call get_custom_field or list_custom_fields. One of: field_type.
page_sizeintegernoItems per page (default 25, max 200)
page_tokenstringnopagination.next_page_token from the previous page. It carries that page's filters, so other args may be omitted; changing a filter mid-walk is rejected.

update_case

Update Case write destructive beta

Update an existing case. Each list param (client_ids, staff_ids, contact_ids, company_ids) REPLACES the case's full set of that association — any existing member not included in the list is removed from the case; omit a list param to leave that association unchanged. To add members without removing existing ones, use add_clients_to_case, add_staff_to_case, or add_companies_to_case. lead_lawyer_id and originating_lawyer_id work only alongside staff_ids, so setting either one also replaces the staff roster. custom_field_values is not one of these replace-in-full params: it is an upsert keyed on custom field id, so a field you include overwrites only that field, and a field you omit keeps its current value.

ParameterTypeRequiredDescription
case_idintegeryes
namestringno
case_numberstringno
descriptionstringno
statusstringnoOne of: open, closed.
case_stage_idintegerno
case_stage_namestringno
practice_area_idintegerno
practice_area_namestringno
office_idintegernoOffice ID to assign the case to. Find office IDs in get_firm's offices list. If omitted, the case's current office is left unchanged; unlike create_case, update does not assign the firm's primary office.
client_idsarray[integer]no
staff_idsarray[integer]no
lead_lawyer_idintegernoStaff ID to make the case's lead lawyer, taking the role from whoever holds it. Must also be one of the staff_ids in this call, or the call is refused. If the new holder is already on the case, MyCase can refuse the move with a 'can only be set for one user per case' error. Do not remove the current holder or drop them from staff_ids to get around it; tell the user to reassign the role in MyCase. Because staff_ids replaces the whole roster, list everyone who should stay on the case. To change only the role, use add_staff_to_case with just the new holder in staff_ids. Omit to leave the role unchanged.
originating_lawyer_idintegernoStaff ID to record as the case's originating lawyer, taking the role from whoever holds it. Must also be one of the staff_ids in this call, or the call is refused. If the new holder is already on the case, MyCase can refuse the move with a 'can only be set for one user per case' error. Do not remove the current holder or drop them from staff_ids to get around it; tell the user to reassign the role in MyCase. Because staff_ids replaces the whole roster, list everyone who should stay on the case. To change only the role, use add_staff_to_case with just the new holder in staff_ids. Omit to leave the role unchanged.
contact_idsarray[integer]no
company_idsarray[integer]no
billing_contact_idintegerno
opened_datestringno
closed_datestringno
sol_datestringno
custom_field_valuesstringnoValues for the custom fields that apply to this case. This is an UPSERT keyed on custom field id, not a replacement of the case's whole set: a field you include OVERWRITES its current value, and a field you OMIT is LEFT UNCHANGED. Omitting a field does not clear it, so send only the fields you are changing — do not re-send a field's existing value to preserve it, and omit the param entirely when you are changing no custom fields. Pass a JSON array encoded as a string, e.g. '[{"custom_field":{"id":42},"value":"Acme"},{"custom_field":{"id":43},"value":"2026-01-05"}]' — each element is an object with a custom_field object holding the field's integer id plus that field's value. Get ids from list_custom_fields with filter_parent_type='case'; a field defined for another record type is rejected. Values go in as strings: dates as ISO8601 (YYYY-MM-DD), currency/numeric as decimal strings such as '1250.00', booleans as 'true'/'false', and a list field's value must match one of its options exactly (list_custom_field_options). A custom field may appear at most once per call — a repeated id is rejected. Case custom fields are also scoped by practice area, which list_custom_fields does not report: a value for a field that is not enabled for the practice area the case has after this call is rejected with a validation error naming that field. Drop that field and retry, and tell the user that field is not enabled for the case's practice area. A case with no practice area accepts every case field.

Chats

list_case_chat_conversations

List Case Chat Conversations read-only

List the firm's internal staff chat conversations linked to a case. This is staff-to-staff chat inside the firm — NOT client messaging: secure client-portal threads are a separate surface, read with list_message_threads / list_thread_messages. Returns conversation metadata only (id, name, description, conversation_type, private_conversation, created_by, created_at, updated_at, last_message_at); message bodies are NOT included — pass a conversation's id to list_chat_conversation_messages to read them. Use last_message_at to pick the active channel BEFORE fetching messages, rather than calling the messages tool once per conversation. Read it precisely: it is the newest updated_at across the messages the companion tool serves (text and announcement, not reactions), so EDITING an old message advances it. It is last activity, NOT when the last thing was said — do not report it to the user as the most recent message's send time. Two limits worth stating to the user rather than reading past: only conversations the CALLER is an active participant in are returned, so an empty list means 'none you are in', not 'none on this case'; and only case-linked channels are reachable at all, so firm-wide channels and direct messages between staff are invisible to this tool no matter who asks. Archived conversations are excluded. Participant lists are not exposed, so this cannot answer who is in a channel.

ParameterTypeRequiredDescription
case_idintegeryes
filter_updated_afterstringnoMatches conversations whose metadata OR whose messages changed strictly after this ISO8601 timestamp (exclusive bound), so a new message surfaces its conversation; a timestamp with no UTC offset is read as UTC. Only readable messages count as message activity: an emoji reaction does not surface its conversation here, matching the text-and-announcement messages list_chat_conversation_messages serves for the same filter.
page_sizeintegernoItems per page (default 25, max 1000)
page_tokenstringnopagination.next_page_token from the previous page. It carries that page's filters, so other args may be omitted; changing a filter mid-walk is rejected.

list_chat_conversation_messages

List Chat Conversation Messages read-only

Read the messages in one internal staff chat conversation in insertion order — ascending id, the order rows were stored — which is NOT a guaranteed chronological sort. The two agree for live chat and diverge for backdated or imported history, so when chronology matters, sort on the created_at each message already carries. Get the conversation's id from list_case_chat_conversations. Returns what people actually said — posted messages and system announcements such as someone joining a channel; emoji reactions are excluded, matching what the MyCase chat thread itself shows. Each message carries its author, timestamp, and reply_to_message_id for threaded replies. Returns 404 if the conversation does not exist on that case OR the caller is not an active participant in it — the two are deliberately indistinguishable, so do not report a 404 as proof the conversation does not exist. Busy channels run long; page with page_size and page_token rather than assuming one call is the whole history.

ParameterTypeRequiredDescription
case_idintegeryes
chat_conversation_idintegeryes
filter_updated_afterstringnoOnly messages whose own updated_at is strictly after this ISO8601 timestamp (exclusive bound); a timestamp with no UTC offset is read as UTC, and a non-ISO8601 value is rejected upstream.
page_sizeintegernoItems per page (default 25, max 1000)
page_tokenstringnopagination.next_page_token from the previous page. It carries that page's filters, so other args may be omitted; changing a filter mid-walk is rejected.

Clients

create_client

Create Client write beta

Create a new client in MyCase. To set an address, supply all five of address_street, address_city, address_state, address_zip_code, and address_country together (address_street2 is optional — include it only for a second line); a partial address is rejected.

ParameterTypeRequiredDescription
first_namestringyes
last_namestringyes
emailstringno
middle_namestringnoMiddle name or initial, up to 60 characters. MyCase keeps one middle-name field per person: client responses carry it as both middle_name and middle_initial, and leads and staff call it middle_initial.
cell_phone_numberstringno
work_phone_numberstringno
home_phone_numberstringno
fax_phone_numberstringno
notesstringno
birthdatestringnoDate of birth as an ISO8601 date, e.g. '1979-04-23'. Two rejections to avoid, both returned as a 422: any other format (only ISO8601 parses), and a date that is not already past — today itself is rejected, not just future dates, with 'must be in the past.' This field is date-only: a full ISO8601 timestamp is accepted rather than rejected, but its time and offset are silently discarded instead of converted, so a UTC-normalized datetime can land on the wrong calendar day — send the bare date.
people_group_idintegernoPeople group ID
contact_groupstringnoPeople group to file the client under, given by NAME — the same groups list_people_groups returns, matched on the trimmed, case-insensitive name. An unrecognized name is NOT rejected: MyCase silently files the client under the firm's default 'client' group instead, so confirm the name with list_people_groups first, or use people_group_id, which does reject an id the firm does not have. Mutually exclusive with people_group_id — sending both is rejected. An empty or blank string is treated as omitting the param. Omit both this and people_group_id and the new client is filed under the firm's default 'client' group.
case_idsarray[integer]noCase IDs to associate
address_streetstringno
address_street2stringno
address_citystringno
address_statestringno
address_zip_codestringno
address_countrystringno
custom_field_valuesstringnoValues for the custom fields that apply to a client, set on the new client. Pass a JSON array encoded as a string, e.g. '[{"custom_field":{"id":42},"value":"Acme"},{"custom_field":{"id":43},"value":"2026-01-05"}]' — each element is an object with a custom_field object holding the field's integer id plus that field's value. Get ids from list_custom_fields with filter_parent_type='client'; a field defined for another record type is rejected. Values go in as strings: dates as ISO8601 (YYYY-MM-DD), currency/numeric as decimal strings such as '1250.00', booleans as 'true'/'false', and a list field's value must match one of its options exactly (list_custom_field_options). A custom field may appear at most once per call — a repeated id is rejected.

create_client_note

Create Client Note write beta

Create a note on a client.

ParameterTypeRequiredDescription
client_idintegeryes
notestringyesNote content
datestringyesNote date (ISO8601 date). MyCase requires it and has no default; for a note written now, pass today's date in the user's own time zone.
subjectstringno

get_client

Get Client read-only

Get a specific client by ID. A client that came from a converted lead keeps the lead's referral_source (name), referral_source_reference ({id}) and referred_by ({id} of the referring client or company; the id does not say which, so try get_client, then get_company). Each is null when the client did not come from a lead or the lead had no value for it; all three are omitted when the user cannot view leads.

ParameterTypeRequiredDescription
client_idintegeryes

list_client_cases

List Client Cases read-only

List cases for a specific client. outstanding_balance is the case's full flat-fee amount (the same value as get_case_billing_summary's fee_structure.flat_fee): the agreed flat fee, or a balance entered when the case was created or imported. It does not go down as that fee is invoiced or paid, so do not report it as the current balance. For what is owed on a case, use get_case_billing_summary: unbilled.flat_fees is the part of the flat fee not yet invoiced, and totals.outstanding is the unpaid balance on the case's invoices. The Outstanding Balance Total on a MyCase client or company page adds both up across that contact's open cases, plus unpaid retainer requests, and leaves out draft invoices, which totals.outstanding includes (list_case_invoices shows each invoice's status and balance_due).

ParameterTypeRequiredDescription
client_idintegeryes
filter_statusstringnoOne of: open, closed.
filter_updated_afterstringno
field_clientarray[string]noClient fields to add to every nested client reference on each case — the contacts and clients entries, and billing_contact when the case is billed to a client. Nested records are returned as {id} only; each name listed here is added to them. This grows the response — it cannot be used to drop fields. Use it to read client details straight off a page of cases instead of calling get_client once per client id. Cost: each field is serialized once per reference, so twice for every client on the case plus once more for its billing contact — on a full page of cases, asking for six fields makes a very large response. Request only the fields you will use; id is always present. If your MyCase user cannot view clients, this tool is refused outright: it resolves a client by id before reading any cases. One of: id, first_name, last_name, middle_initial, middle_name, email, contact_group, birthdate, cell_phone_number, work_phone_number, home_phone_number, fax_phone_number, updated_at, created_at.
field_custom_fieldarray[string]noCustom-field attributes to add to the nested custom_field reference inside each custom_field_values entry. Nested records are returned as {id} only; each name listed here is added to them. This grows the response — it cannot be used to drop fields. field_type is the only value MyCase accepts here, so this widens {id} to {id, field_type} and no further — for a custom field's name, parent type, or list options, call get_custom_field or list_custom_fields. One of: field_type.
page_sizeintegernoItems per page (default 25, max 200)
page_tokenstringnopagination.next_page_token from the previous page. It carries that page's filters, so other args may be omitted; changing a filter mid-walk is rejected.

list_client_message_threads

List Client Message Threads read-only

List message threads for a client.

ParameterTypeRequiredDescription
client_idintegeryes
filter_updated_afterstringno
page_sizeintegernoItems per page (default 25, max 1000)
page_tokenstringnopagination.next_page_token from the previous page. It carries that page's filters, so other args may be omitted; changing a filter mid-walk is rejected.

list_client_notes

List Client Notes read-only

List notes for a client.

ParameterTypeRequiredDescription
client_idintegeryes
filter_statusstringnoOne of: active, archived.
filter_updated_afterstringno
page_sizeintegernoItems per page (default 25, max 1000)
page_tokenstringnopagination.next_page_token from the previous page. It carries that page's filters, so other args may be omitted; changing a filter mid-walk is rejected.

list_clients

List Clients read-only

List all clients. Supports filtering by name, email, phone, and text search. A client that came from a converted lead keeps the lead's referral_source (name), referral_source_reference ({id}) and referred_by ({id} of the referring client or company; the id does not say which, so try get_client, then get_company). Each is null when the client did not come from a lead or the lead had no value for it; all three are omitted when the user cannot view leads.

ParameterTypeRequiredDescription
filter_updated_afterstringno
filter_emailstringno
filter_first_namestringno
filter_last_namestringno
filter_cell_phone_numberstringno
filter_work_phone_numberstringno
filter_home_phone_numberstringno
filter_fax_phone_numberstringno
search_starts_withstringno
field_custom_fieldarray[string]noCustom-field attributes to add to the nested custom_field reference inside each custom_field_values entry. Nested records are returned as {id} only; each name listed here is added to them. This grows the response — it cannot be used to drop fields. field_type is the only value MyCase accepts here, so this widens {id} to {id, field_type} and no further — for a custom field's name, parent type, or list options, call get_custom_field or list_custom_fields. One of: field_type.
page_sizeintegernoItems per page (default 25, max 1000)
page_tokenstringnopagination.next_page_token from the previous page. It carries that page's filters, so other args may be omitted; changing a filter mid-walk is rejected.

update_client

Update Client write destructive beta

Update an existing client. case_ids REPLACES the client's full set of case associations — cases not included are unlinked; omit it to leave case associations unchanged. To add this client to one case without touching their other cases, use add_clients_to_case instead. To change the address, supply all five of address_street, address_city, address_state, address_zip_code, and address_country together; a partial address is rejected. Changing the address REPLACES it in full — include address_street2 to keep an existing second line, since omitting it clears any current second line. Omit all address fields to leave the existing address unchanged. custom_field_values is not one of these replace-in-full params: it is an upsert keyed on custom field id, so a field you include overwrites only that field, and a field you omit keeps its current value.

ParameterTypeRequiredDescription
client_idintegeryes
first_namestringno
last_namestringno
emailstringno
middle_namestringnoMiddle name or initial, up to 60 characters. MyCase keeps one middle-name field per person: client responses carry it as both middle_name and middle_initial, and leads and staff call it middle_initial.
cell_phone_numberstringno
work_phone_numberstringno
home_phone_numberstringno
fax_phone_numberstringno
notesstringno
birthdatestringnoDate of birth as an ISO8601 date, e.g. '1979-04-23'. Two rejections to avoid, both returned as a 422: any other format (only ISO8601 parses), and a date that is not already past — today itself is rejected, not just future dates, with 'must be in the past.' This field is date-only: a full ISO8601 timestamp is accepted rather than rejected, but its time and offset are silently discarded instead of converted, so a UTC-normalized datetime can land on the wrong calendar day — send the bare date.
people_group_idintegernoPeople group ID
contact_groupstringnoPeople group to file the client under, given by NAME — the same groups list_people_groups returns, matched on the trimmed, case-insensitive name. An unrecognized name is NOT rejected: MyCase silently files the client under the firm's default 'client' group instead, so confirm the name with list_people_groups first, or use people_group_id, which does reject an id the firm does not have. Mutually exclusive with people_group_id — sending both is rejected. An empty or blank string is treated as omitting the param. Omit it to leave the client's current group unchanged.
case_idsarray[integer]no
address_streetstringno
address_street2stringno
address_citystringno
address_statestringno
address_zip_codestringno
address_countrystringno
custom_field_valuesstringnoValues for the custom fields that apply to this client. This is an UPSERT keyed on custom field id, not a replacement of the client's whole set: a field you include OVERWRITES its current value, and a field you OMIT is LEFT UNCHANGED. Omitting a field does not clear it, so send only the fields you are changing — do not re-send a field's existing value to preserve it, and omit the param entirely when you are changing no custom fields. Pass a JSON array encoded as a string, e.g. '[{"custom_field":{"id":42},"value":"Acme"},{"custom_field":{"id":43},"value":"2026-01-05"}]' — each element is an object with a custom_field object holding the field's integer id plus that field's value. Get ids from list_custom_fields with filter_parent_type='client'; a field defined for another record type is rejected. Values go in as strings: dates as ISO8601 (YYYY-MM-DD), currency/numeric as decimal strings such as '1250.00', booleans as 'true'/'false', and a list field's value must match one of its options exactly (list_custom_field_options). A custom field may appear at most once per call — a repeated id is rejected.

Comments

list_case_comments

List Case Comments read-only

List the comments left on a case's records — the internal comment threads MyCase shows on tasks, documents, and calendar events. These are staff commentary attached to a record, NOT client-portal messages (list_message_threads / list_thread_messages), NOT case notes (list_case_notes), and NOT internal staff chat (list_case_chat_conversations). Each comment returns comment_text, the author's name, created_at/updated_at, its own id, a type of TaskComment / DocumentComment / AppointmentComment, and a parent anchor {type, id} naming the record it sits on — open a Task or Document parent with get_task or get_document. No tool opens an Appointment parent: its id names a single calendar occurrence, not an event, so passing it to get_event 404s or returns an unrelated event. Quote parent.id rather than the comment's own id when telling the user which record is being discussed. All three kinds come back interleaved, oldest first by insertion order (ascending id); narrow to one kind with filter_comment_type. Comments deleted in MyCase are excluded. An empty list means 'none you can see', not 'none on this case': what is returned follows your own MyCase permissions, and comments on calendar events are limited to events you are a participant on.

ParameterTypeRequiredDescription
case_idintegeryes
filter_comment_typestringnoReturn only comments on one kind of parent record. The values are the parent's lowercase name, so 'appointment' means a calendar event and selects the rows whose parent.type comes back as 'Appointment'. Omit it for all three kinds. One of: task, document, appointment.
filter_updated_afterstringnoOnly comments whose own updated_at is strictly after this ISO8601 timestamp (exclusive bound); a timestamp with no UTC offset is read as UTC, and a non-ISO8601 value is rejected upstream.
page_sizeintegernoItems per page (default 25, max 1000)
page_tokenstringnopagination.next_page_token from the previous page. It carries that page's filters, so other args may be omitted; changing a filter mid-walk is rejected.

Companies

add_clients_to_company

Add Clients To Company write beta

Add clients to a company. Additive — existing linked clients are preserved (unlike update_company, whose client_ids replaces).

ParameterTypeRequiredDescription
company_idintegeryes
client_idsarray[integer]yesClient IDs to add

create_company

Create Company write beta

Create a new company in MyCase. To set an address, supply all five of address_street, address_city, address_state, address_zip_code, and address_country together (address_street2 is optional — include it only for a second line); a partial address is rejected.

ParameterTypeRequiredDescription
namestringyesCompany name
websitestringno
emailstringno
fax_phone_numberstringno
main_phone_numberstringno
notesstringno
client_idsarray[integer]noClient IDs to associate
case_idsarray[integer]noCase IDs to associate
address_streetstringno
address_street2stringno
address_citystringno
address_statestringno
address_zip_codestringno
address_countrystringno
custom_field_valuesstringnoValues for the custom fields that apply to a company, set on the new company. Pass a JSON array encoded as a string, e.g. '[{"custom_field":{"id":42},"value":"Acme"},{"custom_field":{"id":43},"value":"2026-01-05"}]' — each element is an object with a custom_field object holding the field's integer id plus that field's value. Get ids from list_custom_fields with filter_parent_type='company'; a field defined for another record type is rejected. Values go in as strings: dates as ISO8601 (YYYY-MM-DD), currency/numeric as decimal strings such as '1250.00', booleans as 'true'/'false', and a list field's value must match one of its options exactly (list_custom_field_options). A custom field may appear at most once per call — a repeated id is rejected.

create_company_note

Create Company Note write beta

Create a note on a company.

ParameterTypeRequiredDescription
company_idintegeryes
notestringyes
datestringyesNote date (ISO8601 date). MyCase requires it and has no default; for a note written now, pass today's date in the user's own time zone.
subjectstringno

get_company

Get Company read-only

Get a specific company by ID.

ParameterTypeRequiredDescription
company_idintegeryes

list_companies

List Companies read-only

List all companies. Supports filtering by status, name, email, phone, and text search.

ParameterTypeRequiredDescription
filter_statusstringnoFilter by company status. One of: active, archived.
filter_updated_afterstringno
filter_emailstringno
filter_namestringno
filter_fax_phone_numberstringno
filter_main_phone_numberstringno
search_starts_withstringno
field_custom_fieldarray[string]noCustom-field attributes to add to the nested custom_field reference inside each custom_field_values entry. Nested records are returned as {id} only; each name listed here is added to them. This grows the response — it cannot be used to drop fields. field_type is the only value MyCase accepts here, so this widens {id} to {id, field_type} and no further — for a custom field's name, parent type, or list options, call get_custom_field or list_custom_fields. One of: field_type.
page_sizeintegernoItems per page (default 25, max 1000)
page_tokenstringnopagination.next_page_token from the previous page. It carries that page's filters, so other args may be omitted; changing a filter mid-walk is rejected.

list_company_notes

List Company Notes read-only

List notes for a company.

ParameterTypeRequiredDescription
company_idintegeryes
filter_statusstringnoOne of: active, archived.
filter_updated_afterstringno
page_sizeintegernoItems per page (default 25, max 1000)
page_tokenstringnopagination.next_page_token from the previous page. It carries that page's filters, so other args may be omitted; changing a filter mid-walk is rejected.

update_company

Update Company write destructive beta

Update an existing company. client_ids and case_ids each REPLACE the company's full set of that association — members not included are removed; omit a list param to leave that association unchanged. To add without removing existing ones, use add_clients_to_company (clients) or add_companies_to_case (cases). To change the address, supply all five of address_street, address_city, address_state, address_zip_code, and address_country together; a partial address is rejected. Changing the address REPLACES it in full — include address_street2 to keep an existing second line, since omitting it clears any current second line. Omit all address fields to leave the existing address unchanged. custom_field_values is not one of these replace-in-full params: it is an upsert keyed on custom field id, so a field you include overwrites only that field, and a field you omit keeps its current value.

ParameterTypeRequiredDescription
company_idintegeryes
namestringno
websitestringno
emailstringno
fax_phone_numberstringno
main_phone_numberstringno
notesstringno
client_idsarray[integer]no
case_idsarray[integer]no
address_streetstringno
address_street2stringno
address_citystringno
address_statestringno
address_zip_codestringno
address_countrystringno
custom_field_valuesstringnoValues for the custom fields that apply to this company. This is an UPSERT keyed on custom field id, not a replacement of the company's whole set: a field you include OVERWRITES its current value, and a field you OMIT is LEFT UNCHANGED. Omitting a field does not clear it, so send only the fields you are changing — do not re-send a field's existing value to preserve it, and omit the param entirely when you are changing no custom fields. Pass a JSON array encoded as a string, e.g. '[{"custom_field":{"id":42},"value":"Acme"},{"custom_field":{"id":43},"value":"2026-01-05"}]' — each element is an object with a custom_field object holding the field's integer id plus that field's value. Get ids from list_custom_fields with filter_parent_type='company'; a field defined for another record type is rejected. Values go in as strings: dates as ISO8601 (YYYY-MM-DD), currency/numeric as decimal strings such as '1250.00', booleans as 'true'/'false', and a list field's value must match one of its options exactly (list_custom_field_options). A custom field may appear at most once per call — a repeated id is rejected.

Contacts

list_contacts

List Contacts read-only

List all contacts (clients, companies, leads) across the firm.

ParameterTypeRequiredDescription
filter_updated_afterstringno
page_sizeintegernoItems per page (default 25, max 1000)
page_tokenstringnopagination.next_page_token from the previous page. It carries that page's filters, so other args may be omitted; changing a filter mid-walk is rejected.

Custom Fields

create_custom_field

Create Custom Field write beta

Create a new custom field definition.

ParameterTypeRequiredDescription
namestringyesField name
field_typestringyesOne of: boolean, currency, date, list, long_text, numeric, short_text.
parent_typestringyesOne of: case, client, company, expense, time, time_and_expense.
option_valuesarray[string]noOption values — required when field_type is 'list', omit otherwise

create_custom_field_options

Create Custom Field Options write beta

Add one or more options to a list-type custom field in one call. To rename a single existing option, use update_custom_field_option.

ParameterTypeRequiredDescription
custom_field_idintegeryes
option_valuesarray[string]yesOption values to add

get_custom_field

Get Custom Field read-only

Get a specific custom field definition by ID.

ParameterTypeRequiredDescription
custom_field_idintegeryes

list_custom_field_options

List Custom Field Options read-only

List options for a list-type custom field.

ParameterTypeRequiredDescription
custom_field_idintegeryes
page_sizeintegernoItems per page (default 25, max 1000)
page_tokenstringnopagination.next_page_token from the previous page. It carries that page's filters, so other args may be omitted; changing a filter mid-walk is rejected.

list_custom_fields

List Custom Fields read-only

List all custom field definitions.

ParameterTypeRequiredDescription
filter_parent_typestringnoOne of: case, client, company, expense, time, time_and_expense.
filter_updated_afterstringno
page_sizeintegernoItems per page (default 25, max 1000)
page_tokenstringnopagination.next_page_token from the previous page. It carries that page's filters, so other args may be omitted; changing a filter mid-walk is rejected.

update_custom_field

Update Custom Field write destructive beta

Rename a custom field definition. Only the name can be changed; a list field's options are preserved (use update_custom_field_option to change an option's value).

ParameterTypeRequiredDescription
custom_field_idintegeryes
namestringyesNew field name

update_custom_field_option

Update Custom Field Option write destructive beta

Update one existing option on a list-type custom field. To add new options, use create_custom_field_options, which takes a list.

ParameterTypeRequiredDescription
custom_field_idintegeryes
option_idintegeryes
option_valuestringyesNew option value

Documents

create_document

Create Document write beta

Create a new document record and get a presigned upload URL — step 1 of a two-step upload. This call sends metadata only (no file content). The response includes the new document's id plus top-level put_url and put_headers fields. Step 2: upload the file content yourself with an HTTP PUT of the raw bytes to put_url, sending every header in put_headers exactly as returned; if put_headers does not include a Content-Type, also send 'Content-Type: application/octet-stream' (the content type the URL is signed for). The document is visible via get_document once created.

ParameterTypeRequiredDescription
pathstringnoFolder path in the firm's Documents storage, e.g. 'Templates'; missing folders are created. Omit to file the document at the firm's root folder.
filenamestringyes
descriptionstringno
staff_idsarray[integer]noStaff IDs to assign
assigned_datestringnoThe document's own date, as an ISO8601 date, e.g. '2026-01-05'. Despite the name this is the document's datestamp — the date the document itself carries — and NOT a date on which the document was assigned to anyone. Only ISO8601 parses: any other format, including the US-style 01/05/2026, is rejected with a 422, 'assigned_date is invalid'. This field is date-only: a full ISO8601 timestamp is accepted rather than rejected, but its time and offset are silently discarded instead of converted, so a UTC-normalized datetime can land on the wrong calendar day — send the bare date.

create_document_version

Create Document Version write beta

Create a new version of an existing document and get a presigned upload URL — step 1 of a two-step upload. Takes no body params: the new version keeps the document's current filename, and its file content comes from step 2. The response includes the new version's id and version number plus top-level put_url and put_headers fields. Step 2: upload the file content yourself with an HTTP PUT of the raw bytes to put_url, sending every header in put_headers exactly as returned; if put_headers does not include a Content-Type, also send 'Content-Type: application/octet-stream' (the content type the URL is signed for). Verify with list_document_versions.

ParameterTypeRequiredDescription
document_idintegeryes

download_document

Download Document read-only

Get the raw file content of a document. Returns a short-lived presigned download URL (redirect_url) to the raw file in storage; if you cannot fetch URLs, pass stream_content=true to receive the bytes in this response instead, in chunks — UTF-8 text as text, anything else base64. The file is returned as-is — for server-extracted text, use get_document_text instead.

ParameterTypeRequiredDescription
document_idintegeryes
stream_contentbooleannoSet true to have the server fetch the file and return its content in this response instead of a URL — use it when you cannot fetch URLs yourself. Content arrives one chunk per call: UTF-8 text as encoding 'utf-8' in 'text', anything else (including text in other charsets) as encoding 'base64' in 'data', with content_type, content_length and filename alongside. encoding is classified from each chunk's own bytes, so re-read it on every chunk rather than assuming the first chunk's value holds. Each base64 chunk is padded on its own: decode every chunk's data separately and join the bytes, never the strings. When next_offset is a number, call again with offset set to it for the next chunk; null means the file is complete.
offsetintegernoByte offset to start the chunk at — pass the previous response's next_offset. Default 0. Only valid with stream_content=true.
max_bytesintegernoChunk size ceiling in bytes (default 65536, max 1048576). Only valid with stream_content=true.

download_document_version

Download Document Version read-only

Get the raw file content of a specific document version. Returns a short-lived presigned download URL (redirect_url) to the raw file in storage; if you cannot fetch URLs, pass stream_content=true to receive the bytes in this response instead, in chunks — UTF-8 text as text, anything else base64. The file is returned as-is — for server-extracted text of the latest parsed version, use get_document_text instead.

ParameterTypeRequiredDescription
document_idintegeryes
version_numberintegeryes
stream_contentbooleannoSet true to have the server fetch the file and return its content in this response instead of a URL — use it when you cannot fetch URLs yourself. Content arrives one chunk per call: UTF-8 text as encoding 'utf-8' in 'text', anything else (including text in other charsets) as encoding 'base64' in 'data', with content_type, content_length and filename alongside. encoding is classified from each chunk's own bytes, so re-read it on every chunk rather than assuming the first chunk's value holds. Each base64 chunk is padded on its own: decode every chunk's data separately and join the bytes, never the strings. When next_offset is a number, call again with offset set to it for the next chunk; null means the file is complete.
offsetintegernoByte offset to start the chunk at — pass the previous response's next_offset. Default 0. Only valid with stream_content=true.
max_bytesintegernoChunk size ceiling in bytes (default 65536, max 1048576). Only valid with stream_content=true.

get_document

Get Document read-only

Get document metadata by ID. Returns metadata only — use download_document for the raw file or get_document_text for extracted text.

ParameterTypeRequiredDescription
document_idintegeryes

get_document_text

Get Document Text read-only

Get server-extracted plain text for a document. Returns a short-lived URL to the extracted text plus metadata (content_length, page_count, parsed_at). Fetch the URL promptly with your available tools — it expires in about 5 minutes and serves text/plain. If you cannot fetch URLs, pass stream_content=true to receive the text in this response instead, in chunks (follow next_offset). For large documents, prefer downloading and searching locally over reading the whole text into context. Text reflects the document version current when it was parsed (see parsed_at); newly uploaded versions are not re-extracted. When no extracted text exists, returns not_found with a detail field — error 'no_parsed_text' plus a parsing_status. When that status is 'not_parsed', a detail parsing_enabled of false means text extraction is not enabled for this firm and no parse will ever run: do not retry, and use download_document for the raw file instead. Otherwise 'not_parsed' means extraction has not completed for the current version and may still be in progress for a recently uploaded document; 'deferred_parser', 'quota_blocked_backparse' and 'quota_blocked_new_upload' are also still awaiting a parse (retry later). Every other status — 'failed', 'unparseable', 'not_supported', 'scanned', 'ocr_disabled', 'large_document', 'old_document', and 'parsed' when its extracted text object is missing — will not change on retry: use download_document for the raw file instead. Detail error 'not_found' means the document itself does not exist.

ParameterTypeRequiredDescription
document_idintegeryes
stream_contentbooleannoSet true to have the server fetch the file and return its content in this response instead of a URL — use it when you cannot fetch URLs yourself. Content arrives one chunk per call: UTF-8 text as encoding 'utf-8' in 'text', anything else (including text in other charsets) as encoding 'base64' in 'data', with content_type, content_length and filename alongside. encoding is classified from each chunk's own bytes, so re-read it on every chunk rather than assuming the first chunk's value holds. Each base64 chunk is padded on its own: decode every chunk's data separately and join the bytes, never the strings. When next_offset is a number, call again with offset set to it for the next chunk; null means the file is complete.
offsetintegernoByte offset to start the chunk at — pass the previous response's next_offset. Default 0. Only valid with stream_content=true.
max_bytesintegernoChunk size ceiling in bytes (default 65536, max 1048576). Only valid with stream_content=true.

list_document_versions

List Document Versions read-only

List all versions of a document.

ParameterTypeRequiredDescription
document_idintegeryes
filter_updated_afterstringno
page_sizeintegernoItems per page (default 25, max 1000)
page_tokenstringnopagination.next_page_token from the previous page. It carries that page's filters, so other args may be omitted; changing a filter mid-walk is rejected.

list_documents

List Documents read-only

List all documents across the firm. Returns document metadata only — use get_document_text for extracted text or download_document for the raw file.

ParameterTypeRequiredDescription
filter_updated_afterstringno
page_sizeintegernoItems per page (default 25, max 1000)
page_tokenstringnopagination.next_page_token from the previous page. It carries that page's filters, so other args may be omitted; changing a filter mid-walk is rejected.

list_folder_documents

List Folder Documents read-only

List documents within a folder.

ParameterTypeRequiredDescription
folder_idintegeryes
filter_updated_afterstringno
page_sizeintegernoItems per page (default 25, max 1000)
page_tokenstringnopagination.next_page_token from the previous page. It carries that page's filters, so other args may be omitted; changing a filter mid-walk is rejected.

list_folder_subfolders

List Folder Subfolders read-only

List subfolders within a folder.

ParameterTypeRequiredDescription
folder_idintegeryes
filter_updated_afterstringno
page_sizeintegernoItems per page (default 25, max 1000)
page_tokenstringnopagination.next_page_token from the previous page. It carries that page's filters, so other args may be omitted; changing a filter mid-walk is rejected.

update_document

Update Document write destructive beta

Update document metadata. staff_ids REPLACES the document's full assigned-staff list — staff not included are unassigned; omit it to leave staff unchanged. Staff cannot be updated on a document that belongs to a case.

ParameterTypeRequiredDescription
document_idintegeryes
pathstringnoNew folder path for the document, e.g. 'Templates/Retainers'; missing folders are created. Omit to leave the document in its current folder — unlike create_document, omitting it here does NOT move the document to the root.
filenamestringno
descriptionstringno
staff_idsarray[integer]no
assigned_datestringnoThe document's own date, as an ISO8601 date, e.g. '2026-01-05'. Despite the name this is the document's datestamp — the date the document itself carries — and NOT a date on which the document was assigned to anyone. Only ISO8601 parses: any other format, including the US-style 01/05/2026, is rejected with a 422, 'assigned_date is invalid'. This field is date-only: a full ISO8601 timestamp is accepted rather than rejected, but its time and offset are silently discarded instead of converted, so a UTC-normalized datetime can land on the wrong calendar day — send the bare date.

Events

add_staff_to_event

Add Staff To Event write beta

Add staff members to an event. Additive — existing attendees are preserved (unlike update_event, whose staff_ids replaces). New attendees join as optional unless listed in required_staff_ids, and staff already on the event keep their current setting. A recurring event cannot be updated with this tool, because the change would apply to every occurrence; edit its attendees in the MyCase app.

ParameterTypeRequiredDescription
event_idintegeryes
staff_idsarray[integer]yesStaff IDs to add
required_staff_idsarray[integer]noStaff IDs, all also in staff_ids, who must attend (the Attend box in MyCase). When you pass it, every other staff_ids entry is marked optional. That includes anyone already on the event whom you list again; leave them out of staff_ids to keep their setting.

create_event

Create Event write beta

Create a new calendar event. Timed events' start/end are instants, returned in UTC (Z); show them to the user in get_me's time_zone. All-day events' start/end are calendar dates (YYYY-MM-DD) with no zone, and end is the last day, inclusive.

ParameterTypeRequiredDescription
namestringyesEvent name
startstringyesStart (ISO8601). Timed: a local time with the UTC offset get_me's time_zone has on that date, e.g. 2026-09-29T18:30:00-06:00 (Denver in summer; -07:00 in winter); a time without an offset is read as UTC. All-day (all_day=true): the calendar date, e.g. 2026-09-29; any time or offset is dropped, not converted.
endstringyesEnd (ISO8601), same format as start. All-day: the last day, inclusive, so a one-day event has end equal to start.
staff_idsarray[integer]yesStaff member IDs to invite
required_staff_idsarray[integer]noStaff IDs, all also in staff_ids, who must attend (the Attend box in MyCase). When you pass it, every other staff_ids entry is marked optional. Omit it and every attendee is optional.
case_idintegernoAssociated case ID
location_idintegernoLocation ID
all_daybooleannoWhether this is an all-day event

get_event

Get Event read-only

Get a specific event by ID. When starting from a full_text_search result, pass its appointment_rule_id — an event search result's id identifies a single occurrence on the calendar, drawn from a different table, so passing it here usually 404s and can otherwise return an unrelated event. Each staff entry carries required: true for an attendee who must attend. Timed events' start/end are instants, returned in UTC (Z); show them to the user in get_me's time_zone. All-day events' start/end are calendar dates (YYYY-MM-DD) with no zone, and end is the last day, inclusive.

ParameterTypeRequiredDescription
event_idintegeryes

list_events

List Events read-only

List all calendar events. Use filter_occurs_after/filter_occurs_before to answer calendar questions -- without them (and without filter_updated_after) this returns the firm's whole history, most recently updated first. The pair is an overlap window: an event running across it is returned even though it started earlier, so a multi-day trial or filing period is covered as well as all-day and timed events. Bounds are inclusive. A recurring event matches on its own dates only, not on its later occurrences. filter_staff_id matches the staff array. Each staff entry carries required: true for an attendee who must attend. Timed events' start/end are instants, returned in UTC (Z); show them to the user in get_me's time_zone. All-day events' start/end are calendar dates (YYYY-MM-DD) with no zone, and end is the last day, inclusive. For a day or week, write both bounds as the user's local times with the UTC offset get_me's time_zone has on those dates, e.g. 2026-09-29T00:00:00-06:00 to 2026-09-29T23:59:59-06:00, not converted to Z: all-day events are matched on the date each bound is written in, so a Z-converted end bound also returns the next day's all-day events.

ParameterTypeRequiredDescription
filter_updated_afterstringno
filter_occurs_afterstringnoOnly events still running at or after this ISO8601 datetime -- compares the event's end, so one that began earlier still matches; the bound is inclusive. Write it in the user's local offset, not converted to Z; a time without an offset is read as UTC
filter_occurs_beforestringnoOnly events that begin at or before this ISO8601 datetime; the bound is inclusive. Send it WITH filter_occurs_after -- on its own it also matches every older event, because anything that started earlier also begins before this bound. Write it in the user's local offset, not converted to Z; a time without an offset is read as UTC
filter_staff_idintegernoOnly events this staff member is on (see list_staff)
page_sizeintegernoItems per page (default 25, max 1000)
page_tokenstringnopagination.next_page_token from the previous page. It carries that page's filters, so other args may be omitted; changing a filter mid-walk is rejected.

update_event

Update Event write destructive beta

Update an existing event. staff_ids REPLACES the event's full staff attendee list — staff not included are removed; omit it to leave attendees unchanged. To add staff without removing existing attendees, use add_staff_to_event. A recurring event cannot be updated with this tool; edit it in the MyCase app. Timed events' start/end are instants, returned in UTC (Z); show them to the user in get_me's time_zone. All-day events' start/end are calendar dates (YYYY-MM-DD) with no zone, and end is the last day, inclusive.

ParameterTypeRequiredDescription
event_idintegeryes
namestringno
startstringnoStart (ISO8601). Timed: a local time with the UTC offset get_me's time_zone has on that date, e.g. 2026-09-29T18:30:00-06:00 (Denver in summer; -07:00 in winter); a time without an offset is read as UTC. All-day (all_day=true): the calendar date, e.g. 2026-09-29; any time or offset is dropped, not converted.
endstringnoEnd (ISO8601), same format as start. All-day: the last day, inclusive, so a one-day event has end equal to start.
staff_idsarray[integer]no
required_staff_idsarray[integer]noStaff IDs, all also in staff_ids, who must attend (the Attend box in MyCase). When you pass it, every other staff_ids entry is marked optional. Omit it and attendees already on the event keep their current setting, while new ones join as optional.
case_idintegerno
location_idintegerno
all_daybooleanno

Expenses

create_expense

Create Expense write beta

Create a new expense entry.

ParameterTypeRequiredDescription
case_idintegeryesID of the case this expense belongs to
activity_namestringyesExpense activity name
billablebooleanyesWhether this expense is billable
entry_datestringyesExpense date (ISO8601)
costnumberyesCost per unit
unitsnumberyesNumber of units
staff_idintegernoStaff member ID
descriptionstringno
custom_field_valuesstringnoValues for the custom fields that apply to an expense, set on the new expense. Pass a JSON array encoded as a string, e.g. '[{"custom_field":{"id":42},"value":"Matter code A-17"},{"custom_field":{"id":43},"value":"1250.00"}]' — each element is an object with a custom_field object holding the field's integer id plus that field's value. Get ids from list_custom_fields: a field applies to an expense only when its parent_type is 'expense' or 'time_and_expense', and one defined for another record type is rejected. filter_parent_type matches the stored type exactly, so filter_parent_type='expense' does NOT return the 'time_and_expense' fields an expense also accepts — call list_custom_fields once per parent type. Values go in as strings: dates as ISO8601 (YYYY-MM-DD), currency/numeric as decimal strings such as '1250.00', booleans as 'true'/'false', and a list field's value must match one of its options exactly (list_custom_field_options). A custom field may appear at most once per call — a repeated id is rejected.

get_expense

Get Expense read-only

Get a specific expense by ID.

ParameterTypeRequiredDescription
expense_idintegeryes

list_all_expenses

List All Expenses read-only

List all expenses across the firm. Optionally filter by case.

ParameterTypeRequiredDescription
filter_case_idintegernoFilter expenses to a specific case ID
filter_updated_afterstringno
field_custom_fieldarray[string]noCustom-field attributes to add to the nested custom_field reference inside each custom_field_values entry. Nested records are returned as {id} only; each name listed here is added to them. This grows the response — it cannot be used to drop fields. field_type is the only value MyCase accepts here, so this widens {id} to {id, field_type} and no further — for a custom field's name, parent type, or list options, call get_custom_field or list_custom_fields. One of: field_type.
page_sizeintegernoItems per page (default 25, max 1000)
page_tokenstringnopagination.next_page_token from the previous page. It carries that page's filters, so other args may be omitted; changing a filter mid-walk is rejected.

update_expense

Update Expense write destructive beta

Update an expense. Partial update — only the provided params change; omitted params keep their current values. Cannot update an expense already associated with an invoice.

ParameterTypeRequiredDescription
expense_idintegeryes
case_idintegernoID of the case this expense belongs to
activity_namestringnoExpense activity name
billablebooleanno
entry_datestringnoExpense date (ISO8601)
costnumbernoCost per unit
unitsnumbernoNumber of units
staff_idintegernoStaff member ID
descriptionstringno
custom_field_valuesstringnoValues for the custom fields that apply to this expense. This is an UPSERT keyed on custom field id, not a replacement of the expense's whole set: a field you include OVERWRITES its current value, and a field you OMIT is LEFT UNCHANGED. Omitting a field does not clear it, so send only the fields you are changing — do not re-send a field's existing value to preserve it, and omit the param entirely when you are changing no custom fields. Pass a JSON array encoded as a string, e.g. '[{"custom_field":{"id":42},"value":"Matter code A-17"},{"custom_field":{"id":43},"value":"1250.00"}]' — each element is an object with a custom_field object holding the field's integer id plus that field's value. Get ids from list_custom_fields: a field applies to an expense only when its parent_type is 'expense' or 'time_and_expense', and one defined for another record type is rejected. filter_parent_type matches the stored type exactly, so filter_parent_type='expense' does NOT return the 'time_and_expense' fields an expense also accepts — call list_custom_fields once per parent type. Values go in as strings: dates as ISO8601 (YYYY-MM-DD), currency/numeric as decimal strings such as '1250.00', booleans as 'true'/'false', and a list field's value must match one of its options exactly (list_custom_field_options). A custom field may appear at most once per call — a repeated id is rejected.

Feedback

report_feedback

Report Feedback write

Report a bug or request a feature for the MyCase MCP server itself. Call this when a tool fails repeatedly or behaves unexpectedly, or when the user wants a capability these tools don't provide. Confirm with the user before submitting. Do NOT include client names, case details, or document contents — describe the problem generically.

ParameterTypeRequiredDescription
feedback_typestringyesOne of: bug, feature_request.
summarystringyesOne-line description of the problem or request
detailsstringnoExpected vs. actual behavior, and exact error text if any
related_toolstringnoName of the MCP tool this feedback concerns

Firm

get_firm

Get Firm read-only

Get information about the current firm, including its offices (id, name, primary, phones, address) — the source of office IDs for create_case and update_case.

get_me

Get Me read-only

Get information about the currently authenticated user. time_zone is the IANA zone (e.g. America/Denver) MyCase shows this user's calendar in; there is no firm-level zone. Use its UTC offset for datetimes the user means locally, such as "today" or "9am".

Invoices

get_invoice

Get Invoice read-only

Get a specific invoice by ID, including invoices that have online payments disabled: the by-id lookup uses the same wide invoice scope as list_all_invoices, so any invoice that appears there can also be fetched here.

ParameterTypeRequiredDescription
invoice_idintegeryes

list_all_invoices

List All Invoices read-only

List invoices (bills) across the firm, or scope to a single case with filter_case_id. At this tool's default only_allowed_online_payments=false, filter_case_id returns the same rows as list_case_invoices for the same caller, balance-forwarded bills (status 'forwarded') included. Requires the caller's billing permission and returns 403 without it. But unlike list_case_invoices, which 404s a case the caller cannot see, an unknown filter_case_id here returns an empty list — so an empty result is not proof that the case exists or that it has no invoices. Confirm the case with get_case before reporting either. Case visibility and bill visibility are separate rules: a caller without all-cases access still sees the bills shared with them, so this tool can return rows for a case list_case_invoices 404s.

ParameterTypeRequiredDescription
filter_case_idintegernoOnly invoices on this case — the server-side case scope, so one case's invoices need no client-side filtering. It composes with the caller's own authorization scope and never widens it: a caller who cannot view all firm cases still sees only the bills shared with them. Setting only_allowed_online_payments true alongside it drops invoices that have online payments disabled, narrowing below what list_case_invoices shows.
filter_updated_afterstringnoOnly records updated strictly after this ISO8601 timestamp (exclusive bound)
only_allowed_online_paymentsbooleannoWhen true, returns only invoices that allow online payments. Defaults to false so all invoices are listed.
page_sizeintegernoItems per page (default 25, max 1000)
page_tokenstringnopagination.next_page_token from the previous page. It carries that page's filters, so other args may be omitted; changing a filter mid-walk is rejected.

list_all_payments

List All Payments read-only

List payment transactions across ALL payable types — bill, retainer, subscription, and quick-bill payments — including pending and failed rows (pass filter_status to narrow); each row's payable_type names its kind. Ordered by payment date, most recent first; payments sharing a date come back newest-recorded first, and a payment with no date sorts last, after every dated payment. amount is SIGNED: refunds/voids are negative with is_refund true, so they net out rather than inflate a total. To total true settled receipts, sum only status=success rows — pending and failed rows are returned here by default and never settled. Scope to one case with filter_case_id (spanning every payable type and status for that case) or to one invoice with filter_payable_id. For a case's SETTLED BILL receipts only — retainer, subscription, and quick-bill receipts and pending/failed transactions excluded — use list_case_billing_payments instead; the two feeds agree on amount sign and both report client as the payable's billing contact (never the staff member who recorded the payment), differing in payable-type breadth, status breadth, and order — list_case_billing_payments returns oldest-recorded first rather than by payment date. For payments in a period ("this month", "last 30 days"), pass filter_pay_date_after / filter_pay_date_before. For incremental sync of changes (status changes, refunds, backdated entries), pass filter_updated_after; it is slow on firms with a long payment history, so never use it to find recent payments.

ParameterTypeRequiredDescription
filter_payable_idintegernoFilter by invoice ID
filter_case_idintegernoFilter to payments whose payable (bill/retainer/subscription/quick-bill) is on this case — the server-side case scope for firm-wide payment analysis, so a single case's payments need no client-side assembly. Spans all payable types and statuses for the case; list_case_billing_payments is the bill-only, successful-only case feed.
filter_statusstringnoFilter by payment status. One of: pending, success, failure, error, timeout.
filter_updated_afterstringnoISO8601 datetime; returns only payments whose payment record's own updated_at is strictly after this bound (exclusive). Keys off the payment transaction itself — an update to the parent invoice/bill does not surface its payments. Slow on large firms; for a date range use filter_pay_date_after / filter_pay_date_before.
filter_pay_date_afterstringnoOnly payments dated on or after this date-only ISO8601 date (YYYY-MM-DD); the bound is inclusive. Undated payments are excluded.
filter_pay_date_beforestringnoOnly payments dated on or before this date-only ISO8601 date (YYYY-MM-DD); the bound is inclusive. Undated payments are excluded.
page_sizeintegernoItems per page (default 25, max 1000)
page_tokenstringnopagination.next_page_token from the previous page. It carries that page's filters, so other args may be omitted; changing a filter mid-walk is rejected.

Leads

convert_lead

Convert Lead write destructive beta

Convert a lead into a client and open their potential case as a real case (the MyCase intake workflow). The lead becomes a client with the same ID, and the opened case is returned. A lead still pending review is approved as part of the conversion. Conversion cannot be undone.

ParameterTypeRequiredDescription
lead_idintegeryes
case_namestringnoName for the opened case. Defaults to the potential case's existing name (usually "Potential Case: <lead name>"), so prefer providing a real case name.

create_lead

Create Lead write beta

Create a new lead in MyCase. This lands two records, not one: MyCase opens a potential case for the lead, and that case's id comes back as the lead's case reference. A potential case is not a regular case on this surface: list_cases never returns it and get_case 404s on its id; convert_lead is what turns it into a real case. Read its notes with list_lead_notes, not list_case_notes. To set an address, supply all five of address_street, address_city, address_state, address_zip_code, and address_country together (address_street2 is optional — include it only for a second line); a partial address is rejected.

ParameterTypeRequiredDescription
first_namestringyes
last_namestringyes
middle_initialstringnoMiddle name or initial: 1-60 letters, no spaces or punctuation. Despite the name it is the same MyCase field clients call middle_name.
emailstringno
cell_phone_numberstringno
work_phone_numberstringno
home_phone_numberstringno
birthdatestringnoDate of birth as an ISO8601 date, e.g. '1979-04-23'. Two rejections to avoid, both returned as a 422: any other format (only ISO8601 parses), and a date that is not already past — today itself is rejected, not just future dates, with 'must be in the past.' This field is date-only: a full ISO8601 timestamp is accepted rather than rejected, but its time and offset are silently discarded instead of converted, so a UTC-normalized datetime can land on the wrong calendar day — send the bare date.
drivers_license_numberstringno
drivers_license_statestringno
referral_source_idintegernoReferral source ID
referral_source_namestringnoReferral source by name (mutually exclusive with referral_source_id). An unrecognized name is NOT rejected: MyCase files the lead under the firm's 'Other' referral source instead, so confirm the exact name with list_referral_sources first. An empty or blank string is treated as omitting the param.
referred_by_idintegernoID of the client or company that referred this lead
lead_detailsstringno
address_streetstringno
address_street2stringno
address_citystringno
address_statestringno
address_zip_codestringno
address_countrystringno
custom_field_valuesstringnoValues for the custom fields that apply to a lead, set on the new lead. Pass a JSON array encoded as a string, e.g. '[{"custom_field":{"id":42},"value":"Acme"},{"custom_field":{"id":43},"value":"2026-01-05"}]' — each element is an object with a custom_field object holding the field's integer id plus that field's value. Leads use the firm's CLIENT custom fields — MyCase defines no lead-specific custom field type. Get ids from list_custom_fields with filter_parent_type='client'; a field defined for another record type is rejected. Values go in as strings: dates as ISO8601 (YYYY-MM-DD), currency/numeric as decimal strings such as '1250.00', booleans as 'true'/'false', and a list field's value must match one of its options exactly (list_custom_field_options). A custom field may appear at most once per call — a repeated id is rejected.

get_lead

Get Lead read-only

Get a specific lead by ID. The lead's case reference is the potential case MyCase paired with it. A potential case is not a regular case on this surface: list_cases never returns it and get_case 404s on its id; convert_lead is what turns it into a real case. Read its notes with list_lead_notes, not list_case_notes.

ParameterTypeRequiredDescription
lead_idintegeryes

list_lead_notes

List Lead Notes read-only

List the notes on a lead: the Notes tab under the lead's Case Details in MyCase, where intake staff record consultation notes and next steps. Each note names the lead it belongs to. Notes stay with the case when the lead is converted; read them with list_case_notes after convert_lead.

ParameterTypeRequiredDescription
lead_idintegeryes
filter_statusstringnoOne of: active, archived.
filter_updated_afterstringno
page_sizeintegernoItems per page (default 25, max 1000)
page_tokenstringnopagination.next_page_token from the previous page. It carries that page's filters, so other args may be omitted; changing a filter mid-walk is rejected.

list_leads

List Leads read-only

List all leads. Supports filtering by status, name, email, phone, and text search. Each lead's case reference is the potential case MyCase paired with it. A potential case is not a regular case on this surface: list_cases never returns it and get_case 404s on its id; convert_lead is what turns it into a real case. Read its notes with list_lead_notes, not list_case_notes.

ParameterTypeRequiredDescription
filter_statusstringnoOne of: approved, unapproved.
filter_updated_afterstringno
filter_emailstringno
filter_first_namestringno
filter_last_namestringno
filter_cell_phone_numberstringno
filter_work_phone_numberstringno
filter_home_phone_numberstringno
search_starts_withstringno
field_custom_fieldarray[string]noCustom-field attributes to add to the nested custom_field reference inside each custom_field_values entry. Nested records are returned as {id} only; each name listed here is added to them. This grows the response — it cannot be used to drop fields. field_type is the only value MyCase accepts here, so this widens {id} to {id, field_type} and no further — for a custom field's name, parent type, or list options, call get_custom_field or list_custom_fields. One of: field_type.
page_sizeintegernoItems per page (default 25, max 1000)
page_tokenstringnopagination.next_page_token from the previous page. It carries that page's filters, so other args may be omitted; changing a filter mid-walk is rejected.

update_lead

Update Lead write destructive beta

Update an existing lead. To change the address, supply all five of address_street, address_city, address_state, address_zip_code, and address_country together; a partial address is rejected. Changing the address REPLACES it in full — include address_street2 to keep an existing second line, since omitting it clears any current second line. Omit all address fields to leave the existing address unchanged. custom_field_values is not one of these replace-in-full params: it is an upsert keyed on custom field id, so a field you include overwrites only that field, and a field you omit keeps its current value.

ParameterTypeRequiredDescription
lead_idintegeryes
first_namestringno
last_namestringno
statusstringnoPipeline status, by name. Each firm configures its own statuses, so there is no fixed set of values; get_lead and list_leads show a lead's current status. A name that matches none of the firm's active statuses is rejected with a 422 whose message lists the firm's active statuses, and the lead keeps the status it had. An archived status counts as no match. The lead must already be approved, and create_lead makes a lead that is still pending review: setting status on such a lead refuses the whole update with a 400, so approve the lead in MyCase first. Omit status to leave it unchanged; an empty or blank string is treated as omitting the param.
middle_initialstringnoMiddle name or initial: 1-60 letters, no spaces or punctuation. Despite the name it is the same MyCase field clients call middle_name.
emailstringno
cell_phone_numberstringno
work_phone_numberstringno
home_phone_numberstringno
birthdatestringnoDate of birth as an ISO8601 date, e.g. '1979-04-23'. Two rejections to avoid, both returned as a 422: any other format (only ISO8601 parses), and a date that is not already past — today itself is rejected, not just future dates, with 'must be in the past.' This field is date-only: a full ISO8601 timestamp is accepted rather than rejected, but its time and offset are silently discarded instead of converted, so a UTC-normalized datetime can land on the wrong calendar day — send the bare date.
drivers_license_numberstringno
drivers_license_statestringno
referral_source_idintegerno
referral_source_namestringnoReferral source by name (mutually exclusive with referral_source_id). An unrecognized name is NOT rejected: MyCase files the lead under the firm's 'Other' referral source instead, so confirm the exact name with list_referral_sources first. An empty or blank string is treated as omitting the param.
referred_by_idintegernoID of the client or company that referred this lead
lead_detailsstringno
address_streetstringno
address_street2stringno
address_citystringno
address_statestringno
address_zip_codestringno
address_countrystringno
custom_field_valuesstringnoValues for the custom fields that apply to this lead. This is an UPSERT keyed on custom field id, not a replacement of the lead's whole set: a field you include OVERWRITES its current value, and a field you OMIT is LEFT UNCHANGED. Omitting a field does not clear it, so send only the fields you are changing — do not re-send a field's existing value to preserve it, and omit the param entirely when you are changing no custom fields. Pass a JSON array encoded as a string, e.g. '[{"custom_field":{"id":42},"value":"Acme"},{"custom_field":{"id":43},"value":"2026-01-05"}]' — each element is an object with a custom_field object holding the field's integer id plus that field's value. Leads use the firm's CLIENT custom fields — MyCase defines no lead-specific custom field type. Get ids from list_custom_fields with filter_parent_type='client'; a field defined for another record type is rejected. Values go in as strings: dates as ISO8601 (YYYY-MM-DD), currency/numeric as decimal strings such as '1250.00', booleans as 'true'/'false', and a list field's value must match one of its options exactly (list_custom_field_options). A custom field may appear at most once per call — a repeated id is rejected.

Locations

create_location

Create Location write beta

Create a new location. To set an address, supply all five of address_street, address_city, address_state, address_zip_code, and address_country together (address_street2 is optional — include it only for a second line); a partial address is rejected.

ParameterTypeRequiredDescription
namestringyesLocation name
address_streetstringno
address_street2stringno
address_citystringno
address_statestringno
address_zip_codestringno
address_countrystringno

get_location

Get Location read-only

Get a specific location by ID.

ParameterTypeRequiredDescription
location_idintegeryes

list_locations

List Locations read-only

List all locations.

ParameterTypeRequiredDescription
filter_updated_afterstringno
search_starts_withstringno
page_sizeintegernoItems per page (default 25, max 1000)
page_tokenstringnopagination.next_page_token from the previous page. It carries that page's filters, so other args may be omitted; changing a filter mid-walk is rejected.

update_location

Update Location write destructive beta

Update a location. To change the address, supply all five of address_street, address_city, address_state, address_zip_code, and address_country together; a partial address is rejected. Changing the address REPLACES it in full — include address_street2 to keep an existing second line, since omitting it clears any current second line. Omit all address fields to leave the existing address unchanged.

ParameterTypeRequiredDescription
location_idintegeryes
namestringno
address_streetstringno
address_street2stringno
address_citystringno
address_statestringno
address_zip_codestringno
address_countrystringno

Messages

create_message_thread

Create Message Thread write destructive beta

Create a new message thread. Provide at least one recipient via client_recipient_ids and/or staff_recipient_ids.

ParameterTypeRequiredDescription
subjectstringyesMessage thread subject
bodystringyesFirst message body
client_recipient_idsarray[integer]noClient recipient IDs (at least one of client_/staff_recipient_ids)
staff_recipient_idsarray[integer]noStaff recipient IDs (at least one of client_/staff_recipient_ids)

get_message_thread

Get Message Thread read-only

Get a message thread's metadata by ID: subject, sender, participants (clients and staff), related case, and the opening message body. Use list_thread_messages to read the full conversation.

ParameterTypeRequiredDescription
thread_idintegeryes

list_message_threads

List Message Threads read-only

List message threads the authorizing user can view, most recently active first, including staff-only threads (list_client_message_threads only covers threads with a specific client). Returns thread metadata plus the opening message; use list_thread_messages to read a full conversation.

ParameterTypeRequiredDescription
filter_last_post_afterstringnoISO8601 datetime. Returns threads whose most recent message was posted after this time. A thread edited but not posted to is not returned, nor is one with no messages yet.
page_sizeintegernoItems per page (default 25, max 1000)
page_tokenstringnopagination.next_page_token from the previous page. It carries that page's filters, so other args may be omitted; changing a filter mid-walk is rejected.

list_thread_messages

List Thread Messages read-only

List every message in a message thread — the opening message and all replies, oldest first — with each message's sender and timestamp.

ParameterTypeRequiredDescription
thread_idintegeryes
page_sizeintegernoItems per page (default 25, max 1000)
page_tokenstringnopagination.next_page_token from the previous page. It carries that page's filters, so other args may be omitted; changing a filter mid-walk is rejected.

reply_to_message_thread

Reply To Message Thread write destructive beta

Reply to an existing message thread. Use list_thread_messages first to read the conversation you are replying to.

ParameterTypeRequiredDescription
thread_idintegeryes
bodystringyesReply message body

Notes

get_note

Get Note read-only

Get a specific note by ID.

ParameterTypeRequiredDescription
note_idintegeryes

update_note

Update Note write destructive beta

Update an existing note. Cannot update archived notes.

ParameterTypeRequiredDescription
note_idintegeryes
notestringnoNote content
subjectstringno
datestringnoNote date (ISO8601)

People Groups

create_people_group

Create People Group write beta

Create a new people group. Name must be unique.

ParameterTypeRequiredDescription
namestringyesPeople group name (must be unique)

get_people_group

Get People Group read-only

Get a specific people group by ID.

ParameterTypeRequiredDescription
people_group_idintegeryes

list_people_groups

List People Groups read-only

List all people groups (contact groups).

ParameterTypeRequiredDescription
filter_updated_afterstringno
page_sizeintegernoItems per page (default 25, max 1000)
page_tokenstringnopagination.next_page_token from the previous page. It carries that page's filters, so other args may be omitted; changing a filter mid-walk is rejected.

update_people_group

Update People Group write destructive beta

Update a people group. Cannot update system groups.

ParameterTypeRequiredDescription
people_group_idintegeryes
namestringno

Practice Areas

create_practice_area

Create Practice Area write beta

Create a new practice area.

ParameterTypeRequiredDescription
namestringyesPractice area name

get_practice_area

Get Practice Area read-only

Get a specific practice area by ID.

ParameterTypeRequiredDescription
practice_area_idintegeryes

list_practice_areas

List Practice Areas read-only

List all practice areas.

ParameterTypeRequiredDescription
filter_updated_afterstringno
search_starts_withstringno
page_sizeintegernoItems per page (default 25, max 1000)
page_tokenstringnopagination.next_page_token from the previous page. It carries that page's filters, so other args may be omitted; changing a filter mid-walk is rejected.

update_practice_area

Update Practice Area write destructive beta

Update a practice area.

ParameterTypeRequiredDescription
practice_area_idintegeryes
namestringno

Referral Sources

create_referral_source

Create Referral Source write beta

Create a new referral source.

ParameterTypeRequiredDescription
namestringyesReferral source name

get_referral_source

Get Referral Source read-only

Get a specific referral source by ID.

ParameterTypeRequiredDescription
referral_source_idintegeryes

list_referral_sources

List Referral Sources read-only

List all referral sources.

ParameterTypeRequiredDescription
filter_updated_afterstringno
search_starts_withstringno
page_sizeintegernoItems per page (default 25, max 1000)
page_tokenstringnopagination.next_page_token from the previous page. It carries that page's filters, so other args may be omitted; changing a filter mid-walk is rejected.

Full Text Search read-only

Search across the firm's records by text query: cases, contacts, documents, notes, tasks, events, leads, messages, expenses, and call log entries. Matches names, descriptions, numbers, and notes, and returns matched-text highlights. Only record types the connection is authorized to read are searched; the response's requested_types field lists the types the search was submitted with, narrowed by scope and by case_id, and is not proof each one was searched — a type the firm has disabled is dropped upstream without being echoed back. Pass case_id to confine the search to a single case instead of the whole firm. Event results are keyed by appointment_rule_id, not by id — pass appointment_rule_id to get_event.

ParameterTypeRequiredDescription
querystringyesSearch text, 3-100 characters
typesarray[string]noRecord types to search. Defaults to every type the connection can read. Searching 'documents' alone also matches document file content where the firm has content search enabled. One of: calls, cases, contacts, documents, events, expenses, leads, messages, notes, tasks.
case_idintegernoScope the search to one case: only records associated with that case are returned. Firm-level documents — those filed outside any case — are excluded, so omit case_id to reach them. contacts and leads cannot be case-scoped: they are dropped from a case-scoped search and requested_types echoes the reduced list, and asking for only contacts or leads together with case_id is rejected. A message's case association can be stale, so message hits are best-effort. A case id that does not exist, or that this user cannot see, returns an empty result set rather than an error — indistinguishable from a case that simply has no matches, so do not read empty results as proof the case is empty. Where the firm's search index cannot apply the case filter, the scope is enforced after each upstream page is fetched, so a page may return fewer than page_size results — even zero — while later pages still hold matches. Judge that by the token and never by page length: a short page still carries pagination.next_page_token when more results remain.
page_sizeintegernoResults per page (default 10, max 50)
page_tokenstringnoToken from the previous response's pagination.next_page_token, to fetch the next page. Pass it back with the same query, types and case_id it was issued for; a token replayed against a different search is rejected rather than answered. page_size is not part of that match — it may be changed mid-sweep, and the new value applies from that page on. A response with no next_page_token is the last page.

Staff

get_staff

Get Staff read-only

Get a specific staff member by ID.

ParameterTypeRequiredDescription
staff_idintegeryes

list_staff

List Staff read-only

List all staff members.

ParameterTypeRequiredDescription
filter_statusstringnoOne of: active, inactive.
filter_updated_afterstringno
search_starts_withstringno
page_sizeintegernoItems per page (default 25, max 1000)
page_tokenstringnopagination.next_page_token from the previous page. It carries that page's filters, so other args may be omitted; changing a filter mid-walk is rejected.

Tasks

add_staff_to_task

Add Staff To Task write beta

Add staff members to a task. Additive — existing assignees are preserved (unlike update_task, whose staff_ids replaces).

ParameterTypeRequiredDescription
task_idintegeryes
staff_idsarray[integer]yesStaff member IDs to add

create_task

Create Task write beta

Create a new task in MyCase.

ParameterTypeRequiredDescription
namestringyesTask name
prioritystringnoTask priority. Defaults to "None" (no priority). One of: None, Low, Medium, High.
staff_idsarray[integer]yesList of staff member IDs to assign
descriptionstringno
due_datestringnoDue date in ISO8601 format
completedbooleanno
case_idintegernoCase ID to associate the task with

get_task

Get Task read-only

Get a specific task by ID. A task on a lead's potential case carries a lead reference in place of case -- resolve it with get_lead, not get_case.

ParameterTypeRequiredDescription
task_idintegeryes

list_tasks

List Tasks read-only

List all tasks. Use filter_completed=false with filter_due_before to answer "what is due" -- without them this returns the firm's whole task history. filter_completed=false includes tasks awaiting review, matching the open task list in the app. A task on a lead's potential case carries a lead reference in place of case -- resolve it with get_lead, not get_case.

ParameterTypeRequiredDescription
filter_case_idintegernoFilter tasks to a specific case ID
filter_updated_afterstringnoISO8601 datetime to filter tasks updated after this time
filter_due_beforestringnoOnly tasks due on or before this ISO8601 date (YYYY-MM-DD); the bound is inclusive
filter_completedbooleannotrue -> only completed tasks; false -> only open ones, which includes tasks awaiting review
filter_staff_idintegernoOnly tasks this staff member is assigned (see list_staff)
page_sizeintegernoItems per page (default 25, max 1000)
page_tokenstringnopagination.next_page_token from the previous page. It carries that page's filters, so other args may be omitted; changing a filter mid-walk is rejected.

update_task

Update Task write destructive beta

Update an existing task. staff_ids REPLACES the task's full assigned-staff list — staff not included are unassigned; omit it to leave staff unchanged. To add staff without removing existing assignees, use add_staff_to_task.

ParameterTypeRequiredDescription
task_idintegeryes
namestringno
prioritystringnoOne of: None, Low, Medium, High.
staff_idsarray[integer]noList of staff member IDs to assign
descriptionstringno
due_datestringno
completedbooleanno
case_idintegerno

Texts

get_text_conversation

Get Text Conversation read-only

Get one SMS conversation's metadata by id: the external phone number, the linked contact (id, name, and whether they are a Client or a Lead), and when it last moved. Message bodies are not included — use list_text_conversation_messages. Archived conversations are returned, with archived_at set. Returns 404 if the conversation does not exist, belongs to another firm, or is with a lead you cannot view; those are deliberately indistinguishable, so do not report a 404 as proof the conversation does not exist.

ParameterTypeRequiredDescription
text_conversation_idintegeryes

list_text_conversation_messages

List Text Conversation Messages read-only

Read the individual text messages in one SMS conversation. Get the conversation's id from list_text_conversations. Each message carries its body, a direction of 'incoming' or 'outgoing', the staff member who sent an outgoing one, the delivery status, and the time it was sent or received — which is the field to order by, not created_at, since a queued message can be delivered later than it was written. Text threads run long: production conversations commonly hold a few hundred messages and the largest hold over a thousand, so page with page_size and page_token rather than assuming one call is the whole history, and say so if you are summarizing only part of it. MMS attachments are listed by id and content type only — no URL and no filename. An image or PDF sent by text can be reported as present and counted, never opened, downloaded, or read. Treat that as settled rather than a gap waiting on a tool: the media is held by the SMS carrier and MyCase stores only the carrier's own link, so there is nothing here to hand back safely. Point the user at the conversation in MyCase to view an attachment instead of implying a retrieval path exists.

ParameterTypeRequiredDescription
text_conversation_idintegeryes
filter_updated_afterstringnoOnly messages whose own updated_at is strictly after this ISO8601 timestamp (exclusive bound); a timestamp with no UTC offset is read as UTC, and a non-ISO8601 value is rejected upstream.
page_sizeintegernoItems per page (default 25, max 1000)
page_tokenstringnopagination.next_page_token from the previous page. It carries that page's filters, so other args may be omitted; changing a filter mid-walk is rejected.

list_text_conversations

List Text Conversations read-only

List the firm's two-way SMS/text conversations — real text messages to and from phones, exchanged with clients, leads and unrecognized numbers. This is NOT MyCase's secure client-portal messaging (list_message_threads) and NOT internal staff chat (list_case_chat_conversations); all three use the word 'message' and share nothing else. Returns conversation metadata only (id, external_phone_number, the linked contact's id/name/type, last_message_at, archived_at, timestamps); message bodies are NOT included — pass a conversation's id to list_text_conversation_messages to read them. The list is firm-wide, not per-case: a text conversation is keyed to a phone number and a contact, and carries no case at all. To answer 'what texts are on this case', list the case's clients first and then pass one of their ids as filter_client_id — and say plainly that this is a per-contact answer, since the same conversation belongs to every case that contact is on. Conversations with no linked contact (an inbound text from an unrecognized number) are returned and simply carry no client. Archived conversations are excluded by default; pass include_archived=true to list them too, as the MyCase app's 'show archived' toggle does. An archived row carries archived_at. An empty list means 'none in your firm that you may see', not 'this firm does not text'. Requires the MyCase text-messaging permission; without it every text tool returns a permission error rather than an empty list. Conversations with a LEAD are withheld from users who cannot view leads.

ParameterTypeRequiredDescription
include_archivedbooleannotrue → also return archived conversations; omitted or false → active conversations only.
filter_client_idintegernoOnly conversations linked to this contact — a client or lead id, not a case id.
filter_updated_afterstringnoOnly conversations whose own updated_at is strictly after this ISO8601 timestamp (exclusive bound); a timestamp with no UTC offset is read as UTC.
page_sizeintegernoItems per page (default 25, max 1000)
page_tokenstringnopagination.next_page_token from the previous page. It carries that page's filters, so other args may be omitted; changing a filter mid-walk is rejected.

Time Entries

create_time_entry

Create Time Entry write beta

Create a new time entry.

ParameterTypeRequiredDescription
case_idintegeryesID of the case this time entry belongs to
activity_namestringyesTime entry activity name
entry_datestringyesEntry date (ISO8601)
staff_idintegeryesStaff member ID
ratenumbernoRate. When flat_fee is true this is the flat-fee total charged, not an hourly rate; otherwise the hourly rate. Omit it to use the rate MyCase would fill in: the activity's own rate (a flat-fee activity makes a flat-fee entry at its fee), else the staff member's rate on the case (case rate, rate plan or default rate). Required when flat_fee is true and the activity has no flat fee. When you omit it, tell the user what was applied: the response's rate (when visible), flat_fee and total.
hoursnumbernoNumber of hours (required by the API unless flat_fee is true)
billablebooleanno
flat_feebooleannoIf true, hours is optional
descriptionstringno
custom_field_valuesstringnoValues for the custom fields that apply to a time entry, set on the new time entry. Pass a JSON array encoded as a string, e.g. '[{"custom_field":{"id":42},"value":"Matter code A-17"},{"custom_field":{"id":43},"value":"1250.00"}]' — each element is an object with a custom_field object holding the field's integer id plus that field's value. Get ids from list_custom_fields: a field applies to a time entry only when its parent_type is 'time' or 'time_and_expense', and one defined for another record type is rejected. filter_parent_type matches the stored type exactly, so filter_parent_type='time' does NOT return the 'time_and_expense' fields a time entry also accepts — call list_custom_fields once per parent type. Values go in as strings: dates as ISO8601 (YYYY-MM-DD), currency/numeric as decimal strings such as '1250.00', booleans as 'true'/'false', and a list field's value must match one of its options exactly (list_custom_field_options). A custom field may appear at most once per call — a repeated id is rejected.

get_time_entry

Get Time Entry read-only

Get a specific time entry by ID. Includes the server-computed total (always present); billing_status ('unbilled', 'on_draft_invoice', or 'invoiced') and the invoices list are included only with billing access (the caller's billing permission plus the read_invoices scope) and are withheld otherwise.

ParameterTypeRequiredDescription
time_entry_idintegeryes

list_all_time_entries

List All Time Entries read-only

List all time entries across the firm. Optionally filter by case. Results filtered by entry date come back newest entry date first. Each entry carries a server-computed total that prices flat-rate entries correctly — prefer it over hours x rate math; total is always present. With billing access (the caller's billing permission plus the read_invoices scope) each entry also carries a billing_status of 'unbilled', 'on_draft_invoice', or 'invoiced' and an invoices list reflecting actual invoice association including draft invoices; without that access those billing fields are withheld, so their absence does not mean an entry is unbilled. billed does NOT imply the entry was billable — check the billable field when reconciling. Flat-fee billing line items are separate records that never appear in time-entry results — use list_case_billing_flat_fees for a case's flat fees; billed flat fees also appear in get_case_invoice_line_items, but unbilled flat-fee revenue appears only via list_case_billing_flat_fees, so a work-in-progress total built without it misses that revenue.

ParameterTypeRequiredDescription
filter_case_idintegernoFilter time entries to a specific case ID
filter_updated_afterstringnoOnly entries updated strictly after this ISO8601 timestamp (exclusive bound, unlike the inclusive entry-date filters)
filter_entry_date_afterstringnoOnly entries dated on or after this date-only ISO8601 date (YYYY-MM-DD); the bound is inclusive
filter_entry_date_beforestringnoOnly entries dated on or before this date-only ISO8601 date (YYYY-MM-DD); the bound is inclusive
filter_billedbooleannotrue → only entries already on an invoice (draft or finalized — use billing_status to distinguish); false → only entries not yet invoiced
field_custom_fieldarray[string]noCustom-field attributes to add to the nested custom_field reference inside each custom_field_values entry. Nested records are returned as {id} only; each name listed here is added to them. This grows the response — it cannot be used to drop fields. field_type is the only value MyCase accepts here, so this widens {id} to {id, field_type} and no further — for a custom field's name, parent type, or list options, call get_custom_field or list_custom_fields. One of: field_type.
page_sizeintegernoItems per page (default 25, max 1000)
page_tokenstringnopagination.next_page_token from the previous page. It carries that page's filters, so other args may be omitted; changing a filter mid-walk is rejected.

update_time_entry

Update Time Entry write destructive beta

Update a time entry. Partial update — only the provided params change; omitted params keep their current values. Cannot update a time entry already associated with an invoice.

ParameterTypeRequiredDescription
time_entry_idintegeryes
case_idintegernoID of the case this time entry belongs to
activity_namestringnoTime entry activity name
entry_datestringnoEntry date (ISO8601)
staff_idintegernoStaff member ID
ratenumbernoRate. When flat_fee is true this is the flat-fee total charged, not an hourly rate; otherwise the hourly rate.
hoursnumbernoNumber of hours (required by the API unless flat_fee is true)
billablebooleanno
flat_feebooleanno
descriptionstringno
custom_field_valuesstringnoValues for the custom fields that apply to this time entry. This is an UPSERT keyed on custom field id, not a replacement of the time entry's whole set: a field you include OVERWRITES its current value, and a field you OMIT is LEFT UNCHANGED. Omitting a field does not clear it, so send only the fields you are changing — do not re-send a field's existing value to preserve it, and omit the param entirely when you are changing no custom fields. Pass a JSON array encoded as a string, e.g. '[{"custom_field":{"id":42},"value":"Matter code A-17"},{"custom_field":{"id":43},"value":"1250.00"}]' — each element is an object with a custom_field object holding the field's integer id plus that field's value. Get ids from list_custom_fields: a field applies to a time entry only when its parent_type is 'time' or 'time_and_expense', and one defined for another record type is rejected. filter_parent_type matches the stored type exactly, so filter_parent_type='time' does NOT return the 'time_and_expense' fields a time entry also accepts — call list_custom_fields once per parent type. Values go in as strings: dates as ISO8601 (YYYY-MM-DD), currency/numeric as decimal strings such as '1250.00', booleans as 'true'/'false', and a list field's value must match one of its options exactly (list_custom_field_options). A custom field may appear at most once per call — a repeated id is rejected.

Trust

list_trust_account_balances

List Trust Account Balances read-only

Current per-client trust (IOLTA) holdings — the rows behind the MyCase Trust Account Summary report. Each row is one client's balance in one trust bank account, either allocated to a case or unallocated: unallocated=true rows (case is null) are client-wide trust funds not tied to any case. The holder in client may be a company, not only a person: client.type is Client, Company, or Lead, so look a holder up with get_client, get_company, or get_lead to match (get_client returns not_found for a company). A client's total trust = the sum of their rows, which equals list_trust_ledger_entries net change summed over that client's ENTIRE unfiltered history — never a date-filtered ledger sum. A case's trust picture = its allocated rows PLUS its clients' unallocated rows, which get_case_billing_summary.balances.trust also reports; the two are independent reads that use different case-allocation predicates, so they usually agree but may legitimately differ — treat them as corroborating, not a guaranteed identity. Balances are current as of now (no as-of-date support); for changes over a period use list_trust_ledger_entries. Zero-balance rows are included unless filter_include_zero_balances=false. Trust money is client money, never firm revenue. Requires the billing user permission and returns 403 without it.

ParameterTypeRequiredDescription
filter_client_idintegernoOnly holdings of this holder (client or company) ID
filter_case_idintegernoOnly holdings ALLOCATED to this case — excludes the clients' unallocated (client-wide) rows, so this alone understates the case's available trust
filter_bank_account_idintegernoOnly holdings in this trust bank account ID
filter_include_zero_balancesbooleannofalse → omit zero-balance rows (clients whose trust is fully disbursed); default true
page_sizeintegernoItems per page (default 25, max 1000)
page_tokenstringnopagination.next_page_token from the previous page. It carries that page's filters, so other args may be omitted; changing a filter mid-walk is rejected.

list_trust_bank_accounts

List Trust Bank Accounts read-only

List the firm's trust (IOLTA) bank accounts with the total client funds currently held in each. balance is CLIENT money the firm holds in trust — never firm revenue; do not mix it with billing totals (invoices, payments, collected). balance equals the sum of list_trust_account_balances rows for the account, and clients_with_balance counts distinct clients with a nonzero balance. Deleted accounts are excluded. Requires the billing user permission and returns 403 without it — an empty list really means the firm has no trust accounts.

ParameterTypeRequiredDescription
page_sizeintegernoItems per page (default 25, max 1000)
page_tokenstringnopagination.next_page_token from the previous page. It carries that page's filters, so other args may be omitted; changing a filter mid-walk is rejected.

list_trust_ledger_entries

List Trust Ledger Entries read-only

Trust (IOLTA) ledger activity — the rows of the MyCase Trust Account Activity report: deposits into trust and payments/withdrawals out of trust, including the incoming deposits that invoice-payment feeds never show. Each entry carries credit (client funds INTO trust) or debit (funds OUT of trust) as non-negative amounts with exactly one nonzero; net change over a set = sum(credit) - sum(debit). That net change equals a client's current trust balance ONLY when summing ALL of that client's entries with no date filter (their entire unfiltered history); a date-windowed sum is just the net change for that window, not the as-of-now balance — for current balances use list_trust_account_balances. No running balance is served. client is the holder and may be a company: route by client.type (Client, Company, Lead) to get_client, get_company, or get_lead. case is null for activity on a client's unallocated (client-wide) trust; related_to names the invoice, retainer request, or subscription the money was applied to, when any. Refunds and voided checks appear as opposite-side entries (a voided trust withdrawal shows as a credit), never as deletions. Results are ordered by id (creation order), not by date — use the inclusive filter_pay_date_after/_before bounds for date windows. Trust money is client money, never firm revenue — do not sum it into billing totals. Requires the billing user permission and returns 403 without it, so an empty list really means no matching trust activity.

ParameterTypeRequiredDescription
filter_client_idintegernoOnly entries for this holder (client or company) ID
filter_case_idintegernoOnly entries on trust buckets allocated to this case; excludes the clients' unallocated (client-wide) activity
filter_bank_account_idintegernoOnly entries touching this trust bank account ID
filter_pay_date_afterstringnoOnly entries dated on or after this date-only ISO8601 date (YYYY-MM-DD); the bound is inclusive
filter_pay_date_beforestringnoOnly entries dated on or before this date-only ISO8601 date (YYYY-MM-DD); the bound is inclusive
filter_updated_afterstringnoOnly records updated strictly after this ISO8601 timestamp (exclusive bound, unlike the inclusive pay-date filters)
page_sizeintegernoItems per page (default 25, max 1000)
page_tokenstringnopagination.next_page_token from the previous page. It carries that page's filters, so other args may be omitted; changing a filter mid-walk is rejected.