{"service":"autofish-inference","purpose":"Async sleep-stage inference over Firebase-stored accelerometer data.","auth":{"type":"bearer","header":"Authorization: Bearer <token>","exempt_endpoints":["GET /","GET /healthz","GET /docs","GET /openapi.json"]},"endpoints":[{"method":"POST","path":"/jobs","summary":"Create an inference job.","request_body_example":{"firebase_project_id":"takeda","unique_id":"310AA67B-7C1C-4B2E-8DF6-05D58A748ACE","user_name":"Dmitri-WearOS","start_ms":1776249780000,"end_ms":1777387658720,"model":"model_31"},"response_example":{"job_id":"abcd...","status":"queued","created_at":"2026-04-29T12:00:00+00:00"}},{"method":"GET","path":"/jobs/{job_id}","summary":"Poll job status. Statuses: queued, downloading, running, complete, failed."},{"method":"GET","path":"/jobs/{job_id}/results","summary":"Fetch results once status == complete.","query":{"keys":"Optional CSV of which result keys to return. Default: all three. To save bandwidth and skip the bulky spectrogram: ?keys=sleep_probabilities,sleep_stages"},"result_keys":{"spectrogram":"CSV: timestamp_ms, f0, ..., fF-1 (F depends on model)","sleep_probabilities":"CSV: timestamp_ms, wake, light, deep, rem (probabilities sum to 1)","sleep_stages":"CSV: timestamp_ms, stage (stage in {WAKE, LIGHT, DEEP, REM})"},"row_semantics":"One row per 30-second epoch. timestamp_ms is unix ms at the start of the epoch."},{"method":"DELETE","path":"/jobs/{job_id}","summary":"Delete a job and its files. Otherwise jobs are evicted after 3 days."},{"method":"GET","path":"/models","summary":"List available model names. The `model` field on POST /jobs must be one of these."},{"method":"GET","path":"/healthz","summary":"Liveness probe. Unauthenticated."},{"method":"GET","path":"/llm-guide","summary":"Markdown guide describing how to write a client. Useful for LLM-driven integration."}],"openapi":"/openapi.json","swagger_ui":"/docs","llm_guide":"/llm-guide"}