Campagnes et annonces dans l'API Ads

Idée centrale

Deux ressources de l'API REST Ads d'OpenAI (api.ads.openai.com/v1) forment le cœur de la gestion programmatique de la hiérarchie publicitaire : la campagne (campaign), qui porte budget, calendrier et ciblage, et l'annonce (ad), qui porte le contenu créatif. Chacune expose un cycle de vie CRUD complet (créer, lire, mettre à jour) ainsi que des actions dédiées de changement d'état (activate, pause, archive). Le niveau intermédiaire de la hiérarchie — le groupe d'annonces (ad_group) — se rattache aux campagnes et aux annonces mais sa page de référence n'a pas été récupérée dans le lot de sources traité ici (voir « Limites et nuances »).

Définition

Les points de terminaison POST /campaigns et POST /ads (et leurs variantes de lecture, mise à jour et changement d'état) de l'API Ads d'OpenAI, qui permettent de créer et piloter par programmation la même hiérarchie publicitaire (campagne → groupe d'annonces → annonce) que celle gérée manuellement dans Ads Manager via Création de campagnes dans Ads Manager.

Contexte

Documente deux des huit pages de la référence API Ads : Campaigns et Ads. S'appuie sur l'authentification et les conventions générales documentées dans Authentification, compte publicitaire et fichiers dans l'API Ads (non redéfinies ici). Le groupe d'annonces (ad_group), niveau intermédiaire nécessaire pour rattacher une annonce à une campagne (champ ad_group_id requis à la création d'une annonce), est mentionné dans plusieurs exemples de cette page (adgrp_301) mais sa page de référence propre (« Ad Groups », api-reference/ad-groups) est absente du lot de vingt sources traité pour cette intégration — voir « Limites et nuances ». Capturée le 2026-08-08.

Fonctionnement

Campagnes

Lister les campagnes — GET /campaigns

ParamètreTypeRequisNotes
limitintegerNonEntre 1 et 500. Par défaut 20.
afterstringNonCurseur pour la page suivante.
beforestringNonCurseur pour la page précédente.
orderstringNonasc ou desc.

Réponse paginée, enveloppe object: "list". L'objet campaign expose au minimum : id (préfixe cmpn_), created_at, updated_at, status, bidding_type, budget.lifetime_spend_limit_micros, conversion_event_setting_ids, description, start_time, end_time, mode, name, targeting.

Créer une campagne — POST /campaigns

ChampTypeRequisNotes
namestringOui3 à 1000 caractères, doit inclure un caractère non-espace.
descriptionstringNonDescription de la campagne.
start_timeintegerNonTimestamp Unix entre 946684800 et 4102444800. Si omis, la campagne démarre immédiatement.
end_timeintegerNonTimestamp Unix entre 946684800 et 4102444800.
statusstringOuiactive ou paused.
budget.lifetime_spend_limit_microsintegerOuiMinimum 1000000 (micro-unités de la devise du compte ; 1000000 micros = 1 unité).
modestringNonproduct_feed pour une campagne à flux produits — voir Création de campagnes à flux produits via l'API Ads.
bidding_typestringNonimpressions, clicks ou conversions. Par défaut impressions.
conversion_event_setting_idsstring[]NonPour conversions : exactement un identifiant actif de configuration d'événement standard du compte — voir Campagnes optimisées pour la conversion via l'API Ads (oCPC).
targeting.locations.includeobject[]NonIdentifiants de localisations incluses — voir Ciblage géographique des campagnes dans l'API Ads (Campaign Targeting).

Si le ciblage de localisation est omis, la campagne peut cibler toutes les localisations disponibles.

curl -X POST "https://api.ads.openai.com/v1/campaigns" \
  -H "Authorization: Bearer $OPENAI_ADS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Spring launch",
    "description": "Promote the new productivity bundle.",
    "start_time": 1735689600,
    "end_time": 1738368000,
    "status": "active",
    "budget": { "lifetime_spend_limit_micros": 25000000 },
    "targeting": {
      "locations": { "include": [{ "id": "2000043" }, { "id": "3000194" }] }
    }
  }'

La réponse résout les localisations avec leurs métadonnées complètes (id, typeregion ou dma dans les exemples disponibles —, country_code, name, region_code).

La création d'une campagne standard et d'une campagne à enchère optimisée pour la conversion (oCPC) empruntent le même point de terminaison POST /campaigns : seule la présence de conversion_event_setting_ids (exactement un identifiant) et bidding_type: "conversions" distinguent le second cas — voir le détail complet du flux oCPC dans Campagnes optimisées pour la conversion via l'API Ads (oCPC).

Récupérer une campagne — GET /campaigns/{campaign_id}

curl -X GET "https://api.ads.openai.com/v1/campaigns/cmpn_101" \
  -H "Authorization: Bearer $OPENAI_ADS_API_KEY"

Mettre à jour une campagne — POST /campaigns/{campaign_id}

La mise à jour se fait via POST, explicitement pas via PATCH ni PUT. Tous les champs sont optionnels. Si budget est inclus, il faut envoyer l'objet complet. description, start_time, end_time et targeting peuvent être mis à null pour les effacer. status accepte active, paused ou archived. On ne peut pas mettre à jour bidding_type, ni (pour une campagne oCPC) conversion_event_setting_ids.

curl -X POST "https://api.ads.openai.com/v1/campaigns/cmpn_101" \
  -H "Authorization: Bearer $OPENAI_ADS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "description": "Updated launch window and budget.",
    "status": "paused",
    "budget": { "lifetime_spend_limit_micros": 30000000 }
  }'

Changer l'état d'une campagne via des actions dédiées

Chaque point de terminaison retourne la campagne mise à jour. Les campagnes en pause ne diffusent pas d'annonces. L'archivage n'est pas réversible (« archiving isn't reversible ») : ne l'utiliser que pour des objets définitivement inutiles.

Annonces

Lister les annonces — GET /ads

ParamètreTypeRequisNotes
ad_group_idstringOuiID du groupe d'annonces parent.
limitintegerNonEntre 1 et 500. Défaut 20.
afterstringNonCurseur pour la page suivante.
beforestringNonCurseur pour la page précédente.
orderstringNonasc ou desc.

L'objet ad expose : id (préfixe ad_), name, created_at, updated_at, creative (sous-objet), status, review_status.

Créer une annonce — POST /ads

ChampTypeRequisNotes
ad_group_idstringOuiID du groupe d'annonces parent.
namestringOui3 à 1000 caractères, non montré aux utilisateurs finaux.
creative.typestringOuichat_card ou product_ad_template — voir Création de campagnes à flux produits via l'API Ads.
creative.titlestringOui3 à 50 caractères.
creative.bodystringOuiMaximum 100 caractères.
creative.pricestringNonTexte de prix, ou {{product.price}} pour un template produit.
creative.target_urlstringPour chat_cardURL de destination ; un template produit la reçoit automatiquement de l'article de flux.
creative.file_idstringPour chat_cardFichier retourné par POST /upload — voir Authentification, compte publicitaire et fichiers dans l'API Ads.
statusstringOuiactive ou paused.
curl -X POST "https://api.ads.openai.com/v1/ads" \
  -H "Authorization: Bearer $OPENAI_ADS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "ad_group_id": "adgrp_301",
    "name": "Planner launch card",
    "status": "active",
    "creative": {
      "type": "chat_card",
      "title": "Try the new workspace planner",
      "body": "Coordinate tasks, docs, and meetings in one place.",
      "target_url": "https://example.com/workspace-planner",
      "file_id": "file_901"
    }
  }'

Product-ad templates : un groupe d'annonces de type flux produit ne peut contenir qu'au maximum une annonce product_ad_template non archivée. Ces templates reçoivent leur image et leur URL de destination de l'article de flux sélectionné : ils n'ont donc besoin ni de creative.file_id ni de creative.target_url.

Récupérer une annonce — GET /ads/{ad_id}

curl -X GET "https://api.ads.openai.com/v1/ads/ad_501" \
  -H "Authorization: Bearer $OPENAI_ADS_API_KEY"

Mettre à jour une annonce — POST /ads/{ad_id}

Tous les champs sont optionnels. Si creative est inclus, il faut envoyer l'objet créatif complet (pas de fusion partielle). À la mise à jour, status accepte active, paused ou archived (contrairement à la création, où seuls active/paused sont acceptés).

Statut de revue (review_status)

Chaque réponse d'annonce inclut review_status, qui peut valoir in_review, rejected ou approved. Une annonce rejetée enfreint l'une des politiques publicitaires d'OpenAI (voir Ad Policies) ; il faut la modifier pour qu'elle repasse en revue.

Changer l'état d'une annonce via des actions dédiées

Distinctes de la mise à jour générique. Une annonce en pause n'est pas diffusée. L'archivage n'est pas réversible.

Éléments essentiels

Distinctions importantes

Ne pas confondre le champ status d'une campagne ou d'une annonce (active/paused/archived, modifiable par la mise à jour générique) avec les actions dédiées /activate, /pause, /archive : les deux chemins mènent au même résultat pour activer ou mettre en pause, mais l'avertissement d'irréversibilité n'est explicitement rattaché qu'aux actions dédiées d'archivage.

Ne pas confondre creative.file_id (fourni par l'appelant, via POST /upload) et creative.image_url (retourné en lecture, calculé côté serveur à partir du file_id) : image_url n'apparaît jamais dans les champs acceptés en écriture.

Ne pas confondre cette page (gestion programmatique via l'API REST, authentifiée par jeton porteur) avec Création de campagnes dans Ads Manager (même hiérarchie campagne/groupe/annonce, mais pilotée depuis l'interface Ads Manager) : les deux couvrent le même objet fonctionnel sous deux angles complémentaires, non fusionnés dans ce wiki.

Cas pratiques

Aucun cas pratique disponible : les identifiants et valeurs d'exemple (cmpn_101, ad_501, Spring launch) sont manifestement fictifs et illustratifs.

Erreurs fréquentes

Ne pas tenter de modifier bidding_type par POST /campaigns/{campaign_id} : ce champ est verrouillé après création, une nouvelle campagne est nécessaire pour changer d'objectif.

Ne pas envoyer un objet creative partiel lors d'une mise à jour d'annonce : l'objet complet est requis, il n'y a pas de fusion partielle des champs du créatif.

Ne pas archiver une campagne ou une annonce par erreur en pensant pouvoir revenir en arrière : l'archivage est explicitement non réversible.

Ne pas créer plusieurs annonces product_ad_template non archivées dans un même groupe d'annonces à flux produits : la contrainte est d'une seule au maximum.

Limites et nuances

Relations

Points à vérifier

Sources