AmberPen Get started

HTTP API reference

The API speaks JSON over HTTPS. All the shapes on this page ship as TypeScript types in @amber-pen/sdk, which also handles serialization and error mapping for you.

Authentication and key types

Send either key type as Authorization: Bearer <api-key>. Live ap_live_v1 keys require an active subscription. Verified accounts can create one ap_test_v1 key for free; it calls the same endpoint and returns the same response shapes.

Test-key allowance is shared across the account:

  • 20 requests per minute
  • 1,000 weighted input characters per request, including dictionary and proper-noun entries
  • 200 request units and 50,000 weighted input characters per UTC day

An evaluate request consumes two request units and twice its weighted input length. Successful responses expose minute limits in RateLimit-* headers and daily allowance in X-Test-Daily-* headers. See Testing for free for the complete setup and quota guide.

POST /proofread

Proofreads text and returns the edits needed to construct the corrected version.

curl https://api.amberpen.dev/proofread \
	-H "authorization: Bearer $AMBER_PEN_API_KEY" \
	-H "content-type: application/json" \
	-d '{ "text": "This are a sentnce by AmberPen and cachebuster.", "dictionary": ["cachebuster"], "properNouns": ["AmberPen"] }'

Request body

FieldTypeDescription
textstringRequired. The complete text to proofread. Empty text is accepted and produces no edits.
dictionarystring[]Words the correction pass should recognize and preserve.
properNounsstring[]Names the correction pass should recognize and preserve.
mode"correct" | "evaluate"The strategy; defaults to correct. evaluate adds a second pass that reviews each proposed edit and is billed at twice the character usage.
streambooleanSet to true to stream complete edit batches as NDJSON.

textId is not a request field: incremental proofreading is handled by the SDK for both proofread and proofreadStream. The SDK diffs the text in your process, strips the identifier, and sends only the chunks that changed. A direct HTTP request body containing textId is rejected with a 400.

Response

Both modes return an edits array. Correct mode returns plain edits:

{
	"mode": "correct",
	"processingTimeMs": 217,
	"edits": [
		{ "id": 0, "start": 5, "end": 8, "original": "are", "replacement": "is" },
		{ "id": 1, "start": 11, "end": 18, "original": "sentnce", "replacement": "sentence" }
	]
}

In evaluate mode the second pass has already reviewed each proposed edit, so the array only contains edits worth applying, and every edit adds three fields: possibleReplacements ranked by relevance, a category, and a one-sentence explanation written in the language of the submitted text.

{
	"mode": "evaluate",
	"processingTimeMs": 434,
	"edits": [
		{
			"id": 0,
			"start": 5,
			"end": 8,
			"original": "are",
			"replacement": "is",
			"possibleReplacements": ["is"],
			"category": "grammar",
			"explanation": "The singular subject “This” takes “is”."
		},
		{
			"id": 1,
			"start": 11,
			"end": 18,
			"original": "sentnce",
			"replacement": "sentence",
			"possibleReplacements": ["sentence", "sentience"],
			"category": "spelling",
			"explanation": "“sentnce” is misspelled."
		}
	]
}
FieldDescription
modeThe strategy that produced the response: "correct" or "evaluate".
processingTimeMsCumulative time spent waiting for inference-provider responses, in milliseconds. Evaluate mode includes both passes.
editsSorted, non-overlapping edits that transform the submitted text into the corrected text.

Streaming response

With stream: true, the response uses application/x-ndjson. Every non-empty line is a complete edit array with offsets into the full submitted text. Correct mode emits TextEdit[]. Evaluate mode collects correction proposals in document order, evaluates them five at a time, and emits complete EvaluatedEdit[] batches. A final empty array marks successful completion. Use the SDK's proofreadStream method to parse transport fragments, validate batches, and detect truncated streams.

curl -N https://api.amberpen.dev/proofread \
	-H "authorization: Bearer $AMBER_PEN_API_KEY" \
	-H "content-type: application/json" \
	-H "accept: application/x-ndjson" \
	-d '{ "text": "This are a sentnce.", "mode": "correct", "stream": true }'

[{"id":0,"start":5,"end":8,"original":"are","replacement":"is"}]
[{"id":1,"start":11,"end":18,"original":"sentnce","replacement":"sentence"}]
[]

Edits

FieldDescription
idIdentifier unique within the containing edit list.
start / endInclusive start and exclusive end offsets, in UTF-16 code units — pass them directly to String.prototype.slice.
originalThe exact source substring between start and end.
replacementThe text to insert in place of original.
possibleReplacementsEvaluation mode only. Valid replacements in descending order of relevance. The first value equals replacement.
categoryEvaluation mode only. spelling, grammar, style, or repetition.
explanationEvaluation mode only. A one-sentence explanation of the issue, in the language of the submitted text.

The SDK's applyEdits(text, edits) reconstructs the corrected text from a response's edits.

GET /health

Returns { "status": "ok" } when the API is ready to receive requests. No authentication required.

Errors

Failures return a JSON body with a human-readable message:

{
	"error": "Field 'text' must be a string"
}
StatusWhen
400Invalid JSON, missing text, or an unrecognized mode / model value.
401The Bearer API key is missing, invalid, expired, or revoked.
413The request body or test-key weighted input limit was exceeded.
429A test key exceeded its minute or daily allowance. Inspect Retry-After and the rate-limit headers.
404Unknown method or path.
503Proofreading failed upstream, or test quota enforcement or another required service is temporarily unavailable.

A failure that interrupts a stream is delivered as a JSON object on its own NDJSON line rather than as an HTTP status, and that object carries a stable code. The terminal empty array is not sent, so a stream that ends without one has failed.

{"error":"Service unavailable, please try again later or contact our support at contact@amberpen.dev","code":"provider_error"}
CodeMeaning
configuration_errorThe server is misconfigured for the requested pass.
provider_errorThe inference provider returned an error.
invalid_provider_responseThe provider's output could not be parsed.
invalid_editA generated edit did not match the source text.