Quick Start
1. Create an API key in Settings → API Keys
2. Include it as a Bearer token in your requests:
curl https://calibrationos.com/api/v1/equipment \
-H "Authorization: Bearer cal_your_api_key_here"Authentication
All API requests require a valid API key passed via the Authorization header using the Bearer scheme.
Authorization: Bearer cal_your_api_key_hereAPI keys start with the cal_ prefix. Each key has one or more scopes that control access:
| Scope | Access |
|---|---|
| equipment:read | List and view equipment |
| equipment:write | Create, update, and retire equipment |
| calibrations:read | List and view calibration records |
| calibrations:write | Create and update calibration records |
| standards:read | List and view reference standards |
| reports:read | Generate and download reports |
| webhooks:manage | Create, update, and delete webhooks |
Equipment
/api/v1/equipmentList equipment for your organization. Supports filtering, search, and pagination.
Parameters
| search | string | Filter by equipment number, description, or serial number |
| status | string | Filter by status: active, overdue, in_calibration, retired |
| category | string | Filter by category: dimensional, electrical, pressure, temperature, etc. |
| page | number | Page number (default: 1) |
| limit | number | Items per page (default: 50, max: 100) |
Response
{
"equipment": [
{
"id": "uuid",
"equipmentNumber": "EQ-2026-0001",
"description": "Digital Caliper",
"category": "dimensional",
"status": "active",
"lastCalDate": "2026-01-15T00:00:00Z",
"nextDueDate": "2027-01-15T00:00:00Z"
}
],
"pagination": {
"page": 1,
"limit": 50,
"total": 26,
"totalPages": 1
}
}/api/v1/equipmentCreate a new piece of equipment. Automatically generates an equipment number.
Body Parameters
| description* | string | Equipment description |
| category* | string | Equipment category |
| serialNumber | string | Manufacturer serial number |
| manufacturer | string | Equipment manufacturer |
| model | string | Model number |
| calFrequencyDays | number | Calibration interval in days (default: 365) |
| calType | string | in_house or external |
Response
{
"id": "uuid",
"equipmentNumber": "EQ-2026-0027",
"description": "Torque Wrench",
"category": "torque",
"status": "active",
"nextDueDate": "2027-03-18T00:00:00Z"
}/api/v1/equipment/:idRetrieve a single equipment record with recent calibration history.
/api/v1/equipment/:idUpdate equipment fields. Only provided fields are updated.
Body Parameters
| description | string | Updated description |
| status | string | active, in_calibration, or retired |
| calFrequencyDays | number | Updated calibration interval |
| locationId | string | UUID of new location |
Calibrations
/api/v1/calibrationsList calibration records with optional filtering by equipment, date range, and result.
Parameters
| equipmentId | string | Filter by equipment UUID |
| result | string | Filter by result: pass, fail, in_tolerance, out_of_tolerance |
| startDate | string | ISO date — filter records on or after this date |
| endDate | string | ISO date — filter records on or before this date |
| page | number | Page number (default: 1) |
| limit | number | Items per page (default: 50, max: 100) |
/api/v1/calibrationsRecord a new calibration. Automatically updates equipment status and next due date.
Body Parameters
| equipmentId* | string | Equipment UUID |
| calDate* | string | ISO date of calibration |
| overallResult* | string | pass, fail, in_tolerance, or out_of_tolerance |
| performedBy | string | Name of calibration technician |
| asFoundData | object | As-found measurement data |
| asLeftData | object | As-left measurement data (after adjustment) |
| certificateNumber | string | External certificate number |
/api/v1/calibrations/:idRetrieve a single calibration record with full measurement data.
Reference Standards
/api/v1/standardsList reference standards with traceability chain information.
/api/v1/standards/:idRetrieve a reference standard with its parent/child traceability chain.
Webhooks
Webhooks deliver real-time event notifications to your endpoint via HTTP POST. All payloads are signed with HMAC-SHA256 for verification.
Available Events
calibration.completedequipment.overdueoot.detectedinvestigation.openedinvestigation.closedequipment.createdequipment.retireddrift.alertSignature Verification
Each webhook request includes an X-CalOS-Signature header containing a hex-encoded HMAC-SHA256 digest of the raw request body, using your webhook secret as the key.
const crypto = require('crypto');
function verifySignature(body, signature, secret) {
const expected = crypto
.createHmac('sha256', secret)
.update(body)
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(expected)
);
}Payload Format
{
"event": "calibration.completed",
"timestamp": "2026-03-18T14:30:00Z",
"data": {
"id": "uuid",
"recordNumber": "CR-2026-0050",
"equipmentId": "uuid",
"equipmentNumber": "EQ-2026-0001",
"overallResult": "pass",
"calDate": "2026-03-18T00:00:00Z"
}
}Errors
The API uses standard HTTP status codes and returns errors in a consistent JSON format:
{
"error": "Validation failed: description is required"
}| Status | Meaning |
|---|---|
| 400 | Bad Request — Validation failed or invalid parameters |
| 401 | Unauthorized — Missing or invalid API key |
| 403 | Forbidden — Insufficient scope or plan quota exceeded |
| 404 | Not Found — Resource does not exist or belongs to another tenant |
| 429 | Too Many Requests — Rate limit exceeded (60 req/min) |
| 500 | Internal Server Error — Something went wrong on our end |