v2 responses & errors
The API v2 reference lets you browse the endpoints interactively. This page covers the request rules, response fields and error codes in detail.
- Base path:
/v2 - Content type:
application/jsonfor requests and responses - Authentication:
api-keyheader (Authentication) - Machine-readable spec (public):
GET /v2/openapi.json(OpenAPI 3.1). Interactive docs are at/v2/docs(Swagger UI) and/v2/redoc. The spec declares theapi-keyheader as theApiKeyAuthsecurity scheme and uses stable operation IDspredictandpredict_with_model, suitable for generating client SDKs.
Request notes
POST /v2/predict
Analyse one image with the latest model.
Headers
| Header | Required | Description |
|---|---|---|
api-key |
Yes | Your API key |
Content-Type |
Yes | application/json |
X-Request-ID |
No | Your own request ID (Request IDs) |
Request body
| Field | Type | Required | Description |
|---|---|---|---|
image |
string | Yes | Base64-encoded image (Image best practices). Must not be empty. |
threshold |
number or null |
No | Discomfort threshold, 0.0 ≤ threshold ≤ 1.0 (integers 0 and 1 accepted). Must be a JSON number. Strings ("0.5"), booleans, NaN, and Infinity are rejected. If omitted or null, the model's default is used. |
Unknown fields in the request body are ignored.
{
"image": "/9j/4AAQSkZJRgABAQAAAQABAAD...",
"threshold": 0.5
}
Response 200 OK: see Response schema.
Errors: 400, 401, 422, 500 (Errors).
POST /v2/models/{model_id}/predict
Identical to POST /v2/predict, but uses the model you name.
| Path parameter | Type | Description |
|---|---|---|
model_id |
string | Model identifier, e.g. bc-v1 (Choosing a model in v2) |
Headers, body, and response are the same as POST /v2/predict. An unknown model_id returns 404 model_not_found.
curl -X POST "$BASE_URL/v2/models/bc-v1/predict" \
-H "api-key: $API_KEY" -H "Content-Type: application/json" \
--data @body.json
Response schema
Every key below is always present. Keys that don't apply are null, never missing.
| Field | Type | Description |
|---|---|---|
request_id |
string | Request ID (also in the X-Request-ID header) |
model |
object | Model that produced the result |
model.id |
string | Model identifier, e.g. "bc-v1" |
model.version |
string | Sylvester service release version, e.g. "0.0.34" |
detection |
string | "detected", "low_confidence", or "not_detected" (Detection) |
prediction |
object | null | Present only when detection is "detected" |
prediction.label |
string | "comfort" or "discomfort" |
prediction.score |
number | Probability of discomfort, 0.0–1.0 |
prediction.threshold |
number | Threshold applied. label is "discomfort" when score > threshold. |
cat |
object | null | The detected cat (detected) or best candidate (low_confidence); null when not_detected |
cat.bounding_box |
object | x_min, y_min, x_max, y_max (integers, pixels; Bounding box coordinates) |
cat.detection_confidence |
number | Detector confidence for this cat, 0.0–1.0 |
image |
object | The decoded input image |
image.width |
integer | Width in pixels |
image.height |
integer | Height in pixels |
More attributes may be added inside
catin future (for example coat colour or estimated age), each shaped as{ "value": ..., "confidence": ... }. Ignore keys you don't use.
Response examples
Cat detected
{
"request_id": "req_743a78dbedca420f9ab7dac5dd0df7d7",
"model": { "id": "bc-v1", "version": "0.0.34" },
"detection": "detected",
"prediction": {
"label": "discomfort",
"score": 0.32395651936531067,
"threshold": 0.3
},
"cat": {
"bounding_box": { "x_min": 56, "y_min": 74, "x_max": 1005, "y_max": 1013 },
"detection_confidence": 0.9662923216819763
},
"image": { "width": 1028, "height": 1028 }
}
Low confidence: a cat-like object was found, but not clearly enough to classify
{
"request_id": "smoke-1",
"model": { "id": "bc-v1", "version": "0.0.34" },
"detection": "low_confidence",
"prediction": null,
"cat": {
"bounding_box": { "x_min": 4, "y_min": 74, "x_max": 1013, "y_max": 775 },
"detection_confidence": 0.6602507829666138
},
"image": { "width": 1028, "height": 1028 }
}
No cat detected
{
"request_id": "req_0b7c2d0e8e1d4a5f9c3b6a1e2d4f8a90",
"model": { "id": "bc-v1", "version": "0.0.34" },
"detection": "not_detected",
"prediction": null,
"cat": null,
"image": { "width": 1920, "height": 1080 }
}
Errors
All v2 errors (4xx/5xx generated by the API) share one shape:
{
"request_id": "req_60b465463f52493c8c085a5e74445c67",
"error": {
"code": "invalid_image",
"message": "Image is not valid base64.",
"details": {}
}
}
| Field | Type | Description |
|---|---|---|
request_id |
string | Same as the X-Request-ID response header |
error.code |
string | Stable, machine-readable code. Branch on this. |
error.message |
string | Human-readable explanation. The wording may change, so don't parse it. |
error.details |
object | Extra structured information; {} when there is none |
Error codes
| HTTP | code |
When | message examples |
details |
|---|---|---|---|---|
| 400 | invalid_image |
Not valid base64, empty, not a decodable image, or unsupported bit depth | Image is not valid base64. · Image is empty. · Image could not be decoded. · Unsupported pixel format; send an 8-bit image. |
{} |
| 401 | unauthorized |
Missing or invalid api-key |
Invalid or missing API key. |
{} |
| 404 | model_not_found |
Unknown model_id |
Model 'bc-v9' does not exist. |
{"model_id": "bc-v9"} |
| 404 | not_found |
Unknown path under /v2 |
Not Found |
{} |
| 405 | method_not_allowed |
Wrong HTTP method (the Allow response header lists valid methods) |
Method Not Allowed |
{} |
| 422 | invalid_request |
Body missing, malformed JSON, missing image, invalid threshold |
Request validation failed. |
{"errors": [{"field": "...", "message": "..."}]} |
| 500 | internal_error |
Unexpected server failure | An internal error occurred. |
{} |
| other 4xx | http_error |
Other protocol-level errors | varies | {} |
New codes may be added. Treat unknown codes by their HTTP status.
422 examples
Missing image:
{
"request_id": "doc-example-1",
"error": {
"code": "invalid_request",
"message": "Request validation failed.",
"details": {
"errors": [ { "field": "image", "message": "Field required" } ]
}
}
}
threshold out of range (1.5):
{
"request_id": "doc-example-1",
"error": {
"code": "invalid_request",
"message": "Request validation failed.",
"details": {
"errors": [ { "field": "threshold", "message": "Input should be less than or equal to 1" } ]
}
}
}
threshold sent as a string ("0.5"):
{ "field": "threshold", "message": "Input should be a valid number" }
Malformed JSON body:
{ "field": "body", "message": "JSON decode error" }
details.errors[].field names the request field (image, threshold), or body when the body as a whole is the problem. The submitted values are never echoed back in error responses.