Amazon Ads Refresh Tokens: 365 Tage Laufzeit seit dem 30. Juli, keine Erinnerung

Inhalt
Vor elf Tagen hat Amazon geändert, wie lange ein Refresh Token für die Advertising API gültig bleibt. Hat eine Integration am 1. August einen Advertiser autorisiert, funktioniert dieses Token am 01.08.2027 nicht mehr – ganz gleich, wie oft es dazwischen zum Einsatz kommt. Es gibt keine E-Mail, keinen Deprecation-Header, keinen Hinweis in der Console. Auffallen wird es allein dem Betreiber, und zwar genau in dem Moment, in dem ein nächtlicher Export leer zurückkommt. Dieser Artikel korrigiert zunächst ein weit verbreitetes falsches Datum und baut anschließend das Einzige, was tatsächlich davor schützt: ein Token-Ledger mit einem Cron-Job.
1. Was sich geändert hat – und das Datum, das alle falsch angeben
Amazon hat die Änderung am 26.05.2026 angekündigt. In Kraft getreten ist sie am 30.07.2026. Refresh Tokens, die an oder nach diesem Datum ausgestellt werden, laufen 365 Tage nach dem Datum ab, an dem der Advertiser seinen Consent erteilt hat – nicht 365 Tage nach der Ausstellung des Tokens und auch nicht 365 Tage nach der letzten Nutzung.
Hartnäckig kursiert ein falsches Datum: der 30. Juni. Es steht in Forenbeiträgen, in Changelogs von Anbietern und in Suchmaschinen-Zusammenfassungen, die auf die Frage, seit wann Amazon Refresh Tokens ablaufen, selbstbewusst „30. Juni“ antworten. Das ist einen vollen Monat daneben. Wer ein Migrationsfenster auf Ende Juni gelegt oder einem Kunden gesagt hat, seine Tokens seien bereits abgedeckt, sollte die eigenen Annahmen prüfen. Der korrekte Stichtag ist der 30.07.2026, und die ersten Massenabläufe fallen damit auf den Zeitraum ab dem 30.07.2027.
- Angekündigt: 26.05.2026.
- In Kraft: 30.07.2026, nicht 30. Juni.
- Laufzeit: 365 Tage ab dem Consent-Datum des Advertisers.
- Wiederherstellung nach Ablauf: ein frischer Consent des Advertisers über einen interaktiven Dialog. Einen stillen Weg zurück gibt es nicht.
- Benachrichtigung durch Amazon: keine.
2. Warum es nichts bringt, das Token zu benutzen
An diesem Punkt stolpern auch erfahrene Teams. In praktisch jedem anderen OAuth-Setup hat ein Refresh Token entweder gar kein Ablaufdatum oder ein gleitendes: Jeder Tausch gegen ein neues Access Token setzt den Idle-Timer zurück, sodass eine stündlich laufende Integration faktisch nie abläuft. Amazons Uhr gleitet nicht mit. Sie ist am Consent-Datum verankert und läuft unabhängig vom Traffic auf null. Eine Pipeline, die ein Jahr lang alle 55 Minuten sauber refresht hat, fällt an Tag 366 genauso aus wie eine, die seit Tag eins brachliegt.
Der Fehlerfall ist deshalb leise und tritt verzögert ein. Das Monitoring sieht bis unmittelbar an die Grenze heran eine gesunde Integration, dann einen Refresh-Call, der kein Access Token mehr zurückgibt – und die Lösung ist weder ein Retry noch ein Redeploy. Jemand beim Advertiser muss sich erneut durch einen Consent-Dialog klicken. An einem Samstag, für einen Kunden in einer anderen Zeitzone, ist das keine Wiederherstellung in fünf Minuten.
Im selben Atemzug erwähnenswert, weil es dieselben Codebasen trifft: Sechs alte Endpunkte des Account Managements sind seit Juli 2026 für neue Nutzung gesperrt und liefern ab Juli 2027 HTTP 404. Die Nachfolger sind seit dem 04.06.2026 allgemein verfügbar. Diese Migration gehört in dasselbe Quartal wie die Consent-Erneuerungen.
3. Ein Token-Ledger auf der eigenen Seite
Amazon meldet nicht, wann ein Token stirbt. Zu speichern ist deshalb die einzige Tatsache, auf die es ankommt – das Consent-Datum –, alles Übrige leitet sich daraus ab. Eine Tabelle pro Environment genügt. Die Spalte mit dem Ablaufdatum ist generiert und kann dadurch nie aus dem Tritt mit dem Consent-Datum geraten.
CREATE TABLE amazon_ads_token_ledger (
advertiser_id text PRIMARY KEY,
account_name text NOT NULL,
region text NOT NULL CHECK (region IN ('na', 'eu', 'fe')),
consent_date date NOT NULL,
token_issued_at timestamptz NOT NULL,
expires_on date GENERATED ALWAYS AS (consent_date + 365) STORED,
last_refresh_ok timestamptz,
owner_email text NOT NULL,
status text NOT NULL DEFAULT 'active'
);
CREATE INDEX ON amazon_ads_token_ledger (expires_on) WHERE status = 'active';
Die Tabelle wird einmalig befüllt, notfalls von Hand. Für jeden Advertiser, der am oder nach dem 30.07.2026 onboardet wurde, kommt das Consent-Datum aus den Onboarding-Unterlagen hinein. Für ältere Tokens ist das Datum trotzdem zu erfassen, mit status = 'legacy': Sobald ein solcher Advertiser aus irgendeinem Grund erneut seinen Consent gibt, gilt für das Ersatz-Token die neue Regel – und dann soll die Zeile bereits stehen.
4. Das Prüfskript und die Crontab-Zeile
Das Skript gibt nichts aus, solange alles in Ordnung ist – Cron bleibt also still. Ab 60 Tagen beginnt es zu mailen, und es beendet sich mit einem Exit-Code ungleich null, sobald wirklich etwas abgelaufen ist, damit ein Wrapper oder das Monitoring darauf alarmieren kann.
#!/usr/bin/env python3
"""Warnt vor Amazon Ads Consents, die sich ihrer 365-Tage-Grenze naehern."""
import sys
from datetime import date
import psycopg
DSN = "postgresql:///ops"
WARN_DAYS = 60
QUERY = """
SELECT advertiser_id, account_name, region, consent_date, expires_on,
expires_on - CURRENT_DATE AS days_left, owner_email
FROM amazon_ads_token_ledger
WHERE status = 'active'
AND expires_on - CURRENT_DATE <= %s
ORDER BY days_left
"""
def main() -> int:
with psycopg.connect(DSN) as conn:
rows = conn.execute(QUERY, (WARN_DAYS,)).fetchall()
if not rows:
return 0
print(f"Amazon Ads re-consent needed, checked {date.today()}:")
for aid, name, region, consent, expires, days, owner in rows:
state = "EXPIRED" if days < 0 else f"{days} days left"
print(f" {aid} {name} [{region}] consent={consent} "
f"expires={expires} {state} owner={owner}")
return 1 if any(r[5] < 0 for r in rows) else 0
if __name__ == "__main__":
sys.exit(main())
# crontab -e (als Service-User ausfuehren, dem die ops-Datenbankrolle gehoert)
MAILTO=ads-ops@example.com
17 6 * * * /usr/bin/python3 /opt/ads/token_ledger_check.py
Die 60 Tage sind nicht willkürlich gewählt. Ein erneuter Consent ist ein menschlicher Prozess: Zuerst ist die richtige Person beim Advertiser zu erreichen, diese muss jemanden mit Freigabebefugnis auftreiben, und diese Kette dauert routinemäßig vier bis sechs Wochen. last_refresh_ok lässt sich zusätzlich aus dem Refresh-Job heraus aktualisieren, damit auch eine völlig andere Störung in derselben Tabelle auftaucht.
5. Fazit
Damit steht ein Ledger, das das Consent-Datum jedes Advertisers festhält und das Ablaufdatum als Consent plus 365 Tage in der Datenbank statt im Anwendungscode ableitet, dazu ein Cron-Job, der zwei Monate vor dem Ausfall zu mailen beginnt. Gesamter Fußabdruck: eine Tabelle, ein Index, vierzig Zeilen Python, ein Crontab-Eintrag. Das ersetzt eine Klasse von Ausfällen, für die es kein Error Budget gibt, weil der Weg zurück ein Telefonat ist und kein Deployment.
Zwei Dinge zum Mitnehmen. Der Stichtag ist der 30.07.2026 und nicht der 30. Juni, was auch immer eine Suchergebnis-Zusammenfassung behauptet; Tokens, die ab diesem Tag ausgestellt werden, laufen also ab dem 30.07.2027 aus. Und die Nutzung verlängert die Laufzeit nicht – deshalb kann eine Integration, die heute vollkommen gesund aussieht, elf Monate vor dem harten Stopp stehen. Amazon dokumentiert das Verhalten unter access tokens in den Amazon Advertising API Guides; diese Seite ist die Quelle der Wahrheit, das eigene Ledger der Wecker, den Amazon nicht mitliefert.
2 Kommentare
Der Hinweis auf das falsche Datum kam gerade rechtzeitig — der 30. Juni stand bei uns bereits in einer Migrationsplanung.
Eine Frage zum Ledger: Wenn die Laufzeit am Datum der Consent-Erteilung hängt und nicht an der Ausstellung des Tokens, wie lässt sich dieses Datum für Autorisierungen ermitteln, die längst bestehen und nirgends protokolliert wurden?
Gar nicht, jedenfalls nicht aus dem Token heraus. Genau das ist der unangenehme Teil der Änderung.
Das Consent-Datum steht nicht im Refresh Token und lässt sich auch nicht daraus ableiten. Wo es beim Autorisieren nicht mitgeschrieben wurde, ist es weg — deshalb schreibt das Ledger es im Moment der Autorisierung mit und nicht später.
Für den Bestand bleiben zwei Wege. Entweder wird ein Ablauf bewusst in Kauf genommen und die Neuautorisierung als Ereignis behandelt, auf das der Betrieb vorbereitet ist statt überrascht zu werden. Oder die betroffenen Advertiser werden vorsorglich einmal neu autorisiert, womit ein bekanntes Startdatum entsteht und der Bestand von da an im Ledger geführt wird. Der zweite Weg kostet einmal Abstimmung und beendet das Raten dauerhaft.