{"openapi":"3.1.0","info":{"title":"Havida Sensor API","description":"Customer and location-scoped current and historical Havida sensor measurements.","version":"4.9.0"},"paths":{"/oauth/token":{"post":{"tags":["OAuth2"],"summary":"Oauth Token","operationId":"oauth_token_oauth_token_post","requestBody":{"content":{"application/x-www-form-urlencoded":{"schema":{"$ref":"#/components/schemas/Body_oauth_token_oauth_token_post"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBasic":[]}]}},"/v1/oauth/identity":{"get":{"tags":["OAuth2"],"summary":"Oauth Identity","operationId":"oauth_identity_v1_oauth_identity_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"HTTPBearer":[]}]}},"/health":{"get":{"tags":["Operations"],"summary":"Health","operationId":"health_health_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/v1/measurements":{"post":{"tags":["Ingest"],"summary":"Receive","operationId":"receive_v1_measurements_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MeasurementBatch"}}},"required":true},"responses":{"202":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/v1/measurements/latest":{"get":{"tags":["Read-only"],"summary":"Latest","operationId":"latest_v1_measurements_latest_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"customer_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Customer Id"}},{"name":"location_name","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Location Name"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/measurements/history":{"get":{"tags":["Read-only"],"summary":"History","operationId":"history_v1_measurements_history_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"from","in":"query","required":true,"schema":{"type":"string","format":"date-time","title":"From"}},{"name":"to","in":"query","required":true,"schema":{"type":"string","format":"date-time","title":"To"}},{"name":"customer_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Customer Id"}},{"name":"location_name","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Location Name"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":5000,"minimum":1,"default":1000,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/measurements/series":{"get":{"tags":["Read-only"],"summary":"Series","operationId":"series_v1_measurements_series_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"from","in":"query","required":true,"schema":{"type":"string","format":"date-time","title":"From"}},{"name":"to","in":"query","required":true,"schema":{"type":"string","format":"date-time","title":"To"}},{"name":"customer_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Customer Id"}},{"name":"location_name","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Location Name"}},{"name":"bucket_minutes","in":"query","required":false,"schema":{"type":"integer","default":10,"title":"Bucket Minutes"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/measurements/export.csv":{"get":{"tags":["Read-only"],"summary":"Export Csv","operationId":"export_csv_v1_measurements_export_csv_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"from","in":"query","required":true,"schema":{"type":"string","format":"date-time","title":"From"}},{"name":"to","in":"query","required":true,"schema":{"type":"string","format":"date-time","title":"To"}},{"name":"customer_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Customer Id"}},{"name":"location_name","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Location Name"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/admin/status":{"get":{"tags":["Havida administration"],"summary":"Admin Status","operationId":"admin_status_v1_admin_status_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"HTTPBearer":[]}]}},"/v1/admin/audit":{"get":{"tags":["Havida administration"],"summary":"Audit Log","operationId":"audit_log_v1_admin_audit_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":1000,"minimum":1,"default":200,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/admin/oauth-clients":{"get":{"tags":["Havida administration"],"summary":"Oauth Clients","operationId":"oauth_clients_v1_admin_oauth_clients_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"HTTPBearer":[]}]},"post":{"tags":["Havida administration"],"summary":"Oauth Client Create","operationId":"oauth_client_create_v1_admin_oauth_clients_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OAuthClientCreate"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/v1/admin/oauth-clients/{client_id}/rotate-secret":{"post":{"tags":["Havida administration"],"summary":"Oauth Client Rotate","operationId":"oauth_client_rotate_v1_admin_oauth_clients__client_id__rotate_secret_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"client_id","in":"path","required":true,"schema":{"type":"string","title":"Client Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OAuthRotate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/admin/oauth-clients/{client_id}/revoke":{"post":{"tags":["Havida administration"],"summary":"Oauth Client Revoke","operationId":"oauth_client_revoke_v1_admin_oauth_clients__client_id__revoke_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"client_id","in":"path","required":true,"schema":{"type":"string","title":"Client Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/cages":{"get":{"tags":["Cage history"],"summary":"Cages","operationId":"cages_v1_cages_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"customer_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Customer Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/cages/{cage_id}/history":{"get":{"tags":["Cage history"],"summary":"Linked Cage History","operationId":"linked_cage_history_v1_cages__cage_id__history_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"cage_id","in":"path","required":true,"schema":{"type":"string","title":"Cage Id"}},{"name":"from","in":"query","required":true,"schema":{"type":"string","format":"date-time","title":"From"}},{"name":"to","in":"query","required":true,"schema":{"type":"string","format":"date-time","title":"To"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":50000,"minimum":1,"default":5000,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/admin/cages":{"post":{"tags":["Havida administration"],"summary":"Admin Create Cage","operationId":"admin_create_cage_v1_admin_cages_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CageCreate"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/v1/admin/cages/{cage_id}/camera-links":{"post":{"tags":["Havida administration"],"summary":"Admin Link Camera","operationId":"admin_link_camera_v1_admin_cages__cage_id__camera_links_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"cage_id","in":"path","required":true,"schema":{"type":"string","title":"Cage Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CameraLinkCreate"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}}},"components":{"schemas":{"Body_oauth_token_oauth_token_post":{"properties":{"grant_type":{"type":"string","title":"Grant Type"},"scope":{"type":"string","title":"Scope","default":""}},"type":"object","required":["grant_type"],"title":"Body_oauth_token_oauth_token_post"},"CageCreate":{"properties":{"cage_id":{"type":"string","pattern":"^[a-z0-9][a-z0-9._-]{2,99}$","title":"Cage Id"},"customer_id":{"type":"string","maxLength":63,"minLength":1,"title":"Customer Id"},"location_name":{"type":"string","maxLength":120,"minLength":1,"title":"Location Name"},"display_name":{"type":"string","maxLength":160,"minLength":1,"title":"Display Name"}},"type":"object","required":["cage_id","customer_id","location_name","display_name"],"title":"CageCreate"},"CameraLinkCreate":{"properties":{"camera_id":{"type":"string","maxLength":80,"minLength":1,"title":"Camera Id"},"valid_from":{"type":"string","format":"date-time","title":"Valid From"},"valid_to":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Valid To"}},"type":"object","required":["camera_id","valid_from"],"title":"CameraLinkCreate"},"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"Measurement":{"properties":{"customer_name":{"type":"string","maxLength":120,"minLength":1,"title":"Customer Name"},"location_id":{"anyOf":[{"type":"string","maxLength":63,"minLength":1,"pattern":"^[a-z0-9][a-z0-9._-]*$"},{"type":"null"}],"title":"Location Id"},"location_name":{"type":"string","maxLength":120,"minLength":1,"title":"Location Name"},"cage_number":{"anyOf":[{"type":"string","maxLength":40,"minLength":1},{"type":"null"}],"title":"Cage Number"},"camera_name":{"type":"string","maxLength":160,"minLength":1,"title":"Camera Name"},"device_key":{"anyOf":[{"type":"string","maxLength":180,"minLength":1},{"type":"null"}],"title":"Device Key"},"temperature_celsius":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Temperature Celsius"},"depth_meters":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Depth Meters"},"oxygen_percent":{"anyOf":[{"type":"number","maximum":200.0,"minimum":0.0},{"type":"null"}],"title":"Oxygen Percent"},"measured_at":{"type":"string","format":"date-time","title":"Measured At"}},"additionalProperties":false,"type":"object","required":["customer_name","location_name","camera_name","measured_at"],"title":"Measurement"},"MeasurementBatch":{"properties":{"measurements":{"items":{"$ref":"#/components/schemas/Measurement"},"type":"array","maxItems":500,"minItems":1,"title":"Measurements"}},"additionalProperties":false,"type":"object","required":["measurements"],"title":"MeasurementBatch"},"OAuthClientCreate":{"properties":{"client_id":{"type":"string","pattern":"^[A-Za-z0-9._-]{3,80}$","title":"Client Id"},"display_name":{"type":"string","maxLength":160,"minLength":1,"title":"Display Name"},"customer_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Customer Id"},"customer_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Customer Name"},"location_id":{"anyOf":[{"type":"string","pattern":"^[a-z0-9][a-z0-9._-]*$"},{"type":"null"}],"title":"Location Id"},"location_name":{"anyOf":[{"type":"string","maxLength":120},{"type":"null"}],"title":"Location Name"},"role":{"type":"string","pattern":"^(ingest|read|admin)$","title":"Role"},"scopes":{"items":{"type":"string"},"type":"array","minItems":1,"title":"Scopes"}},"type":"object","required":["client_id","display_name","role","scopes"],"title":"OAuthClientCreate"},"OAuthRotate":{"properties":{"grace_seconds":{"type":"integer","maximum":86400.0,"minimum":0.0,"title":"Grace Seconds","default":3600}},"type":"object","title":"OAuthRotate"},"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":{"HTTPBasic":{"type":"http","scheme":"basic"},"HTTPBearer":{"type":"http","description":"Enter the token value only. Swagger adds the Bearer prefix automatically.","scheme":"bearer"}}}}