{"openapi":"3.1.0","info":{"title":"Arrested Development Quotes API","description":"A free, read-only REST API serving quotes from the television series *Arrested Development*.\n\nEach quote carries the line itself and `speakers`, a comma-separated list of everyone who speaks in it, in the order they speak (`\"Lucille,Michael\"`). Speaker names come from a fixed list of characters, matched case-insensitively.\n\nNo API key, no sign-up, no rate limit beyond ordinary courtesy. Responses are cacheable for an hour.","contact":{"name":"Bluthquotes","url":"https://github.com/bbhart/bluthsapi"},"license":{"name":"MIT","url":"https://github.com/bbhart/bluthsapi/blob/main/LICENSE"},"version":"1.0.0"},"paths":{"/health":{"get":{"tags":["Health"],"summary":"Health Check","description":"Health check endpoint.","operationId":"health_check_health_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/quotes/random":{"get":{"tags":["Quotes"],"summary":"Random Quote","description":"Get a random quote from all available quotes.","operationId":"random_quote_api_quotes_random_get","responses":{"200":{"description":"Successfully retrieved random quote","content":{"application/json":{"schema":{"$ref":"#/components/schemas/QuoteResponse"}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/quotes/meme":{"get":{"tags":["Quotes"],"summary":"Meme Quote","description":"Get a random quote that has an associated image.","operationId":"meme_quote_api_quotes_meme_get","responses":{"200":{"description":"Successfully retrieved meme quote","content":{"application/json":{"schema":{"$ref":"#/components/schemas/QuoteResponse"}}}},"404":{"description":"No meme quotes available","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/quotes/{speaker}":{"get":{"tags":["Quotes"],"summary":"Quote By Speaker","description":"Get a random quote filtered by speaker (case-insensitive).","operationId":"quote_by_speaker_api_quotes__speaker__get","parameters":[{"name":"speaker","in":"path","required":true,"schema":{"type":"string","title":"Speaker"}}],"responses":{"200":{"description":"Successfully retrieved quote for speaker","content":{"application/json":{"schema":{"$ref":"#/components/schemas/QuoteResponse"}}}},"404":{"description":"No quotes found for speaker","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}}},"components":{"schemas":{"ErrorResponse":{"properties":{"detail":{"type":"string","title":"Detail","description":"Human-readable error message"}},"type":"object","required":["detail"],"title":"ErrorResponse","description":"Error response structure.\n\nThe field is `detail` because that is what FastAPI's HTTPException emits.\nThis model exists only to document that shape in the OpenAPI spec; nothing\nconstructs it. Renaming the field would silently break every client that\nreads the published spec."},"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"Quote":{"properties":{"id":{"type":"string","title":"Id","description":"Unique identifier for the quote"},"quote":{"type":"string","maxLength":1000,"title":"Quote","description":"The actual quote text"},"speakers":{"type":"string","title":"Speakers","description":"Characters speaking in the quote, comma-separated in order of appearance (e.g. 'Lucille,Michael'). Empty when unknown. Names must match app/data/list-of-characters.txt.","default":""},"context":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Context","description":"Episode reference or situational context"},"imageUrl":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Imageurl","description":"Relative path to image (S3 key)"}},"type":"object","required":["id","quote"],"title":"Quote","description":"Quote entity as stored in quotes.json."},"QuoteResponse":{"properties":{"data":{"$ref":"#/components/schemas/Quote"}},"type":"object","required":["data"],"title":"QuoteResponse","description":"Success response wrapping a quote."},"ValidationError":{"properties":{"loc":{"items":{"anyOf":[{"type":"string"},{"type":"integer"}]},"type":"array","title":"Location"},"msg":{"type":"string","title":"Message"},"type":{"type":"string","title":"Error Type"}},"type":"object","required":["loc","msg","type"],"title":"ValidationError"}}},"tags":[{"name":"Quotes","description":"Retrieve a single quote: at random, by character, or one that has an image attached."},{"name":"Health","description":"Service health and the number of quotes loaded."}]}