courtmesh 0.5.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- courtmesh-0.5.0/.gitignore +16 -0
- courtmesh-0.5.0/CHANGELOG.md +238 -0
- courtmesh-0.5.0/LICENSE +21 -0
- courtmesh-0.5.0/PKG-INFO +728 -0
- courtmesh-0.5.0/README.md +697 -0
- courtmesh-0.5.0/pyproject.toml +58 -0
- courtmesh-0.5.0/src/courtmesh/__init__.py +249 -0
- courtmesh-0.5.0/src/courtmesh/_http.py +288 -0
- courtmesh-0.5.0/src/courtmesh/_version.py +9 -0
- courtmesh-0.5.0/src/courtmesh/client.py +1469 -0
- courtmesh-0.5.0/src/courtmesh/errors.py +474 -0
- courtmesh-0.5.0/src/courtmesh/models.py +1361 -0
- courtmesh-0.5.0/src/courtmesh/monitoring.py +139 -0
- courtmesh-0.5.0/src/courtmesh/py.typed +0 -0
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to `courtmesh` are documented here. The format follows
|
|
4
|
+
[Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
|
|
5
|
+
|
|
6
|
+
Each entry also states which server flags/behaviour the version targets on
|
|
7
|
+
the CourtMesh research server, since some of this SDK's contract only takes
|
|
8
|
+
effect once a given server flag is on for your account.
|
|
9
|
+
|
|
10
|
+
## [0.5.0]
|
|
11
|
+
|
|
12
|
+
Adds CNR lookup and case monitoring (API docs 1.3.0).
|
|
13
|
+
|
|
14
|
+
### Added
|
|
15
|
+
|
|
16
|
+
- `get_case_by_cnr(cnr, fetch=False)` for `GET /cases/by-cnr/{cnr}`, and a `cnr` argument on `search_cases` (exact match; `query` is now optional when `cnr` is given).
|
|
17
|
+
- Watchlists: `create_watchlist`, `list_watchlists`, `get_watchlist`, `update_watchlist`, `delete_watchlist`, `add_watchlist_items`, `list_watchlist_items`, `remove_watchlist_item`.
|
|
18
|
+
- Change feed: `list_changes`, `list_watchlist_events`, with generators `iter_changes` and `iter_watchlist_events` that walk pages until caught up.
|
|
19
|
+
- Webhooks: `create_webhook`, `list_webhooks`, `get_webhook`, `update_webhook`, `delete_webhook`, `rotate_webhook_secret`, `test_webhook`, `list_webhook_deliveries`, `retry_webhook_delivery`, plus `iter_watchlists`, `iter_watchlist_items`, `iter_webhooks` and `iter_webhook_deliveries`.
|
|
20
|
+
- `verify_webhook_signature(raw_body, header, secret, tolerance_seconds=300)` and `WebhookSignatureError`.
|
|
21
|
+
- `normalize_cnr` and `assert_cnr`, exported, matching the server's CNR normalisation.
|
|
22
|
+
- Typed models for all of the above, including `ChangeEvent` and `CursorListResult`.
|
|
23
|
+
- `PATCH` and `DELETE` support in the HTTP layer. `DELETE` is retried like `GET`; `PATCH` and all new `POST` calls follow the `retry_posts` rule and send an `Idempotency-Key` when it is in effect.
|
|
24
|
+
|
|
25
|
+
### Changed
|
|
26
|
+
|
|
27
|
+
- `get_case_by_cnr` with `fetch=True`: the call that starts the fetch returns `pending` and is free; the poll that returns the record is the one 1 credit charge. `requestId` is opaque and is polled via the same call, not `get_timeline`.
|
|
28
|
+
- `ITEM_NOT_FOUND` documented; `Webhook.secretRotating` added.
|
|
29
|
+
- `request_timeline(refresh=True)` now costs 1 credit (it was 20). Docs and docstrings updated.
|
|
30
|
+
- `search_cases` takes `query` as optional (required unless `cnr` is set).
|
|
31
|
+
- `User-Agent` is `courtmesh-python/0.5.0`.
|
|
32
|
+
- Project URLs now point at `github.com/thinkscoop-technologies/courtmesh-python`.
|
|
33
|
+
- `WatchlistItem.status` gains `unavailable` (a case taken down at a party's request: `caseId`, `court`, `title`, `snapshot`, `lastCheckedAt` and `lastChangedAt` are `None`, no events are sent). Adding a taken down CNR returns `not_found`.
|
|
34
|
+
- Documented the daily add allowance per account (Free 50, Pay As You Go 5,000, Scale 50,000, Enterprise 500,000) on top of the daily limit on new CNRs; both report `cap_exceeded`. The watch cap counts distinct CNRs across all lists.
|
|
35
|
+
- Documented the 24 hour cooldown after the court portal has nothing for a CNR: watchlist adds return `not_found` and `get_case_by_cnr(..., fetch=True)` raises `NotFoundError` without a new fetch.
|
|
36
|
+
- Documented that `search_cases(cnr=...)` returns one ordinary search hit, that `case.tracking_started` is sent after the first fresh refresh, that a burst announces the newest 20 orders and never orders dated more than 7 days before watching began, that feed cursors are opaque and `since` is converted once, and that dates are `YYYY-MM-DD` with 9999 meaning no date.
|
|
37
|
+
- Documented webhook behaviour: `test_webhook` is sent even to a disabled endpoint, 10 second deadline and 64 KB read per attempt, never attempted deliveries older than 24 hours are `failed` with `lastError: "expired"`, a webhook created without `events` echoes the full default `case.*` list, and `watchlist_ids=[]` means all lists. `create_webhook` honours `idempotency_key`.
|
|
38
|
+
- Validation error `details` is a list of `"path: message"` strings for query and body alike.
|
|
39
|
+
|
|
40
|
+
## [0.4.1]
|
|
41
|
+
|
|
42
|
+
Live QA pass against the redeployed production research server
|
|
43
|
+
(`research.courtmesh.ai`, 2026-09-19) and its updated OpenAPI spec. All items
|
|
44
|
+
below were confirmed with live calls against an Enterprise key, not only
|
|
45
|
+
against the spec.
|
|
46
|
+
|
|
47
|
+
### Added
|
|
48
|
+
|
|
49
|
+
- `User-Agent: courtmesh-python/0.4.1` sent on every request.
|
|
50
|
+
- `UsageTierLimits["published"]`: this tier's number in the OpenAPI
|
|
51
|
+
rate-limit table, distinct from `requestsPerMinute` (the number actually
|
|
52
|
+
enforced right now) until the API self-serve tiers flag is on for your
|
|
53
|
+
account, at which point the two converge.
|
|
54
|
+
- `CoverageMeta["snapshotAgeSeconds"]`, `["cacheAgeSeconds"]` and
|
|
55
|
+
`["stale"]`, replacing a single `ageSeconds` field that never actually
|
|
56
|
+
existed on the wire.
|
|
57
|
+
- `CoverageCourt["courtType"]`, now explicitly `Optional[str]` (added to the
|
|
58
|
+
live schema 2026-09-19).
|
|
59
|
+
- `HealthCheckEntry`, `HealthCheckResult`, `PartyScreenRedactedName` and
|
|
60
|
+
`PartyScreenRedactedAliases` (carried forward from the interim QA branch,
|
|
61
|
+
re-verified live, see Changed below).
|
|
62
|
+
|
|
63
|
+
### Changed
|
|
64
|
+
|
|
65
|
+
- **Breaking:** `AuditHit["userAgent"]` removed - the redeployed server no
|
|
66
|
+
longer sends it at all (dropped for privacy alongside raw `ipAddress`,
|
|
67
|
+
which never appeared on the wire in the first place). `AuditHit["ipHash"]`
|
|
68
|
+
(a SHA-256 digest of the caller's IP) is retained; a same-day interim fix
|
|
69
|
+
had renamed `ipAddress` to `ipHash`, which remains correct.
|
|
70
|
+
- **Breaking:** `UsageTierLimits`: every field but `requestsPerMinute` (and
|
|
71
|
+
now `published`) is `Optional`, matching a live Enterprise-key response
|
|
72
|
+
with the self-serve tiers flag off. `limits` itself is confirmed always a
|
|
73
|
+
populated dict, never `None`.
|
|
74
|
+
- **Breaking:** `CoverageCourt`/`CoverageByCourtType`/`CoverageDistrictCourts`
|
|
75
|
+
date and `businessDaysBehind` fields are now `Optional`, matching the live
|
|
76
|
+
schema.
|
|
77
|
+
- `AuditHit["metadata"]` is now `Optional[Dict[str, Any]]` - observed `None`
|
|
78
|
+
in production for hits with nothing to log, not only omitted.
|
|
79
|
+
- `HealthResponse["checks"]` entries are bare status strings in production
|
|
80
|
+
(`"ok" | "fail" | "skipped"`), not `{"status", "latencyMs"?, "error"?}`
|
|
81
|
+
dicts; `HealthCheckEntry` accepts either shape (interim fix, re-verified
|
|
82
|
+
live).
|
|
83
|
+
- `PartyScreenQueryEcho["name"]`/`["aliases"]` are redacted to
|
|
84
|
+
`{"redacted": True, "length": ...}`/`{"redacted": True, "count": ...}` on
|
|
85
|
+
a replayed idempotent `party/screen` response instead of echoing the
|
|
86
|
+
original string/list (interim fix, re-verified live via a same-key
|
|
87
|
+
replay).
|
|
88
|
+
- Confirmed unchanged and correct: `caseNumber` is a string (never a number)
|
|
89
|
+
on every endpoint that returns one; the five idempotency-key-aware POST
|
|
90
|
+
endpoints (`screen_party`, `screen_party_batch`, `analyze_case`,
|
|
91
|
+
`analyze_consolidated`, `request_timeline`) still send `Idempotency-Key`
|
|
92
|
+
and mark a replay; the per-endpoint default timeouts are unchanged.
|
|
93
|
+
|
|
94
|
+
### Removed
|
|
95
|
+
|
|
96
|
+
- `AuditHit["userAgent"]` (see Changed above).
|
|
97
|
+
|
|
98
|
+
## [0.4.0]
|
|
99
|
+
|
|
100
|
+
Targets the research server's account-introspection endpoints
|
|
101
|
+
(`GET /usage`, `GET /me`, `GET /audit`), the public reference endpoints
|
|
102
|
+
(`GET /reference/courts`, `GET /reference/case-types`), the new
|
|
103
|
+
`POST /party/screen/batch` endpoint, and the `Idempotency-Key` contract
|
|
104
|
+
being rolled out across the five job/charge-triggering POST endpoints.
|
|
105
|
+
|
|
106
|
+
### Added
|
|
107
|
+
|
|
108
|
+
- `get_usage()`: `GET /usage`, this key's tier, wallet balance,
|
|
109
|
+
`TIER_LIMITS` for that tier, the current Asia/Kolkata billing period and a
|
|
110
|
+
per endpoint call breakdown. Unmetered.
|
|
111
|
+
- `me()`: `GET /me`, the calling account's id, email, name, role and (if
|
|
112
|
+
any) organization id.
|
|
113
|
+
- `audit(...)`: `GET /audit`, this key's own logged calls (or, for an org
|
|
114
|
+
admin, an organization's), with summary stats and a top-endpoints
|
|
115
|
+
breakdown. Takes `organizationId`, `userId`, `limit`, `offset`,
|
|
116
|
+
`startDate`, `endDate`. Returns a new `AuditResult` dataclass (`data`,
|
|
117
|
+
`pagination`, `request_id`).
|
|
118
|
+
- `reference_courts()`: `GET /reference/courts`, the court taxonomy
|
|
119
|
+
accepted by `court` filters elsewhere in this API. No API key required.
|
|
120
|
+
- `reference_case_types()`: `GET /reference/case-types`, every `caseType`
|
|
121
|
+
value accepted elsewhere in this API. No API key required.
|
|
122
|
+
- `screen_party_batch(items, purpose, ...)`: `POST /party/screen/batch`,
|
|
123
|
+
screens 1 to 25 names in one call; each item is independently priced and
|
|
124
|
+
can independently fail (`result.data["results"][i]["ok"]`) without
|
|
125
|
+
failing the whole batch. Not available on the Free tier. LLM adjudication
|
|
126
|
+
is not supported in the batch endpoint.
|
|
127
|
+
- `health()` now takes a `deep` argument, `health(deep=True)` calls
|
|
128
|
+
`GET /health?deep=1`: also checks Mongo, OpenSearch, Qdrant, Redis and IAM
|
|
129
|
+
standing, and reports `status in ("degraded", "unhealthy")` plus a
|
|
130
|
+
`checks` dict per dependency. `HealthResponse` gained `commit` and
|
|
131
|
+
`checks`.
|
|
132
|
+
- `idempotency_key` argument on `screen_party`, `screen_party_batch`,
|
|
133
|
+
`analyze_case`, `analyze_consolidated` and `request_timeline`: sent as
|
|
134
|
+
the `Idempotency-Key` header (1 to 128 characters, `[A-Za-z0-9_.-]`,
|
|
135
|
+
scoped per API key for 24 hours). A replayed call with the same key and
|
|
136
|
+
body returns the stored response again (`result.replayed is True`, no
|
|
137
|
+
new charge); the same key with a different body raises `ConflictError`
|
|
138
|
+
with `code == "IDEMPOTENCY_KEY_REUSED"`. When omitted, and `retry_posts`
|
|
139
|
+
is in effect for that call (the call's own override, or the client's
|
|
140
|
+
default), the SDK auto-generates a UUID v4 so an automatic retry of that
|
|
141
|
+
exact call is always safe from a double charge or a double-run job.
|
|
142
|
+
- `APIResponse.request_id` / `.replayed` (also on `SearchCasesResult` and
|
|
143
|
+
`SemanticSearchResult`, `request_id` only): every response now carries
|
|
144
|
+
the request id, either the server's own `meta["requestId"]`/body level
|
|
145
|
+
`requestId` when it set one, or (backfilled client side as a fallback)
|
|
146
|
+
the `X-Request-Id` response header. `replayed` is `True` when the
|
|
147
|
+
response carried `Idempotency-Replayed: true`.
|
|
148
|
+
- `ConflictError` (409): raised by the five idempotency-key-aware methods
|
|
149
|
+
when the same `Idempotency-Key` was reused with a different body
|
|
150
|
+
(`code == "IDEMPOTENCY_KEY_REUSED"`) or a request with that key is still
|
|
151
|
+
in flight (`code == "IDEMPOTENCY_IN_PROGRESS"`).
|
|
152
|
+
`IDEMPOTENCY_KEY_REUSED`, `IDEMPOTENCY_IN_PROGRESS` and
|
|
153
|
+
`IDEMPOTENCY_KEY_INVALID` added to `API_REFUSAL_CODES`/`ApiRefusalCode`.
|
|
154
|
+
- New models: `ApiTier`, `UsageData`/`UsageMeta`/`UsageBalance`/
|
|
155
|
+
`UsageTierLimits`/`UsagePeriod`/`UsageByEndpoint`/`UsageWalletOwner`,
|
|
156
|
+
`MeData`, `AuditResult`/`AuditData`/`AuditHit`/`AuditSummary`/
|
|
157
|
+
`AuditTopEndpoint`/`AuditPagination`, `CourtHierarchy`/`CourtNamesMap`,
|
|
158
|
+
`CaseTypeEntry`, `PartyScreenBatchItemOk`/`PartyScreenBatchError`/
|
|
159
|
+
`PartyScreenBatchItemResult`/`PartyScreenBatchSummary`/
|
|
160
|
+
`PartyScreenBatchResult`/`PartyScreenBatchMeta`, `HealthCheckResult`.
|
|
161
|
+
|
|
162
|
+
## [0.3.0]
|
|
163
|
+
|
|
164
|
+
Targets the research server after the 2026-09-18 API abuse-control and
|
|
165
|
+
parity pass (`server/config/api-tiers.ts`, `server/routes/api-v1-prod.ts`,
|
|
166
|
+
`server/middleware/api-tier-limits.ts`, `server/utils/rate-limiter.ts`).
|
|
167
|
+
Correct against that server regardless of whether `API_SELF_SERVE_TIERS` is
|
|
168
|
+
on for your account, though several fields (`cursor`, tier refusal codes,
|
|
169
|
+
per tier pagination caps) are only ever populated once it is.
|
|
170
|
+
|
|
171
|
+
### Added
|
|
172
|
+
|
|
173
|
+
- `cursor` request field on `search_cases`, and `pagination["nextCursor"]`
|
|
174
|
+
can now be a signed opaque string (when the API self-serve tiers flag is
|
|
175
|
+
on for your account) as well as the legacy raw list. `searchAfter` is
|
|
176
|
+
documented as deprecated/legacy.
|
|
177
|
+
- `iter_search_cases` is now cursor-first: it passes
|
|
178
|
+
`pagination["nextCursor"]` back as `cursor` (or, on the legacy list
|
|
179
|
+
shape, continues via `searchAfter`) instead of only incrementing `page`.
|
|
180
|
+
- `refresh` argument on `request_timeline`; `result.meta["liveFetch"]` and
|
|
181
|
+
`result.data["liveFetchSupported"]` on its response.
|
|
182
|
+
- `allow_remote_fetch` argument on `analyze_case`.
|
|
183
|
+
- `meta["sortBy"]`, `meta["warnings"]`, `meta["someRecordsWithheld"]` and
|
|
184
|
+
`meta["restrictedCheckDegraded"]` on `search_cases` and `semantic_search`.
|
|
185
|
+
- `PayloadTooLargeError` (413).
|
|
186
|
+
- `API_REFUSAL_CODES` (tuple) and `ApiRefusalCode` (`Literal`), mirroring
|
|
187
|
+
the server's own machine refusal codes plus the handler-local and
|
|
188
|
+
SDK-synthesised ones (`CASE_RESTRICTED`, `PDF_NOT_STORED`,
|
|
189
|
+
`CASE_NOT_FOUND`, `PARTY_SCREEN_SEARCH_DEGRADED`, `CURSOR_INVALID`,
|
|
190
|
+
`PAGE_LIMIT_EXCEEDED`, `PAGINATION_DEPTH_EXCEEDED`, the `API_KEY_*` auth
|
|
191
|
+
codes, `ORGANIZATION_DEACTIVATED`, `ACCOUNT_STANDING_UNAVAILABLE`,
|
|
192
|
+
`IP_NOT_ALLOWED`, `VALIDATION_ERROR`, `MALFORMED_JSON`,
|
|
193
|
+
`PAYLOAD_TOO_LARGE`, and more) and `is_retryable_429_code`.
|
|
194
|
+
- `code` and `request_id` on every exception class (previously there was no
|
|
195
|
+
machine-readable `code` attribute at all, only `response_body["code"]`).
|
|
196
|
+
- `wallet`, `wallet_owner` and `contact_admin` on `InsufficientCreditsError`;
|
|
197
|
+
`limit` and `tier` on `ValidationError`, with a synthesised `message` for
|
|
198
|
+
the two pagination cap codes (whose response body carries no message of
|
|
199
|
+
its own) and, more generally, `_http.py`'s error message now falls back
|
|
200
|
+
to the machine `code` when the body has neither `error` nor `message`.
|
|
201
|
+
- `retry_posts` and `max_retry_after_seconds` client options (also
|
|
202
|
+
overridable per call), and per call `timeout=`/`retry_posts=` arguments
|
|
203
|
+
on every endpoint method.
|
|
204
|
+
- Per endpoint default timeouts: `semantic_search` 630s, `request_timeline`
|
|
205
|
+
240s, `analyze_consolidated` 300s, `screen_party` 90s, everything else 30s.
|
|
206
|
+
- `PartyRole`, `PartyScreenRelatedMatch` and `PartyScreenQueryEcho` types.
|
|
207
|
+
|
|
208
|
+
### Changed
|
|
209
|
+
|
|
210
|
+
- **Breaking:** `CaseListItem` now exposes `id`/`score`/`highlights` as the
|
|
211
|
+
primary fields; `_id`/`_score` are kept but documented as legacy.
|
|
212
|
+
- **Breaking:** `PartyScreenCoverage` no longer has `candidatesEvaluated` or
|
|
213
|
+
`adjudicationsRun` - `adjudicationsRun` moved to a top level field of
|
|
214
|
+
`PartyScreenResult` (matching the server's actual response shape).
|
|
215
|
+
- **Breaking:** `semantic_search`'s `caseNumber` argument is now a single
|
|
216
|
+
digits-only string (was a string-or-list, validated but silently ignored
|
|
217
|
+
by the handler for any value that was not already digits-only); `judges`/
|
|
218
|
+
`judge` are now aliases collapsed into the single `judgeName` field sent
|
|
219
|
+
on the wire, matching what the vector store actually matches against
|
|
220
|
+
(one judge name).
|
|
221
|
+
- Only `RATE_LIMITED` and `CONCURRENT_ANALYSIS_LIMIT` are retried
|
|
222
|
+
automatically on a 429; a daily/monthly cap code never is.
|
|
223
|
+
- A POST is no longer retried automatically after a connection/timeout
|
|
224
|
+
error or a 502/503/504 response, unless `retry_posts=True`. A 429 is
|
|
225
|
+
unaffected by this (it is a pre-flight refusal on every method).
|
|
226
|
+
- Renamed "CourtMesh Enterprise API" to "CourtMesh API" throughout.
|
|
227
|
+
|
|
228
|
+
### Removed
|
|
229
|
+
|
|
230
|
+
- Deleted four stale README caveats that no longer describe the live
|
|
231
|
+
server: `caseNumber` is applied server side (not ignored); `sortBy`
|
|
232
|
+
supports `relevance`/`recent`/`oldest` (not only `relevance`);
|
|
233
|
+
`semantic_search`'s top level filter fields are merged in, not ignored;
|
|
234
|
+
`semantic_search` no longer returns HTTP 200 for a failed request.
|
|
235
|
+
|
|
236
|
+
## [0.2.0] and earlier
|
|
237
|
+
|
|
238
|
+
Pre-dates this changelog. See git history.
|
courtmesh-0.5.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Thinkscoop Technologies LLP
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|