Cikada Vision API
Developers
Everything the interface does, a robot can do. Authenticate with a bearer key from Settings, send images, receive typed attributes with a confidence per field. Base URL https://vision.cikadasolutions.com/api/v1. Rate limit 60 requests per minute per key. Errors always look like { "error": { "code", "message", "details?" } }.
Quickstart
curl
curl -X POST https://vision.cikadasolutions.com/api/v1/items \
-H "Authorization: Bearer ck_live_…" \
-H "Idempotency-Key: run-42-item-7" \
-F "image[]=@front.jpg" -F "view[]=front" \
-F "image[]=@label.jpg" -F "view[]=label" \
-F "external_ref=run-42-item-7"
# → 202 {"item_id":"…","status":"queued"}
curl https://vision.cikadasolutions.com/api/v1/items/ITEM_ID -H "Authorization: Bearer ck_live_…"Python
import requests
API = "https://vision.cikadasolutions.com/api/v1"
HEADERS = {"Authorization": "Bearer ck_live_…"}
# Synchronous: image in, classification out (p95 < 15 s)
with open("front.jpg", "rb") as front:
r = requests.post(f"{API}/classify/sync", headers=HEADERS,
files=[("image[]", ("front.jpg", front, "image/jpeg"))],
data={"view[]": "front", "external_ref": "run-42-item-7"})
r.raise_for_status()
item = r.json()
print(item["attributes"]["garment_type"]) # {'value': 'jeans', 'confidence': 0.97, 'source': 'model'}
print(item["attributes"]["condition_grade"]["value"], item["classification"]["recommended_route"]["value"])
# Correct a value from the operator panel
requests.patch(f"{API}/items/{item['id']}/attributes", headers=HEADERS,
json={"attributes": {"condition_grade": "C"}, "reviewer": "line-3-operator"}).raise_for_status()Endpoints
Items
Garments and their classifications
post/itemsCreate an item and queue classification
Multipart: fields image[] (1–8 files, JPEG/PNG/WebP/HEIC, 20 MB each), view[] (front|back|label|detail), external_ref, robot_id, batch_id. Or JSON with image_urls for pre-hosted HTTPS images. Send an Idempotency-Key header to make retries safe for 24 hours.
| Parameter | In | Type | Required |
|---|---|---|---|
| Idempotency-Key | header | string | no |
Request body
{
"multipart/form-data": {
"schema": {
"type": "object",
"required": [
"image[]"
],
"properties": {
"image[]": {
"type": "array",
"items": {
"type": "string",
"format": "binary"
}
},
"view[]": {
"type": "array",
"items": {
"type": "string",
"enum": [
"front",
"back",
"label",
"detail",
"unknown"
]
}
},
"external_ref": {
"type": "string",
"maxLength": 120
},
"robot_id": {
"type": "string",
"format": "uuid"
},
"batch_id": {
"type": "string",
"format": "uuid"
}
}
}
},
"application/json": {
"schema": {
"$ref": "#/components/schemas/CreateItemJson"
}
}
}Responses
{
"202": {
"description": "Item queued",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ItemAccepted"
}
}
}
},
"401": {
"description": "Missing, malformed or revoked API key",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "API key lacks the required scope",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"422": {
"description": "Request failed validation",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limit exceeded; see Retry-After",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}get/itemsList items
| Parameter | In | Type | Required |
|---|---|---|---|
| status | query | string (queued | processing | classified | reviewed | failed) | no |
| batch_id | query | string | no |
| since | query | string | no |
| cursor | query | string | no |
| limit | query | integer | no |
Responses
{
"200": {
"description": "Page of items, newest first",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ItemList"
}
}
}
},
"401": {
"description": "Missing, malformed or revoked API key",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"422": {
"description": "Request failed validation",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limit exceeded; see Retry-After",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}get/items/{id}Get an item
| Parameter | In | Type | Required |
|---|---|---|---|
| id | path | string | yes |
Responses
{
"200": {
"description": "Item with images, current attributes and prediction history",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Item"
}
}
}
},
"401": {
"description": "Missing, malformed or revoked API key",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"description": "Not found in this organization",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limit exceeded; see Retry-After",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}post/items/{id}/classifyRe-run classification
Queues a new prediction, for example after adding a label image. Existing predictions and corrections are kept.
| Parameter | In | Type | Required |
|---|---|---|---|
| id | path | string | yes |
Responses
{
"202": {
"description": "Item queued",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ItemAccepted"
}
}
}
},
"401": {
"description": "Missing, malformed or revoked API key",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "API key lacks the required scope",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"description": "Not found in this organization",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limit exceeded; see Retry-After",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}patch/items/{id}/attributesSubmit human corrections
Each changed attribute becomes a new human row beside the model row. Emits item.reviewed.
| Parameter | In | Type | Required |
|---|---|---|---|
| id | path | string | yes |
Request body
{
"application/json": {
"schema": {
"$ref": "#/components/schemas/PatchAttributes"
}
}
}Responses
{
"200": {
"description": "Corrections written",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/PatchResult"
}
}
}
},
"401": {
"description": "Missing, malformed or revoked API key",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "API key lacks the required scope",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"description": "Not found in this organization",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"422": {
"description": "Request failed validation",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limit exceeded; see Retry-After",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}Classification
Synchronous classification for low-latency robot use
post/classify/syncClassify synchronously
Same body as POST /items. The item is stored, classified inline and returned in full. Target p95 under 15 s.
Request body
{
"multipart/form-data": {
"schema": {
"type": "object",
"required": [
"image[]"
],
"properties": {
"image[]": {
"type": "array",
"items": {
"type": "string",
"format": "binary"
}
},
"view[]": {
"type": "array",
"items": {
"type": "string"
}
},
"external_ref": {
"type": "string"
},
"robot_id": {
"type": "string",
"format": "uuid"
},
"batch_id": {
"type": "string",
"format": "uuid"
}
}
}
},
"application/json": {
"schema": {
"$ref": "#/components/schemas/CreateItemJson"
}
}
}Responses
{
"200": {
"description": "Classified item",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Item"
}
}
}
},
"401": {
"description": "Missing, malformed or revoked API key",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "API key lacks the required scope",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"422": {
"description": "Request failed validation",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limit exceeded; see Retry-After",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"502": {
"description": "The model failed",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}Batches
Groups of items, such as one robot run
post/batchesCreate a batch
Request body
{
"application/json": {
"schema": {
"$ref": "#/components/schemas/CreateBatch"
}
}
}Responses
{
"201": {
"description": "Batch created",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Batch"
}
}
}
},
"401": {
"description": "Missing, malformed or revoked API key",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "API key lacks the required scope",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"422": {
"description": "Request failed validation",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limit exceeded; see Retry-After",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}get/batches/{id}Get a batch
| Parameter | In | Type | Required |
|---|---|---|---|
| id | path | string | yes |
Responses
{
"200": {
"description": "Batch",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Batch"
}
}
}
},
"401": {
"description": "Missing, malformed or revoked API key",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"description": "Not found in this organization",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limit exceeded; see Retry-After",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}get/batches/{id}/exportExport a batch
| Parameter | In | Type | Required |
|---|---|---|---|
| id | path | string | yes |
| format | query | string (csv | json) | no |
Responses
{
"200": {
"description": "All items in the batch",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"data": {
"type": "array",
"items": {
"$ref": "#/components/schemas/Item"
}
}
}
}
},
"text/csv": {
"schema": {
"type": "string"
},
"example": "id,status,...\r\n"
}
}
},
"401": {
"description": "Missing, malformed or revoked API key",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"description": "Not found in this organization",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limit exceeded; see Retry-After",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}Webhooks
Signed event deliveries with retries
post/webhooksCreate a webhook
Deliveries are JSON POSTs `{ event, item_id, org_id, occurred_at, data }` with `X-Cikada-Signature: sha256=HMAC-SHA256(secret, body)`. Failed deliveries retry after 1 m, 5 m, 30 m, 2 h and 12 h. The secret is returned once.
Request body
{
"application/json": {
"schema": {
"$ref": "#/components/schemas/CreateWebhook"
}
}
}Responses
{
"201": {
"description": "Webhook created; includes the secret",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Webhook"
}
}
}
},
"401": {
"description": "Missing, malformed or revoked API key",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "API key lacks the required scope",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"422": {
"description": "Request failed validation",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limit exceeded; see Retry-After",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}get/webhooksList webhooks
Responses
{
"200": {
"description": "Webhooks without secrets",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"data": {
"type": "array",
"items": {
"$ref": "#/components/schemas/Webhook"
}
}
}
}
}
}
},
"401": {
"description": "Missing, malformed or revoked API key",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "API key lacks the required scope",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limit exceeded; see Retry-After",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}get/webhooks/{id}Get a webhook
| Parameter | In | Type | Required |
|---|---|---|---|
| id | path | string | yes |
Responses
{
"200": {
"description": "Webhook",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Webhook"
}
}
}
},
"401": {
"description": "Missing, malformed or revoked API key",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "API key lacks the required scope",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"description": "Not found in this organization",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limit exceeded; see Retry-After",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}delete/webhooks/{id}Delete a webhook
| Parameter | In | Type | Required |
|---|---|---|---|
| id | path | string | yes |
Responses
{
"204": {
"description": "Deleted"
},
"401": {
"description": "Missing, malformed or revoked API key",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "API key lacks the required scope",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"description": "Not found in this organization",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limit exceeded; see Retry-After",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}get/webhooks/{id}/deliveriesRecent deliveries
| Parameter | In | Type | Required |
|---|---|---|---|
| id | path | string | yes |
| limit | query | integer | no |
Responses
{
"200": {
"description": "Newest first",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"data": {
"type": "array",
"items": {
"$ref": "#/components/schemas/WebhookDelivery"
}
}
}
}
}
}
},
"401": {
"description": "Missing, malformed or revoked API key",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "API key lacks the required scope",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"description": "Not found in this organization",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limit exceeded; see Retry-After",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}Reference
Taxonomy and health
get/healthService healthno auth
Responses
{
"200": {
"description": "Component status",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Health"
}
}
}
}
}get/taxonomyCurrent enums and grading rubric
Fetch once and validate locally before sending corrections.
Responses
{
"200": {
"description": "Taxonomy",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Taxonomy"
}
}
}
},
"401": {
"description": "Missing, malformed or revoked API key",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limit exceeded; see Retry-After",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}Schemas
Generated from the same Zod contracts the service validates with.
Error
{
"type": "object",
"properties": {
"error": {
"type": "object",
"properties": {
"code": {
"type": "string",
"enum": [
"validation_error",
"unauthorized",
"forbidden",
"not_found",
"rate_limited",
"model_error",
"internal"
]
},
"message": {
"type": "string"
},
"details": {}
},
"required": [
"code",
"message"
],
"additionalProperties": false
}
},
"required": [
"error"
],
"additionalProperties": false,
"description": "Every failure, on every endpoint."
}Health
{
"type": "object",
"properties": {
"status": {
"type": "string",
"enum": [
"ok",
"degraded"
]
},
"db": {
"type": "string",
"enum": [
"ok",
"error"
]
},
"storage": {
"type": "string",
"enum": [
"ok",
"error"
]
},
"model": {
"type": "string"
},
"version": {
"type": "string"
}
},
"required": [
"status",
"db",
"storage",
"model",
"version"
],
"additionalProperties": false
}Taxonomy
{
"type": "object",
"properties": {
"version": {
"type": "string"
},
"enums": {
"type": "object",
"propertyNames": {
"type": "string"
},
"additionalProperties": {
"type": "object",
"propertyNames": {
"type": "string"
},
"additionalProperties": {
"type": "string"
}
}
},
"rubric": {
"type": "object",
"propertyNames": {
"type": "string"
},
"additionalProperties": {
"type": "string"
}
},
"attributes": {
"type": "array",
"items": {
"type": "string"
}
}
},
"required": [
"version",
"enums",
"rubric",
"attributes"
],
"additionalProperties": false
}Item
{
"type": "object",
"properties": {
"id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
},
"status": {
"type": "string",
"enum": [
"queued",
"processing",
"classified",
"reviewed",
"failed"
]
},
"source": {
"type": "string",
"enum": [
"upload",
"camera",
"robot",
"api"
]
},
"external_ref": {
"type": [
"string",
"null"
]
},
"batch_id": {
"anyOf": [
{
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
},
{
"type": "null"
}
]
},
"robot_id": {
"anyOf": [
{
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
},
{
"type": "null"
}
]
},
"site_id": {
"anyOf": [
{
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
},
{
"type": "null"
}
]
},
"error": {
"type": [
"string",
"null"
]
},
"created_at": {
"type": "string",
"format": "date-time",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
},
"classified_at": {
"anyOf": [
{
"type": "string",
"format": "date-time",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
},
{
"type": "null"
}
]
},
"reviewed_at": {
"anyOf": [
{
"type": "string",
"format": "date-time",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
},
{
"type": "null"
}
]
},
"images": {
"type": "array",
"items": {
"$ref": "#/components/schemas/ItemImage"
}
},
"attributes": {
"type": "object",
"propertyNames": {
"type": "string"
},
"additionalProperties": {
"$ref": "#/components/schemas/Attribute"
}
},
"classification": {
"anyOf": [
{
"$ref": "#/components/schemas/GarmentClassification"
},
{
"type": "null"
}
],
"description": "Latest full model output, validated against the contract"
},
"predictions": {
"type": "array",
"items": {
"$ref": "#/components/schemas/Prediction"
}
}
},
"required": [
"id",
"status",
"source",
"external_ref",
"batch_id",
"robot_id",
"site_id",
"error",
"created_at",
"classified_at",
"reviewed_at",
"images",
"attributes",
"classification",
"predictions"
],
"additionalProperties": false
}ItemAccepted
{
"type": "object",
"properties": {
"item_id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
},
"status": {
"type": "string",
"const": "queued"
}
},
"required": [
"item_id",
"status"
],
"additionalProperties": false
}ItemList
{
"type": "object",
"properties": {
"data": {
"type": "array",
"items": {
"$ref": "#/components/schemas/Item"
}
},
"next_cursor": {
"type": [
"string",
"null"
]
}
},
"required": [
"data",
"next_cursor"
],
"additionalProperties": false
}CreateItemJson
{
"type": "object",
"properties": {
"image_urls": {
"minItems": 1,
"maxItems": 8,
"type": "array",
"items": {
"type": "string",
"format": "uri"
}
},
"views": {
"type": "array",
"items": {
"type": "string",
"enum": [
"front",
"back",
"label",
"detail",
"unknown"
]
}
},
"external_ref": {
"type": "string",
"maxLength": 120
},
"robot_id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
},
"batch_id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
}
},
"required": [
"image_urls"
],
"additionalProperties": false,
"description": "Alternative to multipart: images already hosted at HTTPS URLs."
}PatchAttributes
{
"type": "object",
"properties": {
"attributes": {
"type": "object",
"propertyNames": {
"type": "string"
},
"additionalProperties": {
"type": "string",
"minLength": 1,
"maxLength": 60
}
},
"reviewer": {
"type": "string",
"minLength": 1,
"maxLength": 80
}
},
"required": [
"attributes",
"reviewer"
],
"additionalProperties": false
}PatchResult
{
"type": "object",
"properties": {
"item_id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
},
"corrections": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
}
},
"required": [
"item_id",
"corrections"
],
"additionalProperties": false
}CreateBatch
{
"type": "object",
"properties": {
"name": {
"type": "string",
"minLength": 1,
"maxLength": 120
},
"source": {
"default": "robot",
"type": "string",
"enum": [
"upload",
"camera",
"robot",
"api"
]
}
},
"required": [
"name",
"source"
],
"additionalProperties": false
}Batch
{
"type": "object",
"properties": {
"id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
},
"name": {
"type": "string"
},
"source": {
"type": "string",
"enum": [
"upload",
"camera",
"robot",
"api"
]
},
"item_count": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
"created_at": {
"type": "string",
"format": "date-time",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
}
},
"required": [
"id",
"name",
"source",
"item_count",
"created_at"
],
"additionalProperties": false
}Attribute
{
"type": "object",
"properties": {
"value": {
"type": "string"
},
"confidence": {
"type": "number",
"minimum": 0,
"maximum": 1
},
"source": {
"type": "string",
"enum": [
"model",
"human"
]
},
"evidence": {
"type": [
"string",
"null"
]
}
},
"required": [
"value",
"confidence",
"source"
],
"additionalProperties": false,
"description": "Current value of one attribute: latest human correction if any, else the latest model value."
}ItemImage
{
"type": "object",
"properties": {
"id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
},
"view": {
"type": "string",
"enum": [
"front",
"back",
"label",
"detail",
"unknown"
]
},
"position": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
"width": {
"anyOf": [
{
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
{
"type": "null"
}
]
},
"height": {
"anyOf": [
{
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
{
"type": "null"
}
]
},
"urls": {
"type": "object",
"properties": {
"original": {
"anyOf": [
{
"type": "string",
"format": "uri"
},
{
"type": "null"
}
]
},
"model_input": {
"anyOf": [
{
"type": "string",
"format": "uri"
},
{
"type": "null"
}
]
},
"thumbnail": {
"anyOf": [
{
"type": "string",
"format": "uri"
},
{
"type": "null"
}
]
}
},
"required": [
"original",
"model_input",
"thumbnail"
],
"additionalProperties": false,
"description": "Signed URLs valid for one hour"
}
},
"required": [
"id",
"view",
"position",
"width",
"height",
"urls"
],
"additionalProperties": false
}Prediction
{
"type": "object",
"properties": {
"id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
},
"model": {
"type": "string"
},
"prompt_version": {
"type": "string"
},
"latency_ms": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
"input_tokens": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
"output_tokens": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
"attempts": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
"created_at": {
"type": "string",
"format": "date-time",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
}
},
"required": [
"id",
"model",
"prompt_version",
"latency_ms",
"input_tokens",
"output_tokens",
"attempts",
"created_at"
],
"additionalProperties": false
}CreateWebhook
{
"type": "object",
"properties": {
"url": {
"type": "string",
"maxLength": 2000,
"format": "uri"
},
"events": {
"minItems": 1,
"type": "array",
"items": {
"type": "string",
"enum": [
"item.classified",
"item.reviewed"
]
}
},
"description": {
"type": "string",
"maxLength": 200
}
},
"required": [
"url",
"events"
],
"additionalProperties": false
}Webhook
{
"type": "object",
"properties": {
"id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
},
"url": {
"type": "string"
},
"events": {
"type": "array",
"items": {
"type": "string"
}
},
"active": {
"type": "boolean"
},
"description": {
"type": [
"string",
"null"
]
},
"failure_count": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
"last_delivery_at": {
"anyOf": [
{
"type": "string",
"format": "date-time",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
},
{
"type": "null"
}
]
},
"created_at": {
"type": "string",
"format": "date-time",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
},
"secret": {
"description": "Only present in the creation response",
"type": "string"
}
},
"required": [
"id",
"url",
"events",
"active",
"description",
"failure_count",
"last_delivery_at",
"created_at"
],
"additionalProperties": false
}WebhookDelivery
{
"type": "object",
"properties": {
"id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
},
"event": {
"type": "string"
},
"status": {
"type": "string",
"enum": [
"pending",
"delivered",
"failed",
"exhausted"
]
},
"status_code": {
"anyOf": [
{
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
{
"type": "null"
}
]
},
"attempts": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
"next_retry_at": {
"type": "string",
"format": "date-time",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
},
"delivered_at": {
"anyOf": [
{
"type": "string",
"format": "date-time",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
},
{
"type": "null"
}
]
},
"last_error": {
"type": [
"string",
"null"
]
},
"created_at": {
"type": "string",
"format": "date-time",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
}
},
"required": [
"id",
"event",
"status",
"status_code",
"attempts",
"next_retry_at",
"delivered_at",
"last_error",
"created_at"
],
"additionalProperties": false
}GarmentClassification
{
"type": "object",
"properties": {
"garment_type": {
"type": "object",
"properties": {
"value": {
"type": "string",
"enum": [
"t_shirt",
"shirt",
"blouse",
"polo",
"tank_top",
"sweater",
"cardigan",
"hoodie",
"sweatshirt",
"vest",
"jeans",
"trousers",
"shorts",
"skirt",
"leggings",
"joggers",
"dress",
"jumpsuit",
"overalls",
"jacket",
"coat",
"blazer",
"parka",
"raincoat",
"underwear",
"socks",
"swimwear",
"sportswear",
"nightwear",
"scarf",
"hat",
"gloves",
"bag",
"shoes",
"home_textile",
"workwear",
"other",
"unknown"
],
"description": "Type of garment"
},
"confidence": {
"type": "number",
"minimum": 0,
"maximum": 1,
"description": "Confidence between 0 and 1"
},
"evidence": {
"anyOf": [
{
"type": "string",
"maxLength": 120
},
{
"type": "null"
}
]
}
},
"required": [
"value",
"confidence"
],
"additionalProperties": false
},
"garment_category": {
"type": "object",
"properties": {
"value": {
"type": "string",
"enum": [
"tops",
"bottoms",
"full_body",
"outerwear",
"underwear",
"accessories",
"footwear",
"home_textile",
"other",
"unknown"
],
"description": "Category the garment type belongs to"
},
"confidence": {
"type": "number",
"minimum": 0,
"maximum": 1,
"description": "Confidence between 0 and 1"
},
"evidence": {
"anyOf": [
{
"type": "string",
"maxLength": 120
},
{
"type": "null"
}
]
}
},
"required": [
"value",
"confidence"
],
"additionalProperties": false
},
"primary_color": {
"type": "object",
"properties": {
"value": {
"type": "string",
"enum": [
"black",
"white",
"grey",
"navy",
"blue",
"light_blue",
"green",
"olive",
"red",
"burgundy",
"pink",
"purple",
"orange",
"yellow",
"beige",
"brown",
"cream",
"multicolor",
"unknown"
],
"description": "Colour covering most of the garment"
},
"confidence": {
"type": "number",
"minimum": 0,
"maximum": 1,
"description": "Confidence between 0 and 1"
},
"evidence": {
"anyOf": [
{
"type": "string",
"maxLength": 120
},
{
"type": "null"
}
]
}
},
"required": [
"value",
"confidence"
],
"additionalProperties": false
},
"secondary_color": {
"type": "object",
"properties": {
"value": {
"type": "string",
"enum": [
"black",
"white",
"grey",
"navy",
"blue",
"light_blue",
"green",
"olive",
"red",
"burgundy",
"pink",
"purple",
"orange",
"yellow",
"beige",
"brown",
"cream",
"multicolor",
"none",
"unknown"
],
"description": "Second most prominent colour, or none"
},
"confidence": {
"type": "number",
"minimum": 0,
"maximum": 1,
"description": "Confidence between 0 and 1"
},
"evidence": {
"anyOf": [
{
"type": "string",
"maxLength": 120
},
{
"type": "null"
}
]
}
},
"required": [
"value",
"confidence"
],
"additionalProperties": false
},
"color_hex": {
"type": "object",
"properties": {
"value": {
"anyOf": [
{
"type": "string",
"pattern": "^#[0-9A-F]{6}$",
"description": "Dominant colour as an uppercase hex value like #1B4D3E"
},
{
"type": "string",
"const": "unknown"
}
]
},
"confidence": {
"type": "number",
"minimum": 0,
"maximum": 1,
"description": "Confidence between 0 and 1"
},
"evidence": {
"anyOf": [
{
"type": "string",
"maxLength": 120
},
{
"type": "null"
}
]
}
},
"required": [
"value",
"confidence"
],
"additionalProperties": false
},
"pattern": {
"type": "object",
"properties": {
"value": {
"type": "string",
"enum": [
"solid",
"striped",
"checked",
"floral",
"graphic_print",
"logo_print",
"dotted",
"camouflage",
"animal",
"abstract",
"other",
"unknown"
],
"description": "Surface pattern"
},
"confidence": {
"type": "number",
"minimum": 0,
"maximum": 1,
"description": "Confidence between 0 and 1"
},
"evidence": {
"anyOf": [
{
"type": "string",
"maxLength": 120
},
{
"type": "null"
}
]
}
},
"required": [
"value",
"confidence"
],
"additionalProperties": false
},
"condition_grade": {
"type": "object",
"properties": {
"value": {
"type": "string",
"enum": [
"A",
"B",
"C",
"D",
"unknown"
],
"description": "Condition grade A to D per the rubric"
},
"confidence": {
"type": "number",
"minimum": 0,
"maximum": 1,
"description": "Confidence between 0 and 1"
},
"evidence": {
"anyOf": [
{
"type": "string",
"maxLength": 120
},
{
"type": "null"
}
]
}
},
"required": [
"value",
"confidence"
],
"additionalProperties": false
},
"defects": {
"type": "array",
"items": {
"type": "object",
"properties": {
"type": {
"type": "string",
"enum": [
"stain",
"hole",
"tear",
"pilling",
"fading",
"missing_button",
"broken_zipper",
"stretched",
"odor_visible_signs",
"discoloration",
"other"
]
},
"severity": {
"type": "string",
"enum": [
"minor",
"moderate",
"severe"
]
},
"location": {
"type": "string",
"maxLength": 60,
"description": "Where on the garment, at most 60 characters"
},
"confidence": {
"type": "number",
"minimum": 0,
"maximum": 1,
"description": "Confidence between 0 and 1"
}
},
"required": [
"type",
"severity",
"location",
"confidence"
],
"additionalProperties": false
}
},
"recommended_route": {
"type": "object",
"properties": {
"value": {
"type": "string",
"enum": [
"reuse",
"repair",
"recycle_fiber",
"waste",
"unknown"
],
"description": "Recommended handling route"
},
"confidence": {
"type": "number",
"minimum": 0,
"maximum": 1,
"description": "Confidence between 0 and 1"
},
"evidence": {
"anyOf": [
{
"type": "string",
"maxLength": 120
},
{
"type": "null"
}
]
}
},
"required": [
"value",
"confidence"
],
"additionalProperties": false
},
"material_primary": {
"type": "object",
"properties": {
"value": {
"type": "string",
"enum": [
"cotton",
"polyester",
"wool",
"viscose",
"linen",
"nylon",
"acrylic",
"elastane",
"silk",
"cashmere",
"denim_cotton",
"leather",
"blend",
"unknown"
],
"description": "Main fibre"
},
"confidence": {
"type": "number",
"minimum": 0,
"maximum": 1,
"description": "Confidence between 0 and 1"
},
"evidence": {
"anyOf": [
{
"type": "string",
"maxLength": 120
},
{
"type": "null"
}
]
}
},
"required": [
"value",
"confidence"
],
"additionalProperties": false
},
"material_composition": {
"type": "array",
"items": {
"type": "object",
"properties": {
"fiber": {
"type": "string",
"description": "Fibre name as printed on the care label"
},
"percent": {
"type": "number",
"minimum": 0,
"maximum": 100,
"description": "Percentage 0 to 100"
}
},
"required": [
"fiber",
"percent"
],
"additionalProperties": false
},
"description": "Only from a visible care label. Empty when no label is readable."
},
"material_source": {
"type": "string",
"enum": [
"care_label_ocr",
"visual_estimate",
"unknown"
]
},
"brand": {
"type": "object",
"properties": {
"value": {
"type": "string",
"maxLength": 60,
"description": "Brand from a visible label or unmistakable logo. Use \"unknown\" when not visible."
},
"confidence": {
"type": "number",
"minimum": 0,
"maximum": 1,
"description": "Confidence between 0 and 1"
},
"evidence": {
"anyOf": [
{
"type": "string",
"maxLength": 120
},
{
"type": "null"
}
]
}
},
"required": [
"value",
"confidence"
],
"additionalProperties": false
},
"size": {
"type": "object",
"properties": {
"value": {
"type": "string",
"maxLength": 12,
"description": "Size from a visible label. Use \"unknown\" when not visible."
},
"confidence": {
"type": "number",
"minimum": 0,
"maximum": 1,
"description": "Confidence between 0 and 1"
},
"evidence": {
"anyOf": [
{
"type": "string",
"maxLength": 120
},
{
"type": "null"
}
]
}
},
"required": [
"value",
"confidence"
],
"additionalProperties": false
},
"gender_segment": {
"type": "object",
"properties": {
"value": {
"type": "string",
"enum": [
"women",
"men",
"unisex",
"kids",
"baby",
"unknown"
],
"description": "Intended wearer"
},
"confidence": {
"type": "number",
"minimum": 0,
"maximum": 1,
"description": "Confidence between 0 and 1"
},
"evidence": {
"anyOf": [
{
"type": "string",
"maxLength": 120
},
{
"type": "null"
}
]
}
},
"required": [
"value",
"confidence"
],
"additionalProperties": false
},
"sleeve_length": {
"type": "object",
"properties": {
"value": {
"type": "string",
"enum": [
"sleeveless",
"short",
"three_quarter",
"long",
"not_applicable",
"unknown"
],
"description": "Sleeve length"
},
"confidence": {
"type": "number",
"minimum": 0,
"maximum": 1,
"description": "Confidence between 0 and 1"
},
"evidence": {
"anyOf": [
{
"type": "string",
"maxLength": 120
},
{
"type": "null"
}
]
}
},
"required": [
"value",
"confidence"
],
"additionalProperties": false
},
"closure": {
"type": "object",
"properties": {
"value": {
"type": "string",
"enum": [
"none",
"buttons",
"zipper",
"hook",
"drawstring",
"velcro",
"other",
"unknown"
],
"description": "Main closure"
},
"confidence": {
"type": "number",
"minimum": 0,
"maximum": 1,
"description": "Confidence between 0 and 1"
},
"evidence": {
"anyOf": [
{
"type": "string",
"maxLength": 120
},
{
"type": "null"
}
]
}
},
"required": [
"value",
"confidence"
],
"additionalProperties": false
},
"season": {
"type": "object",
"properties": {
"value": {
"type": "string",
"enum": [
"summer",
"winter",
"all_season",
"unknown"
],
"description": "Season the garment is made for"
},
"confidence": {
"type": "number",
"minimum": 0,
"maximum": 1,
"description": "Confidence between 0 and 1"
},
"evidence": {
"anyOf": [
{
"type": "string",
"maxLength": 120
},
{
"type": "null"
}
]
}
},
"required": [
"value",
"confidence"
],
"additionalProperties": false
},
"care_label_text": {
"description": "Verbatim text of a visible care label, or null",
"anyOf": [
{
"type": "string",
"maxLength": 500
},
{
"type": "null"
}
]
},
"notes": {
"description": "Anything an operator should know, or null",
"anyOf": [
{
"type": "string",
"maxLength": 300
},
{
"type": "null"
}
]
}
},
"required": [
"garment_type",
"garment_category",
"primary_color",
"secondary_color",
"color_hex",
"pattern",
"condition_grade",
"defects",
"recommended_route",
"material_primary",
"material_composition",
"material_source",
"brand",
"size",
"gender_segment",
"sleeve_length",
"closure",
"season"
],
"additionalProperties": false,
"description": "Full model output: every attribute with a 0–1 confidence, defects, composition and label text."
}Webhooks
Subscribe in Settings to item.classified and item.reviewed. Each delivery is a JSON POST { event, item_id, org_id, occurred_at, data } signed with your endpoint secret. Verify before acting on it. Failed deliveries retry five times over twelve hours.
import hashlib, hmac
def verify(secret: str, body: bytes, signature_header: str) -> bool:
# X-Cikada-Signature: sha256=<hex HMAC of the raw body>
expected = "sha256=" + hmac.new(secret.encode(), body, hashlib.sha256).hexdigest()
return hmac.compare_digest(expected, signature_header)