Opérations en masse sur les campagnes, groupes d'annonces et annonces (Bulk API)

Idée centrale

Le Bulk API est un point de terminaison asynchrone qui permet de créer ou mettre à jour, en une seule requête, jusqu'à 1 000 opérations portant sur des campagnes, groupes d'annonces et annonces. Un job soumis se suit et se récupère par identifiant, avec inspection du résultat de chaque opération individuelle. Le Bulk API est en « limited preview » et activé par compte publicitaire ; il n'est pas inclus dans la spécification OpenAPI téléchargeable.

Définition

Le point de terminaison POST /bulk_mutation_jobs de l'API Ads (et ses endpoints de suivi associés), qui permet des mutations en masse sur la hiérarchie campagne → groupe d'annonces → annonce, en s'appuyant sur des références internes au job (via des clés d'idempotence) plutôt que sur des identifiants réels connus à l'avance.

Contexte

Documente un mécanisme opérationnel autonome, compréhensible et utilisable sans avoir lu le détail complet des pages de référence classiques (Campagnes et annonces dans l'API Ads), bien que les types d'opérations reprennent directement les entités et une partie des champs documentés par ces pages. Si un endpoint bulk renvoie 404, il faut contacter l'équipe de compte OpenAI pour confirmer l'accès associé à la clé API utilisée. Capturée le 2026-08-08.

Fonctionnement

Soumission d'un job — POST /bulk_mutation_jobs

Authentification par Authorization: Bearer $OPENAI_ADS_API_KEY (voir Authentification, compte publicitaire et fichiers dans l'API Ads) ; chaque clé est propre à un compte publicitaire, sans en-tête OpenAI-Ad-Account supplémentaire. Un en-tête optionnel Idempotency-Key sécurise les nouvelles tentatives : le réutiliser avec un corps différent renvoie une erreur ; pour rejouer un job failed ou partially_failed, soumettre le même corps avec une nouvelle clé d'idempotence au niveau requête (les créations déjà réussies sont réutilisées).

La réponse à la soumission est 202 Accepted avec un objet job : id (préfixe blkmtnjob_), status (pending au départ), operation_count, created_at, completed_at (null tant que non terminé).

ChampTypeRequisDescription
operationsobject[]OuiEntre 1 et 1 000 opérations de création ou mise à jour.
validate_onlybooleanNonValide champs et dépendances sans modifier les ressources si true. Défaut false.
partial_failurebooleanNonPoursuit les opérations indépendantes après une erreur si true. Défaut true.

Mettre partial_failure à false interrompt les opérations suivantes après un échec (n'annule pas les opérations déjà effectuées). Un job en validate_only ne garantit pas la réussite finale : il ne vérifie ni l'existence des cibles de mise à jour, ni la récupération des images, ni les limites d'entités, ni les autres erreurs qui ne surviennent qu'à l'écriture.

Opérations prises en charge

Chaque entrée de operations inclut un operation_id unique, un type, et un objet input. Les créations exigent une idempotency_key unique ; les mises à jour exigent target_resource_id et au moins un champ d'entrée.

TypeEntrée requiseAutres entrées prises en charge
campaign.createname, max_budget_microsbilling_event_type, budget_type, status, target_countries, location_ids
campaign.updateAu moins un champ pris en chargename, description, status, max_budget_micros, budget_type, start_time, end_time, location_ids
ad_group.createcampaign_idempotency_key, namecontext_hints, exclusion_hints, max_bid_micros, max_cpm_bid_micros, status
ad_group.updateAu moins un champ pris en chargename, description, status, context_hints, exclusion_hints, max_bid_micros, max_cpm_bid_micros
ad.createcampaign_idempotency_key, ad_group_idempotency_key, title, body, target_url, source_image_urlstatus
ad.updateAu moins un champ pris en chargename, status, creative

Références internes au job : campaign_idempotency_key pointe vers l'idempotency_key de l'opération de campagne, ad_group_idempotency_key vers celle du groupe d'annonces — cela évite d'avoir à connaître à l'avance les identifiants réels des ressources parentes. La référence de campagne sur ad.create doit correspondre au ad_group.create parent. Une mise à jour ne peut cibler qu'une ressource qui existait déjà au moment de la soumission : impossible de mettre à jour une ressource créée dans le même job. Chaque ressource ne doit être mise à jour qu'une seule fois par job.

Statuts de création : active ou paused ; les mises à jour prennent en charge en plus archived. campaign.create a par défaut une facturation à l'impression, un budget lifetime, un statut paused, budget minimum 1000000 micro-unités. Les enchères de groupe d'annonces doivent correspondre à l'événement de facturation de la campagne parente : fournir soit max_bid_micros (clics) soit max_cpm_bid_micros (impressions, nécessite un accès de compte spécifique), pas les deux.

Contraintes de longueur : noms de campagne/groupe entre 3 et 1 000 caractères ; titres d'annonce entre 3 et 50 caractères ; corps d'annonce jusqu'à 100 caractères ; URLs jusqu'à 2 048 caractères. Une campagne accepte jusqu'à 2 500 identifiants de localisation (voir Ciblage géographique des campagnes dans l'API Ads (Campaign Targeting) pour location_ids) ; un groupe d'annonces jusqu'à 2 000 « context hints ». Pour mettre à jour une création publicitaire (creative), inclure title, body, target_url et file_id.

Récupération d'un job — GET /bulk_mutation_jobs/{job_id}

StatutSignification
pendingLe job attend d'être exécuté.
in_progressLe job traite les opérations.
completedToutes les opérations ont réussi.
partially_failedAu moins une opération réussie, une autre failed ou skipped.
failedAucune opération n'a réussi.

completed, partially_failed et failed sont des statuts terminaux.

Liste des résultats d'opérations — GET /bulk_mutation_jobs/{job_id}/operations

Paramètre limit entre 1 et 100 (défaut 100). Réponse object: "list", data[] (chaque élément portant operation_id, type, status, resource_id, submitted_version_id, error_code, error, retryable, retry_after_seconds), has_more, complete, error (au niveau job). Utiliser has_more et le dernier operation_id pour paginer avec after. Les curseurs de pagination ne sont disponibles qu'une fois complete: true ; tant que le job tourne, l'endpoint peut renvoyer un instantané incomplet des résultats déjà collectés. submitted_version_id est null pour les créations de campagne et de groupe d'annonces.

Statut d'opérationSignification
createdCréation réussie.
updatedMise à jour réussie.
validatedValidation passée, en mode validation seule.
failedErreur ; utiliser les champs de nouvelle tentative.
skippedNon exécutée car une dépendance ou opération antérieure a échoué.

Limites par défaut

LimiteValeur
Opérations par job1 000
Taille du corps de requête16 MiB
Taille sérialisée d'une opération512 KiB
Requêtes de création par compte publicitaire10 requêtes par 10 secondes
Résultats d'opération par page100
Campagnes self-serve par compte publicitaire5 000 campagnes non archivées
Groupes d'annonces self-serve par compte publicitaire5 000 groupes non archivés
Annonces self-serve par compte publicitaire5 000 annonces actives ou en pause

operation_id et idempotency_key (au niveau opération de création) doivent être uniques au sein d'un job, jusqu'à 255 caractères chacune. Si retryable: true, attendre retry_after_seconds (si fourni) avant de resoumettre le même corps dans un nouveau job, en réutilisant les idempotency_key de création d'origine.

Éléments essentiels

Distinctions importantes

Ne pas confondre operation_id (identifiant unique de l'opération dans le job, fourni par l'appelant) et idempotency_key (identifiant de création, réutilisé pour les références internes au job et les nouvelles tentatives).

Ne pas confondre max_bid_micros (enchère au clic) et max_cpm_bid_micros (enchère à l'impression, accès de compte spécifique requis) : un groupe d'annonces fournit l'un ou l'autre, jamais les deux, selon l'événement de facturation de la campagne parente.

Cas pratiques

Aucun cas pratique disponible : les identifiants et limites (5 000 campagnes, 1 000 opérations) sont des valeurs documentées par la source, pas des retours d'usage réel.

Erreurs fréquentes

Ne pas tenter de mettre à jour, dans le même job, une ressource créée par une opération précédente du même job : ce n'est pas pris en charge, il faut un job ultérieur.

Ne pas fournir à la fois max_bid_micros et max_cpm_bid_micros sur un même groupe d'annonces.

Ne pas ignorer has_more/complete lors de la lecture des résultats d'opérations : tant que complete n'est pas true, la pagination par curseur n'est pas fiable.

Limites et nuances

Relations

Points à vérifier

Sources