TrustPDF

Facts about a PDF, over HTTP or MCP.

One endpoint, no account, and no signup. Send a document, get back what is in it — cited to byte offsets, with benign and adversarial readings side by side. You decide what it means; we do not.

https://trustpdf.io schema 1

The whole integration

curl -X POST https://trustpdf.io/v1/analyze \
  -H "Authorization: Bearer $TRUSTPDF_KEY" \
  -H "Content-Type: application/pdf" \
  --data-binary @document.pdf

That is the integration. There is no session to establish, no token to refresh and no account to create. A key is a bearer instrument: we store its digest and a balance, and nothing that identifies you.

Callers whose input must be JSON can send {"document": "<base64>"} as application/json instead.

Three ways in

SendYou get
nothing one test check, when a slot is available — up to 4 MB
Authorization: Bearer tp_… a document analysed against your balance
PAYMENT-SIGNATURE one document, paid for on its own with x402

Test checks prove an integration end to end. They are not a tier to build on, and the limits say so: one document anywhere every 15 minutes, one per caller every 3 hours, and the same 4 MB ceiling every route has. The first of those is shared, so a slot taken by anyone is a slot nobody else has until it comes round.

A document costs 1 to 4 units by size, and a key spends units on the same scale a single payment does, so the two never price the same file differently.

Sending the same document twice

Send bytes you have already been given a report for, under the same engine, and that report comes back at no charge, marked — CACHED: 1 and ANALYSED-AT, the second you first received it. The engine is deterministic, so it is the same artefact rather than a second one, and you paid for the analysis once. A ruleset change makes it a new document again.

?force=1, or force: true over MCP, runs the engine anyway at the usual price. Paying per document with x402 never returns a stored report at all.

We will never tell you whether anyone else has sent a document — not with a flag, not by answering faster, not by leaving your allowance untouched. CACHED means "you have had this", never "this has been seen". Uploading a copy of a document is not a way to find out who else has been looking at it.

Getting a key

POST /v1/bundle with no payment returns 402 and a price list. Pay it with x402 and the same request returns a key. Send a key you already hold and the purchase credits that key instead of issuing another.

A key bought over HTTP works over MCP, and the other way round — the ledger has never known which surface sold one. It is shown once and cannot be recovered; anyone holding it can spend it.

GET /v1/history returns what your key has been spent on: when, your document's digest, its size, how long the call took, what it cost and what was left. It answers only for the key that asks, and costs nothing.

What comes back

A report validating against the contract at /v1/schema. Two arrays, and both matter: observations is what was found, and undetermined is what could not be checked and why.

Every observation carries its evidence and both readings of it — the ordinary explanation and the adversarial one, unweighted and in that order. There is no score, no risk level and no judgement of authenticity, because the decision belongs to whoever bears the consequences of getting it wrong.

schema is the envelope version. Refuse a report whose version you do not recognise rather than guessing at it.

MCP

{ "mcpServers": { "trustpdf": {
    "type": "http",
    "url": "https://trustpdf.io/mcp",
    "headers": { "Authorization": "Bearer tp_…" } } } }

The same capabilities as tools, plus two things HTTP has no way to ask for: the report contract, and every observation identifier this engine can emit with what each one means. An agent can read both before it spends anything, which is the reason to prefer MCP where you have the choice.

The full reference

/v1/docs is every endpoint, price, header and refusal code, as Markdown — written for pasting into an editor or a context window. It is generated from the same settings that enforce it, so a price there cannot disagree with a price in a 402.