# eInnsyn This repository contains the API specification for [eInnsyn](https://einnsyn.no)'s API. The API is written in [TypeSpec](https://typespec.io), and the generated OpenAPI document is available at [openapi/einnsyn.openapi.yml](openapi/einnsyn.openapi.yml). The main files in the [typespec](typespec)-folder are: - [einnsyn.tsp](typespec/einnsyn.tsp): Entry point for the API, including service metadata and authentication. - [einnsyn.exceptions.tsp](typespec/einnsyn.exceptions.tsp): Shared exception and error response definitions. - [einnsyn.arkiv.models.tsp](typespec/einnsyn.arkiv.models.tsp): Model definition for archive data, mostly Noark 5 with some extensions for meetings. - [einnsyn.arkiv.operations.tsp](typespec/einnsyn.arkiv.operations.tsp): Endpoints for archive models. - [einnsyn.queryparameters.tsp](typespec/einnsyn.queryparameters.tsp): Base models for query parameters. - [einnsyn.responses.tsp](typespec/einnsyn.responses.tsp): Models for API responses. - [einnsyn.web.models.tsp](typespec/einnsyn.web.models.tsp): Models for entities that are mainly used for the eInnsyn website, not related to archive data. - [einnsyn.web.operations.tsp](typespec/einnsyn.web.operations.tsp): Endpoints for web models. ## Authentication The eInnsyn API uses API keys to authenticate requests. To send an authenticated request, include the API key in the `API-KEY` header: ```sh curl -H "API-KEY: " https://api.einnsyn.no ``` ## General endpoint structure Most routable resources expose standard CRUD endpoints: - `GET /{entityName}`: Get a paginated list of objects - `GET /{entityName}/{id}`: Get an object - `PATCH /{entityName}/{id}`: Update an object - `DELETE /{entityName}/{id}`: Delete an object Resources that do not require a parent object can usually be added directly at the root level using `POST /{entityName}`. Resources that require a parent are added through the parent resource, for example `POST /arkiv/{id}/arkivdel`. The API also includes task-specific endpoints such as `/search`, `/statistics`, and `/me`. ## Pagination List endpoints use cursor-based pagination. You can control page size with `limit` (between 1 and 100, default 25), use `startingAfter` to fetch the next page, and `endingBefore` to paginate backwards. List responses contain an `items` array and may include `next` and `previous` URLs: ```sh curl -H "API-KEY: " "https://api.einnsyn.no/journalpost?limit=2" { "items": [ { "entity": "Journalpost", "id": "jp_01jh532p3ve6haq7n53xgpqayh" }, { "entity": "Journalpost", "id": "jp_01jh532p6qfhxrz1w9fdw4jjrh" } ], "next": "https://api.einnsyn.no/journalpost?limit=2&startingAfter=jp_01jh532p6qfhxrz1w9fdw4jjrh", "previous": null } ``` If you pass `ids` or `externalIds`, the other list parameters are ignored. ## IDs All objects in eInnsyn get an auto-generated `eInnsynId`. An `eInnsynId` is a Base32-encoded UUID with a prefix that indicates the type of resource. In the API specification, each entity has an extension annotation describing its ID prefix. Example annotation for the Journalpost entity: `@extension("x-idPrefix", "jp")`. Example journalpost ID: `jp_01jh532p3ve6haq7n53xgpqayh` In addition, all Noark5 objects must have a globally unique systemId assigned by the publisher. This identifier can be used interchangeably with the eInnsynId in the API. ## Read-only and write-only fields Some fields are only available during certain lifecycle stages. In the TypeSpec source, this is expressed with `@visibility(...)`. - Read-only fields are returned by `GET` requests, but are not meant to be sent when creating or updating resources. - Write-only fields can be sent when creating or updating resources, but are omitted from `GET` responses. For example, `Saksmappe.saksnummer` and `Saksmappe.administrativEnhetObjekt` are read-only, while `Saksmappe.journalpost` is write-only. Because of that, `journalpost` is not returned by `GET /saksmappe/{id}` and cannot be expanded there. To read the journalposts for a case, use `GET /saksmappe/{id}/journalpost` instead. ## Expanding responses We use a concept called "expandable fields", inspired by Stripe's API ([Expanding Responses](https://docs.stripe.com/api/expanding_objects)). Throughout the API, references to entity objects are either an ID or the expanded object. On endpoints that support `expand`, nested objects in a `GET` response are sent as IDs by default. If you need nested objects, you can use the `expand` query parameter: ### Default expansion: ```sh curl -H "API-KEY: " https://api.einnsyn.no/journalpost/jp_01jh532p3ve6haq7n53xgpqayh { "entity": "Journalpost", "id": "jp_01jh532p3ve6haq7n53xgpqayh", ... "saksmappe": "sm_01jh50h5brf7wrbwga8xd0rwdy" } ``` ### Expand `saksmappe`: ```sh curl ... https://api.einnsyn.no/journalpost/jp_01jh532p3ve6haq7n53xgpqayh?expand=saksmappe { "entity": "Journalpost", "id": "jp_01jh532p3ve6haq7n53xgpqayh", ... "saksmappe": { "entity": "Saksmappe", "id": "sm_01jh50h5brf7wrbwga8xd0rwdy", "saksnummer": "2025/1234", ... "administrativEnhetObjekt": "enh_01jh532p50epvvcjfv8xrzzwp5" } } ``` ### Expand `saksmappe.administrativEnhetObjekt`: ```sh curl ... https://api.einnsyn.no/journalpost/jp_01jh532p3ve6haq7n53xgpqayh?expand=saksmappe.administrativEnhetObjekt { "entity": "Journalpost", "id": "jp_01jh532p3ve6haq7n53xgpqayh", ... "saksmappe": { "entity": "Saksmappe", "id": "sm_01jh50h5brf7wrbwga8xd0rwdy", "saksnummer": "2025/1234", ... "administrativEnhetObjekt": { "entity": "Enhet", "id": "enh_01jh532p50epvvcjfv8xrzzwp5", "navn": "Oslo kommune", ... } } } ``` ## Client libraries - Java SDK: [felleslosninger/einnsyn-sdk-java](https://github.com/felleslosninger/einnsyn-sdk-java) - TypeScript SDK: [felleslosninger/einnsyn-sdk-typescript](https://github.com/felleslosninger/einnsyn-sdk-typescript)