In an OpenAPI schema, what is the difference between type and format?
answer
- One is the JSON type, one refines it
- Only one of the two is always enforced
- Open-ended by design; unknown values allowed
- Its real payoff is generated code types
- Use enum or pattern for real constraints
basics
~20 sIn an OpenAPI schema, type is the JSON data type — string, number, integer, boolean, array, object — and is enforced by validators. format is an open-ended hint refining that type, such as int64 or date-time; validators may ignore unknown formats, but code generators use them for type mapping.
solid answer
~40 s`type` picks one of the JSON types the value must be: `string`, `number`, `integer`, `boolean`, `array`, `object` (and `null` in OpenAPI 3.1). Validators enforce it strictly. `format` is a free-form string that further describes the *same* value: the specification defines `int32`, `int64`, `float`, `double`, `byte`, `binary`, `date`, `date-time` and `password`, and anything else — `uuid`, `email`, `uri` — is legal too, because format is deliberately open. Tooling treats it as an annotation: a validator is not obliged to check an unrecognised format, so `format: uuid` may not reject a non-UUID string, while a code generator will happily map it to a UUID type in the target language. Use `type` for what must be true and `enum` or explicit constraints such as `pattern`, `minimum` and `maxLength` when you need the rule enforced.
code
yaml · 21 linescomponents:
schemas:
Order:
type: object
properties:
id:
type: integer
format: int64
reference:
type: string
format: uuid
placedAt:
type: string
format: date-time
status:
type: string
enum: [ACTIVE, PAUSED, CLOSED]
total:
type: number
format: double
minimum: 0go deeper
Recall the six JSON types and the common formats — int64, date-time, uuid — and that format refines a type rather than replacing it.
Explain that type is an assertion and format is largely an annotation, and show how format drives generated language types while enum and pattern do the enforcing.
Demonstrate the boundary discipline: never rely on format alone for validation that protects the system, and know that 3.1 replaced format: binary with contentMediaType.
Own the house rules — which custom formats are sanctioned, whether generators across all languages support them, and where enforcement actually lives if not in the schema layer.
## Two keywords, two jobs Every Schema Object in an OpenAPI document describes the shape of a value. `type` says what kind of JSON value it is; `format` adds a finer-grained label that mostly serves tooling. ## type The allowed values come from JSON Schema: `string`, `number`, `integer`, `boolean`, `array`, `object`. OpenAPI 3.0 allows exactly one of them per schema. OpenAPI 3.1, aligned with JSON Schema 2020-12, additionally allows `null` and allows `type` to be an *array* of types. `integer` is worth calling out: it is a distinct type from `number`, not a format of it. `type: number` accepts `4.5`; `type: integer` does not. Validators enforce `type` unconditionally. If the document says `type: integer` and the payload carries `"4"`, validation fails. ## format `format` is a string that refines the type. The OpenAPI specification lists a set of formats it defines: - with `type: integer` — `int32`, `int64` - with `type: number` — `float`, `double` - with `type: string` — `byte` (base64-encoded), `binary` (raw octets), `date` (RFC 3339 full-date), `date-time` (RFC 3339 date-time), `password` (a hint that UIs should mask the input) Crucially the specification states that `format` is an **open** value: you may use any string, and tooling that does not recognise it should simply ignore it. That is why `uuid`, `email`, `uri`, `hostname`, `ipv4` and countless vendor-specific formats appear in real documents and work fine with generators that know them. ## What actually gets enforced This is the point interviewers probe. A validator must enforce `type`. It is not required to enforce an unrecognised `format`, and in JSON Schema 2020-12 — the dialect OpenAPI 3.1 aligns with — `format` is by default an *annotation*, not an assertion. Practically: - `type: string, format: uuid` documents intent and drives codegen, but a request carrying `"not-a-uuid"` may sail through your schema validation layer. - If you need it rejected, add an assertion the validator does enforce: `pattern` for strings, `minimum`/`maximum` for numbers, `minLength`/`maxLength`, or `enum` for a closed set of values. Some validation libraries do offer opt-in format assertion, but you cannot assume it across a toolchain, so a spec that relies on `format` alone for security-relevant validation is fragile. ## What format buys you **Code generation.** This is the main payoff. `integer` + `format: int64` becomes a 64-bit type rather than a 32-bit one — a real correctness issue for identifiers and timestamps. `string` + `format: date-time` becomes a date-time type instead of a bare string. `string` + `format: byte` becomes a byte array. **Documentation and UI.** Renderers show the format next to the type, and `format: password` tells form-generating tools to mask the field. ## The 3.1 change for binary payloads In OpenAPI 3.0, a file upload or download was `type: string, format: binary` (or `format: byte` for base64). OpenAPI 3.1, following JSON Schema 2020-12, expresses this with `contentMediaType` and `contentEncoding` instead — for example `contentMediaType: application/octet-stream`, or `contentEncoding: base64`. `format: binary` is not part of the 3.1 vocabulary. If you migrate a document that describes uploads, this is one of the changes you must make by hand. ## Where enum fits When the value space is a fixed, known list — a status, a currency, a country code you control — `enum` is the right tool, and unlike `format` it is a genuine assertion every validator enforces. `enum` also generates a proper enum type in most target languages. Reach for `format` to describe a *kind* of value and `enum` to fix the exact set. ## A short checklist - Need it rejected at the boundary? Use `type`, `enum`, `pattern`, and the numeric/length constraints. - Need generated code to use the right language type? Set `format`. - Using a non-standard format? Confirm your generator recognises it, or it silently degrades to a plain string.
- If format: uuid is not reliably enforced, why write it?Because it drives code generation and documentation: generators map it to a UUID type in the target language and renderers show it to consumers. Pair it with a `pattern` when the value must actually be rejected at the boundary — the two roles are complementary, not interchangeable.
- Is integer a type or a format of number in OpenAPI?A distinct `type`. `type: integer` rejects `4.5`, while `type: number` accepts it. `int32` and `int64` are the *formats* that refine `type: integer`, and they matter mainly because they control the width of the generated language type.
- How do you describe a binary file payload in OpenAPI 3.1?With `contentMediaType` and, when the bytes are base64-encoded, `contentEncoding`. OpenAPI 3.0's `type: string, format: binary` is not part of 3.1's JSON Schema 2020-12 vocabulary, so upload and download schemas are one of the things a 3.0-to-3.1 migration must rewrite by hand.
saying these in an interview costs you the question
- Assumes every validator enforces format: uuid
- Calls integer a format of number
- Uses format instead of enum for a fixed value set
- Thinks unknown format values make a document invalid
- Keeps format: binary when moving to OpenAPI 3.1