Prestaties upload¶
POST Upload a CSV file with prestaties (billing records of add-on medicines) to Pharma-Insights.
Institutions that use Pharma-Insights can deliver their billing records straight from their own systems (HIS, EHR, data warehouse). This is the API counterpart of the manual upload in Insights. It is a REST API with a single endpoint and a single action.
The file is validated on receipt and processed asynchronously. The response contains the per-row validation result; further processing (unit conversion, start-stop analysis, dashboards) happens in the background and is visible in the upload history in Insights.
Access
Available to institutions with a Pharma-Insights licence only. Request an API key via vragen@pharma-insights.nl. A test environment is not offered by default; contact us if you need one for your implementation.
Endpoint¶
Requests are POST requests with the CSV content as the raw body (no multipart upload, no
JSON). Other HTTP methods are rejected with 405.
File format¶
- No header row. A header row is reported as an invalid row and skipped.
- Delimiter:
;(recommended),,or tab. The character that occurs most often in the first line is used for the whole file. - Encoding UTF-8; a UTF-8 BOM is accepted.
- Empty lines are skipped.
- Use a single date format throughout the file.
YYYY-MM-DDis recommended. - Quantities are units (pieces) by default. If you deliver packages or the HiX purchase
quantity, say so with the
x-aantallen-inheader (see below).
The columns, in order:
| # | Column | Required | Notes |
|---|---|---|---|
| 1 | prestatie_id |
yes | Unique number of the billing record. Digits only, at most 18 digits. |
| 2 | patient_id |
yes | Pseudonymised patient identifier (text). Never a citizen service number or a name. |
| 3 | indicatie_id |
yes | G-Standaard indication id (file indicaties bij supplementaire producten). |
| 4 | agb_code |
yes | AGB code of the medical specialty, e.g. 313 (internal medicine) or 324 (rheumatology). Must exist in the NZa care typing (zorgtypering). |
| 5 | zindex_nummer |
yes | Z-Index number (8 digits) of an add-on product with a billing title. |
| 6 | aantal_eenheden |
yes | Quantity in the unit given by x-aantallen-in (units by default), non-zero. Decimal separator , or .. |
| 7 | uzovi_code |
yes | UZOVI code of the health insurer. |
| 8 | uitvoerings_datum |
yes | Date of administration/dispensing, YYYY-MM-DD. May not be in the future. |
| 9 | zorgtypering_code |
yes | NZa care typing component valid for the given agb_code. |
| 10 | opmerkingen |
no | Free text. |
| 11 | arts_code |
no | Free text, e.g. the prescriber's AGB code. |
| 12 | postcode |
no | Four digits of the patient's postal code, or empty. |
| 13 | muraliteit |
no | intramuraal (default) or extramuraal. |
Required columns must always be present; optional columns may be omitted (a row then has 9 columns) or left empty.
Authentication¶
The institution is identified by two headers. There is no HMAC and no IP whitelisting, so treat the API key as a secret.
| Header | Notes |
|---|---|
x-picode |
The PI-Code of your institution. |
x-apikey |
The API key issued to your institution. |
x-aantallen-in |
Optional. Unit of aantal_eenheden: stuk (default), verpakking or inkoophoeveelheid. See Unit of quantities. |
content-type |
text/csv |
Unit of quantities (x-aantallen-in)¶
Insights converts all quantities to packages. The x-aantallen-in header tells us which unit
your file uses; it applies to the whole file.
| Value | Meaning |
|---|---|
stuk (default) |
Number of counting units, e.g. tablets, vials or syringes. Divided by the package content from the G-Standaard. |
verpakking |
Number of packages. No conversion. |
inkoophoeveelheid |
Purchase quantity as in a HiX extract, where the package content of some products (e.g. oral solutions in ml) is defined differently. Divided by the purchase quantity from the G-Standaard. |
An unknown value yields a 400. The last unit used is remembered and preselected in the manual
upload in Insights.
Request¶
curl -X POST https://www.pharma-insights.nl/api/prestaties \
-H "x-picode: 871001" \
-H "x-apikey: <your-api-key>" \
-H "x-aantallen-in: stuk" \
-H "content-type: text/csv" \
--data-binary @prestaties.csv
Example prestaties.csv with the required columns only:
900000001;P-8f3a2c;1234;313;12118249;2;3311;2026-06-15;0
900000002;P-8f3a2c;1234;313;12118249;2;3311;2026-07-13;0
900000003;P-51be09;1234;324;15239876;1;7029;2026-07-14;0
With optional columns:
Response¶
| Code | Meaning |
|---|---|
200 |
File received and queued for processing. validation lists the rejected rows (may be empty). |
400 |
Empty body, invalid x-aantallen-in, or no valid row in the file. |
401 |
x-picode or x-apikey missing, or not matching an active institution. |
405 |
HTTP method other than POST. |
503 |
The API is temporarily disabled. Retry later. |
All error responses are JSON.
Example response for a processed request in which one row was rejected:
{
"result": "success",
"message": "Bestand succesvol ontvangen en in verwerking.",
"validation": [
{
"columnIndex": 4,
"columnNumber": 5,
"value": 14321976,
"message": "Nummer is geen geldig Z-Index nummer voor een add-on product. Het artikel dient een declaratietitel te hebben (gehad).",
"rowNumber": 3,
"rowIndex": 2
}
]
}
Example response when no row is valid:
{
"result": "error",
"message": "Bestand bevat geen geldige rijen.",
"validation": [
{
"columnIndex": 0,
"columnNumber": 1,
"value": "",
"message": "Niet genoeg kolommen in de rij. Verwacht minimaal 9 kolommen. Gevonden: 3 kolommen.",
"rowNumber": 1,
"rowIndex": 0
}
]
}
Example response for an authentication failure:
Messages are in Dutch.
Fields¶
| Field | Type | Description |
|---|---|---|
result |
string | success or error. |
message |
string | Explanation of the result. |
error |
string | Error message; only present for errors without row validation (empty body, authentication, 405, 503). |
validation |
object[] | Rejected rows. Empty when all rows are valid. |
validation[].rowNumber |
integer | Line number in the file (1-based). |
validation[].rowIndex |
integer | Line index (0-based). |
validation[].columnNumber |
integer | Column number (1-based). |
validation[].columnIndex |
integer | Column index (0-based). |
validation[].value |
mixed | The supplied value after normalisation. |
validation[].message |
string | Reason for rejection. |
Points of attention
Check validation even on a 200. Rejected rows are not processed; the remaining
rows are. Correct the rejected rows and submit them again.
Check the unit of your quantities. Without x-aantallen-in the quantities are read as
units; a file in packages would then yield far too low quantities.
Processing happens in the background. The status and the number of processed rows are shown in the upload history in Insights.
Questions about onboarding, the API key or the file format: vragen@pharma-insights.nl.