---
name: getjson
description: getJSON reads any content a user or an agent points at, a web page or a file, and returns JSON in your schema, validated. Try and use it without an account. Use when the user wants the text of a link the agent cannot read (an X, Bluesky, Mastodon or Hacker News post, a GitHub issue or file, a public Google Doc or Sheet, a PDF behind a URL, a web article), invoice, receipt, form, table or contract data from a document (PDF, PNG, JPEG, WebP, TXT, CSV) as JSON, the metadata of a link, or asks to "turn this file into JSON".
---

# getJSON

```bash
curl https://getjson.de/https://x.com/jack/status/20
```

getJSON reads any content a user or an agent points at, a web page or a file, and returns JSON in your schema, validated. Try and use it without an account. Base URL: `https://getjson.de`. Full spec: https://getjson.de/openapi.json. One page per source, with a recorded answer: https://getjson.de/read/x (also `/read/bluesky`, `/read/mastodon`, `/read/hacker-news`, `/read/github`, `/read/google-docs`, `/read/pdf-url`, `/read/article`, `/read/walls`).

## Read a link, no key

To read a link, call it without a key. It costs nothing and uses no AI:

```bash
curl https://getjson.de/https://example.com/article
curl -H "Accept: text/markdown" https://getjson.de/https://example.com/article
```

- The answer is JSON: the title and text in `content`, the page metadata in `meta`, `wall` when the page cannot be read. The text is cut at 20,000 characters; add `?full=1` for all of it.
- A wall answers `200` with `content: null`: `login` (a `401` page or a private Google document), `bot_protection` (a `403` page or a Cloudflare challenge), `no_text` (a scan, an image or a page with no text, such as a JavaScript shell), `unsupported` (a GitHub file that is not text), `too_large` (a file over the limit). Do not retry a wall; `wall.hint` names the next step. A `429` or `5xx` from the page is a `502` error with a hint to retry, and the page's `Retry-After` when it sent one.
- A file from disk: `curl -F "file=@report.pdf" https://getjson.de/`. Without a key a file may have 5 MB.
- To get fields in your own shape, add `?schema=<URL-encoded JSON Schema>` (or the header `X-JSON-Schema`). A shared schema goes by its id in front of the link: `https://getjson.de/s_7Kq2hnAb9Z/<link>`; the link keeps its own query string. The answer waits up to 60 seconds and has `result`, validated against your schema. A result that breaks the schema, also after one retry, answers `422` with `"code": "schema_mismatch"` and `errors` (`path` and `message` per field). The schema may have 16,000 characters, the `instructions` 2,000. Each network has 3 of these per day without a key. The 4th answers `429` with a hint to get a trial key (section 1).
- 20 reads per minute and IP without a key. With a key, send schema calls to `POST /v1/extract` (section 2).

## 1. Get an API key

Use `$GETJSON_API_KEY` if it is set. Otherwise get a trial key — no email, no human:

```bash
CH=$(curl -sX POST https://getjson.de/api/agent/trial/challenge)
SOLUTION=$(python3 -c '
import hashlib, itertools, json, sys
c = json.loads(sys.argv[1]); ch, d = c["challenge"], c["difficulty"]
for i in itertools.count():
    if int.from_bytes(hashlib.sha256(f"{ch}:{i}".encode()).digest(), "big") >> (256 - d) == 0:
        print(i); break
' "$CH")
curl -sX POST https://getjson.de/api/agent/trial -H "Content-Type: application/json" \
  -d "{\"challenge\": $(echo "$CH" | jq .challenge), \"solution\": \"$SOLUTION\"}"
```

The response has `key` (`gj_…`, shown only once), `claim_url` and `expires_at`. The trial runs 2 extractions in the `budget` mode on files up to 5 MB, and expires after 24 hours.

- Tell the user the `claim_url`. When they open it and sign in, the key moves into their account, stops expiring and loses the limits. Also tell them that the key can then read all jobs in their account and spend their credits.
- A `url` job with `model=auto` and no `schema` or `instructions` returns the source data without AI, for 0 credits: the X post, an envelope (`source`, `content`, `meta`, `wall`) for Bluesky, Mastodon, Hacker News, GitHub and Google Docs links, a PDF/TXT/CSV behind a link (its text) and any web page (its article as Markdown, or only the head when it has no article body; the page metadata in `meta`). A trial key gets this path even without `model`. Other trial jobs run the `budget` mode for 1 credit. A trial key runs at most 20 jobs.
- Tell the user to store the key, for example as `GETJSON_API_KEY`. Never write it into a file in the repository.
- If the user wants a full account at once, use the email flow instead: `POST /api/agent/signup` with `{"email"}`, ask the user for the 6-digit code from the email, then `POST /api/agent/verify` with `{"email", "code", "key_name"}`.

## 2. Extract

```bash
JOB=$(curl -s https://getjson.de/v1/extract \
  -H "Authorization: Bearer $GETJSON_API_KEY" \
  -F "file=@path/to/document.pdf" | jq -r .jobId)

until STATUS=$(curl -s https://getjson.de/v1/jobs/$JOB \
  -H "Authorization: Bearer $GETJSON_API_KEY"); \
  echo "$STATUS" | jq -e '.status == "completed" or .status == "failed"' >/dev/null; do sleep 2; done

echo "$STATUS" | jq .result
```

For an X post, send `-F "url=https://x.com/<user>/status/<id>"` instead of `file`. To only read a post without AI (0 credits): `GET /v1/sources/x/<id>`.

## 2a. Read a web link

For the title, description, favicon, preview image, Open Graph and Twitter card tags or JSON-LD of any page, call the link source. It costs 0 credits, needs no balance and answers directly:

```bash
curl -s "https://getjson.de/v1/sources/link/$(jq -rn --arg u "$LINK" '$u|@uri')" \
  -H "Authorization: Bearer $GETJSON_API_KEY" | jq .link
```

- URL-encode the link. X post links go to `/v1/sources/x/` instead (the link source answers 400).
- The link source returns only what the page's `<head>` declares. It does not run JavaScript and does not return the article text. To get the article, use the keyless read above or `/v1/extract`.
- `-F "url=<link>" -F "model=auto"` on `/v1/extract` reads the page as an article and gives the envelope as the job result, for 0 credits and with any balance: the article as Markdown in `content` (a page with no article body gives only the head, `kind: "page"`), the object above in `meta`. Add a `schema` or `instructions` only when the user wants fields reshaped: the AI then reads the article text and credits are spent.
- Errors: `400` invalid link or a private or internal address, `404` page not found, `415` not HTML (a PDF or image link: download it and send it as `file`), `502` unreachable, `504` no answer in 10 s.

Optional form fields: `model` (default `claude-sonnet`, 1 credit; or `auto`, `standard`, `premium`, `budget`, `ocr`, `multilingual`, or a model id from `GET /v1/models`), `instructions`, `schema` (a JSON Schema as a string, at most 16,000 characters; every account, also a trial key) and, on the Pro plan only, `schema_id` (a saved schema). A shared schema id (`s_…`) works as `schema_id` on every plan and costs the credits of the model. The `result` is validated against the schema (draft 2020-12, or draft-07 by `$schema`). A result that breaks it, also after one retry, makes the job `failed` with `"error_code": "schema_mismatch"` and `errors`, and the credits are refunded. A schema that does not compile answers `400` before any credit is spent.

## 3. Check what is left

`GET /v1/balance` returns `{ "balance": <credits> }`. `POST /v1/extract` answers `402` when the balance cannot cover the extraction (`auto` needs up to 3 credits; the default model needs 1). A `url` job with `model=auto` and no `schema` or `instructions` costs 0 and never gets `402`. For a trial key, the error names the `claim_url`: send the user there. Otherwise send the user to https://getjson.de/settings/credits.

## MCP alternative

If the harness supports MCP, the same features are tools on `https://getjson.de/mcp`. The `read` tool needs no key (`url`, optional `schema` or `instructions`, `max_chars`); the other tools need the key:

```bash
claude mcp add --transport http getjson https://getjson.de/mcp \
  --header "Authorization: Bearer $GETJSON_API_KEY"
```

## Rules

- Tell the user before an extraction spends credits on many files.
- Do not send documents the user has not asked you to process.
- Read the `RateLimit` header (`r` = requests left, `t` = seconds to reset) and slow down before you hit the limit. On `429`, wait for the `Retry-After` seconds, then retry once.
