# PDF tool match API · v1

This is a free, documentation-reviewed prototype. Payments are disabled. A $1 report is a proposed future offer, not an active checkout or subscription. No payment details, accounts, or API keys are collected by the application.

The browser form runs the same matching code locally. The Worker package also exposes these routes when deployed. A route listed here is a contract, not proof that your host has deployed it: check `GET /api/v1/status` first. The current public deployment exposes the form and API without an application API key. Other deployments may apply hosting access controls; this prototype does not create API keys.

## Routes

- `GET /api/v1/status`: service/data versions, evidence date, current price, compute bounds
- `GET /api/v1/quote`: $0 now; proposed future $1; no payment required or taken
- `GET /api/v1/schema`: request JSON Schema
- `GET /api/v1/example`: example request
- `POST /api/v1/pdf-tool-match`: deterministic report
- `GET /tool-match/response.schema.json`: success/error response JSON Schema

Send `Content-Type: application/json`. The maximum request body is 4,096 bytes. Only one bounded object is accepted; documents, text, URLs, credentials and arbitrary extra fields are rejected. Compressed bodies are not accepted. No file uploads, LLM calls, external APIs, database, analytics, or application input storage are used. Hosting may retain ordinary access logs.

## Example

```json
{
  "pdf_type": "digital",
  "os": "macos",
  "hardware": "cpu_only",
  "local_only": true,
  "commercial_use": true,
  "programming": "python",
  "table_type": "ruled",
  "max_results": 3
}
```

The canonical public origin is `https://proof.hammerhandworks.com`. The original `https://proof-of-use.vinnyd329.chatgpt.site` origin remains supported. Both expose the same relative API routes. For another deployment, use its own origin.

```sh
curl --request POST "https://proof.hammerhandworks.com/api/v1/pdf-tool-match" \
  --header 'Content-Type: application/json' \
  --data @example-request.json
```

The current public deployment needs no application API key. If a host enables restricted access, use its authorized access flow; this command does not bypass it.

## Input meaning

All seven preference fields are required. `max_results` is optional, defaults to 3, and must be an integer 1–5.

- `pdf_type`: `digital`, `scanned`, `mixed`. Describe every target table page. Selectable text elsewhere in the PDF does not make scanned tables digital.
- `os`: `windows`, `macos`, `linux`
- `hardware`: `cpu_only`, `nvidia_gpu`, `apple_silicon`. This is available hardware, not a requirement to accelerate. Documented CPU fallback can qualify. OS/architecture combinations are checked conservatively.
- `local_only`: boolean. True means document content is processed locally; installation, model downloads, update checks and other network traffic are separate. Strict air-gap behavior is not certified.
- `commercial_use`: boolean. True requires source-backed eligibility for the reviewed code and relevant model bundle. A permissive code license does not clear all weights or inputs. This is a license screen, not legal advice.
- `programming`: `no_code`, `command_line`, `python`. This is maximum acceptable interface complexity. Python users can also use a GUI; CLI users are not assumed to write Python table-extraction scripts.
- `table_type`: `ruled`, `borderless`, `complex`, `unknown`. Unknown means no layout constraint was supplied; the report explicitly asks you to validate a sample and does not promise all-layout compatibility.

Budget is not a v1 request field. Tool package fees and unmeasured operating costs are separate report context.

## Response

A valid match request always returns HTTP 200, including abstentions:

- `status`: `matched` or `abstained`
- `report_id`: deterministic SHA-256 identity of normalized input, service version and the full reviewed dataset
- `candidates`: only tools with all required constraints supported; ranked by documented workflow fit
- `needs_review`: tools with missing/ambiguous evidence and no known mismatch
- `rejected`: tools with at least one known mismatch, also retaining any unknowns
- `counts`: total reviewed, qualified, returned, needs-review and rejected
- `constraints`, `reasons`, `rejections`, `unknowns`: per-tool decisions with source IDs
- `code_license`, `model_licenses`: distinct terms, plus configuration-specific caveats and preflight checks
- `sources`: official documentation links and check dates
- `evidence_status`: `documentation_reviewed_not_tested`
- `price_quote`: current amount 0 USD, payments disabled, no commitment

No three-result guarantee exists. A no-code scanned-PDF request returns no qualified matches in this five-tool edition. Commercial-use-required requests never promote the reviewed OCR/ML pipelines while full model-bundle terms remain unresolved.

Ranking is editorial workflow fit, not measured accuracy or performance: +20 for native-text focus on digital input or OCR focus on scanned/mixed input; +10 for a focused table-extraction workflow; +5 for a guided UI when no-code is required. Profiles must resolve to reviewed sources. Ties sort by tool ID, ascending. Hard constraints are evaluated before scoring; ranking cannot override an unsupported or unknown constraint.

Source dates are review dates, not immutable release pins. Main/stable branches can change. Reports must be checked against representative, non-sensitive local samples before adoption.

## Errors

Errors have a machine-readable `error` object (`code`, `message`, `details`), `schema_version`, and `payment_taken: false`. Error details never echo rejected input values.

- 400 `empty_body`, `invalid_json`, `invalid_body`
- 404 `not_found`
- 405 `method_not_allowed` with `Allow`
- 413 `request_too_large`
- 415 `unsupported_media_type`, `unsupported_encoding`
- 422 `invalid_request`: per-field `required`, `invalid_type`, `invalid_enum`, `unknown_field`, `out_of_range`
- 500 `service_error`: unexpected internal failure; no payment taken

## Retries and bounded operation

The service is stateless and has no paid or other mutating side effects. Identical normalized input and unchanged code/data produce the same JSON response and report ID; key order and omitted/default `max_results` do not change identity. No idempotency key is needed. This is not a promise of request deduplication, persistent history, rate limiting, or production abuse controls.

Each request examines at most 20 in-memory tool profiles (five currently), returns at most five recommendations, and makes zero downstream calls. Before broader traffic or a paid launch, separately review traffic limits, operational budget, access control, deployment terms, payments, refunds and support policy.


## Consuming the audit efficiently

The response includes the complete decision audit, including exclusions, source records and separate model terms. The verified example response was approximately 52 KB. Parse it as JSON; start with `status`, `summary`, `counts`, and `candidates` with their reasons, caveats and preflight checks. Retrieve the relevant `sources` entries by source ID when explaining or verifying a decision. There is no need to place the entire audit verbatim into an agent's prompt. Preserve the full JSON as the inspectable report, and keep unknowns and abstentions visible in any shorter presentation.
