Cadmus collects intra-oral scan orders from IOS portals and exposes them through a single, normalised REST API. This guide walks you through authentication, retrieving orders, and downloading scan files.
All endpoints are relative to the base URL for your environment. Use HTTPS in all environments.
https://api.staging.cadmuslabs.nl
Shared development environment. Requires a valid user account.
https://api.cadmuslabs.nl
Live environment. Requires a valid user account.
https://api.cadmuslabs.nl as the base URL.
Replace it with https://api.staging.cadmuslabs.nl when working against the staging environment.
Every API call requires a JSON Web Token (JWT). Obtain one by posting your credentials
to /auth/login. The token is valid for 8 hours.
https://api.cadmuslabs.nl/auth/login
{
"email": "you@example.com",
"password": "your-password"
}
curl -s -X POST https://api.cadmuslabs.nl/auth/login \
-H "Content-Type: application/json" \
-d '{"email":"you@example.com","password":"your-password"}'
{
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"expiresAt": "2026-03-09T18:30:00Z"
}
Copy the token value. You will pass it as
Authorization: Bearer <token> on every subsequent request.
Orders are exposed through the /unified-cases resource. Every order is mapped to a single consistent schema — patient name, scan files, dentist, and restorations always appear in the same place regardless of which IOS portal the order originated from.
https://api.cadmuslabs.nl/unified-cases
curl -s https://api.cadmuslabs.nl/unified-cases \
-H "Authorization: Bearer <token>"
{
"items": [
{
"id": 42,
"organizationId": 3,
"portalId": 1,
"configuredPortalId": 7,
"caseId": "16ad2e12-fb26-4931-ba16-321285d74550",
"guid": "33b07a91-c6ae-4824-aab6-f4a02560b0a6",
"createdAt": "2026-03-08T09:14:00Z",
"patientFullname": null, /* may be null — use acceptedData.patient.fullName */
"status": "new",
"completenessStatus": "complete",
"infoRequestStatus": "none",
"acceptedData": { /* normalised case fields — see data model below */ }
}
],
"page": 1,
"pageSize": 20,
"total": 183
}
Supported query parameters: page, pageSize,
from (YYYY-MM-DD), to (YYYY-MM-DD).
All files (scan files and the order form PDF) are stored in cloud object storage
(Google Cloud Storage) — they are not served directly from the
database. The fileLink fields in acceptedData are internal
storage paths, not public URLs.
Request a pre-authenticated signed URL from the API. Signed URLs are valid for 15 minutes and can be used directly in a browser, a 3D viewer, or a download client — no extra headers needed.
upper.stlstl, ply, …upper, lower, bitehttps://api.cadmuslabs.nl/unified-cases/{id}/files/{filename}?fileType=stl
curl -s "https://api.cadmuslabs.nl/unified-cases/42/files/upper.stl?fileType=stl" \
-H "Authorization: Bearer <token>"
{
"url": "https://storage.googleapis.com/cadmus_collector_bucket/...&X-Goog-Signature=...",
"filename": "upper.stl",
"fileType": "stl",
"expiresAt": "2026-03-09T10:45:00Z"
}
The order form is a single PDF attached to the case
(acceptedData.orderForm). Use the dedicated endpoint to get a signed URL
for it — no fileType parameter needed.
https://api.cadmuslabs.nl/unified-cases/{id}/order-form
curl -s "https://api.cadmuslabs.nl/unified-cases/42/order-form" \
-H "Authorization: Bearer <token>"
{
"url": "https://storage.googleapis.com/cadmus_collector_bucket/...&X-Goog-Signature=...",
"filename": "DS Core_orderform.pdf",
"expiresAt": "2026-03-09T10:45:00Z"
}
Pass the url directly to a PDF viewer or trigger a download.
Request a fresh URL if the link has expired.
Each unified case carries portalId and configuredPortalId to
identify which IOS portal and which configured connection the order came from. Use these
endpoints to resolve those IDs to names.
/portals/ios
All active IOS portal types. Returns id, name, className, url, axisMaping, quantizationBits.
/portals/configured
Configured portal connections for your organisation. Returns id, displayName, username, lastFetch, portalName.
Top-level status fields on each case: status
(new | accepted | rejected | in_production | complete | cancelled),
completenessStatus (complete | incomplete),
infoRequestStatus (none | requested | received).
The acceptedData object contains the following normalised fields.
Use GET /unified-cases/{id}/order-form to get a 15-min signed download URL.
The interactive API reference lets you authenticate and call every endpoint directly in the browser. The OpenAPI JSON spec can be imported into Postman, Insomnia, or any compatible tooling.