Order API
This document describes the order creation endpoint that allows a third-party provider to create orders.
Overview
- Method:
POST - Path:
/api/v1/external/orders - Content-Type:
application/json - Authentication: HMAC SHA-256 signature in request headers
- Versioning: The API is currently versioned through the request path. The current stable endpoint is
/api/v1/external/orders. Breaking changes will be introduced through a new path version and communicated in advance; non-breaking additions (new optional fields, new response properties) may be made without prior notice.
Endpoint
http
POST /api/v1/external/orders
Content-Type: application/json
X-Client-Id: <client_id>
X-Request-Signature: <hex_hmac_sha256_signature>
X-Request-Timestamp: <unix_epoch_seconds>Authentication
Each request must include these headers:
| Header | Required | Description |
|---|---|---|
X-Client-Id | Yes | The client identifier issued to you. It is matched against an active, non-revoked credential. |
X-Request-Signature | Yes | HMAC SHA-256 signature of the raw request body, encoded as a 64-character lowercase or uppercase hexadecimal string. |
X-Request-Timestamp | Yes | Unix timestamp in seconds. Requests outside the 5-minute allowed window are rejected. |
Signature rules
The server resolves the shared secret from the X-Client-Id header and validates the signature using that client's secret.
- Algorithm: HMACSHA256
- Payload to sign: the raw HTTP request body exactly as sent
- Encoding for the shared secret: UTF-8
- Encoding for the body: UTF-8
- Signature format: hexadecimal string
Request body
Schema
json
{
"orderReference": "ORD-2024-00123",
"prescriptionUrl": "https://example.com/prescriptions/ORD-2024-00123.pdf",
"medicines": [
{
"name": "Amoxicillin",
"reference": "MED-456",
"description": "Amoxicillin 500mg",
"packageSize": "21 capsules",
"dosage": "500",
"dosageUnit": "mg",
"units": 21,
"unitLabel": "capsule",
"quantity": 1,
"usageAdvice": "Take 1 capsule 3 times daily."
}
],
"customer": {
"reference": "CUST-789",
"firstName": "Jan",
"lastName": "de Vries",
"email": "jan.devries@example.com",
"phone": "+31612345678",
"dateOfBirth": "1985-04-22",
"gender": "male"
},
"shipping": {
"address1": "Herengracht 182",
"address2": "Herengracht 182",
"postalCode": "1016 BR",
"city": "Amsterdam",
"country": "NL"
}
}Field requirements
| Field | Type | Required | Rules |
|---|---|---|---|
orderReference | string | Yes | Required Must be unique per order. Comparison is case-insensitive after trimming. |
prescriptionUrl | string | Yes | Must be a valid absolute URL with http or https scheme. |
medicines | array | Yes | Must contain at least 1 item. |
medicines[].reference | string | Yes | Max 100 characters. Must be unique within the request and globally across all orders. |
medicines[].description | string | Yes | Max 255 characters. |
medicines[].quantity.amount | integer | Yes | Must be greater than 0. Whole numbers only. |
medicines[].quantity.unit | string | Yes | Max 50 characters. The API stores this value in lowercase. Send normalized values such as capsule or tablet for consistency. |
medicines[].usageAdvice | string | Yes | Required |
customer.reference | string | Yes | Required Existing customers with the same reference are updated; all customer fields (firstName, lastName, email, phone, dateOfBirth, gender) are overwritten with the values provided in the request. |
customer.firstName | string | Yes | - |
customer.lastName | string | Yes | - |
customer.email | string | Yes | Must be a valid email address. |
customer.phone | string | Yes | - |
customer.dateOfBirth | string | Yes | Must be a valid ISO date in YYYY-MM-DD format. |
customer.gender | string | Yes | Allowed values: male, female. Case-insensitive. |
shipping.address | string | Yes | - |
shipping.postalCode | string | Yes | - |
shipping.city | string | Yes | - |
shipping.country | string | Yes | - |
Successful response
201 Created
Returned when the order is created successfully.
json
{
"orderId": "1c1f82d8-7724-4fc8-b4d8-6cfa4d74353a",
"orderReference": "ORD-2024-00123",
"createdAt": "2026-06-19T08:15:30.0000000+00:00"
}| Field | Type | Description |
|---|---|---|
orderId | UUID | Internal Pharmacy order identifier. |
orderReference | string | Order reference provided in the request after normalization. |
createdAt | datetimeoffset | UTC timestamp when the order was created. |
Error responses
400 Bad Request
Returned when the JSON body is malformed or cannot be bound to the request model.
Example:
json
{
"type": "validation_error",
"message": "Invalid request body."
}401 Unauthorized
Returned when authentication fails.
Possible messages include:
- Missing
X-Client-Id. X-Client-Idis invalid.- Missing
X-Request-Signature. - Missing
X-Request-Timestamp. X-Request-Timestampmust be a Unix epoch value.X-Request-Timestampis outside the allowed five-minute window.X-Request-Signatureformat is invalid.X-Request-Signatureis invalid.
Example:
json
{
"message": "X-Request-Signature is invalid."
}409 Conflict
Returned when an order with the same orderReference already exists.
json
{
"message": "Order with reference 'ORD-2024-00123' already exists."
}422 Unprocessable Entity
Returned when the request body is valid JSON but fails business validation.
Example:
json
{
"type": "validation_error",
"errors": [
{
"field": "Medicines[1].Reference",
"message": "Medicine reference must be unique within the order."
}
]
}Common validation failures:
- Missing Required fields
- Duplicate medicine references inside the same order
- Invalid email address
- Invalid date format
- Unsupported gender value
- Invalid country code
- Invalid prescription URL
- Quantity amount that is missing, zero, negative, or not a whole number