Publisert - 03.11.2026

IKJ-API Overview

Behavior

In short, FHIR resources submitted to IKJ is stored as they are received, and key information is indexed to enable searching.

Incoming resources are validated to ensure that they are valid FHIR R4 resources - more strict profile validation might be added at a later stage. For now, we have made recommendation on how to use IKJ in this page.

Available environments

Environment FQDN
Test api.ikj.test.nhn.no

Authentication & Authorization

Accessing the IKJ API requires clients to be authenticated using HelseID and DPoP.

Property Value Description
Audience nhn:ikj Identifies the API
Scope nhn:ikj/api.read Access to read endpoints
Scope nhn:ikj/api.write Access to write endpoints
Claim helseid://claims/client/claims/orgnr_parent Organization you are acting on behalf of

Supported resource types

Operation Patient EpisodeOfCare CarePlan
Submit: POST /v1/{type} ✓ ✓ ✓
Update: PUT /v1/{type}/{resourceId} ✓ ✓ ✓
Update: PUT /v1/{type}?identifier=... ✓
Read: GET /v1/{type}/{resourceId} ✓ ✓ ✓
Search: GET /v1/{type}?... ✓ ✓ ✓

Submitting and updating resources

All write requests are processed asynchronously. A request that passes initial validation returns 202 Accepted, and the resource is queued for processing. The Location header contains the URL of a Task resource that reports the outcome. Poll the Task to find out whether processing succeeded or failed.

Errors are reported in one of two ways:

  • A request that cannot be accepted — such as an unparsable body or a malformed parameter — is rejected immediately with 400 Bad Request.
  • A request that is accepted but cannot be carried out — such as one referencing a resource that does not exist, or violating an identifier rule — returns 202, and the failure is reported on the Task.

Resource IDs are assigned by the server and cannot be chosen by the client. A submitted resource's ID is not part of the 202 response; once processing has succeeded, the Task contains a reference to the resource, such as Patient/3f9a1c58-2d4b-4e17-8c60-7a5b9e0d1234.

The request body size limit is 900 KB (921,600 bytes); querystring size limit is 2048 bytes.

Resource-specific rules

  • A Patient must carry at least one identifier with both a system and a value; processing of a Patient without one fails.
  • An EpisodeOfCare's patient element is required and must reference an existing patient. The patient reference cannot be changed when updating the resource.
  • A CarePlan's subject element is required and must reference an existing patient. The subject reference cannot be changed when updating the resource.

Updating by resource ID

PUT /v1/{type}/{resourceId} replaces an existing resource.

  • {resourceId} is the resource ID reported in the Task when resource was created, as described above. A value that is not a well-formed resource ID is rejected with 400 Bad Request.
  • The request body must contain an id identical to {resourceId}. A missing or different id is rejected with 400 Bad Request.
  • A PUT to a resource that does not exist fails during processing.

A PUT replaces the stored resource in full — it is not a merge. For identifiers, this means the stored set becomes exactly the set in the request body: an identifier that is omitted is removed, and stops working as a lookup key. An identifier in the body that is already registered to a different resource of the same type fails processing — resources are never merged.

Updating by identifier

PUT /v1/{type}?identifier={system}|{value} replaces an existing resource found by identifier instead of resource ID. It otherwise behaves like updating by resource ID.

  • The identifier parameter must use the full {system}|{value} form, and must match one of the identifiers in the request body; otherwise the request is rejected with 400 Bad Request. Since that identifier must be in the body, it is the one identifier this endpoint cannot change — use another identifier or the resource ID to change it.
  • The id in the request body is optional. When omitted, the server fills in the ID of the resource found. When present, a mismatch with the resource found fails processing.

Reading single resource

GET /v1/{type}/{resourceId} returns the resource, or 404 Not Found with an OperationOutcome if there is no match.

Searching for resources

GET /v1/{type}?... returns a FHIR Bundle of type searchset with the matching resources, possibly none. Matching entries have search.mode = match. The supported search parameters for each resource type are listed in the OpenAPI document, and may be combined freely; a resource must match all of them.

Pagination

Search results are paged using keyset pagination:

  • _count controls the page size (1–50, default 20).
  • _sort controls the sort order: _lastUpdated for ascending (default) or -_lastUpdated for descending.
  • When there are more results, the Bundle includes a next link with an opaque cursor parameter. Follow the link via GET to fetch the next page.

Treat the cursor as opaque — do not decode or modify it. It carries the filters, page size and sort order of the request that produced it, so combining a cursor with filter parameters, _count or _sort is rejected with 400 Bad Request.

GET /v1/Patient?_count=10&_sort=-_lastUpdated
{
  "resourceType": "Bundle",
  "type": "searchset",
  "link": [
    {
      "relation": "self",
      "url": "https://api.ikj.test.nhn.no/v1/Patient?_count=10&_sort=-_lastUpdated"
    },
    {
      "relation": "next",
      "url": "https://api.ikj.test.nhn.no/v1/Patient?cursor=ZXlKTVlYTjB..."
    }
  ]
}

Identifiers and coded elements

IKJ treats three kinds of elements differently, which decides both what you must submit and what you can search for:

  • Identifiers (Patient.identifier, EpisodeOfCare.identifier, CarePlan.identifier) name one specific resource. They are lookup keys, so they must be unambiguous.
  • Referenced identifiers (EpisodeOfCare.managingOrganization.identifier) identify a different resource that this one points at. They are written and searched like identifiers, but say nothing about the identity of the resource carrying them.
  • Coded elements (EpisodeOfCare.type, and other CodeableConcept elements as they are introduced) classify a resource. Many resources legitimately share the same code.

Rules for identifiers and referenced identifiers

  1. Only identifiers with both a system and a value are indexed. An identifier missing either part is stored in the resource as submitted, but cannot be searched for, cannot be used to update by identifier, and takes no part in the uniqueness rule below.
  2. The system may be at most 256 and the value at most 64 characters long. A resource carrying a longer one fails processing.
  3. Identifiers are unique: if an identifier is already registered to a different resource of the same type in your organization, processing fails. Referenced identifiers are not unique — many EpisodeOfCare resources may name the same managing organization.
  4. Searching by identifier is a token search, and may return more than one resource. Only the full {system}|{value} form of an identifier is guaranteed to match at most one. Updating by identifier requires the full form.

Rules for coded elements

  1. system and code are both optional, but a coding carrying neither is ignored, as nothing could ever match it. A CodeableConcept with only text and no coding is therefore not searchable.
  2. Coded elements are not unique. A search by code returns every resource carrying it.

Empty values

FHIR does not allow an empty string as an element value — omit the element instead. "system": "" is invalid and is rejected when the resource is parsed, before any of the rules above are applied.

Token search forms

Search parameters that match an identifier or a coded element are FHIR tokens. For identifiers, read {code} as {value}:

Form Matches
{code} The code in any system
{system}\|{code} The code in that system
\|{code} The code, only where the coding was submitted without a system
{system}\| Any code in that system

The |{code} form is only supported for coded elements: identifiers without a system are not indexed, so the form could never match one. It is rejected with 400 Bad Request for identifier search parameters.

A token that is just |, that contains more than one |, or whose system exceeds 256 or code exceeds 64 characters, is rejected with 400 Bad Request. A parameter given with an empty value, such as type=, is treated as if it were absent.

Search with _include

_include=EpisodeOfCare:patient adds the referenced Patient to the response, with search.mode = include. It is supported:

  • When searching: Each patient is included once per page.
  • When reading by resource ID: The response becomes a searchset Bundle instead of a single EpisodeOfCare.

Søk i Utviklerportalen

Søket er fullført!