# Publier et s'abonner

> Publier un évènement par HTTP, et recevoir ceux de votre tenant en SSE ou en WebSocket - sans client du courtier. Les messages sont des CloudEvents 1.0. Côté…

Guide - Depuis la version 1.5.0 - Flexway v1.6.3 - https://flexway.io/docs/developer-async/

> Publier un évènement par HTTP, et recevoir ceux de **votre** tenant en SSE ou en WebSocket - sans client du courtier. Les messages sont des **CloudEvents 1.0**.
>
> Côté produit : [Plan asynchrone et courtiers](https://flexway.io/docs/product-async/) ; côté exploitation : [Publier et consommer sur un courtier](https://flexway.io/docs/operations-async/).

## Publier

```bash
curl -i -X POST https://api.example.com/orders/events -H "Authorization: Bearer $TOKEN" \
  -H 'Content-Type: application/json' -H 'Idempotency-Key: order-42' -d '{"orderId":"42"}'
# HTTP/1.1 202 Accepted   {"id":"order-42"}
```

| Réponse | Sens | Que faire |
| --- | --- | --- |
| `202` | Le courtier a **accusé** le message | Rien |
| `428 idempotency_key_required` | La porte exige `Idempotency-Key` | L'ajouter |
| `504 upstream_timeout` | Issue **inconnue** : le message a peut-être été écrit | Renvoyer avec la **même** `Idempotency-Key` - elle devient l'`id`, les consommateurs dédupliquent |
| `503 overloaded` | Tampon de la passerelle plein | Attendre `Retry-After` |
| `503 upstream_unavailable` | Courtier injoignable | Attendre `Retry-After` |
| `400` | Vous avez envoyé un en-tête `ce-*` : les attributs sont ceux de la passerelle | Le retirer |
| `415`, `422` | Corps d'un autre type, ou hors schéma | Corriger |

Le tenant, l'`id`, la `source` et la trace sont posés par la passerelle. L'ordre n'est garanti que
par clé de message.

## S'abonner en SSE

```bash
curl -N https://api.example.com/orders/stream -H "Authorization: Bearer $TOKEN" -H 'Accept: text/event-stream'
# id: 0:18,1:7,2:11
# event: created
# data: {"specversion":"1.0","id":"order-42","tenant":"acme","data":{"orderId":"42"},...}
```

| Règle | Détail |
| --- | --- |
| Reprise | Revenez avec `Last-Event-ID` : la lecture reprend dans l'historique récent du canal |
| Hors historique | `412 precondition_failed` : rouvrez **sans** `Last-Event-ID` |
| Abonné trop lent | Fermé (`event: error`, `overloaded`) |
| Nombre de flux | Plafonné par appelant |
| Charges binaires | Reçues en JSON (`datacontenttype: application/json`) |

## S'abonner en WebSocket

Chaque message est un CloudEvent JSON ; accusez-le dans le délai annoncé :

```javascript
ws.onmessage = (m) => {
  const ev = JSON.parse(m.data);
  handle(ev);
  ws.send(JSON.stringify({ ack: ev.id }));
};
```

| Fermeture | Sens |
| --- | --- |
| `1008` | Refus, ou accusé manquant dans le délai : le message sera relivré à la reconnexion (**au moins une fois**) |
| `1011` | Courtier en panne : reconnectez-vous après un délai |
| `1013` | Abonné trop lent |

Le dernier message avant la fermeture porte le problème RFC 9457. Dédupliquez sur `source` + `id`.
