# Interroger l’API Chat Completions d’OpenAI depuis un hook WordPress

> Construire un premier appel à l'API Chat Completions dans une extension WordPress, sans bibliothèque tierce, avec wp_remote_post et un hook cœur.

- Auteur : WordPress Développement
- Publié le : 2023-03-14
- Mis à jour le : 2023-03-14
- Catégorie : IA &amp; MCP
- URL : https://www.wpmoderne.fr/ia-mcp/chat-completions-openai-hook-wordpress/

## L’essentiel

- Un appel HTTP direct suffit pour commencer
- wp_remote_post gère l'authentification par en-tête
- Le hook choisi conditionne le moment de l'appel

Le 1er mars 2023, OpenAI ouvre au public l'API Chat Completions et le modèle `gpt-3.5-turbo`. Pour un développeur WordPress habitué aux appels HTTP classiques, la nouveauté tient moins à la technique qu'au format des messages échangés : une liste de rôles (`system`, `user`, `assistant`) plutôt qu'un simple bloc de texte à compléter.

Aucune bibliothèque officielle en PHP n'est fournie à cette date. La fonction `wp_remote_post`, déjà présente dans le cœur, suffit largement pour construire ce premier appel : elle gère les en-têtes, le corps JSON et les erreurs réseau sans dépendance supplémentaire.

## Choisir le bon hook pour déclencher l'appel

Le choix du hook détermine si l'appel bloque ou non le rendu d'une page. Sur une page publique, un appel synchrone dans `template_redirect` ralentirait chaque visite. Il est préférable de le déclencher depuis un contexte administrateur, par exemple lors de l'enregistrement d'un article :

- `save_post` pour lancer un traitement à la publication
- `admin_post_{action}` pour une action déclenchée par un bouton d'administration
- Un événement planifié via `wp_schedule_single_event` pour différer l'appel

## Construire la requête avec wp_remote_post

Le corps de la requête suit le format attendu par l'API : un tableau `messages`, un modèle, et éventuellement une température. La clé API se transmet dans l'en-tête `Authorization`.

> L'essentiel à retenir : Un appel HTTP direct suffit pour commencer ; wp_remote_post gère l'authentification par en-tête ; Le hook choisi conditionne le moment de l'appel

```
add_action( 'save_post', function ( $post_id ) {
    if ( wp_is_post_revision( $post_id ) ) {
        return;
    }

    $api_key = get_option( 'monplugin_openai_key' );
    if ( empty( $api_key ) ) {
        return;
    }

    $response = wp_remote_post( 'https://api.openai.com/v1/chat/completions', array(
        'timeout' => 20,
        'headers' => array(
            'Authorization' => 'Bearer ' . $api_key,
            'Content-Type'  => 'application/json',
        ),
        'body' => wp_json_encode( array(
            'model'    => 'gpt-3.5-turbo',
            'messages' => array(
                array( 'role' => 'system', 'content' => 'Tu résumes un article en deux phrases.' ),
                array( 'role' => 'user', 'content' => get_post_field( 'post_content', $post_id ) ),
            ),
        ) ),
    ) );
} );
```

## Lire et valider la réponse

La réponse arrive sous forme de texte JSON, qu'il faut décoder puis vérifier avant de l'utiliser. Deux échecs sont fréquents : un code HTTP différent de 200, ou une structure inattendue si l'API a renvoyé une erreur métier plutôt qu'un problème réseau.

```
if ( is_wp_error( $response ) ) {
    error_log( 'Erreur réseau OpenAI : ' . $response->get_error_message() );
    return;
}

$code = wp_remote_retrieve_response_code( $response );
$data = json_decode( wp_remote_retrieve_body( $response ), true );

if ( 200 !== (int) $code || empty( $data['choices'][0]['message']['content'] ) ) {
    error_log( 'Réponse OpenAI inattendue, code ' . $code );
    return;
}

$resume = sanitize_textarea_field( $data['choices'][0]['message']['content'] );
update_post_meta( $post_id, '_resume_ia', $resume );
```

### Gérer le délai d'attente

Le paramètre `timeout` mérite une attention particulière : la valeur par défaut de `wp_remote_post` est de cinq secondes, souvent trop courte pour une génération de texte. Vingt secondes constituent un compromis raisonnable pour un appel déclenché en tâche de fond plutôt qu'au chargement d'une page.

## Sécuriser la clé API

Stocker la clé dans une option WordPress classique via `update_option` l'expose dans un export de base de données non chiffré. Une alternative simple consiste à la lire depuis une constante définie dans `wp-config.php`, en dehors de la racine web :

```
define( 'MONPLUGIN_OPENAI_KEY', 'sk-xxxxxxxxxxxxxxxx' );
```

Le plugin lit alors la constante si elle existe, avant de retomber sur l'option en base pour les environnements où elle n'est pas définie.

> Un appel à une API externe ne doit jamais bloquer la publication d'un contenu : en cas d'échec, l'article se publie normalement, sans résumé généré, quitte à relancer le traitement plus tard.

## Pour aller plus loin

Ce premier appel reste volontairement minimal : pas de gestion de file d'attente, pas de nouvelle tentative automatique en cas d'échec temporaire. Ces raffinements ont leur place une fois le principe de base validé sur un cas réel, avec un volume d'articles suffisant pour justifier l'investissement.

La logique reste la même quel que soit le fournisseur choisi par la suite : un hook déclencheur, une requête HTTP sortante, une réponse validée avant d'être enregistrée. C'est cette structure, plus que le fournisseur, qui vieillit bien.
