Kubb for the Sume OpenAPI spec: Zod schemas and SWR hooks
Kubb parses an OpenAPI spec once and feeds plugins for TypeScript, Zod and SWR. Here is how that maps to Sume's 3.0.3 spec, jobs and the polling stop rule.

The answer
Kubb's home page describes an adapter that parses an API spec into a shared AST, and plugins that consume it: TypeScript, Axios, Fetch, React Query, Vue Query, SWR, Zod, Faker, MSW and MCP among them. Run it with npx kubb generate. For Sume, feed it the OpenAPI document and enable the TypeScript, Zod and SWR plugins to get types, runtime validators and polling hooks from one source.
The value of the Zod plugin is that a status payload is checked at the boundary, not only typed. The value of the SWR plugin is a hook per operation that you can combine with a function-valued refreshInterval.
Which plugin does what
Kubb lists these as separate plugins on the same page, so you can adopt them one at a time. Starting with types alone is a safe first step.
| Plugin | Output | Sume use |
|---|---|---|
| TypeScript | Types from the spec | Job, status and error shapes |
| Zod | Zod schemas | Validate status and result bodies |
| SWR | SWR hooks | Poll a job until terminal |
| MSW | Request handlers | Mock Sume in front-end tests |
| Faker | Fake data | Seed fixtures from the schemas |
Using the generated pieces for a job
A Sume submit returns status_url, result_url, terminal and result_ready fields. With the Zod schema in front of the status call, a malformed or changed payload fails loudly at the edge instead of producing an undefined deep in the UI.
In the SWR hook, return 0 from the interval function when terminal is true and the suggested next_poll_after_seconds times 1000 otherwise. Our SWR polling post shows the interval rule in detail.
Spec caveats
Sume's OpenAPI is 3.0.3, with fields marked nullable: true rather than 3.1 type unions. Check that your generated Zod schema uses .nullable() for next_poll_after_seconds and retry_after_seconds. If it emits a plain number you will get a parse failure on exactly the terminal responses you care about most.
Creates also take an Idempotency-Key header parameter. Generated clients usually expose header parameters as an options argument; set it from your business intent, not from a random value per call.
Keep generation reproducible
Commit the spec file you generated from, record the date you fetched it, and rerun Kubb in CI to detect drift. That turns an API change into a reviewable diff of generated files rather than a production surprise.
A practical rollout order
Start with the TypeScript plugin alone and compile your app against it. Add Zod next, and use it only on the two responses that drive control flow: the create response and the status response. Add SWR last, once the schemas are stable, so the hook's data type is already the validated one.
Resist generating everything for all 183 operations if you call five of them. A smaller generated tree, which you can get by trimming the spec to the operations you use, is quicker to review and to rebuild when the spec moves.
For tests, the MSW and Faker plugins listed on the same page let you serve fake job statuses in a browser or Node test. Script three responses in a row, non-terminal twice and then terminal with result_ready true, and assert that the hook stops polling after the third.
Sources
Related posts
More in Developers
- LangChain4j StreamableHttpMcpTransport: protocol detection for Sume
LangChain4j probes the MCP protocol on connect, which costs one round trip. Pin protocolVersion and set timeouts before pointing it at Sume's hosted MCP server.
- last_frame without first_frame returns 400: kling-3 and Seedance fix
A frame_images list with only a last_frame is rejected with 400 unsupported_capability. Send a first_frame too; Kling 3.0 uses start and end frames only.
- Latin American Spanish text to speech: es or es-MX on Sume?
Sume's TTS language is a free string and its voice library tags voices with plain es. What that means for Mexican, Argentine or Spain Spanish, and how to test.
- FLUX 3 style boxes for Sume: draw a layout reference sheet in Python
Sume has no bounding-box input. Draw numbered boxes on a blank sheet from a 0-1000 grid, pass it as a reference, and name each box in the prompt.
Written by Sume