{"openapi":"3.1.0","info":{"title":"Gainmaps API","version":"1.1.0","description":"Public JSON API for the Gainmaps photo and logo catalogs, version info, and OpenAPI spec.\n\n**Versioning**: The stable, versioned base path is `/api/v1/`. The unversioned `/api/` prefix\nis kept for backwards compatibility and maps to the same handlers. Non-breaking additions\n(new fields, new endpoints) are shipped without a version bump. Breaking changes increment\nthe `info.version` field and are announced via the /api/version endpoint.\nThe current API version is returned in the `X-Api-Version` response header on every response.\n\n**Pagination**: List endpoints return the full catalog.\nThe catalogs are small (hundreds of items) so cursor/offset pagination is not implemented.\nFilter by slug using the per-item endpoints instead.\n\n**Errors**: All error responses use a typed `Error` object with `code`, `message`, and `hint`.\nUnsupported methods return HTTP 405 with an `Allow` header and a JSON error body."},"servers":[{"url":"https://www.gainmaps.com","description":"Production — versioned at /api/v1/"}],"components":{"schemas":{"Error":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"hint":{"type":"string"}},"required":["code","message","hint"]}},"required":["error"]},"Photo":{"type":"object","properties":{"id":{"type":"string"},"slug":{"type":"string"},"alt":{"type":"string"},"width":{"type":"number"},"height":{"type":"number"},"photographer":{"type":"string"},"photographerUrl":{"type":"string"},"photoUrl":{"type":"string"},"standardSrc":{"type":"string"},"gainmapSrc":{"type":"string"}},"required":["id","slug","alt","width","height","standardSrc","gainmapSrc"]},"PhotoList":{"type":"array","items":{"$ref":"#/components/schemas/Photo"}},"Logo":{"type":"object","properties":{"rank":{"type":"number"},"name":{"type":"string"},"slug":{"type":"string"},"svgPath":{"type":"string"},"gainmapPath":{"type":"string"}},"required":["rank","name","slug","svgPath","gainmapPath"]},"LogoList":{"type":"array","items":{"$ref":"#/components/schemas/Logo"}},"VersionInfo":{"type":"object","properties":{"name":{"type":"string"},"version":{"type":"string"},"installCommands":{"type":"object"},"homebrewFormula":{"type":"string"}},"required":["name","version","installCommands","homebrewFormula"]}},"headers":{"X-Api-Version":{"description":"Current API version (semver). Breaking changes increment the major segment.","schema":{"type":"string","example":"1.1.0"}}}},"paths":{"/api/photos":{"get":{"operationId":"listPhotos","summary":"List all photos","description":"Returns the full catalog of photos. No pagination — the full array is returned.","responses":{"200":{"description":"List all photos","headers":{"X-Api-Version":{"$ref":"#/components/headers/X-Api-Version"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PhotoList"}}}},"405":{"description":"Method not allowed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/photos/{slug}":{"get":{"operationId":"getPhoto","summary":"Get a photo by slug","description":"Returns a single photo by slug.","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Get a photo by slug","headers":{"X-Api-Version":{"$ref":"#/components/headers/X-Api-Version"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Photo"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"405":{"description":"Method not allowed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/logos":{"get":{"operationId":"listLogos","summary":"List all logos","description":"Returns the full catalog of brand logos. No pagination — the full array is returned.","responses":{"200":{"description":"List all logos","headers":{"X-Api-Version":{"$ref":"#/components/headers/X-Api-Version"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LogoList"}}}},"405":{"description":"Method not allowed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/logos/{slug}":{"get":{"operationId":"getLogo","summary":"Get a logo by slug","description":"Returns a single logo by slug.","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Get a logo by slug","headers":{"X-Api-Version":{"$ref":"#/components/headers/X-Api-Version"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Logo"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"405":{"description":"Method not allowed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/version":{"get":{"operationId":"getVersion","summary":"Get CLI version info","description":"Returns the current gainmap package version and install commands.","responses":{"200":{"description":"Version info","headers":{"X-Api-Version":{"$ref":"#/components/headers/X-Api-Version"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/VersionInfo"}}}},"405":{"description":"Method not allowed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/photos":{"get":{"operationId":"listPhotosV1","summary":"List all photos (v1)","description":"Stable v1 alias for `/api/photos`. Returns the full catalog of photos.","responses":{"200":{"description":"List all photos (v1)","headers":{"X-Api-Version":{"$ref":"#/components/headers/X-Api-Version"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PhotoList"}}}},"405":{"description":"Method not allowed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/photos/{slug}":{"get":{"operationId":"getPhotoV1","summary":"Get a photo by slug (v1)","description":"Stable v1 alias for `/api/photos/{slug}`.","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Get a photo by slug (v1)","headers":{"X-Api-Version":{"$ref":"#/components/headers/X-Api-Version"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Photo"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"405":{"description":"Method not allowed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/logos":{"get":{"operationId":"listLogosV1","summary":"List all logos (v1)","description":"Stable v1 alias for `/api/logos`. Returns the full catalog of brand logos.","responses":{"200":{"description":"List all logos (v1)","headers":{"X-Api-Version":{"$ref":"#/components/headers/X-Api-Version"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LogoList"}}}},"405":{"description":"Method not allowed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/logos/{slug}":{"get":{"operationId":"getLogoV1","summary":"Get a logo by slug (v1)","description":"Stable v1 alias for `/api/logos/{slug}`.","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Get a logo by slug (v1)","headers":{"X-Api-Version":{"$ref":"#/components/headers/X-Api-Version"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Logo"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"405":{"description":"Method not allowed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/version":{"get":{"operationId":"getVersionV1","summary":"Get CLI version info (v1)","description":"Stable v1 alias for `/api/version`.","responses":{"200":{"description":"Version info","headers":{"X-Api-Version":{"$ref":"#/components/headers/X-Api-Version"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/VersionInfo"}}}},"405":{"description":"Method not allowed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}}}