{"openapi":"3.1.0","info":{"title":"CargoGauge client API","version":"1.0.0","description":"Read-only access to your company's trips in CargoGauge, for your own systems (ERP, WMS, TMS).\n\n**Authentication.** Send your API key as `Authorization: Bearer cgk_...`. Never put a key in a URL: such a call is refused (API_KEY_IN_URL) and the key is flagged for rotation. **HTTPS only**: plain HTTP is refused with no redirect, and a key ever sent over plain HTTP must be rotated. A key reads every trip of your company: give it to your own systems, not to your customers.\n\n**Polling.** Poll GET /v1/events every 15 to 60 seconds with after=<the last next>; when hasMore is true, call again at once. A new integration starts at GET /v1/me feed.head to skip the backlog, or without after to read the 30 days kept. Events appear within about 5 seconds of the change.\n\n**Compatibility.** v1 only grows: new fields, event types, enum values and endpoints may appear at any time. Ignore what you do not know, and treat every cursor as an opaque string. An unknown query parameter is refused (400).\n\n**When events may be missing.** On a `feed.gap` event, refetch every trip that was open between data.since and data.until (GET /v1/trips?status=open, plus from/to for trips that finished in that window), then carry on with the feed. On 410 CURSOR_EXPIRED, resynchronise through GET /v1/trips (from/to over the days you missed, at most 31 per call, or status=open), then continue with after=params.head. Restarting without after replays the retained feed and repairs nothing.\n\n**ETAs.** An event ETA is a snapshot, valid for freshMinutes (GET /v1/me) after its calculatedAt; if tracking is lost no new event comes, so re-read the trip, whose etaBasis then says stale or none. Only trips under way get ETA events: one that has not started shows a schedule ETA in its detail, and one that has finished gets none.\n\n**Proof of delivery.** stop.delivered with proof:false is a status, not a proof of delivery.\n\nNot served: drivers, vehicles and plates, trailers, subcontractors, positions, photographs, scanned barcode values and any free text. Deleting a finished trip produces no event; GET /v1/trips/{id} then answers 404.","contact":{"email":"support@cargogauge.com"}},"servers":[{"url":"https://api.cargogauge.com"}],"security":[{"apiKey":[]}],"x-reserved-paths":["/v1/shipments/{externalRef}"],"paths":{"/v1/me":{"get":{"operationId":"getMe","summary":"The key, its company and the feed bounds","responses":{"200":{"description":"The key.","headers":{"RateLimit-Limit":{"description":"The key's calls per minute.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Calls left right now.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Me"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/v1/events":{"get":{"operationId":"listEvents","summary":"The event feed, in cursor order","parameters":[{"name":"after","in":"query","required":false,"description":"Continue after this cursor (the previous page's next). Without it, the feed starts at its oldest retained event. Today at most 18 digits; treat it as opaque.","schema":{"type":"string"}},{"name":"limit","in":"query","required":false,"description":"Items per page.","schema":{"type":"integer","minimum":1,"maximum":500,"default":100}}],"responses":{"200":{"description":"A page of events.","headers":{"RateLimit-Limit":{"description":"The key's calls per minute.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Calls left right now.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EventsPage"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"410":{"$ref":"#/components/responses/CursorExpired"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/v1/trips":{"get":{"operationId":"listTrips","summary":"Trip summaries for a day, a range, or every open trip","description":"Exactly one selector: serviceDate; or from and to (both days included, at most 31 days); or status=open. For start-up and for resynchronising after a feed.gap or a 410.","parameters":[{"name":"serviceDate","in":"query","required":false,"description":"The trips of one service day.","schema":{"type":"string","format":"date"}},{"name":"from","in":"query","required":false,"description":"First service day of a range (with to).","schema":{"type":"string","format":"date"}},{"name":"to","in":"query","required":false,"description":"Last service day of a range (with from).","schema":{"type":"string","format":"date"}},{"name":"status","in":"query","required":false,"description":"open: every trip not yet completed or cancelled.","schema":{"type":"string","enum":["open"]}},{"name":"after","in":"query","required":false,"description":"Continue after this cursor (the previous page's next).","schema":{"type":"string"}},{"name":"limit","in":"query","required":false,"description":"Items per page.","schema":{"type":"integer","minimum":1,"maximum":500,"default":100}}],"responses":{"200":{"description":"A page of trips.","headers":{"RateLimit-Limit":{"description":"The key's calls per minute.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Calls left right now.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TripsPage"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/v1/trips/{id}":{"get":{"operationId":"getTrip","summary":"One trip with its stops and live ETA","parameters":[{"name":"id","in":"path","required":true,"description":"The trip id, from an event or a trip summary.","schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"The trip.","headers":{"RateLimit-Limit":{"description":"The key's calls per minute.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Calls left right now.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Trip"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/TripNotFound"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/v1/openapi.json":{"get":{"operationId":"getOpenApi","summary":"This document","security":[],"responses":{"200":{"description":"The OpenAPI document.","content":{"application/json":{"schema":{"type":"object"}}}}}}}},"components":{"securitySchemes":{"apiKey":{"type":"http","scheme":"bearer","description":"An API key from the API tab of your company admin page: cgk_ and 43 characters."}},"responses":{"BadRequest":{"description":"API_KEY_IN_URL, CURSOR_INVALID, TRIP_SELECTOR_INVALID, BAD_REQUEST, or HTTPS_REQUIRED from the edge.","headers":{},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Unauthorized":{"description":"API_KEY_MISSING, API_KEY_INVALID, API_KEY_REVOKED, API_KEY_EXPIRED, COMPANY_SUSPENDED, COMPANY_DELETION_SCHEDULED.","headers":{"WWW-Authenticate":{"description":"Bearer","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Forbidden":{"description":"API_IP_NOT_ALLOWED.","headers":{},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"TripNotFound":{"description":"TRIP_NOT_FOUND.","headers":{},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"CursorExpired":{"description":"CURSOR_EXPIRED: params.head is where to continue after resynchronising.","headers":{},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"RateLimited":{"description":"RATE_LIMITED.","headers":{"Retry-After":{"description":"Seconds until a call is available again.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"schemas":{"Me":{"type":"object","description":"The key making the call, its company and the feed bounds.","required":["key","company","rateLimit","feed","freshMinutes","timezone","version"],"properties":{"key":{"$ref":"#/components/schemas/MeKey"},"company":{"$ref":"#/components/schemas/CompanyRef"},"rateLimit":{"$ref":"#/components/schemas/RateLimit"},"feed":{"$ref":"#/components/schemas/FeedBounds"},"freshMinutes":{"type":"integer","minimum":1,"description":"How long an event's ETA stays valid after its calculatedAt, in minutes: the company's tracking-lost limit, the same one the trip's etaBasis is judged by."},"timezone":{"type":"string","description":"The platform timezone (IANA name) a serviceDate is a day in."},"version":{"type":"string","description":"The contract version (info.version)."}}},"MeKey":{"type":"object","description":"The key.","required":["id","name","hint","createdAt","expiresAt"],"properties":{"id":{"type":"string","format":"uuid","description":"The key."},"name":{"type":"string","description":"The name the admin gave the key."},"hint":{"type":"string","description":"The key's first characters (cgk_...), as the API tab shows them."},"createdAt":{"type":["string","null"],"format":"date-time","description":"When the key was created. ISO-8601, UTC."},"expiresAt":{"type":["string","null"],"format":"date-time","description":"When a rotation ends this key; null while it has no end. ISO-8601, UTC."}}},"CompanyRef":{"type":"object","description":"The key's company.","required":["id","name"],"properties":{"id":{"type":"string","format":"uuid","description":"The company."},"name":{"type":"string","description":"The company name."}}},"RateLimit":{"type":"object","description":"The rate limit of the key.","required":["perMinute"],"properties":{"perMinute":{"type":"integer","minimum":1,"description":"Calls per minute for this key, as a bucket: a full minute may be spent at once, then it refills at this rate."}}},"FeedBounds":{"type":"object","description":"The feed's bounds. Cursors are opaque strings.","required":["head","oldest"],"properties":{"head":{"type":"string","description":"The newest cursor. Start a new integration with after=head to read only what happens from now on."},"oldest":{"type":"string","description":"The oldest cursor still valid as after. GET /v1/events without after starts here."}}},"RouteRef":{"type":"object","description":"The recurring route the trip runs.","required":["id","name"],"properties":{"id":{"type":"string","format":"uuid","description":"The route."},"name":{"type":"string","description":"The route name, unique per company."}}},"LocationRef":{"type":"object","description":"Where the stop is.","required":["id","name"],"properties":{"id":{"type":"string","format":"uuid","description":"The location."},"name":{"type":["string","null"],"description":"The location name; null when it has since been deleted."}}},"Event":{"type":"object","description":"A thin notice: this changed, here is enough to route it. Fetch the trip for its full state. The feed is ordered by cursor, which is the order events were numbered: neither occurredAt nor recordedAt order.","required":["id","cursor","type","occurredAt","recordedAt","trip","stop","data"],"properties":{"id":{"type":"string","format":"uuid","description":"Stable event id: deduplicate on it."},"cursor":{"type":"string","description":"Opaque. Resume with after=<cursor>. Neither contiguous nor arithmetic."},"type":{"type":"string","enum":["trip.planned","trip.changed","trip.started","trip.completed","trip.cancelled","trip.deleted","stop.arrived","stop.departed","stop.delivered","stop.failed","stop.skipped","stop.eta_changed","stop.pod_available","feed.gap"],"x-extensible-enum":true,"description":"What happened. Extensible: ignore values you do not know."},"occurredAt":{"type":"string","format":"date-time","description":"Business time; may be back-dated (a GPS arrival is the first fix inside the area). Not the feed order. ISO-8601, UTC."},"recordedAt":{"type":"string","format":"date-time","description":"When CargoGauge recorded it. Not monotonic in cursor order. ISO-8601, UTC."},"trip":{"anyOf":[{"$ref":"#/components/schemas/EventTrip"},{"type":"null"}]},"stop":{"anyOf":[{"$ref":"#/components/schemas/EventStop"},{"type":"null"}]},"data":{"type":"object","description":"Type-specific; see the *Data schemas. Ignore keys you do not know."}},"allOf":[{"if":{"properties":{"type":{"const":"trip.planned"}},"required":["type"]},"then":{"properties":{"data":{"$ref":"#/components/schemas/EmptyEventData"}}}},{"if":{"properties":{"type":{"const":"trip.changed"}},"required":["type"]},"then":{"properties":{"data":{"$ref":"#/components/schemas/EmptyEventData"}}}},{"if":{"properties":{"type":{"const":"trip.started"}},"required":["type"]},"then":{"properties":{"data":{"$ref":"#/components/schemas/EmptyEventData"}}}},{"if":{"properties":{"type":{"const":"trip.completed"}},"required":["type"]},"then":{"properties":{"data":{"$ref":"#/components/schemas/EmptyEventData"}}}},{"if":{"properties":{"type":{"const":"trip.cancelled"}},"required":["type"]},"then":{"properties":{"data":{"$ref":"#/components/schemas/EmptyEventData"}}}},{"if":{"properties":{"type":{"const":"trip.deleted"}},"required":["type"]},"then":{"properties":{"data":{"$ref":"#/components/schemas/EmptyEventData"}}}},{"if":{"properties":{"type":{"const":"stop.arrived"}},"required":["type"]},"then":{"properties":{"data":{"$ref":"#/components/schemas/EmptyEventData"}}}},{"if":{"properties":{"type":{"const":"stop.departed"}},"required":["type"]},"then":{"properties":{"data":{"$ref":"#/components/schemas/EmptyEventData"}}}},{"if":{"properties":{"type":{"const":"stop.delivered"}},"required":["type"]},"then":{"properties":{"data":{"$ref":"#/components/schemas/StopDeliveredData"}}}},{"if":{"properties":{"type":{"const":"stop.failed"}},"required":["type"]},"then":{"properties":{"data":{"$ref":"#/components/schemas/StopFailedData"}}}},{"if":{"properties":{"type":{"const":"stop.skipped"}},"required":["type"]},"then":{"properties":{"data":{"$ref":"#/components/schemas/EmptyEventData"}}}},{"if":{"properties":{"type":{"const":"stop.eta_changed"}},"required":["type"]},"then":{"properties":{"data":{"$ref":"#/components/schemas/StopEtaChangedData"}}}},{"if":{"properties":{"type":{"const":"stop.pod_available"}},"required":["type"]},"then":{"properties":{"data":{"$ref":"#/components/schemas/StopPodAvailableData"}}}},{"if":{"properties":{"type":{"const":"feed.gap"}},"required":["type"]},"then":{"properties":{"data":{"$ref":"#/components/schemas/FeedGapData"}}}}],"examples":[{"id":"5cbd7fec-9351-405f-9562-575b322c919a","cursor":"1042","type":"stop.arrived","occurredAt":"2026-10-26T10:26:30.339Z","recordedAt":"2026-10-26T10:27:30.339Z","trip":{"id":"fbdb8502-07ea-49f5-b2e3-94819d80033d","serviceDate":"2026-10-26","route":{"id":"71462c05-aa2a-403c-8a1e-dd916a13cd88","name":"Route 12"}},"stop":{"id":"591ee32b-2bc1-4637-9bfb-ee9670df45e3","role":"delivery","location":{"id":"565913f3-5622-468b-8c3b-29917e217533","name":"North terminal"}},"data":{}}]},"EventTrip":{"type":"object","description":"The trip the event is about. route is null only when the route was deleted after the trip.","required":["id","serviceDate","route"],"properties":{"id":{"type":"string","format":"uuid","description":"The trip."},"serviceDate":{"anyOf":[{"type":"string","format":"date","description":"A service day, YYYY-MM-DD, in the platform timezone (/v1/me timezone; Europe/Copenhagen today). A day key: never convert it."},{"type":"null"}]},"route":{"anyOf":[{"$ref":"#/components/schemas/RouteRef"},{"type":"null"}]}}},"EventStop":{"type":"object","description":"The stop the event is about (stop.* events only).","required":["id","role","location"],"properties":{"id":{"type":"string","format":"uuid","description":"The stop."},"role":{"anyOf":[{"type":"string","enum":["pickup","delivery","both","waypoint","cross_dock","return"],"x-extensible-enum":true,"description":"The stop's role when it happened. Extensible: ignore values you do not know."},{"type":"null"}]},"location":{"anyOf":[{"$ref":"#/components/schemas/LocationRef"},{"type":"null"}]}}},"EventsPage":{"type":"object","description":"One page of the feed.","required":["data","next","hasMore"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Event"}},"next":{"type":"string","description":"The cursor to continue with: the last event returned, or the one you sent when there is nothing new. Keep it."},"hasMore":{"type":"boolean","description":"More events are ready: call again with after=next now."}}},"TripSummary":{"type":"object","description":"A trip, without its stops.","required":["id","serviceDate","status","route","plannedStartAt","actualStartAt","actualEndAt","stopCount"],"properties":{"id":{"type":"string","format":"uuid","description":"The trip."},"serviceDate":{"anyOf":[{"type":"string","format":"date","description":"A service day, YYYY-MM-DD, in the platform timezone (/v1/me timezone; Europe/Copenhagen today). A day key: never convert it."},{"type":"null"}]},"status":{"type":"string","enum":["planned","in_progress","completed","cancelled"],"x-extensible-enum":true,"description":"The trip status. Extensible: ignore values you do not know."},"route":{"$ref":"#/components/schemas/RouteRef"},"plannedStartAt":{"type":["string","null"],"format":"date-time","description":"Planned start. ISO-8601, UTC."},"actualStartAt":{"type":["string","null"],"format":"date-time","description":"Actual start. ISO-8601, UTC."},"actualEndAt":{"type":["string","null"],"format":"date-time","description":"Actual end. ISO-8601, UTC."},"stopCount":{"type":"integer","minimum":0,"description":"Stops on the trip."}}},"TripsPage":{"type":"object","description":"One page of trips, ordered by service day and id.","required":["data","next","hasMore"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/TripSummary"}},"next":{"type":["string","null"],"description":"The cursor of the next page (after=next), or null on the last page."},"hasMore":{"type":"boolean","description":"Another page follows."}}},"Trip":{"type":"object","description":"One trip with its ordered stops, live ETA and proof-of-delivery summary.","required":["id","serviceDate","status","route","plannedStartAt","actualStartAt","actualEndAt","stops"],"properties":{"id":{"type":"string","format":"uuid","description":"The trip."},"serviceDate":{"anyOf":[{"type":"string","format":"date","description":"A service day, YYYY-MM-DD, in the platform timezone (/v1/me timezone; Europe/Copenhagen today). A day key: never convert it."},{"type":"null"}]},"status":{"type":"string","enum":["planned","in_progress","completed","cancelled"],"x-extensible-enum":true,"description":"The trip status: planned (not started), in_progress, completed, cancelled. Extensible: ignore values you do not know."},"route":{"$ref":"#/components/schemas/RouteRef"},"plannedStartAt":{"type":["string","null"],"format":"date-time","description":"Planned start. ISO-8601, UTC."},"actualStartAt":{"type":["string","null"],"format":"date-time","description":"Actual start. ISO-8601, UTC."},"actualEndAt":{"type":["string","null"],"format":"date-time","description":"Actual end. ISO-8601, UTC."},"stops":{"type":"array","items":{"$ref":"#/components/schemas/Stop"},"description":"In driving order."}},"examples":[{"id":"fbdb8502-07ea-49f5-b2e3-94819d80033d","serviceDate":"2026-10-26","status":"in_progress","route":{"id":"71462c05-aa2a-403c-8a1e-dd916a13cd88","name":"Route 12"},"plannedStartAt":"2026-10-26T08:29:30.339Z","actualStartAt":"2026-10-26T08:34:30.339Z","actualEndAt":null,"stops":[]}]},"Stop":{"type":"object","description":"A stop of the trip.","required":["id","position","role","status","location","window","eta","etaBasis","etaCalculatedAt","etaApproximate","predictedDelayMinutes","actualArrivalAt","actualDepartureAt","pod"],"properties":{"id":{"type":"string","format":"uuid","description":"The stop."},"position":{"type":"integer","minimum":1,"description":"Place in driving order, from 1."},"role":{"type":"string","enum":["pickup","delivery","both","waypoint","cross_dock","return"],"x-extensible-enum":true,"description":"The stop's role. Extensible: ignore values you do not know."},"status":{"type":"string","enum":["planned","arrived","departed","skipped"],"x-extensible-enum":true,"description":"The stop status. Extensible: ignore values you do not know."},"location":{"$ref":"#/components/schemas/StopLocation"},"window":{"$ref":"#/components/schemas/Window"},"eta":{"type":["string","null"],"format":"date-time","description":"The predicted arrival, as etaBasis allows it to be shown: for live and stale, for schedule only while the projection is recent, never for none. Null once the stop is arrived, departed or skipped. ISO-8601, UTC."},"etaBasis":{"type":"string","enum":["live","stale","schedule","none"],"x-extensible-enum":true,"description":"Where the ETA comes from. live: a position confirmed within freshMinutes. stale: from a position nothing has confirmed since. schedule: the trip has not started, projected from its plan. none: under way, no position-based ETA yet. Extensible: ignore values you do not know."},"etaCalculatedAt":{"type":["string","null"],"format":"date-time","description":"When the ETA was calculated. ISO-8601, UTC."},"etaApproximate":{"type":"boolean","description":"Part of the route behind the ETA was estimated in a straight line."},"predictedDelayMinutes":{"type":["integer","null"],"description":"ETA minus the end of the window (else the planned arrival), in whole minutes; negative is early. Only for a live ETA."},"actualArrivalAt":{"type":["string","null"],"format":"date-time","description":"Actual arrival. ISO-8601, UTC."},"actualDepartureAt":{"type":["string","null"],"format":"date-time","description":"Actual departure. ISO-8601, UTC."},"pod":{"$ref":"#/components/schemas/Pod"}}},"StopLocation":{"type":"object","description":"Where the stop is. No street address is served.","required":["id","name","city","postalCode","countryCode"],"properties":{"id":{"type":"string","format":"uuid","description":"The location."},"name":{"type":["string","null"],"description":"The location name."},"city":{"type":["string","null"],"description":"City."},"postalCode":{"type":["string","null"],"description":"Postal code."},"countryCode":{"type":["string","null"],"description":"ISO 3166-1 alpha-2 country code."}}},"Window":{"type":"object","description":"The planned time at the stop.","required":["from","to"],"properties":{"from":{"type":["string","null"],"format":"date-time","description":"Planned arrival, or the start of the window. ISO-8601, UTC."},"to":{"type":["string","null"],"format":"date-time","description":"Planned departure, or the end of the window. ISO-8601, UTC."}}},"Pod":{"type":"object","description":"The proof-of-delivery summary. Photographs and scanned values are never served; notes neither.","required":["required","status","outcome","reasonCode","capturedAt","photoCount","scanCount"],"properties":{"required":{"type":"boolean","description":"A proof of delivery is required at the stop."},"status":{"type":"string","enum":["none","awaiting_upload","complete","missing"],"x-extensible-enum":true,"description":"The proof-of-delivery state. Extensible: ignore values you do not know."},"outcome":{"type":["string","null"],"enum":["delivered","partial","failed",null],"x-extensible-enum":true,"description":"What happened at the stop; null until a proof is captured."},"reasonCode":{"type":["string","null"],"enum":["refused","damaged","nobody_present","colli_missing","wrong_address","other",null],"x-extensible-enum":true,"description":"Why it was not a clean delivery; null when it was."},"capturedAt":{"type":["string","null"],"format":"date-time","description":"When the proof was captured. ISO-8601, UTC."},"photoCount":{"type":"integer","minimum":0,"description":"Photographs taken (never served)."},"scanCount":{"type":"integer","minimum":0,"description":"Codes scanned (the values are never served)."}}},"Error":{"type":"object","description":"Every error, from the backend or the edge.","required":["statusCode","code","message"],"properties":{"statusCode":{"type":"integer","description":"The HTTP status."},"code":{"type":"string","enum":["API_KEY_IN_URL","CURSOR_INVALID","TRIP_SELECTOR_INVALID","BAD_REQUEST","HTTPS_REQUIRED","API_KEY_MISSING","API_KEY_INVALID","API_KEY_REVOKED","API_KEY_EXPIRED","COMPANY_SUSPENDED","COMPANY_DELETION_SCHEDULED","API_IP_NOT_ALLOWED","TRIP_NOT_FOUND","NOT_FOUND","METHOD_NOT_ALLOWED","CURSOR_EXPIRED","RATE_LIMITED","INTERNAL"],"x-extensible-enum":true,"description":"Branch on this. API_KEY_IN_URL (400): A query value carries something that looks like an API key. Keys go in the Authorization header only; a key that was sent in a URL is flagged for rotation. CURSOR_INVALID (400): `after` is not a cursor this endpoint issued. TRIP_SELECTOR_INVALID (400): GET /v1/trips needs exactly one of serviceDate, from and to together, or status, with real calendar days and a range of at most the documented number of days. BAD_REQUEST (400): A parameter is malformed or unknown (message lists each failed rule). HTTPS_REQUIRED (400, from the edge): The call used plain HTTP. There is no redirect. A key ever sent over plain HTTP must be rotated. API_KEY_MISSING (401): No Authorization header. API_KEY_INVALID (401): The Authorization header is not `Bearer cgk_...`, or names no key. API_KEY_REVOKED (401): The key was revoked. API_KEY_EXPIRED (401): The key was rotated and its overlap has ended. COMPANY_SUSPENDED (401): The key's company is suspended. COMPANY_DELETION_SCHEDULED (401): The key's company is being deleted. API_IP_NOT_ALLOWED (403): The caller's address is outside the key's allowed ranges. Checked before anything else about a known key. TRIP_NOT_FOUND (404): No trip with this id in the key's company. NOT_FOUND (404, from the edge): No such path. METHOD_NOT_ALLOWED (405, from the edge): Not GET or HEAD (header `Allow: GET, HEAD`). v1 is read-only. CURSOR_EXPIRED (410): `after` is older than the retained feed, or ahead of its head (a restored database). `params.head` is where to continue once the client has resynchronised through GET /v1/trips. RATE_LIMITED (429): The key's per-minute budget is spent (or the edge's per-address brake, from nginx). `Retry-After` and `retryAfterSeconds` say when to try again. INTERNAL (500): Unexpected. `reference` identifies it to support."},"message":{"description":"For people. A list of the failed rules on BAD_REQUEST.","anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}]},"params":{"type":"object","description":"Values the error names: head on CURSOR_EXPIRED, maxDays on TRIP_SELECTOR_INVALID."},"retryAfterSeconds":{"type":"integer","description":"On RATE_LIMITED: seconds until a call is available again."},"reference":{"type":"string","description":"On INTERNAL: quote it to support."},"error":{"type":"string","description":"The HTTP reason phrase, on some errors (a BAD_REQUEST, a NOT_FOUND for a path that does not exist). For people: branch on code."}}},"EmptyEventData":{"type":"object","description":"No data: the event says what changed; fetch the trip for its state.","required":[],"properties":{}},"StopDeliveredData":{"type":"object","description":"data of stop.delivered.","required":["outcome","reasonCode","proof"],"properties":{"outcome":{"type":"string","enum":["delivered","partial"],"description":"delivered or partial. Read from the stop's proof of delivery; \"delivered\" without proof is a status, not a proof."},"reasonCode":{"type":["string","null"],"enum":["refused","damaged","nobody_present","colli_missing","wrong_address","other",null],"description":"Why it was not a clean delivery; null when it was. Extensible.","x-extensible-enum":true},"proof":{"type":"boolean","description":"The driver captured a proof of delivery at the stop. False means the stop was departed without one."}}},"StopFailedData":{"type":"object","description":"data of stop.failed.","required":["reasonCode","proof"],"properties":{"reasonCode":{"type":["string","null"],"enum":["refused","damaged","nobody_present","colli_missing","wrong_address","other",null],"description":"Why it was not a clean delivery; null when it was. Extensible.","x-extensible-enum":true},"proof":{"type":"boolean","description":"The driver captured a proof of delivery at the stop. False means the stop was departed without one."}}},"StopEtaChangedData":{"type":"object","description":"data of stop.eta_changed.","required":["eta","previousEta","calculatedAt","approximate"],"properties":{"eta":{"type":"string","format":"date-time","description":"The new predicted arrival. ISO-8601, UTC."},"previousEta":{"type":["string","null"],"format":"date-time","description":"The ETA last published for the stop; null for its first. ISO-8601, UTC."},"calculatedAt":{"type":["string","null"],"format":"date-time","description":"When the ETA was calculated. ISO-8601, UTC."},"approximate":{"type":"boolean","description":"Part of the route was estimated in a straight line."}}},"StopPodAvailableData":{"type":"object","description":"data of stop.pod_available.","required":["photoCount","scanCount"],"properties":{"photoCount":{"type":"integer","minimum":0,"description":"Photographs of the proof of delivery (never served)."},"scanCount":{"type":"integer","minimum":0,"description":"Codes scanned at the stop (the values are never served)."}}},"FeedGapData":{"type":"object","description":"data of feed.gap.","required":["since","until"],"properties":{"since":{"type":"string","format":"date-time","description":"Capture was off from (about) this moment. ISO-8601, UTC."},"until":{"type":"string","format":"date-time","description":"Capture was back on at (about) this moment. ISO-8601, UTC."}}}}}}