Assets
The assets API manages your organization's equipment inventory - laptops, monitors, phones, badges - and tracks recovery when someone leaves.
Base path: /api/assets
List assets
GET /api/assets
Query parameters
| Param | Type | Description |
|---|---|---|
limit | integer | Results per page (default 100, max 500) |
offset | integer | Row offset for pagination (default 0) |
There's no status or assignedTo filter on this endpoint - filtering happens client-side, or you can page through everything and filter yourself.
Response 200 OK
{
"rows": [
{
"id": "8f14e45f-...",
"org_id": "org_xyz",
"org_employee_id": "9bb58f26-...",
"item_name": "MacBook Pro 14\"",
"serial_number": "C02XY1234",
"model": "MacBook Pro M3 14-inch",
"category": "laptop",
"condition": "good",
"tracking_number": "",
"return_deadline": "2024-06-15",
"status": "deployed",
"created_at": "2023-09-01T00:00:00.000Z",
"updated_at": "2023-09-01T00:00:00.000Z",
"employee": {
"id": "9bb58f26-...",
"full_name": "Jordan Lee",
"email": "jordan@acme.com",
"employee_id": "EMP-1042",
"department": "Engineering"
}
}
],
"total": 38,
"limit": 100,
"offset": 0
}Fields come straight off the assets table - snake_case throughout, not camelCase. employee is joined in from org_employees and will be null-ish (all fields null) if the asset isn't assigned to anyone.
Asset summary
GET /api/assets/summary
Org-wide rollup used by the unreturned-assets report: totals by status, a breakdown by category, and an aging bucket for overdue returns.
Response 200 OK
{
"totals": { "total": 38, "deployed": 22, "returned": 15, "lost": 1 },
"byCategory": [
{ "category": "laptop", "total": 20, "deployed": 12, "returned": 8 }
],
"overdueAging": [
{ "bucket": "1-7d", "count": 3 },
{ "bucket": "8-30d", "count": 1 },
{ "bucket": "30d+", "count": 0 }
],
"noDeadlineDeployedCount": 4
}Create an asset
POST /api/assets
Admin only.
Request body
{
"itemName": "MacBook Pro 14\"",
"serialNumber": "C02XY1234",
"model": "MacBook Pro M3 14-inch",
"category": "laptop",
"condition": "good",
"orgEmployeeId": "9bb58f26-...",
"trackingNumber": "",
"returnDeadline": "2024-06-15"
}| Field | Required | Description |
|---|---|---|
itemName | ✅ | Device / equipment name |
serialNumber | ✅ | Unique serial or asset tag |
model | - | Model name |
category | - | laptop · monitor · phone · badge · peripheral · other (anything else is coerced to other) |
condition | - | Free text, defaults to good |
orgEmployeeId | - | Assign to an org employee record |
trackingNumber | - | Shipping tracking number |
returnDeadline | - | ISO date string |
New assets are always created with status: "deployed". Fails with 409 if the serial number already exists, and 403 if your plan's asset limit is reached.
Response 201 Created - the created asset, including the joined employee object.
Bulk import assets
POST /api/assets/bulk
Admin only. Imports as many assets as your plan has room for; the rest are reported as skipped rather than rejecting the whole batch.
Request body
{
"assets": [
{ "itemName": "MacBook Pro 14\"", "serialNumber": "C02XY1234", "category": "laptop" },
{ "itemName": "Dell Monitor", "serialNumber": "D5567", "category": "monitor" }
]
}Response 201 Created
{
"inserted": 1,
"skipped": 1,
"errors": [
{ "serialNumber": "D5567", "reason": "Duplicate serial number - already exists" }
]
}Update an asset
PATCH /api/assets/:id
Admin only. This is a full edit, not a partial one - itemName and serialNumber are required on every call, even if unchanged. Accepts the same fields as create, plus status.
Response 200 OK - the updated asset, with the joined employee object.
Mark asset returned
PATCH /api/assets/:id/return
Admin or manager. Sets status to returned and touches updated_at - that's all it does.
This endpoint doesn't take a request body. Any condition or notes you send are ignored; there's no field on the assets table to store return condition or notes today. If you need to record condition at return time, follow up with PATCH /api/assets/:id to set condition separately.
Response 200 OK - the full updated asset row (snake_case, same shape as the list endpoint).
Bulk mark returned
PATCH /api/assets/bulk-return
Admin or manager. Marks multiple assets returned in one call.
Request body
{ "ids": ["8f14e45f-...", "3c9c9a1e-..."] }Response 200 OK
{ "updated": 2, "assets": [ /* updated asset rows */ ] }Delete an asset
DELETE /api/assets/:id
Admin only.
Response 200 OK
{ "success": true }