Stripe Issuing 2-second timeout vs a 10-second Sume webhook
Stripe's real-time authorization for agent cards falls back after 2 seconds. Sume's run webhook allows 10 seconds per attempt. Keep decisions fast.

Treat them as two different clocks. Stripe's Issuing for agents asks your webhook to answer an issuing_authorization.request within a 2-second default timeout, after which Stripe falls back to the card's default rules. Sume's run webhook allows 10 seconds per attempt and retries on failure. One is a live yes or no on a purchase, the other is a notification that work finished.
The two timing contracts
| Property | Stripe `issuing_authorization.request` | Sume run webhook |
|---|---|---|
| Purpose | Approve or decline a card purchase as it happens | Tell you a run completed or failed |
| Response budget | 2 seconds by default | 10 seconds per attempt |
| On timeout | Falls back to the card's default rules | Counts as a failed attempt and retries |
| Retries | Not applicable | Up to 10 attempts; backoff min(max(30s x 2^(n-1) with jitter, Retry-After), 1h) |
| What you return | An approve or decline decision | Any 2xx |
| Dedupe key | Authorization id | request_id, equal to the run id |
Design for the shorter clock
For the Stripe path, decide from data already in memory: the card's metadata, running totals you keep as issuing_authorization.created events arrive, and the merchant category on the request. Stripe lists business match, amount confirmation and velocity checks as common patterns. Do not call an agent in this path, and do not start a Sume run inside it. A language-model turn can easily cost more than 2 seconds, and a late answer is the same as no answer.
Stripe's page also lists signals an authorization handler can use, such as a network risk score and address and CVC checks on the request. Reading those from the event costs nothing, so they fit the 2-second budget. Keep anything slower, such as a human review or an agent's reasoning, for after the decision: decline or approve on rules first, then flag the card for review if the pattern looks wrong.
Design for the longer clock
For the Sume path, record the event durably and return 2xx quickly, then process after you respond. The docs say a slow endpoint uses the whole 10-second budget and invites a retry. Verify the HMAC signature, dedupe on request_id, and branch on outcome. Sume does not follow redirects, so a 3xx is a failure, not a delivery.
Where the two meet
An agent that buys things and generates media crosses both. Stripe's page notes settlement can follow an authorization by one to two days, so an authorization total is not the final charge. Sume's receipt carries usage.billable_amount_usd_micros, which counts generation spend only and leaves out the agent's own model turn. Keep both ledgers keyed by your own task id, and reconcile them in a batch job, not in either webhook path.
Sources
More in Developers
- Sume 401 halfway through a batch: stop every worker, do not retry
A 401 on a Sume submit means a missing, malformed or revoked key. The SDK does not retry it, and neither should you. Python sample that keeps job ids.
- AI video client timeout: the Sume job still runs and still bills
A timeout on your HTTP client does not cancel a Sume job. Save the job id, poll the polling_url, and cancel only before generation starts. Python example.
- Sume SDK 402 insufficient credits: it is returned, not thrown
Generated Sume SDK calls resolve with data, error and response. Turn a 402 into SumeInsufficientCreditsError with toSumeApiError and stop retrying.
- Sume SDK idempotencyKey: null sends no key, so POST retries stop
subscribeFormatRun mints a UUID Idempotency-Key by default. Pass null and the create call carries no key, so the SDK will not retry it on a 429 or 5xx.
Written by Sume