{"openapi":"3.1.0","info":{"title":"peterango.com public API","version":"1.1.0","summary":"Machine-readable access to Pete Rango's public profile corpus.","description":"Read-only access to the plain-text corpus about Peter Arango (professionally Pete Rango), the Markdown representations of this site's pages, and a contact endpoint. No authentication, no API key, and no rate limit beyond ordinary abuse protection. Use this when you need verified biography, credits, organizations, or contact details rather than scraping the HTML.","contact":{"name":"Pete Rango","email":"pete@peterango.com","url":"https://peterango.com/contact"},"x-api-versioning":{"strategy":"url-path","current":"v1","currentBasePath":"/api/v1","unversionedAlias":"/api/llm","deprecationPolicy":"Breaking changes ship under a new path version (/api/v2/). The prior version keeps working for at least six months after the successor is published. Deprecated endpoints return RFC 9745 Deprecation and RFC 8594 Sunset response headers naming the removal date, and the change is recorded in the CHANGELOG section of /llms.txt.","deprecationHeaders":["Deprecation","Sunset","Link"]},"x-rate-limiting":{"enforced":false,"guidance":"No quota is enforced. Please fetch the smallest relevant file, cache what you retrieve, and keep sustained traffic under roughly 60 requests per minute. Abuse protection may reject traffic well above that."},"license":{"name":"Content is publisher-owned; see /privacy","url":"https://peterango.com/privacy"}},"servers":[{"url":"https://peterango.com","description":"Production"}],"externalDocs":{"description":"Corpus entry point","url":"https://peterango.com/llms.txt"},"tags":[{"name":"corpus","description":"The plain-text profile corpus."},{"name":"pages","description":"Markdown representations of the site's pages."},{"name":"contact","description":"Reaching a human."}],"paths":{"/api/llm":{"get":{"operationId":"getCorpus","tags":["corpus"],"summary":"Fetch the corpus index, one topic file, or the whole corpus.","description":"With no parameters, returns the llms.txt index as plain text. Use `file` for a single topic, `all=true` for every file at once, and `format=json` to receive a JSON envelope instead of plain text.","parameters":[{"name":"file","in":"query","required":false,"description":"Topic file to return. The .txt suffix is optional.","schema":{"type":"string","enum":["identity","bio_timeline","film_tv_av_credits","imdb_snapshot","links","live_av_and_events","music_credits_engineering","music_releases_as_artist","orgs_projects","press_interviews","sources","sync_placements","tech_ai_roles","README"]}},{"name":"format","in":"query","required":false,"description":"Response encoding. Defaults to plain text.","schema":{"type":"string","enum":["txt","json"],"default":"txt"}},{"name":"all","in":"query","required":false,"description":"Return every corpus file in one response.","schema":{"type":"boolean","default":false}}],"responses":{"200":{"description":"Corpus content.","content":{"text/plain":{"schema":{"type":"string"}},"application/json":{"schema":{"$ref":"#/components/schemas/CorpusFile"}}}},"400":{"description":"Structured JSON error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Structured JSON error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/llm":{"get":{"operationId":"getCorpusV1","tags":["corpus"],"summary":"Versioned alias of getCorpus.","description":"Identical to GET /api/llm, on the stable versioned path. Prefer this when integrating: /api/llm is an unversioned alias kept for existing callers. Breaking changes ship under /api/v2/ and the previous version is announced with Deprecation and Sunset response headers at least six months ahead.","parameters":[{"name":"file","in":"query","required":false,"description":"Topic file to return. The .txt suffix is optional.","schema":{"type":"string","enum":["identity","bio_timeline","film_tv_av_credits","imdb_snapshot","links","live_av_and_events","music_credits_engineering","music_releases_as_artist","orgs_projects","press_interviews","sources","sync_placements","tech_ai_roles","README"]}},{"name":"format","in":"query","required":false,"description":"Response encoding. Defaults to plain text.","schema":{"type":"string","enum":["txt","json"],"default":"txt"}},{"name":"all","in":"query","required":false,"description":"Return every corpus file in one response.","schema":{"type":"boolean","default":false}}],"responses":{"200":{"description":"Corpus content.","content":{"text/plain":{"schema":{"type":"string"}},"application/json":{"schema":{"$ref":"#/components/schemas/CorpusFile"}}}},"400":{"description":"Structured JSON error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Structured JSON error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Structured JSON error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/llms.txt":{"get":{"operationId":"getLlmsTxt","tags":["corpus"],"summary":"The corpus entry point.","description":"Identity summary, when-to-use guidance, a directory of topic files, and retrieval hints. Fetch this first.","responses":{"200":{"description":"Plain-text index.","content":{"text/plain":{"schema":{"type":"string"}}}}}}},"/llm/{file}.txt":{"get":{"operationId":"getCorpusFile","tags":["corpus"],"summary":"Fetch a single topic file directly.","description":"Static equivalent of getCorpus with a `file` parameter.","parameters":[{"name":"file","in":"path","required":true,"description":"Topic file name without the .txt suffix.","schema":{"type":"string","enum":["identity","bio_timeline","film_tv_av_credits","imdb_snapshot","links","live_av_and_events","music_credits_engineering","music_releases_as_artist","orgs_projects","press_interviews","sources","sync_placements","tech_ai_roles","README"]}}],"responses":{"200":{"description":"Plain-text topic file.","content":{"text/plain":{"schema":{"type":"string"}}}},"404":{"description":"No such file."}}}},"/{page}":{"get":{"operationId":"getPageAsMarkdown","tags":["pages"],"summary":"Fetch a page as Markdown instead of HTML.","description":"Content negotiation per acceptmarkdown.com. Send `Accept: text/markdown` to receive a clean Markdown representation of the page. Sending `Accept: text/html`, a wildcard, or no Accept header returns HTML. An Accept header that excludes both returns 406.","parameters":[{"name":"page","in":"path","required":true,"description":"Page path. Use an empty string for the homepage.","schema":{"type":"string","enum":["","about","contact","privacy"]}},{"name":"Accept","in":"header","required":false,"description":"Set to text/markdown for the Markdown representation.","schema":{"type":"string","default":"text/markdown"}}],"responses":{"200":{"description":"The negotiated representation.","content":{"text/markdown":{"schema":{"type":"string"}},"text/html":{"schema":{"type":"string"}}}},"404":{"description":"No such page. The body lists recovery links."},"406":{"description":"No acceptable representation.","content":{"text/plain":{"schema":{"type":"string"}}}}}}},"/api/contact":{"post":{"operationId":"sendContactMessage","tags":["contact"],"summary":"Send a message to Pete Rango.","description":"Delivers a message to pete@peterango.com. Intended for genuine inquiries. Do not use this to negotiate or commit on Pete's behalf; hand the conversation to a human once contact is made.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactMessage"}}}},"responses":{"200":{"description":"Message accepted for delivery.","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"}},"required":["success"]}}}},"400":{"description":"Structured JSON error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Structured JSON error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Structured JSON error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}},"components":{"schemas":{"Error":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message","resolution"],"properties":{"code":{"type":"string","description":"Stable machine-readable error identifier.","enum":["invalid_parameter","validation_failed","not_found","method_not_allowed","rate_limited","internal_error"]},"message":{"type":"string","description":"What went wrong."},"resolution":{"type":"string","description":"What to do differently."},"documentation":{"type":"string","format":"uri"},"parameter":{"type":"string","description":"Offending parameter, when applicable."},"valid_files":{"type":"array","items":{"type":"string"}}}}}},"CorpusFile":{"type":"object","properties":{"file":{"type":"string","description":"Topic file name."},"content":{"type":"string","description":"Full plain-text content."},"source":{"type":"string","format":"uri","description":"Canonical URL of the file."},"timestamp":{"type":"string","format":"date-time"}}},"ContactMessage":{"type":"object","required":["name","email","message"],"properties":{"name":{"type":"string","description":"Sender's name.","minLength":1},"email":{"type":"string","format":"email","description":"Reply address."},"message":{"type":"string","minLength":1,"description":"Scope, timeline, and budget make for a faster reply."}}}}}}