Skip to content
ADP
API Design PrincipleBETA

[ADP-130] Idempotent-Key

Overview

POST/PATCH requests are not inherently idempotent, but we can make POST/PATCH requests idempotent by using the Idempotency-Key header, ensuring that multiple identical requests have the same result as a single request. This allows clients to safely retry requests without causing unintended side effects. For more information on idempotency, please refer to ADP-366.

Guidance

  • APIs SHOULD allow clients to use the Idempotency-Key for POST/PATCH operations to ensure that multiple identical requests are processed only once.

    • That is, API designs MAY decide whether the Idempotency-Key is an optional or required parameter.
  • The server MUST verify that the client-provided Idempotency-Key is unique for each request to prevent duplicate processing.

  • As suggested by the RFC draft, using UUIDs can ensure that the Idempotency-Key has high uniqueness and randomness.

  • Clients MAY decide whether to include the Idempotency-Key in the request header. For requests that fail due to network issues, clients can retry with the same Idempotency-Key.

  • If an API requires an Idempotency-Key, it SHOULD respond with a 400 Bad Request when the key is missing.

  • If the Idempotency-Key is not mandatory, the API SHOULD still process requests for non-idempotent operations.

Implementation Example

Scenario

A client creates a new resource using a POST request, including an Idempotency-Key to prevent multiple resource creations on retries.

Request

http
POST /resources HTTP/1.1
Host: api.example.com
Idempotency-Key: 123e4567-e89b-12d3-a456-426614174000
Content-Type: application/json

{
  "name": "Example Resource",
  "type": "example"
}

Server Processing

  1. Check the Idempotency-Key upon receiving the request.
  2. If the Idempotency-Key has not been used before, process the request and create the resource.
  3. If the Idempotency-Key has been used, return the result of the previous request.

Response

http
HTTP/1.1 201 Created
Content-Type: application/json

{
  "id": "abc123",
  "name": "Example Resource",
  "type": "example"
}

Example with OpenAPI

yaml
openapi: 3.1.0
info:
  title: Example API
  version: 1.0.0
paths:
  /resources:
    post:
      summary: Create a new resource
      operationId: createResource
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                type:
                  type: string
              required:
                - name
                - type
      responses:
        '201':
          description: Resource created successfully
          content:
            application/json:
              schema:
                type: object
                properties:
                  id:
                    type: string
                  name:
                    type: string
                  type:
                    type: string
        '400':
          description: Idempotency-Key is missing
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Error'
      parameters:
        - name: Idempotency-Key
          in: header
          required: false
          schema:
            type: string
          description: A unique identifier to ensure idempotency

components:
  schemas:
    Error:
      type: object
      properties:
        type:
          type: string
        title:
          type: string
        detail:
          type: string

Reference