Documentation
relayted API
Base URL https://api.relayted.de/v1 · JSON in, JSON out · one key for all services.
Quick start
- Create a key and top up at API key & balance.
- Create a job. With
?wait=20the call returns as soon as the job is finished (at most 25 seconds are honoured). - Download the results from the
urlof each result, with the same key.
export RELAYTED_KEY="RAPI-XXXX-XXXX-XXXX-XXXX-XXXX"
# 1. create a job and wait for it
curl -s "https://api.relayted.de/v1/websitepro/jobs?wait=20" \
-H "Authorization: Bearer $RELAYTED_KEY" -H "Content-Type: application/json" \
-d '{"url":"https://example.com","outputs":["markdown","metadata"]}'
# 2. fetch a result (the "url" field of the result)
curl -s "https://api.relayted.de/v1/jobs/JOB_ID/results/markdown" -H "Authorization: Bearer $RELAYTED_KEY"
Authentication
Send your key with every request to /v1 that touches your balance:
Authorization: Bearer RAPI-XXXX-XXXX-XXXX-XXXX-XXXX
- A key is created by the owner of a wallet on the account page. There is no API call that creates, lists or returns keys.
- The key is shown once and stored only as a keyed hash. If it leaks, replace it on the account page: the old key stops working immediately, the balance stays.
- Upper/lower case and dashes do not matter. Never put the key in a URL.
- These endpoints need no key:
GET /v1,/v1/pricing,/v1/services,/v1/services/<service>.
Jobs & results
Every service follows the same pattern.
A job consists of results (one per output, screenshot or test module). Each result is billed, delivered and refunded on its own.
{
"job": {
"id": "Zq3...", "service": "websitepro", "target": "example.com",
"status": "completed", // queued | processing | completed | failed
"cost": 65, "refunded": 0, "charged": 65, // Payloads
"createdAt": 1790000000000, "expiresAt": 1790086400000,
"results": [
{ "key": "markdown", "status": "done", "price": 45, "refunded": false,
"contentType": "text/markdown; charset=utf-8", "bytes": 5120,
"url": "https://api.relayted.de/v1/jobs/Zq3.../results/markdown" },
{ "key": "metadata", "status": "done", "price": 20, "refunded": false, "url": "..." }
]
},
"balance": 49935
}
completedmeans at least one result was delivered; check each result'sstatus(pending,done,failed).failedmeans nothing was delivered and nothing was charged.- Results are files, served with their real content type as a download. They are available until
expiresAt; after that the request answers410 expired. - Without
wait, pollGET /v1/jobs/<id>every few seconds. Withwait, the request is held open until the job is finished or the time is over, then returns the current state.
Billing & refunds
All amounts are in Payloads (1 EUR = 10000 Payloads). The price list is on the pricing page and at /v1/pricing.
- The whole job is charged when it is created. If the balance is too low you get
402 insufficient_fundswithneededandbalance, and nothing happens. - Every result that is not delivered is refunded automatically. You do not have to poll for that.
- A request that is rejected (invalid input, target not reachable, queue full, service down) costs nothing.
Top up by API
A program that can pay Lightning invoices can refill its own balance. The first key is still created in a browser.
curl -s https://api.relayted.de/v1/topups -H "Authorization: Bearer $RELAYTED_KEY" \
-H "Content-Type: application/json" -d '{"eur": 5}'
{ "topup": { "id": "...", "status": "pending", "eur": 5, "payloads": 50000, "bonusPayloads": 0,
"bolt11": "lnbc...", "sats": 7500, "expiresAt": 1790003600000 } }
Minimum 0.25 EUR, maximum 100.00 EUR per top-up. The balance is credited as soon as the payment is confirmed.
Errors
Errors use HTTP status codes and always this body. Branch on code; message is for humans and may change.
{ "error": { "code": "insufficient_funds", "message": "...", "needed": 2400, "balance": 400 } }
| Status | Code | Meaning |
|---|---|---|
| 400 | bad_request, bad_url, no_output, ... | The request is not valid. The service pages list their codes. Nothing charged. |
| 400 | blocked_address, unreachable | The target is private/local or does not answer. Nothing charged. |
| 401 | unauthorized | Key missing or wrong. |
| 402 | insufficient_funds | Balance too low. Includes needed, balance, topup. |
| 404 | not_found, unknown_service | No such job, result or service (also: a job of another key). |
| 409 | not_ready | The result is still being produced. |
| 410 | expired | The result was deleted after its retention period. |
| 429 | rate_limited, relay_busy | Too many requests. Retry later. |
| 503 | service_unavailable, busy | Service down or queue full. Nothing charged, retry in a moment. |
Limits & retention
- 600 jobs per hour and key. Quotes, status and downloads are not counted against it.
- Request bodies up to 64 KB. Long polling up to 25 seconds per request.
- Result files: 24 hours for websitepro and shots, 30 days for labs reports (see
expiresAt). - Stored about a job: service, target host name, result keys, prices, states. Not the URL, not the content. Host names are removed from the history after 30 days.
- Targets must be public: private, local and reserved addresses are refused by the services themselves.
- CORS is open on
/v1. Do not ship your key to browsers you do not control.