API NewDeal

L'API NewDeal permet d'accéder aux données de reporting de la campagne de prospection : appels, contacts, performance bizdevs et indicateurs clés de performance.

API Reporting v2

Toutes les routes sont accessibles via HTTPS. L'authentification se fait par token JWT passé dans le header Authorization.

Base URL https://bo.citoubi.fr/v2/api

Authentification

Toutes les routes nécessitent un token JWT transmis via le header Authorization: Bearer <token>.

Obtenir un token
POST
https://bo.citoubi.fr/v2/api/login
ChampTypeDescription
emailstringEmail de l'utilisateur (ex: utilisateur@newdeal)
passwordstringMot de passe du compte
Réponse
JSON
{
  "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ1c2VyQGthYmVlbi5pbyIsInJvbGUiOiJST0xFX0tBQkVFTiIsImV4cCI6MTc0MjUwMDAwMH0.abc123signature",
  "token_type": "bearer",
  "expires_in": 3600
}
cURL
curl -X POST https://bo.citoubi.fr/v2/api/login \
  -H "Content-Type: application/json" \
  -d '{"email":"utilisateur@newdeal","password":"votre_mot_de_passe"}'
Contrôle d'accès
ConditionAccès
Utilisateur @newdeal✓ Autorisé
Administrateur (ROLE_ADMIN)✓ Autorisé
Tout autre utilisateur✗ Erreur 403
GET

Contacts Count

https://bo.citoubi.fr/v2/api/kabeen/contacts/count

Retourne le nombre total de contacts présents dans la liste HubSpot NewDeal.

Réponse
ChampTypeExemple
contact_countinteger978
JSON
{
  "contact_count": 978
}
cURL
curl -X GET https://bo.citoubi.fr/v2/api/kabeen/contacts/count \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..."

GET

Calls Count

https://bo.citoubi.fr/v2/api/kabeen/calls/count

Retourne le nombre total d'appels enregistrés sur la campagne NewDeal.

Réponse
ChampTypeExemple
total_callsinteger966
JSON
{
  "total_calls": 966
}
cURL
curl -X GET https://bo.citoubi.fr/v2/api/kabeen/calls/count \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..."

GET

Calls by BizDev

https://bo.citoubi.fr/v2/api/kabeen/calls/bizdevs

Retourne le volume d'appels par business developer, trié par volume décroissant. Utile pour analyser la performance individuelle de chaque bizdev sur la campagne.

Réponse
ChampTypeDescription
bizdevsarrayTableau de bizdevs trié par volume décroissant
Champs de chaque bizdev
ChampTypeExemple
owner_emailstringalice.m@example.com
owner_first_namestringAlice
owner_last_namestringM.
total_callsinteger203
JSON
{
  "bizdevs": [
    {
      "owner_email": "alice.m@newdeal",
      "owner_first_name": "Alice",
      "owner_last_name": "M.",
      "total_calls": 203
    },
    {
      "owner_email": "thomas.d@newdeal",
      "owner_first_name": "Thomas",
      "owner_last_name": "D.",
      "total_calls": 187
    },
    {
      "owner_email": "sofia.r@newdeal",
      "owner_first_name": "Sofia",
      "owner_last_name": "R.",
      "total_calls": 142
    }
  ]
}
cURL
curl -X GET https://bo.citoubi.fr/v2/api/kabeen/calls/bizdevs \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..."

GET

Calls by Contact

https://bo.citoubi.fr/v2/api/kabeen/contacts/calls

Retourne le volume d'appels par contact de la liste NewDeal, trié par volume décroissant. Permet d'identifier les contacts les plus sollicités.

Réponse
ChampTypeDescription
contactsarrayTableau de contacts trié par volume décroissant
Champs de chaque contact
ChampTypeExemple
hubspot_contact_idstring123456
firstnamestringPierre
lastnamestringD.
emailstringpierre.d@example.com
total_callsinteger7
JSON
{
  "contacts": [
    {
      "hubspot_contact_id": "123456",
      "firstname": "Pierre",
      "lastname": "D.",
      "email": "pierre.d@example.com",
      "total_calls": 7
    },
    {
      "hubspot_contact_id": "234567",
      "firstname": "Marie",
      "lastname": "L.",
      "email": "marie.l@example.com",
      "total_calls": 5
    },
    {
      "hubspot_contact_id": "345678",
      "firstname": "Jean",
      "lastname": "B.",
      "email": "jean.b@example.com",
      "total_calls": 4
    }
  ]
}
cURL
curl -X GET https://bo.citoubi.fr/v2/api/kabeen/contacts/calls \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..."

GET

All Calls

https://bo.citoubi.fr/v2/api/kabeen/calls

Retourne le détail de chaque appel enregistré sur la campagne NewDeal, trié par date décroissante. Inclut les informations du contact appelé, du bizdev, et les notes.

Réponse
ChampTypeDescriptionExemple
callsarrayTableau d'appels
Champs de chaque appel
ChampTypeDescriptionExemple
call_hubspot_idstringID HubSpot de l'appel100000001
call_datedateDate de l'appel2026-03-04
call_resultstring | nullRésultat de l'appelConnecté
call_notestring | nullCorps de l'appelÉchange positif...
note_appelstring | nullNote du bizdevRappeler la semaine prochaine.
hubspot_contact_idstring | nullID HubSpot du contact123456
contact_firstnamestring | nullPrénom du contactPierre
contact_lastnamestring | nullNom du contactD.
contact_emailstring | nullEmail du contactpierre.d@example.com
bizdev_firstnamestring | nullPrénom du bizdevAlice
bizdev_lastnamestring | nullNom du bizdevM.
cumulative_calls_on_contactintegerAppels cumulés sur ce contact à cette date3
Valeurs possibles de call_result
ValeurSignification
Connecté Le contact a décroché et répondu à l'appel
Aucune réponse L'appel n'a pas abouti, pas de réponse
Occupé Ligne occupée au moment de l'appel
Mauvais numéro Le numéro est incorrect ou n'existe pas
A laissé un message en direct Le bizdev a laissé un message en direct
A laissé un message vocal Le bizdev a laissé un message sur la messagerie vocale
null Résultat non renseigné
JSON
{
  "calls": [
    {
      "call_hubspot_id": "100000001",
      "call_date": "2026-03-18",
      "call_result": "Connecté",
      "call_note": "Échange positif, très intéressé par la solution NewDeal. Demande une démo la semaine prochaine.",
      "note_appel": "Rappeler mardi 24 mars à 14h.",
      "hubspot_contact_id": "123456",
      "contact_firstname": "Pierre",
      "contact_lastname": "D.",
      "contact_email": "pierre.d@example.com",
      "bizdev_firstname": "Alice",
      "bizdev_lastname": "M.",
      "cumulative_calls_on_contact": 3
    },
    {
      "call_hubspot_id": "100000002",
      "call_date": "2026-03-17",
      "call_result": "Aucune réponse",
      "call_note": null,
      "note_appel": "Rappeler dans 2 jours.",
      "hubspot_contact_id": "234567",
      "contact_firstname": "Marie",
      "contact_lastname": "L.",
      "contact_email": "marie.l@example.com",
      "bizdev_firstname": "Thomas",
      "bizdev_lastname": "D.",
      "cumulative_calls_on_contact": 1
    },
    {
      "call_hubspot_id": "100000003",
      "call_date": "2026-03-16",
      "call_result": "A laissé un message vocal",
      "call_note": "Message laissé sur la messagerie.",
      "note_appel": null,
      "hubspot_contact_id": "345678",
      "contact_firstname": "Jean",
      "contact_lastname": "B.",
      "contact_email": "jean.b@example.com",
      "bizdev_firstname": "Sofia",
      "bizdev_lastname": "R.",
      "cumulative_calls_on_contact": 2
    }
  ]
}
cURL
curl -X GET https://bo.citoubi.fr/v2/api/kabeen/calls \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..."

GET

KPI

https://bo.citoubi.fr/v2/api/kabeen/kpi

Retourne les indicateurs clés de performance de la campagne NewDeal : taux de connexion, leads générés et taux de conversion.

Réponse
ChampTypeCalculExemple
total_callsintegerNombre total d'appels966
connected_callsintegerAppels avec résultat "Connecté"191
connection_ratefloatconnected / total × 10019.77
total_leadsintegerLeads générés sur la campagne17
conversion_ratefloatleads / connected × 1008.90
JSON
{
  "total_calls": 966,
  "connected_calls": 191,
  "connection_rate": 19.77,
  "total_leads": 17,
  "conversion_rate": 8.90
}
cURL
curl -X GET https://bo.citoubi.fr/v2/api/kabeen/kpi \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..."

Erreurs

Toutes les erreurs retournent un objet JSON avec deux champs : error (code machine) et message (explication lisible).

Exemple d'erreur 401
{
  "error": "token_invalid",
  "message": "Le token JWT est expiré ou malformé."
}
HTTPCodeCause
401 token_missing Header Authorization absent de la requête
401 token_invalid Token JWT expiré ou malformé
403 forbidden Utilisateur non NewDeal et non administrateur
404 user_not_found L'utilisateur associé au token a été supprimé
404 list_not_found La liste HubSpot NewDeal est introuvable
422 list_error La liste n'est pas de type contact ou est vide
500 server_error Erreur interne du serveur
⚠️
En cas d'erreur 500, veuillez contacter l'équipe technique NewDeal. Ces erreurs indiquent un problème côté serveur et non un problème de configuration client.

Architecture

L'API NewDeal est construite sur Laravel. Voici les fichiers clés qui composent la stack backend.

Fichiers principaux
🛣️
routes/kabeen.php
Définition des routes REST de l'API
🔐
app/Http/Middleware/NewDealAPIAuth.php
Middleware JWT — validation du token et contrôle d'accès @newdeal / ROLE_ADMIN
🎮
app/Http/Controllers/API/NewDeal/ReportingController.php
Controller principal — orchestration des appels de service et formatage des réponses
⚙️
app/Services/NewDeal/NewDealReportingService.php
Service métier — logique de reporting et requêtes SQL sur la base de données
📞
app/Services/Newdeal/Hubspot/CallsServices.php
Service d'enrichissement des contacts depuis HubSpot Calls
🔗
app/Services/External/Hubspot/ContactService.php
Service externe — mise à jour des propriétés de contacts dans HubSpot via l'API
Jointures SQL

Les données sont construites par une série de jointures depuis la campagne jusqu'aux contacts HubSpot.

SourceClé de jointureCibleRésultat
Campagne (KABEEN_CAMPAIGN_ID) id_campaign hubspot.calls_campaign Appels de la campagne
hubspot.calls_campaign id_instance → id_call hubspot.simple_calls Détails de l'appel
hubspot.simple_calls call_owner → hubspot_id hubspot.simple_owners Informations bizdev
hubspot.calls_campaign id_instance → hubspot_id hubspot.calls Appel HubSpot complet
hubspot.calls associations.contacts.results[0].id hubspot.contact_overview Contact (nom, email)
Campagne campaign_id public.lead Volume de leads
💡
La constante KABEEN_CAMPAIGN_ID est définie dans la configuration Laravel et identifie de façon unique la campagne de prospection NewDeal dans la base de données.