Code Examples¶
Here you will find practical examples for using the calServer REST API with curl and PHP.
Interactive Documentation
The interactive API documentation automatically generates code examples in over 20 programming languages for each endpoint. You can also test requests directly there:
- API v1 Documentation (Production)
- API v2 Documentation (Beta — calServer 6.0)
API v2 — Examples (Bearer Token)¶
Generate Token¶
<?php
$domain = 'your-instance.example.com';
$ch = curl_init("https://{$domain}/api/v2/auth/token");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode([
'email' => 'user@example.com',
'password' => 'YourPassword',
'device_name' => 'api-client',
]));
$response = curl_exec($ch);
curl_close($ch);
$data = json_decode($response, true);
$token = $data['token'];
echo "Token: {$token}\n";
Response:
Retrieve Inventory (API v2)¶
<?php
$domain = 'your-instance.example.com';
$token = '1|a1b2c3d4e5f6...';
$ch = curl_init("https://{$domain}/api/v2/inventories?page[size]=10");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer {$token}",
'Accept: application/json',
]);
$response = curl_exec($ch);
curl_close($ch);
$data = json_decode($response, true);
echo "Total: " . $data['meta']['total'] . "\n";
foreach ($data['data'] as $item) {
echo $item['attributes']['asset_number'] . ' — '
. $item['attributes']['manufacturer'] . ' '
. $item['attributes']['model'] . "\n";
}
Response:
{
"data": [
{
"id": "ea79b775-8b4b-8e17-98c9-b33e7065ff6f",
"type": "inventory",
"attributes": {
"asset_number": "DMM-001",
"serial_number": "SN-1234567890",
"description": "Digital Multimeter",
"manufacturer": "FLUKE",
"model": "179",
"location": "Lab A",
"status": 1,
"calibration_interval": 12
},
"relationships": {
"customer": { "data": { "id": "45f09720-...", "type": "customer" } },
"categories": [
{
"id": "3fa85f64-...",
"type": "category",
"attributes": {
"name": "Measuring Device",
"type": "inventory",
"color": "#4CAF50"
}
}
]
}
}
],
"meta": { "total": 150, "page": 1, "per_page": 10, "last_page": 15 },
"links": { "self": "...", "next": "...", "prev": null }
}
List Categories¶
<?php
$domain = 'your-instance.example.com';
$token = '1|a1b2c3d4e5f6...';
$ch = curl_init("https://{$domain}/api/v2/categories?filter[type]=inventory");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer {$token}",
'Accept: application/json',
]);
$response = curl_exec($ch);
curl_close($ch);
$data = json_decode($response, true);
foreach ($data['data'] as $cat) {
$indent = $cat['attributes']['parent_id'] ? ' └─ ' : '';
echo $indent . $cat['attributes']['name']
. ' (' . $cat['attributes']['type'] . ")\n";
}
Response:
{
"data": [
{
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"type": "category",
"attributes": {
"name": "Measuring Device",
"short_name": "MG",
"type": "inventory",
"parent_id": null,
"sort_num": 1,
"color": "#4CAF50",
"text_color": "#FFFFFF",
"rentable": 1
}
},
{
"id": "7fb91c22-3a44-4e89-b0fc-8d5e6f7a8b9c",
"type": "category",
"attributes": {
"name": "Multimeter",
"short_name": "MM",
"type": "inventory",
"parent_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"sort_num": 1,
"color": "#2196F3",
"text_color": "#FFFFFF",
"rentable": 1
}
}
],
"meta": { "total": 2 }
}
Create Category¶
# Create main category
curl -X POST "https://your-instance.example.com/api/v2/categories" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "Oscilloscopes",
"short_name": "OSZ",
"type": "inventory",
"color": "#FF9800",
"text_color": "#000000",
"rentable": 1
}'
# Create subcategory (with parent_id)
curl -X POST "https://your-instance.example.com/api/v2/categories" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "Digital Oscilloscopes",
"short_name": "DOSZ",
"type": "inventory",
"parent_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"sort_num": 1,
"color": "#E65100"
}'
<?php
$domain = 'your-instance.example.com';
$token = '1|a1b2c3d4e5f6...';
$categoryData = [
'name' => 'Oscilloscopes',
'short_name' => 'OSZ',
'type' => 'inventory',
'color' => '#FF9800',
'text_color' => '#000000',
'rentable' => 1,
];
$ch = curl_init("https://{$domain}/api/v2/categories");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer {$token}",
'Content-Type: application/json',
]);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($categoryData));
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($httpCode === 201) {
$result = json_decode($response, true);
echo "Category created: " . $result['data']['id'] . "\n";
}
Response (201 Created):
{
"data": {
"id": "b2c3d4e5-f6a7-8901-bcde-f12345678901",
"type": "category",
"attributes": {
"name": "Oscilloscopes",
"short_name": "OSZ",
"type": "inventory",
"parent_id": null,
"sort_num": 0,
"color": "#FF9800",
"text_color": "#000000",
"rentable": 1
}
}
}
Retrieve Field Configurations¶
# Table overview
curl -X GET "https://your-instance.example.com/api/v2/fields" \
-H "Authorization: Bearer $TOKEN"
# Fields for the inventory table
curl -X GET "https://your-instance.example.com/api/v2/fields/inventory" \
-H "Authorization: Bearer $TOKEN"
# Fields with category overrides
curl -X GET "https://your-instance.example.com/api/v2/fields/inventory?category_uID=3fa85f64-5717-4562-b3fc-2c963f66afa6" \
-H "Authorization: Bearer $TOKEN"
<?php
$domain = 'your-instance.example.com';
$token = '1|a1b2c3d4e5f6...';
$categoryUid = '3fa85f64-5717-4562-b3fc-2c963f66afa6';
// Fields for inventory with category overrides
$url = "https://{$domain}/api/v2/fields/inventory?category_uID={$categoryUid}";
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer {$token}",
'Accept: application/json',
]);
$response = curl_exec($ch);
curl_close($ch);
$result = json_decode($response, true);
foreach ($result['data'] as $field) {
$attr = $field['attributes'];
$required = $attr['mandatory'] ? '(Required)' : '';
echo "{$attr['api_name']} — {$attr['label']} {$required}\n";
}
Response (Table overview):
{
"data": [
{ "table": "inventory", "field_count": 65, "active_field_count": 32 },
{ "table": "calibration", "field_count": 98, "active_field_count": 45 },
{ "table": "customer", "field_count": 38, "active_field_count": 20 },
{ "table": "location", "field_count": 15, "active_field_count": 8 },
{ "table": "repair", "field_count": 20, "active_field_count": 12 }
]
}
Response (Fields for inventory):
{
"data": [
{
"id": "I4201:inventory",
"type": "field-configuration",
"attributes": {
"api_name": "asset_number",
"column_name": "I4201",
"table_name": "inventory",
"label": "Asset Number",
"field_type": "text",
"field_type_raw": "varchar",
"filterable": true,
"sortable": true,
"editable": true,
"visible": true,
"mandatory": true,
"display_order": 1,
"options": null,
"is_user_defined": false
}
},
{
"id": "I4209:inventory",
"type": "field-configuration",
"attributes": {
"api_name": "status_code",
"column_name": "I4209",
"table_name": "inventory",
"label": "Status",
"field_type": "select",
"field_type_raw": "varchar",
"filterable": true,
"sortable": true,
"editable": true,
"visible": true,
"mandatory": false,
"display_order": 9,
"options": [
{ "value": "uuid-active", "label": "Active" },
{ "value": "uuid-inactive", "label": "Inactive" },
{ "value": "uuid-repair", "label": "In Repair" }
],
"field_category": "StatusDatabase",
"is_user_defined": false
}
}
]
}
Inventory with Filter and Sorting¶
<?php
$domain = 'your-instance.example.com';
$token = '1|a1b2c3d4e5f6...';
$params = http_build_query([
'filter' => ['manufacturer' => 'like:FLUKE'],
'sort' => 'asset_number',
'page' => ['size' => 5],
]);
$ch = curl_init("https://{$domain}/api/v2/inventories?{$params}");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer {$token}",
'Accept: application/json',
]);
$response = curl_exec($ch);
curl_close($ch);
$data = json_decode($response, true);
echo "Matches: {$data['meta']['total']}\n";
API v1 — Examples (Header Auth)¶
Authentication¶
All API v1 requests require three authentication parameters as query parameters:
HTTP_X_REST_USERNAME– Your username (email)HTTP_X_REST_PASSWORD– Your passwordHTTP_X_REST_API_KEY– Your API key (can be generated in your user account)
Retrieve Inventory¶
<?php
$domain = 'demo.net-cal.com';
$params = http_build_query([
'HTTP_X_REST_USERNAME' => 'user@example.com',
'HTTP_X_REST_PASSWORD' => 'yourpassword',
'HTTP_X_REST_API_KEY' => 'your-api-key',
]);
$ch = curl_init("https://{$domain}/api/inventory?{$params}");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);
$data = json_decode($response, true);
echo "Total count: " . $data['data']['totalCount'] . "\n";
foreach ($data['data']['inventory'] as $item) {
echo $item['I4201'] . ' - ' . $item['I4202'] . ' ' . $item['I4203'] . "\n";
}
Response structure:
{
"success": true,
"message": "Record(s) Found",
"data": {
"totalCount": 42,
"inventory": [
{
"MTAG": "ea79b775-8b4b-8e17-98c9-b33e7065ff6f",
"I4201": "Test-API-Asset",
"I4202": "FLUKE",
"I4203": "179",
"I4206": "1234567890",
"I4211": "CALSERVICE",
"I4228": "M",
"I4229": "12"
}
]
}
}
Inventory with Filter (API v1)¶
curl -X GET "https://demo.net-cal.com/api/inventory?\
HTTP_X_REST_USERNAME=user@example.com&\
HTTP_X_REST_PASSWORD=yourpassword&\
HTTP_X_REST_API_KEY=your-api-key&\
filter=%5B%7B%22property%22%3A%22I4201%22%2C%22value%22%3A%22Test-API-Asset%22%2C%22operator%22%3A%22%3D%22%7D%5D"
The URL-encoded filter parameter corresponds to:
<?php
$domain = 'demo.net-cal.com';
$filter = json_encode([
['property' => 'I4201', 'value' => 'Test-API-Asset', 'operator' => '=']
]);
$params = http_build_query([
'HTTP_X_REST_USERNAME' => 'user@example.com',
'HTTP_X_REST_PASSWORD' => 'yourpassword',
'HTTP_X_REST_API_KEY' => 'your-api-key',
'filter' => $filter,
]);
$ch = curl_init("https://{$domain}/api/inventory?{$params}");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);
$data = json_decode($response, true);
print_r($data);
Filter Inventory by Category Name (API v1)¶
The API supports dot notation for related fields (relation.field).
For inventory categories, there is also a shorthand field categoryname,
which is automatically resolved internally via the category table.
# Option 1: categoryname shorthand (recommended for inventory)
curl -X GET "https://demo.net-cal.com/api/inventory?\
HTTP_X_REST_USERNAME=user@example.com&\
HTTP_X_REST_PASSWORD=yourpassword&\
HTTP_X_REST_API_KEY=your-api-key&\
filter=%5B%7B%22property%22%3A%22categoryname%22%2C%22value%22%3A%22Messgeraet%22%2C%22operator%22%3A%22like%22%7D%5D"
The URL-encoded filter parameter corresponds to:
<?php
$domain = 'demo.net-cal.com';
// Option 1: categoryname shorthand
$filter = json_encode([
['property' => 'categoryname', 'value' => 'Messgeraet', 'operator' => 'like']
]);
// Option 2: Dot notation (generic for all relations)
// $filter = json_encode([
// ['property' => 'categories.name', 'value' => 'Messgeraet', 'operator' => 'like']
// ]);
$params = http_build_query([
'HTTP_X_REST_USERNAME' => 'user@example.com',
'HTTP_X_REST_PASSWORD' => 'yourpassword',
'HTTP_X_REST_API_KEY' => 'your-api-key',
'filter' => $filter,
]);
$ch = curl_init("https://{$domain}/api/inventory?{$params}");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);
$data = json_decode($response, true);
echo "Matches: " . $data['data']['totalCount'] . "\n";
foreach ($data['data']['inventory'] as $item) {
echo $item['I4201'] . ' - ' . $item['I4202'] . ' ' . $item['I4203'] . "\n";
}
Dot Notation for Other Relations
Dot notation (relation.field) works generically for all relations defined in the
Yii model — not just for categories. The API automatically adds the corresponding
JOIN. Example: categories.name, customer.name, etc.
Create Inventory (API v1)¶
curl -X POST "https://demo.net-cal.com/api/inventory/insert?\
HTTP_X_REST_USERNAME=user@example.com&\
HTTP_X_REST_PASSWORD=yourpassword&\
HTTP_X_REST_API_KEY=your-api-key" \
-F "ktag=45f09720-082f-5c74-9cfa-a605e2863904" \
-F "I4201=Test-API-Asset" \
-F "I4202=FLUKE" \
-F "I4203=179" \
-F "I4206=1234567890" \
-F "I4211=CALSERVICE" \
-F "I4228=M" \
-F "I4229=12"
<?php
$domain = 'demo.net-cal.com';
$params = http_build_query([
'HTTP_X_REST_USERNAME' => 'user@example.com',
'HTTP_X_REST_PASSWORD' => 'yourpassword',
'HTTP_X_REST_API_KEY' => 'your-api-key',
]);
$postData = [
'ktag' => '45f09720-082f-5c74-9cfa-a605e2863904',
'I4201' => 'Test-API-Asset',
'I4202' => 'FLUKE',
'I4203' => '179',
'I4206' => '1234567890',
'I4211' => 'CALSERVICE',
'I4228' => 'M',
'I4229' => '12',
];
$ch = curl_init("https://{$domain}/api/inventory/insert?{$params}");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $postData);
$response = curl_exec($ch);
curl_close($ch);
$data = json_decode($response, true);
if ($data['success']) {
echo "Inventory successfully created!\n";
} else {
echo "Error: " . print_r($data['errors'], true) . "\n";
}
Pagination (Limit & Offset) (API v1)¶
<?php
$domain = 'demo.net-cal.com';
$params = http_build_query([
'HTTP_X_REST_USERNAME' => 'user@example.com',
'HTTP_X_REST_PASSWORD' => 'yourpassword',
'HTTP_X_REST_API_KEY' => 'your-api-key',
'limit' => 10,
'offset' => 30,
]);
$ch = curl_init("https://{$domain}/api/calibration?{$params}");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);
$data = json_decode($response, true);
echo "Page with " . count($data['data']['calibration']) . " entries\n";
echo "Total count: " . $data['data']['totalCount'] . "\n";
Retrieve Validation Rules (API v1)¶
Available rules endpoints:
| Resource | Endpoint |
|---|---|
| Inventory | GET /api/inventory/rules |
| Calibration | GET /api/calibration/rules |
| Customers | GET /api/customer/rules |
| Standards | GET /api/standard/rules |
| Users | GET /api/user/rules |
| Repairs | GET /api/repair/rules |
| Locations | GET /api/location/rules |