MAI Flash 429 and spend limits vs Sume queued jobs and idempotency

OpenRouter's MAI-Voice-2.1-Flash returns 429 on rate limits and has spend limits. Sume accepts jobs into queued status. See an idempotent double submit.

4 min readSume
All posts

Flash on OpenRouter answers 429 when you hit rate limits and enforces per-account spend limits, so a batch client has to back off and retry. Sume also returns 429 (rate_limited on submit volume, queue_full when the queue is full), but below those limits a submit is accepted and sits in queued until a worker is free, and repeating a submit with the same Idempotency-Key returns the original job.

Two failure models

The OpenRouter page for the Flash model lists 429 for rate limits and per-account spend limits. Sume's job envelope returns data.request_id, a status URL and a result URL; queued is a normal accepted state, and concurrency applies when workers move jobs to processing. A full queue returns 429 queue_full, so back off there too.

What happens at the limit (read 2026-10-05)
SituationMAI-Voice-2.1-Flash via OpenRouterSume TTS Router
Rate limit429 response429 rate_limited over the limit; under it, accepted and queued until processed
Spend capAccount spend limits applyAccount balance and credits apply
Retry after a lost responseClient must avoid a duplicateSame Idempotency-Key returns the same job
DeliverySynchronous audio responsePoll status, then read result

Submit twice, pay once

The script submits the same request twice with one key. The second response has data.idempotency_hit set, and both carry the same request id.

for i in 1 2; do
  curl -sS -X POST https://api.sume.com/v1/tts-router/generate \
    -H "Authorization: Bearer $SUME_API_KEY" \
    -H "Content-Type: application/json" \
    -H "Idempotency-Key: demo-double-submit-001" \
    -d '{"model":"sonic-3.6","transcript":"One line, one charge.","avatar_handle":"product_host","language":"en"}' \
    | jq -c '.data | {request_id, idempotency_hit}'
done

Polling rules

Read GET /v1/jobs/:id/status with exponential backoff, then /result when it completes. Never resubmit a paid request that is only queued; the key makes a retry safe but a new key makes a new charge.

Limits

I did not exercise Flash's 429 path. Check the retry headers on the response you receive before you write a back-off policy.

Sources

Related posts

More in Developers

All Developers posts

Written by Sume