Skills DirectorySkills Directory
SkillsLearnSecurityCategoriesDocsCommunityBlog
Sign InSubmit Skill
Skills Directory

Security-tested agent skills for Claude, coding agents, and AI workflows.

Directory

  • Browse Skills
  • All Skills A–Z
  • Claude Skills
  • Claude Code Skills
  • Agent Skills
  • Categories
  • Submit a Skill

Learn

  • Learn Hub
  • Install Claude Skills
  • Write SKILL.md
  • Skills vs MCP
  • Directories Compared

Security

  • Security
  • Methodology
  • Secure Claude Skills
  • Security Badges

Company

  • About
  • Community
  • Blog
  • API Docs
  • Advertise

2026 Skills Directory. All rights reserved.

Back to skills

Fhir Developer Skill

ASecurity

FHIR API development guide for building healthcare endpoints. Use when: (1) Creating FHIR REST endpoints (Patient, Observation, Encounter, Condition, MedicationRequest), (2) Validating FHIR resources and returning proper HTTP status codes and error responses, (3) Implementing SMART on FHIR authorization and OAuth scopes, (4) Working with Bundles, transactions, batch operations, or search pagination. Covers FHIR R4 resource structures, required fields, value sets (status codes, gender, intent)...

2,984 stars
0 votes
0 copies
0 views
Added 5/30/2026
developmenttypescriptpythongobashexpressfastapiapibackend

Works with

cliapi

Security Analysis

A100/100

Scanned 5/30/2026

Install to Claude Code

$npx -y skills add FreedomIntelligence/OpenClaw-Medical-Skills --skill fhir-developer-skill --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Fhir Developer Skill?

Add the live security badge to your README — it updates automatically with every re-scan.

Security grade badge for Fhir Developer Skill
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/freedomintelligence-fhir-developer-skill/badge)](https://www.skillsdirectory.com/skills/freedomintelligence-fhir-developer-skill)

More formats (shields.io, HTML) on the badges page.

Download Zip
Files
SKILL.md
---
name: fhir-developer-skill
description: >
  FHIR API development guide for building healthcare endpoints. Use when: (1) Creating
  FHIR REST endpoints (Patient, Observation, Encounter, Condition, MedicationRequest),
  (2) Validating FHIR resources and returning proper HTTP status codes and error responses,
  (3) Implementing SMART on FHIR authorization and OAuth scopes, (4) Working with Bundles,
  transactions, batch operations, or search pagination. Covers FHIR R4 resource structures,
  required fields, value sets (status codes, gender, intent), coding systems (LOINC, SNOMED,
  RxNorm, ICD-10), and OperationOutcome error handling.
---

# FHIR Developer Skill

## Quick Reference

### HTTP Status Codes
| Code | When to Use |
|------|-------------|
| `200 OK` | Successful read, update, or search |
| `201 Created` | Successful create (include `Location` header) |
| `204 No Content` | Successful delete |
| `400 Bad Request` | Malformed JSON, wrong resourceType |
| `401 Unauthorized` | Missing, expired, revoked, or malformed token (RFC 6750) |
| `403 Forbidden` | Valid token but insufficient scopes |
| `404 Not Found` | Resource doesn't exist |
| `412 Precondition Failed` | If-Match ETag mismatch (NOT 400!) |
| `422 Unprocessable Entity` | Missing required fields, invalid enum values, business rule violations |

### Required Fields by Resource (FHIR R4)
| Resource | Required Fields | Everything Else |
|----------|-----------------|-----------------|
| Patient | *(none)* | All optional |
| Observation | `status`, `code` | Optional |
| Encounter | `status`, `class` | Optional (including `subject`, `period`) |
| Condition | `subject` | Optional (including `code`, `clinicalStatus`) |
| MedicationRequest | `status`, `intent`, `medication[x]`, `subject` | Optional |
| Medication | *(none)* | All optional |
| Bundle | `type` | Optional |

---

## Required vs Optional Fields (CRITICAL)

**Only validate fields with cardinality starting with "1" as required.**

| Cardinality | Required? |
|-------------|-----------|
| `0..1`, `0..*` | NO |
| `1..1`, `1..*` | YES |

**Common mistake**: Making `subject` or `period` required on Encounter. They are 0..1 (optional).

---

## Value Sets (Enum Values)

Invalid enum values must return `422 Unprocessable Entity`.

### Patient.gender
`male | female | other | unknown`

### Observation.status
`registered | preliminary | final | amended | corrected | cancelled | entered-in-error | unknown`

### Encounter.status
`planned | arrived | triaged | in-progress | onleave | finished | cancelled | entered-in-error | unknown`

### Encounter.class (Common Codes)
| Code | Display | Use |
|------|---------|-----|
| `AMB` | ambulatory | Outpatient visits |
| `IMP` | inpatient encounter | Hospital admissions |
| `EMER` | emergency | Emergency department |
| `VR` | virtual | Telehealth |

### Condition.clinicalStatus
`active | recurrence | relapse | inactive | remission | resolved`

### Condition.verificationStatus
`unconfirmed | provisional | differential | confirmed | refuted | entered-in-error`

### MedicationRequest.status
`active | on-hold | cancelled | completed | entered-in-error | stopped | draft | unknown`

### MedicationRequest.intent
`proposal | plan | order | original-order | reflex-order | filler-order | instance-order | option`

### Bundle.type
`document | message | transaction | transaction-response | batch | batch-response | history | searchset | collection`

---

## Validation Pattern

**Python/FastAPI:**
```python
from fastapi import FastAPI
from fastapi.responses import JSONResponse

app = FastAPI()

def operation_outcome(severity: str, code: str, diagnostics: str):
    return {
        "resourceType": "OperationOutcome",
        "issue": [{"severity": severity, "code": code, "diagnostics": diagnostics}]
    }

VALID_OBS_STATUS = {"registered", "preliminary", "final", "amended",
                    "corrected", "cancelled", "entered-in-error", "unknown"}

@app.post("/Observation", status_code=201)
async def create_observation(data: dict):
    if not data.get("status"):
        return JSONResponse(status_code=422, content=operation_outcome(
            "error", "required", "Observation.status is required"
        ), media_type="application/fhir+json")

    if data["status"] not in VALID_OBS_STATUS:
        return JSONResponse(status_code=422, content=operation_outcome(
            "error", "value", f"Invalid status '{data['status']}'"
        ), media_type="application/fhir+json")
    # ... create resource
```

**TypeScript/Express:**
```typescript
const VALID_OBS_STATUS = new Set(['registered', 'preliminary', 'final', 'amended',
  'corrected', 'cancelled', 'entered-in-error', 'unknown']);

app.post('/Observation', (req, res) => {
  if (!req.body.status) {
    return res.status(422).contentType('application/fhir+json')
      .json(operationOutcome('error', 'required', 'Observation.status is required'));
  }
  if (!VALID_OBS_STATUS.has(req.body.status)) {
    return res.status(422).contentType('application/fhir+json')
      .json(operationOutcome('error', 'value', `Invalid status '${req.body.status}'`));
  }
  // ... create resource
});
```

**Pydantic v2 Models** (use `Literal`, not `const=True`):
```python
from typing import Literal
from pydantic import BaseModel

class Patient(BaseModel):
    resourceType: Literal["Patient"] = "Patient"
    id: str | None = None
    gender: Literal["male", "female", "other", "unknown"] | None = None
```

---

## Coding Systems (URLs)

| System | URL |
|--------|-----|
| LOINC | `http://loinc.org` |
| SNOMED CT | `http://snomed.info/sct` |
| RxNorm | `http://www.nlm.nih.gov/research/umls/rxnorm` |
| ICD-10 | `http://hl7.org/fhir/sid/icd-10` |
| v3-ActCode | `http://terminology.hl7.org/CodeSystem/v3-ActCode` |
| Observation Category | `http://terminology.hl7.org/CodeSystem/observation-category` |
| Condition Clinical | `http://terminology.hl7.org/CodeSystem/condition-clinical` |
| Condition Ver Status | `http://terminology.hl7.org/CodeSystem/condition-ver-status` |

### Common LOINC Codes (Vital Signs)
| Code | Description |
|------|-------------|
| `8867-4` | Heart rate |
| `8480-6` | Systolic blood pressure |
| `8462-4` | Diastolic blood pressure |
| `8310-5` | Body temperature |
| `2708-6` | Oxygen saturation (SpO2) |

---

## Data Type Patterns

### Coding (direct) vs CodeableConcept (wrapped)

**Coding** - Used by `Encounter.class`:
```json
{"system": "http://terminology.hl7.org/CodeSystem/v3-ActCode", "code": "AMB"}
```

**CodeableConcept** - Used by `Observation.code`, `Condition.code`:
```json
{"coding": [{"system": "http://loinc.org", "code": "8480-6"}], "text": "Systolic BP"}
```

### Reference
```json
{"reference": "Patient/123", "display": "John Smith"}
```

### Identifier
```json
{"system": "http://hospital.example.org/mrn", "value": "12345"}
```

---

## Common Mistakes

| Mistake | Correct Approach |
|---------|------------------|
| Making `subject` or `period` required on Encounter | Both are 0..1 (optional). Only `status` and `class` are required |
| Using CodeableConcept for `Encounter.class` | `class` uses Coding directly: `{"system": "...", "code": "AMB"}` |
| Returning 400 for ETag mismatch | Use `412 Precondition Failed` for If-Match failures |
| Returning 400 for invalid enum values | Use `422 Unprocessable Entity` for validation errors |
| Forgetting Content-Type header | Always set `Content-Type: application/fhir+json` |
| Missing Location header on create | Return `Location: /Patient/{id}` with 201 Created |

---

## Resource Structures

For complete JSON examples of all resources, see **[references/resource-examples.md](references/resource-examples.md)**.

Quick reference for error responses:

```json
{
  "resourceType": "OperationOutcome",
  "issue": [{"severity": "error", "code": "not-found", "diagnostics": "Patient/123 not found"}]
}
```

---

## RESTful Endpoints

```
POST   /[ResourceType]              # Create (returns 201 + Location header)
GET    /[ResourceType]/[id]         # Read
PUT    /[ResourceType]/[id]         # Update
DELETE /[ResourceType]/[id]         # Delete (returns 204)
GET    /[ResourceType]?param=value  # Search (returns Bundle)
GET    /metadata                    # CapabilityStatement
POST   /                            # Bundle transaction/batch
```

---

## Conditional Operations

**If-Match** (optimistic locking):
- Client sends: `If-Match: W/"1"`
- Mismatch returns `412 Precondition Failed`

**If-None-Exist** (conditional create):
- Client sends: `If-None-Exist: identifier=http://mrn|12345`
- Match exists: return existing (200)
- No match: create new (201)

---

## Reference Files

For detailed guidance, see:

- **[Resource Examples](references/resource-examples.md)**: Complete JSON structures for Patient, Observation, Encounter, Condition, MedicationRequest, OperationOutcome, CapabilityStatement
- **[SMART on FHIR Authorization](references/smart-auth.md)**: OAuth flows, scope syntax (v1/v2), backend services, scope enforcement
- **[Pagination](references/pagination.md)**: Search result pagination, `_count`/`_offset` parameters, link relations
- **[Bundle Operations](references/bundles.md)**: Transaction vs batch semantics, atomicity, processing order

---

## Implementation Checklist

1. Set `Content-Type: application/fhir+json` on all responses
2. Return `meta.versionId` and `meta.lastUpdated` on resources
3. Return `Location` header on create: `/Patient/{id}`
4. Return `ETag` header: `W/"{versionId}"`
5. Use OperationOutcome for all error responses
6. Validate required fields → 422 for missing
7. Validate enum values → 422 for invalid
8. Search returns Bundle with `type: "searchset"`

---

## Quick Start Script

To scaffold a new FHIR API project with correct Pydantic v2 patterns:

```bash
python scripts/setup_fhir_project.py my_fhir_api
```

Creates a FastAPI project with correct models, OperationOutcome helpers, and Patient CRUD endpoints.

Attribution

FreedomIntelligenceFreedomIntelligence
View sourceMore from FreedomIntelligence →
SSkills DirectorySkills Directory

Your tool, in front of Claude Code builders.

3 founder slots · $299/mo · GSC-verified traffic · sponsors can never buy grades.

See placements

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments (0)

No comments yet. Be the first to comment!

SSkills DirectorySkills Directory

Your tool, in front of Claude Code builders.

3 founder slots · $299/mo · GSC-verified traffic · sponsors can never buy grades.

See placements

Related Skills

Browser Extension Developer

Use this skill when developing or maintaining browser extension code in the `browser/` directory, including Chrome/Firefox/Edge compatibility, content scripts, background scripts, or i18n updates.

281612 votes

Seo Optimizer

SEO optimization with keyword analysis, readability assessment, technical validation, content quality. Use for search rankings, blog posts, content audits, or encountering keyword density, readability scores, meta tags, schema markup errors.

2132 votes

Google Official Seo Guide

Official Google SEO guide covering search optimization, best practices, Search Console, crawling, indexing, and improving website search visibility based on official Google documentation

1862 votes

Tanstack Start

Build a full-stack TanStack Start app on Cloudflare Workers from scratch — SSR, file-based routing, server functions, D1+Drizzle, better-auth, Tailwind v4+shadcn/ui. Use whenever the user mentions TanStack Start, asks to scaffold a full-stack Cloudflare app with SSR, wants an SSR dashboard, or asks for a React 19 + Cloudflare Workers app with file-based routing and server functions — even if they don't name TanStack Start specifically. No template repo — Claude generates every file fresh per ...

9881 votes

Pentest

PTES-aligned adversarial security audit for backend, frontend, and mobile applications. Produces a CVSS-scored Hacker Report with verified PoCs and phased remediation.

5491 votes
View all in development →