---
title: "Integration with Prorenata Journal through the REST API"
canonical: "https://docs.prorenata.se/space/MAN/2150072431/Integration+with+Prorenata+Journal+through+the+REST+API"
format: markdown
---
# Background

Prorenata Journal provides a full REST API for all functionality the system includes. The API is the primary integration for all user interaction, including Prorenata’s own frontend applications.

Prorenata’s API is based on REST principles with some added RPC-style endpoints. Authentication is handled through API-tokens (shared secret) connected to specific API-users.

More information about the API can be found at [https://journal.prorenata.se/api/docs/](https://journal.prorenata.se/api/docs/)

# Authentication

Each request is authenticated using the http header `Authorization` with the word `Token`, a space and your API token. This is an example of the content of the `Authorization` header:

`Token 9944b09199c62bcf9418ad846dd0e4bbdfc6ee4b`

 If you haven't received an API token, please reach out to [Prorenata Support](https://journal.prorenata.se/apps/support/).

# API Calls

The API supports three main kinds of API endpoints, single items, lists and actions.

## Single items

Single items are accessed on urls like `/api/v2/base/user/{id}/`where `{id}` is the id of the item. This endpoint accepts GET, PUT and DELETE, performing the actions of retrieving, updating or deleting the item.

### GET

Returns a json representation of the item and HTTP 200 when successful, returns HTTP 404 if no such item exists that you have access to.

### PUT

Accepts a json-formatted full representation of the item. Returns an HTTP 200 and the updated json representation of the item if successful. Returns HTTP 400 and json formatted error message if the validation fails.

### DELETE

Deletes the object, returns an empty response

### Response format

GET and PUT requests receive a full json representation of the item as the response, always including the `id` key. Relations to other models are expressed as a single integer id or a list of ids. 

#### Example

```json
{
  "id": 25,
  "first_name": "Teste",
  "last_name": "Testsson",
  "organization": 12,
  "friends": [10,11,12,28]
}
```

## Lists of items

Lists of items are accessed on urls like `/api/v2/base/user/`. 

### GET

Returns a json formatted response with a list of the objects and meta data from the selection. Se Response format. The list can be limited, filtered and ordered using query parameters in the url, see Limiting, Filtering and Ordering

### POST

Accepts a json representation of the object to be created, without the id parameter. The response will contain a json representation of the created object with the given id. 

### Response format

The list endpoints return a json object using the following keys:

- `objects` - an array of full json representation of the returned objects
- `total` - the total number of objects found in the database using the query
- `limit` - the maximum number of objects returned in this response
- `start_index` - the index of the first returned object among the total objects
- `end_index` - the index of the last returned object among the total objects
- `page` - If `limit` is less than `total` the response will be paginated and this is the number of the current page
- `previous` - If paginated, this is the number of the precious page, if any
- `next` - If paginated, this is the number of the next page, if any

#### Example

```json
{
  "objects":[
    {
      "id": 25,
      "first_name": "Teste",
      "last_name": "Testsson",
      "organization": 12,
      "friends": [10,11,12,28]
    },
    {
      "id": 28,
      "first_name": "Testina",
      "last_name": "Testsson",
      "organization": 12,
      "friends": [25]
    }
  ],
  "total": 240,
  "limit": 2,
  "start_index": 25,
  "end_index": 28,
  "page": 1,
  "previous": null,
  "next": 2
}

```

### Limiting

The response can be limited (for instance for performance reasons) using the special `_limit` request parameter with an integer as value

`curl -X GET "https://sandbox.test.prorenata.se/api/v2/base/user/?_limit=20" -H "Authorization: $TOKEN"`

### Filtering

All list endpoints support filtering on the attributes of the listed model. Filtering is done using a subset of the Django query filtering language in the request parameters with the filtering field and lookup keyword as the key and the value as the value of the request parameter. Basic filtering can look like this:

`curl -X GET "https://sandbox.test.prorenata.se/api/v2/base/user/?first_name=Test" -H "Authorization: $TOKEN"`

Multiple filters can be applied to a single request and are logically combined using AND

`curl -X GET "https://sandbox.test.prorenata.se/api/v2/base/user/?first_name=Test&last_name=Testsson" -H "Authorization: $TOKEN"`

Some filter values are expressed in specific ways:

- Booleans are expressed as integers, 1=True, 0=False
- Multiple values are expressed as comma-separated lists

Filters can have lookups, such as _contains_, _greater than_, _lesser than_, etc. A lookup is added to a filter using double underscores `__`. A basic use of the lookup `contains` could look like this:

`curl -X GET "https://sandbox.test.prorenata.se/api/v2/base/user/?first_name__contains=Te" -H "Authorization: $TOKEN"`

The following filter lookups are supported (support might be limited to certain field types)

- `gt` - Greater than
- `gte` - Greater than or equal
- `lt` - Lesser than
- `lte` - Lesser than or equal
- `contains` - case sensitive check if the field contains the value as text
- `icontains` - case insensitive check if the field contains the value as text
- `startswith` - case sensitive check if the field starts with the value as text
- `istartswith` - case insensitive check if the field starts with the value as text
- `isnull` - check if the value is null or not (use 1 for True and 0 for False)
- `in` - check if value is within a given list of values, the list should be comma delimited. Typically used to retrieve multiple items in one go using for example `id__in=1,2,5,7,12`.

Filters can also span relationships using the same double underscore notation, example:

`curl -X GET "https://sandbox.test.prorenata.se/api/v2/base/user/?profile__organization__name=Testorganization" -H "Authorization: $TOKEN"`

### Ordering

The response can be ordered using the special `_ordering` request parameter with the field to order on as value. The ordering is ascending by default, but can be descending by prepending a minus sign. Multiple orderings can be added in the same `_ordering` parameter by separating them with the space character (%20 in url escaped strings). Ordering can span relationships with the double underscore notation.

`curl -X GET "https://sandbox.test.prorenata.se/api/v2/base/user/?_ordering=first_name%20last_name" -H "Authorization: $TOKEN"`

## Remote actions

Certain endpoints also support remote actions. These are remote procedure call style invocations performed on a single item. For example, to sign a journal entry, you invoke the `/sign/` action on the entry, like this:

`curl -X POST "https://sandbox.test.prorenata.se/api/v2/patients/journalentry/25/sign/" -H "Authorization: $TOKEN"`

Remote actions are typically invoked using POST. Some remote actions take json-formatted parameters as part of the request. See documentation for specific remote actions, as their behavior may vary.

##   
Return codes

The table below describes code, description and when used.

| **Code** | **Description** | **Used when** |
| --- | --- | --- |
| HTTP 200 | OK | Returned after a successful GET or PUT, with the full json representation of the created item |
| HTTP 201 | Created | Returned after a successful POST, with the full json representation of the created item |
| HTTP 204 | No content | Returned after a successful DELETE |
| HTTP 400 | Bad request | Returned after a PUT or POST where the validation of the content failed. Returns a json representation of the error |
| HTTP 401 | Unauthorized | Returned when not logged in or authentication failed |
| HTTP 403 | Forbidden | Returned when trying to perform an action on an object that the user can access but where that particular action is forbidden. For example if trying to PUT to an item where the user only has read access. |
| HTTP 404 | Not found | Returned when trying to retrieve a single item and no item exists that the user has access to |
| HTTP 405 | Method not allowed | The method is not supported on the endpoint, for instance, some endpoints are read only. |
| HTTP 500 | Server error | Returned if the request led to a server error. No details of the server error is given, but the error is logged. |

## Error messages

When validation fails on a PUT or POST, an HTTP 400 response is returned with a json formatted set of error descriptions. The error response has one key `error` that holds an array of generic error messages as strings relating to the request as a whole or multiple fields together and one key `field_errors` that holds one key per field with errors related to that specific field and each field has an array of error messages as strings.

### Example

```json
{
  "errors": ["If a first_name is given, require_first_name cannot be null"],
  "field_errors": {
    "first_name": ["This field cannot be null"]
  }
}
```

# Common scenarios

## Creating a patient

> ℹ️ I want to create a patient with contact information

`curl -X POST "https://sandbox.test.prorenata.se/api/v2/patients/patient/" --data '{...}'  -H "Authorization: Token $TOKEN"`

For data, see [https://journal.prorenata.se/api/docs/](https://journal.prorenata.se/api/docs/) - `/api/v2/patients/patient/`

Note that you can add contact info directly in the POST, but that info is write-only and is stored and returned as separate objects in the response.

## Reading the journal entries of a patient with a specific personal id

> ℹ️ I want to read all journal entries on a patient with a specific personal id

`curl -X GET "https://sandbox.test.prorenata.se/api/v2/patients/journalentry/?admission__patient__personal_id=201212121212"  -H "Authorization: Token $TOKEN"  `

## Creating and updating a journal entry for a patient with a specific personal id

> ℹ️ I have content that I want to upload as a journal entry connected to a patient

This is a common and reasonably straight forward ask of the API, but due to how journal entries work and the flexibilities of the data models, it is a multi step process requiring multiple API calls.

### Retrieving the patient

First you need a reference to the patient object that the entry should refer to, To get patients with a specific personal id, you can filter on the personal id in the list API.

`curl -X GET "https://sandbox.test.prorenata.se/api/v2/patients/patient/?personal_id=201212121212"  -H "Authorization: Token $TOKEN"`

This might return multiple patient objects if you have multiple organization units, as patients can exists in multiple organization units in the organization. In that case, you need to decide what patient object to use.

### Retrieving the admission

When you create the journal entry you need a reference to an admission. An admission is in this context a specific journal that the entry should exist in. Admissions are created automatically for patients, representing the different health care unit types of the organization.

You retrieve the admission to use for a patient by fetching the admissions of the patient using the following (for patient with id 25 and health care unit type 13):

`curl -X POST "https://sandbox.test.prorenata.se/api/v2/patients/admission/?patient=25€health_care_unit__type=25" --data '{...}'  -H "Authorization: Token $TOKEN"`

As this is a list, you will get a list response, but by definition, the list should only include one admission.

### Creating the entry

`curl -X POST "https://sandbox.test.prorenata.se/api/v2/patients/journalentry/" --data '{...}'  -H "Authorization: Token $TOKEN"`

For data content, see [https://journal.prorenata.se/api/docs/](https://journal.prorenata.se/api/docs/) - `/api/v2/patients/journalentry/`

When creating a journal entry, you may choose to base it on a template. If you do, journal entry rows will be automatically created for you. You create an entry based on a template by setting the `template` field to the id of the template and setting the `create_rows` field to `true`

### Acquiring a lock for the entry

When updating a journal entry, you need to first acquire a lock on the entry to stop anyone else from updating it. You do this by using the remote action  `acquire_lock` (it takes an empty POST). 

`curl -X POST "https://sandbox.test.prorenata.se/api/v2/patients/journalentry/25/acquire_lock/"  -H "Authorization: Token $TOKEN"`

### Updating the entry with information

The response from the previous call to create the journal entry will include rows with id:s in the `rows` key of the entry. You can then update the rows of the entry individually by performing PUT operations on the individual row endpoints.

`curl -X PUT "https://sandbox.test.prorenata.se/api/v2/patients/journalentryrow/38/" --data '{...}'  -H "Authorization: Token $TOKEN"`

`curl -X PUT "https://sandbox.test.prorenata.se/api/v2/patients/journalentryrow/39/" --data '{...}'  -H "Authorization: Token $TOKEN"`

Data for journalentryrow can be found here [https://journal.prorenata.se/api/docs/](https://journal.prorenata.se/api/docs/)- `/api/v2/patients/journalentryrow/{id}/`

Specifically you need to fill the `data`field with reasonable values (it will be validated). What reasonable values are depends on the value of the `row_type` field (see below under JournalEntryRow data content).

### Acquiring a lock for the entry

When you are done updating, you release the lock using a POST towards `release_lock`

`curl -X POST "https://sandbox.test.prorenata.se/api/v2/patients/journalentry/25/release_lock/"  -H "Authorization: Token $TOKEN"`

### Signing the entry

You can then sign the entry using the remote action `sign`

`curl -X POST "https://sandbox.test.prorenata.se/api/v2/patients/journalentry/25/sign/"  -H "Authorization: Token $TOKEN"`

After the entry is signed, it can no longer be modified and neither can its rows.

## JournalEntryRow `data` content

The JournalEntryRow model has a `data` field that is by default an empty JSON document. This is used to hold the data of the journal entry row. The format of the json document depends on the `row_type`attribute of the JorunalEntryRow, but generally it is a JSON document with a single `value` key. These are some common `data` formats.

| **Row type** | **Description** | **example** |
| --- | --- | --- |
| `CHAR` | Short text with no markup | ```json
{
  "value": "Lorem ipsum"
}
``` |
| `TEXT` | Long text with html markup (will be cleaned for XSS prevention) | ```json
{
  "value": "<strong>Lorem</strong> ipsum"
}
``` |
| `NMBR` | Single integer number | ```json
{
  "value": 25
}
``` |
| `BOOL` | A single, boolean value | ```json
{
  "value": true
}
``` |
| `DATE` | ISO-formatted date string (without TZ-info, assumed to be Stockholm time) | ```json
{
  "value": "2021-11-30T12:33:35"
}
``` |
| `MULT` | Multiple choice select one, the data contains the single string representing the chosen option | ```json
{
  "value": "Lorem ipsum"
}
``` |
| `MULM` | Multiple choice select multiple, the data contains an array of strings representing the chosen options | ```json
{
  "value": ["Lorem, "ipsum"]
}
``` |

There are several other, more complex row types for vaccinations, audiometry, etc. To get more information on those row types, please contact [Prorenata support](https://journal.prorenata.se/apps/support/). 

## Transferring a patient to another unit

> ℹ️ I want to transfer a patient to another unit

Moving a patient from a unit to another is a three step process that requires the creation of a transfer object.

First create the transfer object:  
`curl -X POST "https://sandbox.test.prorenata.se/api/v2/patients/patienttransfer/"`  
`--data '{"created_by": <userid>, "organization": <orgid>,  "patient": <patientid>,  "to_organization_unit": <unitid>,  "to_school_class": null,  "merge_if_conflict": false}' -H "Authorization: Token $TOKEN"`

Then validate the transfer by calling the validate endpoint of the created transfer object:  
`curl -X POST "https://sandbox.test.prorenata.se/api/v2/patients/patienttransfer/<id>/validate/"`  
` -H "Authorization: Token $TOKEN" `

If the validation passes the transfer can be executed:  
`curl -X POST `  
`"https://sandbox.test.prorenata.se/api/v2/patients/patienttransfer/<id>/execute/"`  
`-H "Authorization: Token $TOKEN"`  
Note that the execution of the transfer runs as a background job and the server always returns “OK” after passing the authorization checks. For actually capturing any eventual errors in the transfer it is required to re-fetch the object at a later time.