Docs / Job Data API / Endpoints / Batch liveness
Batch liveness
Answers “which of these ids are still live?” for up to 1,000 ids in one request, billed as ONE request rather than one per id. Post {"ids": [...]}; every id you send comes back exactly once, in order, with a state of active, inactive, missing or unknown — an id we could not resolve is answered unknown rather than dropped, because a missing row is indistinguishable from a retired one and that ambiguity is the whole reason this endpoint exists. It reads the same path as GET /v1/jobs/{id}, so its verdict carries that endpoint's authority: absence from a ?active=true sweep does not.
Request
curl https://api.softon.dev/v1/jobs/liveness \
-H "Authorization: Bearer $SOFTON_KEY"
req, _ := http.NewRequestWithContext(ctx, "GET", "https://api.softon.dev/v1/jobs/liveness", nil) req.Header.Set("Authorization", "Bearer "+os.Getenv("SOFTON_KEY")) res, err := http.DefaultClient.Do(req) if err != nil { log.Fatal(err) } defer res.Body.Close() var page struct { Data []Livenes `json:"data"` Meta struct{ Requested, Answered int } `json:"meta"` } if err := json.NewDecoder(res.Body).Decode(&page); err != nil { log.Fatal(err) }
import json, os, urllib.parse, urllib.request url = "https://api.softon.dev/v1/jobs/liveness" req = urllib.request.Request(url, headers={ "Authorization": "Bearer " + os.environ["SOFTON_KEY"], }) page = json.load(urllib.request.urlopen(req)) # page["data"] is the object; page["error"] is None on success
const url = new URL("https://api.softon.dev/v1/jobs/liveness"); const res = await fetch(url, { headers: { Authorization: `Bearer ${process.env.SOFTON_KEY}` }, }); if (!res.ok) throw new Error(`${res.status} ${await res.text()}`); const { data, meta } = await res.json();
Response
The envelope is identical on every softon.dev API: data, meta, error. Only the shape inside data changes per dataset — see the response envelope.
{
"data": [
{ "id": "tap_az:48493167", "state": "active", "active": true, "checked_at": "2026-09-15T09:14:02.117Z" },
{ "id": "easyjob_az:2", "state": "inactive", "active": false, "checked_at": "2026-09-15T09:14:02.117Z" },
{ "id": "boss_az:99999", "state": "missing", "active": null, "checked_at": "2026-09-15T09:14:02.117Z" },
{ "id": "not-an-id", "state": "unknown", "active": null, "checked_at": "2026-09-15T09:14:02.117Z" }
],
"meta": { "requested": 4, "answered": 4, "request_id": "req_9f2c1a55d0e3b477" },
"error": null
}
Fields of each item in data[]
| Field | Type | Description |
|---|---|---|
id |
string | Echoed back exactly as you sent it, including an id this platform could not parse. Match on it; it is not normalised. |
state |
string | One of active, inactive, missing, unknown, and that set is closed.
active — the posting is here and its source still lists it. inactive — it is here and retired: its source's last complete run did not list it, or the source has stored nothing for 14 days and the daily pass retired what it held. Only the first says the posting closed; the source's last_observed_at on GET /v1/sources tells them apart. missing — this platform holds no such posting, either because it never did or because it was withdrawn on request; both are "gone" to a caller reconciling their own copy. unknown — no verdict, because the id could not be resolved into one. Treat unknown as "change nothing, ask again"; it is the safe answer and it is why every id gets a row rather than being dropped. |
active |
boolean · nullable | A real boolean whenever state is active or inactive, and null otherwise. Never absent. |
checked_at |
string (RFC 3339) | When this verdict was read. One timestamp for the whole batch, because it is one query. |
Explore a documented example
This preview shows the documented response. It does not call the live API or use your key.
Choose Show example to view the documented response.