{"openapi":"3.1.0","info":{"title":"Dog Image API","version":"1.0.0","description":"The same nine views of every dog breed, on a transparent background."},"servers":[{"url":"https://dogimage.dev"}],"components":{"securitySchemes":{"key":{"type":"http","scheme":"bearer"}},"schemas":{"Error":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"Stable. Match on this, not on the message."},"message":{"type":"string"},"choices":{"type":"array","items":{"type":"string"},"description":"Valid values, on some 400 and 404 replies"}}}}},"View":{"type":"object","required":["id","label"],"properties":{"id":{"type":"string","enum":["front","front-left","left","rear-left","rear","rear-right","right","front-right","head"]},"label":{"type":"string"}}},"VariantSummary":{"type":"object","required":["slug","name","kind"],"properties":{"slug":{"type":"string"},"name":{"type":"string"},"kind":{"type":"string","enum":["color","pattern","coat"]}}},"BreedSummary":{"type":"object","required":["slug","name","crossbreed","default_variant","variants"],"properties":{"slug":{"type":"string"},"name":{"type":"string"},"crossbreed":{"type":"boolean"},"default_variant":{"type":"string","description":"The slug of the breed's main set"},"variants":{"type":"array","items":{"$ref":"#/components/schemas/VariantSummary"}}}},"BreedList":{"type":"object","required":["views","breeds"],"properties":{"views":{"type":"array","items":{"$ref":"#/components/schemas/View"}},"breeds":{"type":"array","items":{"$ref":"#/components/schemas/BreedSummary"}}}},"ViewLinks":{"type":"object","required":["preview_512","preview_1024","full"],"properties":{"preview_512":{"type":"string","format":"uri","description":"Transparent WebP, 512 pixels, no key"},"preview_1024":{"type":"string","format":"uri","description":"Transparent WebP, 1024 pixels, no key"},"full":{"type":"string","format":"uri","description":"Transparent PNG, 2048 pixels, needs a key and a plan"}}},"VariantDetail":{"type":"object","required":["slug","name","kind","views"],"properties":{"slug":{"type":"string"},"name":{"type":"string"},"kind":{"type":"string","enum":["color","pattern","coat"]},"views":{"type":"object","description":"One entry per view id","required":["front","front-left","left","rear-left","rear","rear-right","right","front-right","head"],"properties":{"front":{"$ref":"#/components/schemas/ViewLinks"},"front-left":{"$ref":"#/components/schemas/ViewLinks"},"left":{"$ref":"#/components/schemas/ViewLinks"},"rear-left":{"$ref":"#/components/schemas/ViewLinks"},"rear":{"$ref":"#/components/schemas/ViewLinks"},"rear-right":{"$ref":"#/components/schemas/ViewLinks"},"right":{"$ref":"#/components/schemas/ViewLinks"},"front-right":{"$ref":"#/components/schemas/ViewLinks"},"head":{"$ref":"#/components/schemas/ViewLinks"}}}}},"BreedDetail":{"type":"object","required":["slug","name","crossbreed","default_variant","summary","variants"],"properties":{"slug":{"type":"string"},"name":{"type":"string"},"crossbreed":{"type":"boolean"},"default_variant":{"type":"string"},"summary":{"oneOf":[{"type":"null"},{"type":"object","required":["text","url","title"],"properties":{"text":{"type":"string"},"url":{"type":"string","format":"uri"},"title":{"type":"string"}},"description":"From Wikipedia, CC BY-SA 4.0"}]},"variants":{"type":"array","items":{"$ref":"#/components/schemas/VariantDetail"}}}},"Usage":{"type":"object","required":["month","plan","limit","used","remaining"],"properties":{"month":{"type":"string","example":"2026-11","description":"The calendar month counted, UTC"},"plan":{"oneOf":[{"type":"string","enum":["starter","pro","all"]},{"type":"null"}]},"limit":{"oneOf":[{"type":"integer"},{"type":"null"}],"description":"Full-size images a month. null: every image. 0: no plan"},"used":{"type":"integer"},"remaining":{"oneOf":[{"type":"integer"},{"type":"null"}],"description":"null on the All images plan"}}}}},"paths":{"/api/v1/breeds":{"get":{"operationId":"listBreeds","summary":"List breeds","responses":{"200":{"description":"Breeds and views","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BreedList"}}}}}}},"/api/v1/breeds/{breed}":{"get":{"operationId":"getBreed","summary":"One breed with preview links","parameters":[{"name":"breed","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"The breed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BreedDetail"}}}},"404":{"description":"Unknown breed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/images/{breed}/{variant}/{view}":{"get":{"operationId":"getImage","summary":"An image. Previews are free; size=full needs a key and a plan.","parameters":[{"name":"breed","in":"path","required":true,"schema":{"type":"string"}},{"name":"variant","in":"path","required":true,"schema":{"type":"string"},"description":"A color slug, or default"},{"name":"view","in":"path","required":true,"schema":{"type":"string","enum":["front","front-left","left","rear-left","rear","rear-right","right","front-right","head"]}},{"name":"size","in":"query","schema":{"type":"string","enum":["512","1024","full"],"default":"1024"}}],"security":[{},{"key":[]}],"responses":{"200":{"description":"Full-size PNG (size=full)","headers":{"X-Quota-Limit":{"description":"Images a month on the plan, or the word unlimited","schema":{"type":"string"},"example":"188"},"X-Quota-Used":{"description":"Distinct images used this month","schema":{"type":"string"},"example":"188"},"X-Quota-Remaining":{"description":"Images left this month, or the word unlimited","schema":{"type":"string"},"example":"188"}},"content":{"image/png":{"schema":{"type":"string","format":"binary"}}}},"302":{"description":"Redirect to the WebP preview (size=512 or 1024)","headers":{"Location":{"schema":{"type":"string","format":"uri"}}}},"400":{"description":"Bad size","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"No active plan","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown breed, variant or view","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Monthly files used up","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"File unavailable, not counted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Plan check failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/usage":{"get":{"operationId":"getUsage","summary":"Files used this month","security":[{"key":[]}],"responses":{"200":{"description":"Usage","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Usage"}}}},"401":{"description":"Missing or invalid key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Plan check failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}}}