Comment envoyer les données d’un formulaire de contact directement vers HubSpot, sans passer par un plugin de synchronisation généraliste qui gère des dizaines de CRM différents et n’expose qu’une fraction des options réellement utiles ici ? C’est la question posée pour un client déjà équipé de HubSpot, dont le thème sur mesure devait alimenter son CRM sans ajouter une dépendance supplémentaire à surveiller.
Ce tutoriel construit cet appel direct à l’API HubSpot depuis un formulaire de template, avec une gestion complète des erreurs. Il ne traite ni les workflows marketing HubSpot déclenchés après la création du contact, ni la configuration du pipeline commercial associé.
Préparer l’authentification côté HubSpot
HubSpot authentifie les appels API via un jeton d’accès privé, généré depuis les paramètres de l’application privée du compte HubSpot. Ce jeton ne doit jamais apparaître en clair dans le code du thème : il se stocke en variable d’environnement, lue côté serveur uniquement.
// wp-config.php, ou fichier .env chargé en amont
define( 'HUBSPOT_JETON_ACCES', getenv( 'HUBSPOT_JETON_ACCES' ) );
Construire l’endpoint de création de contact
Le formulaire du template envoie ses données à un endpoint REST WordPress dédié, qui se charge à son tour d’appeler l’API HubSpot côté serveur — jamais directement depuis le navigateur, pour ne pas exposer le jeton d’accès.
add_action( 'rest_api_init', function () {
register_rest_route( 'contact/v1', '/hubspot', array(
'methods' => 'POST',
'callback' => 'contact_creer_dans_hubspot',
'permission_callback' => '__return_true',
'args' => array(
'email' => array( 'required' => true, 'sanitize_callback' => 'sanitize_email' ),
'nom' => array( 'required' => true, 'sanitize_callback' => 'sanitize_text_field' ),
),
) );
} );
L’appel HTTP vers l’API HubSpot
WordPress fournit wp_remote_post() pour ce type d’appel, sans nécessiter de bibliothèque HTTP supplémentaire. L’endpoint HubSpot concerné est /crm/v3/objects/contacts, qui accepte une création de contact via une requête POST classique en JSON.
function contact_creer_dans_hubspot( WP_REST_Request $request ) {
$reponse = wp_remote_post( 'https://api.hubapi.com/crm/v3/objects/contacts', array(
'headers' => array(
'Authorization' => 'Bearer ' . HUBSPOT_JETON_ACCES,
'Content-Type' => 'application/json',
),
'body' => wp_json_encode( array(
'properties' => array(
'email' => $request->get_param( 'email' ),
'firstname' => $request->get_param( 'nom' ),
),
) ),
'timeout' => 10,
) );
if ( is_wp_error( $reponse ) ) {
return new WP_REST_Response( array(
'succes' => false,
'erreur' => 'Impossible de contacter HubSpot pour le moment.',
), 502 );
}
$code = wp_remote_retrieve_response_code( $reponse );
$corps = json_decode( wp_remote_retrieve_body( $reponse ), true );
if ( 201 === $code ) {
return new WP_REST_Response( array( 'succes' => true ), 200 );
}
return contact_gerer_erreur_hubspot( $code, $corps );
}

Gérer les erreurs, en particulier les doublons
L’API HubSpot renvoie un code 409 lorsque le contact existe déjà avec cette adresse email — un cas fréquent dès qu’un visiteur remplit le formulaire une seconde fois. Il faut alors basculer vers une mise à jour plutôt qu’une création, en récupérant l’identifiant du contact existant à partir du message d’erreur retourné par HubSpot.
function contact_gerer_erreur_hubspot( $code, $corps ) {
if ( 409 === $code ) {
preg_match( '/Existing ID: (\d+)/', $corps['message'] ?? '', $correspondances );
if ( ! empty( $correspondances[1] ) ) {
return contact_mettre_a_jour_hubspot( $correspondances[1], $corps );
}
}
return new WP_REST_Response( array(
'succes' => false,
'erreur' => 'Erreur HubSpot : ' . ( $corps['message'] ?? 'inconnue' ),
), 500 );
}
Cette extraction par expression régulière n’est pas idéale — elle dépend du format exact du message d’erreur retourné par HubSpot, qui pourrait évoluer. Une alternative plus robuste consiste à effectuer d’abord une recherche du contact par email via l’endpoint /crm/v3/objects/contacts/search, avant toute tentative de création, pour éviter de dépendre de ce message d’erreur.
Journaliser sans exposer le jeton
- Consigner les échecs d’appel dans les logs applicatifs du thème, sans jamais y inclure le jeton d’accès en clair
- Prévoir une alerte email vers l’équipe technique si le taux d’échec dépasse un seuil sur une fenêtre glissante
- Afficher côté visiteur un message générique, jamais le détail de l’erreur HubSpot brute
Ne renvoyez jamais le contenu brut d’une réponse d’erreur d’API tierce à l’utilisateur final. Un message générique protège à la fois l’expérience utilisateur et des détails d’implémentation qui n’ont rien à faire côté navigateur.
En résumé
Un appel direct à l’API HubSpot depuis un endpoint REST maison évite d’installer un plugin de synchronisation générique dès que le besoin se limite à la création ou mise à jour de contacts. La rigueur se joue sur trois points : garder le jeton d’accès strictement côté serveur, gérer explicitement le cas des doublons, et ne jamais exposer le détail technique d’une erreur HubSpot à l’utilisateur qui a rempli le formulaire.