Cache
Les rapports sont mis en cache sur le serveur par nom d'hôte et par liste de sections ; redemander les mêmes sections pendant la durée du cache renvoie donc la même observation, avec "cached": true et ses heures observedAt d'origine. Les en-têtes Cache-Control indiqués ci-dessus permettent aussi aux navigateurs et au CDN de réutiliser une réponse pendant un court moment. Aucun paramètre ne permet de forcer une nouvelle recherche.
CORS
Les points d'accès de cette page envoient Access-Control-Allow-Origin: * et répondent aux requêtes préliminaires OPTIONS, pour GET uniquement. Vous pouvez les appeler depuis une page d'une autre origine. Ils ne lisent jamais de cookies ; aucun identifiant n'entre donc en jeu.
Usage raisonnable
Chaque requête déclenche de vraies requêtes vers des registres, des résolveurs DNS et le site recherché lui-même. Utilisez l'API pour des outils interactifs, des tableaux de bord et des contrôles occasionnels de domaines que vous avez une raison d'examiner. Ne parcourez pas des listes de domaines, ne faites pas tourner des adresses pour contourner les limites et ne revendez pas les résultats. La politique d'utilisation acceptable s'applique au trafic de l'API exactement comme au site.
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
| Nom | Description |
|---|---|
| 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)
| Nom | Description |
|---|---|
| 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.
Description OpenAPI
Un document OpenAPI 3.1 lisible par machine, décrivant ces points d'accès, est généré à partir du même code : /api/openapi.json