Passer au contenu principal

SORTIE - Migration V1 vs V2

La V2 du webhook de sortie restructure en profondeur le payload que Pinpo envoie à vos systèmes à chaque événement. Le format V1 — avec son objet insightPinpo profondément imbriqué et ses champs HTML mélangés — est remplacé par une structure plate, lisible et directement exploitable.

Qu'est-ce qui change entre la V1 et la V2 ?

**La structure est aplatie : **

  • En V1, les données étaient enfouies dans un objet insightPinpo imbriqué sur plusieurs niveaux (insightPinpo.report.qualificationForm[0].formResponse.value).

  • En V2, les informations essentielles sont accessibles au premier niveau du payload (segmentation, engaged, formFields).
    **La conversation est structurée : **

  • En V1, la conversation n'était disponible qu'en HTML brut (conversationDisplay).

  • En V2, elle est fournie sous forme d'un tableau d'objets typés (conversation) avec sender, content et timestamp, en plus du rendu HTML.
    Les données extraites sont simplifiées :

  • Le qualificationForm V1 (avec formQuestion, formResponse, state, lastModifiedAt) est remplacé

  • en V2 par un tableau formFields avec trois champs : key, label, value.
    **Les champs de synthèse sont séparés: **

  • En V1, le champ resume contenait un bloc HTML mélangeant segmentation, données extraites et conversation.

  • En V2, chaque élément dispose de son propre champ structuré et de sa propre version HTML (segmentationDisplay, formFieldsDisplay, conversationDisplay).
    **De nouveaux champs apparaissent : **La V2 ajoute l'objet qualification avec les dates du cycle de vie, le canal utilisé, les champs personnalisés, les tags et un lien direct vers le détail de la qualification.

Comment comprendre le format du JSON V2 par rapport au JSON V1 ?

Identification et métadonnées

Segmentation et statut

Données extraites

Avant (V1) — **insightPinpo.report.qualificationForm** :

[
  {
    "formQuestion": {
      "id": "project",
      "question": "Le lead a un projet d'achat dans le neuf",
      "type": "boolean"
    },
    "formResponse": {
      "value": true
    },
    "note": null,
    "state": "add",
    "lastModifiedAt": "2024-03-04T10:02:00.000Z"
  }
]

Après (V2) — **formFields** :

[
  {
    "key": "budget",
    "label": "Budget",
    "value": "10000"
  }
]

Conversation

Avant (V1) : La conversation n'était disponible qu'en HTML brut dans insightPinpo.report.conversationDisplay.
Après (V2) : La conversation est fournie sous deux formes :

{
  "conversation": [
    {
      "sender": "agent",
      "content": "Hello, I'm Alicia from Pinpo...",
      "timestamp": "2026-02-23T10:05:00.000Z"
    },
    {
      "sender": "contact",
      "content": "Yes, I want to know more about it",
      "timestamp": "2026-02-23T10:06:00.000Z"
    }
  ],
  "conversationDisplay": "<ul>...</ul>"
}

Contact

Commercial (salesperson)

Champs supprimés en V2

Exemple complet : Avant / Après

Payload de sortie V1

{
  "id": "SNkSwfNMIV",
  "externalId": "externalIdLead",
  "leadTypology": {
    "key": "hot-with-meeting",
    "value": "Chaud avec RDV"
  },
  "contact": {
    "firstName": "John",
    "lastName": "Doe",
    "phone": "33606060606",
    "mail": "[email protected]",
    "externalId": "abcd1234",
    "gender": "male"
  },
  "resume": "Lead chaud

<b><u>Détail Insight PINPO</u></b>:...", "insightPinpo": { "details": [ { "key": "engaged", "title": "Engagé", "value": true }, { "key": "temperature", "title": "Température", "value": { "key": "hot", "display": "Lead chaud", "emoji": { "..." } } }, { "key": "qualificationStatus", "title": "Statut de la qualification", "value": "Clôturée" } ], "report": { "qualificationForm": [ { "formQuestion": { "id": "project", "question": "Le lead a un projet d'achat dans le neuf", "type": "boolean" }, "formResponse": { "value": true }, "state": "add", "lastModifiedAt": "2024-03-04T10:02:00.000Z" } ], "qualificationFormDisplay": "<ul>...</ul>", "conversationDisplay": "<ul>...</ul>", "conversationUrl": "https://pinpo.app.link/e/ezSMLbOx4Bb" }, "lastActivity": "2023-08-07T14:55:05.195Z", "requestDate": "2023-08-07T12:54:12.425Z", "trigger": "lead:change", "idScenario": "idAssistant" } }

Payload de sortie V2 équivalent

{
  "agentId": "c74a151b-cc63-428f-a96a-7cfe3c9c578d",
  "eventType": "done",
  "engaged": true,
  "summary": "Contact engaged - Hot - 3 data extracted",
  "segmentation": "hot",
  "segmentationDisplay": "🔥 Hot",
  "tags": "",
  "tagsDisplay": "",
  "conversation": [
    {
      "sender": "agent",
      "content": "Bonjour, je suis Marion, Cheffe de projet chez ...",
      "timestamp": "2023-08-07T12:54:00.000Z"
    },
    {
      "sender": "contact",
      "content": "Oui",
      "timestamp": "2023-08-07T14:39:00.000Z"
    }
  ],
  "conversationDisplay": "<ul>...</ul>",
  "formFields": [
    { "key": "project", "label": "Le lead a un projet d'achat dans le neuf", "value": "true" },
    { "key": "optinContact", "label": "Mise en relation souhaitée avec un conseiller", "value": "true" },
    { "key": "buyHorizon", "label": "Horizon d'achat", "value": "3 mois" },
    { "key": "meetingTime", "label": "Date et heure du RDV", "value": "2024-03-05T10:00:00.000Z" }
  ],
  "formFieldsDisplay": "<ul>...</ul>",
  "qualification": {
    "id": "SNkSwfNMIV",
    "externalId": "externalIdLead",
    "source": "",
    "customFields": {},
    "test": false,
    "channel": "sms",
    "importedAt": "2023-08-07T12:54:12.425Z",
    "engagedAt": "2023-08-07T12:54:00.000Z",
    "lastActivityAt": "2023-08-07T14:55:05.195Z"
  },
  "contact": {
    "firstname": "John",
    "lastname": "Doe",
    "gender": "male",
    "phone": "+33606060606",
    "mail": "[email protected]",
    "externalId": "abcd1234"
  },
  "salesperson": {},
  "detailsUrl": "https://app.pinpo.ai/app/qualifications?tab=qualifications&detail=SNkSwfNMIV"
}

Checklist de migration (sortie)

Étape

Action

1

Remplacer la lecture de leadTypology.key par segmentation.

2

Remplacer insightPinpo.details[engaged].value par engaged (premier niveau).

3

Remplacer insightPinpo.trigger par eventType.

4

Remplacer insightPinpo.idScenario par agentId.

5

Remplacer la lecture de insightPinpo.report.qualificationForm par formFields.

6

Adapter le parsing : formQuestion.questionlabel (in formFields), formResponse.valuevalue (in formFields).

7

Remplacer insightPinpo.report.conversationDisplay par le tableau structuré conversationDisplay.

8

Remplacer id et externalId (racine) par qualification.id et qualification.externalId.

9

Remplacer insightPinpo.requestDate par qualification.importedAt.

10

Remplacer insightPinpo.lastActivity par qualification.lastActivityAt.

11

Remplacer insightPinpo.report.conversationUrl par detailsUrl.

12

Adapter la casse des champs contact : firstNamefirstname, lastNamelastname.

13

Supprimer tout parsing de resume et utiliser summary + les champs *Display séparés.

14

Supprimer toute dépendance à insightPinpo — cet objet n'existe plus.

15

Intégrer les nouveaux champs si pertinent : qualification.channel, qualification.engagedAt, tags, contact.whatsAppUserId, salesperson.

16

Le tag unreachable ou l’insight not-responding sont remplacé par la segmentation unreachable.

17

Le tag wrong-phone devient une réponse booléenne dans le formFields (consulter les données dans Agents<Automatisations pour récupérer la bonne key).

18

Le tag rgpd devient une réponse booléenne dans le formFields (consulter les données dans Agents<Automatisations pour récupérer la bonne key).

19

Le tag opt-out devient une réponse booléenne dans le formFields (consulter les données dans Agents<Automatisations pour récupérer la bonne key).

Conseil : Si vous faisiez du parsing du HTML du champ resume ou de conversationDisplay pour en extraire des données, la V2 vous simplifie la vie. Les données structurées (conversation, formFields, segmentation) vous évitent tout parsing HTML. Profitez de la migration pour supprimer ce code fragile.


🌟 - Bonnes pratiques

  • Utilisez les champs structurés plutôt que les champs **Display**. Les champs conversation, formFields et segmentation sont faits pour être traités programmatiquement. Les champs Display (HTML) sont destinés à l'affichage humain uniquement.

  • Ne cherchez pas l'objet **insightPinpo**. Il n'existe plus. Si votre code y fait référence, il cassera. Faites un rechercher/remplacer global dans votre codebase.

  • Exploitez les nouvelles dates. Les champs importedAt, engagedAt et lastActivityAt vous permettent de mesurer les délais de traitement sans calcul supplémentaire.

  • Gérez le champ **salesperson** en sortie. En V1, les données du commercial n'étaient pas renvoyées dans le webhook. En V2, elles le sont. Utilisez-les pour router la qualification vers le bon commercial dans votre CRM.

  • Testez avec un webhook de test. Configurez un webhook pointant vers un outil de capture (comme webhook.site ou un endpoint Make/Zapier temporaire) pour visualiser le payload V2 complet avant d'adapter votre code de production.

  • Migrez entrée et sortie en même temps. Si vous migrez l'API d'import (entrée) en V2, migrez le webhook (sortie) dans le même mouvement. Maintenir un mix V1/V2 entre entrée et sortie complexifie inutilement votre intégration.

Avez-vous trouvé la réponse à votre question ?