Démarrage rapide
Créez une clé dans l'app sous Wire → Clés d'API, puis appelez l'API de n'importe où. Les réponses sont en JSON, les heures en ISO-8601 UTC.
curl -H "Authorization: Bearer rr_live_…" \
https://realityradar-7h6.pages.dev/api/v1/public/alerts?limit=5const res = await fetch('https://realityradar-7h6.pages.dev/api/v1/public/entities', {
method: 'POST',
headers: { Authorization: `Bearer ${process.env.RADAR_KEY}`, 'Content-Type': 'application/json' },
body: JSON.stringify({ entityType: 'software_version', displayName: 'Node.js', modelOrVersion: '18.20.0',
identifiers: { eolProduct: 'nodejs' }, relationship: 'used' }),
});
console.log(res.status, await res.json());import os, requests
r = requests.get("https://realityradar-7h6.pages.dev/api/v1/public/events", params={"type": "product_recall", "limit": 20},
headers={"Authorization": f"Bearer {os.environ['RADAR_KEY']}"}, timeout=10)
r.raise_for_status()
for e in r.json()["items"]:
print(e["firstSeenAt"], e["title"], e["sourceUrl"])Authentification
Envoyez la clé comme jeton Bearer. Elle n'est affichée qu'une fois, stockée seulement sous forme de hachage, peut expirer après 30, 90 ou 365 jours et être remplacée avec 24 heures de recouvrement.
Authorization: Bearer rr_live_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXPortées
Chaque clé ne porte que les portées choisies. Une requête hors portée renvoie 403 insufficient_scope : une clé en lecture seule ne peut ni ajouter d'éléments ni gérer des webhooks.
| Portée | Endpoints |
|---|---|
read:signals | GET /public/eventsGET /public/events/{id} |
read:entities | GET /public/entities |
write:entities | POST /public/entities |
read:alerts | GET /public/alerts |
manage:webhooks | GET /public/webhooksPOST /public/webhooksDELETE /public/webhooks/{id}GET /public/webhooks/{id}/deliveriesPOST /public/webhooks/{id}/deliveries/{deliveryId}/replay |
Limites de débit
Les clés standard autorisent 60 requêtes par minute, les clés étendues 300. Un 429 signifie attendre et réessayer ; l'usage par clé et par endpoint est visible dans Wire.
Pagination
Les listes renvoient items et nextCursor. Renvoyez le curseur jusqu'à ce qu'il soit null ; les curseurs sont opaques et stables pendant la pagination.
cursor = None
while True:
page = requests.get(f"https://realityradar-7h6.pages.dev/api/v1/public/events", headers=H, params={"limit": 100, "cursor": cursor}).json()
handle(page["items"])
cursor = page["nextCursor"]
if not cursor:
breakErreurs
Les erreurs partagent un même format avec un code stable. Réessayez les 5xx et 429 avec un délai croissant ; un 4xx signale un problème dans la requête.
{ "error": { "code": "insufficient_scope", "message": "This key lacks the \"write:entities\" scope" } }invalid_api_key | 401 | Clé absente, mal formée ou révoquée |
api_key_expired | 401 | La clé a dépassé son expiration ou sa période de remplacement |
insufficient_scope | 403 | La clé n'a pas la portée requise par cet endpoint |
not_found | 404 | Introuvable ou non visible pour cet espace |
plan_limit | 409 | Limite d'éléments du plan gratuit atteinte |
ssrf_blocked | 422 | L'URL pointe vers une adresse privée ou interne |
rate_limited | 429 | Trop de requêtes : réessayez après la fenêtre |
Webhooks
Les webhooks envoient en POST un événement JSON quand une alerte de votre niveau ou plus est créée. Le journal des envois conserve 30 jours avec statut, latence et renvoi en un clic.
POST /your/endpoint
Content-Type: application/json
User-Agent: RealityRadar-Webhook/1.0
X-Radar-Signature: t=1761112800,v1=5f2b…a91c,v1=03de…77b0
{"type":"alert.created","alert":{"impactLevel":"critical","matchType":"exact",…},"event":{…}}Vérifier les signatures
Calculez le HMAC-SHA256 de t, d'un point et du corps brut avec votre secret, comparez en temps constant à n'importe quel v1 et refusez les horodatages de plus de cinq minutes. Après un changement de secret, deux v1 arrivent pendant 24 heures.
import { createHmac, timingSafeEqual } from 'node:crypto';
// rawBody: the exact bytes you received (do not re-serialize JSON)
export function verifyRadar(header, rawBody, secret) {
const parts = header.split(',').map((p) => p.split('='));
const t = Number(parts.find(([k]) => k === 't')?.[1]);
const sigs = parts.filter(([k]) => k === 'v1').map(([, v]) => v);
if (!Number.isFinite(t) || Math.abs(Date.now() / 1000 - t) > 300) return false;
const mac = createHmac('sha256', secret).update(`${t}.${rawBody}`).digest('hex');
return sigs.some((v) => v.length === mac.length && timingSafeEqual(Buffer.from(v), Buffer.from(mac)));
}import hmac, hashlib, time
def verify_radar(header: str, raw_body: bytes, secret: str) -> bool:
parts = [p.split("=", 1) for p in header.split(",")]
t = next((int(v) for k, v in parts if k == "t"), None)
sigs = [v for k, v in parts if k == "v1"]
if t is None or abs(time.time() - t) > 300:
return False
mac = hmac.new(secret.encode(), f"{t}.".encode() + raw_body, hashlib.sha256).hexdigest()
return any(hmac.compare_digest(mac, s) for s in sigs)func VerifyRadar(header string, rawBody []byte, secret string) bool {
var t int64 = -1
var sigs []string
for _, p := range strings.Split(header, ",") {
k, v, ok := strings.Cut(p, "=")
if !ok { continue }
if k == "t" { t, _ = strconv.ParseInt(v, 10, 64) }
if k == "v1" { sigs = append(sigs, v) }
}
if t < 0 || math.Abs(float64(time.Now().Unix()-t)) > 300 { return false }
m := hmac.New(sha256.New, []byte(secret))
fmt.Fprintf(m, "%d.", t)
m.Write(rawBody)
want := hex.EncodeToString(m.Sum(nil))
for _, s := range sigs {
if hmac.Equal([]byte(want), []byte(s)) { return true }
}
return false
}# Replay a delivery (fresh timestamp + signature)
curl -X POST -H "Authorization: Bearer rr_live_…" \
https://realityradar-7h6.pages.dev/api/v1/public/webhooks/WEBHOOK_ID/deliveries/DELIVERY_ID/replayDépendances et OSV
Suivez des paquets avec un purl comme pkg:npm/lodash et une version exacte. Reality Radar interroge OSV.dev et marque une correspondance exacte si votre version est listée comme affectée. Importez lockfiles ou SBOM dans l'app, rubrique Importer.
curl -X POST -H "Authorization: Bearer rr_live_…" -H "Content-Type: application/json" \
-d '{"entityType":"software_version","displayName":"lodash","modelOrVersion":"4.17.20","identifiers":{"purl":"pkg:npm/lodash"},"relationship":"used"}' \
https://realityradar-7h6.pages.dev/api/v1/public/entitiesGlossaire
Les termes que vous verrez dans les réponses.
- Signal
- Un changement détecté dans une source officielle, avec preuves et horodatages.
- Beacon (balise)
- Une source de données. Le niveau A est un régulateur ou fabricant officiel, le niveau B une base de données vérifiée.
- Type de correspondance
- exact, strong, probable ou weak : notre degré de certitude que l'événement concerne votre élément. Seuls exact et strong sont présentés comme certains.
- Pertinence, confiance, gravité
- Trois scores de 0 à 100 calculés séparément : cela vous concerne-t-il, quelle est la fiabilité des preuves, quelle est la gravité du changement.
- purl
- Package URL, par ex. pkg:npm/lodash, l'identifiant standard utilisé pour la correspondance OSV.
- Registre des preuves
- Une chaîne de hachages inviolable de chaque preuve stockée, vérifiable par tous.