{"openapi":"3.1.0","info":{"title":"InQMS API","description":"InQMS API allows fetching content from sample collections.\n\nBehind the scenes there is a system (called KOA) which collects live samples from multiple data sources.\n\nOne sample collection (collection for short) contains consequtive set of samples consumed from one data source within single session (which can last for years).\n\nInQMS API allows consuming samples from collections (currently it allows consuming the latest one).\n\n# Terms and definitions\nTerms related to where the data comes from:\n- **KOA**: system, which collects samples from multiple data sources and archives them.\n- **(data) provider**: subject making the data technically available\n- **(data) source**: technical system delivering data using specific content, format and using specific protocol\n\nTerms related to how are the data made available via InQMS API:\n- **(data) sample**: single instance of a message, received from (data) source\n- **(KOA) session**: collection of samples consumed from a data source during single subscription\n- **(data) collection**: virtual folder for storing samples collected during single KOA session\n- **collection url**: URL of data collection virtual folder on AWS S3\n- **collection id** string identifying collection (does not include \"/\" character).\n\n\n# API documentation\n\nDocumentation (work in progress) can be seen in two flavours:\n\n- Swagger: apart from API documentation also allows interactive calls of the API\n- Redoc: not interactive, but looks pretty\n\nThe docs lives on these urls:\n\n- Swagger: <https://api.inqms.tamtamresearch.com/docs>\n- Redoc: <https://api.inqms.tamtamresearch.com/redoc>\n\n# Quick Start\nNote 1: examples below use httpie CLI (http). For more see https://httpie.io/cli. Feel free to use any outher HTTP client.\n\nNote 2: Currently there is no authorization yet. It will come later on.\n\n\n## Welcome to API root\n\nTry to access the API::\n\n    http --print Hhb GET https://api.inqms.tamtamresearch.com\n    GET / HTTP/1.1\n    Accept-Encoding: gzip, deflate\n    Connection: keep-alive\n    User-Agent: HTTPie/3.2.2\n    Accept: application/json, */*;q=0.5\n    Content-Type: application/json\n    Host: api.inqms.tamtamresearch.com\n\n    HTTP/1.1 200 OK\n    Content-Length: 89\n    Content-Type: application/json\n    Date: Wed, 24 Jul 2024 21:49:04 GMT\n    Server: uvicorn\n\n    {\n        \"openapi_json_url\": \"/openapi.json\",\n        \"redoc_docs_url\": \"/redoc\",\n        \"swagger_docs_url\": \"/docs\"\n    }\n\n\n## List data collections available\n\nCollect list of data collections showing their url and id (hash).\n\n\n      http GET https://api.inqms.tamtamresearch.com/collection\n      [\n        {\n          \"id\": \"46fdc50cf6c3c17e\",\n          \"url\": \"s3://ttr-koa/cz-ndic/d2-pls-weather-v1.1-gn23.12/2024-06-13/\"\n        },\n        .....\n        {\n          \"id\": \"2fd3e15bc8844b99\",\n          \"url\": \"s3://ttr-koa/fr-bison-fute.gouv.fr/d2-action-c/2024-07-17/\"\n        }\n      ]\n\n## Pick a collection id and fetch its latest sample\n\n1. Find the collection you want to get the latest sample from, e.g. s3://ttr-koa/fr-bison-fute.gouv.fr/d2-action-c/2024-07-17/\n2. Record (put to clibpoard?) the collection id, e.g. \"2fd3e15bc8844b99\"\n3. Take the following URL pattern `https://api.inqms.tamtamresearch.com/collection/id/{collection_id}/sample/latest`\n4. Fill in the collection id, e.g. `https://api.inqms.tamtamresearch.com/collection/id/2fd3e15bc8844b99/sample/latest`\n5. Make HTTP GET request to given URL (and make sure you \"follow redirects\")\n\nLets try it:\n\n    http GET https://api.inqms.tamtamresearch.com/collection/id/2fd3e15bc8844b99/sample/latest\n\nIt might seem like nothing was returned, but as this is redirection response, the relevant content is found in Location response header.\n\nLets repeat the request and print request and response headers:\n\n    http --print Hh GET https://api.inqms.tamtamresearch.com/collection/id/2fd3e15bc8844b99/sample/latest\n    Accept: */*\n    Accept-Encoding: gzip, deflate\n    Connection: keep-alive\n    Host: api.inqms.tamtamresearch.com\n    User-Agent: HTTPie/3.2.2\n\n    HTTP/1.1 307 Temporary Redirect\n    Content-Disposition: attachment; filename=\"2024-07-25T12_30_35.211299Z-8cb9.xml\"\n    Content-Length: 0\n    Date: Thu, 25 Jul 2024 12:32:03 GMT\n    Etag: \"f7bbb7c49fdf00b184142110f63e6965\"\n    Last-Modified: Thu, 25 Jul 2024 12:30:36 +0000\n    Location: https://ttr-koa.s3.eu-west-1.amazonaws.com/fr-bison-fute.gouv.fr/d2-action-c/2024-07-17/2024-07-25T12_30_35.211299Z-8cb9?AWSAccessKeyId=AKIAJ3CMXEIHXMCCKFLA&Signature=FP%2Brs%2FDcFUF0J4FjbsK01rZXUyQ%3D&Expires=1721914325\n    Server: uvicorn\n\nLets instruct our HTTP client to follow redirects:\n\n    http --follow GET https://api.inqms.tamtamresearch.com/collection/id/2fd3e15bc8844b99/sample/latest\n\nYou shall see the content of the latest sample printed to stdout.\n\nThis concludes the Quick Start.\n\n# Using conditional HTTP requests\nContitional HTTP requests allows you to:\n\n- fetch some content\n- mark what you have got (either using timestamp from Last-Modified header or content \"fingerprint\" from  ETag header)\n- with next HTTP request, ask for the data again, but using a header with your \"mark\" you say: \"this is what I already have, send content only if there is something new.\"\n- the response either provides you with new content or states 304 Not Modified\n\nThis allows more frequent requests without repeatedly fetching data, you already have.\n\n## Using ETag value for If-None-Match header\n- you copy literal value from \"ETag\" response header (warning, it very often includes double-quotes as part of the literal value, this might be confusing a bit) \n- put it into your request header named \"If-None-Match\"\n\n## Using Last-Modified value for If-Modified-Since header\n- you copy literal value from \"Last-Modified\" response header\n- put it into your request header named \"If-Modified-Since\"\n\n\nPick the method (If-Modified-Since or If-None-Match) you prefer. If you use both, the If-None-Match will be used and If-Modified-Since will be ignored.\n\n\nNote, that the InQMS API does one extra step to make things simpler: even though it redirects you to another url to get the content, the actual response\nfrom the API (which either redirects you or report 304 Not Modified) uses exact copy of real target headers Last-Modified and ETag.\n\n# Actual API documentation\n","version":"0.1.0"},"paths":{"/collection":{"get":{"summary":"Get Collections","description":"List collections.","operationId":"get_collections_collection_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Collections"}}}}}}},"/collections.html":{"get":{"summary":"Get Collections Html","description":"List collections as HTML page.","operationId":"get_collections_html_collections_html_get","responses":{"200":{"description":"Successful Response","content":{"text/html":{"schema":{"type":"string"}}}}}}},"/collection/id/{collection_id}":{"get":{"summary":"Get Collection By Id","description":"Describe single collection identified by id.","operationId":"get_collection_by_id_collection_id__collection_id__get","parameters":[{"name":"collection_id","in":"path","required":true,"schema":{"title":"Collection Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Collection"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/collection/url/{collection_url}":{"get":{"summary":"Get Collection By Url","description":"Describe single collection identified by its url.","operationId":"get_collection_by_url_collection_url__collection_url__get","parameters":[{"name":"collection_url","in":"path","required":true,"schema":{"title":"Collection Url"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Collection"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/collection/id/{collection_id}/sample/latest":{"get":{"summary":"Get Latest Sample","description":"Redirects to the latest sample in collection identified by its id","operationId":"get_latest_sample_collection_id__collection_id__sample_latest_get","parameters":[{"name":"collection_id","in":"path","required":true,"schema":{"type":"string","title":"Collection Id"}},{"name":"if-modified-since","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"If-Modified-Since"}},{"name":"if-none-match","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"If-None-Match"}}],"responses":{"307":{"description":"Temporary redirect to actual content.\n\nTarget url has limited time validity.\n\nResponse headers ETag and Last-Modified copy values from the target sample."},"404":{"description":"Not Found."},"304":{"description":"Not Modified.\n\nResponse headers ETag and Last-Modified copy values from target sample."},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}}},"components":{"schemas":{"Collection":{"properties":{"id":{"type":"string","title":"Id"},"url":{"type":"string","title":"Url"}},"type":"object","required":["id","url"],"title":"Collection","examples":[{"id":"075e9b22843abd3c","url":"cz-ndic/d2-vms_1851D6F/2023-10-16"}]},"Collections":{"items":{"$ref":"#/components/schemas/Collection"},"type":"array","title":"Collections","examples":[[{"id":"9d4cdadc95bd41fe","url":"cz-ndic/d2-pls-weather-v1.1-gn23.12/2024-06-13"},{"id":"b2533cf0d495d798","url":"cz-ndic/d2-traffic-status/2023-10-16"},{"id":"075e9b22843abd3c","url":"cz-ndic/d2-vms_1851D6F/2023-10-16"}]]},"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"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"}}}}