Nearly every unpleasant surprise on a credit-priced API comes from the same mistake: treating all calls as one thing called a request, and then budgeting by counting requests. On any legal data API worth using there are at least two distinct classes of call, they differ in cost by more than an order of magnitude, and nothing in your code tells you which one you just made.
A wallet of credits is a sensible way to price an API that does genuinely different amounts of work per call. A lookup of one case record by identifier costs the provider a database read. A semantic search over an embedded corpus costs a model invocation to extract filters from your prose, another to expand the query into legal terminology, an embedding pass, a vector search, and then a hydration step that pulls full documents from the primary store. Charging the same for both would mean either overcharging for the lookup or subsidising the search. Credits let a provider price the difference honestly.
They also let a provider price the difference dishonestly, or at least opaquely, which is why this piece is written the way it is. What follows is a structural account of where credit goes on a legal data API, which calls are cheap and deterministic, which draw AI credit and why, how cache aware billing changes the arithmetic, and the two contract terms that decide your bill far more than the headline rate does. Sticker price is the least interesting number in a credit pricing page.
Why Providers Meter in Credits Rather Than Calls
A per-call price is a promise that all calls cost the same to serve. For a static data API that is roughly true. For an API where some endpoints run a language model over a hundred thousand characters of judgment text, it is not close to true, and a provider who charges per call has to pick a price that assumes some mix of usage. If your mix is heavier on the expensive endpoints than the assumed mix, you are being subsidised. If it is lighter, you are subsidising someone else. Neither is a good basis for planning.
Credits decouple the unit of billing from the unit of transport. One HTTP request debits an amount of credit that reflects the work behind it. That is the theory, and it is a sound one. The practical consequence for an integrator is that you cannot forecast spend by instrumenting request counts. You have to instrument by endpoint, and you have to know which endpoints are in which class.
The single most useful thing you can build first
Before you build any product feature against a credit-priced API, build a per-endpoint counter. Not a total request counter. A map from endpoint path to call count, refreshed daily. Every cost conversation you will have for the next two years, internal or with the vendor, is answerable from that map and unanswerable without it. You cannot optimise a bill you cannot attribute.
The Calls That Are Cheap Because Nothing Is Being Thought About
The first class is deterministic retrieval. These calls read from an index or a document store and return what is there. The answer is the same every time for the same input, no model runs, and the cost profile is flat and predictable. On the CourtMesh API this class covers most of what an integration actually does all day.
- Keyword search, a POST to /search/cases, which queries the OpenSearch backed corpus of roughly 310 million records with your query string plus structured filters for court, case type, case number, judge, year and date range. It ranks by relevance or by date, pages with page and limit or with a searchAfter cursor, and does no interpretation of your prose whatsoever.
- Case fetch, a GET to /cases/:id, which accepts either the internal identifier or a case number and returns the stored record: title, court, judges, petitioners, respondents, decision date, disposal nature, filing and registration dates, case status and stage, next hearing date, the CNR, acts and sections, and the courtMetadata block carrying state, district and establishment names on District Court records.
- Related documents, a GET to /cases/:id/related, which gathers every stored document sharing the same case number, sorts them by decision date and returns both a relatedDocuments array and an assembled timeline, capped at 50.
- Judge search, a GET to /judges/search with a q parameter, a case insensitive substring match against the combined Supreme Court and High Court judge name lists, returning a plain array of names capped at 50 with totalMatches in meta. It is built for autocomplete and behaves like it.
- PDF links, a GET to /cases/:id/pdf, which returns a presigned pdfUrl with an expiresIn of 3600 seconds. The link is time limited and issued per request, so it must never be stored as though it were permanent.
- Health, a GET to /health, the only endpoint that needs no key at all. It returns success, status, version and a timestamp, and it exists so your monitoring does not have to spend anything to know the service is up.
Two things follow from this list. The first is that a very large share of a real integration lives here. Autocompleting a judge name, resolving a case number a user pasted in, pulling the record behind a search result, fetching a document link when someone clicks download: this is the ordinary traffic of a legal product, and none of it needs a model. The second is that the binding constraint on this class is usually not credit at all. It is the rate limit of 10 requests per minute per API key, a fixed window, with X-RateLimit-Limit, X-RateLimit-Remaining and X-RateLimit-Reset on every response and a 429 carrying retryAfter and resetTime when you breach it. Design for that ceiling and the cheap class rarely troubles your budget.
The Calls That Draw AI Credit, and What They Are Actually Doing
The second class is where a model runs. Three endpoints sit here: semantic search, single case analysis and consolidated analysis. They are not expensive because someone decided to charge more for the word AI. They are expensive because each one is several inference passes wearing a single URL.
Semantic search is five steps, not one
A POST to /search/cases/semantic looks, from your client, like a search. Inside, it is a pipeline, and it is worth knowing the order because the order explains the price.
Normalisation
The raw query is cleaned. Case numbers written as 123-2024 or 123/2024 are collapsed to 1232024 and captured separately, so an identifier buried in prose is treated as an identifier rather than as noise fed to an embedding model.
Filter extraction
A model reads the prose and pulls out structured filters: court, year, case type, case number. It also returns a cleaned query with those elements removed. This is one inference pass, and it is the step that lets a user type a sentence instead of filling a form.
Query expansion
The cleaned query is expanded into legal terminology, so a plainly worded question reaches judgments that state the same point in the vocabulary a bench would use. This is a second pass over the query.
Embedding
The expanded query is converted into a vector. Cheap relative to the reasoning steps, but still an inference call, and still not something a keyword index ever has to do.
Vector search and hydration
Only now does the request touch the vector store, with a minimum similarity threshold of 0.3 and offset based paging. Matching records are then hydrated from the primary store into full case documents, each carrying a score.
So a single semantic call has already run a model twice and embedded once before it retrieves anything. That is the honest reason it draws AI credit and keyword search does not. There is one wrinkle worth knowing for cost reasons: if filter extraction strips so much that the cleaned query falls below three characters, meaning the user supplied only filters and no real question, the request falls back to keyword search and reports meta.fallbackMode as opensearch. Watch that field. A high fallback rate means your users are typing filters into a semantic box and you are paying the reasoning tax for a keyword result.
Analysis, and why consolidated analysis costs materially more
A POST to /cases/:id/analyze runs the analysis pipeline over one document. It returns 202 with a status of processing and does the work in the background, and it returns 400 outright when the case has neither at least 100 characters of text nor any stored document to work from. That guard is a kindness: it declines to bill you for reasoning over nothing.
A POST to /cases/:id/analyze-consolidated does something structurally larger. It analyses the whole family of documents sharing one case number rather than a single document. For a Supreme Court matter it gathers related records by case number, up to 20 of them. For a High Court matter it takes the case plus its five most recent stored orders. The combined text is capped at 100,000 characters before it goes to the model. It requires a case number and returns 400 without one.
Where the cost difference actually comes from
Consolidated analysis is not a premium tier of the same operation. It feeds a materially larger document set to the model. Twenty related records, or a judgment plus five orders, against a single document. Input volume is the dominant term in the cost of a language model call, so the price difference is a property of the work rather than of the pricing page. Reach for consolidated analysis when the question genuinely spans the family of documents, and for the single case endpoint when it does not.
Cache Aware Billing: Reading Is Not Generating
This is the part that most changes real bills, and it is the part least often explained. On a well built analysis API, the expensive thing is producing the analysis, not serving it. Once a case has been analysed, that analysis is stored. Every subsequent read of it is a document fetch.
The API surfaces this distinction plainly. A GET to /cases/:id/analysis returns the stored analysis with a hasAnalysis flag, and when nothing has been generated yet, meta.note points you at the analyze endpoint rather than silently generating one and charging you. A POST to /cases/:id/analyze with force unset returns 200 immediately with alreadyExists set to true and the stored analysis attached, rather than regenerating. The consolidated endpoint behaves the same way, returning the existing consolidated analysis with a status of already_analyzed unless force is true.
force is the switch that turns a cheap read into an expensive write
Passing force true tells the API to discard the stored result and regenerate. That is exactly what you want when the underlying document has changed or when you are deliberately refreshing against a newer analysis schema. It is exactly what you do not want in a retry loop, in a background job that runs nightly over your whole watchlist, or in a client that sets it because someone copied a snippet. A force flag on a defaulted true in shared code is the single most expensive line of code you can write against a credit-priced API. Default it false, set it explicitly at the one call site that needs it, and log every call that carries it.
There is a design implication here beyond avoiding accidents. If reads of stored analyses are cheap and generations are not, then the shape of a cost efficient integration is obvious: check first, generate deliberately. Fetch the case with GET /cases/:id, look at whether analysis exists, read it with GET /cases/:id/analysis when it does, and only call analyze when a user has actually asked for something that does not yet exist. Analysis runs in the background and the API itself suggests checking back in 30 to 60 seconds, so the interaction you build around it should be a job, not a blocking call.
The Two Terms That Actually Decide Your Bill
Now the argument this piece exists to make. When people compare credit-priced APIs, they compare the rate: how many credits a plan includes for a given amount of money. That number is the least predictive input in the whole comparison. Two other terms decide what you pay.
Credit expiry
Credits that expire are not the same asset as credits that do not. A grant that lapses at the end of a period converts unused headroom into nothing, which means your effective rate is not the sticker rate but the sticker rate divided by your utilisation. If you use sixty percent of a monthly grant, you are paying roughly a sixty seven percent premium on every credit you actually consumed, and no line in the pricing page says so.
This matters more in legal software than in most categories, because legal usage is lumpy. Due diligence on a transaction, a litigation audit for a new client, a bulk review before a hearing block: these arrive in bursts and leave quiet weeks behind them. A plan sized for the burst wastes credit in the quiet weeks if credits expire monthly. A plan sized for the average runs dry in the burst and pushes you onto overage rates. Rollover, or a longer expiry horizon, is what makes lumpy usage affordable, and it is worth more than a modest discount on the headline rate.
Pay as you go multipliers
The second term is what happens when you run out. Almost every provider sells top up credit at a worse rate than plan credit, and the multiplier between the two is where the real money sits. If plan credit is one unit and overage credit is two, then any month where you exceed your allowance by a third has an effective cost well above what your spreadsheet predicted, because a third of your usage is priced at double.
The two terms interact, and they interact badly. Expiring credits push you towards buying small so you do not waste. Buying small pushes you into overage during bursts. Overage is priced at a multiplier. That loop is how an integration with entirely reasonable usage ends up materially over budget while every individual decision looked prudent.
| Term to ask about | Why it matters | What a good answer looks like |
|---|---|---|
| Credit expiry | Unused credit that lapses raises your effective rate by the inverse of your utilisation, silently. | A stated expiry horizon, rollover of unused balance, or credits that simply do not expire while the account is active. |
| Overage multiplier | Top up credit priced above plan credit is where burst months become expensive months. | A published pay as you go rate you can compute against, not a sales conversation triggered by exhaustion. |
| Per-endpoint cost | You cannot forecast without knowing which calls are cheap reads and which run a model. | A published breakdown that separates deterministic retrieval from AI endpoints, and separates single from consolidated analysis. |
| Cached read treatment | If reading a stored analysis costs the same as generating one, your bill scales with views rather than with work. | Explicit confirmation that reads are cheap, that alreadyExists short circuits generation, and that force is the only way to regenerate. |
| Failure billing | A 502 from an upstream registry or a 408 on a long query is not a result you can use. | A clear statement of what is billed on non-2xx responses, and on a semantic call that fell back to keyword mode. |
| Rate limit versus credit | Ten requests per minute per key is a throughput ceiling, entirely separate from spend. | Documented limits, rate limit headers on every response, and a 429 body carrying retryAfter and resetTime. |
| Free or trial grant shape | A one time grant that lapses cannot support a product; a recurring allowance can. | A recurring allowance with stated terms, rather than a lump sum that quietly ends the project when it runs out. |
A Worked Example, Clearly Illustrative
Real rates live at API pricing and they change, so the arithmetic below uses a symbol rather than a number. Nothing here is a quoted price. Let C be the credit cost of one deterministic call, and suppose for the sake of the shape of the calculation that a semantic search costs 10C and a single case analysis costs 20C. Substitute the current published values before you plan anything.
Take a modest litigation research product with 200 active users. In a month, suppose the traffic looks like this: 40,000 judge autocomplete calls, 12,000 keyword searches, 9,000 case fetches, 3,000 related document calls, 2,000 semantic searches, and 400 analyses generated on cases that did not already have one, plus 6,000 reads of analyses that already existed.
- Deterministic traffic: 40,000 plus 12,000 plus 9,000 plus 3,000 plus 6,000 cached analysis reads is 70,000 calls at C, so 70,000C.
- Semantic traffic: 2,000 calls at 10C is 20,000C.
- Generated analyses: 400 calls at 20C is 8,000C.
- Total: 98,000C, of which the 2,400 AI calls, under two and a half percent of request volume, account for roughly 28,000C, or a bit over a quarter of consumption.
Now change one thing. Suppose a nightly job re-analyses every case in every user watchlist with force set to true, and that comes to 6,000 regenerations. Those 6,000 calls at 20C are 120,000C, more than the entire rest of the integration combined, produced by a background job nobody demonstrated in a sprint review and no user asked for. The analyses it regenerates are, for the most part, identical to the ones already stored.
On a credit-priced API, the expensive code is almost never the code a user is looking at. It is a loop, a retry policy, or a nightly job written by someone who did not know which class of call they were in.
Designing an Integration That Does Not Leak Credit
None of the following is exotic. All of it is the difference between an integration whose cost tracks its usefulness and one whose cost tracks its bugs.
Route by question type before you route by convenience
An identifier, a case number, a party name or a judge name is a keyword question and belongs on /search/cases or /judges/search. A described fact pattern is a semantic question. Sending everything through semantic search because it handles both is the most common and most expensive design error in this category.
Cache what is stable and never cache what is not
Case records, related documents and stored analyses change rarely, so cache them in your own store with a sensible time to live and serve repeat views from there. The presigned pdfUrl from /cases/:id/pdf expires in 3600 seconds and is issued per request, so cache the case metadata around it and fetch the link fresh each time.
Make analysis a user-triggered job, never a page-load side effect
Generating analysis on render means every refresh, every crawler and every duplicate tab is a candidate for a model call. Trigger it on explicit intent, return 202 and a pending state, and poll the case record afterwards.
Treat force as a privileged operation
Default it false everywhere. Set it at exactly one call site. Log every request that carries it with the reason and the caller. If it appears in a retry path or a scheduled job, that is a defect until proven otherwise.
Respect the rate limit rather than discovering it
Ten requests per minute per key is a fixed window. Read X-RateLimit-Remaining, queue rather than burst, and back off on 429 using the retryAfter value in the body. A retry storm against a rate limit is how a cheap endpoint becomes an availability problem.
Instrument credit at the call site, not at the invoice
Emit a metric per endpoint per call with the caller, the feature and whether force was set. Reconcile it against the account balance weekly. Discovering a cost regression at the end of a billing period means paying for the whole period.
Size the plan against the burst and negotiate the tail
Look at your worst week rather than your average one, then ask what happens to the unused credit in a quiet month and what the top up rate is in a busy one. Those two answers determine your annual cost more than the plan price does.
How to Read a Pricing Page, Yours or Anyone Else's
Comparing vendors on effective rupee per call is the only comparison that survives contact with reality, and computing it takes about twenty minutes with your own numbers. Estimate your monthly volume split by class: deterministic calls, semantic searches, single analyses, consolidated analyses, and cached analysis reads. Convert each to credits using the vendor's published per-endpoint costs. Divide the plan price by the credits you will actually consume rather than by the credits you are granted, because the difference between those two numbers is the expiry term made visible. Then repeat the calculation for your worst month, applying the overage multiplier to everything above the allowance.
Do that for two vendors and the ranking will frequently invert relative to the headline rate. A provider with a slightly worse per-credit price, credits that do not expire and a modest overage multiplier will usually beat a provider with an attractive rate, monthly expiry and expensive top ups, for any workload that is not perfectly flat. Legal workloads are never perfectly flat.
The question to ask before you sign anything
Ask what happens to unused credit at the end of the period, and ask what a credit costs once the allowance is gone. Those two answers, together with your own per-endpoint call mix, tell you your real annual cost. Everything else on the pricing page is context. Current CourtMesh rates, plan structure and the per-endpoint breakdown are published at API pricing, and the endpoint semantics that determine which class each call falls into are at the API documentation.
What the Credit Is Actually Buying
It is worth ending on what sits behind the meter, because cost optimisation that degrades the answer is not a saving. The keyword corpus runs to roughly 310 million cases sourced directly from official government portals, the eCourts system, the NJDG and court registries, with no third party intermediary between the registry and your result. It spans the Supreme Court, all 25 High Courts, the district judiciary and tribunals including NCLT, NCLAT, ITAT, CESTAT, SAT, TDSAT and DRT.
The semantically embedded and AI analysed corpus is far smaller, in the low millions. That is a real and important limit and it should shape how you spend. Semantic search runs against the analysed slice, not against all 310 million records, so a query that needs exhaustive coverage of a High Court under section 138 of the Negotiable Instruments Act 1881 belongs on keyword search with filters, both because it is cheaper and because it is more complete. Metadata quality also varies: District Court records are thinner than Supreme Court records, and older records are thinner than recent ones. Spending AI credit to reason over a sparse record does not make the record less sparse.
The discipline this adds up to is unglamorous. Know which class each call belongs to. Read before you generate. Treat force as dangerous. Instrument per endpoint. Then negotiate expiry and the overage multiplier rather than the headline rate, because those are the terms that will decide what you actually pay, in every month that does not look exactly like the average one.
Price the integration you are actually going to build
Credit pricing is fair when you know which calls run a model and which merely read a store, and expensive when you do not. The CourtMesh API separates the two plainly: keyword search, case fetch, related documents, judge search and PDF links are deterministic retrieval, while semantic search and the two analyze endpoints run models and draw AI credit. Stored analyses are cheap to read and only regenerate when you pass force. Current rates and plan terms, including how credit expiry and pay as you go work, are at API pricing. The endpoint reference that tells you which class each call falls into is at the API documentation, and there is an API overview.
Explore CourtMesh


