Documentation
Vision API reference
Read what the cameras saw, correct what they got wrong, and pull the QC report your buyer asks for. Frames are ingested by the edge agent, not through this API.
Cameras
GET/v1/cameras
List cameras with their binding to a machine and their current health.
Requires scope cameras:read
GET/v1/cameras/{id}
Retrieve one camera, including sampling configuration and last frame time.
Requires scope cameras:read
{
"data": [
{
"id": "cam_01J8R4T7",
"name": "CAM-03",
"unit_id": "unt_02",
"machine_id": "PR-04",
"status": "online",
"model_version": "rajhans-v7",
"sample_interval_ms": 2250,
"region_of_interest": { "x": 0.08, "y": 0.12, "w": 0.84, "h": 0.76 },
"last_frame_at": "2026-08-08T14:21:06+05:30",
"edge_agent": {
"version": "1.6.0",
"spool_bytes": 41943040,
"spool_capacity_bytes": 21474836480,
"connected": true
}
}
],
"has_more": false,
"next_cursor": null
}spool_bytes is the useful health signal. A spool that is growing means the unit has lost its uplink and frames are queuing — detection is delayed but nothing is being lost yet.
Defect events
GET/v1/defects
List defect events, newest first, filterable by camera, machine, shift, order or class.
Requires scope defects:read
GET/v1/defects/{id}
Retrieve one defect event with a signed URL for the frame.
Requires scope defects:read
POST/v1/defects/{id}/review
Confirm, reclassify or dismiss a detection. Reviews feed the next training run.
Requires scope defects:write
| Parameter | Type | Description |
|---|---|---|
| camera_id | string | Restrict to one camera. |
| machine_id | string | Restrict to one machine. |
| work_order | string | Your order reference, e.g. ESR-2026-0431. |
| shift | enum | A, B or C. |
| class | string | A class from your taxonomy, e.g. weft_bar. Repeatable. |
| severity | enum | minor, major or critical. |
| min_confidence | number | 0 to 1. Defaults to your account threshold. |
| review_status | enum | unreviewed, confirmed, reclassified or dismissed. |
| from | timestamp | Inclusive lower bound on captured_at. |
| to | timestamp | Exclusive upper bound on captured_at. |
curl "https://api.easarctech.com/v1/defects?work_order=ESR-2026-0431&severity=major&limit=50" \
-H "Authorization: Bearer esk_live_7f3a9c2e8b14d05a" \
-H "Easarc-Version: 2026-08-01"{
"data": [
{
"id": "dfe_01J9ZK4M7Q2X8V",
"camera_id": "cam_01J8R4T7",
"machine_id": "PR-04",
"unit_id": "unt_02",
"shift": "B",
"operator_id": "OP-2291",
"work_order": "ESR-2026-0431",
"order_id": "ord_01J9ZK4M7Q2X8V",
"class": "weft_bar",
"class_label": "Weft bar",
"severity": "major",
"confidence": 0.91,
"bbox": [0.24, 0.38, 0.38, 0.47],
"captured_at": "2026-08-08T14:21:06.412+05:30",
"received_at": "2026-08-08T14:21:07.884+05:30",
"model_version": "rajhans-v7",
"review_status": "unreviewed",
"frame_url": "https://cdn.easarctech.com/clips/…?expires=1754654400&sig=…"
}
],
"has_more": true,
"next_cursor": "dfe_01J9ZK4M7Q2X8V"
}frame_url is signed and expires in 15 minutes. Do not store it — re-request the event when you need the image again. bbox is [x1, y1, x2, y2] in normalised coordinates against the cropped region of interest, not the raw camera frame.
Reviewing a detection
Reviews are how the model improves. A dismissal is as valuable as a confirmation, and a reclassification is the most valuable of the three.
// The QC person said this is not a weft bar, it is a shade variation.
await easarc.defects.review('dfe_01J9ZK4M7Q2X8V', {
verdict: 'reclassified',
class: 'shade_variation',
severity: 'minor',
reviewed_by: 'OP-1183',
note: 'Beam change at 14:15, colour lifted for about 40 m',
})Inspection sessions
GET/v1/inspection-sessions
List inspection sessions. A session is one continuous run of a work order on a machine.
Requires scope defects:read
GET/v1/inspection-sessions/{id}
Retrieve a session with its aggregate defect rate and per-class breakdown.
Requires scope defects:read
{
"id": "ins_01J9ZQ8B4K",
"work_order": "ESR-2026-0431",
"machine_id": "PR-04",
"camera_id": "cam_01J8R4T7",
"shift": "B",
"started_at": "2026-08-08T14:02:11+05:30",
"ended_at": "2026-08-08T21:58:40+05:30",
"inspected": { "value": 3200, "uom": "MTR" },
"frames_analysed": 12704,
"defect_count": 41,
"defect_rate_percent": 1.28,
"by_class": [
{ "class": "weft_bar", "count": 18, "share_percent": 43.9 },
{ "class": "oil_stain", "count": 12, "share_percent": 29.3 },
{ "class": "shade_variation", "count": 7, "share_percent": 17.1 },
{ "class": "hole", "count": 4, "share_percent": 9.8 }
],
"threshold_breaches": [
{
"at": "2026-08-08T18:40:00+05:30",
"rate_percent": 3.4,
"threshold_percent": 3.0,
"notified": ["+919xxxxxxx41"]
}
]
}Defect taxonomy
GET/v1/defect-classes
List the defect classes configured for your account, with training example counts.
Requires scope defects:read
POST/v1/defect-classes
Add a class. It starts unavailable for detection until it has enough confirmed examples.
Requires scope defects:write
{
"data": [
{
"id": "dfc_01J8P2M4",
"class": "weft_bar",
"label": "Weft bar",
"label_gu": "વેફ્ટ બાર",
"default_severity": "major",
"confirmed_examples": 812,
"detection_enabled": true,
"precision": 0.93,
"recall": 0.89
},
{
"id": "dfc_01J8P2M9",
"class": "reed_mark",
"label": "Reed mark",
"label_gu": "રીડ માર્ક",
"default_severity": "minor",
"confirmed_examples": 137,
"detection_enabled": false,
"precision": null,
"recall": null
}
],
"has_more": false,
"next_cursor": null
}A class stays detection_enabled: false until it has around 400 confirmed examples. We would rather report nothing for a class than report something we cannot stand behind, and the precision and recall figures are the ones measured on your held-out data, not on a benchmark.
QC reports for buyer audits
POST/v1/qc-reports
Generate a signed PDF and JSON QC report for an order or a date range.
Requires scope defects:read
GET/v1/qc-reports/{id}
Retrieve a generated report and its download URLs.
Requires scope defects:read
curl -X POST https://api.easarctech.com/v1/qc-reports \
-H "Authorization: Bearer esk_live_7f3a9c2e8b14d05a" \
-H "Easarc-Version: 2026-08-01" \
-H "Content-Type: application/json" \
-d '{
"work_order": "ESR-2026-0431",
"include_frames": true,
"language": "en",
"format": ["pdf", "json"]
}'Generation is asynchronous for large ranges. The response carries status: "processing" and you either poll the report or listen for the vision.qc_report.completed webhook, which is what we recommend.