> ## Documentation Index
> Fetch the complete documentation index at: https://docs.wethehivers.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Webhooks (à venir)

> Notifications HTTP sortantes pour événements THE HIVE

# Webhooks

<Warning>
  Les webhooks sont **en cours de conception** — non exposés en production. Cette page décrit le modèle prévu pour permettre aux intégrateurs de préparer leurs systèmes.
</Warning>

## Vision

Permettre aux recruteurs et intégrateurs tiers (ATS, CRM, Slack, Discord) de recevoir des événements **en push** sans polling.

```mermaid theme={null}
flowchart LR
    EV[Événement backend] --> BUS[Event bus interne]
    BUS --> MATCH[Match souscriptions]
    MATCH --> SIGN[Signer payload HMAC]
    SIGN --> DELIV[Delivery service]
    DELIV -->|POST| SUB[Endpoint client]
    SUB -->|2xx| OK[Marqué livré]
    SUB -->|4xx/5xx| RETRY[Retry backoff]
    RETRY --> DELIV
    RETRY -->|10 échecs| DLQ[Dead letter + alerte]
```

## Événements prévus

| Événement                    | Déclencheur                    | Scope                            |
| ---------------------------- | ------------------------------ | -------------------------------- |
| `offre.published`            | Offre passe à `PUBLISHED`      | Recruteur                        |
| `offre.closed`               | Offre fermée                   | Recruteur                        |
| `candidature.created`        | Nouveau candidat sur une offre | Recruteur                        |
| `candidature.status_changed` | Transition pipeline            | Recruteur                        |
| `candidat.hired`             | Candidature → HIRED            | Recruteur                        |
| `recruiter.approved`         | Admin valide un recruteur      | Admin                            |
| `recruiter.suspended`        | Sanction appliquée             | Admin                            |
| `alert.triggered`            | Nouveau match d'alerte         | Candidat (email seulement en v1) |
| `blog.comment.flagged`       | Commentaire signalé > 3 fois   | Admin                            |

## Modèle de payload

```json theme={null}
{
  "id": "evt_01HX3R...",
  "type": "candidature.created",
  "createdAt": "2026-04-18T10:00:00Z",
  "data": {
    "candidatureId": 142,
    "offreId": 55,
    "candidatId": 17,
    "statut": "NEW"
  },
  "deliveryAttempt": 1
}
```

Headers HTTP envoyés :

```http theme={null}
POST /your-webhook HTTP/1.1
Content-Type: application/json
X-Hive-Event: candidature.created
X-Hive-Delivery: dlv_01HX3R...
X-Hive-Signature: t=1713441600,v1=a1b2c3...
User-Agent: HiveWebhooks/1.0
```

## Signature HMAC

```mermaid theme={null}
sequenceDiagram
    participant API as Backend
    participant SUB as Subscriber

    API->>API: timestamp = now
    API->>API: payload = JSON body
    API->>API: sig = HMAC_SHA256(secret, f"{ts}.{payload}")
    API->>SUB: POST avec X-Hive-Signature: t=ts,v1=sig
    SUB->>SUB: Recalcule HMAC côté serveur
    SUB->>SUB: Compare en temps constant
    SUB->>SUB: Vérifie ts dans ±5 min
    alt Valide
        SUB-->>API: 200 OK
    else Invalide
        SUB-->>API: 401 Unauthorized
    end
```

### Vérification (Node.js)

```javascript theme={null}
import crypto from 'crypto';

function verifyHiveSignature(rawBody, header, secret) {
  const parts = Object.fromEntries(header.split(',').map((p) => p.split('=')));
  const expected = crypto
    .createHmac('sha256', secret)
    .update(`${parts.t}.${rawBody}`)
    .digest('hex');
  const valid = crypto.timingSafeEqual(
    Buffer.from(expected),
    Buffer.from(parts.v1),
  );
  const fresh = Math.abs(Date.now() / 1000 - Number(parts.t)) < 300;
  return valid && fresh;
}
```

### Vérification (Python)

```python theme={null}
import hmac, hashlib, time

def verify(raw_body: bytes, header: str, secret: str) -> bool:
    parts = dict(p.split("=") for p in header.split(","))
    expected = hmac.new(secret.encode(),
                        f"{parts['t']}.{raw_body.decode()}".encode(),
                        hashlib.sha256).hexdigest()
    fresh = abs(time.time() - int(parts["t"])) < 300
    return hmac.compare_digest(expected, parts["v1"]) and fresh
```

## Politique de retry

```mermaid theme={null}
flowchart TD
    SEND[Livraison] --> S{Réponse}
    S -->|2xx| OK[Livré]
    S -->|4xx| FAIL[Échec définitif, log]
    S -->|5xx ou timeout| R[Retry]
    R --> W[Attente backoff exponentiel]
    W --> SEND
    R -->|> 10 tentatives| DLQ[Dead letter queue]
    DLQ --> ALERT[Email intégrateur]
```

| Tentative |    Délai |
| --------- | -------: |
| 1         | immédiat |
| 2         |     30 s |
| 3         |    2 min |
| 4         |   10 min |
| 5         |   30 min |
| 6         |      1 h |
| 7         |      4 h |
| 8         |     12 h |
| 9         |     24 h |
| 10        |     48 h |

**Timeout** par tentative : 10 secondes.

## Endpoints prévus

```http theme={null}
POST   /v1/api/webhooks/subscriptions
GET    /v1/api/webhooks/subscriptions
GET    /v1/api/webhooks/subscriptions/{id}
PATCH  /v1/api/webhooks/subscriptions/{id}
DELETE /v1/api/webhooks/subscriptions/{id}

GET    /v1/api/webhooks/deliveries?subscriptionId=123
POST   /v1/api/webhooks/deliveries/{id}/replay
GET    /v1/api/webhooks/events  # liste des types disponibles
```

### Exemple de souscription

```json theme={null}
POST /v1/api/webhooks/subscriptions
{
  "url": "https://ats.example.com/hive-webhook",
  "events": ["candidature.created", "candidature.status_changed"],
  "active": true,
  "description": "ATS intégration Tech Corp"
}
```

Réponse avec `secret` à stocker :

```json theme={null}
{
  "id": 12,
  "url": "https://ats.example.com/hive-webhook",
  "events": [...],
  "secret": "whsec_abc123...",
  "active": true
}
```

## Alternative actuelle : polling

En attendant les webhooks, utiliser :

```mermaid theme={null}
flowchart LR
    CRON[Cron ou worker] --> API[GET /recruiters/me/offres/X/candidatures]
    API --> FILT[Filtrer createdAt > last_seen]
    FILT --> SYNC[Sync ATS]
    SYNC --> STORE[Update last_seen]
```

**Fréquence recommandée** : 60 secondes minimum (rate limit oblige).

## Roadmap

```mermaid theme={null}
timeline
    title Webhooks THE HIVE
    Q2 2026 : Design finalisé, endpoints spec OpenAPI
    Q3 2026 : Bêta fermée avec 5 partenaires
    Q4 2026 : GA, dashboard recruteur, replay UI
    2027 : Filtres avancés, transformation payload
```

## Voir aussi

* [FAQ intégration](/dx/faq)
* [Rate limiting](/rate-limiting)
