Skip to main content

Matters

What a matter is

A matter is the case or file a firm bills its work against. If your product serves law firms, matters let a firm answer one question for every dollar of AI cost: which case does this belong to? Once usage is tied to matters, a firm can pull a per-matter cost record it can hand a client or an auditor. Anything no matter claims stays visible in an Unassigned bucket, so nothing gets lost. You can manage matters on the Law tab in the dashboard, from your own code with the endpoints below, or in plain English through the MCP tools. All three do the same work against the same numbers.

How usage attaches to a matter

Every usage event lands on at most one matter. There are three ways it can get there, and when more than one applies, the strongest wins:
  1. Manual assignment (strongest). Someone puts the event on a matter by hand, in the dashboard or through the assign endpoint below. A manual choice always wins, and it’s never overwritten by tags or rules later.
  2. A tag on the event. When you record a usage event, add the matter’s own case number as metadata.matterId. If a matter with that exact number exists, the event attaches to it. The tag is matched against the matter’s number (the matterNumber you set), not its UUID.
  3. A routing rule (weakest). A rule says “events for this agent code, this customer, or this signal go to this matter.” Rules fill in the events you didn’t tag.
If none of the three apply, the event stays Unassigned until you assign it or a rule sweeps it up.
Tagging at record time is the cleanest path. When your agent already knows the case it’s working on, send metadata.matterId with the usage event (see Usage Events). The event lands on the right matter the moment it’s recorded, with nothing to clean up later. An unknown tag is never dropped and never creates a matter on its own. The event simply falls through to the rules, and to Unassigned if no rule matches.

Actual cost, never an estimate

Every cost figure on a matter is the sum of that matter’s real usage-event costs. It’s never a guess. When an event’s cost isn’t resolved yet (its model isn’t in the pricing table), that event adds 0 to the total and is counted separately in an eventsMissingCost field. A nonzero eventsMissingCost means the true cost is higher than the number shown, and it tells you exactly how many events to fix first. See Usage Events for how to resolve an unpriced model.

Who can manage matters

Every endpoint on this page needs a secret key that belongs to an owner, admin, finance, or legal user. Any other key gets a 403 Forbidden naming the role it needs. A publishable key (mf_pk_...) is refused. A legal key is a secret key scoped for exactly this surface, so a firm can hand it to its own agent without handing over the books. An owner or admin mints one under Build → API keys. A legal key can reach:
  • Every endpoint on this page.
  • The usage-recording surface: record events, /v1/verify, its own key info, and read-only Spend Controls.
Everything else answers 403 Forbidden: customers, invoices, usage events, analytics, pricing, and portal sessions. That limit is always on and enforced on the server.

Matters

List matters

Returns your matters, each with its all-time actual AI cost and event count. Response (200 OK):

Create a matter

Request body:
Response (201 Created): the created matter.
Common errors:
  • 409 Conflict: a matter with that matterNumber already exists in your organization.

Get one matter

Returns the matter, its all-time cost and event count, and its 100 most recent events. The full record lives on the audit endpoint below; eventsCap tells you the cutoff. Response (200 OK):
An event’s usageCost is null when its cost isn’t resolved yet. source is tag, rule, manual, or null. Common errors:
  • 404 Not Found: no matter with that ID in your organization.

Update a matter

Only the fields you send change. Send responsibleUserId: null to clear the responsible timekeeper. Closing a matter (status: "closed") is a label only. It doesn’t stop anything at record time. Response (200 OK): the updated matter, same shape as create. Common errors:
  • 404 Not Found: no matter with that ID in your organization.
  • 409 Conflict: the new matterNumber is already used by another matter.

Delete a matter

Deleting a matter doesn’t delete its usage events. They survive and return to Unassigned, where a rule or a manual assignment can pick them up again. The matter’s routing rules are deleted with it. The response counts both. Response (200 OK):
Common errors:
  • 404 Not Found: no matter with that ID in your organization.

Unassigned events

List unassigned events

Returns the usage events no matter has claimed. totalResults is the true all-time count of unassigned events (it’s never limited to the page or a date window), and totalCost is the cost of the whole unassigned set. Response (200 OK):

Assign an event to a matter

Puts one usage event on a matter by hand, or pulls it off. A manual assignment outranks a tag or a rule, and a manual unassignment is never swept back up by the apply-rules pass. Request body:
Response (201 Created):
Common errors:
  • 404 Not Found: the event or the target matter isn’t in your organization.

Routing rules

A routing rule attaches events to a matter automatically. A rule matches an event when every matcher it sets matches: agentCode exactly, customerExternalId exactly, and signalPattern as a case-insensitive substring of the signal name. A rule needs at least one matcher. Rules run in evaluation order: lowest priority first, and older rules before newer ones on a tie. The first rule that matches wins.

List routing rules

Returns your rules in the exact order they’re evaluated at record time and when you apply them. Response (200 OK):

Create a routing rule

Request body:
At least one of agentCode, customerExternalId, or signalPattern is required. Response (201 Created): the rule, including its matter’s number and name. Common errors:
  • 400 Bad Request: no matcher was provided.
  • 404 Not Found: the target matter isn’t in your organization.

Apply routing rules

Sweeps your rules across events that are still Unassigned, in priority order. It touches only events with no matter and no attribution history, so it never overrides a tag, an earlier rule, or a manual choice. Response (201 Created):
If the sweep stops partway, the response says how many events were assigned before it stopped. Run it again to finish the rest.

Update a routing rule

Only the fields you send change. Send a matcher as null to clear it. A rule must always keep at least one matcher. Response (200 OK): the updated rule. Common errors:
  • 404 Not Found: no rule with that ID in your organization.

Delete a routing rule

Deleting a rule stops future matching only. Events the rule already assigned keep their matter. Response (200 OK):
Common errors:
  • 404 Not Found: no rule with that ID in your organization.

The audit record

Export the matter audit

This is the record a firm shows a client or a carrier: the actual AI cost per matter over a window. The default summary view is one row per matter, plus an Unassigned row, plus organization totals. It reconciles exactly with the Law tab CSV export for the same window. Response (200 OK, summary):
The row with a null matterNumber is the Unassigned row. It’s present whenever unassigned events fall in the window. When you pass format=detail, the response also carries a rows array, one entry per event, each with its matter, date, agent, signal, the models used, cost, quantity, and attribution source. Costs that aren’t resolved yet count as 0 in every total and are flagged in eventsMissingCost. They’re never invented, so the number you hand an auditor is honest.

A quick pattern

A firm that wants clean records from day one usually does this:
  1. Create a matter for each open case, using the firm’s own case number as matterNumber.
  2. Tag each usage event with metadata.matterId set to that case number, so events land on the right matter as they’re recorded.
  3. Add a routing rule or two for the work that’s hard to tag at the source.
  4. Check the Unassigned list now and then, and assign anything left over by hand.
  5. Export the audit for a billing window when it’s time to bill.
Steps 1 through 4 keep the record accurate. Step 5 turns it into a number a client can trust.