Notion 429/529 retry_after in the body vs Sume retry-after header

Notion now puts additional_data.retry_after in 429/529 bodies. Sume sends a retry-after header on rate_limited. One small helper can read both.

4 min readSume
All posts

Notion's 2026-09-24 changelog says 429 and 529 responses now include additional_data.retry_after in the response body. Sume's 429 rate_limited carries a retry-after header when present. A single helper can read the wait from either place, then retry.

Notion facts are from its changelog, read 2026-10-01. Sume facts are from Errors and credits and Generation admission.

Where does each API put the wait time?

Different places, so a header-only retry layer will miss Notion's value and a body-only one will miss Sume's.

Retry-wait location by API, read 2026-10-01.
APIStatusWhere the wait is
Notion429, 529additional_data.retry_after in the body
Sume429 rate_limitedretry-after header, when present
Sume429 queue_fullNo wait value; wait for jobs to finish or cancel queued ones

What does one retry helper look like?

Read the header first, fall back to the body, and cap the number of attempts. This sketch assumes the value is a number of seconds, so check the unit in each API's reference before relying on it.

async function waitFor(res) {
  const header = res.headers.get("retry-after");
  if (header) return Number(header);
  const body = await res.clone().json().catch(() => null);
  const fromBody = body && body.additional_data && body.additional_data.retry_after;
  return fromBody ? Number(fromBody) : 1;
}

export async function send(url, init, tries = 4) {
  for (let i = 0; i < tries; i++) {
    const res = await fetch(url, init);
    if (res.status !== 429 && res.status !== 529) return res;
    const seconds = await waitFor(res);
    await new Promise((r) => setTimeout(r, seconds * 1000));
  }
  throw new Error("still rate limited");
}

Is it safe to retry a paid Sume submit?

Yes, if the same Idempotency-Key goes on every attempt. The docs say not to retry unsafe submit requests without one, and a 409 idempotency_conflict means a key was reused for a different payload. See axios retry with an idempotency key for the pattern.

Why is queue_full different?

The docs state that queue_full is different from ordinary request rate limiting: Sume cannot accept another paid generation job for the workspace until an existing queued or processing job finishes or is canceled. Backing off on a timer alone may not clear it, so read the error.code before choosing a retry policy. Compare 429 vs 503.

Sources

Related posts

More in Developers

All Developers posts

Written by Sume