{"openapi":"3.1.0","info":{"title":"RespiQ Prediction API","version":"0.4.0"},"paths":{"/":{"get":{"summary":"Root","operationId":"root__get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/health":{"get":{"summary":"Health","operationId":"health_health_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/molecules":{"get":{"summary":"Molecules","operationId":"molecules_molecules_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/molecules/{molecule}":{"get":{"summary":"Molecule Details","operationId":"molecule_details_molecules__molecule__get","parameters":[{"name":"molecule","in":"path","required":true,"schema":{"type":"string","title":"Molecule"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/molecules/{molecule}/schema":{"get":{"summary":"Molecule Input Schema","operationId":"molecule_input_schema_molecules__molecule__schema_get","parameters":[{"name":"molecule","in":"path","required":true,"schema":{"type":"string","title":"Molecule"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/predict/{molecule}":{"post":{"summary":"Predict Preprocessed","description":"Predict from a single preprocessed spectral row.\n\n    curl -X POST http://localhost:8080/predict/cyclohexanone\n      -H \"Authorization: Bearer <token>\"\n      -H \"Content-Type: application/json\"\n      -d '{\"350.0\": 0.023, \"350.3\": 0.024, ...}'","operationId":"predict_preprocessed_predict__molecule__post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"molecule","in":"path","required":true,"schema":{"type":"string","title":"Molecule"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":{"type":"number"},"title":"Data"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PredictionResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/predict/{molecule}/raw/multiple":{"post":{"summary":"Predict Raw Multiple","description":"Predict from every run of one sampling session.\n\nA breath test is sampled several times and each run writes its own AVS CSV.\nSend them all: each is scored on its own, runs that fail the quality checks\nare left out, and `concentration` is the mean over the runs that passed.\n`files` in the response lists every uploaded file in request order, so\nseveral molecules can be scored from the same batch and lined up by index.\n\n    curl -X POST http://localhost:8080/predict/h2/raw/multiple\n      -H \"Authorization: Bearer <token>\"\n      -F \"files=@AVSExtra_2026-06-01_17-10-17_AVS_Run_1.csv\"\n      -F \"files=@AVSExtra_2026-06-01_17-10-17_AVS_Run_2.csv\"","operationId":"predict_raw_multiple_predict__molecule__raw_multiple_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"molecule","in":"path","required":true,"schema":{"type":"string","title":"Molecule"}}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_predict_raw_multiple_predict__molecule__raw_multiple_post"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BatchPredictionResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}}},"components":{"schemas":{"BatchPredictionResponse":{"properties":{"molecule":{"type":"string","title":"Molecule"},"concentration":{"type":"number","title":"Concentration"},"unit":{"type":"string","title":"Unit"},"files_total":{"type":"integer","title":"Files Total"},"files_used":{"type":"integer","title":"Files Used"},"files":{"items":{"$ref":"#/components/schemas/FilePrediction"},"type":"array","title":"Files"}},"type":"object","required":["molecule","concentration","unit","files_total","files_used","files"],"title":"BatchPredictionResponse","description":"Prediction for a set of files sampled in the same test.\n\n`concentration` is the mean over the files that passed the quality checks.\n`files` always holds one entry per uploaded file, valid or not, in request\norder — callers scoring several molecules from the same batch rely on that\norder to line the responses up."},"Body_predict_raw_multiple_predict__molecule__raw_multiple_post":{"properties":{"files":{"items":{"type":"string","contentMediaType":"application/octet-stream"},"type":"array","title":"Files"}},"type":"object","required":["files"],"title":"Body_predict_raw_multiple_predict__molecule__raw_multiple_post"},"FilePrediction":{"properties":{"index":{"type":"integer","title":"Index"},"filename":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Filename"},"valid":{"type":"boolean","title":"Valid"},"reasons":{"items":{"type":"string"},"type":"array","title":"Reasons"},"concentration":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Concentration"},"quality":{"$ref":"#/components/schemas/FileQuality"}},"type":"object","required":["index","valid","quality"],"title":"FilePrediction","description":"Outcome for one file of a batch.\n\n`concentration` is None whenever `valid` is False: a file that failed the\nquality checks is never run through the model."},"FileQuality":{"properties":{"mean_intensity":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Mean Intensity"},"nan_count":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Nan Count"},"mean_intensity_by_wavelength":{"$ref":"#/components/schemas/ImportantWavelengths"}},"type":"object","required":["mean_intensity_by_wavelength"],"title":"FileQuality","description":"Measurements the quality verdict was based on.\n\nBoth are None when the file carried nothing measurable, so a caller can tell\na bad reading from a missing one."},"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"ImportantWavelengths":{"properties":{"483.4":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"483.4"},"656.3":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"656.3"},"431.2":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"431.2"},"810.3":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"810.3"},"821.5":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"821.5"}},"additionalProperties":false,"type":"object","title":"ImportantWavelengths"},"PredictionResponse":{"properties":{"molecule":{"type":"string","title":"Molecule"},"concentration":{"type":"number","title":"Concentration"},"unit":{"type":"string","title":"Unit"}},"type":"object","required":["molecule","concentration","unit"],"title":"PredictionResponse"},"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"}},"securitySchemes":{"HTTPBearer":{"type":"http","scheme":"bearer"}}}}