# Webhooks

> Aláírt, újrapróbálkozó, karcsú események erőforrás-írásokhoz, hozzájárulási változásokhoz és véglegesített dokumentumokhoz, aláírás-ellenőrzéssel TypeScript, Dart és Python nyelven.

Source: https://developers.anpheros.com/hu/guides/webhooks

Az Anpheros Platform meghívhatja a szerverét, amikor valami történik a projektben: egy erőforrás
írásra került, egy személy hozzáférést adott vagy visszavonta, egy dokumentum véglegesítésre került. Az események
**karcsúak**: id-k, típus, verzió — soha nem klinikai tartalom. Olvassa el az erőforrást az API-n
keresztül, ha szüksége van rá. Minden kézbesítés alá van írva; ellenőrizze az aláírást, mielőtt megbízna benne.

## Végpont regisztrálása

```bash
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"}'
```

A válasz tartalmaz `secret` (`whsec_…`) **egyszer**. Tárolja el; szüksége lesz rá az aláírások ellenőrzéséhez.
A `events` elfogadja a `["*"]` vagy bármelyikét a következőknek:

| típus | mikor | `data` |
|---|---|---|
| `resource.created` / `resource.updated` / `resource.deleted` | a projektje FHIR erőforrást írt (REST v1, FHIR API vagy egy köteg) — **vagy egy másik projekt írt egy olyan rekordba, amelyhez hozzáférése van** ( Ön hozta létre a beteget, vagy aktív hozzáférése van); akkor a `data.external` `true`, és a `data.source` megmondja, ki írta: `author_type` (beteg / gyakorló / eszköz / import / AI), `organization` (a megjelenítendő név, amely nevében az író járt el), `practitioner` (név a címtárból, ha ismert), `source_system` | `resource_type`, `id`, `patient` (az azonosító, amit lát), `version`, `last_updated`, és külső írások esetén `external`, `source` |
| `consent.granted` | egy személy hozzáférést adott az alkalmazásához a hozzájárulási oldalon (vagy egy megbízható alkalmazás összekapcsolta a rekordját) | `grant_id`, `patient`, `application_id`, `scopes`, `purpose`, `expires_at` |
| `consent.revoked` | a személy (vagy a platform) megszüntetett egy hozzáférést | ugyanaz, mint fent, plusz `revoked_at`, `reason` |
| `document.finalized` | egy dokumentum feltöltése befejeződött és ellenőrzőösszeggel lett ellátva | `id`, `patient`, `content_type`, `size`, `sha256` |
| `proposal.created` | egy AI ügynök írást javasolt egy olyan rekordba, amelyet lát; várja a személy jóváhagyását | `id`, `patient`, `action`, `resource_type` |
| `ping` | tesztszállítást kért | `endpoint` |

A végpontok projektenként **és környezetenként** vannak: egy `sk_test_` kulcs kezeli a sandbox végpontokat,
egy `sk_live_` kulcs pedig a production végpontokat. Az URL-eknek nyilvános `https://` végpontoknak kell lenniük. A regisztráció (és bármely későbbi `url` változtatás) megtagadja a helyi, privát, link-local, metaadat és más fenntartott címeket — `localhost`, `127.0.0.1`, `::1`, `10.0.0.0/8`, `192.168.0.0/16`, `fd00::/8` és hasonlókat — és az ezekre feloldódó neveket, `400` `invalid` hibával a `url` mezőben; ez a sandboxban is érvényes. Minden kézbesítés újra ellenőrzi a címet, és csak az éppen ellenőrzött IP-címekhez csatlakozik, így egy név, amely később egy privát hálózatra mutat (DNS-újrakötés), semmit sem kap. Az események fogadásához a saját gépen fejlesztés közben, tegye elérhetővé egy nyilvános HTTPS alagúton keresztül, és regisztrálja az alagút címét.
Legfeljebb 10 végpont projektenként és környezetenként.

## A kézbesítés

```
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":"…"}}
```

Bármilyen `2xx` esetén 10 másodpercen belül válaszoljon. Minden más (vagy időtúllépés) hiba, és a
kézbesítést legfeljebb 24 órán (10 kísérlet) keresztül próbáljuk újra, visszalépéssel, majd `exhausted` jelöljük.
A kézbesítések legalább egyszeriek, és előfordulhat, hogy nem sorrendben érkeznek: használja a `Anpheros-Event-Id`-ot
az ismétlődések kiküszöbölésére, és a `data.version`-ot az elavult frissítések figyelmen kívül hagyására.

## Aláírás ellenőrzése

A(z) `v1` a titkos kulcsoddal végzett HMAC-SHA256 művelet eredménye a(z) `<t>.<raw body>` felett; utasítsd el, ha a(z) `t` 5 percnél régebbi.

```ts
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();
});
```

```dart
import 'package:anpheros_sdk/anpheros_sdk.dart';
final ok = verifyWebhookSignature(secret: secret, header: request.headers['anpheros-signature'], body: rawBodyBytes);
```

```python
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"])
```

## Működtetés

- `GET /v1/webhooks/{id}/deliveries?status=failed` — a napló, legújabb elöl, állapotkóddal és hibával.
- `POST /v1/webhooks/{id}/deliveries/{delivery_id}/redeliver` — küldjön egyet újra most.
- `POST /v1/webhooks/{id}/ping` — egy teszt esemény.
- `POST /v1/webhooks/{id}/rotate` — új titkos kulcs (a régi azonnal leáll; frissítse a szerverét először, ha nem engedheti meg magának a szünetet: regisztráljon egy második végpontot, majd törölje a régit).
- `PATCH /v1/webhooks/{id}` `{"active": false}`-tal szünetelteti a kézbesítéseket; a függőben lévőket eldobja, amikor törli a végpontot.

Mindkét SDK ezt a `webhooks` alatt teszi elérhetővé (`create`, `list`, `get`, `update`, `delete`, `rotateSecret`, `ping`, `deliveries`, `redeliver`).
