Select the records worth sending to a model
Send every record you are considering plus the task they must serve. Needlepath returns the subset it selected — together with a rendered block, per-record scores and reasons, and the token arithmetic.
Selection, not rewriting. Nothing is paraphrased or summarised into
new prose and no model writes replacement text; an excerpt is built from
the record’s own content. It is not guaranteed byte-identical to a
span of your input — see SelectedRecord.excerpt. If you need exact
spans, join on record_id and use your own copy.
Stateless. Records ride in on every request; nothing is persisted
between calls. The same request under the same operating_point gets
the same answer — with two caveats worth knowing before you assert on
it in a test: record order breaks score ties, and a record sent
without an id comes back under a freshly generated one, so
selected[].record_id will differ between two otherwise identical
calls. Send ids.
A stand-down is a success. If the engine judges that trimming would
not pay, it returns your context essentially intact with
fallback_used = true and, when a gate verdict ran, gate.engaged = false plus a reason. Treat it as a normal 200 and send what you were
going to send. Do not treat a low tokens_saved as an error.
Fail open. If this call times out, returns non-2xx, or returns an empty selection, send your original context unmodified. It is a binding rule for every integration, first-party or yours.
Authorizations
Authorization: Bearer np_live_…
One credential form. There is no query-parameter, cookie or
x-api-key alternative — the legacy x-api-key header stopped being
accepted at the Bearer cutover and now fails authorization.
Keys are org-scoped, never user-scoped, and the secret is shown exactly once at mint. Rotation is create-then-revoke.
Body
ContextRequest. Maximum body size is 6 MB — the AWS Lambda
synchronous payload cap. API Gateway rejects an oversized body before
the service is invoked, so guard it client-side rather than relying on
a readable error.
Your correlation id for this unit of work. The response echoes it back byte-for-byte, and the published client raises if it does not match — so it is the key you join a response back to a request on.
Keep it to ≤ 128 characters from [A-Za-z0-9._:-]. An id outside
that bound is still echoed to you unchanged, but the internal
correlation copy is truncated and de-fanged, and the response then
carries format_metrics.request_id_sanitized: true so you can see it
happened. Two consequences worth designing for: an id that differs
only past character 128 is indistinguishable in our logs, and
anything you put in this field reaches our logs — so do not put
record content, customer text or credentials in it.
"req-2026-08-01-0001"
The state Needlepath may keep, drop or excerpt. An empty array is accepted and yields an empty selection.
Order is a tie-breaker. Records that score equally are ranked by the order they arrived in, so reordering an otherwise identical request can change which records survive a tight budget. Send a stable order if you want stable results.
Record count is capped per request alongside the token ceiling, because selection cost scales with count as well as size. See Limits.
The query the selected context has to serve.
The operating point, in arm-neutral quantities only.
No method-tuning knobs appear here or anywhere else in the request.
Thresholds, weightings, tier rules and gate parameters are resolved
server-side from the operating_point label. That is a contract
property, not an omission: it is what makes a published label
reproducible and what keeps a benchmark comparison honest.
Ask for rendered_context, a model-facing string assembled from the
selection. Set false if you assemble the prompt yourself from
selected[].
Currently ignored — the rendered block is always built and returned. Discard it client-side until this is wired.
A neutral rendering hint, not a method knob.
plain (the default) leaves excerpts as text. hybrid additionally
allows a structured excerpt — JSON, typically — to be re-encoded into
a more compact form when that would save tokens; excerpt_format on
each selected record reports which form was used. Send plain if
you intend to re-parse excerpts as JSON.
plain, hybrid Include the selected[] detail — per-record score, reason, excerpt
and token count. Set false and you get rendered_context plus the
token arithmetic only, which is a materially smaller response body.
Response
A selection. Includes stand-downs and engine-internal failures —
see fallback_used and selection_error. This service returns 200
with a usable body rather than a 5xx when its own selection pass
fails, because the correct client behaviour in that case is to send
the original context, which the body already contains.
The selection.
Required by the contract (the published client raises if any is
missing, or if request_id does not echo): request_id,
rendered_context, tokens_before, tokens_after, tokens_saved,
records_available, records_selected, fallback_used,
engine_latency_ms.
Everything else is optional and new optional fields ship within
/v1 — ignore what you do not recognise.
The first field that will exercise that rule is already designed and is
documented in this file as the Usage schema. It is deliberately not
listed as a property below, because it is not serving: listing it would
make every generated client carry a field that never arrives.
Your request_id, echoed byte-for-byte.
The model-facing block, assembled from the selection. Empty when you
sent render: false.
The engine's own accounting of the context available before filtering.
On this deployment it works out to exactly
Σ estimate_tokens(record.text). It is still not the billing
quantity: the meter additionally counts record.title,
task.prompt and task.recent_prompts, so input_tokens is the
larger number and the two will not match.
It is also an engine-internal quantity by definition rather than by promise — it is a per-record sum taking a maximum against the summary the engine holds, which on this deployment is your text. Budget against it; do not reconcile an invoice with it.
Context size after selection, on the same engine-internal basis as tokens_before.
tokens_before − tokens_after. Zero on a stand-down, and that is a
correct outcome rather than a failed one.
How many records the engine considered.
How many it selected.
The engine stood aside and returned your context essentially intact.
fallback_used = true does not tell you why, and three different
causes produce it: a deliberate gate stand-down, an empty or
unusable record set, and an engine-internal exception. Read gate
and selection_error to tell them apart, and see
format_metrics.engine_fallback_reason.
Server-measured selection time. It excludes network transit, so it is not your round trip, and the two are different measurements that must not be compared or added together casually.
Example values in this document are illustrative and are not a performance commitment. Measure your own end-to-end latency from your own client.
The frozen version behind the operating_point that actually ran.
Record it with every result: it is what makes a result file
self-describing, and it is how you detect that you inherited a
default you did not choose.
Per-record detail, in selection order. Empty when you sent
return_per_record: false, and also empty on some stand-downs —
an empty selected[] is not by itself evidence that nothing was
selected. Read records_selected for that.
Set when the engine's own selection pass raised. The HTTP status is still 200 — the body carries a usable full-context result, which is what a client should send anyway. If you monitor Needlepath, alarm on this field, not on 5xx: an availability metric defined on status code reports health straight through an engine outage.
The budget the returned selection was produced under.
Every rung attempted on the adaptive ladder, in order. Empty on the fixed path. This is the field to watch if you want to know whether an adaptive workload is doing several selection passes per request.
tokens_saved / tokens_before, on the engine-internal basis. Zero
when tokens_before is zero.
Present only when a coverage verdict actually ran. null on the
plain fixed-budget path, so a null safety means "no verdict was
computed", never "the verdict was fine".
Present when a gate decision was made.
Free-form, additive rendering and diagnostic telemetry. Treat unknown keys as informational. Keys you may see today:
engine_fallback_reason— present only when the engine actually stood aside, carrying its own reason. This is the field that distinguishes "nothing cleared the selection floor" from other stand-downs on the fixed path, wheresafetyis null.request_id_sanitized: true— yourrequest_idviolated the length or charset bound and the internal copy was truncated and de-fanged. The echo you received is still your bytes.client_latency_ms— added by the client, not by the server. The published Python client records its own round trip here. Do not read it as a server measurement.