Publisert - 27.08.2026

Changelog

v2.0.0

Released date: TBD

Motivation

The previous status field (draft/active/revoked) tried to capture the plan's lifecycle in a single enum. It couldn't represent multiple content versions with independent approval states, and draft and revoked were both just "not in effect".

The new model replaces status with an active_version pointer — the version number of the content version that can currently be shown to patients (null if no version can). The old statuses map to the new model like this:

Old status Meaning New representation
draft Not yet in effect No active version: active_version is null, is_active is false
active Can be shown to patients active_version points at the version that can be shown (is_active is true for that version)
revoked Withdrawn, no longer shown Same as draft: deactivating clears active_version

Since draft and revoked collapse into the same state, "a draft" is now simply "a plan without an active version". This also enables:

  • per-version approval tracking (approvals array)
  • clients always seeing current metadata when querying historical snapshots

Terminology cleanup

  • version has been renamed to revision for all endpoints and models to avoid confusion with content.version
  • content.version has been renamed to version for all endpoints and models
  • the term revoke has been replaced by deactivate. Deactivating a plan clears the active_version pointer, so the plan has no active version

Changes

New endpoint

  • Added GET /api/v2/plan/{id}/active — returns the currently active version of a plan

PlanResponse changes

  • status field removed
  • is_active field added — true only when this content version is the active one
  • active_version field added — the content version that is currently active, null if the plan has no active version
  • content_version renamed to version
  • version (event counter) renamed to revision
  • approval_status removed — replaced with approvals array (one entry per content version)
  • rejection_reason and revoke_reason fields removed
  • publication_status entries: content_version renamed to version, published_at renamed to updated_at

Approvals

  • approvals is now an array of ApprovalEntry — one per content version
  • Each entry has: version, status (requested/given/rejected), updated_at
  • Approval commands ($approval-requested, $approval-given, $approval-rejected) now require both revision (for optimistic locking) and version (the content version being approved)

Mutation commands

  • All commands: version field renamed to revision (optimistic locking)
  • All commands: content_version field renamed to version (where applicable)
  • CreatePlanCommand no longer accepts status — new plans start with no active version

Renamed endpoints

  • POST /api/v2/plan/{id}/$publishPOST /api/v2/plan/{id}/$mark-published
  • POST /api/v2/plan/{id}/$unpublishPOST /api/v2/plan/{id}/$mark-unpublished
  • POST /api/v2/plan/{id}/$revokePOST /api/v2/plan/{id}/$deactivate

Removed endpoint

  • POST /api/v2/plan/{id}/$draft — plans start with no active version

Search filters

  • Removed ?status and ?approval_status query parameters
  • Added ?is_active=true|false — filter by active/inactive plans
  • Added ?updated_since=<RFC3339> — filter by last updated timestamp
  • Added ?published=true|false — filter by publication status for the requesting provider (uses orgnr_parent header). This can be used by each provider to keep up to date with publication status for plans.

HistoryResponse changes

  • version renamed to revision, content_version renamed to version
  • status and approval_status fields removed
  • Added event_type field — shows which event produced that snapshot
  • approvals is now the count of approval entries, publications is the count of publication entries

Response to versioned queries

  • GET /api/v2/plan/{id}/version/{version} now returns the historical content with current approvals, publication_status, and active_version merged in
  • GET /api/v2/plan/{id}/history returns raw historical snapshots (no merge) for audit purposes

v1.2.2

Released date: 2026-08-19

Motivation

The description field in clinical_content was renamed to better reflect its purpose: capturing the patient's personal goals for the care plan.

Changes

  • clinical_content.description renamed to clinical_content.personal_goals (breaking change)

v1.2.1

Released date: 2026-08-03

Motivation

Improve data quality and prevent leaking real national identity numbers (NIN) through the test & dev environment

Changes

We only accept synthetic NINs in the dev & test environment, and we will only accept real NINs in production

v1.2.0

Released date: 2026-07-28

Motivation

Providers need to independently control when a plan is visible to patients in their own systems. The publication workflow enables per-provider publication tracking.

Changes

  • Added POST /api/v2/plan/{id}/$publish to mark plan as published for the requesting provider
  • Added POST /api/v2/plan/{id}/$unpublish to mark plan as unpublished for the requesting provider
  • Publish and unpublish commands require version and content_version to specify which content snapshot to publish
  • PlanResponse now includes content_version (independent content version counter)
  • PlanResponse now includes publication_status (array of PublicationEntry per provider)
  • HistoryResponse now includes content_version, approval_status, and publications (count of publication entries)
  • PublicationEntry model: provider_id, status (published/unpublished), content_version, published_at

v1.1.1

Released date: 2026-07-20

Motivation

Improve routing internally in NHN

Changes

All endpoints exposed to clients are prefixed /api/. This means that GET /v2/plan/{id} becomes GET /api/v2/plan/{id} and so on

v1.1.0

Released date: 2026-07-01

Motivation

The CQRS pattern (/write/ and /read/ prefixes) is an internal implementation detail that shouldn't be exposed to API consumers. Additionally, automatic API documentation via Swagger improves developer experience.

Changes

  • All v2 endpoints unified under /v2/ prefix, hiding the internal /write/ and /read/ CQRS separation
  • GET /write/plan/{id} renamed to GET /v2/plan/{id}/$latest
  • Swagger UI available at /swagger/
  • 409 Conflict responses include Location header pointing to the plan's $latest endpoint

v1.0.0

Released date: 2026-06-30

Motivation

The API has been rewritten with CQRS to separate mutations from queries and added an approval workflow for plan governance.

Changes

  • All mutations moved under /write/plan, all queries under /read/plan
  • Single PUT /plan/{id} replaced with dedicated endpoints: $update-content, $draft, $activate, $revoke
  • New approval workflow: $approval-requested, $approval-given, $approval-rejected
  • Read response includes approval_status, rejection_reason, revoke_reason fields
  • Search endpoint supports approval_status query parameter (pending, approved, rejected)
  • Mutation endpoints return minimal response ({id, version}); use GET to retrieve full plan
  • Added GET /write/plan/{id} for reading from the write model
  • Documentation moved to Endpoints_v2.md

v0.4.0

Released date: 2026-06-15

Motivation

Clients need to retrieve a specific historical version of a plan, not just the latest one. This complements the History endpoint (which returns metadata only) by returning the full plan object at a given version.

Changes

  • Added GET /plan/{id}/version/{version} endpoint returning full Response object
  • Returns 400 for invalid UUID or version format, 404 for plan or version not found

v0.3.0

Released date: 2026-06-12

Motivation

The API now supports retrieving the full version history of a plan, enabling audit trail use cases. Additionally, the Search endpoint now requires the patient parameter to prevent unintended broad queries.

Changes

  • Added GET /plan/{id}/history endpoint returning []HistoryResponse
  • Added HistoryResponse model with fields: version, status, updated_at, updated_by, comment
  • patient query parameter is now mandatory in Search endpoint (returns 400 when missing)

v0.2.0

Released date: 2026-06-12

Motivation

The API model has been refactored to separate request and response. This provides a cleaner public API where server-assigned fields (id, version, updated_at) are not exposed in request bodies, and consumers receive dedicated response objects.

Additionally, the API now enforces optimistic locking via version checking on updates.

Changes

  • Split single Request model into CreateRequest, UpdateRequest, and Response
  • Renamed plan field to clinical_content in all requests and responses
  • Renamed Plan model to Content / Clinical Content
  • CreateRequest no longer accepts version — assigned by server
  • UpdateRequest requires version — must match current server version for optimistic locking
  • Update endpoint returns 409 Conflict on version mismatch, 422 Unprocessable Entity on missing version
  • Updated active status description to clarify it does NOT imply the plan is approved

v0.1.0

Released date: 2026-06-12

Motivation

Based of the feedback from work meeting 2026-06-11, we have revised which FHIR statuses to include as of now.

Furthermore, we have updated the documentation for the active status to not imply the plan is approved. This does not currently cause any behavioural changes in the API.

Changes

  • Added Request.status option revoked
  • Removed Request.status options completed and on-hold

Søk i Utviklerportalen

Søket er fullført!