Skip to content

Contracts upload

Draft

This specification is not final. This API does not exist yet; this document is a draft specification that we provide for alignment so you can prepare your data format. Endpoints, columns, headers and responses may still change during implementation. Do not build a production integration based on this document without aligning with Pharma-Intelligence.

POST Import (upload) contracts from your own system into PharmaPortal.

Users of PharmaPortal can import (upload) contracts into PharmaPortal from their own system via an API. This is the API variant of the "Add contract" upload function in PharmaPortal. Each contract links a price agreement per article (Z-Index number) to a customer (PI code), valid over a period. Contracts are written under your organisation. This is a REST API with a single endpoint and a single possible action.

Access

Available to PharmaPortal licence holders only.

Endpoint

POST https://demo.pharma-portal.nl/api/contracten/upload
POST https://www.pharma-portal.nl/api/contracten/upload

See also Contracts at reference date for reading active contracts.

Request body

Requests are POST requests with the CSV content directly as the body (so no multipart file or JSON). The CSV file contains thirteen columns without a header row. Both , and ; are recognised as separators. The columns are, in order:

# Column Description
1 pi_code PI code of the customer the contract applies to.
2 zindex_nummer Z-Index number (8 digits).
3 ingangs_datum Start date, format YYYY-MM-DD.
4 eind_datum End date, format YYYY-MM-DD.
5 soort vast (fixed) or percentage.
6 vaste_prijs For vast: the fixed price per pack (excl. VAT). Empty for percentage.
7 percentage For percentage: discount percentage relative to AIP (0–100). Empty for vast.
8 distributie groothandel (wholesale) or direct.
9 herkomst Free text, origin of the contract.
10 opmerking Free text (optional).
11 volume_stuks Committed annual volume in units (optional, empty/unknown by default).
12 toeslag Surcharge amount (optional).
13 toeslag_omschrijving Description of the surcharge (optional).

For soort=percentage the final price is calculated server-side from the article's AIP (just like in the "Add contract" upload function). The afslag type is not supported when importing contracts.

Examples

1. Minimal rows — only the required fields filled in; optional columns (opmerking, volume_stuks, toeslag, toeslag_omschrijving) remain empty but the separators stay in place.

671234;12345678;2026-01-01;2026-12-31;vast;100.01;;direct;Inkooptraject 2026;;;;
671234;34567890;2026-01-01;2026-12-31;vast;14.31;;direct;Inkooptraject 2026;;;;

2. Fixed price and discount percentage mixed — for percentage you leave vaste_prijs empty and fill in percentage; the price is calculated from the AIP.

671234;12345678;2026-01-01;2026-12-31;vast;100.01;;groothandel;Inkooptraject 2026;;1000;;
671234;34567890;2026-01-01;2026-12-31;percentage;;12.5;direct;Inkooptraject 2026;kortingsafspraak;500;;

3. Multiple customers in one upload — each row determines via pi_code which customer the contract applies to.

671234;12345678;2026-01-01;2026-12-31;vast;100.01;;groothandel;Inkooptraject 2026;;1000;;
671299;12345678;2026-01-01;2026-12-31;vast;98.75;;groothandel;Inkooptraject 2026;;750;;
680055;12345678;2026-01-01;2026-12-31;percentage;;10;direct;Inkooptraject 2026;;250;;

4. With surcharge — a surcharge amount with description and a specified annual volume.

671234;56789012;2026-01-01;2026-12-31;vast;53.23;;groothandel;Inkooptraject 2026;incl. koeltransport;2000;3.50;Koelvergoeding

A comma (,) is also allowed as a separator instead of ;.

Authentication

This API uses (identical to the other PharmaPortal APIs): IP whitelisting for security, an API key for authentication & rate limiting, and HMAC for integrity checking (mandatory for POST). The API key determines on behalf of which PharmaPortal organisation the contracts are written. You specify the customer per row via the pi_code column.

Header Description
x-portal-key The API key issued to your organisation.
x-portal-hmac Hexadecimally encoded SHA-512 HMAC of the request body (the raw CSV), computed with your API secret.
content-type text/csv

Request

curl -X POST https://demo.pharma-portal.nl/api/contracten/upload \
  -H "x-portal-key: <your-api-key>" \
  -H "x-portal-hmac: <sha-512-hmac>" \
  -H "content-type: text/csv" \
  --data-binary @contracten.csv

Response

Code Meaning
200 For a processed request (also when individual rows contain errors).
401 For invalid authentication, HMAC or IP.

Example of a response for a successful & correct request:

{
  "result": "success",
  "data": {
    "numRowsTotal": 2,
    "numRowsImported": 2,
    "numRowsError": 0,
    "errors": []
  }
}

Example of a response with row errors:

{
  "result": "success",
  "data": {
    "numRowsTotal": 2,
    "numRowsImported": 1,
    "numRowsError": 1,
    "errors": [
      { "line": 2, "message": "Percentage moet tussen 0 en 100 liggen" }
    ]
  }
}

Example of a response for a request error:

{
  "result": "error",
  "errorMessage": "Niet genoeg velden op rij (3)"
}

Fields

Field Type Description
result string success or error.
data.numRowsTotal integer Number of rows supplied.
data.numRowsImported integer Number of contracts created successfully.
data.numRowsError integer Number of rows with an error (not created).
data.errors object[] Row errors, with line and message.
errorMessage string Only for result: error: description of the request error.

Notes

The HMAC must be computed over the exact CSV bytes of the request body.

Each contract is written with your organisation as owner; leverancier_nummer remains empty (this is only filled from a completed purchasing round). Each row is added as a separate contract. The specified volume_stuks is recorded as the annual volume for the contract.

A maximum file size of 10 MB applies per upload. You can split very large lists into multiple requests (guideline: at most approx. 50,000 rows per request).

Want to test your integration? Contact us in good time at info@zagis.nl. We will then prepare test data for you and provide you with an API key.