{
 "openapi": "3.1.0",
 "info": {
  "title": "Dashivo Pro API",
  "version": "1.0.0",
  "description": "Read your company's drivers, vehicles, routes, live locations, alerts, events, scores and footage details; create and dispatch routes; subscribe to webhooks. Owners and Admins create keys in the console (Company \u203a API & webhooks). Each key may make 120 requests a minute (30 of them writes). Guide: https://dashivo.app/pro/api/",
  "contact": {
   "name": "Dashivo Pro support",
   "url": "https://dashivo.app/pro/contact/"
  }
 },
 "servers": [
  {
   "url": "https://pro.dashivo.app/api/public/v1"
  }
 ],
 "security": [
  {
   "apiKey": []
  }
 ],
 "tags": [
  {
   "name": "Account"
  },
  {
   "name": "Drivers"
  },
  {
   "name": "Vehicles"
  },
  {
   "name": "Routes"
  },
  {
   "name": "Live"
  },
  {
   "name": "Safety"
  },
  {
   "name": "Footage"
  },
  {
   "name": "Webhooks"
  }
 ],
 "paths": {
  "/me": {
   "get": {
    "summary": "The key and its company",
    "tags": [
     "Account"
    ],
    "parameters": [],
    "responses": {
     "200": {
      "description": "OK",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "400": {
      "$ref": "#/components/responses/BadRequest"
     },
     "401": {
      "$ref": "#/components/responses/Unauthorized"
     },
     "403": {
      "$ref": "#/components/responses/Forbidden"
     },
     "429": {
      "$ref": "#/components/responses/RateLimited"
     }
    },
    "description": "Any valid key. Zapier's connection test.",
    "security": [
     {
      "apiKey": []
     }
    ]
   }
  },
  "/drivers": {
   "get": {
    "summary": "List drivers",
    "tags": [
     "Drivers"
    ],
    "parameters": [
     {
      "name": "email",
      "in": "query",
      "schema": {
       "type": "string"
      },
      "description": "Only the driver with this email."
     }
    ],
    "responses": {
     "200": {
      "description": "OK",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "required": [
          "data",
          "has_more",
          "next_cursor"
         ],
         "properties": {
          "data": {
           "type": "array",
           "items": {
            "$ref": "#/components/schemas/Driver"
           }
          },
          "has_more": {
           "type": "boolean"
          },
          "next_cursor": {
           "type": [
            "string",
            "null"
           ]
          }
         }
        }
       }
      }
     },
     "400": {
      "$ref": "#/components/responses/BadRequest"
     },
     "401": {
      "$ref": "#/components/responses/Unauthorized"
     },
     "403": {
      "$ref": "#/components/responses/Forbidden"
     },
     "429": {
      "$ref": "#/components/responses/RateLimited"
     }
    },
    "security": [
     {
      "apiKey": []
     }
    ],
    "x-required-scope": "drivers:read",
    "description": "Scope: `drivers:read`."
   }
  },
  "/drivers/{driver_id}": {
   "get": {
    "summary": "Get a driver",
    "tags": [
     "Drivers"
    ],
    "parameters": [
     {
      "name": "driver_id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string",
       "format": "uuid"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "OK",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Driver"
        }
       }
      }
     },
     "400": {
      "$ref": "#/components/responses/BadRequest"
     },
     "401": {
      "$ref": "#/components/responses/Unauthorized"
     },
     "403": {
      "$ref": "#/components/responses/Forbidden"
     },
     "429": {
      "$ref": "#/components/responses/RateLimited"
     }
    },
    "security": [
     {
      "apiKey": []
     }
    ],
    "x-required-scope": "drivers:read",
    "description": "Scope: `drivers:read`."
   }
  },
  "/vehicles": {
   "get": {
    "summary": "List vehicles",
    "tags": [
     "Vehicles"
    ],
    "parameters": [],
    "responses": {
     "200": {
      "description": "OK",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "required": [
          "data",
          "has_more",
          "next_cursor"
         ],
         "properties": {
          "data": {
           "type": "array",
           "items": {
            "$ref": "#/components/schemas/Vehicle"
           }
          },
          "has_more": {
           "type": "boolean"
          },
          "next_cursor": {
           "type": [
            "string",
            "null"
           ]
          }
         }
        }
       }
      }
     },
     "400": {
      "$ref": "#/components/responses/BadRequest"
     },
     "401": {
      "$ref": "#/components/responses/Unauthorized"
     },
     "403": {
      "$ref": "#/components/responses/Forbidden"
     },
     "429": {
      "$ref": "#/components/responses/RateLimited"
     }
    },
    "security": [
     {
      "apiKey": []
     }
    ],
    "x-required-scope": "vehicles:read",
    "description": "Scope: `vehicles:read`."
   }
  },
  "/vehicles/{vehicle_id}": {
   "get": {
    "summary": "Get a vehicle",
    "tags": [
     "Vehicles"
    ],
    "parameters": [
     {
      "name": "vehicle_id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string",
       "format": "uuid"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "OK",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Vehicle"
        }
       }
      }
     },
     "400": {
      "$ref": "#/components/responses/BadRequest"
     },
     "401": {
      "$ref": "#/components/responses/Unauthorized"
     },
     "403": {
      "$ref": "#/components/responses/Forbidden"
     },
     "429": {
      "$ref": "#/components/responses/RateLimited"
     }
    },
    "security": [
     {
      "apiKey": []
     }
    ],
    "x-required-scope": "vehicles:read",
    "description": "Scope: `vehicles:read`."
   }
  },
  "/routes": {
   "get": {
    "summary": "List routes",
    "tags": [
     "Routes"
    ],
    "parameters": [
     {
      "name": "status",
      "in": "query",
      "schema": {
       "type": "string",
       "enum": [
        "draft",
        "dispatched",
        "archived"
       ]
      }
     },
     {
      "name": "updated_since",
      "in": "query",
      "schema": {
       "type": "string",
       "format": "date-time"
      }
     },
     {
      "name": "limit",
      "in": "query",
      "schema": {
       "type": "integer",
       "minimum": 1,
       "maximum": 200,
       "default": 50
      }
     },
     {
      "name": "cursor",
      "in": "query",
      "schema": {
       "type": "string"
      },
      "description": "next_cursor from the previous page."
     }
    ],
    "responses": {
     "200": {
      "description": "OK",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "required": [
          "data",
          "has_more",
          "next_cursor"
         ],
         "properties": {
          "data": {
           "type": "array",
           "items": {
            "$ref": "#/components/schemas/Route"
           }
          },
          "has_more": {
           "type": "boolean"
          },
          "next_cursor": {
           "type": [
            "string",
            "null"
           ]
          }
         }
        }
       }
      }
     },
     "400": {
      "$ref": "#/components/responses/BadRequest"
     },
     "401": {
      "$ref": "#/components/responses/Unauthorized"
     },
     "403": {
      "$ref": "#/components/responses/Forbidden"
     },
     "429": {
      "$ref": "#/components/responses/RateLimited"
     }
    },
    "security": [
     {
      "apiKey": []
     }
    ],
    "x-required-scope": "routes:read",
    "description": "Scope: `routes:read`."
   },
   "post": {
    "summary": "Create a route from orders or stops",
    "tags": [
     "Routes"
    ],
    "parameters": [],
    "responses": {
     "201": {
      "description": "Created",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Route"
        }
       }
      }
     },
     "400": {
      "$ref": "#/components/responses/BadRequest"
     },
     "401": {
      "$ref": "#/components/responses/Unauthorized"
     },
     "403": {
      "$ref": "#/components/responses/Forbidden"
     },
     "429": {
      "$ref": "#/components/responses/RateLimited"
     }
    },
    "security": [
     {
      "apiKey": []
     }
    ],
    "x-required-scope": "routes:write",
    "description": "Stops without lat/lon are looked up on Dashivo's address search (up to 40 a request). With dispatch true the driver gets it at once.\n\nScope: `routes:write`.",
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/NewRoute"
       }
      }
     }
    }
   }
  },
  "/routes/{route_id}": {
   "get": {
    "summary": "Get a route with its stops, their status and proof of delivery",
    "tags": [
     "Routes"
    ],
    "parameters": [
     {
      "name": "route_id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string",
       "format": "uuid"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "OK",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Route"
        }
       }
      }
     },
     "400": {
      "$ref": "#/components/responses/BadRequest"
     },
     "401": {
      "$ref": "#/components/responses/Unauthorized"
     },
     "403": {
      "$ref": "#/components/responses/Forbidden"
     },
     "429": {
      "$ref": "#/components/responses/RateLimited"
     }
    },
    "security": [
     {
      "apiKey": []
     }
    ],
    "x-required-scope": "routes:read",
    "description": "Scope: `routes:read`."
   }
  },
  "/routes/{route_id}/dispatch": {
   "post": {
    "summary": "Dispatch a route to its driver",
    "tags": [
     "Routes"
    ],
    "parameters": [
     {
      "name": "route_id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string",
       "format": "uuid"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "OK",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Route"
        }
       }
      }
     },
     "400": {
      "$ref": "#/components/responses/BadRequest"
     },
     "401": {
      "$ref": "#/components/responses/Unauthorized"
     },
     "403": {
      "$ref": "#/components/responses/Forbidden"
     },
     "429": {
      "$ref": "#/components/responses/RateLimited"
     }
    },
    "security": [
     {
      "apiKey": []
     }
    ],
    "x-required-scope": "routes:write",
    "description": "Scope: `routes:write`."
   }
  },
  "/media/{media_id}": {
   "get": {
    "summary": "Download a proof-of-delivery photo or signature",
    "tags": [
     "Routes"
    ],
    "parameters": [
     {
      "name": "media_id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string",
       "format": "uuid"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "The image (it may redirect to a short-lived link)",
      "content": {
       "image/jpeg": {},
       "image/png": {}
      }
     },
     "400": {
      "$ref": "#/components/responses/BadRequest"
     },
     "401": {
      "$ref": "#/components/responses/Unauthorized"
     },
     "403": {
      "$ref": "#/components/responses/Forbidden"
     },
     "429": {
      "$ref": "#/components/responses/RateLimited"
     }
    },
    "security": [
     {
      "apiKey": []
     }
    ],
    "x-required-scope": "routes:read",
    "description": "Scope: `routes:read`."
   }
  },
  "/locations": {
   "get": {
    "summary": "Live locations of drivers on shift",
    "tags": [
     "Live"
    ],
    "parameters": [],
    "responses": {
     "200": {
      "description": "OK",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "required": [
          "data",
          "has_more",
          "next_cursor"
         ],
         "properties": {
          "data": {
           "type": "array",
           "items": {
            "$ref": "#/components/schemas/Location"
           }
          },
          "has_more": {
           "type": "boolean"
          },
          "next_cursor": {
           "type": [
            "string",
            "null"
           ]
          }
         }
        }
       }
      }
     },
     "400": {
      "$ref": "#/components/responses/BadRequest"
     },
     "401": {
      "$ref": "#/components/responses/Unauthorized"
     },
     "403": {
      "$ref": "#/components/responses/Forbidden"
     },
     "429": {
      "$ref": "#/components/responses/RateLimited"
     }
    },
    "security": [
     {
      "apiKey": []
     }
    ],
    "x-required-scope": "locations:read",
    "description": "Scope: `locations:read`."
   }
  },
  "/alerts": {
   "get": {
    "summary": "The alert log (30 days)",
    "tags": [
     "Safety"
    ],
    "parameters": [
     {
      "name": "since",
      "in": "query",
      "schema": {
       "type": "string",
       "format": "date-time"
      }
     },
     {
      "name": "severity",
      "in": "query",
      "schema": {
       "type": "string",
       "enum": [
        "critical",
        "warning",
        "info"
       ]
      }
     },
     {
      "name": "limit",
      "in": "query",
      "schema": {
       "type": "integer",
       "minimum": 1,
       "maximum": 200,
       "default": 50
      }
     },
     {
      "name": "cursor",
      "in": "query",
      "schema": {
       "type": "string"
      },
      "description": "next_cursor from the previous page."
     }
    ],
    "responses": {
     "200": {
      "description": "OK",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "required": [
          "data",
          "has_more",
          "next_cursor"
         ],
         "properties": {
          "data": {
           "type": "array",
           "items": {
            "$ref": "#/components/schemas/Alert"
           }
          },
          "has_more": {
           "type": "boolean"
          },
          "next_cursor": {
           "type": [
            "string",
            "null"
           ]
          }
         }
        }
       }
      }
     },
     "400": {
      "$ref": "#/components/responses/BadRequest"
     },
     "401": {
      "$ref": "#/components/responses/Unauthorized"
     },
     "403": {
      "$ref": "#/components/responses/Forbidden"
     },
     "429": {
      "$ref": "#/components/responses/RateLimited"
     }
    },
    "security": [
     {
      "apiKey": []
     }
    ],
    "x-required-scope": "alerts:read",
    "description": "Scope: `alerts:read`."
   }
  },
  "/events": {
   "get": {
    "summary": "Driving events (30 days)",
    "tags": [
     "Safety"
    ],
    "parameters": [
     {
      "name": "since",
      "in": "query",
      "schema": {
       "type": "string",
       "format": "date-time"
      }
     },
     {
      "name": "type",
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "driver_id",
      "in": "query",
      "schema": {
       "type": "string",
       "format": "uuid"
      }
     },
     {
      "name": "limit",
      "in": "query",
      "schema": {
       "type": "integer",
       "minimum": 1,
       "maximum": 200,
       "default": 50
      }
     },
     {
      "name": "cursor",
      "in": "query",
      "schema": {
       "type": "string"
      },
      "description": "next_cursor from the previous page."
     }
    ],
    "responses": {
     "200": {
      "description": "OK",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "required": [
          "data",
          "has_more",
          "next_cursor"
         ],
         "properties": {
          "data": {
           "type": "array",
           "items": {
            "$ref": "#/components/schemas/Event"
           }
          },
          "has_more": {
           "type": "boolean"
          },
          "next_cursor": {
           "type": [
            "string",
            "null"
           ]
          }
         }
        }
       }
      }
     },
     "400": {
      "$ref": "#/components/responses/BadRequest"
     },
     "401": {
      "$ref": "#/components/responses/Unauthorized"
     },
     "403": {
      "$ref": "#/components/responses/Forbidden"
     },
     "429": {
      "$ref": "#/components/responses/RateLimited"
     }
    },
    "security": [
     {
      "apiKey": []
     }
    ],
    "x-required-scope": "events:read",
    "description": "Scope: `events:read`."
   }
  },
  "/event-videos": {
   "get": {
    "summary": "The event video inbox",
    "tags": [
     "Safety"
    ],
    "parameters": [
     {
      "name": "status",
      "in": "query",
      "schema": {
       "type": "string",
       "enum": [
        "new",
        "reviewed",
        "coached",
        "dismissed"
       ]
      }
     },
     {
      "name": "since",
      "in": "query",
      "schema": {
       "type": "string",
       "format": "date-time"
      }
     },
     {
      "name": "limit",
      "in": "query",
      "schema": {
       "type": "integer",
       "minimum": 1,
       "maximum": 200,
       "default": 50
      }
     },
     {
      "name": "cursor",
      "in": "query",
      "schema": {
       "type": "string"
      },
      "description": "next_cursor from the previous page."
     }
    ],
    "responses": {
     "200": {
      "description": "OK",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "required": [
          "data",
          "has_more",
          "next_cursor"
         ],
         "properties": {
          "data": {
           "type": "array",
           "items": {
            "$ref": "#/components/schemas/EventVideo"
           }
          },
          "has_more": {
           "type": "boolean"
          },
          "next_cursor": {
           "type": [
            "string",
            "null"
           ]
          }
         }
        }
       }
      }
     },
     "400": {
      "$ref": "#/components/responses/BadRequest"
     },
     "401": {
      "$ref": "#/components/responses/Unauthorized"
     },
     "403": {
      "$ref": "#/components/responses/Forbidden"
     },
     "429": {
      "$ref": "#/components/responses/RateLimited"
     }
    },
    "security": [
     {
      "apiKey": []
     }
    ],
    "x-required-scope": "events:read",
    "description": "Scope: `events:read`."
   }
  },
  "/scores": {
   "get": {
    "summary": "Driver scores",
    "tags": [
     "Safety"
    ],
    "parameters": [
     {
      "name": "days",
      "in": "query",
      "schema": {
       "type": "integer",
       "enum": [
        7,
        30,
        90
       ],
       "default": 30
      }
     }
    ],
    "responses": {
     "200": {
      "description": "OK",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "required": [
          "data",
          "has_more",
          "next_cursor"
         ],
         "properties": {
          "data": {
           "type": "array",
           "items": {
            "$ref": "#/components/schemas/Score"
           }
          },
          "has_more": {
           "type": "boolean"
          },
          "next_cursor": {
           "type": [
            "string",
            "null"
           ]
          }
         }
        }
       }
      }
     },
     "400": {
      "$ref": "#/components/responses/BadRequest"
     },
     "401": {
      "$ref": "#/components/responses/Unauthorized"
     },
     "403": {
      "$ref": "#/components/responses/Forbidden"
     },
     "429": {
      "$ref": "#/components/responses/RateLimited"
     }
    },
    "security": [
     {
      "apiKey": []
     }
    ],
    "x-required-scope": "scores:read",
    "description": "Scope: `scores:read`."
   }
  },
  "/footage": {
   "get": {
    "summary": "Footage details (no video)",
    "tags": [
     "Footage"
    ],
    "parameters": [
     {
      "name": "since",
      "in": "query",
      "schema": {
       "type": "string",
       "format": "date-time"
      }
     },
     {
      "name": "driver_id",
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "kind",
      "in": "query",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "limit",
      "in": "query",
      "schema": {
       "type": "integer",
       "minimum": 1,
       "maximum": 200,
       "default": 50
      }
     },
     {
      "name": "cursor",
      "in": "query",
      "schema": {
       "type": "string"
      },
      "description": "next_cursor from the previous page."
     }
    ],
    "responses": {
     "200": {
      "description": "OK",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "required": [
          "data",
          "has_more",
          "next_cursor"
         ],
         "properties": {
          "data": {
           "type": "array",
           "items": {
            "$ref": "#/components/schemas/Footage"
           }
          },
          "has_more": {
           "type": "boolean"
          },
          "next_cursor": {
           "type": [
            "string",
            "null"
           ]
          }
         }
        }
       }
      }
     },
     "400": {
      "$ref": "#/components/responses/BadRequest"
     },
     "401": {
      "$ref": "#/components/responses/Unauthorized"
     },
     "403": {
      "$ref": "#/components/responses/Forbidden"
     },
     "429": {
      "$ref": "#/components/responses/RateLimited"
     }
    },
    "security": [
     {
      "apiKey": []
     }
    ],
    "x-required-scope": "footage:read",
    "description": "Scope: `footage:read`."
   }
  },
  "/webhooks": {
   "get": {
    "summary": "List webhook endpoints",
    "tags": [
     "Webhooks"
    ],
    "parameters": [],
    "responses": {
     "200": {
      "description": "OK",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "required": [
          "data",
          "has_more",
          "next_cursor"
         ],
         "properties": {
          "data": {
           "type": "array",
           "items": {
            "$ref": "#/components/schemas/Webhook"
           }
          },
          "has_more": {
           "type": "boolean"
          },
          "next_cursor": {
           "type": [
            "string",
            "null"
           ]
          }
         }
        }
       }
      }
     },
     "400": {
      "$ref": "#/components/responses/BadRequest"
     },
     "401": {
      "$ref": "#/components/responses/Unauthorized"
     },
     "403": {
      "$ref": "#/components/responses/Forbidden"
     },
     "429": {
      "$ref": "#/components/responses/RateLimited"
     }
    },
    "security": [
     {
      "apiKey": []
     }
    ],
    "x-required-scope": "webhooks:manage",
    "description": "Scope: `webhooks:manage`."
   },
   "post": {
    "summary": "Add a webhook endpoint (Zapier subscribe)",
    "tags": [
     "Webhooks"
    ],
    "parameters": [],
    "responses": {
     "201": {
      "description": "Created",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Webhook"
        }
       }
      }
     },
     "400": {
      "$ref": "#/components/responses/BadRequest"
     },
     "401": {
      "$ref": "#/components/responses/Unauthorized"
     },
     "403": {
      "$ref": "#/components/responses/Forbidden"
     },
     "429": {
      "$ref": "#/components/responses/RateLimited"
     }
    },
    "security": [
     {
      "apiKey": []
     }
    ],
    "x-required-scope": "webhooks:manage",
    "description": "A company can have up to 50 endpoints added through the API (10 from the console); over that the answer is 409 too_many_webhooks.\n\nScope: `webhooks:manage`.",
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object",
        "required": [
         "url",
         "events"
        ],
        "properties": {
         "url": {
          "type": "string",
          "format": "uri"
         },
         "events": {
          "type": "array",
          "items": {
           "type": "string",
           "enum": [
            "stop.arrived",
            "stop.completed",
            "stop.skipped",
            "route.dispatched",
            "route.accepted",
            "route.declined",
            "alert.created",
            "crash.detected",
            "police_stop.started",
            "inspection.failed",
            "event_video.ready"
           ]
          }
         },
         "description": {
          "type": "string"
         }
        }
       }
      }
     }
    }
   }
  },
  "/webhooks/{endpoint_id}": {
   "delete": {
    "summary": "Remove a webhook endpoint (Zapier unsubscribe)",
    "tags": [
     "Webhooks"
    ],
    "parameters": [
     {
      "name": "endpoint_id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string",
       "format": "uuid"
      }
     }
    ],
    "responses": {
     "204": {
      "description": "Removed"
     },
     "400": {
      "$ref": "#/components/responses/BadRequest"
     },
     "401": {
      "$ref": "#/components/responses/Unauthorized"
     },
     "403": {
      "$ref": "#/components/responses/Forbidden"
     },
     "429": {
      "$ref": "#/components/responses/RateLimited"
     }
    },
    "security": [
     {
      "apiKey": []
     }
    ],
    "x-required-scope": "webhooks:manage",
    "description": "Scope: `webhooks:manage`."
   }
  },
  "/webhook-events": {
   "get": {
    "summary": "The event types an endpoint can subscribe to",
    "tags": [
     "Webhooks"
    ],
    "parameters": [],
    "responses": {
     "200": {
      "description": "OK",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "400": {
      "$ref": "#/components/responses/BadRequest"
     },
     "401": {
      "$ref": "#/components/responses/Unauthorized"
     },
     "403": {
      "$ref": "#/components/responses/Forbidden"
     },
     "429": {
      "$ref": "#/components/responses/RateLimited"
     }
    },
    "security": []
   }
  },
  "/webhook-events/recent": {
   "get": {
    "summary": "The latest events of one type, in the webhook body's shape (Zapier sample data)",
    "tags": [
     "Webhooks"
    ],
    "parameters": [
     {
      "name": "type",
      "in": "query",
      "required": true,
      "schema": {
       "type": "string",
       "enum": [
        "stop.arrived",
        "stop.completed",
        "stop.skipped",
        "route.dispatched",
        "route.accepted",
        "route.declined",
        "alert.created",
        "crash.detected",
        "police_stop.started",
        "inspection.failed",
        "event_video.ready"
       ]
      }
     },
     {
      "name": "limit",
      "in": "query",
      "schema": {
       "type": "integer",
       "minimum": 1,
       "maximum": 10,
       "default": 3
      }
     }
    ],
    "responses": {
     "200": {
      "description": "OK",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "required": [
          "data",
          "has_more",
          "next_cursor"
         ],
         "properties": {
          "data": {
           "type": "array",
           "items": {
            "$ref": "#/components/schemas/WebhookEvent"
           }
          },
          "has_more": {
           "type": "boolean"
          },
          "next_cursor": {
           "type": "null"
          }
         }
        }
       }
      }
     },
     "400": {
      "$ref": "#/components/responses/BadRequest"
     },
     "401": {
      "$ref": "#/components/responses/Unauthorized"
     },
     "403": {
      "$ref": "#/components/responses/Forbidden"
     },
     "429": {
      "$ref": "#/components/responses/RateLimited"
     }
    },
    "security": [
     {
      "apiKey": []
     }
    ],
    "x-required-scope": "webhooks:manage",
    "description": "Your company's most recent events of `type`, newest first. Each item is exactly the JSON body a webhook delivery of that event posts (the delivered body when one went out), so `id` is the same idempotency key. An empty `data` list when there are none yet.\n\nScope: `webhooks:manage`."
   }
  },
  "/openapi.json": {
   "get": {
    "summary": "This document",
    "tags": [
     "Account"
    ],
    "parameters": [],
    "responses": {
     "200": {
      "description": "OK",
      "content": {
       "application/json": {
        "schema": {
         "type": "object"
        }
       }
      }
     },
     "400": {
      "$ref": "#/components/responses/BadRequest"
     },
     "401": {
      "$ref": "#/components/responses/Unauthorized"
     },
     "403": {
      "$ref": "#/components/responses/Forbidden"
     },
     "429": {
      "$ref": "#/components/responses/RateLimited"
     }
    },
    "security": []
   }
  }
 },
 "webhooks": {
  "stop.arrived": {
   "post": {
    "summary": "A driver arrived at a stop.",
    "tags": [
     "Stops"
    ],
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/WebhookEvent"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "Any 2xx counts as delivered."
     }
    }
   }
  },
  "stop.completed": {
   "post": {
    "summary": "A stop was marked done, with its proof of delivery.",
    "tags": [
     "Stops"
    ],
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/WebhookEvent"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "Any 2xx counts as delivered."
     }
    }
   }
  },
  "stop.skipped": {
   "post": {
    "summary": "A driver skipped a stop, with the reason.",
    "tags": [
     "Stops"
    ],
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/WebhookEvent"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "Any 2xx counts as delivered."
     }
    }
   }
  },
  "route.dispatched": {
   "post": {
    "summary": "A route was sent to its driver.",
    "tags": [
     "Routes"
    ],
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/WebhookEvent"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "Any 2xx counts as delivered."
     }
    }
   }
  },
  "route.accepted": {
   "post": {
    "summary": "The driver accepted a dispatched route.",
    "tags": [
     "Routes"
    ],
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/WebhookEvent"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "Any 2xx counts as delivered."
     }
    }
   }
  },
  "route.declined": {
   "post": {
    "summary": "The driver declined a dispatched route.",
    "tags": [
     "Routes"
    ],
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/WebhookEvent"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "Any 2xx counts as delivered."
     }
    }
   }
  },
  "alert.created": {
   "post": {
    "summary": "A new alert reached the dispatch console.",
    "tags": [
     "Safety"
    ],
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/WebhookEvent"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "Any 2xx counts as delivered."
     }
    }
   }
  },
  "crash.detected": {
   "post": {
    "summary": "The phone detected a crash.",
    "tags": [
     "Safety"
    ],
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/WebhookEvent"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "Any 2xx counts as delivered."
     }
    }
   }
  },
  "police_stop.started": {
   "post": {
    "summary": "A driver started police stop recording.",
    "tags": [
     "Safety"
    ],
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/WebhookEvent"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "Any 2xx counts as delivered."
     }
    }
   }
  },
  "inspection.failed": {
   "post": {
    "summary": "A vehicle inspection had a failed item.",
    "tags": [
     "Safety"
    ],
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/WebhookEvent"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "Any 2xx counts as delivered."
     }
    }
   }
  },
  "event_video.ready": {
   "post": {
    "summary": "A clip of a crash or harsh-driving event finished uploading.",
    "tags": [
     "Safety"
    ],
    "requestBody": {
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/WebhookEvent"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "Any 2xx counts as delivered."
     }
    }
   }
  }
 },
 "components": {
  "securitySchemes": {
   "apiKey": {
    "type": "http",
    "scheme": "bearer",
    "bearerFormat": "dshv_<prefix>_<secret>",
    "description": "Scopes: drivers:read, vehicles:read, routes:read, routes:write, locations:read, alerts:read, events:read, scores:read, footage:read, webhooks:manage"
   }
  },
  "schemas": {
   "Error": {
    "type": "object",
    "properties": {
     "error": {
      "type": "object",
      "required": [
       "code",
       "message"
      ],
      "properties": {
       "code": {
        "type": "string"
       },
       "message": {
        "type": "string"
       }
      }
     }
    }
   },
   "Person": {
    "type": "object",
    "properties": {
     "id": {
      "type": "string",
      "format": "uuid"
     },
     "name": {
      "type": [
       "string",
       "null"
      ]
     }
    }
   },
   "Driver": {
    "type": "object",
    "properties": {
     "id": {
      "type": "string",
      "format": "uuid"
     },
     "name": {
      "type": "string"
     },
     "email": {
      "type": [
       "string",
       "null"
      ]
     },
     "role": {
      "type": "string"
     },
     "also_drives": {
      "type": "boolean"
     },
     "employee_id": {
      "type": [
       "string",
       "null"
      ]
     },
     "phone": {
      "type": [
       "string",
       "null"
      ]
     },
     "team_ids": {
      "type": "array",
      "items": {
       "type": "string"
      }
     },
     "vehicle_id": {
      "type": [
       "string",
       "null"
      ]
     },
     "joined_at": {
      "type": "string",
      "format": "date-time"
     },
     "on_shift": {
      "type": "boolean"
     }
    }
   },
   "Vehicle": {
    "type": "object",
    "properties": {
     "id": {
      "type": "string",
      "format": "uuid"
     },
     "name": {
      "type": "string"
     },
     "make": {
      "type": [
       "string",
       "null"
      ]
     },
     "model": {
      "type": [
       "string",
       "null"
      ]
     },
     "model_year": {
      "type": [
       "integer",
       "null"
      ]
     },
     "vin": {
      "type": [
       "string",
       "null"
      ]
     },
     "fuel_type": {
      "type": [
       "string",
       "null"
      ]
     }
    }
   },
   "Stop": {
    "type": "object",
    "properties": {
     "index": {
      "type": "integer"
     },
     "id": {
      "type": [
       "string",
       "null"
      ]
     },
     "address": {
      "type": "string"
     },
     "kind": {
      "type": "string",
      "enum": [
       "start",
       "waypoint",
       "break",
       "lunch",
       "fuel",
       "charging",
       "office",
       "destination"
      ]
     },
     "lat": {
      "type": [
       "number",
       "null"
      ]
     },
     "lon": {
      "type": [
       "number",
       "null"
      ]
     },
     "dwell_minutes": {
      "type": "integer"
     },
     "window_start": {
      "type": [
       "string",
       "null"
      ]
     },
     "window_end": {
      "type": [
       "string",
       "null"
      ]
     },
     "note": {
      "type": [
       "string",
       "null"
      ]
     },
     "time_zone": {
      "type": [
       "string",
       "null"
      ]
     },
     "status": {
      "type": "string",
      "enum": [
       "remaining",
       "arrived",
       "completed",
       "skipped",
       "missed"
      ]
     },
     "proof_of_delivery": {
      "$ref": "#/components/schemas/ProofOfDelivery"
     }
    }
   },
   "ProofOfDelivery": {
    "type": [
     "object",
     "null"
    ],
    "properties": {
     "id": {
      "type": "string"
     },
     "stop_index": {
      "type": "integer"
     },
     "photo_ids": {
      "type": "array",
      "items": {
       "type": "string"
      }
     },
     "photo_urls": {
      "type": "array",
      "items": {
       "type": "string"
      }
     },
     "signature_id": {
      "type": [
       "string",
       "null"
      ]
     },
     "signature_url": {
      "type": [
       "string",
       "null"
      ]
     },
     "recipient_name": {
      "type": [
       "string",
       "null"
      ]
     },
     "scans": {
      "type": "array",
      "items": {}
     },
     "note": {
      "type": [
       "string",
       "null"
      ]
     },
     "left_at_door": {
      "type": [
       "boolean",
       "null"
      ]
     },
     "lat": {
      "type": [
       "number",
       "null"
      ]
     },
     "lon": {
      "type": [
       "number",
       "null"
      ]
     },
     "captured_at": {
      "type": "string",
      "format": "date-time"
     }
    }
   },
   "Route": {
    "type": "object",
    "properties": {
     "id": {
      "type": "string",
      "format": "uuid"
     },
     "number": {
      "type": [
       "integer",
       "null"
      ]
     },
     "name": {
      "type": "string"
     },
     "status": {
      "type": "string",
      "enum": [
       "draft",
       "dispatched",
       "archived"
      ]
     },
     "revision": {
      "type": "integer"
     },
     "driver_id": {
      "type": [
       "string",
       "null"
      ]
     },
     "team_id": {
      "type": [
       "string",
       "null"
      ]
     },
     "vehicle_id": {
      "type": [
       "string",
       "null"
      ]
     },
     "stop_count": {
      "type": "integer"
     },
     "distance_miles": {
      "type": [
       "number",
       "null"
      ]
     },
     "duration_seconds": {
      "type": [
       "integer",
       "null"
      ]
     },
     "created_at": {
      "type": "string",
      "format": "date-time"
     },
     "updated_at": {
      "type": "string",
      "format": "date-time"
     },
     "stops": {
      "type": "array",
      "items": {
       "$ref": "#/components/schemas/Stop"
      }
     },
     "deliveries": {
      "type": "array",
      "items": {
       "type": "object",
       "properties": {
        "dispatch_id": {
         "type": "string"
        },
        "driver": {
         "$ref": "#/components/schemas/Person"
        },
        "revision": {
         "type": "integer"
        },
        "status": {
         "type": "string"
        },
        "assigned_at": {
         "type": "string"
        },
        "acknowledged_at": {
         "type": [
          "string",
          "null"
         ]
        },
        "completed_at": {
         "type": [
          "string",
          "null"
         ]
        },
        "response_note": {
         "type": [
          "string",
          "null"
         ]
        }
       }
      }
     }
    }
   },
   "NewStop": {
    "type": "object",
    "required": [
     "address"
    ],
    "properties": {
     "address": {
      "type": "string",
      "maxLength": 500
     },
     "lat": {
      "type": "number",
      "description": "With lon. Without them the address is looked up."
     },
     "lon": {
      "type": "number"
     },
     "kind": {
      "type": "string",
      "default": "waypoint"
     },
     "dwell_minutes": {
      "type": "integer",
      "minimum": 0,
      "maximum": 1440
     },
     "window_start": {
      "type": "string",
      "description": "HH:MM in the stop's time zone"
     },
     "window_end": {
      "type": "string"
     },
     "note": {
      "type": "string"
     }
    }
   },
   "NewRoute": {
    "type": "object",
    "required": [
     "name",
     "stops"
    ],
    "properties": {
     "name": {
      "type": "string",
      "maxLength": 120
     },
     "stops": {
      "type": "array",
      "minItems": 1,
      "maxItems": 1000,
      "items": {
       "$ref": "#/components/schemas/NewStop"
      }
     },
     "driver_id": {
      "type": "string",
      "format": "uuid"
     },
     "team_id": {
      "type": "string",
      "format": "uuid"
     },
     "vehicle_id": {
      "type": "string",
      "format": "uuid"
     },
     "optimize": {
      "type": "boolean",
      "default": false,
      "description": "Let the planner reorder the stops."
     },
     "dispatch": {
      "type": "boolean",
      "default": false,
      "description": "Send it to the driver at once."
     }
    }
   },
   "Location": {
    "type": "object",
    "properties": {
     "driver": {
      "$ref": "#/components/schemas/Person"
     },
     "lat": {
      "type": "number"
     },
     "lon": {
      "type": "number"
     },
     "accuracy_m": {
      "type": [
       "number",
       "null"
      ]
     },
     "heading_deg": {
      "type": [
       "number",
       "null"
      ]
     },
     "speed_mps": {
      "type": [
       "number",
       "null"
      ]
     },
     "measured_at": {
      "type": "string",
      "format": "date-time"
     },
     "age_s": {
      "type": "integer"
     },
     "on_shift": {
      "type": "boolean"
     }
    }
   },
   "Alert": {
    "type": "object",
    "properties": {
     "key": {
      "type": "string"
     },
     "severity": {
      "type": "string",
      "enum": [
       "critical",
       "warning",
       "info"
      ]
     },
     "kind": {
      "type": "string"
     },
     "category": {
      "type": "string"
     },
     "title": {
      "type": "string"
     },
     "detail": {
      "type": [
       "string",
       "null"
      ]
     },
     "at": {
      "type": "string",
      "format": "date-time"
     },
     "resolved_at": {
      "type": [
       "string",
       "null"
      ]
     },
     "driver": {
      "$ref": "#/components/schemas/Person"
     }
    }
   },
   "Event": {
    "type": "object",
    "properties": {
     "id": {
      "type": "string",
      "format": "uuid"
     },
     "type": {
      "type": "string",
      "enum": [
       "police_stop",
       "impact",
       "accident",
       "hard_brake",
       "rapid_accel",
       "harsh_turn",
       "speed_trap",
       "hazard",
       "sos",
       "vehicle_problem",
       "road_closed",
       "running_late",
       "delivery_problem",
       "speeding",
       "phone_use"
      ]
     },
     "at": {
      "type": "string",
      "format": "date-time"
     },
     "lat": {
      "type": "number"
     },
     "lon": {
      "type": "number"
     },
     "speed_mps": {
      "type": [
       "number",
       "null"
      ]
     },
     "severity": {
      "type": [
       "string",
       "null"
      ]
     },
     "note": {
      "type": [
       "string",
       "null"
      ]
     },
     "driver": {
      "$ref": "#/components/schemas/Person"
     }
    }
   },
   "EventVideo": {
    "type": "object",
    "properties": {
     "id": {
      "type": "string",
      "format": "uuid"
     },
     "type": {
      "type": "string"
     },
     "title": {
      "type": "string"
     },
     "at": {
      "type": "string",
      "format": "date-time"
     },
     "lat": {
      "type": [
       "number",
       "null"
      ]
     },
     "lon": {
      "type": [
       "number",
       "null"
      ]
     },
     "speed_mps": {
      "type": [
       "number",
       "null"
      ]
     },
     "driver": {
      "$ref": "#/components/schemas/Person"
     },
     "clip": {
      "type": [
       "object",
       "null"
      ],
      "properties": {
       "id": {
        "type": "string"
       },
       "ready_at": {
        "type": "string"
       },
       "duration_s": {
        "type": [
         "number",
         "null"
        ]
       }
      }
     },
     "status": {
      "type": "string",
      "enum": [
       "new",
       "reviewed",
       "coached",
       "dismissed"
      ]
     },
     "reviewed_at": {
      "type": [
       "string",
       "null"
      ]
     },
     "coached": {
      "type": "boolean"
     }
    }
   },
   "Score": {
    "type": "object",
    "properties": {
     "driver": {
      "$ref": "#/components/schemas/Person"
     },
     "days": {
      "type": "integer"
     },
     "score": {
      "type": [
       "integer",
       "null"
      ]
     },
     "grade": {
      "type": [
       "string",
       "null"
      ]
     },
     "trips": {
      "type": "integer"
     },
     "distance_mi": {
      "type": "number"
     },
     "factors": {
      "type": [
       "object",
       "array",
       "null"
      ]
     }
    }
   },
   "Footage": {
    "type": "object",
    "properties": {
     "id": {
      "type": "string",
      "format": "uuid"
     },
     "kind": {
      "type": "string"
     },
     "captured_at": {
      "type": "string",
      "format": "date-time"
     },
     "duration_s": {
      "type": [
       "number",
       "null"
      ]
     },
     "bytes": {
      "type": "integer"
     },
     "camera": {
      "type": [
       "string",
       "null"
      ]
     },
     "kept": {
      "type": "boolean"
     },
     "locked": {
      "type": "boolean"
     },
     "legal_hold": {
      "type": "boolean"
     },
     "driver": {
      "$ref": "#/components/schemas/Person"
     },
     "console_url": {
      "type": "string"
     }
    }
   },
   "Webhook": {
    "type": "object",
    "properties": {
     "id": {
      "type": "string",
      "format": "uuid"
     },
     "url": {
      "type": "string"
     },
     "description": {
      "type": "string"
     },
     "events": {
      "type": "array",
      "items": {
       "type": "string",
       "enum": [
        "stop.arrived",
        "stop.completed",
        "stop.skipped",
        "route.dispatched",
        "route.accepted",
        "route.declined",
        "alert.created",
        "crash.detected",
        "police_stop.started",
        "inspection.failed",
        "event_video.ready"
       ]
      }
     },
     "enabled": {
      "type": "boolean"
     },
     "created_at": {
      "type": "string"
     },
     "secret": {
      "type": "string",
      "description": "Only in the answer that created it."
     }
    }
   },
   "WebhookEvent": {
    "type": "object",
    "required": [
     "id",
     "type",
     "created_at",
     "api_version",
     "organization_id",
     "data"
    ],
    "description": "What we POST to your endpoint. Check Dashivo-Signature first: t=<unix seconds>,v1=<hex HMAC-SHA256(secret, \"<t>.<raw body>\")>.",
    "properties": {
     "id": {
      "type": "string",
      "format": "uuid",
      "description": "The event id: the same for every retry and every endpoint; use it to ignore repeats."
     },
     "type": {
      "type": "string",
      "enum": [
       "stop.arrived",
       "stop.completed",
       "stop.skipped",
       "route.dispatched",
       "route.accepted",
       "route.declined",
       "alert.created",
       "crash.detected",
       "police_stop.started",
       "inspection.failed",
       "event_video.ready",
       "ping"
      ]
     },
     "created_at": {
      "type": "string",
      "format": "date-time",
      "description": "When the event happened (was noted)."
     },
     "api_version": {
      "type": "string"
     },
     "organization_id": {
      "type": "string",
      "format": "uuid"
     },
     "data": {
      "type": "object"
     }
    }
   }
  },
  "responses": {
   "BadRequest": {
    "description": "The request wasn't valid.",
    "content": {
     "application/json": {
      "schema": {
       "$ref": "#/components/schemas/Error"
      }
     }
    }
   },
   "Unauthorized": {
    "description": "No key, a wrong key, or a revoked, expired or stopped one.",
    "content": {
     "application/json": {
      "schema": {
       "$ref": "#/components/schemas/Error"
      }
     }
    }
   },
   "Forbidden": {
    "description": "The key lacks the scope, or the company is unavailable.",
    "content": {
     "application/json": {
      "schema": {
       "$ref": "#/components/schemas/Error"
      }
     }
    }
   },
   "RateLimited": {
    "description": "Too many requests: wait Retry-After seconds.",
    "content": {
     "application/json": {
      "schema": {
       "$ref": "#/components/schemas/Error"
      }
     }
    }
   }
  }
 }
}
