Notifications
POST /admin/notifications
Section titled “POST /admin/notifications”Pousse une annonce éditée par l’admin — soit ciblée sur une liste de destinataires, soit en broadcast à tous les utilisateurs. Rejoint le pipeline standard : la ligne est persistée immédiatement, les préférences in-app sont honorées au dispatch, et le cron digest pousse la notification au tick suivant (individuelle ou en digest).
Le texte est par locale et figé tel quel : chaque destinataire est rendu dans sa locale (fallback locale par défaut → première fournie). Aucune clé de catalogue :
title/bodysont fournis par l’admin et gelés dansdata.translations.
Corps (JSON)
| Champ | Type | Obligatoire | Notes |
|---|---|---|---|
translations | { "<locale>": { "title", "body" } } | oui | locales supportées uniquement ; title/body non vides (title ≤ 150, body ≤ 2000) ; doit inclure la locale par défaut fr-FR (fallback universel) |
url | string | non | deep-link gelé dans data.url (payload push) |
userIds | ["<hex>", …] | exactement un mode | ciblé, 1..1000 ids |
scope | "all" | exactement un mode | broadcast keyset sur tous les users |
announcementId | hex (32) | non | namespace de dedup partagé ; généré et renvoyé si absent |
Fournir exactement un de userIds[] ou scope:"all" (les deux ou aucun = 400).
Dedup / idempotence : tous les destinataires d’une même annonce partagent la clé system.announcement:<announcementId>. En broadcast, renvoyer le announcementId retourné sur chaque appel ?cursor= suivant pour qu’une page reprise/rejouée ne notifie pas deux fois un même destinataire.
Query params (broadcast uniquement)
| Param | Valeurs | Défaut | Notes |
|---|---|---|---|
cursor | hex (32) | début | dernier lastId traité par l’appel précédent |
batchSize | 1..1000 | 200 | taille de lot par appel |
Réponse — ciblé (200)
{ "announcementId": "9f1c…", "mode": "targeted", "dispatched": 12, // lignes persistées "skipped": 1, // destinataire opt-out in-app "failed": [{ "userId": "ab…", "error": "…" }]}Réponse — broadcast (200) — un lot keyset par appel, boucler jusqu’à done:true
{ "announcementId": "9f1c…", "mode": "broadcast", "dispatched": 200, "skipped": 0, "failed": [], "lastId": "<hex>", "nextCursor": "<hex>", // null quand done "done": false, "totalAll": 15234, // COUNT(*) users (snapshot) "durationMs": 38}Comme les autres batches admin, une erreur de dispatch par destinataire n’avorte pas la boucle : elle part dans
failed[].
Erreurs
| Status | Body | Sens |
|---|---|---|
400 | { "error": "Request body must be a JSON object." } | corps absent/non-objet |
400 | { "error": "Provide exactly one of userIds[] or scope:\"all\"." } | ciblage ambigu |
400 | { "error": "Invalid cursor." } / "Invalid batchSize." | pagination broadcast KO |
422 | { "error": "translations must include the default locale \"fr-FR\" (used as fallback)." } | wording invalide (exemples : locale non supportée, title/body vide, trop long, défaut manquant) |
422 | { "error": "userIds must be a non-empty array of hex user ids." } | liste ciblée vide/malformée |
403 | { "error": "..." } | auth KO |
Exemples curl
# Ciblé : 2 destinataires, texte bilingue + deep-linkcurl -s -X POST -H "Authorization: Bearer $ADMIN_API_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "translations": { "fr-FR": { "title": "Nouveauté", "body": "Découvrez les nouvelles villes." }, "en-US": { "title": "What'\''s new", "body": "Discover the new cities." } }, "url": "https://hydrogen.app/cities", "userIds": ["ab12…", "cd34…"] }' \ http://hydrogen.dev.com/admin/notifications
# Broadcast : 1er appel (announcementId généré et renvoyé)curl -s -X POST -H "Authorization: Bearer $ADMIN_API_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "translations": { "fr-FR": { "title": "Maintenance", "body": "Service indisponible 22h-23h." } }, "scope": "all" }' \ "http://hydrogen.dev.com/admin/notifications?batchSize=500"
# Broadcast : appels suivants — réutiliser announcementId + nextCursor jusqu'à done:truecurl -s -X POST -H "Authorization: Bearer $ADMIN_API_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "translations": { "fr-FR": { "title": "Maintenance", "body": "Service indisponible 22h-23h." } }, "scope": "all", "announcementId": "9f1c…" }' \ "http://hydrogen.dev.com/admin/notifications?batchSize=500&cursor=<lastId>"