Publisert - 12.10.2026

IKJ-API overview

Informasjon fra Kommunal Journal (IKJ) provides endpoints for submitting and retrieving patient information. Patient resources are represented using the FHIR standard, version R4.

Available environments

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

Access control

Accessing the IKJ API requires clients to be authenticated using HelseID and DPoP (Demonstrating Proof-of-Possession):

  1. Scope: Clients must request the appropriate scope (nhn:ikj/api.read or nhn:ikj/api.write).
  2. Claim: Access token must include claim helseid://claims/client/claims/orgnr_parent.
  3. DPoP required: Only requests including DPoP tokens are accepted.
  4. Authorization header: Access token must be sent using the DPoP prefix (i.e., not Bearer).
  5. DPoP-Proof: Requests must include a DPoP header with a signed proof generated by the client.

See HelseID Dokumentasjon - DPoP for implementation details.

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}?... ✓ ✓ ✓

The behavior shared by all resource types is described under Common behavior. The sections for each resource type only describe what is specific to that type.

Common behavior

Submitting and updating

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

Updating by resource ID

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

  • {resourceId} must be a resource ID obtained from a Task, 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.

Reading

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

Searching

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 its section, and may be combined freely; a resource must match all of them.

_lastUpdated is supported for all resource types, and limits results by when resources were last updated in IKJ. It requires the prefix ge or gt and at least minute precision, e.g. _lastUpdated=ge2024-01-01T12:00Z.

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.

Patient resources

A Patient must carry at least one identifier with both a system and a value; processing of a Patient without one fails.

Updating by identifier

PUT /v1/Patient?identifier={system}|{value} updates an existing patient 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.
  • This endpoint does not create patients. If no patient in your organization matches the identifier, processing fails.
  • The id in the request body is optional. When omitted, the server fills in the ID of the patient found. When present, a mismatch with the patient found fails processing.

Search parameters

Parameter Description
identifier Identifier token. All token forms except \|{value}.
_lastUpdated See Searching.

Example:

GET /v1/Patient?identifier=http://example.no/ids|12345

EpisodeOfCare resources

Submitting and updating

The patient element is required and must reference an existing patient in the form Patient/{resourceId}. A reference of any other form is rejected with 400 Bad Request; a reference to a patient that does not exist fails processing.

When updating:

  • The patient reference cannot be changed. It must still be present, and name the patient the EpisodeOfCare was created for; a different patient fails processing.
  • managingOrganization is replaced like the identifiers — omitting it removes the stored one.
  • status is required. period is replaced by the value in the body, or cleared if the body omits it.

Search parameters

Parameter Description
patient Resource ID of the patient.
patient.identifier Identifier token of the patient. All token forms except \|{value}.
type Service type token. All four token forms. Matches if any coding of any type entry matches.
managingOrganization.identifier Identifier token of the managing organization. All token forms except \|{value}.
_lastUpdated See Searching.

When patient and patient.identifier are combined, both must match the same patient. Example:

GET /v1/EpisodeOfCare?patient.identifier=urn:oid:2.16.578.1.12.4.1.4.1|12345678901&type=http://example.no/codes|ABC

_include=EpisodeOfCare:patient adds the referenced Patient to the response, with search.mode = include. It is supported both when searching, where each patient is included once per page, and when reading by resource ID, where the response becomes a searchset Bundle instead of a single EpisodeOfCare. Any other _include value is rejected with 400 Bad Request.

CarePlan resources

Submitting and updating

The subject element is required and must reference an existing patient in the form Patient/{resourceId}. A reference of any other form is rejected with 400 Bad Request; a reference to a patient that does not exist fails processing.

When updating:

  • The subject reference cannot be changed. It must still be present, and name the patient the CarePlan was created for; a different patient fails processing.
  • Activities are replaced like the identifiers — an activity omitted from the body is removed.

Search parameters

Parameter Description
activity-date Scheduled period of an activity. See below.
patient Resource ID of the patient referenced by subject.
patient.identifier Identifier token of the patient. All token forms except \|{value}.
_lastUpdated See Searching.

When patient and patient.identifier are combined, both must match the same patient.

activity-date matches CarePlan resources with at least one activity whose scheduled period overlaps the given date criteria. Only schedules of type Period are supported. The parameter can be repeated, in which case a single activity must satisfy all criteria. It requires minute precision, and supports the prefixes eq, gt, ge, lt and le. For example, this matches activities scheduled during 2024:

GET /v1/CarePlan?activity-date=ge2024-01-01T00:00Z&activity-date=le2024-12-31T23:59Z

Søk i Utviklerportalen

Søket er fullført!