Skip to main content

Matter-brief API

Read the instructions for a matter you have been engaged on, straight into the drafting software you already use.

Before you start

This page is public so that a firm can hand it to its own developer or to a software vendor without either of them needing a Orchard72 login. Everything below describes the published shape of the API and nothing on it is account or client data.

The one thing you cannot do from here is mint a key. Keys belong to a person, not to a firm, so the professional whose matters are being read signs in and creates one from their own developer hub.

Where the key comes from

The engaged professional signs in and opens their developer hub, where the same guide sits next to key management. A key scoped for this API cannot be minted by anyone else, including us.

The API

What the matter-brief API is for

The matter-brief API lets your own drafting software pull the instructions for a matter you have been engaged on, so you can work in the tools you already use instead of re-keying a client’s file by hand. It is read-only. Nothing you send can change a matter, and no endpoint here writes.

Client data is never handed over on the strength of your key alone. The list of matters carries no client data at all, and the brief is released only while the client’s own consent for that matter is live. Consent is re-checked on every single fetch, never cached, so a client who withdraws it stops the next call rather than the next month’s.

Authentication and access

Authenticate with a personal API key as a bearer token. Keys begin pk_ and are minted in your developer hub. Send them on every request:

Authorization: Bearer pk_your_key_here

Three separate things must all hold, and each fails differently. The key must carry the pro:read scope, chosen when you mint it. Your account must hold the pro.api_access entitlement, which comes from your plan. And for a brief specifically, the client’s consent grant for that matter must be live. A consumer portfolio key will not work here, and a key from here will not work on the consumer API.

Requests are capped per hour. The cap is your plan’s pro.api_rate_limit entitlement rather than a fixed figure, and brief fetches carry a second, independent egress cap, because a brief is a client’s personal file and bulk pulls are not an ordinary access pattern. Whichever of the two runs out first answers 429.

Endpoints

MethodPathWhat it returns
GET/api/v1/pro/ext/matters/Matters you may request a brief for. Carries no client data at all: no name, no email, no message text, no monetary figure.
GET/api/v1/pro/ext/matters/{id}/brief/The scoped brief for one matter, and only while the client’s consent is live. Returns Cache-Control: no-store.
GET/api/v1/pro/ext/me/The authenticated professional’s own profile and practice details.
GET/api/v1/pro/ext/schema/The OpenAPI schema. Generate your client from this, never from this page.

Quickstart

Four calls, in order. The last one is the case most integrations get wrong, so it is worth running deliberately before you rely on the lane.

# 1. Mint a key with the pro:read scope in your developer hub, then
#    put it in a file curl reads, NOT on the command line. Every process's argv
#    is readable by other users on the same host, so a key passed with -H leaks
#    to anyone who can run ps.
umask 077; TW_CFG=$(mktemp); trap 'rm -f "$TW_CFG"' EXIT INT TERM HUP
printf 'header = "Authorization: Bearer %s"\n' "$TW_KEY" > "$TW_CFG"

# 2. List the matters you may pull a brief for (no client data in this response)
curl -s --config "$TW_CFG" \
     https://api.thewill.ai/api/v1/pro/ext/matters/

# 3. Fetch one brief. Use an id whose brief_available was true.
curl -s --config "$TW_CFG" \
     https://api.thewill.ai/api/v1/pro/ext/matters/MATTER_ID/brief/

# 4. A lapsed or revoked grant answers 404, not 403. Handle it as "not available
#    now" and re-read brief_available, rather than treating it as a hard error.
curl -s -o /dev/null -w '%{http_code}\n' --config "$TW_CFG" \
     https://api.thewill.ai/api/v1/pro/ext/matters/MATTER_ID/brief/

The matter list

/api/v1/pro/ext/matters/ answers one question: which matters may you pull a brief for, and until when. It is deliberately free of client data, so a stolen key that only ever lists learns the shape of a caseload and nothing about the people in it.

FieldMeaning
idMatter identifier. Use it in the brief path.
referenceThe same human reference the brief’s provenance block carries, so a support call can name one thing.
approach_typeHow the matter reached you.
statusWhere the matter sits in your own workflow.
urgencyUrgency the client selected.
sourceWhere the referral came from, e.g. a partner firm or a direct enquiry.
service_categoriesService categories requested.
is_priorityWhether you flagged the matter as priority.
jurisdiction_countryCountry the matter is governed by. A country code, never a client address.
jurisdiction_stateRegion within that country, where one applies.
accepted_atWhen you accepted the matter.
created_atWhen the matter was created.
updated_atWhen the matter last changed.
brief_availableTrue while the client’s consent to share is live. False means a brief fetch will answer 404, so do not attempt it.
brief_expires_atWhen that consent lapses, or null where no live grant exists. Schedule your pull before it.

The brief response, schema v2

A worked response, trimmed for length. The section bodies vary by matter and by the tier the client granted you.

{
  "export_id": "6f1b2e4a-9d33-4f7c-9d2e-0a6a2f1c8b04",
  "schema_version": "2.0",
  "issued_at": "2026-09-10T09:14:22Z",
  "expires_at": "2026-12-10T09:14:22Z",
  "matter_reference": "MATTER-3a7f19c8-2b40-4d6e-8a11-5f0c9e7d3b26",
  "recipient": {
    "professional_name": "A. Solicitor",
    "professional_id": "1d4c8b60-7e29-4f13-9c05-6a2b8d41e7f9",
    "firm_name": "Example Legal LLP",
    "regulatory_id": "000000",
    "professional_license": ""
  },
  "grant_id": "1c9f7d02-5b41-4a8e-8f0b-2d3f6a1e5c77",
  "handling_notice": "This pack is a copy of one client matter, prepared with that client's consent ...",
  "third_party_data_sections": [
    { "key": "wills", "title": "Will instructions", "whose_data": "Executors, beneficiaries, guardians, trustees and witnesses ..." }
  ],
  "brief": {
    "schema_version": "1.0",
    "generated_on": "2026-09-10",
    "tier": "full",
    "tier_display": "Full instructions",
    "tier_description": "The client shared their full instructions with you.",
    "next_step": "Draft from the instructions below.",
    "client_name": "J. Client",
    "approach_reference": "APPROACH-8c17",
    "sections": [
      { "key": "wills", "title": "Will instructions", "purpose": "...", "fields": [], "entries": [], "free_text": [] }
    ],
    "withheld": []
  },
  "sections": [
    {
      "key": "wills",
      "title": "Will instructions",
      "purpose": "What the client asked for",
      "disclosure": "full",
      "rows": [
        { "step": 3, "title": "Executors", "entries": [] }
      ]
    }
  ]
}

The envelope is fixed. Every field below is present on every successful response, though several may be null.

FieldTypeMeaning
export_idUUIDFieldUnique id for this fetch. It appears in the client’s own privacy dashboard as one exported-data row per call, so quote it when a client asks what you pulled and when.
schema_versionCharFieldThe schema this body follows. Pin on the major component only, see the versioning policy below.
issued_atDateTimeFieldWhen this copy was issued.
expires_atDateTimeFieldWhen the client’s consent for this matter lapses. Null where no expiry is set.
matter_referenceCharFieldThe same reference the list carries.
recipientDictFieldThe professional, firm and regulatory id this copy was issued to. Record it: it is your evidence of who received the data.
grant_idUUIDFieldThe client consent grant this fetch was authorised by. Null where none applies.
handling_noticeCharFieldPlain-language notice naming your firm as an independent controller of the copy. Show it to whoever handles the data in your system.
third_party_data_sectionsListFieldSections carrying data about people other than the client, flagged so your own retention rules can treat them separately. Each row carries the section key, its human title, and who those people are.
briefDictFieldThe referral brief, or null below the read-access threshold.
sectionsListFieldOnly the sections you may read for this matter at the resolved tier. A closed section is ABSENT, never present and empty. Do not read absence as "the client has none".

Errors

What each status means here, which is not always what it means generally. The 404 is the one to read carefully.

StatusWhat it means on this API
401 The key is missing, malformed, revoked or expired. Send it as Authorization: Bearer pk_… and mint a replacement in the developer hub.
403 The key authenticated but is not allowed here: either it lacks the pro:read scope, or the account does not hold the pro.api_access entitlement. Retrying will not help; fix the key or the plan.
404 Uniform refusal. The matter is not yours, does not exist, or the client’s consent has lapsed or been revoked. These are deliberately indistinguishable, so a leaked key cannot use the response to learn which matters exist. Treat it as "no data available now" and re-check brief_available on the list.
429 You exceeded a request cap. Two apply and they are independent: your plan’s hourly cap, read from the pro.api_rate_limit entitlement, and a separate egress cap on brief fetches only. Whichever runs out first answers 429. Back off and retry after the window; do not spin.

Versioning and deprecation

Pin on the major component of schema_version only. A minor bump adds fields and never removes or retypes one, so a client that pins 2 keeps working across additive releases, while a client that pins 2.0 breaks on one for no reason. Ignore fields you do not recognise rather than rejecting the response.

A major bump is announced before it ships, and the previous major stays served for the period stated in that announcement. Schema v1, the language-referral brief, remains served and no end date has been set for it; one will be announced in the same way if it ever is. Note that the nested brief object carries its own schema_version, which is the v1 family and is versioned independently of the envelope around it.

Generate your client from the schema

The field tables above are held to the serialisers that answer the requests by a test that fails on any drift, but the published schema is the contract. Point your generator at /api/v1/pro/ext/schema/, or browse it interactively:

Open the interactive API reference (opens in a new tab)

Related

Engagements are what decide which matters appear on this API at all, and a client’s consent is what decides whether a brief may be released. Both are explained in the engagement letters guide.

Can’t find what you’re looking for?

Our support team is here to help. Contact us and we’ll get back to you as soon as possible.

Contact Support

We use cookies to improve your experience. See our Cookie Policy (opens in a new tab) for details.