One call, start to finish
This is a complete request. Paste it with a real key and you get the response below it. The quickstart walks the same billing-dispute scenario in its fullrecords[] form; this is the short text form of it.
reduction_ratio on this request is 0.7. That number is a property of
these eight paragraphs at this budget, not a claim about your workload: run it
on your own traffic before you assume anything about it.
Make your first call
cURL, Python and TypeScript, with the full
records[] form of the same
scenario.What makes it different
Selection, not rewriting
Needlepath decides which of your records to send. It does not paraphrase or
summarise them into new prose, and there is no model in the loop writing
replacement text. Every excerpt is built from the record’s own content.It is not a byte-for-byte guarantee: an excerpt may be non-contiguous,
normalised, or re-encoded. When you need exact bytes, join on
record_id and
use your own copy. See
what comes back.It declines
When trimming would not pay, Needlepath stands down and hands your context
back essentially intact rather than cutting for the sake of cutting. A
stand-down is a normal
200; see Reading a stand-down.Stateless by construction
Records ride in on every request and nothing is persisted. The selection path
runs without the authority to store your content, so there is no mechanism by
which your records could be kept. One field is the deliberate exception:
request_id is logged, because it is your correlation key. See
Retention and trust.Pinned configuration
An operating point is an opaque, immutable label naming a frozen
configuration. Retuning mints a new label; a published label never changes
meaning, so the settings you pinned are the settings you keep getting.What it pins is the configuration, not the engine build that reads it.
See what a label pins.
When to reach for it
Needlepath is aimed at the case where a model call has more candidate context than budget, and where the candidates are heterogeneous (a tool result, a retrieved page, a schema, three turns of conversation) rather than a uniform list of retrieved chunks. It is a good fit when:- an agent loop is accumulating tool results and the message list is growing faster than the useful signal in it;
- you are already retrieving more than you can afford to send;
- the content must survive intact, because it is a schema, a legal clause, a code fragment or a JSON payload that a summariser would break.
The two rules for every integration
Both are load-bearing. Every first-party integration obeys them and yours should too.1
Fail open
If the call times out, returns non-2xx, or returns an empty selection, send
your original context unmodified. Selection is an optimisation; a failed
optimisation must degrade to “no optimisation”, never to an empty prompt.
2
Pin the operating point
Always send
budget.operating_point. Omitting it inherits the server’s
current default, and that default moves when a new label is minted, which is
exactly how behaviour changes under a caller who never asked for it.Where to go next
Quickstart
Your first call, in three languages.
Authentication
Bearer keys, format, rotation.
Limits
What each limit is, and how exact it actually is.
API reference
Every field, generated from the contract.
Clients and adapters
Python and TypeScript clients, plus LangChain, LiteLLM and LlamaIndex.