{"openapi":"3.1.0","info":{"title":"agentblue API","version":"1.0.0","description":"The agentblue API platform. Every call is authenticated with an API key (`Authorization: Bearer blue_…`), rate-limited per key per minute (see the `X-RateLimit-*` headers), and answers JSON; every error is an RFC 9457 problem document (`application/problem+json`) with a stable `type` and the request id as `instance`. Services are versioned under `/v1/{service}`.","contact":{"email":"support@agentblue.app"}},"servers":[{"url":"https://api.agentblue.app"}],"tags":[{"name":"platform","description":"Health, your key, this document, stored files"},{"name":"faces","description":"Face detection and face-centred crops for profile pictures: send an image (by URL, upload or base64), get the faces with boxes, confidence and landmarks, or a square (or any aspect) crop centred on the face as a stored file. Engine: OpenCV YuNet (2023), on our own servers — nothing leaves the platform."}],"security":[{"bearer":[]},{"apiKey":[]}],"paths":{"/v1/health":{"get":{"tags":["platform"],"summary":"Is the API up","operationId":"health","security":[],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"},"version":{"type":"string"},"time":{"type":"string","format":"date-time"},"services":{"type":"array","items":{"type":"string"}}}}}}}}}},"/v1/me":{"get":{"tags":["platform"],"summary":"The key you are calling with","operationId":"me","responses":{"200":{"description":"The key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/KeyInfo"}}}},"401":{"$ref":"#/components/responses/Unauthorized"}}}},"/v1/openapi.json":{"get":{"tags":["platform"],"summary":"This document","operationId":"openapi","security":[],"responses":{"200":{"description":"OpenAPI 3.1"}}}},"/files/{id}":{"get":{"tags":["platform"],"summary":"A stored output (a crop, a render…), immutable, cached a year","operationId":"file","security":[],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"the id with its extension, as a service returned it (e.g. 3fK…9q.webp)"}],"responses":{"200":{"description":"The file"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/v1/faces/detect":{"post":{"tags":["faces"],"summary":"Detect faces","operationId":"facesDetect","description":"Returns every face found (largest first) with its box, confidence and five landmarks. GET with the same parameters in the query string works too.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string","format":"uri","description":"A public http(s) URL of a JPEG, PNG, GIF or WebP (up to 25 MB). Give one of url, file, image_base64."},"image_base64":{"type":"string","description":"The image as base64 (a data: URL prefix is fine)."}},"required":[]}},"multipart/form-data":{"schema":{"type":"object","properties":{"url":{"type":"string","format":"uri","description":"A public http(s) URL of a JPEG, PNG, GIF or WebP (up to 25 MB). Give one of url, file, image_base64."},"file":{"type":"string","format":"binary","description":"The image as a multipart upload (field name `file`)."},"image_base64":{"type":"string","description":"The image as base64 (a data: URL prefix is fine)."}}}}}},"x-example":"curl -X POST https://api.agentblue.app/v1/faces/detect \\\n  -H \"Authorization: Bearer blue_XXXX\" -H \"Content-Type: application/json\" \\\n  -d '{\"url\": \"https://example.com/photo.jpg\"}'","x-example-response":"{\"ok\":true,\"image\":{\"width\":1200,\"height\":800,\"mime\":\"image/jpeg\",\"bytes\":183452,\"source\":\"https://example.com/photo.jpg\"},\"count\":1,\n \"faces\":[{\"box\":{\"x\":512,\"y\":210,\"width\":190,\"height\":240},\"confidence\":0.98,\"landmarks\":{\"right_eye\":[560,290],\"left_eye\":[650,292],\"nose\":[605,345],\"mouth_right\":[570,395],\"mouth_left\":[640,397]}}],\n \"model\":\"yunet-2023mar\",\"ms\":84}","responses":{"200":{"description":"The faces","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DetectResult"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"400":{"$ref":"#/components/responses/Problem"},"413":{"$ref":"#/components/responses/Problem"},"415":{"$ref":"#/components/responses/Problem"},"429":{"$ref":"#/components/responses/RateLimited"},"502":{"$ref":"#/components/responses/Problem"}}}},"/v1/faces/crop":{"post":{"tags":["faces"],"summary":"Face-centred crop (a profile picture)","operationId":"facesCrop","description":"Finds the face (the largest by default), cuts a crop centred on it with `padding` around (0.45 = the face box's larger side plus 45 % on every side), in the `aspect` you ask, resized to `size`, encoded as `format`, and stores it: the answer carries the file's URL. When no face is found the answer is a 422 `no-face` problem — or pass `no_face=center` to crop the middle of the picture instead.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string","format":"uri","description":"A public http(s) URL of a JPEG, PNG, GIF or WebP (up to 25 MB). Give one of url, file, image_base64."},"image_base64":{"type":"string","description":"The image as base64 (a data: URL prefix is fine)."},"size":{"type":"integer","default":400,"description":"the output's longer side in pixels, 16–2048"},"padding":{"type":"number","default":0.45,"description":"room around the face, as a fraction of the face size, 0–3"},"aspect":{"type":"string","default":"1:1","description":"the crop's aspect, like 1:1, 4:3, 3:4, 16:9"},"format":{"type":"string","default":"webp","enum":["webp","jpg","png"]},"quality":{"type":"integer","default":85,"description":"1–100 (webp, jpg)"},"which":{"type":"string","default":"largest","description":"largest, first (leftmost), or a face index from /detect"},"no_face":{"type":"string","default":"error","enum":["error","center"]}},"required":[]}},"multipart/form-data":{"schema":{"type":"object","properties":{"url":{"type":"string","format":"uri","description":"A public http(s) URL of a JPEG, PNG, GIF or WebP (up to 25 MB). Give one of url, file, image_base64."},"file":{"type":"string","format":"binary","description":"The image as a multipart upload (field name `file`)."},"image_base64":{"type":"string","description":"The image as base64 (a data: URL prefix is fine)."},"size":{"type":"integer","default":400,"description":"the output's longer side in pixels, 16–2048"},"padding":{"type":"number","default":0.45,"description":"room around the face, as a fraction of the face size, 0–3"},"aspect":{"type":"string","default":"1:1","description":"the crop's aspect, like 1:1, 4:3, 3:4, 16:9"},"format":{"type":"string","default":"webp","enum":["webp","jpg","png"]},"quality":{"type":"integer","default":85,"description":"1–100 (webp, jpg)"},"which":{"type":"string","default":"largest","description":"largest, first (leftmost), or a face index from /detect"},"no_face":{"type":"string","default":"error","enum":["error","center"]}}}}}},"x-example":"curl -X POST https://api.agentblue.app/v1/faces/crop \\\n  -H \"Authorization: Bearer blue_XXXX\" -H \"Content-Type: application/json\" \\\n  -d '{\"url\": \"https://example.com/photo.jpg\", \"size\": 400, \"format\": \"webp\"}'","x-example-response":"{\"ok\":true,\"count\":1,\"face\":{\"box\":{\"x\":512,\"y\":210,\"width\":190,\"height\":240},\"confidence\":0.98,…},\n \"crop\":{\"x\":385,\"y\":97,\"width\":456,\"height\":456},\n \"file\":{\"id\":\"3fKq…\",\"url\":\"https://api.agentblue.app/files/3fKq….webp\",\"mime\":\"image/webp\",\"bytes\":21804,\"width\":400,\"height\":400,\"expires_at\":\"2027-10-17 10:00:00\"},\n \"options\":{\"size\":400,\"padding\":0.45,\"aspect\":\"1:1\",\"format\":\"webp\",\"quality\":85,\"which\":\"largest\",\"no_face\":\"error\"},\"model\":\"yunet-2023mar\",\"ms\":131}","responses":{"201":{"description":"The crop, stored","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CropResult"}}}},"422":{"description":"No face (type no-face)","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"400":{"$ref":"#/components/responses/Problem"},"413":{"$ref":"#/components/responses/Problem"},"415":{"$ref":"#/components/responses/Problem"},"429":{"$ref":"#/components/responses/RateLimited"},"502":{"$ref":"#/components/responses/Problem"}}}}},"components":{"securitySchemes":{"bearer":{"type":"http","scheme":"bearer","description":"Authorization: Bearer blue_…"},"apiKey":{"type":"apiKey","in":"header","name":"X-Api-Key"}},"schemas":{"Problem":{"type":"object","description":"RFC 9457 problem details — every error of the API","properties":{"type":{"type":"string","format":"uri","example":"https://api.agentblue.app/problems/no-face"},"title":{"type":"string"},"status":{"type":"integer"},"detail":{"type":"string"},"instance":{"type":"string","description":"the request id (also in X-Request-Id) — quote it when you write to us"},"errors":{"type":"object","additionalProperties":{"type":"string"},"description":"field → what is wrong (validation problems)"}},"required":["type","title","status"]},"KeyInfo":{"type":"object","properties":{"id":{"type":"integer"},"name":{"type":"string"},"prefix":{"type":"string"},"scopes":{"type":"array","items":{"type":"string"}},"rate_per_minute":{"type":"integer"}}},"StoredFile":{"type":"object","description":"An output the API stored for you","properties":{"id":{"type":"string"},"url":{"type":"string","format":"uri"},"mime":{"type":"string"},"bytes":{"type":"integer"},"width":{"type":"integer"},"height":{"type":"integer"},"expires_at":{"type":"string","nullable":true,"description":"when the file is removed (null = kept)"}}},"Point":{"type":"array","items":{"type":"integer"},"minItems":2,"maxItems":2,"description":"[x, y] in the original image"},"Face":{"type":"object","properties":{"box":{"type":"object","properties":{"x":{"type":"integer"},"y":{"type":"integer"},"width":{"type":"integer"},"height":{"type":"integer"}},"description":"pixels in the original image"},"confidence":{"type":"number","description":"0–1"},"landmarks":{"type":"object","properties":{"right_eye":{"$ref":"#/components/schemas/Point"},"left_eye":{"$ref":"#/components/schemas/Point"},"nose":{"$ref":"#/components/schemas/Point"},"mouth_right":{"$ref":"#/components/schemas/Point"},"mouth_left":{"$ref":"#/components/schemas/Point"}}}}},"DetectResult":{"type":"object","properties":{"ok":{"type":"boolean"},"image":{"type":"object","properties":{"width":{"type":"integer"},"height":{"type":"integer"},"mime":{"type":"string"},"bytes":{"type":"integer"},"source":{"type":"string","enum":["url","upload","base64"]}}},"count":{"type":"integer"},"faces":{"type":"array","items":{"$ref":"#/components/schemas/Face"}},"model":{"type":"string"},"ms":{"type":"integer"}}},"CropResult":{"type":"object","properties":{"ok":{"type":"boolean"},"image":{"type":"object","properties":{"width":{"type":"integer"},"height":{"type":"integer"},"mime":{"type":"string"},"bytes":{"type":"integer"},"source":{"type":"string","enum":["url","upload","base64"]}}},"count":{"type":"integer"},"face":{"$ref":"#/components/schemas/Face"},"crop":{"type":"object","properties":{"x":{"type":"integer"},"y":{"type":"integer"},"width":{"type":"integer"},"height":{"type":"integer"}}},"file":{"$ref":"#/components/schemas/StoredFile"},"options":{"type":"object"},"model":{"type":"string"},"ms":{"type":"integer"}}}},"responses":{"Problem":{"description":"A problem","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"Unauthorized":{"description":"No valid key","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"Forbidden":{"description":"The key has no scope for this service","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"NotFound":{"description":"Not found","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"RateLimited":{"description":"Too many requests (Retry-After)","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}}