> ## Documentation Index
> Fetch the complete documentation index at: https://docs.ferrum.thalamiq.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Update Resource

> Replace an existing FHIR resource entirely

Replaces an existing resource with a new version. The entire resource must be provided (not partial updates - use PATCH for that).

## Endpoint

```
PUT /fhir/{resourceType}/{id}
```

<ParamField path="resourceType" type="string" required>
  The FHIR resource type (e.g., `Patient`, `Observation`, `Encounter`)
</ParamField>

<ParamField path="id" type="string" required>
  The logical ID of the resource to update
</ParamField>

## Headers

<ParamField header="Content-Type" type="string" required>
  Must be `application/fhir+json` or `application/fhir+xml`
</ParamField>

<ParamField header="Accept" type="string">
  Response format: `application/fhir+json` (default) or `application/fhir+xml`
</ParamField>

<ParamField header="If-Match" type="string">
  Conditional update. Only update if current version matches this ETag. Example:
  `W/"5"` - Prevents lost updates via optimistic locking
</ParamField>

<ParamField header="Prefer" type="string">
  Response style: - `return=representation` (default) - Return full updated
  resource - `return=minimal` - Return headers only - `return=OperationOutcome`

  * Return OperationOutcome
</ParamField>

## Query Parameters

<ParamField query="search parameters" type="string">
  For conditional update. Update the resource matching these search parameters.
  Example: `?identifier=http://hospital.example/mrn|12345`
</ParamField>

## Request Body

The complete resource including the ID. Missing fields are removed (not preserved).

<CodeGroup>
  ```json Patient Update theme={null}
  {
    "resourceType": "Patient",
    "id": "123",
    "name": [
      {
        "family": "Doe",
        "given": ["Jane", "Marie"]
      }
    ],
    "gender": "female",
    "birthDate": "1990-01-01",
    "identifier": [
      {
        "system": "http://hospital.example/mrn",
        "value": "12345"
      }
    ],
    "telecom": [
      {
        "system": "email",
        "value": "jane.doe@example.com",
        "use": "home"
      }
    ],
    "active": true
  }
  ```

  ```json Observation Update theme={null}
  {
    "resourceType": "Observation",
    "id": "456",
    "status": "amended",
    "code": {
      "coding": [
        {
          "system": "http://loinc.org",
          "code": "8867-4",
          "display": "Heart rate"
        }
      ]
    },
    "subject": {
      "reference": "Patient/123"
    },
    "valueQuantity": {
      "value": 75,
      "unit": "beats/minute",
      "system": "http://unitsofmeasure.org",
      "code": "/min"
    }
  }
  ```
</CodeGroup>

<Warning>
  **Total Replacement**: PUT replaces the entire resource. Any fields not
  included in the request body are removed. Use PATCH for partial updates.
</Warning>

## Response

### 200 OK

Resource updated successfully.

<ResponseField name="meta.versionId" type="string" required>
  New version number (incremented from previous)
</ResponseField>

<ResponseField name="meta.lastUpdated" type="string" required>
  ISO 8601 timestamp of this update
</ResponseField>

<ResponseExample>
  ```json Updated Resource theme={null}
  {
    "resourceType": "Patient",
    "id": "123",
    "meta": {
      "versionId": "6",
      "lastUpdated": "2026-01-12T14:30:00.000Z"
    },
    "name": [
      {
        "family": "Doe",
        "given": ["Jane", "Marie"]
      }
    ],
    "gender": "female",
    "birthDate": "1990-01-01",
    "identifier": [
      {
        "system": "http://hospital.example/mrn",
        "value": "12345"
      }
    ],
    "telecom": [
      {
        "system": "email",
        "value": "jane.doe@example.com",
        "use": "home"
      }
    ],
    "active": true
  }
  ```

  Headers:

  ```
  HTTP/1.1 200 OK
  Content-Type: application/fhir+json
  ETag: W/"6"
  Last-Modified: Mon, 12 Jan 2026 14:30:00 GMT
  Content-Location: /fhir/Patient/123/_history/6
  ```
</ResponseExample>

### 201 Created

Resource created (update-as-create). Occurs when the resource doesn't exist and server allows creation via PUT.

<ResponseExample>
  ```json Created Resource theme={null}
  {
    "resourceType": "Patient",
    "id": "new-patient-123",
    "meta": {
      "versionId": "1",
      "lastUpdated": "2026-01-12T14:30:00.000Z"
    },
    "name": [
      {
        "family": "Doe",
        "given": ["John"]
      }
    ]
  }
  ```

  Headers:

  ```
  HTTP/1.1 201 Created
  Location: /fhir/Patient/new-patient-123
  ETag: W/"1"
  Content-Type: application/fhir+json
  ```
</ResponseExample>

<Note>
  **Update-as-Create**: Whether PUT can create resources (when they don't exist)
  depends on server configuration. Check the CapabilityStatement for
  `updateCreate` support.
</Note>

### 400 Bad Request

Validation failed or malformed request.

<ResponseExample>
  ```json Validation Error theme={null}
  {
    "resourceType": "OperationOutcome",
    "issue": [
      {
        "severity": "error",
        "code": "invalid",
        "expression": ["Patient.id"],
        "diagnostics": "Resource ID in body (999) does not match URL (123)"
      }
    ]
  }
  ```
</ResponseExample>

### 404 Not Found

Resource doesn't exist and server doesn't support update-as-create.

<ResponseExample>
  ```json Not Found theme={null}
  {
    "resourceType": "OperationOutcome",
    "issue": [
      {
        "severity": "error",
        "code": "not-found",
        "diagnostics": "Resource Patient/123 not found"
      }
    ]
  }
  ```
</ResponseExample>

### 409 Conflict

Version conflict or referential integrity violation.

<ResponseExample>
  ```json Version Conflict theme={null}
  {
    "resourceType": "OperationOutcome",
    "issue": [
      {
        "severity": "error",
        "code": "conflict",
        "diagnostics": "Version conflict: current version is 7, provided If-Match is W/\"5\""
      }
    ]
  }
  ```
</ResponseExample>

### 412 Precondition Failed

Conditional update matched multiple resources (ambiguous) or If-Match failed.

<ResponseExample>
  ```json Multiple Matches theme={null}
  {
    "resourceType": "OperationOutcome",
    "issue": [
      {
        "severity": "error",
        "code": "multiple-matches",
        "diagnostics": "Multiple resources match the search criteria. Conditional update requires exactly one match."
      }
    ]
  }
  ```
</ResponseExample>

## Examples

<CodeGroup>
  ```bash cURL - Basic Update theme={null}
  curl -X PUT "https://your-server.com/fhir/Patient/123" \
    -H "Content-Type: application/fhir+json" \
    -H "Accept: application/fhir+json" \
    -d '{
      "resourceType": "Patient",
      "id": "123",
      "name": [{"family": "Doe", "given": ["Jane"]}],
      "gender": "female",
      "birthDate": "1990-01-01"
    }'
  ```

  ```bash cURL - Safe Update (with If-Match) theme={null}
  # First, read the resource to get current ETag
  curl -i "https://your-server.com/fhir/Patient/123"
  # Note the ETag: W/"5"

  # Then update with If-Match to prevent lost updates
  curl -X PUT "https://your-server.com/fhir/Patient/123" \
    -H "Content-Type: application/fhir+json" \
    -H "Accept: application/fhir+json" \
    -H 'If-Match: W/"5"' \
    -d '{
      "resourceType": "Patient",
      "id": "123",
      "name": [{"family": "Doe", "given": ["Jane", "Marie"]}],
      "gender": "female",
      "birthDate": "1990-01-01"
    }'
  ```

  ```bash cURL - Conditional Update theme={null}
  curl -X PUT "https://your-server.com/fhir/Patient?identifier=http://hospital.example/mrn|12345" \
    -H "Content-Type: application/fhir+json" \
    -H "Accept: application/fhir+json" \
    -d '{
      "resourceType": "Patient",
      "identifier": [{"system": "http://hospital.example/mrn", "value": "12345"}],
      "name": [{"family": "Doe", "given": ["Jane"]}]
    }'
  ```

  ```bash cURL - Update-as-Create theme={null}
  curl -X PUT "https://your-server.com/fhir/Patient/my-custom-id" \
    -H "Content-Type: application/fhir+json" \
    -H "Accept: application/fhir+json" \
    -d '{
      "resourceType": "Patient",
      "id": "my-custom-id",
      "name": [{"family": "Doe", "given": ["John"]}]
    }'
  ```

  ```python Python Example theme={null}
  import requests

  url = "https://your-server.com/fhir/Patient/123"
  headers = {
      "Content-Type": "application/fhir+json",
      "Accept": "application/fhir+json"
  }

  # Read current version
  response = requests.get(url, headers={"Accept": "application/fhir+json"})
  patient = response.json()
  etag = response.headers['ETag']

  # Modify patient
  patient['name'][0]['given'] = ['Jane', 'Marie']
  patient['telecom'] = [
      {
          "system": "email",
          "value": "jane.doe@example.com"
      }
  ]

  # Update with optimistic locking
  headers['If-Match'] = etag
  response = requests.put(url, json=patient, headers=headers)

  if response.status_code == 200:
      updated = response.json()
      print(f"Updated to version {updated['meta']['versionId']}")
  elif response.status_code == 412:
      print("Version conflict - resource was modified by someone else")
  ```

  ```javascript JavaScript Example theme={null}
  const url = "https://your-server.com/fhir/Patient/123";

  // Read current version
  let response = await fetch(url, {
    headers: { Accept: "application/fhir+json" },
  });
  const patient = await response.json();
  const etag = response.headers.get("ETag");

  // Modify patient
  patient.name[0].given = ["Jane", "Marie"];
  patient.active = true;

  // Update with optimistic locking
  response = await fetch(url, {
    method: "PUT",
    headers: {
      "Content-Type": "application/fhir+json",
      Accept: "application/fhir+json",
      "If-Match": etag,
    },
    body: JSON.stringify(patient),
  });

  if (response.status === 200) {
    const updated = await response.json();
    console.log(`Updated to version ${updated.meta.versionId}`);
  } else if (response.status === 412) {
    console.log("Version conflict - retry needed");
  }
  ```
</CodeGroup>

## Best Practices

<Tip>
  **Always Use If-Match**: Include the `If-Match` header with the current ETag
  to prevent lost updates in concurrent scenarios. Without it, last write wins.
</Tip>

<Warning>
  **Complete Resource Required**: You must send the entire resource. Missing fields are removed. Common mistake:

  ```json Bad - Missing fields will be deleted theme={null}
  {
    "resourceType": "Patient",
    "id": "123",
    "name": [{ "family": "NewName" }]
    // Oops! gender, birthDate, identifier all deleted
  }
  ```

  For partial updates, use [PATCH](/api-reference/endpoint/patch) instead.
</Warning>

<Note>
  **ID Consistency**: The `id` in the request body must match the `id` in the
  URL. The `resourceType` must also match.
</Note>

## See Also

<CardGroup cols={2}>
  <Card title="Patch Resource" href="/api-reference/endpoint/patch">
    Partial updates without replacing entire resource
  </Card>

  <Card title="Read Resource" href="/api-reference/endpoint/read">
    Get current version before updating
  </Card>

  <Card title="Resource History" href="/api-reference/history/resource">
    View update history
  </Card>

  <Card title="Learn FHIR CRUD" href="/learn-fhir/crud">
    Understand FHIR update semantics
  </Card>
</CardGroup>


## OpenAPI

````yaml PUT /{resourceType}/{id}
openapi: 3.1.0
info:
  title: Ferrum API
  description: >-
    FHIR R4 RESTful API implementation. All endpoints are prefixed with `/fhir`
    and follow the FHIR specification.
  version: 1.0.0
  contact:
    name: Ferrum
    url: https://github.com/thalamiq/ferrum
  license:
    name: MIT
servers:
  - url: http://localhost:8080/fhir
    description: Local development server (default port 8080)
  - url: https://your-server.com/fhir
    description: Production server (replace with your actual server URL)
  - url: https://api.example.com/fhir
    description: Example production server
security:
  - bearerAuth: []
paths:
  /{resourceType}/{id}:
    put:
      tags:
        - CRUD
      summary: Update Resource
      description: >-
        Update an existing resource. Requires the current version ID in
        meta.versionId.
      operationId: updateResource
      parameters:
        - $ref: '#/components/parameters/ResourceType'
        - $ref: '#/components/parameters/Id'
        - $ref: '#/components/parameters/IfMatch'
      requestBody:
        required: true
        content:
          application/fhir+json:
            schema:
              $ref: '#/components/schemas/Resource'
          application/fhir+xml:
            schema:
              $ref: '#/components/schemas/Resource'
      responses:
        '200':
          description: Resource updated
          content:
            application/fhir+json:
              schema:
                $ref: '#/components/schemas/Resource'
        '201':
          description: Resource created (update-create)
          content:
            application/fhir+json:
              schema:
                $ref: '#/components/schemas/Resource'
        '400':
          $ref: '#/components/responses/BadRequest'
        '404':
          $ref: '#/components/responses/NotFound'
        '409':
          $ref: '#/components/responses/Conflict'
        '412':
          $ref: '#/components/responses/PreconditionFailed'
components:
  parameters:
    ResourceType:
      name: resourceType
      in: path
      required: true
      description: The FHIR resource type (e.g., Patient, Observation, Encounter)
      schema:
        type: string
    Id:
      name: id
      in: path
      required: true
      description: The logical ID of the resource
      schema:
        type: string
    IfMatch:
      name: If-Match
      in: header
      description: For version-aware updates
      schema:
        type: string
  schemas:
    Resource:
      type: object
      description: A FHIR resource. All resources have resourceType, id, and meta fields.
      required:
        - resourceType
      properties:
        resourceType:
          type: string
          description: The type of resource
        id:
          type: string
          description: Logical id of this artifact
        meta:
          $ref: '#/components/schemas/Meta'
      additionalProperties: true
    Meta:
      type: object
      description: Metadata about a resource
      properties:
        versionId:
          type: string
          description: Version specific identifier
        lastUpdated:
          type: string
          format: date-time
          description: When the resource version last changed
        profile:
          type: array
          items:
            type: string
            format: uri
          description: Profiles this resource claims to conform to
        tag:
          type: array
          items:
            $ref: '#/components/schemas/Coding'
          description: Tags applied to this resource
        security:
          type: array
          items:
            $ref: '#/components/schemas/Coding'
          description: Security labels applied to this resource
    OperationOutcome:
      type: object
      description: >-
        A collection of error, warning or information messages that result from
        a system action
      required:
        - resourceType
      properties:
        resourceType:
          type: string
          enum:
            - OperationOutcome
          description: Resource type
        issue:
          type: array
          items:
            $ref: '#/components/schemas/OperationOutcomeIssue'
          description: A list of issues associated with the operation
    Coding:
      type: object
      description: A reference to a code defined by a terminology system
      properties:
        system:
          type: string
          format: uri
          description: Identity of the terminology system
        version:
          type: string
          description: Version of the system - if relevant
        code:
          type: string
          description: Symbol in syntax defined by the system
        display:
          type: string
          description: Representation defined by the system
    OperationOutcomeIssue:
      type: object
      description: An issue associated with the operation
      required:
        - severity
        - code
      properties:
        severity:
          type: string
          enum:
            - fatal
            - error
            - warning
            - information
          description: Severity of the issue
        code:
          type: string
          enum:
            - invalid
            - structure
            - required
            - value
            - invariant
            - security
            - login
            - unknown
            - expired
            - forbidden
            - suppressed
            - processing
            - not-supported
            - duplicate
            - multiple-matches
            - not-found
            - deleted
            - too-long
            - code-invalid
            - extension
            - too-costly
            - business-rule
            - conflict
            - transient
            - lock-error
            - no-store
            - exception
            - timeout
            - incomplete
            - throttled
            - informational
          description: Error or warning code
        details:
          $ref: '#/components/schemas/CodeableConcept'
        diagnostics:
          type: string
          description: Additional diagnostic information about the issue
        location:
          type: array
          items:
            type: string
          description: XPath or JSONPath expression describing the location of the issue
    CodeableConcept:
      type: object
      description: >-
        A concept that may be defined by a formal reference to a terminology or
        ontology
      properties:
        coding:
          type: array
          items:
            $ref: '#/components/schemas/Coding'
        text:
          type: string
          description: Plain text representation of the concept
  responses:
    BadRequest:
      description: Bad request - validation error or invalid input
      content:
        application/fhir+json:
          schema:
            $ref: '#/components/schemas/OperationOutcome'
    NotFound:
      description: Resource not found
      content:
        application/fhir+json:
          schema:
            $ref: '#/components/schemas/OperationOutcome'
    Conflict:
      description: Version conflict
      content:
        application/fhir+json:
          schema:
            $ref: '#/components/schemas/OperationOutcome'
    PreconditionFailed:
      description: Precondition failed
      content:
        application/fhir+json:
          schema:
            $ref: '#/components/schemas/OperationOutcome'
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT
      description: Bearer token authentication

````