Skip to content
ADP
API Design PrincipleBETA

[ADP-360] Resource Expansion

Guidance

  • SHOULD NOT return standalone subresources by default

    http
    GET /orders/{orderId} HTTP/1.1
    
    {
      "orderId": "12345",
      "customerName": "John Doe",
      "totalPrice": 100.00,
      "orderedAt": "2024-07-05"
    }

    The resource is expected to have items and shippings as standalone subresources (e.g., each resource has its own id)

  • SHOULD support embedding subresources by embed query parameter

    http
    GET /orders/{order-id}?embed=(items)
    
    {
      "orderId": "12345",
      "customerName": "John Doe",
      "totalPrice": 100.00,
      "items": [
        {
          "orderItemId": "1",
          "productId": "987",
          "productName": "Widget",
          "quantity": 2,
          "price": 25.00
        },
        {
          "orderItemId": "2",
          "productId": "654",
          "productName": "Gadget",
          "quantity": 1,
          "price": 50.00
        }
      ],
      "shipping": {
        "shippingId": "56789",
        "carrier": "UPS",
        "trackingNumber": "1Z9999999999999999",
        "estimatedDeliveryDate": "2024-07-10"
      }
    }
  • MAY use HAL format to represent related resources

    http
    GET /orders/{order-id}?embed=(items,shippings)
    
    {
      "id": "uuid-...",
      "_embedded": {
        "items": [
          {
            "_links": { "self": { "href": "/products/987" } },
            "orderItemId": "1",
            "productId": "987",
            "productName": "Widget",
            "quantity": 2,
            "price": 25.00
          },
          {
            "_links": { "self": { "href": "/products/654" } },
            "orderItemId": "2",
            "productId": "654",
            "productName": "Gadget",
            "quantity": 1,
            "price": 50.00
          }
        ],
        "shippings": {
          "_links": { "self": { "href": "/shippings/56789" } },
          "shippingId": "56789",
          "carrier": "UPS",
          "trackingNumber": "1Z9999999999999999",
          "estimatedDeliveryDate": "2024-07-10"
        }
      }
    }
  • SHOULD document the available embed options in the API specification

  • SHOULD limit the depth of embedded resources to prevent performance issues

  • SHOULD implement proper error handling for invalid embed requests

OpenAPI 3.1.0 Example

yaml
openapi: 3.1.0
info:
  title: Order API
  version: 1.0.0
paths:
  /orders/{orderId}:
    get:
      summary: Get an order
      parameters:
        - name: embed
          in: query
          description: Embed related resources
          schema:
            type: array
            items:
              type: string
              enum:
                - items
                - shippings
          collectionFormat: csv
      responses:
        '200':
          description: Successful response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Order'
components:
  schemas:
    Order:
      type: object
      properties:
        orderId:
          type: string
        customerName:
          type: string
        totalPrice:
          type: number
        orderedAt:
          type: string
        items:
          type: array
          items:
            $ref: '#/components/schemas/OrderItem'
        shipping:
          $ref: '#/components/schemas/Shipping'
    OrderItem:
      type: object
      properties:
        orderItemId:
          type: string
        productId:
          type: string
        productName:
          type: string
        quantity:
          type: integer
        price:
          type: number
    Shipping:
      type: object
      properties:
        shippingId:
          type: string
        carrier:
          type: string
        trackingNumber:
          type: string
        estimatedDeliveryDate:
          type: string

Reference

Design references