{"openapi":"3.0.3","info":{"title":"Hotdog API","version":"1.0","description":"Send a picture, find out whether it shows a hot dog.\n\n**Get started in three steps, right from this page:**\n1. Open *Get a key* → `POST /v1/keys`, click *Try it out*, type your name, *Execute*.\n   **Copy the `api_key` from the answer: it is shown only once.**\n2. Click *Authorize* (top right), paste the key, *Authorize*.\n3. Try any endpoint. `GET /v1/me` is a good first call: it checks that your key works.\n\nYour key is free (100 classifications a day). To practise without using your quota, the sandbox keys\nalways give the same verdict: `hd_test_hotdog_000000000000000000000000000000` (always a hot dog) and\n`hd_test_nothotdog_0000000000000000000000000000` (never one). The shared demo key\n`hd_demo_0000000000000000000000000000000000000000` allows only 20 requests a day for everybody.\n\nImages are analysed in memory and never stored. Only the verdict is kept.\n\nEvery error has the same shape, `{\"error\": {\"code\": \"...\", \"message\": \"...\"}}`, and `code` is stable.\n"},"servers":[{"url":"/"}],"security":[{"ApiKeyAuth":[]},{"BearerAuth":[]}],"tags":[{"name":"Get a key","description":"Sign up for a free API key, no account needed"},{"name":"Discovery","description":"Check the API and your key, and find example images"},{"name":"Classification","description":"Is it a hot dog? Send an image or a URL"},{"name":"History","description":"The verdicts you obtained, kept without the image"},{"name":"Hot dogs","description":"Your own collection of hot dogs"},{"name":"Webhooks","description":"Be told when a classification is completed"}],"paths":{"/v1/keys":{"post":{"operationId":"createApiKey","tags":["Get a key"],"summary":"Get a free API key","description":"No account, e-mail or password: the key is your identity. It is shown **only once**, so store it.\nIf you lose it, create another one. Free plan: 100 classifications a day. Reading your data (history,\nhot dogs, webhooks) is not counted. Sign-ups are limited per IP address (30 an hour).\n","security":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["name"],"properties":{"name":{"type":"string","maxLength":60,"example":"Jian Yang","description":"Who or what the key is for (your name, the app you build...)"}}}}}},"responses":{"201":{"description":"Your key. Copy `api_key` now.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NewApiKey"}}}},"422":{"$ref":"#/components/responses/ValidationFailed"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/v1/ping":{"get":{"operationId":"ping","tags":["Discovery"],"summary":"Availability probe","description":"Needs no key and touches neither the database nor the model.","security":[],"responses":{"200":{"description":"The API is up","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","example":"This app is not Jian Yang related"}}}}}},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/v1/me":{"get":{"operationId":"getMe","tags":["Discovery"],"summary":"Your plan and remaining quota","description":"Also a quick way to check that a key works. Does not use any quota.","responses":{"200":{"description":"The key's plan and its daily quota","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Me"}}}},"401":{"$ref":"#/components/responses/Unauthorized"}}},"delete":{"operationId":"revokeApiKey","tags":["Get a key"],"summary":"Revoke your own key","description":"Deletes the key used for the request and everything attached to it (history, hot dogs, webhooks).\nIt stops working at once. The shared demo and sandbox keys cannot be revoked.\n","responses":{"204":{"description":"Revoked"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"description":"The shared demo and sandbox keys cannot be revoked (`key_not_revocable`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/samples":{"get":{"operationId":"listSamples","tags":["Discovery"],"summary":"Example images","description":"Pictures to try the API without a file of your own, with the expected verdict.\nPass a `url` to `POST /v1/classifications/from_url` (the API must be reachable from the internet,\nas private addresses are refused), or download it and upload it.\n","security":[],"responses":{"200":{"description":"The samples","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Sample"}}}}}}},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/v1/classifications":{"post":{"operationId":"classifyUpload","tags":["Classification"],"summary":"Classify an uploaded image","description":"Accepted formats: JPEG, PNG, GIF (first frame), WebP, TIFF, HEIC and AVIF. The format is detected from\nthe content, never from the file name or `Content-Type`. Limits: 10 MB and 50 million pixels.\nCounts as one request against the daily quota.\n","requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"type":"object","required":["image"],"properties":{"image":{"type":"string","format":"binary","description":"The picture"},"label":{"type":"string","maxLength":100,"description":"Optional free-form name, kept in your history"}}}}}},"responses":{"201":{"$ref":"#/components/responses/ClassificationCreated"},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"413":{"$ref":"#/components/responses/TooLarge"},"415":{"$ref":"#/components/responses/UnsupportedFormat"},"422":{"$ref":"#/components/responses/Unprocessable"},"429":{"$ref":"#/components/responses/QuotaExceeded"},"503":{"$ref":"#/components/responses/ModelUnavailable"}}},"get":{"operationId":"listClassifications","tags":["History"],"summary":"Your classification history","description":"Newest first, cursor-paginated. Does not use any quota.","parameters":[{"$ref":"#/components/parameters/Limit"},{"$ref":"#/components/parameters/After"},{"$ref":"#/components/parameters/CreatedAfter"},{"name":"hotdog","in":"query","description":"Keep only hot dogs (`true`) or only the rest (`false`)","schema":{"type":"boolean"}}],"responses":{"200":{"description":"A page of history","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Page"},{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Classification"}}}}]}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"}}}},"/v1/classifications/from_url":{"post":{"operationId":"classifyUrl","tags":["Classification"],"summary":"Classify an image found at a URL","description":"The server downloads the image. Only `http` and `https` on ports 80 and 443 are accepted, without\ncredentials in the URL. Private, local and link-local addresses are refused, after DNS resolution and\nat every redirect (3 at most). Counts as one request against the daily quota.\n","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["url"],"properties":{"url":{"type":"string","format":"uri","example":"https://upload.wikimedia.org/wikipedia/commons/b/b1/Hot_dog_with_mustard.png"},"label":{"type":"string","maxLength":100}}}}}},"responses":{"201":{"$ref":"#/components/responses/ClassificationCreated"},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"413":{"$ref":"#/components/responses/TooLarge"},"415":{"$ref":"#/components/responses/UnsupportedFormat"},"422":{"description":"The image is corrupted (`invalid_image`), the URL is invalid (`invalid_url`), points to a private\naddress (`url_not_allowed`), or could not be fetched (`url_unreachable`)\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"$ref":"#/components/responses/QuotaExceeded"},"503":{"$ref":"#/components/responses/ModelUnavailable"}}}},"/v1/classifications/{id}":{"parameters":[{"$ref":"#/components/parameters/Id"}],"get":{"operationId":"getClassification","tags":["History"],"summary":"One history entry","responses":{"200":{"description":"The entry","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Classification"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}},"patch":{"operationId":"updateClassification","tags":["History"],"summary":"Rename an entry","description":"Only `label` can be changed.","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"label":{"type":"string","maxLength":100,"nullable":true}}}}}},"responses":{"200":{"description":"The updated entry","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Classification"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"},"422":{"$ref":"#/components/responses/ValidationFailed"}}},"delete":{"operationId":"deleteClassification","tags":["History"],"summary":"Delete an entry","responses":{"204":{"description":"Deleted"},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/v1/hotdogs":{"get":{"operationId":"listHotdogs","tags":["Hot dogs"],"summary":"List your hot dogs","description":"Newest first, cursor-paginated.","parameters":[{"$ref":"#/components/parameters/Limit"},{"$ref":"#/components/parameters/After"},{"$ref":"#/components/parameters/CreatedAfter"},{"name":"style","in":"query","schema":{"$ref":"#/components/schemas/HotdogStyle"}},{"name":"min_rating","in":"query","description":"Keep hot dogs rated at least this (unrated ones are left out)","schema":{"type":"integer","minimum":1,"maximum":5}},{"name":"q","in":"query","description":"Part of the name","schema":{"type":"string"}},{"name":"spot_id","in":"query","description":"Only the hot dogs sold at this spot","schema":{"type":"integer"}}],"responses":{"200":{"description":"A page of hot dogs","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Page"},{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Hotdog"}}}}]}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"}}},"post":{"operationId":"createHotdog","tags":["Hot dogs"],"summary":"Add a hot dog","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HotdogInput"}},"application/x-www-form-urlencoded":{"schema":{"$ref":"#/components/schemas/HotdogInput"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Hotdog"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"422":{"$ref":"#/components/responses/ValidationFailed"}}}},"/v1/hotdogs/{id}":{"parameters":[{"$ref":"#/components/parameters/Id"}],"get":{"operationId":"getHotdog","tags":["Hot dogs"],"summary":"One hot dog","responses":{"200":{"description":"The hot dog","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Hotdog"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}},"patch":{"operationId":"updateHotdog","tags":["Hot dogs"],"summary":"Update a hot dog","description":"Only the fields you send are changed.","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HotdogInput"}}}},"responses":{"200":{"description":"The updated hot dog","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Hotdog"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"},"422":{"$ref":"#/components/responses/ValidationFailed"}}},"delete":{"operationId":"deleteHotdog","tags":["Hot dogs"],"summary":"Delete a hot dog","responses":{"204":{"description":"Deleted"},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/v1/spots":{"get":{"operationId":"listSpots","tags":["Hot dogs"],"summary":"List your spots","description":"The places that sell hot dogs. This is the list to use for a **dynamic dropdown** (a \"dynamic select\"\nin Make and Zapier, options loaded from the API). Newest first, cursor-paginated.\n","parameters":[{"$ref":"#/components/parameters/Limit"},{"$ref":"#/components/parameters/After"},{"$ref":"#/components/parameters/CreatedAfter"},{"name":"city","in":"query","description":"Only the spots of this city (not case sensitive)","schema":{"type":"string"}},{"name":"q","in":"query","description":"Part of the name","schema":{"type":"string"}}],"responses":{"200":{"description":"A page of spots","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Page"},{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Spot"}}}}]}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"}}},"post":{"operationId":"createSpot","tags":["Hot dogs"],"summary":"Add a spot","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SpotInput"}},"application/x-www-form-urlencoded":{"schema":{"$ref":"#/components/schemas/SpotInput"}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Spot"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"422":{"$ref":"#/components/responses/ValidationFailed"}}}},"/v1/spots/{id}":{"parameters":[{"$ref":"#/components/parameters/Id"}],"get":{"operationId":"getSpot","tags":["Hot dogs"],"summary":"One spot","responses":{"200":{"description":"The spot","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Spot"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/v1/usage":{"get":{"operationId":"getUsage","tags":["Discovery"],"summary":"Your calls, per integration","description":"Counts the calls made with your key under each `X-Integration-Source` value (`zapier`, `make`, `n8n`,\n`postman`...), and how many failed. This is how you measure which platform brings the traffic.\nCalls sent without the header are counted as `unknown`.\n","responses":{"200":{"description":"One entry per source, the busiest first","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/SourceUsage"}},"total_requests":{"type":"integer"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"}}}},"/v1/errors/{status}":{"get":{"operationId":"simulateError","tags":["Discovery"],"summary":"Get an error on purpose","description":"Answers with the error you ask for, in the usual format, so you can test how your integration handles it\n(Make's review requires a scenario that fails on purpose). Nothing is really broken. Available: 400\n(`bad_request`), 401 (`invalid_api_key`), 403 (`forbidden`), 404 (`not_found`), 422 (`validation_failed`),\n429 (`rate_limited`, with `Retry-After: 2`), 500 (`internal_error`) and 503 (`service_unavailable`).\nThe call is counted as an error in `GET /v1/usage`.\n","parameters":[{"name":"status","in":"path","required":true,"schema":{"type":"integer","enum":[400,401,403,404,422,429,500,503],"example":429}}],"responses":{"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"description":"Simulated 403","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"$ref":"#/components/responses/NotFound"},"422":{"$ref":"#/components/responses/ValidationFailed"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"description":"Simulated 500 (`internal_error`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Simulated 503 (`service_unavailable`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/me/data":{"get":{"operationId":"getMyData","tags":["Get a key"],"summary":"Everything your key has stored, in one call","description":"Your hot dogs, spots, classification history, webhooks and usage figures, each list newest first and\nlimited to 100 entries (`next_cursor` is not `null` when there are more: use the list endpoints to go on).\nThis is what the home page shows in \"My data\".\n\nThe answer carries an `ETag`. Send it back as `If-None-Match` to get an empty `304` as long as nothing has\nchanged: the cheap way to keep a screen up to date, instead of reading each list again. The usage figures\nare part of it, so an ordinary call made with the key counts as a change; the home page sends\n`X-Integration-Source: interface-sync`, which is not counted.\n","responses":{"200":{"description":"Your data","headers":{"ETag":{"description":"Changes whenever something is added","changed or removed":null,"schema":{"type":"string"}}},"content":{"application/json":{"schema":{"type":"object","properties":{"hotdogs":{"allOf":[{"$ref":"#/components/schemas/Page"},{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Hotdog"}}}}]},"spots":{"allOf":[{"$ref":"#/components/schemas/Page"},{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Spot"}}}}]},"classifications":{"allOf":[{"$ref":"#/components/schemas/Page"},{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Classification"}}}}]},"webhooks":{"allOf":[{"$ref":"#/components/schemas/Page"},{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Webhook"}}}}]},"usage":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/SourceUsage"}},"total_requests":{"type":"integer"}}}}}}}},"304":{"description":"Nothing has changed since the `ETag` you sent"},"401":{"$ref":"#/components/responses/Unauthorized"}}},"delete":{"operationId":"resetMyData","tags":["Get a key"],"summary":"Empty everything and start again","description":"Deletes your hot dogs, spots, history, webhooks and usage figures, and **keeps your key and its quota**.\nHandy to repeat an exercise from scratch. No webhook event is sent. Not available on the shared demo and\nsandbox keys.\n","responses":{"204":{"description":"Everything is gone"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"description":"The shared demo and sandbox keys cannot be reset (`key_not_allowed`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/webhooks":{"get":{"operationId":"listWebhooks","tags":["Webhooks"],"summary":"List your webhooks","parameters":[{"$ref":"#/components/parameters/Limit"},{"$ref":"#/components/parameters/After"}],"responses":{"200":{"description":"A page of webhooks","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Page"},{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Webhook"}}}}]}}}},"401":{"$ref":"#/components/responses/Unauthorized"}}},"post":{"operationId":"createWebhook","tags":["Webhooks"],"summary":"Subscribe a URL to classification.completed","description":"Up to 5 per key, with **your own key** (the shared demo and sandbox keys cannot use webhooks). In production the URL must be `https`, on a webhook domain of your platform (Make, Zapier, n8n...); ports other than 80 and 443 are refused. Choose the events with `events`: `classification.completed`, `hotdog.created`, `hotdog.updated`, `hotdog.deleted`.\n**The `secret` is shown only in this response.** Each event is a signed `POST`:\nheader `X-Hotdog-Signature: t=<unix time>,v1=<hex HMAC-SHA256 of \"<t>.<raw body>\" with the secret>`.\nAny 2xx answer is a success; otherwise the delivery is retried (5 attempts in all). Redirects are not followed.\n","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["url"],"properties":{"url":{"type":"string","format":"uri","example":"https://example.com/hotdog-hook"},"events":{"type":"array","description":"The events to receive. Without it, all of them.","items":{"$ref":"#/components/schemas/WebhookEvent"},"example":["hotdog.created"]}}}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookWithSecret"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"description":"The shared demo and sandbox keys cannot use webhooks (`key_not_allowed`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"$ref":"#/components/responses/ValidationFailed"}}}},"/v1/webhooks/{id}":{"parameters":[{"$ref":"#/components/parameters/Id"}],"get":{"operationId":"getWebhook","tags":["Webhooks"],"summary":"One webhook","responses":{"200":{"description":"The webhook (without its secret)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Webhook"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}},"delete":{"operationId":"deleteWebhook","tags":["Webhooks"],"summary":"Unsubscribe","responses":{"204":{"description":"Deleted, with its delivery log"},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/v1/webhooks/{id}/test":{"parameters":[{"$ref":"#/components/parameters/Id"}],"post":{"operationId":"testWebhook","tags":["Webhooks"],"summary":"Send a sample event now","description":"Delivers a `webhook.test` event synchronously. Counts as one request against the daily quota.","responses":{"200":{"description":"The result, whether it worked or not (see `status`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Delivery"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/QuotaExceeded"}}}},"/v1/webhooks/{id}/deliveries":{"parameters":[{"$ref":"#/components/parameters/Id"}],"get":{"operationId":"listWebhookDeliveries","tags":["Webhooks"],"summary":"Delivery log of a webhook","description":"Newest first, cursor-paginated.","parameters":[{"$ref":"#/components/parameters/Limit"},{"$ref":"#/components/parameters/After"}],"responses":{"200":{"description":"A page of deliveries","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Page"},{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Delivery"}}}}]}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}}}},"components":{"securitySchemes":{"ApiKeyAuth":{"type":"apiKey","in":"header","name":"X-API-Key","description":"Your API key. Send an `X-Integration-Source` header too (zapier, make, n8n, postman...) so your calls are counted per platform (`GET /v1/usage`)."},"BearerAuth":{"type":"http","scheme":"bearer","description":"The same key, as `Authorization: Bearer <key>`. Use whichever your platform prefers."}},"parameters":{"Id":{"name":"id","in":"path","required":true,"schema":{"type":"integer"}},"Limit":{"name":"limit","in":"query","description":"Page size","schema":{"type":"integer","minimum":1,"maximum":100,"default":20}},"CreatedAfter":{"name":"created_after","in":"query","description":"Keep what was created strictly after this moment (ISO 8601, e.g. `2026-10-16T18:00:00Z`). Handy for a polling trigger.","schema":{"type":"string","format":"date-time"}},"After":{"name":"after","in":"query","description":"The `next_cursor` of the previous page","schema":{"type":"string","example":"41"}}},"headers":{"RateLimitLimit":{"description":"Requests allowed per day for your key","schema":{"type":"integer"}},"RateLimitRemaining":{"description":"Requests left today","schema":{"type":"integer"}},"RateLimitReset":{"description":"Seconds until the quota resets (midnight UTC)","schema":{"type":"integer"}}},"responses":{"ClassificationCreated":{"description":"The verdict, also recorded in your history","headers":{"RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Classification"}}}},"BadRequest":{"description":"A parameter is missing or malformed (`parameter_missing`, `bad_request`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Unauthorized":{"description":"No key (`missing_api_key`) or an unknown key (`invalid_api_key`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"ModelUnavailable":{"description":"The server cannot classify right now: the model is not loaded (`model_unavailable`) or libvips is\nmissing (`image_processing_unavailable`). Retrying will not help until the operator fixes it.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"NotFound":{"description":"No such resource, also when it belongs to someone else (`not_found`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"TooLarge":{"description":"Over 10 MB or 50 million pixels (`image_too_large`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"UnsupportedFormat":{"description":"Not a supported image format (`unsupported_image_format`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Unprocessable":{"description":"Truncated or corrupted image (`invalid_image`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"ValidationFailed":{"description":"Invalid fields (`validation_failed`); `error.details` lists them","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"QuotaExceeded":{"description":"Daily quota used up (`quota_exceeded`) or too many requests from your IP (`rate_limited`)","headers":{"Retry-After":{"description":"Seconds to wait","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"RateLimited":{"description":"Too many requests from your IP (`rate_limited`)","headers":{"Retry-After":{"description":"Seconds to wait","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"schemas":{"Error":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","example":"invalid_api_key"},"message":{"type":"string","example":"Invalid API key"},"details":{"type":"object","description":"Present on `validation_failed`, the problems field by field","additionalProperties":{"type":"array","items":{"type":"string"}},"example":{"name":["can't be blank"]}}}}}},"Page":{"type":"object","properties":{"next_cursor":{"type":"string","nullable":true,"description":"Pass it as `after` to get the next page. `null` on the last page."}}},"NewApiKey":{"type":"object","properties":{"api_key":{"type":"string","example":"hd_3f9c0a7e5b1d4c8a92e6f0b7d1a5c3e84f2b6a9d1c7e0f35","description":"Shown only once"},"name":{"type":"string","example":"Jian Yang"},"plan":{"type":"string","example":"free"},"quota":{"$ref":"#/components/schemas/Quota"},"warning":{"type":"string"}}},"Quota":{"type":"object","properties":{"limit":{"type":"integer","example":100},"used":{"type":"integer","example":0},"remaining":{"type":"integer","example":100},"period":{"type":"string","example":"day"},"resets_at":{"type":"string","format":"date-time"}}},"Me":{"type":"object","properties":{"name":{"type":"string","example":"Erlich's demo account"},"plan":{"type":"string","enum":["demo","free","pro","sandbox"]},"quota":{"$ref":"#/components/schemas/Quota"}}},"Classification":{"type":"object","properties":{"id":{"type":"integer","example":7},"hotdog":{"type":"boolean","description":"True when hotdog is the top class or its score reaches 0.5"},"confidence":{"type":"number","format":"float","minimum":0,"maximum":1,"description":"Probability that `hotdog` is right","example":0.93},"top_label":{"type":"string","description":"The most likely of the 1000 ImageNet classes","example":"hotdog"},"label":{"type":"string","nullable":true,"description":"Your own free-form name"},"source":{"type":"string","enum":["upload","url"]},"created_at":{"type":"string","format":"date-time"}}},"HotdogStyle":{"type":"string","enum":["chicago","coney_island","corn_dog","new_york","sonoran","seattle","german","other"]},"Hotdog":{"type":"object","properties":{"id":{"type":"integer"},"name":{"type":"string","example":"Windy City"},"style":{"$ref":"#/components/schemas/HotdogStyle"},"toppings":{"type":"array","items":{"type":"string"},"example":["mustard","relish"]},"rating":{"type":"integer","minimum":1,"maximum":5,"nullable":true},"spot_id":{"type":"integer","nullable":true},"spot":{"type":"object","nullable":true,"description":"The spot, nested (null when the hot dog has none)","properties":{"id":{"type":"integer"},"name":{"type":"string","example":"Lou's Hot Dogs"},"city":{"type":"string","nullable":true,"example":"Chicago"}}},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}},"SpotSummary":{"type":"object","properties":{"id":{"type":"integer"},"name":{"type":"string","example":"Lou's Hot Dogs"},"city":{"type":"string","nullable":true,"example":"Chicago"}}},"Spot":{"allOf":[{"$ref":"#/components/schemas/SpotSummary"},{"type":"object","properties":{"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}}]},"SpotInput":{"type":"object","required":["name"],"properties":{"name":{"type":"string","maxLength":100,"example":"Lou's Hot Dogs"},"city":{"type":"string","maxLength":100,"example":"Chicago"}}},"SourceUsage":{"type":"object","properties":{"source":{"type":"string","example":"n8n","description":"The X-Integration-Source value (a lowercase word), `unknown` when absent, `other` when it is not a short word"},"requests":{"type":"integer"},"errors":{"type":"integer","description":"Calls answered with an error"},"first_seen_at":{"type":"string","format":"date-time"},"last_seen_at":{"type":"string","format":"date-time"}}},"HotdogInput":{"type":"object","required":["name"],"properties":{"name":{"type":"string","maxLength":100,"example":"Windy City"},"style":{"$ref":"#/components/schemas/HotdogStyle"},"toppings":{"type":"array","maxItems":20,"items":{"type":"string","maxLength":40}},"rating":{"type":"integer","minimum":1,"maximum":5},"spot_id":{"type":"integer","description":"One of your spots (see GET /v1/spots)"}}},"WebhookEvent":{"type":"string","enum":["classification.completed","hotdog.created","hotdog.updated","hotdog.deleted"]},"Webhook":{"type":"object","properties":{"id":{"type":"integer"},"url":{"type":"string","format":"uri"},"events":{"type":"array","items":{"$ref":"#/components/schemas/WebhookEvent"}},"created_at":{"type":"string","format":"date-time"}}},"WebhookWithSecret":{"allOf":[{"$ref":"#/components/schemas/Webhook"},{"type":"object","properties":{"secret":{"type":"string","example":"whsec_0e692dbcd4eaee8eb3b9167dc704eac1a22e009fa1b25347","description":"Shown only once"}}}]},"Delivery":{"type":"object","properties":{"id":{"type":"integer"},"event":{"type":"string","enum":["classification.completed","hotdog.created","hotdog.updated","hotdog.deleted","webhook.test"]},"status":{"type":"string","enum":["pending","succeeded","failed"]},"attempts":{"type":"integer"},"response_code":{"type":"integer","nullable":true},"error":{"type":"string","nullable":true},"delivered_at":{"type":"string","format":"date-time","nullable":true},"created_at":{"type":"string","format":"date-time"}}},"Sample":{"type":"object","properties":{"name":{"type":"string","example":"hotdog-1.jpg"},"url":{"type":"string","format":"uri"},"hotdog":{"type":"boolean","description":"The expected verdict"},"description":{"type":"string"},"credit":{"type":"string"},"license":{"type":"string","example":"CC0"}}}}}}