Le retrait colis remonte maintenant automatiquement à Trustt via save_receipt (livré, en prod). On veut faire pareil pour les publications : aujourd'hui l'opérateur reçoit le lien et le recopie à la main dans Trustt. Cette page fait l'inventaire de ce qu'on a, du manque exact côté Trustt, et propose un contrat d'endpoint calé sur le style réel de votre API.
Code couleur : livré à créer bloquant.
La réception colis est résolue. La publication reste manuelle.
| Signal | Sens | État |
|---|---|---|
| Réception / retrait colis | Trustt SMS → Trustt | livré via save_receipt (push à la déclaration + réconciliation deux sens) |
| Posts publiés (lecture) | Trustt → Trustt SMS | lecture via realizedUgc sur ambassadors (sert à ne relancer que les silencieux) |
| Posts publiés (écriture) | Trustt SMS → Trustt | manuel l'opérateur copie le lien reçu et le colle dans Trustt à la main |
Objectif : quand un ambassadeur envoie son lien (via le brief Trustt SMS) ou qu'un opérateur l'ajoute à la main, le pousser à Trustt automatiquement, exactement comme le colis.
Tout est prêt côté données et plomberie : c'est une copie du dispositif réception.
| Brique | Détail |
|---|---|
| Donnée publication | Par soumission : postUrl, platform (instagram / tiktok / youtube), status (pending / validated / rejected), submittedAt, source (brief ou ajout manuel). |
| Lien ambassadeur | candidateUUID (le cid Trustt) connu par jonction, déjà rapproché par téléphone à la synchro. |
| Lecture des posts Trustt | Snapshot par jonction depuis realizedUgc (publié oui/non, nombre, avis). |
| Infra de remontée | Réutilisable telle quelle : client d'écriture, file BullMQ avec retries, sous-doc d'état + machine de statuts, classifieur d'écart, réconciliation greffée sur la synchro quotidienne + bouton manuel. |
5 endpoints : 4 en lecture, 1 seul en écriture (save_receipt). Les posts sont en lecture seule, et sans l'URL.
realizedUgc.posts[] (sur l'endpoint ambassadors, LECTURE) :
{
"socialTypeId": 2,
"postTypeId": 4,
"postTypeLabel": "Story Instagram",
"status": "pending",
"dateCrea": "2026-04-30 21:05:24"
}
// pas d'URL du post
Constat : il n'existe aucun endpoint pour déclarer une publication (équivalent de save_receipt côté post), et les posts lus ne portent pas l'URL.
Vérifié en appelant l'API en prod sur l'ensemble du compte (pas seulement nos campagnes liées) : 54 entreprises, 98 marques, 334 campagnes, 9594 ambassadeurs, 4141 posts réels. C'est une certitude empirique, plus une lecture de la doc.
| Donnée | Réalité observée (4141 posts) |
|---|---|
| Champs d'un post | socialTypeId, postTypeId, postTypeLabel, status, dateCrea — rien d'autre, jamais |
| URL / lien / id du post | JAMAIS présent (0 sur 4141) : Trustt ne stocke pas le lien |
status | valid (4009) + pending (132). Aucun rejeté. |
| Types observés | Vidéo TikTok 2284 · Post Instagram 1415 · Story Instagram 366 · Post Facebook 55 · Vidéo Youtube 14 · Article 5 · Post Pinterest 2 |
review (avis) | rempli 4122 fois, forme { dateCrea, isVideo } — pas de contenu, pas d'URL |
merchantReview | 491 entrées, forme { dateCrea } |
testForms | 4428 entrées, forme { formId, name, dateCrea } |
receiptStatus | 0 (1674), 1 (7916), 2 (4 — valeur non documentée, confirmée) |
Trustt auto-détecte déjà les posts. Sur tout le compte, des milliers de posts sont valid sans qu'on ait rien poussé. Trustt a donc son propre pipeline de détection. Le modèle d'un post est par type, pas par lien : aucune URL nulle part, sur 4141 posts.
Relevé du compte entier (335 campagnes pour l'attendu, 9594 ambassadeurs / 4141 posts pour le réalisé). « Publication » au sens large = 4 briques, pas seulement le post.
| Brique | Attendu (campagne) | Réalisé (ambassadeur) | Possibilités |
|---|---|---|---|
| Post social | expectedUgc.expectedPost[] | realizedUgc.posts[] | type + plateforme + quantité |
| Avis produit | expectedUgc.review | realizedUgc.review | expected, hasVideo, hasTestingPhotos |
| Avis marchand | expectedUgc.merchantReview | realizedUgc.merchantReview[] | merchantName, merchantUrl |
| Formulaire de test | expectedUgc.testForms[] | realizedUgc.testForms[] | name, nbDaysStart (J+N) |
| Livrable | Attendu (sur 335 campagnes) | Réalisé |
|---|---|---|
| Post social | 90 (245 n'en demandent aucun) | 4141 posts |
| Avis produit | 173 (+photos 37, +vidéo 2) | 4122 |
| Avis marchand | 46 (Farmaline, Peggy Sage, Labo ACM, Cocooncenter, Trustpilot…) | 491 |
| Formulaire de test | 136 (J+7/14/21/28…) | 4428 |
| Type | Attendu (campagnes) | Réalisé (posts) |
|---|---|---|
| Post Instagram | 54 | 1415 |
| Vidéo TikTok | 49 (+1 en qty 2) | 2284 |
| Story Instagram | jamais | 366 |
| Post Facebook | jamais | 55 |
| Vidéo Youtube | jamais | 14 |
| Article | jamais | 5 |
| Post Pinterest | jamais | 2 |
Conséquence remontée : l'attendu formel ne décrit que 2 types (Post Instagram, Vidéo TikTok). Les ambassadeurs publient pourtant Story, Facebook, Youtube, Article, Pinterest. Une remontée pilotée seulement par expectedPost raterait tout ce contenu hors IG/TikTok réellement publié.
| Campagnes | Contenu attendu |
|---|---|
| 62 | rien d'attendu formellement |
| 53 | Avis + 1 formulaire |
| 36 | Post TikTok |
| 35 | Avis seul |
| 28 | Post Instagram |
| 23 | Avis + Avis marchand + formulaire |
| 15 | Avis + Avis marchand |
| 10 | Post Instagram + Post TikTok |
| queue | jusqu'à Post + Avis(+photos) + Avis marchand + formulaire (profil complet) |
| # | Manque | Conséquence si absent |
|---|---|---|
| 1 | Endpoint d'écriture de publication (save_post). | bloquant on ne peut rien pousser. Même situation que la réception avant save_receipt. |
| 2 | L'URL traitée comme la clé d'un post chez Trustt (au stockage ET en lecture). | bloquant réconciliation sans URL, on ne sait jamais si « notre » post est déjà chez Trustt → on risque de le pousser en double à chaque synchro. |
Le risque central, confirmé par le relevé live : Trustt auto-détecte déjà les posts et les compte par type, sans URL. Si on pousse une URL pour un post que Trustt a déjà détecté, il ne peut pas dédupliquer (il ne connaît pas les liens) → il comptera deux posts du même type. Donc tant que l'URL n'est pas la clé d'un post côté Trustt, pousser nos publications est dangereux, pas juste impossible à réconcilier. C'est le vrai prérequis, avant même save_post.
On a une URL et une plateforme grossière (instagram). Trustt range par postTypeId fin (Post Instagram = 3 vs Story Instagram = 4, Post Facebook = 5, Vidéo Youtube = 7, Vidéo TikTok = 9). On ne sait pas distinguer un post d'une story Instagram depuis l'URL.
Donc save_post doit accepter l'URL et inférer le type côté Trustt, ou se contenter d'un socialTypeId (plateforme) quand on ne peut pas fournir mieux.
save_post à créerCalé sur le style réel de votre API (un endpoint par signal, comme save_receipt), pas sur un puits d'évènements générique.
POST https://pro.trustt.io/api_trusttsms/save_post ?key=xxx &cid=<candidateUUID> &url=<url du post, encodee> &platform=instagram|tiktok|youtube &date=2026-06-05%2012:10:00 (Y-m-d H:i:s) [&postTypeId=<int>] optionnel
| Paramètre | Format | Obligatoire | Description |
|---|---|---|---|
key | string | oui | Clé API Trustt SMS |
cid | UUID | oui | Ambassadeur (candidateUUID) |
url | string | oui | Lien du post publié |
platform | enum | oui | instagram / tiktok / youtube (Trustt infère le postTypeId) |
date | string (Y-m-d H:i:s) | oui | Date de soumission du post |
postTypeId | int | non | Type précis si un jour on peut le fournir |
{
"data": {
"uuid_candidate": "679c7491-...",
"postId": "...", // id du post cree cote Trustt
"url": "https://...", // l'URL, pour le rapprochement
"postTypeId": 9, // type resolu cote Trustt
"status": "pending" // probablement a valider cote Trustt
}
}
Dédup idempotente sur (cid, url) : rejouer le même save_post (re-push, réconciliation) ne crée pas de doublon. C'est ce qui permet de pousser sans risque.
À terme : un delete_post (symétrique du futur cancel_receipt) pour un post rejeté ou retiré localement. Hors périmètre de la première phase.
| # | Question | Notre recommandation |
|---|---|---|
| 1 | Quels posts veux-tu recevoir : seulement nos validés, ou tout (y compris en attente / rejetés) ? | Validés seulement, pour ne pas t'envoyer de liens douteux. |
| 2 | Un post poussé arrive-t-il en pending chez vous (revalidation Trustt) ou est-il pris tel quel ? | Au choix, mais il faut le savoir pour l'afficher honnêtement côté SMS. |
| 3 | Peux-tu exposer l'URL dans realizedUgc.posts ? | Indispensable, sinon pas de réconciliation possible (cf. manque 2). |
Copie du dispositif réception, en deux phases.
| Phase | Contenu |
|---|---|
| Phase 1 | Sous-doc d'état de remontée par soumission (pending / pushed / already_in_trustt / failed), client savePost, file trustt-post-push, push à la validation d'un post + réconciliation greffée sur la synchro quotidienne et le bouton « Mettre à jour depuis Trustt », notifications internes en cas d'échec. |
| Phase 2 | Dédup / adoption dans les deux sens dès que Trustt renvoie les URLs (manque 2 résolu). |
Verdict (revu après relevé live) : bloqué côté Trustt, et le blocage est plus profond qu'un endpoint manquant. Le modèle de post de Trustt est par type, sans URL, et Trustt auto-détecte déjà les posts. Prérequis, dans l'ordre : (1) Trustt traite l'URL comme la clé d'un post (stockage + lecture) pour pouvoir dédupliquer notre push contre sa propre détection ; (2) alors seulement save_post a un sens. Sans (1), pousser nos publications crée des doublons. Côté Trustt SMS, tout est prêt.