# Fare API docs

Base URL: `https://api.fare.dev`

## Authentication

Send your key in the `X-API-Key` header (or `Authorization: Bearer <key>`). Keys start with `fare_live_`. Fare is in private beta; keys are issued by invitation.

Free beta plan: 500 successful calls per calendar month (UTC), 2 requests per second. Failed calls (4xx/5xx) are not counted.

## PDF/UA validator — `POST /v1/pdf/validate`

Send the PDF as the raw request body (up to 50 MB).

Query parameters:

- `profile` — `ua1` (PDF/UA-1, ISO 14289-1), `ua2` (PDF/UA-2, ISO 14289-2), or omit to use the part the file claims in its XMP metadata (PDF/UA-1 if none).

```sh
curl -X POST "https://api.fare.dev/v1/pdf/validate?profile=ua1" \
  -H "X-API-Key: $FARE_KEY" -H "Content-Type: application/pdf" \
  --data-binary @report.pdf
```

Response:

```json
{
  "profile": "PDF/UA-1",
  "compliant": false,
  "failed_rules": ["7.1-t03", "7.3-t01"],
  "violations": [
    {"rule": "7.1-t03", "message": "Content is neither tagged nor marked as an Artifact."},
    {"rule": "7.3-t01", "message": "Figure has no Alt or ActualText."}
  ],
  "rule_set": "veraPDF validation profiles"
}
```

Rule IDs (`<clause>-t<test>`) match the veraPDF validation profiles, so results compare directly with veraPDF. Repeats of one rule are capped at 50 per report.

## PDF/UA remediator — `POST /v1/pdf/remediate`

Send the PDF as the raw request body (up to 50 MB). Untagged documents are tagged
(headings, paragraphs, lists, tables, figures, links, reading order, headers and footers as
artifacts); tagged documents are repaired in place. Document-level fixes (language, title,
metadata, Unicode maps) are applied to both. Page drawing is never changed: marked content
is inserted around the existing operators.

Query parameters:

- `lang` — document language (e.g. `en`, `es-US`); detected from the text when omitted.
- `title` — document title; taken from metadata or the first heading when omitted.
- `format` — `pdf` (default) returns the remediated PDF; `json` returns a report with the PDF as base64.

```sh
curl -X POST "https://api.fare.dev/v1/pdf/remediate?lang=en" \
  -H "X-API-Key: $FARE_KEY" -H "Content-Type: application/pdf" \
  --data-binary @agenda.pdf -o agenda-accessible.pdf -D -
```

PDF responses carry `Fare-Compliant` (true/false), `Fare-Remaining-Rules` (rule IDs still
failing, e.g. `7.3-t01` for figures that need alt text) and `Fare-Review-Items` (count).

JSON response (`format=json`):

```json
{
  "compliant": false,
  "remaining_rules": ["7.3-t01"],
  "violations_before": 108,
  "violations_after": 1,
  "fixes": [{"area": "structure", "message": "Tagged 1 page(s): 22 element(s) — 5 heading(s), 1 list(s)…"}],
  "review": [{"area": "images", "message": "1 figure(s) need alternative text (7.3-t01)."}],
  "outline": ["Document", "  H1 AGENDA", "  H2 CALL TO ORDER", "  L", "    LI"],
  "pdf_base64": "JVBERi0xLjcK…"
}
```

Automatic remediation cannot judge meaning: always review the `review` items (alt text,
guessed headings and table headers) before publishing.

## Email-security grade — `GET /v1/email-grade`

Query parameters: `domain` (required), `selector` (optional DKIM selector; otherwise common selectors are probed).

```sh
curl "https://api.fare.dev/v1/email-grade?domain=example.com" -H "X-API-Key: $FARE_KEY"
```

Returns `grade` (A–F), `score` (0–100: SPF 30, DMARC 50, DKIM 20), a `spf`, `dmarc` and `dkim` check each with `status` (pass, warn, fail, unknown), `mx`, `accepts_mail`, and `fixes` in priority order.

## Errors

Errors are JSON: `{"error": {"code": "...", "message": "..."}}`.

| Status | Code | Meaning |
|---|---|---|
| 400 | `invalid_domain`, `invalid_selector`, `invalid_profile`, `invalid_format`, `invalid_lang`, `not_pdf` | Bad input |
| 401 | `missing_key`, `invalid_key` | No key, unknown key or revoked key |
| 413 | — | PDF larger than 50 MB |
| 422 | `unreadable_pdf` | The file could not be parsed as a PDF |
| 429 | `rate_limited`, `quota_exceeded` | Per-second limit or monthly quota reached |
| 502 | `dns_failed` | A DNS lookup failed; retry shortly |
| 504 | `timeout` | Validation (60 s) or remediation (120 s) took too long |
