Quickstart
Create an API key, then list matters, browse documents and run a search with curl.
Before you start
- A Sentinel staff account with access to at least one matter.
- Your firm's Sentinel address, from Your account → Connected apps. It looks like
https://yourfirm.api.sntlabs.io.
1. Create an API key
In Sentinel, open Your account → Connected apps → For developers: API keys. Name the key, choose an expiry, and select Create key. Copy it right away, because Sentinel shows it only once.
Keep the key in environment variables rather than in your code:
export SENTINEL_API="https://yourfirm.api.sntlabs.io/api/v1"
export SENTINEL_KEY="sk_live_..."An API key acts as you, with your access to every matter you can open. Treat it like a password, and revoke it when you're done.
2. List your matters
curl "$SENTINEL_API/matters?limit=5" \
-H "Authorization: Bearer $SENTINEL_KEY"import os, httpx
api = os.environ["SENTINEL_API"]
headers = {"Authorization": f"Bearer {os.environ['SENTINEL_KEY']}"}
matters = httpx.get(f"{api}/matters", params={"limit": 5}, headers=headers).json()const api = process.env.SENTINEL_API;
const headers = { Authorization: `Bearer ${process.env.SENTINEL_KEY}` };
const matters = await fetch(`${api}/matters?limit=5`, { headers }).then((r) => r.json());{
"data": [
{
"id": "3f6c2a1e-8b4d-4c7a-9e21-5d0b7f9a1c34",
"type": "case",
"number": "CASE-2025-0142",
"title": "Acme Corp. v. Rivera",
"status": "litigation",
"priority": "high",
"sub_type": "trade_secrets",
"closed": false,
"archived_at": null,
"created_at": "2025-03-04T15:12:09.000Z"
}
],
"pagination": { "limit": 5, "has_more": true, "next_cursor": "WyIyMDI1LTAy…" }
}To get the next page, pass next_cursor back as cursor. See Pagination.
3. Browse a matter's documents
curl "$SENTINEL_API/matters/3f6c2a1e-8b4d-4c7a-9e21-5d0b7f9a1c34/documents?custodian=Rivera&limit=10" \
-H "Authorization: Bearer $SENTINEL_KEY"docs = httpx.get(
f"{api}/matters/3f6c2a1e-8b4d-4c7a-9e21-5d0b7f9a1c34/documents",
params={"custodian": "Rivera", "limit": 10},
headers=headers,
).json()const docs = await fetch(
`${api}/matters/3f6c2a1e-8b4d-4c7a-9e21-5d0b7f9a1c34/documents?custodian=Rivera&limit=10`,
{ headers },
).then((r) => r.json());Each document has its file name, type, custodian, Bates number, dates and, for emails, the envelope: subject, sender, recipients and sent time.
4. Search
curl "$SENTINEL_API/matters/3f6c2a1e-8b4d-4c7a-9e21-5d0b7f9a1c34/search" \
-H "Authorization: Bearer $SENTINEL_KEY" \
-H "Content-Type: application/json" \
-d '{"query": "price list Northwind", "mode": "hybrid", "limit": 5}'hits = httpx.post(
f"{api}/matters/3f6c2a1e-8b4d-4c7a-9e21-5d0b7f9a1c34/search",
json={"query": "price list Northwind", "mode": "hybrid", "limit": 5},
headers=headers,
).json()["data"]const { data: hits } = await fetch(`${api}/matters/3f6c2a1e-8b4d-4c7a-9e21-5d0b7f9a1c34/search`, {
method: "POST",
headers: { ...headers, "Content-Type": "application/json" },
body: JSON.stringify({ query: "price list Northwind", mode: "hybrid", limit: 5 }),
}).then((r) => r.json());Hits come back best first, each with the document, a snippet and a score. Use keyword mode for exact phrases, names and Bates numbers, and semantic mode to search by meaning.
5. Read a document
curl "$SENTINEL_API/documents/8e4b1f7a-3c9d-4a52-b6e0-1d7f2c9a5b84?include=text" \
-H "Authorization: Bearer $SENTINEL_KEY"doc = httpx.get(f"{api}/documents/8e4b1f7a-3c9d-4a52-b6e0-1d7f2c9a5b84", params={"include": "text"}, headers=headers).json()
print(doc["text"])const doc = await fetch(`${api}/documents/8e4b1f7a-3c9d-4a52-b6e0-1d7f2c9a5b84?include=text`, { headers }).then((r) => r.json());
console.log(doc.text);include=text adds the document's extracted text.