{"openapi":"3.1.0","info":{"title":"Ecodrive Analyzer Processing API","description":"API for ingesting and processing eco-drive position batches asynchronously. Ingestion endpoint POST /v1/positions/batches accepts an optional batchId; if omitted, the service generates one and returns it as ingestionId.","version":"v1"},"servers":[{"url":"/"}],"tags":[{"name":"Position Ingestion","description":"Endpoints for ingesting position batches for asynchronous processing"}],"paths":{"/v1/positions/batches":{"post":{"tags":["Position Ingestion"],"summary":"Ingest a batch of position points","description":"Accepts a position batch for asynchronous processing. The request field batchId is optional; if omitted, the service generates a UUID and returns it as ingestionId in the 202 response.","operationId":"ingestBatch","parameters":[{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string"}},{"name":"X-Request-Timestamp","in":"header","required":true,"schema":{"type":"string","format":"date-time"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PositionBatchIngestionRequest"}}},"required":true},"responses":{"200":{"description":"OK","content":{"*/*":{"schema":{"$ref":"#/components/schemas/IngestionAcceptedResponse"}}}}}}}},"components":{"schemas":{"PositionBatchIngestionRequest":{"type":"object","description":"Request payload for ingesting a batch of positions for a trip","properties":{"batchId":{"type":"string","format":"uuid","description":"Optional client-provided batch identifier. If omitted, the server generates one."},"tripId":{"type":"string","format":"uuid","description":"Trip identifier to which all provided positions belong"},"vehicleId":{"type":"string","format":"uuid","description":"Vehicle identifier associated with the trip"},"sentAt":{"type":"string","format":"date-time","description":"Timestamp when the batch was sent by the client"},"positions":{"type":"array","description":"Non-empty list of position entries included in this batch","items":{"$ref":"#/components/schemas/PositionInputDto"},"minItems":1},"finalBatch":{"type":"boolean","description":"Indicates whether this is the final batch for the trip"}},"required":["positions","sentAt","tripId","vehicleId"]},"PositionInputDto":{"type":"object","description":"Single GPS position entry included in an ingestion batch","properties":{"timestamp":{"type":"string","format":"date-time","description":"Timestamp of the position measurement"},"latitude":{"type":"number","format":"double","description":"Latitude in decimal degrees","maximum":90.0,"minimum":-90.0},"longitude":{"type":"number","format":"double","description":"Longitude in decimal degrees","maximum":180.0,"minimum":-180.0},"altitude":{"type":"number","format":"double","description":"Altitude in meters"},"speed":{"type":"number","format":"double","description":"Speed in meters per second"},"heading":{"type":"number","format":"double","description":"Heading in degrees","maximum":360.0,"minimum":0.0},"accuracy":{"type":"number","format":"double","description":"Horizontal accuracy in meters"},"altAccuracy":{"type":"number","format":"double","description":"Altitude accuracy in meters"}},"required":["latitude","longitude","timestamp"]},"IngestionAcceptedResponse":{"type":"object","description":"Response returned when a position batch is accepted for asynchronous processing","properties":{"ingestionId":{"type":"string","format":"uuid","description":"Identifier of the accepted ingestion request"},"status":{"type":"string","description":"Processing state of the request","example":"accepted"}}}}}}