> ## 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.

# Delete Resource

> Remove a FHIR resource

Marks a resource as deleted. Most servers use soft delete, preserving the resource in history.

## Endpoint

```
DELETE /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 delete
</ParamField>

## Headers

<ParamField header="Prefer" type="string">
  Response style:

  * `return=representation` - Return OperationOutcome
  * `return=minimal` (default) - No response body
  * `return=OperationOutcome` - Return OperationOutcome
</ParamField>

## Query Parameters

<ParamField query="search parameters" type="string">
  For conditional delete. Delete the resource matching these search parameters.

  Example: `?identifier=http://hospital.example/mrn|12345`
</ParamField>

## Response

### 204 No Content

Resource deleted successfully. No response body.

<ResponseExample>
  Headers:

  ```
  HTTP/1.1 204 No Content
  ETag: W/"6"
  ```
</ResponseExample>

### 200 OK

Resource deleted successfully with OperationOutcome (when using `Prefer: return=OperationOutcome`).

<ResponseExample>
  ```json Deletion Confirmed theme={null}
  {
    "resourceType": "OperationOutcome",
    "issue": [
      {
        "severity": "information",
        "code": "informational",
        "diagnostics": "Resource Patient/123 deleted successfully"
      }
    ]
  }
  ```

  Headers:

  ```
  HTTP/1.1 200 OK
  Content-Type: application/fhir+json
  ETag: W/"6"
  ```
</ResponseExample>

### 404 Not Found

Resource doesn't exist (some servers return 204 for idempotency).

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

### 409 Conflict

Resource cannot be deleted due to referential integrity or business rules.

<ResponseExample>
  ```json Cannot Delete - Has References theme={null}
  {
    "resourceType": "OperationOutcome",
    "issue": [
      {
        "severity": "error",
        "code": "conflict",
        "diagnostics": "Cannot delete Patient/123: referenced by Observation/456, Encounter/789"
      }
    ]
  }
  ```
</ResponseExample>

### 412 Precondition Failed

Conditional delete matched multiple resources (ambiguous).

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

## Examples

<CodeGroup>
  ```bash cURL - Basic Delete theme={null}
  curl -X DELETE "https://your-server.com/fhir/Patient/123"
  ```

  ```bash cURL - Delete with OperationOutcome theme={null}
  curl -X DELETE "https://your-server.com/fhir/Patient/123" \
    -H "Prefer: return=OperationOutcome"
  ```

  ```bash cURL - Conditional Delete theme={null}
  curl -X DELETE "https://your-server.com/fhir/Patient?identifier=http://hospital.example/mrn|12345"
  ```

  ```bash cURL - Verify Deletion theme={null}
  # Delete the resource
  curl -X DELETE "https://your-server.com/fhir/Patient/123"

  # Try to read it (should return 410 Gone)
  curl -i "https://your-server.com/fhir/Patient/123"
  ```

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

  url = "https://your-server.com/fhir/Patient/123"

  response = requests.delete(url)
  if response.status_code == 204:
      print("Patient deleted successfully")
  elif response.status_code == 404:
      print("Patient not found")
  elif response.status_code == 409:
      outcome = response.json()
      print(f"Cannot delete: {outcome['issue'][0]['diagnostics']}")
  ```

  ```python Python - With Safety Check theme={null}
  import requests

  patient_id = "123"
  url = f"https://your-server.com/fhir/Patient/{patient_id}"

  # First check if resource exists
  response = requests.get(url)
  if response.status_code == 200:
      patient = response.json()
      print(f"Deleting patient: {patient['name'][0]['family']}")
      
      # Delete the resource
      response = requests.delete(url)
      if response.status_code == 204:
          print("Deleted successfully")
  else:
      print("Patient not found")
  ```

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

  const response = await fetch(url, {
    method: 'DELETE'
  });

  if (response.status === 204) {
    console.log('Patient deleted successfully');
  } else if (response.status === 404) {
    console.log('Patient not found');
  } else if (response.status === 409) {
    const outcome = await response.json();
    console.log(`Cannot delete: ${outcome.issue[0].diagnostics}`);
  }
  ```

  ```javascript JavaScript - Conditional Delete theme={null}
  const response = await fetch(
    'https://your-server.com/fhir/Patient?identifier=http://hospital.example/mrn|12345',
    {
      method: 'DELETE'
    }
  );

  if (response.status === 204) {
    console.log('Patient deleted');
  } else if (response.status === 412) {
    console.log('Multiple matches found - cannot delete');
  }
  ```
</CodeGroup>

## Delete Behavior

### Soft Delete (Typical)

Most FHIR servers use soft delete:

* Resource marked as deleted in database
* History preserved and accessible
* `GET /Patient/123` returns `410 Gone`
* `GET /Patient/123/_history/5` still works (returns version 5)

### Hard Delete (Rare)

Complete removal from database:

* Resource and all history permanently deleted
* Cannot be recovered
* Usually restricted by policy or disabled entirely

<Note>
  **Check Server Behavior**: Review the server's CapabilityStatement or documentation to understand its delete behavior.
</Note>

## Idempotent Delete

DELETE is idempotent - deleting an already-deleted resource succeeds:

```bash theme={null}
# First delete
DELETE /fhir/Patient/123  # 204 No Content

# Second delete (same resource)
DELETE /fhir/Patient/123  # 204 No Content (idempotent)

# Reading the deleted resource
GET /fhir/Patient/123     # 410 Gone
```

## Conditional Delete

Delete by search criteria instead of ID:

```
DELETE /fhir/{resourceType}?{search_parameters}
```

**Behavior**:

* **0 matches**: No-op, returns `204 No Content`
* **1 match**: Deletes that resource → `204 No Content`
* **2+ matches**: Rejects as ambiguous → `412 Precondition Failed`

**Example**: Delete patient by identifier

```bash theme={null}
DELETE /fhir/Patient?identifier=http://hospital.example/mrn|12345
```

## Accessing Deleted Resources

After soft delete, use history endpoints to access deleted resources:

```bash theme={null}
# List all versions (including deleted)
GET /fhir/Patient/123/_history

# Read specific version (even if resource is deleted)
GET /fhir/Patient/123/_history/5
```

## Referential Integrity

Some servers check if other resources reference the resource being deleted:

**Protected Resources** (common scenarios):

* Patient referenced by Observations, Encounters
* Practitioner referenced by many resources
* Organization referenced by locations, departments

**Server Behavior**:

* Allow deletion regardless (most permissive)
* Return `409 Conflict` if references exist (most cautious)
* Cascade delete (rare - delete referencing resources too)

## Common Use Cases

### Delete Test Data

```bash theme={null}
DELETE /fhir/Patient/test-patient-123
```

### Soft Delete with Verification

```python theme={null}
import requests

# Delete
requests.delete('https://server.com/fhir/Patient/123')

# Verify it's gone (should get 410)
response = requests.get('https://server.com/fhir/Patient/123')
assert response.status_code == 410, "Resource should be deleted"
```

### Conditional Delete by Identifier

```bash theme={null}
DELETE /fhir/Patient?identifier=http://hospital.example/temp|temp-12345
```

### Delete with Audit Trail

```python theme={null}
import requests

patient_id = "123"
url = f"https://server.com/fhir/Patient/{patient_id}"

# Get current state before deleting (for audit)
patient = requests.get(url).json()
audit_log = {
    "action": "delete",
    "resource": patient,
    "timestamp": "2026-01-12T15:00:00Z"
}

# Perform delete
response = requests.delete(url)
if response.status_code == 204:
    print("Deleted and logged")
```

## Best Practices

<Warning>
  **Cannot Undo**: Even with soft delete, most UIs don't provide "undelete" functionality. Ensure deletion is intended before proceeding.
</Warning>

<Tip>
  **Check References First**: Before deleting, search for resources that reference it to avoid breaking referential integrity:

  ```bash theme={null}
  GET /fhir/Observation?subject=Patient/123
  GET /fhir/Encounter?subject=Patient/123
  ```

  If any exist, consider whether deletion is appropriate.
</Tip>

<Note>
  **Empty Body**: DELETE requests should have an empty body per FHIR specification. Don't send a resource in the body.
</Note>

## See Also

<CardGroup cols={2}>
  <Card title="Resource History" href="/api-reference/history/resource">
    View deleted resource versions
  </Card>

  <Card title="Search" href="/api-reference/search/type">
    Find resources before deleting
  </Card>

  <Card title="Update Resource" href="/api-reference/endpoint/update">
    Modify instead of deleting
  </Card>

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


## OpenAPI

````yaml DELETE /{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}:
    delete:
      tags:
        - CRUD
      summary: Delete Resource
      description: Delete a specific resource by type and ID.
      operationId: deleteResource
      parameters:
        - $ref: '#/components/parameters/ResourceType'
        - $ref: '#/components/parameters/Id'
      responses:
        '200':
          description: Resource deleted
          content:
            application/fhir+json:
              schema:
                $ref: '#/components/schemas/Resource'
        '204':
          description: Resource deleted (no content)
        '404':
          $ref: '#/components/responses/NotFound'
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
  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:
    NotFound:
      description: Resource not found
      content:
        application/fhir+json:
          schema:
            $ref: '#/components/schemas/OperationOutcome'
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT
      description: Bearer token authentication

````