OpenAI text.format json_schema to a Sume Format response_format

Move an OpenAI Responses API text.format schema onto a Sume Format run: nest it under response_format.json_schema, or lift it into output_schema.

5 min readSume
All posts

If your code builds an OpenAI Responses API body with text.format, Sume will not accept that shape on a Format run. Either lift name, strict and schema into Sume's output_schema, or re-nest them as response_format: { type: "json_schema", json_schema: { ... } }.

OpenAI's page, Structured model outputs, read on 2026-10-02, shows the Responses form as text: { format: { type: "json_schema", "strict": true, "schema": ... } }. Sume's side is from Structured output.

What exactly differs between the two spellings?

Sume's alias mirrors the Chat Completions style: type at the top, the binding nested under json_schema. The Responses API flattens the same fields into text.format. That flattened shape is not accepted on a Format run.

Read 2026-10-02 from docs.sume.com
SpellingWhere the fields sitAccepted by Sume
output_schemaname, strict, schema at the top of the objectYes, native
response_formattype plus json_schema holding name, strict, schemaYes, normalized to output_schema
text.format (Responses)type, name, strict, schema flattenedNo

How do I convert a Responses body?

Take the object under text.format, drop its type, and place the rest under output_schema. This is the shortest path and the one the receipt echoes back, because response_format is normalized into output_schema on the receipt anyway.

{
  "instruction": "Make one hero image for the linked product.",
  "output_schema": {
    "name": "acme/promo-hero/v1",
    "strict": true,
    "schema": {
      "type": "object",
      "additionalProperties": false,
      "required": ["headline"],
      "properties": { "headline": { "type": "string" } }
    }
  }
}

Can I send both?

No. Sending output_schema and response_format together is 400 invalid_request. Pick one per request. Nothing runs and nothing is charged on a 400 at submit.

What else behaves differently from OpenAI?

The subset rules come from the same strict-mode guidance, but where they apply is different. With OpenAI you constrain what the model says. On a Sume Format run the schema constrains how a finished run is read back, so it cannot make a Format produce a video it does not make.

There is also no equivalent of OpenAI's JSON mode (json_object), and strict: false is accepted but changes nothing: a schema outside the subset is rejected either way with 400 output_schema_invalid and a details.violations[] list. Streamed partial JSON does not exist here, because output appears once on the terminal receipt.

What can still go wrong after a clean 202?

The run can finish and still return output: null with an output_error such as output_schema_unsatisfied, for example when a required media field names a file the Format never made. On an API run that is a failure, not a draft. Check output_error before reading output, and fall back to artifacts[] to show the media anyway.

A quick migration checklist

Every problem is reported in one 400 with a stable lowercase rule token such as required_completeness or unsupported_keyword, so you can fix the whole schema in one pass.

  • Rename the container: text.format becomes output_schema, with type dropped.
  • Keep name (1 to 64 characters of letters, digits, ., _, /, -) and namespace it, since it lands on every receipt.
  • Replace oneOf with anyOf, flatten allOf, and write nullable: true as a type union with null.
  • Add additionalProperties: false to every object and list every property in required.
  • Use only #/$defs/* and SumeMediaFile# for $ref; root recursion with $ref: "#" is rejected.

Why not accept text.format directly?

Sume documents one native spelling and one alias. The alias mirrors Chat Completions, so a client that builds Chat bodies works unchanged, and the receipt normalizes it to output_schema. A Responses-style body needs a small change, and the docs say to lift the fields or re-nest them, not to send text.format.

Unknown top-level fields are rejected with 400 unknown_parameter, with a suggestion when the name is close, so a stray text key surfaces at submit rather than being ignored.

What happens to refusals and truncation?

OpenAI's refusal has no equivalent. The Sume counterpart is output_error on the receipt, which is a failed projection and not a safety refusal. There is no truncated-JSON case either: the projection is small and bounded, and output appears once on the terminal receipt.

If you used partial-JSON streaming to render progress, switch to the phase timeline at events_url or take the terminal webhook. There is no push channel for progress.

Sources

Related posts

More in Formats

All Formats posts

Written by Sume