Try it free in the sandbox · first FHIR call in 5 minutesFree · 30 synthetic patients · no card
Webhook
Eventi sottili, ritentati e firmati per scritture di risorse, modifiche al consenso e documenti finalizzati, con verifica della firma in TypeScript, Dart e Python.
Anpheros Platform può chiamare il tuo server quando accade qualcosa nel tuo progetto: una risorsa è stata scritta, una persona ha concesso o revocato l'accesso, un documento è stato finalizzato. Gli eventi sono leggeri: ID, tipo, versione — mai contenuti clinici. Leggi la risorsa tramite l'API se ne hai bisogno. Ogni consegna è firmata; verifica la firma prima di fidarti.
Registra un endpoint
curl -X POST $BASE/v1/webhooks -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
-d '{"url": "https://your.app/anpheros/hook", "events": ["resource.created", "consent.revoked"], "description": "prod"}'
La risposta contiene secret (whsec_…) una volta. Memorizzala; ti servirà per verificare le firme.
events accetta ["*"] o uno qualsiasi dei seguenti:
| type | when | data |
|---|---|---|
resource.created / resource.updated / resource.deleted |
il tuo progetto ha scritto una risorsa FHIR (REST v1, FHIR API o un bundle) — o un altro progetto ha scritto in un record a cui hai accesso (hai creato il paziente, o detieni una concessione attiva); quindi data.external è true e data.source dice chi ha scritto: author_type (paziente / professionista / dispositivo / importazione / IA), organization (il nome visualizzato per conto del quale ha agito lo scrittore), practitioner (nome dalla directory, quando noto), source_system |
resource_type, id, patient (l'ID che vedi), version, last_updated, e per scritture esterne external, source |
consent.granted |
una persona ha concesso alla tua app l'accesso dalla pagina del consenso (o un'app attendibile ha collegato il suo record) | grant_id, patient, application_id, scopes, purpose, expires_at |
consent.revoked |
la persona (o la piattaforma) ha terminato una concessione | come sopra più revoked_at, reason |
document.finalized |
è stato finalizzato e verificato il checksum di un caricamento di documenti | id, patient, content_type, size, sha256 |
proposal.created |
un agente IA ha proposto una scrittura in un record che puoi vedere; attende l'approvazione della persona | id, patient, action, resource_type |
ping |
hai richiesto una consegna di prova | endpoint |
Gli endpoint sono per progetto e ambiente: una chiave sk_test_ gestisce gli endpoint sandbox,
una chiave sk_live_ quelli di produzione. Gli URL devono essere endpoint pubblici https://. La registrazione (e qualsiasi successiva modifica di url) rifiuta indirizzi locali, privati, link-local, metadata e altri indirizzi riservati — localhost, 127.0.0.1, ::1, 10.0.0.0/8, 192.168.0.0/16, fd00::/8 e simili — e nomi che si risolvono in essi, con 400 invalid sul campo url; questo si applica anche nella sandbox. Ogni consegna controlla nuovamente l'indirizzo e si connette solo agli indirizzi IP che ha appena controllato, quindi un nome che in seguito punta a una rete privata (reindirizzamento DNS) non riceve nulla. Per ricevere eventi sulla tua macchina durante lo sviluppo, esponila tramite un tunnel HTTPS pubblico e registra l'indirizzo del tunnel.
Fino a 10 endpoint per progetto e ambiente.
La consegna
POST https://your.app/anpheros/hook
Content-Type: application/json
User-Agent: Anpheros-Webhooks/1.0
Anpheros-Event: resource.created
Anpheros-Event-Id: evt_…
Anpheros-Delivery: whd_…
Anpheros-Signature: t=1789800000,v1=5f3a…
{"id":"evt_…","type":"resource.created","created_at":"2026-09-19T12:00:00.000Z","environment":"production",
"project":"proj_…","data":{"resource_type":"Observation","id":"…","patient":"…","version":1,"last_updated":"…"}}
Rispondere con qualsiasi 2xx entro 10 secondi. Qualsiasi altra cosa (o un timeout) è un fallimento e la
consegna viene ritentata con backoff per un massimo di 24 ore (10 tentativi), quindi contrassegnata come exhausted.
Le consegne sono "at-least-once" e possono arrivare fuori ordine: utilizzare Anpheros-Event-Id per
de-duplicare e data.version per ignorare aggiornamenti obsoleti.
Verifica della firma
v1 è HMAC-SHA256 con il tuo segreto su <t>.<raw body>; rifiuta se t è più vecchio di 5 minuti.
import { verifyWebhookSignature } from '@anpheros/sdk';
app.post('/anpheros/hook', express.raw({ type: 'application/json' }), async (req, res) => {
const ok = await verifyWebhookSignature({ secret: process.env.ANPHEROS_WEBHOOK_SECRET!, header: req.header('anpheros-signature'), body: req.body });
if (!ok) return res.status(400).end();
const event = JSON.parse(req.body.toString());
// … enqueue and return quickly
res.status(204).end();
});
import 'package:anpheros_sdk/anpheros_sdk.dart';
final ok = verifyWebhookSignature(secret: secret, header: request.headers['anpheros-signature'], body: rawBodyBytes);
import hmac, hashlib, time
def verify(secret: str, header: str, body: bytes, tolerance=300) -> bool:
parts = dict(p.split("=", 1) for p in header.split(","))
if abs(time.time() - int(parts["t"])) > tolerance:
return False
expected = hmac.new(secret.encode(), f"{parts['t']}.".encode() + body, hashlib.sha256).hexdigest()
return hmac.compare_digest(expected, parts["v1"])
Operare
GET /v1/webhooks/{id}/deliveries?status=failed— il log, dal più recente al meno recente, con codice di stato ed errore.POST /v1/webhooks/{id}/deliveries/{delivery_id}/redeliver— invia nuovamente ora.POST /v1/webhooks/{id}/ping— un evento di test.POST /v1/webhooks/{id}/rotate— nuovo segreto (il precedente cessa immediatamente; aggiorna prima il tuo server se non puoi permetterti una interruzione: registra un secondo endpoint, quindi elimina il precedente).PATCH /v1/webhooks/{id}con{"active": false}mette in pausa le consegne; quelle in sospeso vengono eliminate quando si elimina l'endpoint.
Entrambi gli SDK espongono questo sotto webhooks (create, list, get, update, delete, rotateSecret, ping, deliveries, redeliver).
Try it free in the sandbox · first FHIR call in 5 minutesFree · 30 synthetic patients · no card