The API
Everything the web does, it does over this API — there is no private one. Five tools, one shape: you create a job, you follow it, you take the result. Without a key you get the free lane; with one, the higher limits.
Where it lives
https://bigitools.comYour key
Either header works, whichever your client makes easier:
Authorization: Bearer ok_…
X-API-Key: ok_…A key it does not recognise gets a 401, on purpose — it does not quietly fall back to the free lane. If you mistype a key, you find out on the first call and not when a limit you should not have hits you.
A job, start to finish
1. Create it
curl -X POST $API/api/jobs \ -H 'Authorization: Bearer ok_…' \ -H 'Content-Type: application/json' \ -d '{"tool":"mail-doctor","input":{"domain":"example.com"}}' { "id": "cm…", "status": "queued", "stream": "/api/jobs/cm…/stream", "key": "n7Qk…" }Keep the key: it is handed out once and we cannot resend it. Reading the job, its files and cancelling it all need it — send it as X-Job-Key, or as ?key= where a header is not possible. We store only a fingerprint of it, so a lost key means a job you can no longer reach; it expires with the report anyway. If the job was created with an account API key, that key opens it too and you can ignore this one.
Tools that need credentials take them in a separate secret object, never inside input: the input is kept with the job and the secret is encrypted and wiped the moment the job ends.
2. Follow it
Poll GET /api/jobs/:id, or open the stream and get the steps as they happen:
curl -N "$API/api/jobs/cm…/stream?key=n7Qk…"The stream is Server-Sent Events, and each event carries an id. If you drop, reconnect with ?desde=<last id> and you get what you missed instead of starting over. The key goes in the query string here, not in a header, because an SSE client cannot send one — which is also why it is worth knowing that a URL with a key in it ends up in access logs.
3. Take the result
It arrives in result when the job is done. Tools that produce files add:
GET /api/jobs/:id/export/:format the report — /api/tools lists the formats GET /api/jobs/:id/files what was produced, listed GET /api/jobs/:id/files/<path> one of them GET /api/jobs/:id/download.zip all of themAll four want the key, the same as everything else about that job.
The rest of it
GET /api/health is the service up, and is the queue moving
GET /api/tools the catalogue: free-tier limits and export formats
GET /api/me your plan and what you have used
POST /api/jobs/:id/cancel stop one that is still running
POST /api/mailtest a one-off address to send a message to (returns a key too)
GET /api/mailtest/:id has it arrived, and which job scored it (needs that key)
POST /api/monitors watch an IP, a certificate, a domain or its DNS
GET /api/monitors what you are watching, and what changed
DELETE /api/monitors/:id stop watching
GET /api/ip the address this server sees you from, with its reverse DNS
GET /api/ip/plain the same, one line, no JSON to parse — for a terminal
GET /api/is-it-down?url=… is that site down, or is it just you — checked from here
GET /api/speed what the speed test may spend and what is left of it
GET /api/speed/down bytes to measure with; POST /api/speed/up for the other wayThe shape of an error
Every error answers JSON with error — a sentence in English, written to be read from a terminal. Some also carry code: a stable identifier meant for programs, so a client can decide without parsing prose. Branch on code when it is there, and show error when it is not.
The codes in use today:
body-too-large
internal-error
invalid-credentials
invalid-input
job-already-finished
job-expired
job-expired-live
job-no-files
job-not-finished
job-not-found
job-not-yours
job-owner-unknown
key-bad-format
key-not-recognised
mailtest-not-found
monitor-dns-target
monitor-domain-date-ambiguous
monitor-domain-interval
monitor-domain-no-expiry
monitor-domain-no-whois
monitor-domain-registry-list
monitor-domain-silent
monitor-domain-target
monitor-duplicate
monitor-field
monitor-http-no-dns
monitor-http-private
monitor-http-target
monitor-interval
monitor-ip-not-ipv4
monitor-ip-private
monitor-ip-v6
monitor-limit
monitor-no-webhook
monitor-not-found
monitor-tls-is-ip
monitor-tls-target
monitor-webhook-url
monitoring-needs-account
monitoring-not-open
monitoring-paid-plan
monitoring-paid-plan-closed
rate-limited
rate-limited-checks
rate-limited-speed
result-expired
speed-budget-client
speed-budget-server
speed-no-accounting
stream-broken
stream-unavailable
zip-failedWhat the codes mean
| 400 | The request is wrong, and the message says what to change — not the name of one of our variables. |
| 401 | The key is not recognised, or not in the expected format. |
| 402 | Paid feature. Monitoring is the one that answers this. |
| 403 | That job is not yours: the key it was handed at creation is what opens it. |
| 404 | No such job, or it has expired. Results do not stay for ever. |
| 409 | You are already monitoring that, in the same way. |
| 413 | The body is over the limit. |
| 429 | A limit — and the message says which one, so you know whether to wait a minute or a day. |
| 503 | Something the tool depends on is not answering right now. |
The report, in your user’s language
Add ?lang= and the text the engine writes comes back translated: what each check says, the progress, the log, and the reason a job failed. Nine languages; English when you leave it out.
GET /api/jobs/:id?lang=de the report, translated
GET /api/jobs/:id/stream?lang=de progress and log, as it happens
GET /api/jobs/:id/export/:format?lang=de the file you download, translated
lang: de · en · es · fr · it · nl · pl · pt · roOnly the text changes. The code of an error is the same in all nine — that is the one you branch on, and the message is the one you can show as it comes. Accept-Language is ignored on purpose: that is the language of the browser, not of the page your user is reading, and mixing the two puts Spanish sentences inside an English report.
The tools, and what the free lane gives you
The limits are read live from /api/tools, not written here: a catalogue typed by hand goes stale the first time a tool is added.
Two things worth knowing
- · The job key is the credential, not the id. It is handed out once when the job is created, and we keep only a fingerprint. Whoever holds it can read that report until it expires, so treat the key like the report itself.
- · Results expire. Download what you need; after that the input goes too, not just the output.