Attach footnote texts to their in-text markers from page layout coordinates
Given footnote markers (label, page, x, y) and footnote texts (label, page, x, y) extracted from a laid-out document, pairs each marker with its note by label and page, pairing repeated labels on one page in reading order, optionally letting a note continue on the next page, and reports unattached markers, orphan notes, ambiguous groups (different counts for the same label) and notes placed above their marker on the same page. Uses only the coordinates and labels the caller supplies: it does not read PDFs, detect markers or guess when counts disagree.
What you get
Rebuilds footnotes from extracted layout without misattaching a note to the wrong marker. 500 markers per $0.005 call.
Call it
Send the JSON body below to https://agents.writerslogic.com/api/v1/footnote-attach. An unpaid request answers 402 with the price and how to pay; a request that fails with a 5xx status is not charged.
curl -i -X POST https://agents.writerslogic.com/api/v1/footnote-attach \
-H 'content-type: application/json' \
-d '{"markers":[{"label":"1","page":3,"x":200,"y":140},{"label":"2","page":3,"x":90,"y":400}],"notes":[{"label":"1","page":3,"x":72,"y":700,"text":"First note."},{"label":"2","page":3,"x":72,"y":720,"text":"Second note."}]}'
Input
| Field | Type | Required | Description |
|---|---|---|---|
markers | array<object>; max 500 items | yes | |
notes | array<object>; max 500 items | yes | |
yAxis | string; one of "down", "up" | no | Direction of increasing y: down (PDF.js, screen) or up (PDF user space). Default down. |
allowNextPage | boolean | no | A note may sit on the page after its marker. Default false. |
Example request body
{
"markers": [
{
"label": "1",
"page": 3,
"x": 200,
"y": 140
},
{
"label": "2",
"page": 3,
"x": 90,
"y": 400
}
],
"notes": [
{
"label": "1",
"page": 3,
"x": 72,
"y": 700,
"text": "First note."
},
{
"label": "2",
"page": 3,
"x": 72,
"y": 720,
"text": "Second note."
}
]
}
Result
The response is { "data": ..., "_provenance": ... }. data carries these fields; _provenance is a signed W3C Verifiable Credential with a C2PA-style manifest, checked free at POST /api/v1/verify-provenance.
| Field | Type | Required | Description |
|---|---|---|---|
status | string; one of "pass", "fail", "unknown", "unsupported" | no | pass: every rule held. fail: a rule was violated (see witnesses). unknown: the input lacks the evidence to decide. unsupported: outside what this engine covers. Missing evidence is never a pass. |
attachments | array<object>; max 500 items | no | |
unattachedMarkers | array<integer>; max 500 items | no | |
unattachedNotes | array<integer>; max 500 items | no | |
ambiguousGroups | array<object>; max 500 items | no | |
witnesses | array<object> | no | |
versions | object | no | Every semantic dependency of this answer (engine, tables and their as-of dates, tokenizer, calendar, rounding profile). |
limits | array<string> | no | |
deterministic | boolean | no | Always true: pure code, no model. |
Pay and connect
Available through: x402 (USDC on Base), MCP. MCP clients reach it through the context-evidence-kit package.
Machine-readable
- This agent as JSON (schemas, example, OpenAPI operation)
- Free signed sample response
- OpenAPI 3.1 · Catalog · Index of every agent