Ein Schlüssel gilt für genau ein Werbekonto, und damit braucht kein Aufruf eine Kontoangabe
Eine Kampagne für ChatGPT Ads entsteht entweder durch Klicken im Anzeigenmanager oder durch Aufrufe an die Werbe-API. Eine Schnittstelle ist der Weg, auf dem ein Programm dieselben Dinge anlegt, die sonst ein Mensch in der Oberfläche zusammenklickt, und sie hat gegenüber dem Klicken einen Vorteil: der Weg steht danach als Datei da und lässt sich ein zweites Mal genauso gehen.
Für diese Schnittstelle gibt es keine fertige Programmbibliothek von OpenAI. Was es gibt, beschreibt die Übersicht der Werbe-API: zehn Gruppen von Endpunkten unter https://api.ads.openai.com/v1. Ein Endpunkt ist eine einzelne Adresse, die genau einen Aufruf entgegennimmt, und die zehn Gruppen heißen dort Werbekonto, Kampagnen, Anzeigengruppen, Anzeigen, Auswertungen, Dateien, Zielgruppen, Sammelaufträge, Produktdatenfeeds und Konversionen. Angesprochen wird jeder von ihnen mit einer Kopfzeile Authorization: Bearer und einem Schlüssel, den man im Anzeigenmanager unter Einstellungen ausstellt. Der Satz, an dem alles Weitere hängt, steht dort in einer Zeile: "Each key is scoped to one ad account."
Ein Schlüssel gehört also zu genau einem Werbekonto. Kein Aufruf braucht deshalb einen Parameter, der sagt, um welches Konto es geht: welches gemeint ist, entscheidet allein der Schlüssel. Umgekehrt heißt es, dass der Schlüssel dieselbe Sorgfalt braucht wie ein Passwort für das Konto selbst.
Die Grenzen für die Aufrufe nennt dieselbe Seite: 600 Anfragen pro Minute je Endpunkt und 1.200 pro Minute insgesamt, gezählt sowohl je Werbekonto als auch je IP-Adresse. Für Sammelaufträge gilt eine eigene Grenze von zehn Anfragen in zehn Sekunden je Werbekonto.
Der Idempotency-Key steht an zehn von 54 POST-Endpunkten, und das Anlegen einer Ereignisdefinition gehört nicht dazu
Idempotent heißt, dass derselbe Aufruf zweimal geschickt denselben Zustand hinterlässt wie einmal geschickt. Der Idempotency-Key ist das Kopfzeilenfeld, mit dem der Aufrufer selbst eine Kennung vergibt, an der der Server einen Wiederholungsversuch wiedererkennen soll. Genau das ist bei uns nicht passiert: beim Einrichten der Messung sind aus einem zweiten Aufruf zwei Ereignisdefinitionen desselben Typs geworden, wo eine gemeint war. Was das für die Messung bedeutet, steht in Conversion-Tracking für ChatGPT Ads einrichten; hier geht es um die Mechanik dahinter.
Die Mechanik lässt sich nachzählen. OpenAI veröffentlicht die Schnittstelle als OpenAPI-Beschreibung, also als maschinenlesbare Liste aller Pfade mit ihren Feldern und Kopfzeilen. In der Fassung 2.3.0, geladen am 04.09.2026, stehen 70 Pfade. 54 Endpunkte darin nehmen ein POST entgegen, also den Aufruf, mit dem etwas angelegt wird, dazu kommt je einer zum Ändern und zum Löschen; zusammen sind das alle Aufrufe, die etwas verändern. Der Idempotency-Key ist an zehn dieser 54 aufgeführt und an keinem der übrigen 44, am Ändern und am Löschen auch nicht.
An dreien ist er freiwillig: beim Anlegen einer Kampagne, einer Anzeigengruppe und einer Anzeige. An sieben ist er Pflicht, und alle sieben gehören zu Vorgängen, bei denen eine Wiederholung teuer wäre: das Hinzufügen, Entfernen, Ersetzen und Zusammenführen von Zielgruppenlisten, eine Testeinsendung an ein Lead-Formular, das Anlegen einer Kontoerstellungssitzung und das Abonnieren der Lead-Übergabe.
Der Endpunkt, an dem uns das zweite Objekt entstanden ist, heißt POST /conversions/event_settings und ist in dieser Liste nicht enthalten. Wir hatten den Kopf trotzdem mitgeschickt, weil er in der Doku steht, und dabei übersehen, dass er dort an anderen Endpunkten steht als an diesem.
Das Versprechen im Schlüssel gilt einem Wiederholungsversuch und setzt voraus, dass der erste Aufruf schon sichtbar ist
An acht der zehn Stellen, an denen der Kopf aufgeführt ist, steht dieselbe Beschreibung. An den beiden übrigen, dem Anlegen einer Kontoerstellungssitzung und dem Abonnieren der Lead-Übergabe, kommt ein Satz dazu, wonach derselbe Schlüssel mit einem anderen Anfragekörper abgelehnt wird. Die acht lauten:
Unique key for retrying this create request. If a matching prior create is visible, the existing object is returned instead of creating a duplicate. Must contain at least one non-whitespace character and be at most 255 characters.
In diesem Wortlaut stecken zwei Einschränkungen. Die erste ist der Zweck: der Schlüssel ist für den Wiederholungsversuch eines Anlegevorgangs gedacht, also für den Fall, dass die erste Antwort unterwegs verloren ging. Die zweite ist die Bedingung "if a matching prior create is visible". Der Schutz greift, wenn der erste Aufruf zum Zeitpunkt des zweiten schon sichtbar ist.
Sichtbarkeit ist bei dieser Schnittstelle keine Selbstverständlichkeit. Am 02.09.2026 haben wir vier Ereignisdefinitionen angelegt und unmittelbar danach die Liste abgerufen: sie zeigte zwei. Eine Minute später zeigte sie vier. Zwischen dem Anlegen und dem Auftauchen in der Liste liegt also eine Spanne, in der ein Objekt existiert, ohne dass ein Lesevorgang es findet. Wie lang sie ist, sagt diese Messung nicht, sie grenzt sie nach oben auf eine Minute ein.
Der Abstand zwischen den beiden Aufrufen ist dabei nicht festgehalten worden. Für das doppelte Objekt bleiben damit zwei Erklärungen, die sich am Ergebnis nicht unterscheiden lassen, nämlich der am Endpunkt fehlende Kopf und eine erste Anlage, die beim zweiten Aufruf noch nicht sichtbar war.
Wer nicht doppelt anlegen will, liest vor jedem Schreiben nach, was unter dem Namen schon im Konto steht
Daraus folgt eine Bauregel für jedes Skript, das hier etwas anlegt: die Idempotenz stellt es selbst her. Vor jedem Schreiben ruft es die passende Liste ab und sucht darin, was es anlegen wollte. Findet es etwas, meldet es den vorhandenen Stand und legt nichts an.
Wonach gesucht wird, ist dabei nicht überall dasselbe. Bei Kampagne, Anzeigengruppe und Anzeige ist der Name das Merkmal, denn zwei Kampagnen desselben Namens sind der Fehler, den man verhindern will. Bei den Ereignisdefinitionen taugt der Name nicht, denn die Doppelung, die weh tut, sind zwei Definitionen desselben Ereignistyps, und die können unter zwei verschiedenen Namen stehen. Verglichen wird deshalb der Ereignistyp und, wenn es ein selbst benanntes Ereignis ist, zusätzlich dessen Name.
Die zweite Falle in diesem Nachlesen ist die erste Seite. Die Listen kommen seitenweise zurück, und jede Antwort sagt dazu, ob noch eine Seite folgt und wo sie ansetzt. Wer nur die erste Seite liest und dort nichts findet, legt an, was auf Seite zwei längst steht. Verlässlich ist die Suche erst, wenn sie alle Seiten geholt hat.
Nach dem Anlegen kommt der dritte Schritt, und der ist wegen derselben Verzögerung kein Nebensatz. Eine Erfolgsmeldung bestätigt, dass der Aufruf angenommen wurde. Ob der Zustand im Konto dem entspricht, was man wollte, sagt erst ein zweiter Lesevorgang, und der findet den vollständigen Stand erst nach einer Wartezeit: in unserem Fall stand er eine Minute nach dem Anlegen in der Liste.
Die Standortsuche findet nur den kanonischen Namen, und beim Land ist das der englische
Eine Kampagne trägt ihr geografisches Ziel als Liste von Kennungen, und eine Kennung ist hier eine Zahl, die für genau ein Gebiet steht. Diese Zahlen holt man sich über eine eigene Standortsuche, der man einen Suchbegriff gibt. Die Seite zum Standort-Targeting beschreibt, was in der Antwort steht, darunter der kanonische Name eines Eintrags, also sein ausgeschriebener Name samt der Gebiete, in denen er liegt, und zeigt als Beispiel eine Suche nach "San Francisco". Welche Sprache der Suchbegriff haben muss, sagt sie nicht.
Wir haben das am 04.09.2026 selbst abgefragt, mit je zwei Schreibweisen für die drei deutschsprachigen Länder. Die englischen Namen liefern alle drei Länder: Germany trägt die Kennung 1000056, Austria die 1000011, Switzerland die 1000042. Bei jedem der drei steht der Landeseintrag an erster Stelle, dahinter die Regionen desselben Landes.
Die deutschen Schreibweisen liefern etwas anderes. "Deutschland" bringt zwei Treffer, und beide sind Postleitzahlen: 8523 und 8530 in Deutschlandsberg, mit dem Ländercode AT. "Schweiz" bringt null Treffer. "Oesterreich" in der Umschreibung ohne Umlaut bringt ebenfalls null. "Österreich" mit Umlaut bringt zwei Treffer, und beide sind Regionen, nämlich Oberösterreich und Niederösterreich; das Land selbst ist nicht darunter.
Wer im Skript "Deutschland" stehen hat und die erste zurückgegebene Kennung übernimmt, trägt damit die 10002074 in seine Kampagne ein. Die gehört zur Postleitzahl 8523 in Deutschlandsberg, und der Ländercode dazu lautet AT.
Eine Suche ohne Treffer kommt als leere Liste zurück und sieht aus wie eine Suche, bei der es nichts zu finden gab
Keiner dieser Fälle kommt als Fehler zurück. Die Antwort auf "Schweiz" besteht am 04.09.2026 aus dem wiederholten Suchbegriff, der Trefferzahl null und einer leeren Ergebnisliste, und die Schnittstelle meldet dazu Erfolg. Ein Hinweis darauf, dass die Schreibweise das Problem war, steht nirgends, und genauso sähe die Antwort aus, wenn es das gesuchte Gebiet im Verzeichnis wirklich nicht gäbe.
Der gefährlichere Fall ist der mit Treffern. "Deutschland" antwortet mit zwei Zeilen, und eine Prüfung, die nur zählt, ob überhaupt etwas zurückkam, hält das für einen Erfolg. Erst die Angaben in der Zeile widersprechen: als Art des Eintrags steht dort eine Postleitzahl, als Ländercode AT, und der kanonische Name liest sich als "8523, Deutschlandsberg, Austria".
Wer nachschlägt, liest deshalb zu jedem Treffer diese drei Angaben mit, statt nur die Kennung zu übernehmen. Eine Kennung allein ist eine Zahl, der man nicht ansieht, welches Gebiet dahintersteht, und in der Kampagne steht später ebenfalls nur diese Zahl.
Nach der Region sucht man unter einem anderen Namen als nach dem Land
Aus den bisherigen Zahlen ließe sich die Regel ableiten, im Zweifel alles auf Englisch zu suchen. Für Regionen stimmt sie nicht. Die Suche nach "Bayern" liefert genau einen Treffer, nämlich die deutsche Region mit der Kennung 2000347. Die Suche nach "Bavaria" liefert ebenfalls genau einen Treffer, und das ist die Postleitzahl 31040 in einem italienischen Ort namens Bavaria.
Dasselbe Bild zeigen die Regionen, die bei einer Landessuche mitkommen. Wir haben die Antwort auf zehn Zeilen begrenzt, hinter dem Landeseintrag standen also je neun Regionen und womöglich weitere dahinter. Unter Germany standen am 04.09.2026 Bayern, Berlin, Bremen, Hessen, Hamburg, Sachsen, Saarland, Thüringen und Brandenburg. Unter Austria standen Wien, Tirol, Kärnten, Salzburg, Burgenland, Steiermark, Vorarlberg, Oberösterreich und Niederösterreich. Unter Switzerland standen Uri, Zug, Jura, Vaud, Berne, Aargau, Genève, Glarus und Luzern, also weder durchgängig deutsche noch durchgängig englische Formen.
Was in diesem Verzeichnis zählt, ist der kanonische Name des Eintrags, und der folgt keiner Sprachregel, die man vorher wüsste. Die verlässliche Reihenfolge ist deshalb: suchen, den kanonischen Namen samt Ländercode lesen, und erst dann die Kennung in die Kampagne übernehmen.
Ein zweiter Lauf legt ein zweites Objekt an, und den Konversionsschlüssel zeigt OpenAI genau einmal
Die dritte Falle liegt darin, wie wenig sich hier zurücknehmen lässt. Wenn der Idempotency-Key an diesem Endpunkt nicht greift, ist ein versehentlich zweimal gestarteter Anlegevorgang genau der Vorgang, der ein zweites Objekt erzeugt, und für die Ereignisdefinition gibt es danach keinen Weg zurück.
Dazu kommt der Schlüssel für den serverseitigen Messweg, also für den Weg, auf dem ein Shopsystem seine Abschlüsse ohne den Browser an OpenAI meldet. Den zeigt OpenAI genau einmal, nämlich in der Antwort auf das Anlegen; wer ihn in diesem Moment nicht festhält, bekommt ihn über die Schnittstelle nicht wieder.
Eine Kampagne lässt sich pausiert anlegen, und das wirkt in zwei Richtungen zugleich: die Anzeigenprüfung läuft an, während die Kampagne noch nichts ausliefert, und der Anzeigentext lässt sich vor der ersten Einblendung lesen und freigeben. Solange die Kontoprüfung läuft, liefert ohnehin nichts aus, wie in Dein Konto wird vorbereitet beschrieben. Was aus diesem Konto nach der Freigabe geworden ist, steht im Bericht über den ersten Lauf.
Die Ereignisdefinition kennt in der Schnittstellenbeschreibung weder ein Archivieren noch ein Löschen
Wie endgültig ein Fehlgriff ist, hängt am Objekt. Für Kampagne, Anzeigengruppe und Anzeige führt die Beschreibung je einen eigenen Pfad zum Pausieren, zum Aktivieren und zum Archivieren, und eine falsch angelegte Kampagne lässt sich über die Schnittstelle selbst wieder anhalten.
Für die Ereignisdefinition sieht es anders aus. Der Endpunkt der Ereignisdefinition kennt in der Fassung 2.3.0 genau zwei Aufrufe: anlegen und auflisten. Einen Weg zum Archivieren oder Löschen gibt es nicht, und die Referenz zur Konversionseinrichtung beschreibt für diesen Endpunkt entsprechend nur das Anlegen und das Auflisten. Wer hier ein Objekt zu viel anlegt, bekommt es über diese Schnittstelle nicht mehr weg. Am 04.09.2026 standen in der Liste des Kontos vier Definitionen, keine doppelt und keine als archiviert gekennzeichnet; die beiden, die uns am 02.09.2026 doppelt entstanden waren, sind darin nicht mehr enthalten, und über welchen Weg sie verschwunden sind, sagt die Schnittstelle nicht.
Der Endpunkt für die Schlüssel daneben ist noch knapper: er kennt allein das Anlegen. Es gibt also keinen Weg, sich anzeigen zu lassen, welche Schlüssel für den serverseitigen Messweg in einem Konto existieren. Ob einer angelegt wurde, weiß nur, wer es sich beim Anlegen notiert hat.
Dieselbe Referenz nennt die Pflichtangaben für eine Ereignisdefinition: ein Anzeigename, ein Ereignistyp aus der Standardliste oder ein selbst benannter, ein Attributionsfenster und genau eine Quelle. Das Attributionsfenster ist die Zahl der Tage, die ein Abschluss nach dem Klick diesem Klick noch zugerechnet wird; die Referenz gibt dazu die Anweisung "Use 30" und sonst nichts. Zur Quelle steht dort "Exactly one conversion source ID returned by pixel creation".
Das Bild geht über einen eigenen Aufruf in die Anzeige, und Titel und Text sind auf 50 und 100 Zeichen begrenzt
Die Anzeige selbst ist der Ort mit den meisten harten Grenzen, und die stehen alle in der Beschreibung. Das Anzeigenformat für den Chat heißt chat_card. Der Titel darin ist Pflicht und fasst 3 bis 50 Zeichen, der Fließtext ist Pflicht und fasst bis zu 100 Zeichen, die Zieladresse bis zu 2.048.
Das Bild betritt die Anzeige als Datei-Kennung, die dort unter file_id steht. Sie entsteht in einem eigenen Aufruf: ein Hochladeendpunkt nimmt die Bildadresse entgegen und antwortet mit der Kennung. Wer das Bild später austauscht, lädt es erneut hoch und trägt die neue Kennung nach.
Eine Änderung an der Anzeige nimmt die Schnittstelle nur als Ganzes an, also als den sichtbaren Teil aus Format, Titel, Text, Zieladresse und Bildkennung zusammen, und die Anzeige geht damit erneut in die Prüfung. Solange sie pausiert ist, kostet das nichts. Wie lange eine Anzeigenprüfung dauert, beziffert die Übersicht mit "Reviews typically take only a few minutes", nachlesbar am Feld review_status.
Die Doku verlangt ein Konversionsereignis nur für die konversionsoptimierte Gebotsart, der Anzeigenmanager mahnte es trotzdem an
Für die Gebotsart kennt die Schnittstelle drei Werte: Einblendungen, Klicks und Abschlüsse. Der dritte ist die konversionsoptimierte Variante: bezahlt wird laut der Doku weiter je gültigem Klick, während die Auslieferung auf Klicks zielt, aus denen eher ein gemeldeter Abschluss wird. Laut der Seite zu konversionsoptimierten Kampagnen nutzt eine solche Kampagne genau eine aktive Standard-Ereignisdefinition, die ihr an der Kampagne zugeordnet wird. Für eine Kampagne, die auf Klicks bietet, verlangt die Doku das nicht.
Am 02.09.2026 stand im Anzeigenmanager trotzdem der Hinweis, dass keine aktive Kampagne Conversion-Ereignisse nutzt. Wir haben das Ereignis daraufhin auch an der Klick-Kampagne zugeordnet, und die Schnittstelle hat die Zuordnung per Update an der bestehenden Kampagne angenommen. Ob der Hinweis danach verschwunden ist, haben wir nicht nachgesehen.
Was in diesem Fall gilt
Für diesen Stand der Schnittstelle, die Fassung 2.3.0 vom 04.09.2026, gilt: der Idempotency-Key ist an zehn von 54 POST-Endpunkten aufgeführt, das Anlegen einer Ereignisdefinition gehört nicht dazu, und dort sind uns am 02.09.2026 aus einem zweiten Aufruf zwei Objekte geworden, die sich über diese Schnittstelle weder archivieren noch löschen lassen. Die Standortsuche hat am 04.09.2026 alle drei deutschsprachigen Länder unter Germany, Austria und Switzerland geliefert, während Schweiz null Treffer brachte und Deutschland zwei Postleitzahlen mit dem Ländercode AT. Regionen tragen dabei einen eigenen Namen, unter dem sie zu suchen sind, und die Übersetzung ins Englische führt bei Bayern zu einem italienischen Ort.
Die Ursache der Doppelanlage lässt sich am Ergebnis nicht festmachen. Der Endpunkt führt den Kopf nicht, und gleichzeitig hinkt die Liste dem Anlegen um bis zu eine Minute hinterher, was auch die Bedingung "if a matching prior create is visible" ausgehebelt hätte. Den Schlüssel für den serverseitigen Messweg zeigt dieselbe Schnittstelle genau einmal, nämlich in der Antwort auf das Anlegen.





