API documentation.
The API exposes three trimming operations and a way to read current limits. Start with a single trim, then use batches or a shared context budget.
Quickstart
Base URL: https://trimwise.aatbit.com. Send JSON over HTTPS. No API key is required.
Use a bounded HTTP timeout and the application's existing HTTP client. Without network access, use the locally installed Python library with any required tokenizer or model assets already cached.
Queryless curl
With strategy: auto and no query, Trimwise uses structural selection.
curl -sS https://trimwise.aatbit.com/api/v1/trim \
-H 'Content-Type: application/json' \
-d '{
"text": "The answer is in this sentence. Background text follows.",
"limit": 7,
"unit": "words",
"strategy": "auto"
}'
Query-aware curl
Add a question to focus selection. With auto, a nonblank query selects lexical ranking.
curl -sS https://trimwise.aatbit.com/api/v1/trim \
-H 'Content-Type: application/json' \
-d '{
"text": "The answer is in this sentence. Background text follows.",
"limit": 7,
"unit": "words",
"strategy": "auto",
"query": "Where is the answer?"
}'
Python (queryless)
import json
import urllib.request
data = {
"text": "The answer is in this sentence. Background text follows.",
"limit": 7,
"unit": "words",
"strategy": "auto",
}
request = urllib.request.Request(
"https://trimwise.aatbit.com/api/v1/trim",
data=json.dumps(data).encode(),
headers={"Content-Type": "application/json"},
)
with urllib.request.urlopen(request, timeout=30) as response:
print(json.load(response))JavaScript (queryless)
const data = {
"text": "The answer is in this sentence. Background text follows.",
"limit": 7,
"unit": "words",
"strategy": "auto"
};
const response = await fetch("https://trimwise.aatbit.com/api/v1/trim", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(data),
signal: AbortSignal.timeout(30000),
});
console.log(await response.json());Request bodies
Send a JSON object with Content-Type: application/json. Field types are strict; unknown fields are rejected.
The machine-readable schema is at /openapi.json.
POST /api/v1/trim
Trim one text under its own output budget.
{
"text": "The answer is in this sentence. Background text follows.",
"limit": 7,
"unit": "words",
"strategy": "auto"
}
text— required string to trim; an empty string is valid.limit— required integer, zero or greater. This is the maximum output size inunit; zero returns empty text.unit— optionaltokens,words, orcharacters; omitted ornulluses the current default.strategy— optionalauto,structural,lexical,semantic, orhybrid; omitted ornulluses the current default. Only enabled strategies are accepted.query— optional string ornull. A nonblank question makesautoquery-aware; explicitlexical,semantic, andhybridrequire one. Explicitstructuraldoes not use it for ranking.
POST /api/v1/trim/batch
Trim each input separately. Every input has its own
limit and can use a different unit, strategy, or query.
There is no shared output budget for the batch.
{
"inputs": [
{
"text": "The answer is in this sentence. Background text follows.",
"limit": 7,
"unit": "words",
"strategy": "auto"
},
{
"text": "Another source has context.",
"limit": 18,
"unit": "characters",
"strategy": "lexical",
"query": "context"
}
]
}
inputs— required nonempty array of up to 20 single-trim objects. Missingunitorstrategyuses the current default for that input. The batch body accepts onlyinputsat the top level; a top-levellimit,unit,strategy, orqueryreturns422.- All inputs are checked before trimming starts. If one is invalid—for example, a negative limit or
lexicalwithout a query—the whole request fails with422; there is no partial result.
POST /api/v1/context
Choose excerpts from several sources under one shared
output limit. Set limit, unit, strategy, and query
once for the whole request.
{
"sources": [
"First source evidence.",
{
"text": "Second source evidence.",
"prefix": "Source 2: "
}
],
"limit": 8,
"unit": "words",
"separator": "\n\n"
}
sources— required nonempty array of strings or source objects; at most 20 sources. A source object requires stringtext; optional stringprefixandsuffixdefault to empty strings. Wrappers appear around contributing excerpts but do not affect ranking.limit— required integer, zero or greater, shared by all sources.unit,strategy,query— optional, with the same types, defaults, and query rules as a single trim.- Sources cannot override the shared
limit,unit,strategy, orquery. Adding those fields to a source object returns422. Use a batch if each text needs different settings. A source may receive no excerpt when the shared budget is spent elsewhere, but it still has a response row. deduplicate— optional boolean, defaultfalse. For semantic or hybrid ranking, identical passages can share embedding work; it does not remove duplicate sources or response rows.separator— optional string ornull, defaultnull. A string is copied between contributing sources and enables a complete renderedtext, even when it is empty.
Options and behavior
Set the output size
limit is the maximum size of the returned text. unit says how to measure it:
tokens use the server's configured tokenizer, words split on whitespace,
and characters count Unicode codepoints. The current default unit is
tokens. A limit of 0 returns no text.
Choose which excerpts to keep
The current default strategy is auto.
This server allows auto, structural, lexical, semantic, hybrid.
autouses document structure when there is no nonblank query, or word matching when there is one. It never selects semantic or hybrid ranking.structuraluses document structure and ignores a supplied query for ranking.lexicalmatches words from the query;semanticuses the configured CPU model to match meaning;hybridcombines both.
Choose lexical, semantic, or hybrid only with a nonblank
query; otherwise the request returns 422.
Response bodies
Successful requests return JSON. Here is a single-trim response for Cats matter.
with a five-word limit, auto strategy, and no query:
{
"text": "Cats matter.",
"input_count": 2,
"output_count": 2,
"limit": 5,
"unit": "words",
"strategy": "structural",
"trimmed": false,
"spans": [
{
"start": 0,
"end": 12
}
]
}
Single trim
textis the result. It may join several excerpts with omission markers rather than copy one continuous passage.input_countmeasures the original text;output_countmeasures the result. Both useunit, and the output count stays withinlimit.limitandunitshow the budget used, including the default unit when you omit it.strategyshows what actually ran. Anautorequest reportsstructuralorlexical.trimmedistruewhen the result differs from the original text.spansshow where retained excerpts came from in the original text. Eachstartis included and eachendis excluded:original[start:end]gives that excerpt. Offsets use Unicode codepoints (Python string positions), which can differ from JavaScript UTF-16 positions. Generated markers have no spans.
Batch
results contains one single-trim response for each input, in the same order:
results[0] belongs to inputs[0]. Each result reports its own limit,
unit, and resolved strategy, even when the inputs use different settings.
Shared context
One response covers the shared budget and includes a row for every source.
limitandunitshow the shared budget;strategyshows the method that actually ran.sourceshas one row per input source, in input order.source_indexis its zero-based position. A source with no selected excerpt still has a row with emptytext, zerooutput_count, and nospans.- In each source row,
textis the selected excerpt,input_countandoutput_countmeasure that source before and after trimming,trimmedsays whether its text changed, andspanspoint into the original source text. - The top-level
textis the complete rendered context when you provide a source object or a separator, even an empty one. It includes wrappers and separators that fit the budget. If every source is a plain string andseparatoris omitted ornull, it isnull; use the source rows instead. - The top-level
input_counttotals the original source texts.output_countmeasures renderedtextwhen present; otherwise it totals the source-row output counts. It stays within the sharedlimit. Source-row counts exclude wrappers and separators, so they may not add up to the rendered count. - The top-level
trimmedistrueif any source text changed, even if rendering also adds wrappers.
Source spans refer to each source's original text, not wrappers, separators, or generated omission markers.
Limits and errors
Latest limits. The aggregate word limit counts the entire request, including every batch input or context source.
GET /api/v1/limits
Read the current request limits, defaults, enabled strategies, supported units, API version, and discovery rate settings as JSON. No request body or API key is needed.
Example response from this server's loaded configuration:
{
"api_version": "0.2.0",
"limits": {
"active": 100,
"waiting": 150,
"queue_timeout_seconds": 60.0,
"body_timeout_seconds": 30.0,
"retry_after_seconds": 7,
"max_body_bytes": 1048576,
"max_input_words": 15000,
"max_items": 20,
"max_query_chars": 5000,
"max_wrapper_chars": 5000,
"max_separator_chars": 5000
},
"request_defaults": {
"unit": "tokens",
"strategy": "auto",
"allowed_strategies": [
"auto",
"structural",
"lexical",
"semantic",
"hybrid"
]
},
"units": [
"tokens",
"words",
"characters"
],
"limits_discovery": {
"requests_per_second": 10.0,
"burst": 20
}
}
Fetch limits with a timeout
Bash or another shell with curl (prints response headers, including Retry-After):
curl -sS --connect-timeout 5 --max-time 10 -D - https://trimwise.aatbit.com/api/v1/limits
PowerShell (returns the parsed JSON; on an HTTP error, inspect the response's headers in the application's error handler):
Invoke-RestMethod -Uri "https://trimwise.aatbit.com/api/v1/limits" -TimeoutSec 10
limits describes the request limits in the table below. request_defaults gives the default unit and strategy plus allowed_strategies. units lists supported budget units. api_version is the service version. These values come from the same settings used to validate requests; administrators restart the service to apply changes.
This endpoint reports configured limits, not free processing slots, and does not reserve capacity. It has a separate rate limit shared by all callers: 10 requests per second, with a burst of 20. A full bucket starts with that many requests; it refills at the configured rate, up to the burst limit. It does not use the trimming queue.
Fetch limits once when an integration run starts. Reuse them during the run and refresh after a size or field-limit error. Responses use Cache-Control: no-store so HTTP caches do not serve stale settings or another caller's retry delay.
If discovery returns 404, that deployment has not added the endpoint; do not keep retrying it.
Use a last known settings snapshot or compatible OpenAPI schema and handle validation errors normally.
An offline reference is a snapshot, not proof of current production settings. On other temporary failures,
honor Retry-After when present and cap retries within the caller's latency budget.
Request limits
| Limit | Current value | What it covers |
|---|---|---|
| Input words | 15,000 aggregate input words | All submitted text, queries, prefixes, suffixes, and separators together. |
| JSON body | 1,048,576 bytes | Actual request body size, including chunked uploads. |
| Batch or context size | 20 items | Inputs in one batch or sources in one context request. |
| Query | 5,000 codepoints | Length of each query. |
| Source wrappers | 5,000 codepoints | Combined prefix and suffix for each context source. |
| Separator | 5,000 codepoints | Length of the context separator. |
| Processing | 100 active requests | API requests that can process at the same time. |
| Waiting | 150 requests, 60 seconds | Maximum queue size and time allowed before processing starts. |
| Body read | 30 seconds | Time allowed to receive a request body. |
Error responses
Errors return {"error":{"code":"...","message":"..."}}.
Use code to identify the reason; message is a short, safe description.
| Status | Meaning |
|---|---|
422 | Invalid or missing fields, including a required query or an overlong query, wrapper, or separator. |
413 | Request body, aggregate word count, or batch/context item count exceeds its limit. |
415 | Content type is not application/json. |
408 | The body did not arrive in time, or the client disconnected while sending it. |
429 | Limits discovery rate exceeded. The error code is rate_limited; Retry-After gives the seconds to wait until one request token refills, rounded up. |
503 | Processing is busy, queue wait expired, or semantic processing is unavailable. |
500 | Unexpected server error. |
A 503 response includes Retry-After: 7 (seconds).
For discovery 429 responses, the delay is calculated each time. Wait at least that long before trying again, using a capped retry policy; another caller may use the next token first.
Every response includes X-Request-ID for support and troubleshooting.