Is there a Sume API test mode? No sandbox key, but two hosts
Sume has no sume_test key. Use the dev host with its own key, cap each run with generation_spend_cap_usd, and mock the rest. What each option costs and covers.

No. The Sume API has no test mode and no sandbox key prefix: every key looks like sume_live_..., and a paid submit on the production host spends real credits from the workspace that owns the key. What you get instead is a second host, a per-run spend ceiling, and an OpenAPI file you can point a mock at, and together those cover most of what a test mode would.
This post lists what each option really covers, so you can decide which layer of your test suite talks to Sume and which layer never leaves your laptop.
The two hosts and what a key is bound to
The Overview and the Format docs describe two hosts with one contract. https://api.sume.com is production. https://api.dev.sume.com is for integration and staging, with the same routes, the same receipts and the same webhook delivery. A key works only on the host it was created for; the other host answers 401 unauthorized.
Both kinds of key start with sume_live_, so you cannot tell a development key from a production key by looking at it. Name your environment variables by host, for example SUME_API_KEY_DEV and SUME_API_KEY_PROD, and keep the base URL in the same config object as the key. Development keys are issued by Sume for a development workspace; the docs say to ask your Sume contact rather than creating them in the production dashboard.
| Layer | Talks to Sume? | What it proves |
|---|---|---|
| Unit tests of retry and poll logic | No, inject fetch or a fake clock | Your code obeys retry_after and next_poll_after_seconds |
| Contract tests against the reference JSON | No, a mock server from the OpenAPI file | Your client sends valid bodies and parses the envelope |
| Integration run on the dev host | Yes, dev key | Real queueing, real webhook delivery, real receipts |
| Production smoke test | Yes, live key, tiny capped run | Your production key and webhook URL work end to end |
Cap every run you let a test submit
The recipes page and the Format pages keep returning to one control you own: generation_spend_cap_usd. The Format run docs say a run that tries to spend more than its cap fails with format_run_failed, and that a request value above the Format's own cap is accepted and not clamped, so the number you send is the number that applies. The best-practices page puts it bluntly: a missing cap is a bug in the client.
For a test, pick a cap just above the cheapest output you expect. A CI job that accidentally loops then fails on the cap instead of draining a balance. Pair it with the dashboard usage page so someone looks at the ledger after the first week of a new test suite.
Mock what you can, and keep the mock honest
The reference JSON is published at https://api.sume.com/reference/json, and Prism against that file gives you a free server that returns schema-valid bodies. A mock answers fast and never queues, so it cannot reveal a bug in a poll loop that depends on next_poll_after_seconds. For that, write a fake server that walks a job through queued, processing and completed.
Keep the mock honest by saving one real error envelope for each code you handle (insufficient_credits, queue_full, rate_limited, idempotency_conflict) from the dev host and replaying those bodies in tests. A hand-written error body drifts; a recorded one does not.
A short test-plan checklist
Use this order when you add Sume to a new stack, cheapest and fastest layers first.
- Write unit tests for retries and polling with an injected clock and a fake transport.
- Generate types from the reference JSON and let the compiler catch request shape errors.
- Run one integration test on the dev host per workflow you ship, always with a spend cap.
- Keep the live key out of CI except for a single scheduled smoke test with a tiny cap.
- Review the usage ledger after the first runs to confirm what each test really cost.
Sources
Related posts
More in Developers
- sume/auto hides which image model ran: pin an id for brand assets
model sume/auto never discloses the family, and job.model stays sume/auto. Why a brand asset set needs a pinned image model id, and how to pin one on Sume.
- Sume GET /v1/balance expiration fields: warn before credits lapse
GET /v1/balance reports when your next credit lot expires and how much expires soon. Read the fields, convert micros to dollars, and alert from a cron job.
- sume models list is a deprecated alias: use sume catalog list
The Sume CLI keeps sume models list as a deprecated alias of sume catalog list. What the catalog command shows, what it cannot do, and how to migrate scripts.
- Sume public_reason: generation_rejected vs temporary error
How Sume picks generation_rejected, temporary_generation_error or generation_failed on a failed job from the provider HTTP status and the retryable flag.
Written by Sume