Extending schemas with allOf

Question from C-3PO (yes, names and content are changed to protect the innocent):

We are currently using a shared Address schema to document multiple API endpoints. For example, we have one endpoint to update an address, and another one to create an address.

The obvious problem is that all documentation that references the shared Address schema must conform. In other words, it might not be possible to document the address fields as optional for the "update" endpoint, and required for the "create" endpoint. Or is it?

We considered using a separate Address schema dedicated to certain endpoints, but ideally, we would like to keep the shared Address schema (for convenience).

Is there some kind of middle ground between shared schemas and dedicated schemas? I imagine a contextual schema that "shifts" (so to speak) depending on which endpoint is in scope. For example, the schema fields are optional for the "update" endpoint, but they become required for the "create" endpoint.

Great question, C-3PO.

Make two schemas. One schema would be your base schema. The other would reference the base schema and use an allOf to "add" the required properties to it. The allOf is a bit tricky to grok for me sometimes; however, this is the perfect use case for it.

Let me explain.

While allOf can be used to extend objects, it cannot override values. Your particular use case is entirely an extension - adding information on which properties are required without overriding anything.

This uses a simplified address for illustration, but you can imagine something similar with all of the address properties.

  schemas:
    Address:
      type: object
      properties:
        line1:
          type: string
          example: 123 Main Street
        line2:
          type: string
          example: Suite 301
        city:
          type: string
          example: Austin
    AddressRequired:
      allOf:
        - $ref: "#/components/schemas/Address"
        - required:
          - line1
          - city

Then, you can use the schemas as appropriate from the "create" or "update" endpoints.

This GitHub repository holds a minimalist OpenAPI definition. It illustrates extending schemas using allOf.

The following screenshots are from the corresponding demo API docs with two operations: Create address and Update address. Compare their request body schemas - that's allOf in action!

create address

update address

The docs show the correct required fields. What about the mocks?

The Update address operation works with or without fields such as line1 in the following animated screenshot.

patch-address

The Create address operation works with the required fields, but it fails without them as shown in the following animated screenshot.

create-address-try-it

create-address-curl

Now that you've seen how it works, try it with your schemas.

Let me know how it goes. And send my regards to R2.

Latest from our blog

Add OpenAPI tags for next-level API desc...

Tag your OpenAPI endpoints and help your users navigate their own path to success.

Love letter to OpenAPI's info section

How some humble metadata can multiply the impact of your API.

Better examples for better API experienc...

Set API consumers up for success with good and meaningful OpenAPI examples.