Create a new organization / instance in SFM

SFM is set up as a self service system, and when all formal work is in place, the host system (EHR/EPJ) may create a new instance in SFM for the EHR customer.

HelseID preparations

The EHR system vendor prepares the system as a "client system" in HelseID self service, registering the consumption of SFM API in the profile. For multi tenant solutions, a multi tenant HelseID client system may be selected. The Client system will in this case also be a HelseID client.

It is important to understand the differences between the two variants:

  • Multi tenant client will request token with a specific jounal-id
  • Single tentant client will present a pre-configured SFM-id.

Create Organization

For a new customer (doctors office new to SFM), the EHR superuser will create the organization element, using a token with a SFM-id or journal-id. Create is the only allowed operation with an unknown id. The Create payload must be corresponding to identifiers in the token. If successful validation, SFM will create a new database schema, containing one Organization and one Person.

Example

In this example a new organisation Kolåsbakkane legekontor will be created using a new single tenant client (SFM-id not previously known by SFM). The EHR system creates a FHIR Organization payload with the essential properties, and selects active=false. Then this payload is POST-ed to the ./Organization endpoint:

    {
    "resourceType": "Organization",
    "meta": {
        "versionId": "1",
        "lastUpdated": "2024-05-23T15:33:58.7998213+02:00",
        "profile": [
        "http://ehelse.no/fhir/StructureDefinition/sfm-Organization"
        ]
    },
    "extension": [
        {
        "extension": [
            {
            "extension": [
                {
                "url": "systemcode",
                "valueString": "DrWho"
                },
                {
                "url": "systemname",
                "valueString": "Doctor Who testtool"
                },
                {
                "url": "version",
                "valueString": "4.1"
                },
                {
                "url": "updatetime",
                "valueDateTime": "2024-05-23T15:30:17.0349469+02:00"
                }
            ],
            "url": "systeminfo"
            },
            {
            "extension": [
                {
                "url": "servicevendorname",
                "valueString": "Kolåsen vedlikehald"
                },
                {
                "url": "contactname",
                "valueString": "Didrik"
                },
                {
                "url": "contactemail",
                "valueString": "didrik@kolaasen.no"
                },
                {
                "url": "contactphone",
                "valueString": "98765432"
                }
            ],
            "url": "operationsuplierinfo"
            }
        ],
        "url": "http://ehelse.no/fhir/StructureDefinition/sfm-epjinfo"
        }
    ],
    "identifier": [
        {
        "use": "official",
        "system": "urn:oid:2.16.578.1.12.4.1.4.101",
        "value": "917897468"
        },
        {
        "use": "official",
        "system": "urn:oid:2.16.578.1.12.4.1.2",
        "value": "81420690"
        },
        {
        "use": "official",
        "system": "urn:oid:2.16.578.1.12.4.1.4.109",
        "value": "a99abfb4-2bea-4e0a-bb03-38e37febbd2c"
        }
    ],
    "active": false,
    "type": [
        {
        "coding": [
            {
            "system": "http://ehelse.no/fhir/CodeSystem/sfm-type-of-organization",
            "code": "3",
            "display": "Fastlege"
            }
        ]
        }
    ],
    "name": "Kolåsbakkane legekontor",
    "telecom": [
        {
        "system": "phone",
        "value": "12345678",
        "use": "work"
        }
    ],
    "address": [
        {
        "use": "work",
        "type": "physical",
        "text": "Testaddress",
        "line": [
            "Testveien 1"
        ],
        "city": "Oslo",
        "postalCode": "1234"
        }
    ]
    }

The corresponding token used contains SFM-id and organization ID (orgnr_parent corresponding to Identifier [ENH]):

    {
    "iss": "https://helseid-sts.test.nhn.no",
    "nbf": 1716470965,
    "iat": 1716470965,
    "exp": 1716471565,
    "aud": "e-helse:sfm.api",
    "scope": [
        "openid",
        "profile",
        "helseid://scopes/identity/pid",
        "helseid://scopes/identity/security_level",
        "helseid://scopes/hpr/hpr_number",
        "helseid://scopes/identity/assurance_level",
        "e-helse:sfm.api/sfm.api"
    ],
    "amr": [
        "pwd"
    ],
    "client_id": "dc7ce5b5-670a-40f8-bd64-801e408b7069",
    "client_amr": "private_key_jwt",
    "helseid://claims/client/claims/orgnr_parent": "917897468",
    "sub": "tzto6gPhyTQw2bR/Wl0kgF/mTH+jdQoUBvaYSObfmlQ=",
    "auth_time": 1716470964,
    "idp": "testidp-oidc",
    "helseid://claims/identity/pid": "17056600574",
    "helseid://claims/identity/security_level": "4",
    "helseid://claims/identity/assurance_level": "high",
    "helseid://claims/hpr/hpr_number": "431001110",
    "oldsub": "gD6VTyxDgGoCCqOBFCuxuykX7tXL1jiWy0Zg9L0f96I=",
    "helseid://claims/client/amr": "rsa_private_key",
    "e-helse:sfm.api/client/claims/sfm-id": "a99abfb4-2bea-4e0a-bb03-38e37febbd2c",
    "helseid://claims/client/client_tenancy": "single-tenant",
    "sid": "150C9C961CBBF4F67138FA317E2B1C8D",
    "jti": "FC0B6D1EFB47D09A7B62A653B0469174"
    }

This operation takes some time as a new database schema is created, on success SFM replies a payload with an ID of the newly created Organization instance and http status 201 Created. The Organization returned now contains ID for further API access.

Person, the superuser

Behind the scenes SFM also creates the minimal superuser represented by the line: "helseid://claims/identity/pid": "17056600574" in the token. Next natural step is to update this Person resource with proper name:

Do a GET to the ./Person endpoint and receive a search bundle containing one single person object:

    {
    "resourceType": "Bundle",
    "id": "8fd540ca-4e21-4a89-8d40-b8c3cd2598a6",
    "meta": {
        "lastUpdated": "2024-05-23T13:47:42.6275835+00:00"
    },
    "type": "searchset",
    "total": 1,
    "link": [
        {
        "relation": "self",
        "url": "http://base-fhir.test2.forskrivning.no/Person?_count=100&_format=json"
        }
    ],
    "entry": [
        {
        "fullUrl": "http://base-fhir.test2.forskrivning.no/Person/5a7d3824-11ac-4826-89b7-ddfdc9918bff",
        "resource": {
            "resourceType": "Person",
            "id": "5a7d3824-11ac-4826-89b7-ddfdc9918bff",
            "meta": {
            "lastUpdated": "2024-05-23T15:35:03.7386838+02:00",
            "profile": [
                "http://ehelse.no/fhir/StructureDefinition/sfm-Person"
            ]
            },
            "identifier": [
            {
                "use": "official",
                "system": "urn:oid:2.16.578.1.12.4.1.4.1",
                "value": "17056600574"
            }
            ],
            "active": true
        },
        "search": {
            "mode": "include"
        }
        }
    ]
    }

It is now possible to read the particular Person item by GET to endpoint ./Person/5a7d3824-11ac-4826-89b7-ddfdc9918bff

    {
    "resourceType": "Person",
    "id": "5a7d3824-11ac-4826-89b7-ddfdc9918bff",
    "meta": {
        "versionId": "1",
        "lastUpdated": "2024-05-23T15:35:03.7386838+02:00",
        "profile": [
        "http://ehelse.no/fhir/StructureDefinition/sfm-Person"
        ]
    },
    "identifier": [
        {
        "use": "official",
        "system": "urn:oid:2.16.578.1.12.4.1.4.1",
        "value": "17056600574"
        }
    ],
    "active": true
    }

This resource may now be updated with name and other properties by a PUT operation to Person endpoint with the id:
./Person/8fd540ca-4e21-4a89-8d40-b8c3cd2598a6

    {
    "resourceType": "Person",
    "id": "5a7d3824-11ac-4826-89b7-ddfdc9918bff",
    "meta": {
        "versionId": "1",
        "lastUpdated": "2024-05-23T15:35:03.7386838+02:00",
        "profile": [
        "http://ehelse.no/fhir/StructureDefinition/sfm-Person"
        ]
    },
    "identifier": [
        {
        "use": "official",
        "system": "urn:oid:2.16.578.1.12.4.1.4.1",
        "value": "17056600574"
        }
    ],
    "name": [
        {
        "extension": [
            {
            "url": "http://hl7.no/fhir/StructureDefinition/no-basis-middlename",
            "valueString": "D"
            }
        ],
        "family": "Didrikson",
        "given": [
            "Didrik"
        ]
        }
    ],
    "gender": "male",
    "birthDate": "1966-05-17",
    "address": [
        {
        "use": "work",
        "type": "physical",
        "line": [
            "Testveien 1"
        ],
        "city": "Oslo",
        "postalCode": "1234"
        }
    ],

    "active": true
    }

SFM will respond http status 200

To allow other users into this instance of SFM, the superuser may now use HelseID to create other superusers, and Practitioners.

Practitioner - the healtcare user

Lets say that this superuser also is a doctor in this instance, a practitoner may be created:

    {
    "resourceType": "Practitioner",
    "meta": {
        "versionId": "1",
        "lastUpdated": "2024-05-23T15:58:11.8597674+02:00",
        "profile": [
        "http://ehelse.no/fhir/StructureDefinition/sfm-Practitioner"
        ]
    },
    "identifier": [
        {
        "use": "official",
        "system": "urn:oid:2.16.578.1.12.4.1.4.1",
        "value": "17056600574"
        }
    ],
    "active": true,
    "name": [
        {
        "extension": [
            {
            "url": "http://hl7.no/fhir/StructureDefinition/no-basis-middlename",
            "valueString": "D"
            }
        ],
        "family": "Dirdrikson",
        "given": [
            "Didrik"
        ]
        }
    ],
    "address": [
        {
        "use": "work",
        "type": "physical",
        "line": [
            "Testveien 1"
        ],
        "city": "Oslo",
        "postalCode": "1234"
        }
    ],
    "gender": "male",
    "birthDate": "1966-05-17"
    }

SFM responds http 201 Created and the new resource as a Practitioner.

To illustrate the differences between single and multi tenancy, we now simumlate that the vendor for this office stars using multi tenancy client system in HelseID. SFM will only allow known "suppliers", and the vendor must contact sfm enable this in TEST. For production there will be formal processes taking care of this. For clients/vendors using HelseID on behalf of their customer, a delegation from customer to vendor exist in Altinn. For test the delegation is simulated by "Tenants" in HelseID self service. When everything is properly set up, the vendor may reuse the SFM-id from the singe client as journal-id in multi tenant for continued access to the SFM instance.

Here is an example of the multi tenancy token that provides access to the instance created above: (note that SFM-id have no meaning in this case)

    {
    "iss": "https://helseid-sts.test.nhn.no",
    "nbf": 1716473563,
    "iat": 1716473563,
    "exp": 1716477163,
    "aud": "e-helse:sfm.api",
    "scope": [
        "openid",
        "profile",
        "helseid://scopes/identity/pid",
        "helseid://scopes/identity/security_level",
        "helseid://scopes/hpr/hpr_number",
        "helseid://scopes/identity/assurance_level",
        "e-helse:sfm.api/sfm.api"
    ],
    "amr": [
        "pwd"
    ],
    "client_id": "8cd7c619-92db-4d55-89e2-383b75efc758",
    "client_amr": "private_key_jwt",
    "helseid://claims/client/claims/orgnr_parent": "917897468",
    "nhn:sfm:journal-id": "a99abfb4-2bea-4e0a-bb03-38e37febbd2c",
    "sub": "tzto6gPhyTQw2bR/Wl0kgF/mTH+jdQoUBvaYSObfmlQ=",
    "auth_time": 1716473563,
    "idp": "testidp-oidc",
    "helseid://claims/identity/pid": "17056600574",
    "helseid://claims/identity/security_level": "4",
    "helseid://claims/identity/assurance_level": "high",
    "helseid://claims/hpr/hpr_number": "431001110",
    "oldsub": "n57qJQXiVg8sRZRurRDMKiIm6LnWrSzENEcmOgYL/MI=",
    "helseid://claims/client/amr": "rsa_private_key",
    "helseid://claims/client/claims/orgnr_supplier": "994598759",
    "e-helse:sfm.api/client/claims/sfm-id": "ce75db36-c57b-4592-9d47-5dfae8a34340",
    "helseid://claims/client/client_tenancy": "multi-tenant",
    "sid": "9E10C7DFEDC83C399DDBCD03B0907DBF",
    "jti": "6745AAAE3691417B0139C645BA37F7F6"
    }

Further processes

For SFM Basis use, the last step is to update the Organization with active=true. SFM then reports the organization to e-resept by the key HER-id.

For SFM Full use, the next steps will be to migrate necessary personell and patient data to SFM by using the migration API before updating Organization to active=true.

Note on Practitioner in SFM Basis

In SFM basis there is an option to apply for a special automatic sync to Helsepersonellregisteret, where SFM automatically retreives necessary information on the Practitioners by looking up the pid in the token for new/unknown users. This gives a slighly looser access control, and must be agreed between vendor, customer and SFM.