skip to content

In an OpenAPI schema, what is the difference between type and format?

level: juniorimportance: must knowfreq 64%

answer

  1. One is the JSON type, one refines it
  2. Only one of the two is always enforced
  3. Open-ended by design; unknown values allowed
  4. Its real payoff is generated code types
  5. Use enum or pattern for real constraints

basics

~20 s

In 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 lines
yaml
components:
  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: 0

go deeper

for a junior

Recall the six JSON types and the common formats — int64, date-time, uuid — and that format refines a type rather than replacing it.

for a middle

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.

for a senior

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.

for a principal

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

context