{"openapi":"3.1.0","info":{"title":"FetchHarbor","description":"Modular x402 content services for self-hosted deployments","version":"0.1.0"},"paths":{"/scrape":{"get":{"tags":["scrape"],"summary":"scrape (GET)","operationId":"scrape_get","parameters":[{"name":"url","in":"query","required":true,"schema":{"type":"string","title":"Url"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Scrape Get"}}}},"400":{"description":"The URL is invalid, unresolvable, or targets a blocked network."},"402":{"description":"A valid x402 payment is required."},"413":{"description":"The remote response exceeds the configured size limit."},"502":{"description":"The remote server failed or returned an error response."},"504":{"description":"The remote request timed out."},"508":{"description":"The remote server exceeded the redirect limit."},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["scrape"],"summary":"scrape (POST)","operationId":"scrape_post","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScrapeRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Scrape Post"}}}},"400":{"description":"The URL is invalid, unresolvable, or targets a blocked network."},"402":{"description":"A valid x402 payment is required."},"413":{"description":"The remote response exceeds the configured size limit."},"502":{"description":"The remote server failed or returned an error response."},"504":{"description":"The remote request timed out."},"508":{"description":"The remote server exceeded the redirect limit."},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/html-to-md":{"get":{"tags":["html-to-md"],"summary":"html-to-md (GET)","operationId":"html_to_md_get","parameters":[{"name":"html","in":"query","required":true,"schema":{"type":"string","maxLength":2000000,"title":"Html"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Html To Md Get"}}}},"402":{"description":"A valid x402 payment is required."},"413":{"description":"The HTML input exceeds the configured request limit."},"422":{"description":"The request does not contain valid HTML input."}}},"post":{"tags":["html-to-md"],"summary":"html-to-md (POST)","operationId":"html_to_md_post","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HtmlRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Html To Md Post"}}}},"402":{"description":"A valid x402 payment is required."},"413":{"description":"The HTML input exceeds the configured request limit."},"422":{"description":"The request does not contain valid HTML input."}}}},"/pdf-parse":{"get":{"tags":["pdf-parse"],"summary":"pdf-parse (GET)","operationId":"pdf_parse_get","parameters":[{"name":"url","in":"query","required":true,"schema":{"type":"string","title":"Url"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Pdf Parse Get"}}}},"400":{"description":"No PDF URL or file was supplied."},"402":{"description":"A valid x402 payment is required."},"413":{"description":"The PDF exceeds the configured download limit."},"422":{"description":"The PDF is invalid, encrypted, or unsupported."},"502":{"description":"The remote PDF could not be retrieved."},"504":{"description":"The remote PDF request timed out."}}},"post":{"tags":["pdf-parse"],"summary":"pdf-parse (POST)","operationId":"pdf_parse_post","parameters":[{"name":"url","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Url"}}],"requestBody":{"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_pdf_parse_post"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Pdf Parse Post"}}}},"400":{"description":"No PDF URL or file was supplied."},"402":{"description":"A valid x402 payment is required."},"413":{"description":"The PDF exceeds the configured download limit."},"422":{"description":"The PDF is invalid, encrypted, or unsupported."},"502":{"description":"The remote PDF could not be retrieved."},"504":{"description":"The remote PDF request timed out."}}}},"/chat":{"post":{"tags":["chat"],"summary":"chat","operationId":"chat","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChatRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChatResponse"}}}},"402":{"description":"A valid x402 payment is required."},"413":{"description":"The prompt exceeds the configured character limit."},"422":{"description":"The JSON body is invalid or the message is empty."},"502":{"description":"The configured model returned an invalid or rejected response."},"503":{"description":"The local model is unavailable or at its concurrency limit."},"504":{"description":"The model request timed out."}}}},"/v1/audio/speech":{"post":{"tags":["audio-speech"],"summary":"audio-speech","operationId":"audio_speech","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SpeechRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Audio Speech"}}}},"402":{"description":"A valid x402 payment is required."},"413":{"description":"The submitted media exceeds the configured limit."},"415":{"description":"The media type or requested format is unsupported."},"422":{"description":"The submitted media or JSON body is invalid."},"429":{"description":"The bounded media queue is currently full."},"503":{"description":"The isolated media worker is unavailable."},"504":{"description":"Media processing exceeded its time limit."}}}},"/audio/transcribe":{"post":{"tags":["audio-transcribe"],"summary":"audio-transcribe","operationId":"audio_transcribe","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EncodedAudioRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Audio Transcribe"}}}},"402":{"description":"A valid x402 payment is required."},"413":{"description":"The submitted media exceeds the configured limit."},"415":{"description":"The media type or requested format is unsupported."},"422":{"description":"The submitted media or JSON body is invalid."},"429":{"description":"The bounded media queue is currently full."},"503":{"description":"The isolated media worker is unavailable."},"504":{"description":"Media processing exceeded its time limit."}}}},"/audio/subtitles":{"post":{"tags":["audio-subtitles"],"summary":"audio-subtitles","operationId":"audio_subtitles","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubtitleRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Audio Subtitles"}}}},"402":{"description":"A valid x402 payment is required."},"413":{"description":"The submitted media exceeds the configured limit."},"415":{"description":"The media type or requested format is unsupported."},"422":{"description":"The submitted media or JSON body is invalid."},"429":{"description":"The bounded media queue is currently full."},"503":{"description":"The isolated media worker is unavailable."},"504":{"description":"Media processing exceeded its time limit."}}}},"/audio/convert":{"post":{"tags":["audio-convert"],"summary":"audio-convert","operationId":"audio_convert","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConvertRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Audio Convert"}}}},"402":{"description":"A valid x402 payment is required."},"413":{"description":"The submitted media exceeds the configured limit."},"415":{"description":"The media type or requested format is unsupported."},"422":{"description":"The submitted media or JSON body is invalid."},"429":{"description":"The bounded media queue is currently full."},"503":{"description":"The isolated media worker is unavailable."},"504":{"description":"Media processing exceeded its time limit."}}}},"/audio/transcribe-summary":{"post":{"tags":["audio-transcribe-summary"],"summary":"audio-transcribe-summary","operationId":"audio_transcribe_summary","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EncodedAudioRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Audio Transcribe Summary"}}}},"402":{"description":"A valid x402 payment is required."},"413":{"description":"The submitted media exceeds the configured limit."},"415":{"description":"The media type or requested format is unsupported."},"422":{"description":"The submitted media or JSON body is invalid."},"429":{"description":"The bounded media queue is currently full."},"503":{"description":"The isolated media worker is unavailable."},"504":{"description":"Media processing exceeded its time limit."}}}},"/services":{"get":{"summary":"service catalog","operationId":"list_services","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Response List Services"}}}}}}},"/.well-known/x402.json":{"get":{"summary":"x402 discovery","operationId":"x402_discovery","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response X402 Discovery"}}}}}}}},"components":{"schemas":{"Body_pdf_parse_post":{"properties":{"url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Url"},"file":{"anyOf":[{"type":"string","contentMediaType":"application/octet-stream"},{"type":"null"}],"title":"File"}},"type":"object","title":"Body_pdf_parse_post"},"ChatRequest":{"properties":{"message":{"type":"string","maxLength":8000,"minLength":1,"title":"Message"}},"type":"object","required":["message"],"title":"ChatRequest"},"ChatResponse":{"properties":{"status":{"type":"string","title":"Status","default":"success"},"model":{"type":"string","title":"Model"},"response":{"type":"string","title":"Response"},"prompt_tokens":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Prompt Tokens"},"response_tokens":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Response Tokens"}},"type":"object","required":["model","response"],"title":"ChatResponse"},"ConvertRequest":{"properties":{"audio_base64":{"type":"string","maxLength":36000000,"minLength":4,"title":"Audio Base64"},"language":{"anyOf":[{"type":"string","maxLength":16,"minLength":2},{"type":"null"}],"title":"Language"},"format":{"type":"string","enum":["wav","mp3","opus","flac"],"title":"Format","default":"mp3"}},"type":"object","required":["audio_base64"],"title":"ConvertRequest"},"EncodedAudioRequest":{"properties":{"audio_base64":{"type":"string","maxLength":36000000,"minLength":4,"title":"Audio Base64"},"language":{"anyOf":[{"type":"string","maxLength":16,"minLength":2},{"type":"null"}],"title":"Language"}},"type":"object","required":["audio_base64"],"title":"EncodedAudioRequest"},"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"HtmlRequest":{"properties":{"html":{"type":"string","maxLength":2000000,"title":"Html"}},"type":"object","required":["html"],"title":"HtmlRequest"},"ScrapeRequest":{"properties":{"url":{"type":"string","maxLength":2083,"minLength":1,"format":"uri","title":"Url"}},"type":"object","required":["url"],"title":"ScrapeRequest"},"SpeechRequest":{"properties":{"input":{"type":"string","maxLength":5000,"minLength":1,"title":"Input"},"voice":{"type":"string","enum":["af_sarah","af_heart","am_adam","am_michael"],"title":"Voice","default":"af_sarah"},"response_format":{"type":"string","const":"wav","title":"Response Format","default":"wav"},"speed":{"type":"number","maximum":1.25,"minimum":0.75,"title":"Speed","default":1.0}},"type":"object","required":["input"],"title":"SpeechRequest"},"SubtitleRequest":{"properties":{"audio_base64":{"type":"string","maxLength":36000000,"minLength":4,"title":"Audio Base64"},"language":{"anyOf":[{"type":"string","maxLength":16,"minLength":2},{"type":"null"}],"title":"Language"},"format":{"type":"string","enum":["srt","vtt"],"title":"Format","default":"srt"}},"type":"object","required":["audio_base64"],"title":"SubtitleRequest"},"ValidationError":{"properties":{"loc":{"items":{"anyOf":[{"type":"string"},{"type":"integer"}]},"type":"array","title":"Location"},"msg":{"type":"string","title":"Message"},"type":{"type":"string","title":"Error Type"},"input":{"title":"Input"},"ctx":{"type":"object","title":"Context"}},"type":"object","required":["loc","msg","type"],"title":"ValidationError"}}}}