# Reports

After a user completes a measurement or when the prescription period ends, the user and physician receive (periodic) reports with results and insights into the measurement(s).

## Request a measurement report and render the PDF

### SDK

The `getMeasurementReportUrl` method accepts a `measurementId` and handles the creation and fetching of the report.

* The first time you execute this function for a measurement, it will take a little longer. The cloud service will render the report synchronously. Once it's ready (\~5s) a URL will be returned. The report is available at this URL.
* Subsequent calls will be much faster, as the report is already rendered and the URL will be returned almost instantly.
* The PDF will always be rendered in the user's language. This is the language that was specified during the user's registration process. Currently, the supported languages are: `de`, `en`, `es`, `fr`, `it`, `nl`, `ar` and `zh`. When other languages are provided, the report will fall back to the default language `en`.

{% tabs %}
{% tab title="Flutter" %}
This functionality works great in combination with [url\_launcher](https://pub.dev/packages/url_launcher).

```dart
import 'package:url_launcher/url_launcher.dart';
import 'package:flutter_fibricheck_sdk/flutter_fibricheck_sdk.dart';

_reportUrl = await _sdk.getMeasurementReportUrl(widget.measurement.id!);

Future<void> _launchUrl() async {
    final url = Platform.isAndroid ? "https://docs.google.com/viewer?url=$reportUrl" : reportUrl;
    if (await canLaunchUrl(Uri.parse(url))) {
      if (!await launchUrl(Uri.parse(url))) {
        throw 'Could not launch $reportUrl';
      }
    }
  }
```

{% endtab %}

{% tab title="React Native" %}
This functionality works great in combination with `react-native-pdf` or `react-native-share`.

```typescript
import Pdf from 'react-native-pdf';

const measurementId = '0000';

const App = () => {
  const [uri, setUri] = useState();

  useEffect(() => {
    (async () => {
      const uri = await sdk.getReportUrl(measurementId);
      setUri(uri);
    })();
  }, []);

  return (
    <Pdf
      source={{
        uri,
      }}
    />
  );
};  
```

{% endtab %}
{% endtabs %}

### REST API

Rendering a PDF report using the REST API takes 3 simple steps.\
The first step is only needed when no report has been created yet.

#### Step 1 • Generate a report

## Generate a new report

<mark style="color:green;">`POST`</mark> `https://api.fibricheck.com/data/v1/measurement-reports/documents`

{% tabs %}
{% tab title="200: OK " %}

```javascript
{
    "query": "{\"$and\":[{\"data.measurementId\":{\"$eq\":\"63ee4771e8c20b1bfb1bf617\"}},{\"$or\":[{\"$and\":[{\"userIds\":{\"$eq\":\"5811c7a046e0fb000530a465\"}}]},{\"$and\":[{\"groupIds\":{\"$in\":[\"5919759152faff000545b18c\"]}}]}]}]}",
    "page": {
        "total": 1,
        "offset": 0,
        "limit": 1
    },
    "data": [
        {
            "id": "63ee47a8e8c20b8ab31bfbeb",
            "groupIds": [],
            "userIds": [
                "5811c7a046e0fb000530a465"
            ],
            "creatorId": "5811c7a046e0fb000530a465",
            "status": "rendered",
            "statusChangedTimestamp": "2023-02-16T15:11:40.246Z",
            "data": {
                "measurementId": "63ee4771e8c20b1bfb1bf617",
                "language": "EN",
                "forMeasurementUpdatedTimestamp": 1676560280650,
                "readFileToken": "63ee47ac7e2b7133cf59c983-5ec781dc-1616-4793-8dd7-31dfa764d947"
            },
            "updateTimestamp": "2023-02-16T15:11:40.250Z",
            "creationTimestamp": "2023-02-16T15:11:36.698Z"
        }
    ]
}
```

{% endtab %}
{% endtabs %}

This API call should be executed with the following body to trigger a report creation:

```javascript
{
    "measurementId" : "{measurementId}"
    "language": "EN"
}
```

* &#x20;`measurementId` identifies the measurement for which you want to generate a report.
* `language` defines the language in which the report will be generated. It is advised to use the user's set language.

{% hint style="info" %}
The report is generated in the timezone of the user that performed the measurement. Once a report is generated, it's not possible to change the timezone anymore. To change the timezone of the report, you have to change the timezone of the user.
{% endhint %}

{% hint style="warning" %}
To generate a report for a measurement, make sure that the measurement [status](https://docs.fibricheck.com/introduction/measurements#status) is set to`analyzed, pending-review` or `reviewed`
{% endhint %}

#### Step 2 • Fetch the report file token

Using the `measurementId` from the measurement, execute the API call below. This will return the latest generated report.&#x20;

## Fetch report details

<mark style="color:blue;">`GET`</mark> `https://api.fibricheck.com/data/v1/measurement-reports/documents?limit(1)&sort(-id)&eq(data.measurementId,{measurementId})`

#### Query Parameters

| Name          | Type | Description |
| ------------- | ---- | ----------- |
| measurementId |      |             |

{% tabs %}
{% tab title="200: OK " %}

```javascript
{
    "query": "{\"$and\":[{\"data.measurementId\":{\"$eq\":\"63ee4771e8c20b1bfb1bf617\"}},{\"$or\":[{\"$and\":[{\"userIds\":{\"$eq\":\"5811c7a046e0fb000530a465\"}}]},{\"$and\":[{\"groupIds\":{\"$in\":[\"5919759152faff000545b18c\"]}}]}]}]}",
    "page": {
        "total": 1,
        "offset": 0,
        "limit": 1
    },
    "data": [
        {
            "id": "63ee47a8e8c20b8ab31bfbeb",
            "groupIds": [],
            "userIds": [
                "5811c7a046e0fb000530a465"
            ],
            "creatorId": "5811c7a046e0fb000530a465",
            "status": "rendered",
            "statusChangedTimestamp": "2023-02-16T15:11:40.246Z",
            "data": {
                "measurementId": "63ee4771e8c20b1bfb1bf617",
                "language": "EN",
                "forMeasurementUpdatedTimestamp": 1676560280650,
                "readFileToken": "63ee47ac7e2b7133cf59c983-5ec781dc-1616-4793-8dd7-31dfa764d947"
            },
            "updateTimestamp": "2023-02-16T15:11:40.250Z",
            "creationTimestamp": "2023-02-16T15:11:36.698Z"
        }
    ]
}
```

{% endtab %}
{% endtabs %}

{% hint style="info" %}
**Best Practice**

We recommend to compare `data.forMeasurementUpdatedTimestamp` from the report with value with the `updateTimestamp` from the measurement. \
If the measurement timestamp is later than the report timestamp, a new report should be generated (see step 1) because the measurement data has been updated.&#x20;
{% endhint %}

If `data.status` is set to `rendered`, the PDF report is available for downloading.&#x20;

#### Step 3 • Fetch the PDF report URL

Using `data.readFileToken`  from step 2 you can construct the URL at which the PDF is available:

```
https://api.fibricheck.com/files/v1/{readFileToken}/file
```

This endpoint is publicly available.&#x20;

## Request periodic reports

Periodic reports are generated automatically on predetermined timeframes. This can be manual, 7 days, 30 days or at the end of a prescription.

{% hint style="warning" %}
**Note that B2C Essential users will not receive periodic reports!**
{% endhint %}

### SDK

The `getPeriodicReports` method returns a paginated result with all periodic reports for the authenticated user. You can find the measurements from that period in the `data.measurements` property. You can also use the `next` and `previous` methods available on the result to navigate through the user's measurements.

In periodic reports, the `trigger` field indicates for which period the report was made. This can be 7 days, 30 days or at the end of a prescription.

The `getPeriodicReportPdf` method retrieves a PDF version of the report. This method takes a `reportId` as a parameter. The PDF is rendered in the user's language.

{% tabs %}
{% tab title="Flutter" %}

```dart
import 'package:flutter_fibricheck_sdk/flutter_fibricheck_sdk.dart';

_sdk.getPeriodicReports(true); // true -> get newest reports first
await res.getNextPagedPeriodicReportsResult(); // get next 20 reports
await res.getPreviousPagedPeriodicReportsResult(); // get previous 20 reports


// To request a specific report in PDF format, use the following method 
await _sdk.getPeriodicReportPdf(reportId);
```

If you save the PDF you could render it in the app with a package such as <https://pub.dev/packages/pdf_render>
{% endtab %}

{% tab title="React Native" %}
The method is a [generator function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function*) that returns an [iterator](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Iterators_and_Generators). This iterator can be called with `.next()` to retrieve the next 20 reports. Another way to do this is by using the for await construction, as seen in the example.

```typescript
import client from '@fibricheck/javascript-sdk';

interface PeriodicReport {
  id: string;
  status: string;
  trigger: 'PERIOD_DAYS_PASSED_7' | 'PERIOD_DAYS_PASSED_30' | 'PRESCRIPTION_ENDED'; 
  creationTimestamp: number;
}

const sdk = client({
  consumerKey: '',
  consumerSecret: '',
});

await sdk.authenticate({
  token: '',
  tokenSecret: '',
});

const reportsIterator = await sdk.getPeriodicReports();

for await (const reportsPage of reportsIterator) {
  ... /* PagedResult<PeriodReport> */
}
```

Here's an example of how to convert the response to a PDF using [react-native-share](https://github.com/react-native-share/react-native-share):

```typescript
import client from '@fibricheck/javascript-sdk';
import Share from 'react-native-share';

const sdk = client({
  consumerKey: '',
  consumerSecret: '',
});

await sdk.authenticate({
  token: '',
  tokenSecret: '',
});

const report = await sdk.getPeriodicReportPdf('62441ce00000000000000000');
const base64 = Buffer.from(file.data, 'binary').toString('base64');
const file = `data:application/pdf;base64,${base64}`;
const filename = file.headers['content-disposition'].split('filename="')[1].split('.pdf"')[0];

await Share.open({
  title: filename,
  type: 'application/pdf',
  filename: filename,
  url: file,
});
```

{% endtab %}
{% endtabs %}

### REST API

## Get periodic reports

<mark style="color:blue;">`GET`</mark> `https://api/reports/v1?sort(-creation_timestamp)&user_id={userId}`

This API call returns a list of periodic reports for a given user

#### Query Parameters

| Name   | Type | Description                                  |
| ------ | ---- | -------------------------------------------- |
| userId |      | The user for which you want to fetch reports |

{% tabs %}
{% tab title="200: OK " %}

```javascript
{
    "query": "{ {\"user_id\": {\"$oid\": \"5a2e547a46e0fb00053adfc2\"}, \"group_id\": {\"$in\": [{\"$oid\": \"5919759152faff000545b18c\"}]}}  }",
    "page": {
        "total": 9,
        "offset": 0,
        "limit": 20
    },
    "data": [
        {
            "id": "5bfaaef96522050007a622d7",
            "group_id": "5919759152faff000545b18c",
            "user_id": "5a2e547a46e0fb00053adfc2",
            "content": {
                "start_timestamp": 1540559595630,
                "end_timestamp": 1543151595630
            },
            "status": "COMPLETE",
            "trigger": "PERIOD_DAYS_PASSED_30",
            "tags": [
                "not_sent"
            ],
            "status_updated_timestamp": 1543156291414,
            "creation_timestamp": 1543155449711,
            "update_timestamp": 1543156291414
        },
        {
            "id": "5bd31a89e828860007cc9810",
            "group_id": "5919759152faff000545b18c",
            "user_id": "5a2e547a46e0fb00053adfc2",
            "content": {
                "start_timestamp": 1537967595630,
                "end_timestamp": 1540559595630,
                "measurements": [
                    {
                        "id": "5bd0766e1124bd47d1974a4b",
                        "visible": true
                    },
                    {
                        "id": "5bb5f4d9e2b0930b3657a57c",
                        "visible": true
                    }
                ]
            },
            "status": "COMPLETE",
            "trigger": "PERIOD_DAYS_PASSED_30",
            "tags": [
                "not_sent"
            ],
            "status_updated_timestamp": 1545127396954,
            "creation_timestamp": 1540561545640,
            "update_timestamp": 1545127396954
        },
        {
            "id": "5bb235c08970110006cebf23",
            "creator_id": "5a2e547a46e0fb00053adfc2",
            "group_id": "5919759152faff000545b18c",
            "user_id": "5a2e547a46e0fb00053adfc2",
            "content": {
                "start_timestamp": 1535813815911,
                "end_timestamp": 1538405815911
            },
            "status": "COMPLETE",
            "trigger": "MANUAL",
            "tags": [
                "not_sent"
            ],
            "share": {
                "hash": "dbfe970ce6f7a26b88829cb426e896a9e91f6ac0",
                "creation_timestamp": 1538477697487
            },
            "status_updated_timestamp": 1540291283308,
            "creation_timestamp": 1538405824344,
            "update_timestamp": 1540291283308
        },
        {
            "id": "5bb1f6398970110006cebf21",
            "creator_id": "5a2e547a46e0fb00053adfc2",
            "group_id": "5919759152faff000545b18c",
            "user_id": "5a2e547a46e0fb00053adfc2",
            "content": {
                "start_timestamp": 1535797540457,
                "end_timestamp": 1538389540457
            },
            "status": "COMPLETE",
            "trigger": "MANUAL",
            "tags": [
                "not_sent"
            ],
            "share": {
                "hash": "cd335c749bda079406bfc9c95f2c856369b3c052",
                "creation_timestamp": 1538477533308
            },
            "status_updated_timestamp": 1540291246981,
            "creation_timestamp": 1538389561544,
            "update_timestamp": 1540291246981
        },
        {
            "id": "5bab87ea8970110006cebcde",
            "group_id": "5919759152faff000545b18c",
            "user_id": "5a2e547a46e0fb00053adfc2",
            "content": {
                "start_timestamp": 1535375595630,
                "end_timestamp": 1537967595630,
                "measurements": [
                    {
                        "id": "5ba6856a5599f28d1dcce22b",
                        "visible": true
                    },
                    {
                        "id": "5b97d40121559987acfcb869",
                        "visible": true
                    },
                    {
                        "id": "5b8c2ad753aaa05217b6ae6c",
                        "visible": true
                    }
                ]
            },
            "status": "COMPLETE",
            "trigger": "PERIOD_DAYS_PASSED_30",
            "tags": [
                "not_sent"
            ],
            "status_updated_timestamp": 1540287449719,
            "creation_timestamp": 1537968106659,
            "update_timestamp": 1540287449719
        },
        {
            "id": "5b83fd1c46e0fb0005738334",
            "group_id": "5919759152faff000545b18c",
            "user_id": "5a2e547a46e0fb00053adfc2",
            "content": {
                "start_timestamp": 1532783595630,
                "end_timestamp": 1535375595630,
                "measurements": [
                    {
                        "id": "5b65d05430fb89d5e674d101",
                        "visible": true
                    },
                    {
                        "id": "5b63740530fb894ab77492cf",
                        "visible": true
                    }
                ]
            },
            "status": "COMPLETE",
            "trigger": "PERIOD_DAYS_PASSED_30",
            "tags": [
                "not_sent"
            ],
            "status_updated_timestamp": 1540287219328,
            "creation_timestamp": 1535376668579,
            "update_timestamp": 1540287219328
        },
        {
            "id": "5b716e2046e0fb000573831a",
            "group_id": "5919759152faff000545b18c",
            "user_id": "5a2e547a46e0fb00053adfc2",
            "content": {
                "start_timestamp": 1530191595630,
                "end_timestamp": 1532783595630
            },
            "status": "COMPLETE",
            "trigger": "PERIOD_DAYS_PASSED_30",
            "tags": [
                "not_sent"
            ],
            "status_updated_timestamp": 1540287105514,
            "creation_timestamp": 1534160416628,
            "update_timestamp": 1540287105514
        },
        {
            "id": "5b34ebfa46e0fb00057382f2",
            "group_id": "5919759152faff000545b18c",
            "user_id": "5a2e547a46e0fb00053adfc2",
            "content": {
                "start_timestamp": 1527599595630,
                "end_timestamp": 1530191595630
            },
            "status": "COMPLETE",
            "trigger": "PERIOD_DAYS_PASSED_30",
            "tags": [
                "not_sent"
            ],
            "status_updated_timestamp": 1540286984442,
            "creation_timestamp": 1530194938634,
            "update_timestamp": 1540286984442
        },
        {
            "id": "5ae5cc1ec9e77c000533a3e2",
            "group_id": "5919759152faff000545b18c",
            "user_id": "5a2e547a46e0fb00053adfc2",
            "content": {
                "start_timestamp": 1522415595630,
                "end_timestamp": 1525007595630,
                "measurements": [
                    {
                        "id": "5abe90f94cedfd00056ea6ad",
                        "visible": true
                    },
                    {
                        "id": "5abe769e4cedfd00056ea6ac",
                        "visible": true
                    }
                ]
            },
            "status": "COMPLETE",
            "trigger": "PERIOD_DAYS_PASSED_30",
            "tags": [
                "not_sent"
            ],
            "status_updated_timestamp": 1540286639636,
            "creation_timestamp": 1525009438704,
            "update_timestamp": 1540286639636
        }
    ]
}
```

{% endtab %}
{% endtabs %}

To render a PDF version of the periodic report:

## Render periodic report

<mark style="color:blue;">`GET`</mark> `https://api.fibricheck.com/reports/v1/{reportId}/pdf?language={language}&time_zone={timeZone}`

This API call renders a PDF version of a periodic report.

#### Path Parameters

| Name                                       | Type   | Description                                              |
| ------------------------------------------ | ------ | -------------------------------------------------------- |
| reportId<mark style="color:red;">\*</mark> | String | The report for which a PDF version needs to be generated |

#### Query Parameters

| Name     | Type   | Description                                         |
| -------- | ------ | --------------------------------------------------- |
| language | String | The language in which te report should be generated |
| timeZone | String | The timezone in which te report should be generated |

{% tabs %}
{% tab title="200: OK PDF Report" %}

```javascript
{
    // Response
}
```

{% endtab %}
{% endtabs %}
