Caching
Berichte werden auf dem Server nach Hostname und Abschnittsliste zwischengespeichert. Wer dieselben Abschnitte innerhalb der Cache-Zeit erneut anfragt, erhält dieselbe Beobachtung mit "cached": true und den ursprünglichen observedAt-Zeiten. Die oben genannten Cache-Control-Header erlauben außerdem Browsern und dem CDN, eine Antwort kurze Zeit wiederzuverwenden. Einen Parameter, der eine frische Abfrage erzwingt, gibt es nicht.
CORS
Die Endpunkte auf dieser Seite senden Access-Control-Allow-Origin: * und beantworten OPTIONS-Preflight-Anfragen, nur für GET. Sie können sie von einer Seite mit anderem Origin aus aufrufen. Cookies werden nie gelesen, es sind also keine Anmeldedaten im Spiel.
Faire Nutzung
Jede Anfrage löst echte Abfragen bei Registries, DNS-Resolvern und der abgefragten Website selbst aus. Nutzen Sie die API für interaktive Tools, Dashboards und gelegentliche Prüfungen von Domains, für die Sie einen Anlass haben. Arbeiten Sie keine Domainlisten ab, wechseln Sie keine Adressen, um die Limits zu umgehen, und verkaufen Sie die Ausgabe nicht weiter. Die Richtlinie zur zulässigen Nutzung gilt für API-Verkehr genauso wie für die Website.
Outbound webhooks
Signed-in members can have watch alerts, expiry reminders and marketplace notices posted to a URL they own: a Slack incoming webhook or a generic https endpoint (workspace → Settings → Notification channels). This section documents what the receiver gets. It is outbound only: OrbitProbe never accepts requests on these URLs, and there is no inbound API.
Receivers must be https on a public host (default port, no credentials; private, local and reserved hosts are refused, and the host is resolved and checked again at send time). Redirects are not followed. A delivery counts as done when the receiver answers 2xx; after five failed deliveries in a row the webhook is switched off and the owner sees a notice in the workspace.
Request
| Name | Beschreibung |
|---|---|
| POST | JSON body, Content-Type: application/json; charset=utf-8, User-Agent: OrbitProbe-Webhook/1.0 |
| X-OrbitProbe-Event | The kind (see below). |
| X-OrbitProbe-Delivery | The delivery id (ntf_<number>). Repeated on a retry, so you can de-duplicate. |
| X-OrbitProbe-Signature | Generic endpoints only: t=<unix seconds>,v1=<hex HMAC-SHA256 of "<t>.<raw body>"> with the signing secret shown in Settings. |
Body (generic endpoints)
| Name | Beschreibung |
|---|---|
| id | Delivery id, the same as X-OrbitProbe-Delivery. |
| kind | One of the kinds below. |
| category | watch, expiry, market or test. |
| title, text | The notification in the account’s language: the same wording the push notification carries. Counts are "N of M resolvers", never percentages. |
| url | Where to look in the workspace. |
| createdAt | When the event was queued (ISO 8601, UTC). |
| account | The recipient’s account id, so one receiver can serve several accounts. |
| data | The raw event as stored: domain, counts, listing id, amount in integer minor units and currency, and so on. Fields vary by kind; anything missing was not measured, never "no". |
{
"id": "ntf_1042",
"kind": "watch-changed",
"category": "watch",
"title": "Watch: unexpected change",
"text": "example.com TXT: 9 of 12 resolvers return values that differ from the guarded baseline.",
"url": "https://www.orbitprobe.com/app/watch/00000000-0000-4000-8000-000000000000",
"createdAt": "2026-01-01T00:00:00.000Z",
"account": "00000000-0000-4000-8000-0000000000aa",
"data": {
"domain": "example.com",
"kind": "dns-change",
"record_type": "TXT",
"name": "example.com",
"matched": 3,
"total": 12,
"failed": 0,
"differing": 9,
"watch_id": "00000000-0000-4000-8000-000000000000",
"event_id": 77
}
}Body (Slack)
Slack incoming webhooks receive {"text": "…"} only: title, text and URL on three lines, no Block Kit and no attachments, so the message renders in every Slack client and in Slack-compatible receivers such as Mattermost or Rocket.Chat.
{
"text": "*Watch: unexpected change*\nexample.com TXT: 9 of 12 resolvers return values that differ from the guarded baseline.\nhttps://www.orbitprobe.com/app/watch/…"
}Verifying the signature
Recompute the HMAC over "<t>.<raw body>" with your secret, compare in constant time, and reject timestamps older than five minutes. Do not parse and re-serialise the JSON before hashing: sign the bytes as received.
// Node.js receiver: verify X-OrbitProbe-Signature before trusting the body
import { createHmac, timingSafeEqual } from 'node:crypto';
export function verify(secret, rawBody, header, nowSeconds = Math.floor(Date.now() / 1000)) {
const m = /^t=(\d+),v1=([0-9a-f]{64})$/.exec(header ?? '');
if (!m || Math.abs(nowSeconds - Number(m[1])) > 300) return false;
const expected = createHmac('sha256', secret).update(`${m[1]}.${rawBody}`).digest('hex');
return timingSafeEqual(Buffer.from(expected, 'hex'), Buffer.from(m[2], 'hex'));
}Kinds
watch-changed, watch-target, watch-failed, watch-recovered, watch-partial · expiry · offer-received, offer-countered, offer-accepted, offer-rejected, offer-withdrawn, offer-expired, listing-submitted, listing-approved, listing-paused, listing-removed, agreement-cancelled · test (the "Send test" button).
Limits
At most 5 webhooks per account and 20 posts per account per hour; beyond that, events still reach the in-app inbox and e-mail but are not posted. Deliveries are retried up to five times over later runs of the five-minute job. An "offer-accepted" event records an agreement only: no payment, escrow or transfer is implied.
OpenAPI-Beschreibung
Ein maschinenlesbares OpenAPI-3.1-Dokument dieser Endpunkte wird aus demselben Code erzeugt: /api/openapi.json