{
  "openapi": "3.0.3",
  "servers": [
    {
      "url": "https://api.smartroutes.io/v2/"
    }
  ],
  "info": {
    "title": "SmartRoutes Open API",
    "description": "</br>\n<h2 style=\"color:rgb(51, 51, 51)\">Introduction</h2>\n<p>The SmartRoutes Open API allows you to use the power of the SmartRoutes Routing Engine directly from within your own software application.</p>\n<p>To use the API, you will need to generate an API Access Key for your SmartRoutes account. To generate, login to your SmartRoutes account and navigate to Settings > Integrations > SmartRoutes Open API and click 'Generate API Key'. For more details on SmartRoutes integrations, click <a href='https://smartroutes.io/blogs/guides/integrations/'>here</a>.</p>\n<p>This access key can be used to connect to the API.</p>\n<h2 id=\"webhooks\" style=\"color:rgb(51, 51, 51)\">Webhooks</h2>\n<p>Configure a webhook receiver URL in your depot settings and SmartRoutes will deliver event notifications as they happen. Eight event types are emitted:</p>\n<table><thead><tr><th>Event</th><th>Type ID</th><th>Fires when</th><th><code>data</code> payload</th></tr></thead><tbody>\n<tr><td><code>orders.status</code></td><td>2</td><td>An order's status changes (line-item or order-level transition)</td><td><code>{ \"order_id\": &lt;int&gt;, \"order_number\": &lt;string&gt;, \"status\": &lt;OrderStatus&gt; }</code></td></tr>\n<tr><td><code>plans.created</code></td><td>4</td><td>A Plan row is persisted (after <code>POST /plans/optimise/orders</code> or <code>/orders-for-ids</code>). Fires <i>before</i> optimisation completes — see the optimise endpoint description.</td><td><code>{ \"id\": &lt;int&gt; }</code> — plan id</td></tr>\n<tr><td><code>plans.dispatched</code></td><td>5</td><td>A Plan is dispatched (routes published to drivers).</td><td><code>{ \"id\": &lt;int&gt; }</code> — plan id</td></tr>\n<tr><td><code>routes.edited</code></td><td>6</td><td>A dispatched route is edited (re-ordering stops, etc.)</td><td><code>{ \"id\": &lt;int&gt; }</code> — route id</td></tr>\n<tr><td><code>routes.deleted</code></td><td>7</td><td>One or more dispatched routes are deleted (typically as part of solution replacement)</td><td><code>{ \"id\": &lt;int&gt; }</code> — route id</td></tr>\n<tr><td><code>routes.completed</code></td><td>8</td><td>A dispatched route is completed by the driver.</td><td><code>{ \"id\": &lt;int&gt; }</code> — route id</td></tr>\n<tr><td><code>plans.deleted</code></td><td>9</td><td>A Plan row is destroyed</td><td><code>{ \"id\": &lt;int&gt; }</code> — plan id</td></tr>\n<tr><td><code>orders.on_delivery</code></td><td>10</td><td>A stop enters its on-delivery ETA window on a dispatched route (the arriving-soon signal). Rides on the depot's on-delivery customer notifications — fires once per stop, and only for stops that carry contact details.</td><td><code>{ \"order_id\": &lt;int&gt;, \"order_number\": &lt;string&gt;, \"route_id\": &lt;int&gt;, \"eta\": &lt;string&gt;, \"time_to_arrival\": &lt;int&gt; }</code></td></tr>\n</tbody></table>\n<h3>Delivery envelope</h3>\n<p>Each event is delivered as an <code>HTTP POST</code> to the receiver URL configured in your depot settings. The request body is always a JSON object of shape:</p>\n<pre>{ \"type\": &lt;event type string from the table above&gt;, \"data\": &lt;payload object from the table above&gt; }</pre>\n<p>The <code>data</code> field is the payload object for a single event — NOT an array. Bulk operations (e.g. order-status changes from a route delete) fan out into one POST per event, each with its own <code>data</code> object.</p>\n<h3>Headers</h3>\n<p>Outgoing requests carry <code>Content-Type: application/json</code> and an HTTP Basic <code>Authorization</code> header derived from the username/password you supplied when configuring the webhook. No HMAC signature header is sent; treat the basic-auth credentials as the integrity check and rotate them if compromised.</p>\n<h3>Timeout and retries</h3>\n<p>Each delivery has a server-side request timeout of <b>3 seconds</b>. On failure (HTTP error, timeout, or connection error) the delivery is retried up to <b>3 times total</b>; after the third failure the task is marked permanently <code>ERROR</code> and not retried again. Your receiver should respond <code>2xx</code> quickly — slow receivers will be treated as failures.</p>\n<h3>Machine-readable schemas</h3>\n<p>The delivery envelope and per-event payloads are also defined under <code>#/components/schemas/</code>: <code>WebhookDelivery</code>, <code>WebhookOrdersStatusPayload</code>, <code>WebhookPlanIdPayload</code>, <code>WebhookRouteIdPayload</code>, <code>WebhookOnDeliveryPayload</code>. Reference these from your own integration's tests / contract tools to catch shape drift early.</p>\n<h2 style=\"color:rgb(51, 51, 51)\">Headers</h2>\n<p>All requests expect the API Access key to be provided in a header <code>x-access-key:YOUR_ACCESS_KEY</code> </p>\n<h2 id=\"rate-limits\" style=\"color:rgb(51, 51, 51)\">Rate Limits</h2>\n<p>Every endpoint has a per-minute limit, and most also have a short burst limit. Requests are rejected as soon as either limit is hit.</p>\n<p>Most endpoints fall into one of these tiers:</p>\n<table><thead><tr><th>Tier</th><th>Rate limit</th><th>Description</th></tr></thead><tbody>\n<tr><td>Standard</td><td>60 / min (max 5 / sec)</td><td>Single-resource reads and writes (e.g. <code>GET /orders/{id}</code>, <code>PUT /orders/{id}</code>)</td></tr>\n<tr><td>Listing</td><td>30 / min (max 5 / sec)</td><td>Paginated lists (e.g. <code>/customers</code>, <code>/plans</code>, <code>/routes</code>)</td></tr>\n<tr><td>Reference</td><td>60 / min (max 1 / sec)</td><td>Reference data (e.g. depots, capacities, custom fields, vehicles, zone groups)</td></tr>\n<tr><td>Bulk</td><td>30 / min (max 1 per 2 sec)</td><td>Bulk creates and heavy deletes</td></tr>\n<tr><td>Upload</td><td>15 / min (max 1 / sec)</td><td>File uploads (e.g. <code>POST /orders/{id}/attachments</code>)</td></tr>\n</tbody></table>\n<p>The following endpoints have a stricter limit of <b>5 / min (max 2 per 15 sec)</b>:</p>\n<ul>\n<li>Plan optimisation: <code>POST /plans/optimise/orders</code>, <code>POST /plans/optimise/orders-for-ids</code></li>\n<li>Booking availability: <code>POST /booking/availability</code>, <code>POST /booking/available-dates</code>, <code>POST /booking/available-slots</code></li>\n<li>Route reversal: <code>POST /routes/{id}/reverse</code></li>\n</ul>\n<p>When a limit is hit, the API returns HTTP <b>403</b> with a <code>Retry-After</code> header and <code>details.retry_after_seconds</code> in the body — both give the seconds until the limit resets.</p>\n<p>We may temporarily reduce these limits to protect platform stability. We aim to keep such reductions brief and rare. However, your application should be built to handle rate limits gracefully.</p>\n<h2 id=\"idempotency\" style=\"color:rgb(51, 51, 51)\">Idempotency</h2>\n<p>State-changing <code>POST</code> endpoints accept an optional <code>idempotency-key</code> request header. The mechanism is Stripe-style: send the same key with a retry of the same request and the server returns the original response without re-executing the underlying operation.</p>\n<p><b>Header:</b> <code>idempotency-key: &lt;opaque string, 1–255 characters&gt;</code>. The key can be any client-chosen identifier — a UUID is recommended. Keys are scoped per <i>(api-key, endpoint)</i>, so the same key on two different endpoints is treated as two distinct operations.</p>\n<p><b>Retention:</b> 24 hours from the time the original request was received.</p>\n<p><b>Behaviour:</b></p>\n<ul>\n<li><b>Replay (same key, same body, completed)</b> — server returns the original status code and response body. The response header <code>idempotency-replay: true</code> indicates the response is a cached replay. The underlying operation is <i>not</i> re-executed. Replays do not consume rate-limit or data-row quota.</li>\n<li><b>Body mismatch (same key, different body)</b> — server returns <code>422 IDEMPOTENCY_KEY_REUSED_WITH_DIFFERENT_BODY</code>.</li>\n<li><b>In-flight (same key, original request still processing)</b> — server returns <code>409 IDEMPOTENCY_REQUEST_IN_PROGRESS</code> with a <code>Retry-After</code> header. Retry after the period given.</li>\n<li><b>5xx server error</b> — the cached reservation is released. A retry with the same key is treated as a fresh request and can re-execute. <i>4xx client errors</i> are cached: replays return the same 4xx response.</li>\n<li><b>Invalid key</b> (empty, or longer than 255 chars) — server returns <code>400 IDEMPOTENCY_INVALID_KEY</code>.</li>\n</ul>\n<p><b>Supporting endpoints (Phase 1):</b></p>\n<ul>\n<li><code>POST /orders</code></li>\n<li><code>POST /depots/{id}/orders</code></li>\n<li><code>POST /plans/optimise/orders</code></li>\n<li><code>POST /plans/optimise/orders-for-ids</code></li>\n<li><code>POST /customers/</code></li>\n<li><code>POST /vehicles/</code></li>\n<li><code>POST /notifications/schedule/orders</code></li>\n</ul>\n<p>Other <code>POST</code> endpoints ignore the header. Multipart uploads (<code>POST /orders/{id}/attachments</code>) are excluded from idempotency in this phase.</p>\n<h2 style=\"color:rgb(51, 51, 51)\">Paging</h2>\n<h3> Usage:</h3>\n<p>\nMake an initial request to the API endpoint with the desired query parameters.\nThe API response includes the requested data and a Link header for the next page.\nUse the URL provided in the Link header to make subsequent requests for the next page.\n\nExample: <code>\"&#60;https://api.smartroutes.io/v2/orders?page_info=PAGE_INFO_STRING&limit=100&gt;; rel=next\"</code>\n</p>\n<h3>Query Parameters</h3>\n<p>\n<b>limit:</b> Specifies the maximum number of items per page. Limited to a maximum of 100\n\n<u>Example:</u> limit=50\n\n<b>updated_at_min:</b> Filters results based on the minimum update timestamp in the format YYYY-MM-DD hh:mm:ss or YYYY-MM-DDTHH:mm:ss.SSSZ.\n\n<u>Example:</u> updated_at_min=2023-01-01 12:00:00 OR updated_at_min=2023-01-01T12:00:00.000Z\n\n<b>status:</b> Filters results based on the order status.\n\n<u>Example:</u> status=Pending\n</p><h2>Error Responses</h2>\n<p>\n    Errors are classified into specific types, each identified by a unique <b>name</b> and accompanied by an appropriate HTTP <b>statusCode</b>. \n    The error responses include a brief description of the error, and additional <b>details</b> that provide more context about the specific issue.\n</p>\n<h3>Error Types</h3>\n<b>RESOURCE_NOT_FOUND</b>\n- statusCode: 404\n- description: The requested resource could not be found.\n\n<b>INVALID_INPUT</b>\n\n- statusCode: 400\n- description: The submitted input data is invalid.\n- details: An object <code>{ validationErrors: An array of Zod errors specifying validation issues in the submitted data. }</code> containing additional details about the error. For processing validation errors, refer to <a href=\"https://v3.zod.dev/?id=error-handling\">Zod Documentation </a></b>.\n\n<b>GEOCODING_FAILED</b>\n\n- statusCode: 500\n- description: Geocoding operation failed.\n- details: An object containing additional details about the error.",
    "version": "2.0.0",
    "contact": {
      "name": "SmartRoutes Support",
      "email": "support@smartroutes.io",
      "url": "https://smartroutes.io/support"
    }
  },
  "tags": [
    { "name": "Booking" },
    { "name": "Capacities" },
    { "name": "Custom Fields" },
    { "name": "Customers" },
    { "name": "Depots" },
    { "name": "Driver Questionnaires" },
    { "name": "Notification Tasks" },
    { "name": "Notifications" },
    { "name": "Orders" },
    { "name": "Plans" },
    { "name": "Proof of Delivery" },
    { "name": "Routes" },
    { "name": "Third Parties" },
    { "name": "Vehicles" },
    { "name": "Zone Groups" }
  ],
  "paths": {
    "/booking/availability": {
      "post": {
        "summary": "Check Booking Availability",
        "operationId": "checkBookingAvailabilityForOrder",
        "description": "Endpoint to check whether an order can be booked on a specified day",
        "tags": [
          "Booking"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "date": {
                    "type": "string",
                    "format": "date",
                    "description": "Requested date for order collection/delivery."
                  },
                  "order": {
                    "type": "object",
                    "properties": {
                      "type": {
                        "type": "string",
                        "enum": [
                          "delivery",
                          "pickup"
                        ]
                      },
                      "delivery_address": {
                        "type": "string"
                      },
                      "delivery_country_code": {
                        "type": "string",
                        "description": "Two letter country code, e.g. 'IE'"
                      },
                      "delivery_postcode": {
                        "type": "string"
                      },
                      "delivery_lat": {
                        "type": "number"
                      },
                      "delivery_lng": {
                        "type": "number"
                      },
                      "delivery_duration": {
                        "type": "number"
                      },
                      "pickup_address": {
                        "type": "string"
                      },
                      "pickup_country_code": {
                        "type": "string",
                        "description": "Two letter country code, e.g. 'IE'"
                      },
                      "pickup_postcode": {
                        "type": "string"
                      },
                      "pickup_duration": {
                        "type": "number"
                      },
                      "pickup_lat": {
                        "type": "number"
                      },
                      "pickup_lng": {
                        "type": "number"
                      },
                      "capacities": {
                        "type": "array",
                        "items": {
                          "type": "object",
                          "properties": {
                            "id": {
                              "type": "integer",
                              "description": "Id of capacity (e.g., 1, 2)."
                            },
                            "capacity": {
                              "type": "number",
                              "format": "float",
                              "description": "Capacity value for the specified type."
                            }
                          },
                          "required": [
                            "id",
                            "capacity"
                          ],
                          "description": "List of capacities with their types and values."
                        },
                        "description": "List of capacities for the order."
                      }
                    },
                    "required": [
                      "type"
                    ],
                    "description": "Location and other routing information for booking availability check."
                  },
                  "vehicles": {
                    "type": "array",
                    "format": "object",
                    "description": "Array of vehicles to attempt to route the order with. If no vehicles provided, active vehicles will be used."
                  }
                },
                "required": [
                  "date",
                  "order"
                ],
                "description": "Request body for checking availability for bookings."
              },
              "example": [
                {
                  "date": "2025-01-01",
                  "order": {
                    "type": "delivery",
                    "delivery_address": "5 Main Street, London, UK",
                    "delivery_postcode": "HS2 3DE4",
                    "delivery_country_code": "IE",
                    "delivery_duration": 30,
                    "capacities": [
                      {
                        "id": 1,
                        "capacity": 100
                      }
                    ]
                  },
                  "vehicles": [
                    {
                      "id": 123
                    },
                    {
                      "id": 456
                    },
                    {
                      "id": 789
                    }
                  ]
                }
              ]
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/BookingAvailabilityResponse" },
                "example": {
                  "booking": {
                    "available": true
                  }
                }
              }
            }
          },
          "400": { "$ref": "#/components/responses/InvalidInput" },
          "403": { "$ref": "#/components/responses/Forbidden" },
          "500": { "$ref": "#/components/responses/ServerError" }
        }
      }
    },
    "/custom-fields": {
      "get": {
        "summary": "Get All Custom Fields",
        "operationId": "listCustomFields",
        "description": "Endpoint to retrieve all custom fields.",
        "tags": [
          "Custom Fields"
        ],
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "example": {
                  "custom_fields": [
                    {
                      "id": 123,
                      "name": "Custom Field Name",
                      "created": "2022-04-29T16:12:08.000Z",
                      "updated": "2022-09-29T10:11:06.000Z"
                    }
                  ]
                }
              }
            }
          },
          "400": { "$ref": "#/components/responses/InvalidInput" },
          "403": { "$ref": "#/components/responses/Forbidden" },
          "500": { "$ref": "#/components/responses/ServerError" }
        }
      }
    },
    "/capacities": {
      "get": {
        "summary": "Get All Capacities",
        "operationId": "listCapacities",
        "description": "Endpoint to retrieve all capacities.",
        "tags": [
          "Capacities"
        ],
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "example": {
                  "capacities": [
                    {
                      "id": 123,
                      "type": "Palettes",
                      "default": "20",
                      "created": "2022-04-29T16:12:08.000Z",
                      "updated": "2022-09-29T10:11:06.000Z"
                    }
                  ]
                }
              }
            }
          },
          "400": { "$ref": "#/components/responses/InvalidInput" },
          "403": { "$ref": "#/components/responses/Forbidden" },
          "500": { "$ref": "#/components/responses/ServerError" }
        }
      }
    },
    "/customers": {
      "get": {
        "summary": "Get Customers Page",
        "operationId": "listCustomers",
        "description": "Endpoint to retrieve a page of customers.",
        "tags": [
          "Customers"
        ],
        "parameters": [
          {
            "in": "query",
            "name": "page_info",
            "required": false,
            "schema": {
              "type": "string",
              "description": "Information about the page for pagination. Generated by the OpenAPI"
            },
            "description": "Information about the page for pagination. Generated by the OpenAPI"
          },
          {
            "in": "query",
            "name": "updated_at_min",
            "required": false,
            "schema": {
              "type": "string",
              "format": "date-time",
              "description": "Minimum updated date and time for filtering."
            },
            "description": "Minimum updated date and time for filtering."
          },
          {
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "type": "integer",
              "default": 100,
              "description": "Maximum number of customers to retrieve per page."
            },
            "description": "Maximum number of customers to retrieve per page."
          }
        ],
        "responses": {
          "200": {
            "description": "Successful response",
            "headers": {
              "link": {
                "description": "Link to the next page of customers. Use with the page_info parameter for pagination.",
                "schema": {
                  "type": "string"
                },
                "example": "<https://api.smartroutes.io/v2/customers?page_info=PAGE_INFO_STRING&limit=100>; rel=next"
              }
            },
            "content": {
              "application/json": {
                "example": {
                  "customers": [
                    {
                      "id": 123,
                      "name": "John Doe",
                      "account": "NO123",
                      "address": "123 Main St 12345",
                      "email": "john@doe.com",
                      "postcode": "12345",
                      "lat": 12.345,
                      "lng": -67.890,
                      "phone": "+1234567890",
                      "duration": 30,
                      "notes": "Leave at the doorstep",
                      "created": "2022-04-29T16:12:08.000Z",
                      "updated": "2022-09-29T10:11:06.000Z"
                    }
                  ]
                }
              }
            }
          },
          "400": { "$ref": "#/components/responses/InvalidInput" },
          "403": { "$ref": "#/components/responses/Forbidden" },
          "500": { "$ref": "#/components/responses/ServerError" }
        }
      },
      "post": {
        "summary": "Bulk Create Customers",
        "operationId": "createCustomers",
        "description": "Creates multiple customers in a single request (max 100). All referenced `tags`, `skills`, and `capacities` must already exist. `custom_fields` can be matched by `id` or `name`.",
        "tags": [
          "Customers"
        ],
        "parameters": [
          { "$ref": "#/components/parameters/IdempotencyKeyHeader" }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "array",
                "maxItems": 100,
                "items": {
                  "type": "object",
                  "required": [
                    "account"
                  ],
                  "properties": {
                    "name": {
                      "type": "string",
                      "maxLength": 100,
                      "description": "Full name of the customer"
                    },
                    "account": {
                      "type": "string",
                      "maxLength": 100,
                      "description": "Unique account reference (required)"
                    },
                    "address": {
                      "type": "string",
                      "maxLength": 255
                    },
                    "postcode": {
                      "type": "string",
                      "maxLength": 20
                    },
                    "phone": {
                      "type": "string",
                      "maxLength": 30
                    },
                    "email": {
                      "type": "string",
                      "format": "email"
                    },
                    "lat": {
                      "type": "number",
                      "description": "Latitude coordinate"
                    },
                    "lng": {
                      "type": "number",
                      "description": "Longitude coordinate"
                    },
                    "duration": {
                      "type": "number",
                      "minimum": 1,
                      "maximum": 9999,
                      "description": "Visit duration in minutes"
                    },
                    "notes": {
                      "type": "string",
                      "maxLength": 40000
                    },
                    "capacities": {
                      "type": "array",
                      "description": "List of predefined capacity types by ID",
                      "items": {
                        "type": "object",
                        "required": [
                          "id",
                          "capacity"
                        ],
                        "properties": {
                          "id": {
                            "type": "integer"
                          },
                          "capacity": {
                            "type": "number"
                          }
                        }
                      }
                    },
                    "skills": {
                      "type": "array",
                      "description": "List of skill names (must already exist)",
                      "items": {
                        "type": "string"
                      }
                    },
                    "tags": {
                      "type": "array",
                      "description": "List of tag names (must already exist)",
                      "items": {
                        "type": "string"
                      }
                    },
                    "time_windows": {
                      "type": "array",
                      "maxItems": 2,
                      "description": "Up to two delivery/pickup time windows per customer",
                      "items": {
                        "type": "object",
                        "required": [
                          "from"
                        ],
                        "properties": {
                          "from": {
                            "type": "string",
                            "pattern": "^([01]\\d|2[0-3]):([0-5]\\d)$",
                            "description": "Start time in 24-hour HH:mm format"
                          },
                          "to": {
                            "type": "string",
                            "pattern": "^([01]\\d|2[0-3]):([0-5]\\d)$",
                            "description": "End time in 24-hour HH:mm format"
                          }
                        }
                      }
                    },
                    "custom_fields": {
                      "type": "array",
                      "description": "Custom field values. Use `id` or `name` to identify each custom field.",
                      "items": {
                        "type": "object",
                        "required": [
                          "value"
                        ],
                        "properties": {
                          "id": {
                            "type": "integer"
                          },
                          "name": {
                            "type": "string"
                          },
                          "value": {
                            "type": "string"
                          }
                        }
                      }
                    }
                  },
                  "additionalProperties": false
                }
              },
              "example": [
                {
                  "name": "John Doe",
                  "account": "12345678",
                  "address": "Cork, Ireland",
                  "phone": "+353877777777",
                  "email": "john@doe.com",
                  "lat": 51.8985,
                  "lng": -8.4756,
                  "notes": "Customer notes",
                  "duration": 10,
                  "tags": [
                    "Spring Route",
                    "Priority"
                  ],
                  "skills": [
                    "Manual Handling"
                  ],
                  "capacities": [
                    {
                      "id": 145,
                      "capacity": 12
                    }
                  ],
                  "time_windows": [
                    {
                      "from": "10:00",
                      "to": "19:30"
                    }
                  ],
                  "custom_fields": [
                    {
                      "name": "Colour",
                      "value": "Red"
                    },
                    {
                      "id": 261,
                      "value": "10"
                    }
                  ]
                }
              ]
            }
          }
        },
        "responses": {
          "201": {
            "description": "Customers created successfully",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "customers": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "integer"
                          },
                          "account": {
                            "type": "string"
                          }
                        }
                      }
                    },
                    "errors": {
                      "type": "array",
                      "description": "List of customers that failed validation"
                    }
                  }
                },
                "example": {
                  "customers": [
                    {
                      "id": 381321,
                      "account": "12345678"
                    },
                    {
                      "id": 381322,
                      "account": "12345678"
                    }
                  ],
                  "errors": []
                }
              }
            },
            "headers": {
              "idempotency-replay": { "$ref": "#/components/headers/IdempotencyReplay" }
            }
          },
          "400": { "$ref": "#/components/responses/InvalidInput" },
          "404": { "$ref": "#/components/responses/NotFound" },
          "409": { "$ref": "#/components/responses/IdempotencyRequestInProgress" },
          "422": { "$ref": "#/components/responses/IdempotencyKeyReusedWithDifferentBody" },
          "403": { "$ref": "#/components/responses/Forbidden" },
          "500": { "$ref": "#/components/responses/ServerError" }
        }
      }
    },
    "/customers/{id}": {
      "get": {
        "summary": "Get Customer by ID",
        "operationId": "getCustomerById",
        "description": "Retrieve a customer based on ID.",
        "tags": [
          "Customers"
        ],
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "ID of the customer to retrieve."
          }
        ],
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "example": {
                  "id": 123,
                  "name": "John Doe",
                  "account": "NO123",
                  "address": "123 Main St 12345",
                  "postcode": "12345",
                  "lat": 12.345,
                  "lng": -67.890,
                  "phone": "+1234567890",
                  "email": "john@doe.com",
                  "duration": 30,
                  "notes": "Leave at the doorstep",
                  "created": "2022-04-29T16:12:08.000Z",
                  "updated": "2022-09-29T10:11:06.000Z",
                  "capacities": [
                    {
                      "id": 201,
                      "type": "WEIGHT",
                      "capacity": 500
                    },
                    {
                      "id": 202,
                      "type": "VOLUME",
                      "capacity": 1000
                    }
                  ],
                  "time_windows": [
                    {
                      "from": "08:00",
                      "to": "12:00"
                    },
                    {
                      "from": "14:00",
                      "to": "18:00"
                    }
                  ],
                  "skills": [
                    "Skill A",
                    "Skill B"
                  ],
                  "tags": [
                    "Tag A",
                    "Tag B"
                  ],
                  "custom_fields": [
                    {
                      "value": "My Value",
                      "custom_field_type": {
                        "name": "My Custom Field",
                        "type": "TEXT",
                        "id": 123
                      }
                    }
                  ]
                }
              }
            }
          },
          "400": { "$ref": "#/components/responses/InvalidInput" },
          "404": { "$ref": "#/components/responses/NotFound" },
          "403": { "$ref": "#/components/responses/Forbidden" },
          "500": { "$ref": "#/components/responses/ServerError" }
        }
      },
      "put": {
        "summary": "Update Customer by ID",
        "operationId": "updateCustomerById",
        "description": "Update a customer based on ID.",
        "tags": [
          "Customers"
        ],
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "ID of the customer to update."
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "description": "Name of the customer."
                  },
                  "account": {
                    "type": "string",
                    "description": "Account number of the customer."
                  },
                  "address": {
                    "type": "string",
                    "description": "Address of the customer."
                  },
                  "postcode": {
                    "type": "string",
                    "description": "Postcode for the customer address."
                  },
                  "lat": {
                    "type": "number",
                    "description": "Latitude of the customer location."
                  },
                  "lng": {
                    "type": "number",
                    "description": "Longitude of the customer location."
                  },
                  "phone": {
                    "type": "string",
                    "description": "Contact number of the customer."
                  },
                  "email": {
                    "type": "string",
                    "format": "email",
                    "description": "Email of the customer."
                  },
                  "duration": {
                    "type": "number",
                    "description": "Duration for customer interaction in minutes."
                  },
                  "notes": {
                    "type": "string",
                    "description": "Notes for customer interaction."
                  },
                  "time_windows": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "from": {
                          "type": "string",
                          "format": "time",
                          "description": "Start time of the time window."
                        },
                        "to": {
                          "type": "string",
                          "format": "time",
                          "description": "End time of the time window."
                        }
                      },
                      "required": [
                        "from",
                        "to"
                      ],
                      "description": "Time windows for the customer."
                    },
                    "description": "List of time windows for the customer."
                  },
                  "skills": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "description": "List of required skills for the customer."
                    },
                    "description": "List of required skills for the customer."
                  },
                  "tags": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "description": "List of tags for the customer"
                    },
                    "description": "List of tags for the customer"
                  },
                  "capacities": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "integer",
                          "description": "Id of capacity (e.g., 1, 2)."
                        },
                        "capacity": {
                          "type": "number",
                          "format": "float",
                          "description": "Capacity value for the specified type."
                        }
                      },
                      "required": [
                        "id",
                        "capacity"
                      ],
                      "description": "List of capacities with their types and values."
                    },
                    "description": "List of capacities for the customer."
                  },
                  "custom_fields": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "integer",
                          "description": "Id of custom field (e.g., 1, 2)."
                        },
                        "value": {
                          "type": "string",
                          "description": "New custom field value"
                        }
                      }
                    },
                    "description": "List custom fields for the customer"
                  }
                },
                "description": "Details of the customer to be updated."
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "example": {
                  "id": 123,
                  "name": "John Doe",
                  "account": "NO123",
                  "address": "123 Main St 12345",
                  "postcode": "12345",
                  "lat": 12.345,
                  "lng": -67.890,
                  "phone": "+1234567890",
                  "email": "john@doe.com",
                  "duration": 30,
                  "notes": "Leave at the doorstep",
                  "capacities": [
                    {
                      "id": 201,
                      "type": "WEIGHT",
                      "capacity": 500
                    },
                    {
                      "id": 202,
                      "type": "VOLUME",
                      "capacity": 1000
                    }
                  ],
                  "time_windows": [
                    {
                      "from": "08:00",
                      "to": "12:00"
                    },
                    {
                      "from": "14:00",
                      "to": "18:00"
                    }
                  ],
                  "skills": [
                    "Skill A",
                    "Skill B"
                  ],
                  "tags": [
                    "Tag A",
                    "Tag B"
                  ],
                  "custom_fields": [
                    {
                      "id": 123,
                      "value": "My Value",
                      "name": "My Custom Field"
                    }
                  ]
                }
              }
            }
          },
          "400": { "$ref": "#/components/responses/InvalidInput" },
          "404": { "$ref": "#/components/responses/NotFound" },
          "403": { "$ref": "#/components/responses/Forbidden" },
          "500": { "$ref": "#/components/responses/ServerError" }
        }
      }
    },
    "/depots": {
      "get": {
        "summary": "Get All Depots",
        "operationId": "listDepots",
        "description": "Endpoint to retrieve a list of all depots.",
        "tags": [
          "Depots"
        ],
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "example": {
                  "depots": [
                    {
                      "id": 123,
                      "name": "Depot 1",
                      "created": "2021-04-12T15:30:46.000Z",
                      "updated": "2024-06-24T08:38:20.000Z"
                    }
                  ]
                }
              }
            }
          },
          "403": { "$ref": "#/components/responses/Forbidden" },
          "500": { "$ref": "#/components/responses/ServerError" }
        }
      }
    },
    "/depots/{id}/orders": {
      "post": {
        "summary": "Bulk Add Orders to Depot",
        "operationId": "createOrdersForDepot",
        "description": "Endpoint to bulk add orders to a depot.",
        "tags": [
          "Depots"
        ],
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "number"
            },
            "description": "ID of the depot to which bulk orders are added."
          },
          { "$ref": "#/components/parameters/IdempotencyKeyHeader" }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "order_number": {
                      "type": "string"
                    },
                    "type": {
                      "type": "string",
                      "enum": [
                        "delivery",
                        "pickup",
                        "shipment"
                      ]
                    },
                    "customer": {
                      "type": "object",
                      "description": "Optional. When omitted, the order is created without a customer association (`customer_id` will be `null`). Requires the 'Orders Without Customers' depot setting to be enabled.",
                      "properties": {
                        "id": {
                          "type": "number",
                          "description": "ID of the customer."
                        },
                        "account": {
                          "type": "string",
                          "description": "Account number of the customer, if both ID and account are provided, customer's account number will be updated if different to the customer's current account number."
                        },
                        "name": {
                          "type": "string",
                          "description": "Name of the customer."
                        },
                        "email": {
                          "type": "string",
                          "format": "email",
                          "description": "Email of the customer."
                        },
                        "phone": {
                          "type": "string",
                          "description": "Contact number of the customer."
                        },
                        "country_code": {
                          "type": "string",
                          "description": "Country code of the customer."
                        },
                        "address": {
                          "type": "string",
                          "description": "Address of the customer."
                        },
                        "postcode": {
                          "type": "string",
                          "description": "Postcode of the customer."
                        },
                        "lat": {
                          "type": "number",
                          "description": "Latitude of the customer location."
                        },
                        "lng": {
                          "type": "number",
                          "description": "Longitude of the customer location."
                        }
                      },
                      "required": [],
                      "oneOf": [
                        {
                          "title": "id",
                          "required": [
                            "id"
                          ]
                        },
                        {
                          "title": "account",
                          "required": [
                            "account"
                          ]
                        }
                      ]
                    },
                    "delivery_contact_name": {
                      "type": "string"
                    },
                    "delivery_contact_number": {
                      "type": "string"
                    },
                    "delivery_contact_email": {
                      "type": "string",
                      "format": "email"
                    },
                    "delivery_address": {
                      "type": "string"
                    },
                    "delivery_postcode": {
                      "type": "string"
                    },
                    "delivery_lat": {
                      "type": "number"
                    },
                    "delivery_lng": {
                      "type": "number"
                    },
                    "delivery_notes": {
                      "type": "string"
                    },
                    "delivery_time_windows": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "from": {
                            "type": "string",
                            "format": "time",
                            "description": "Start time of the time window."
                          },
                          "to": {
                            "type": "string",
                            "format": "time",
                            "description": "End time of the time window."
                          }
                        },
                        "required": [
                          "from",
                          "to"
                        ],
                        "description": "Time windows for order delivery."
                      },
                      "description": "List of time windows for order delivery."
                    },
                    "delivery_date": {
                      "type": "string",
                      "format": "date"
                    },
                    "delivery_available_days": {
                      "type": "array",
                      "items": {
                        "type": "string",
                        "description": " Days of the week the order can be delivered.",
                        "enum": [
                          "MONDAY",
                          "TUESDAY",
                          "WEDNESDAY",
                          "THURSDAY",
                          "FRIDAY",
                          "SATURDAY",
                          "SUNDAY"
                        ]
                      },
                      "description": "List of available delivery days for the order."
                    },
                    "pickup_address": {
                      "type": "string"
                    },
                    "pickup_postcode": {
                      "type": "string"
                    },
                    "pickup_duration": {
                      "type": "number"
                    },
                    "pickup_lat": {
                      "type": "number"
                    },
                    "pickup_lng": {
                      "type": "number"
                    },
                    "pickup_notes": {
                      "type": "string"
                    },
                    "pickup_time_windows": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "from": {
                            "type": "string",
                            "format": "time",
                            "description": "Start time of the time window."
                          },
                          "to": {
                            "type": "string",
                            "format": "time",
                            "description": "End time of the time window."
                          }
                        },
                        "required": [
                          "from",
                          "to"
                        ],
                        "description": "Time windows for order pickup."
                      },
                      "description": "List of time windows for order pickup."
                    },
                    "pickup_contact_name": {
                      "type": "string"
                    },
                    "pickup_contact_number": {
                      "type": "string"
                    },
                    "pickup_contact_email": {
                      "type": "string",
                      "format": "email"
                    },
                    "pickup_available_days": {
                      "type": "array",
                      "items": {
                        "type": "string",
                        "description": " Days of the week the order can be picked up.",
                        "enum": [
                          "MONDAY",
                          "TUESDAY",
                          "WEDNESDAY",
                          "THURSDAY",
                          "FRIDAY",
                          "SATURDAY",
                          "SUNDAY"
                        ]
                      },
                      "description": "List of available pickup days for the order."
                    },
                    "order_exchange": {
                      "type": "object",
                      "description": "Optional. Links this order to its partner as an exchange — a drop and a collect at one location served by the same vehicle in one consecutive visit. Provide the SAME reference on exactly two orders in the same request; the server pairs them and mints an internal exchange_id. A pair cannot be formed via single-order update.",
                      "required": [
                        "reference"
                      ],
                      "properties": {
                        "reference": {
                          "type": "string",
                          "description": "Pairing key within this request — exactly two orders must share it. Display-only thereafter (never a join key)."
                        }
                      }
                    },
                    "parts": {
                      "type": "number"
                    },
                    "line_items": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "product_code": {
                            "type": "string",
                            "maxLength": 20
                          },
                          "product_name": {
                            "type": "string",
                            "maxLength": 75
                          },
                          "product_quantity": {
                            "type": "integer"
                          },
                          "capacities": {
                            "type": "array",
                            "items": {
                              "type": "object",
                              "properties": {
                                "id": {
                                  "type": "integer",
                                  "description": "Id of capacity (e.g., 1, 2)."
                                },
                                "capacity": {
                                  "type": "number",
                                  "format": "float",
                                  "description": "Capacity value for the specified type."
                                }
                              },
                              "required": [
                                "id",
                                "capacity"
                              ],
                              "description": "List of capacities with their types and values."
                            },
                            "description": "List of capacities for the line item."
                          }
                        },
                        "required": [
                          "product_code",
                          "product_name",
                          "product_quantity"
                        ]
                      }
                    },
                    "skills": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "custom_fields": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "description": "Custom fields to include on the order. Either id or name is required.",
                        "properties": {
                          "id": {
                            "type": "number"
                          },
                          "name": {
                            "type": "number"
                          },
                          "value": {
                            "type": "string"
                          }
                        },
                        "required": [
                          "value"
                        ]
                      }
                    },
                    "capacities": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "integer"
                          },
                          "type": {
                            "type": "string",
                            "description": "Type of the capacity"
                          },
                          "capacity": {
                            "type": "number",
                            "format": "float"
                          }
                        },
                        "required": [
                          "capacity"
                        ]
                      },
                      "description": "List of capacities for the order. Either id or type is required."
                    }
                  },
                  "required": [
                    "order_number",
                    "type"
                  ]
                }
              },
              "example": [
                {
                  "order_number": "ORD123",
                  "delivery_contact_name": "John Doe",
                  "delivery_contact_number": "+123456789",
                  "delivery_contact_email": "john@doe.com",
                  "delivery_address": "123 Main St",
                  "delivery_postcode": "12345",
                  "delivery_lat": 40.7128,
                  "delivery_lng": -74.0060,
                  "delivery_notes": "Leave at the doorstep",
                  "delivery_time_windows": [
                    {
                      "from": "10:00",
                      "to": "11:00"
                    }
                  ],
                  "delivery_date": "2023-12-31",
                  "delivery_available_days": ["MONDAY", "WEDNESDAY", "SUNDAY"],
                  "pickup_address": "456 Oak St",
                  "pickup_postcode": "54321",
                  "pickup_duration": 30,
                  "pickup_lat": 40.730610,
                  "pickup_lng": -73.935242,
                  "pickup_notes": "Call upon arrival",
                  "pickup_time_windows": [
                    {
                      "from": "08:00",
                      "to": "09:00"
                    }
                  ],
                  "pickup_contact_name": "Jane Smith",
                  "pickup_contact_number": "+987654321",
                  "pickup_contact_email": "jane@example.com",
                  "pickup_available_days": ["MONDAY", "WEDNESDAY", "SUNDAY"],
                  "type": "delivery",
                  "parts": 2,
                  "customer": {
                    "id": 123,
                    "account": "NO123"
                  },
                  "line_items": [
                    {
                      "product_code": "P001",
                      "product_name": "Product 1",
                      "product_quantity": 2
                    },
                    {
                      "product_code": "P002",
                      "product_name": "Product 2",
                      "product_quantity": 1
                    }
                  ],
                  "skills": [
                    "skill1",
                    "skill2"
                  ],
                  "custom_fields": [
                    {
                      "id": 123,
                      "value": "Value 1"
                    },
                    {
                      "id": 234,
                      "value": "Value 2"
                    }
                  ],
                  "capacities": [
                    {
                      "id": 1,
                      "capacity": 100
                    },
                    {
                      "id": 2,
                      "capacity": 50
                    }
                  ]
                }
              ]
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "example": {
                  "orders": [
                    {
                      "id": "123",
                      "order_number": "ORD123"
                    },
                    {
                      "id": "124",
                      "order_number": "ORD456"
                    }
                  ],
                  "errors": [
                    {
                      "name": "GEOCODING_FAILED",
                      "description": "We've failed to geocode the provided location.",
                      "details": {
                        "id": 124,
                        "order_number": "ORD456",
                        "is_created": true
                      }
                    }
                  ]
                }
              }
            },
            "headers": {
              "idempotency-replay": { "$ref": "#/components/headers/IdempotencyReplay" }
            }
          },
          "400": { "$ref": "#/components/responses/InvalidInput" },
          "404": { "$ref": "#/components/responses/NotFound" },
          "409": { "$ref": "#/components/responses/IdempotencyRequestInProgress" },
          "422": { "$ref": "#/components/responses/IdempotencyKeyReusedWithDifferentBody" },
          "403": { "$ref": "#/components/responses/Forbidden" },
          "500": { "$ref": "#/components/responses/ServerError" }
        }
      }
    },
    "/notification-tasks": {
      "get": {
        "summary": "Get Notification Tasks Page",
        "operationId": "listNotificationTasks",
        "description": "Endpoint to retrieve a page of notification tasks.",
        "tags": [
          "Notification Tasks"
        ],
        "parameters": [
          {
            "in": "query",
            "name": "page_info",
            "required": false,
            "schema": {
              "type": "string",
              "description": "Pagination cursor generated by the API. Pass this value to retrieve the next page of results."
            },
            "description": "Pagination cursor generated by the API. Pass this value to retrieve the next page of results."
          },
          {
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "type": "integer",
              "default": 100,
              "description": "Maximum number of notification tasks to retrieve per page. Max 100."
            },
            "description": "Maximum number of notification tasks to retrieve per page. Max 100."
          },
          {
            "in": "query",
            "name": "updated_at_min",
            "required": false,
            "schema": {
              "type": "string",
              "format": "date-time",
              "description": "Filter tasks modified at or after this datetime. Format: YYYY-MM-DD hh:mm:ss or YYYY-MM-DDTHH:mm:ss.SSSZ."
            },
            "description": "Filter tasks modified at or after this datetime. Format: YYYY-MM-DD hh:mm:ss or YYYY-MM-DDTHH:mm:ss.SSSZ."
          },
          {
            "in": "query",
            "name": "status",
            "required": false,
            "schema": {
              "type": "string",
              "description": "Filter notification tasks by status."
            },
            "description": "Filter notification tasks by status."
          },
          {
            "in": "query",
            "name": "type",
            "required": false,
            "schema": {
              "type": "string",
              "enum": ["SMS", "EMAIL"],
              "description": "Filter notification tasks by type. Accepted values: SMS, EMAIL (case-insensitive)."
            },
            "description": "Filter notification tasks by type. Accepted values: SMS, EMAIL (case-insensitive)."
          }
        ],
        "responses": {
          "200": {
            "description": "Successful response",
            "headers": {
              "link": {
                "description": "Link to the next page of notification tasks. Use with the page_info parameter for pagination.",
                "schema": {
                  "type": "string"
                },
                "example": "<https://api.smartroutes.io/v2/notification-tasks?page_info=PAGE_INFO_STRING&limit=100>; rel=next"
              }
            },
            "content": {
              "application/json": {
                "example": {
                  "notification_tasks": [
                    {
                      "id": 4616,
                      "template": {
                        "id": 197
                      },
                      "visit": {
                        "id": 599910
                      },
                      "order": null,
                      "scheduled_date": "2026-02-24T14:48:00.000Z",
                      "sent_date": null,
                      "to": "test@smartroutes.io",
                      "subject": "Delivery is on the way",
                      "message": "Hello, your delivery is scheduled.",
                      "status": "Scheduled"
                    },
                    {
                      "id": 4615,
                      "template": {
                        "id": 198
                      },
                      "visit": {
                        "id": 599910
                      },
                      "order": null,
                      "scheduled_date": "2026-02-24T14:48:00.000Z",
                      "sent_date": null,
                      "to": "353892373003",
                      "subject": "",
                      "message": "Hello, your delivery is scheduled.",
                      "status": "Scheduled"
                    },
                    {
                      "id": 4614,
                      "template": {
                        "id": 198
                      },
                      "visit": null,
                      "order": {
                        "id": 458457,
                        "order_number": "183"
                      },
                      "scheduled_date": "2026-02-28T14:42:00.000Z",
                      "sent_date": null,
                      "to": "353892373003",
                      "subject": "",
                      "message": "Hello, your delivery is scheduled.",
                      "status": "Scheduled"
                    }
                  ]
                }
              }
            }
          },
          "400": { "$ref": "#/components/responses/InvalidInput" },
          "403": { "$ref": "#/components/responses/Forbidden" },
          "500": { "$ref": "#/components/responses/ServerError" }
        }
      }
    },
    "/notifications/templates": {
      "get": {
        "summary": "Get Notification Templates",
        "operationId": "listNotificationTemplates",
        "description": "Endpoint to retrieve a depot's notification templates.",
        "tags": [
          "Notifications"
        ],
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "example": [
                  {
                    "id": 123,
                    "type": "EMAIL",
                    "name": "My Email Template"
                  },
                  {
                    "id": 124,
                    "type": "SMS",
                    "name": "My SMS Template"
                  }
                ]
              }
            }
          },
          "403": { "$ref": "#/components/responses/Forbidden" },
          "500": { "$ref": "#/components/responses/ServerError" }
        }
      }
    },
    "/notifications/schedule/orders": {
      "post": {
        "summary": "Schedule Order Notifications",
        "operationId": "scheduleOrderNotifications",
        "description": "Schedule notification dispatches for a set of orders.",
        "tags": [
          "Notifications"
        ],
        "parameters": [
          { "$ref": "#/components/parameters/IdempotencyKeyHeader" }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "orders": {
                    "type": "array",
                    "format": "integer",
                    "description": "Array of order IDs to create notifications for"
                  },
                  "templates": {
                    "type": "array",
                    "format": "integer",
                    "description": "Array of template IDs to generate notifications for"
                  },
                  "send_time_utc": {
                    "type": "string",
                    "description": "UTC Timestamp at which to send the notifications, defaults to current time if not provided."
                  }
                },
                "required": [
                  "orders",
                  "templates"
                ]
              },
              "example": {
                "orders": [
                  123,
                  124
                ],
                "templates": [
                  999
                ],
                "send_time_utc": "2024-12-25 12:00:00"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "example": {
                  "notifications": [
                    {
                      "order_id": 123
                    }
                  ],
                  "errors": [
                    {
                      "name": "INVALID_INPUT",
                      "description": "Couldn't create notification. No phone number provided",
                      "statusCode": 400,
                      "isOperational": true,
                      "sendAlert": false,
                      "sourceError": null,
                      "details": {
                        "id": null,
                        "order_id": 124,
                        "visit_orders": [
                          {
                            "order_id": 124,
                            "order_number": "ORD124"
                          }
                        ],
                        "phone": null,
                        "email": "johndoe@test.com",
                        "country": null,
                        "name": "John Doe",
                        "reference_id": "ORD124",
                        "visit_custom_fields": [],
                        "address": "Cork City, Cork"
                      },
                      "timestamp": "2024-12-30T00:00:00.000Z"
                    }
                  ]
                }
              }
            },
            "headers": {
              "idempotency-replay": { "$ref": "#/components/headers/IdempotencyReplay" }
            }
          },
          "400": { "$ref": "#/components/responses/InvalidInput" },
          "404": { "$ref": "#/components/responses/NotFound" },
          "409": { "$ref": "#/components/responses/IdempotencyRequestInProgress" },
          "422": { "$ref": "#/components/responses/IdempotencyKeyReusedWithDifferentBody" },
          "403": { "$ref": "#/components/responses/Forbidden" },
          "500": { "$ref": "#/components/responses/ServerError" }
        }
      }
    },
    "/orders": {
      "description": "",
      "post": {
        "summary": "Bulk Add Orders",
        "operationId": "createOrders",
        "description": "Endpoint to bulk add orders.",
        "tags": [
          "Orders"
        ],
        "parameters": [
          { "$ref": "#/components/parameters/IdempotencyKeyHeader" }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "order_number": {
                      "type": "string",
                      "description": "Order number."
                    },
                    "customer": {
                      "type": "object",
                      "description": "Optional. When omitted, the order is created without a customer association (`customer_id` will be `null`). Requires the 'Orders Without Customers' depot setting to be enabled.",
                      "properties": {
                        "id": {
                          "type": "number",
                          "description": "ID of the customer."
                        },
                        "account": {
                          "type": "string",
                          "description": "Account number of the customer, if both ID and account are provided, customer's account number will be updated if different to the customer's current account number."
                        },
                        "name": {
                          "type": "string",
                          "description": "Name of the customer."
                        },
                        "email": {
                          "type": "string",
                          "format": "email",
                          "description": "Email of the customer."
                        },
                        "phone": {
                          "type": "string",
                          "description": "Contact number of the customer."
                        },
                        "country_code": {
                          "type": "string",
                          "description": "Country code of the customer."
                        },
                        "address": {
                          "type": "string",
                          "description": "Address of the customer."
                        },
                        "postcode": {
                          "type": "string",
                          "description": "Postcode of the customer."
                        },
                        "lat": {
                          "type": "number",
                          "description": "Latitude of the customer location."
                        },
                        "lng": {
                          "type": "number",
                          "description": "Longitude of the customer location."
                        }
                      },
                      "required": [],
                      "oneOf": [
                        {
                          "title": "id",
                          "required": [
                            "id"
                          ]
                        },
                        {
                          "title": "account",
                          "required": [
                            "account"
                          ]
                        }
                      ]
                    },
                    "type": {
                      "type": "string",
                      "enum": [
                        "delivery",
                        "pickup",
                        "shipment"
                      ],
                      "description": "Type of the order (delivery, pickup, or shipment)."
                    },
                    "priority": {
                      "type": "string",
                      "description": "Priority of the order (Accepts 'P1', 'P2', 'P3')."
                    },
                    "delivery_contact_name": {
                      "type": "string",
                      "description": "Name of the contact person."
                    },
                    "delivery_contact_number": {
                      "type": "string",
                      "description": "Contact number of the person."
                    },
                    "delivery_contact_email": {
                      "type": "string",
                      "description": "Email of the contact person.",
                      "format": "email"
                    },
                    "delivery_address": {
                      "type": "string",
                      "description": "Delivery address."
                    },
                    "delivery_country_code": {
                      "type": "string",
                      "description": "Two letter country code, e.g. 'IE'"
                    },
                    "delivery_postcode": {
                      "type": "string",
                      "description": "Postcode for delivery address."
                    },
                    "delivery_lat": {
                      "type": "number",
                      "description": "Latitude of the delivery location."
                    },
                    "delivery_lng": {
                      "type": "number",
                      "description": "Longitude of the delivery location."
                    },
                    "delivery_duration": {
                      "type": "number",
                      "description": "Duration for order delivery in minutes."
                    },
                    "delivery_notes": {
                      "type": "string",
                      "description": "Notes for delivery instructions."
                    },
                    "delivery_time_windows": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "from": {
                            "type": "string",
                            "format": "time",
                            "description": "Start time of the time window."
                          },
                          "to": {
                            "type": "string",
                            "format": "time",
                            "description": "End time of the time window."
                          }
                        },
                        "required": [
                          "from",
                          "to"
                        ],
                        "description": "Time windows for order delivery."
                      },
                      "description": "List of time windows for order delivery."
                    },
                    "delivery_date": {
                      "type": "string",
                      "format": "date",
                      "description": "Date for order delivery."
                    },
                    "delivery_available_days": {
                      "type": "array",
                      "items": {
                        "type": "string",
                        "description": " Days of the week the order can be delivered.",
                        "enum": [
                          "MONDAY",
                          "TUESDAY",
                          "WEDNESDAY",
                          "THURSDAY",
                          "FRIDAY",
                          "SATURDAY",
                          "SUNDAY"
                        ]
                      },
                      "description": "List of available delivery days for the order."
                    },
                    "pickup_address": {
                      "type": "string",
                      "description": "Address for order pickup."
                    },
                    "pickup_country_code": {
                      "type": "string",
                      "description": "Two letter country code, e.g. 'IE'"
                    },
                    "pickup_postcode": {
                      "type": "string",
                      "description": "Postcode for pickup address."
                    },
                    "pickup_duration": {
                      "type": "number",
                      "description": "Duration for order pickup in minutes."
                    },
                    "pickup_lat": {
                      "type": "number",
                      "description": "Latitude of the pickup location."
                    },
                    "pickup_lng": {
                      "type": "number",
                      "description": "Longitude of the pickup location."
                    },
                    "pickup_notes": {
                      "type": "string",
                      "description": "Notes for pickup instructions."
                    },
                    "pickup_time_windows": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "from": {
                            "type": "string",
                            "format": "time",
                            "description": "Start time of the time window."
                          },
                          "to": {
                            "type": "string",
                            "format": "time",
                            "description": "End time of the time window."
                          }
                        },
                        "required": [
                          "from",
                          "to"
                        ],
                        "description": "Time windows for order pickup."
                      },
                      "description": "List of time windows for order pickup."
                    },
                    "pickup_contact_name": {
                      "type": "string",
                      "description": "Name of the contact person for pickup."
                    },
                    "pickup_contact_number": {
                      "type": "string",
                      "description": "Contact number of the person for pickup."
                    },
                    "pickup_contact_email": {
                      "type": "string",
                      "format": "email",
                      "description": "Email of the contact person for pickup."
                    },
                    "pickup_available_days": {
                      "type": "array",
                      "items": {
                        "type": "string",
                        "description": "Days of the week the order can be picked up.",
                        "enum": [
                          "MONDAY",
                          "TUESDAY",
                          "WEDNESDAY",
                          "THURSDAY",
                          "FRIDAY",
                          "SATURDAY",
                          "SUNDAY"
                        ]
                      },
                      "description": "List of available pickup days for the order."
                    },
                    "order_exchange": {
                      "type": "object",
                      "description": "Optional. Links this order to its partner as an exchange — a drop and a collect at one location served by the same vehicle in one consecutive visit. Provide the SAME reference on exactly two orders in the same request; the server pairs them and mints an internal exchange_id. A pair cannot be formed via single-order update.",
                      "required": [
                        "reference"
                      ],
                      "properties": {
                        "reference": {
                          "type": "string",
                          "description": "Pairing key within this request — exactly two orders must share it. Display-only thereafter (never a join key)."
                        }
                      }
                    },
                    "parts": {
                      "type": "number",
                      "description": "Number of parts in the order."
                    },
                    "vehicle_assignment": {
                      "type": "object",
                      "properties": {
                        "vehicle_id": {
                          "type": "integer",
                          "description": "ID of the assigned vehicle"
                        }
                      }
                    },
                    "emails": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "email": {
                            "type": "string",
                            "format": "email",
                            "description": "Additional emails"
                          }
                        }
                      }
                    },
                    "third_party": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "integer",
                          "description": "ID of the third party for the order"
                        }
                      },
                      "description": "Third party object"
                    },
                    "line_items": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "product_code": {
                            "type": "string",
                            "description": "Code of the product.",
                            "maxLength": 20
                          },
                          "product_name": {
                            "type": "string",
                            "description": "Name of the product.",
                            "maxLength": 75
                          },
                          "product_quantity": {
                            "type": "integer",
                            "description": "Quantity of the product."
                          },
                          "capacities": {
                            "type": "array",
                            "items": {
                              "type": "object",
                              "properties": {
                                "id": {
                                  "type": "integer",
                                  "description": "Id of capacity (e.g., 1, 2)."
                                },
                                "capacity": {
                                  "type": "number",
                                  "format": "float",
                                  "description": "Capacity value for the specified type."
                                }
                              },
                              "required": [
                                "id",
                                "capacity"
                              ],
                              "description": "List of capacities with their types and values."
                            },
                            "description": "List of capacities for the line item."
                          },
                          "date": {
                            "type": "string",
                            "format": "date",
                            "description": "Date for the line item."
                          },
                          "custom_fields": {
                            "type": "array",
                            "items": {
                              "type": "object",
                              "properties": {
                                "id": {
                                  "type": "integer",
                                  "description": "Id of custom field (e.g., 1, 2)."
                                },
                                "value": {
                                  "type": "string",
                                  "description": "New custom field value"
                                }
                              }
                            },
                            "description": "List custom fields for the line item"
                          }
                        },
                        "required": [
                          "product_code",
                          "product_name",
                          "product_quantity"
                        ],
                        "description": "Details of each line item in the order."
                      },
                      "description": "List of line items in the order."
                    },
                    "skills": {
                      "type": "array",
                      "items": {
                        "type": "string",
                        "description": "List of required skills for the order."
                      },
                      "description": "List of required skills for the order."
                    },
                    "custom_fields": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "number",
                            "description": "ID of the custom field."
                          },
                          "name": {
                            "type": "string",
                            "description": "Name of the custom field."
                          },
                          "value": {
                            "type": "string",
                            "description": "Value of the custom field."
                          }
                        },
                        "required": [
                          "value"
                        ],
                        "description": "Custom fields to include on the order. Either id or name is required."
                      },
                      "description": "List of custom fields for the order."
                    },
                    "capacities": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "integer",
                            "description": "ID of a capacity."
                          },
                          "type": {
                            "type": "string",
                            "description": "Type of the capacity"
                          },
                          "capacity": {
                            "type": "number",
                            "format": "float",
                            "description": "Capacity value for the specified type."
                          }
                        },
                        "required": [
                          "capacity"
                        ],
                        "description": "List of capacities with their ids and values."
                      },
                      "description": "List of capacities for the order. Either id or type is required."
                    },
                    "tags": {
                      "type": "array",
                      "description": "List of tag names (must already exist)",
                      "items": {
                        "type": "string"
                      }
                    }
                  },
                  "required": [
                    "order_number",
                    "type"
                  ],
                  "description": "Details of an order including delivery, pickup, or shipment information."
                }
              },
              "example": [
                {
                  "order_number": "ORD123",
                  "delivery_contact_name": "John Doe",
                  "delivery_contact_number": "+123456789",
                  "delivery_contact_email": "john@doe.com",
                  "delivery_address": "123 Main St",
                  "delivery_country_code": "IE",
                  "delivery_postcode": "12345",
                  "delivery_lat": 40.7128,
                  "delivery_lng": -74.0060,
                  "delivery_notes": "Leave at the doorstep",
                  "delivery_time_windows": [
                    {
                      "from": "10:00",
                      "to": "11:00"
                    }
                  ],
                  "delivery_date": "2023-12-31",
                  "delivery_available_days": ["MONDAY", "WEDNESDAY", "SUNDAY"],
                  "pickup_address": "456 Oak St",
                  "pickup_country_code": "IE",
                  "pickup_postcode": "54321",
                  "pickup_duration": 30,
                  "pickup_lat": 40.730610,
                  "pickup_lng": -73.935242,
                  "pickup_notes": "Call upon arrival",
                  "pickup_time_windows": [
                    {
                      "from": "08:00",
                      "to": "09:00"
                    }
                  ],
                  "pickup_contact_name": "Jane Smith",
                  "pickup_contact_number": "+987654321",
                  "pickup_contact_email": "jane@example.com",
                  "pickup_available_days": ["MONDAY", "WEDNESDAY", "SUNDAY"],
                  "priority": "P1",
                  "type": "delivery",
                  "parts": 2,
                  "vehicle_assignment": {
                    "vehicle_id": 1958
                  },
                  "emails": [
                    {
                      "email": "example@email.com"
                    },
                    {
                      "email": "example2@email.com"
                    }
                  ],
                  "customer": {
                    "id": 123,
                    "account": "NO123"
                  },
                  "line_items": [
                    {
                      "product_code": "P001",
                      "product_name": "Product 1",
                      "product_quantity": 2,
                      "date": "2024-07-12",
                      "custom_fields": [
                        {
                          "id": 123,
                          "value": "Value 1"
                        }
                      ]
                    },
                    {
                      "product_code": "P002",
                      "product_name": "Product 2",
                      "product_quantity": 1,
                      "date": "2024-07-12",
                      "custom_fields": [
                        {
                          "id": 321,
                          "value": "Value 1"
                        }
                      ]
                    }
                  ],
                  "skills": [
                    "skill1",
                    "skill2"
                  ],
                  "custom_fields": [
                    {
                      "id": 123,
                      "value": "Value 1"
                    },
                    {
                      "id": 234,
                      "value": "Value 2"
                    }
                  ],
                  "capacities": [
                    {
                      "id": 1,
                      "capacity": 100
                    },
                    {
                      "id": 2,
                      "capacity": 50
                    }
                  ],
                  "tags": [
                    "tag1",
                    "tag2"
                  ]
                }
              ]
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "example": {
                  "orders": [
                    {
                      "id": "123",
                      "order_number": "ORD123"
                    },
                    {
                      "id": "124",
                      "order_number": "ORD456"
                    }
                  ],
                  "errors": [
                    {
                      "name": "GEOCODING_FAILED",
                      "description": "We've failed to geocode the provided location.",
                      "details": {
                        "id": 124,
                        "order_number": "ORD456",
                        "is_created": true
                      }
                    }
                  ]
                }
              }
            },
            "headers": {
              "idempotency-replay": { "$ref": "#/components/headers/IdempotencyReplay" }
            }
          },
          "400": { "$ref": "#/components/responses/InvalidInput" },
          "404": { "$ref": "#/components/responses/NotFound" },
          "409": { "$ref": "#/components/responses/IdempotencyRequestInProgress" },
          "422": { "$ref": "#/components/responses/IdempotencyKeyReusedWithDifferentBody" },
          "403": { "$ref": "#/components/responses/Forbidden" },
          "500": { "$ref": "#/components/responses/ServerError" }
        }
      },
      "get": {
        "summary": "Get Orders Page",
        "operationId": "listOrders",
        "description": "Endpoint to retrieve a page of orders.",
        "tags": [
          "Orders"
        ],
        "parameters": [
          {
            "in": "query",
            "name": "page_info",
            "required": false,
            "schema": {
              "type": "string",
              "description": "Information about the page for pagination. Generated by the OpenAPI"
            },
            "description": "Information about the page for pagination. Generated by the OpenAPI"
          },
          {
            "in": "query",
            "name": "status",
            "required": false,
            "schema": {
              "type": "string",
              "description": "Status of the orders to filter."
            },
            "description": "Status of the orders to filter."
          },
          {
            "in": "query",
            "name": "customer_id",
            "required": false,
            "schema": {
              "type": "integer",
              "description": "SmartRoutes customer id."
            },
            "description": "Filter orders by the customer they belong to."
          },
          {
            "in": "query",
            "name": "order_number",
            "required": false,
            "schema": {
              "type": "string",
              "description": "Order number of the order to filter"
            },
            "description": "Filter orders by a specific order number"
          },
          {
            "in": "query",
            "name": "updated_at_min",
            "required": false,
            "schema": {
              "type": "string",
              "format": "date-time",
              "description": "Minimum updated date and time for filtering."
            },
            "description": "Minimum updated date and time for filtering."
          },
          {
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "type": "integer",
              "default": 100,
              "description": "Maximum number of orders to retrieve per page."
            },
            "description": "Maximum number of orders to retrieve per page."
          }
        ],
        "responses": {
          "200": {
            "description": "Successful response",
            "headers": {
              "link": {
                "description": "Link to the next page of orders. Use with the page_info parameter for pagination.",
                "schema": {
                  "type": "string"
                },
                "example": "<https://api.smartroutes.io/v2/orders?page_info=PAGE_INFO_STRING&limit=100>; rel=next"
              }
            },
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/OrdersListResponse" },
                "example": {
                  "orders": [
                    {
                      "id": 1,
                      "order_number": "ABC123",
                      "status": "DELIVERED",
                      "type": "delivery",
                      "stops": [
                        {
                          "id": 101,
                          "route_id": 123,
                          "address": "Dublin Road, Portlaoise, Ireland",
                          "postcode": "R32 XD32",
                          "phone": "+353 215 12320",
                          "lat": 53.52145,
                          "lng": -7.58954,
                          "planned_distance": 1278.2,
                          "arrival_date": "2024-03-04",
                          "departure_date": "2024-03-04",
                          "estimated_arrival_time": "14:17",
                          "estimated_departure_time": "14:27",
                          "actual_completed_ts": "2024-03-04T14:04:51.000Z",
                          "actual_completed_lat": 12.345,
                          "actual_completed_lng": -45.678,
                          "delivery_notes": null,
                          "driver_notes": null,
                          "actual_arrival_time": null,
                          "actual_duration": null,
                          "signature": "https://api.smartroutes.io/v2/proof-of-delivery/signatures/116839",
                          "signature_lat": 12.345,
                          "signature_lng": -45.678,
                          "signed_by": "James Murphy",
                          "photos": [
                            "https://api.smartroutes.io/v2/proof-of-delivery/photos/491548"
                          ],
                          "tracking_link": null,
                          "vehicle_assignment": null,
                          "directions": [
                            {
                              "instruction": "Turn left onto Sample Road"
                            },
                            {
                              "instruction": "At the roundabout, take the 3rd exit onto Baker Street"
                            }
                          ],
                          "driver_questionnaire_submissions": [
                            {
                              "id": 1269,
                              "driver_questionnaire": {
                                "type": "VISIT",
                                "title": "Stop Questionaire"
                              }
                            }
                          ],
                          "failed_reason": {
                            "reason": "Wrong Parcel"
                          },
                          "route": {
                            "id": 201,
                            "date": "2024-03-04",
                            "started_ts": "2024-03-04T15:09:34.000Z"
                          }
                        },
                        {
                          "id": 102,
                          "route_id": 456,
                          "address": "Dublin Road, Portlaoise, Ireland",
                          "postcode": "R32 XD32",
                          "phone": "+353 215 12320",
                          "lat": 53.52145,
                          "lng": -7.58954,
                          "planned_distance": 1234.5,
                          "arrival_date": "2024-03-05",
                          "departure_date": "2024-03-05",
                          "estimated_arrival_time": "13:27",
                          "estimated_departure_time": "13:37",
                          "actual_completed_ts": "2024-03-05T13:28:51.000Z",
                          "actual_completed_lat": 12.345,
                          "actual_completed_lng": -45.678,
                          "delivery_notes": null,
                          "driver_notes": null,
                          "actual_arrival_time": null,
                          "actual_duration": null,
                          "signature": "https://api.smartroutes.io/v2/proof-of-delivery/signatures/116839",
                          "signature_lat": 12.345,
                          "signature_lng": -45.678,
                          "signed_by": "James Murphy",
                          "photos": null,
                          "tracking_link": null,
                          "vehicle_assignment": null,
                          "directions": [
                            {
                              "instruction": "Turn right onto Example Road"
                            },
                            {
                              "instruction": "At the roundabout, take the 2nd exit onto Cook Street"
                            }
                          ],
                          "driver_questionnaire_submissions": [
                            {
                              "id": 1270,
                              "driver_questionnaire": {
                                "type": "VISIT",
                                "title": "Stop Questionaire"
                              }
                            }
                          ],
                          "failed_reason": {
                            "reason": "Wrong Parcel"
                          },
                          "route": {
                            "id": 202,
                            "date": "2024-03-05",
                            "started_ts": "2024-03-05T15:09:34.000Z"
                          }
                        }
                      ],
                      "customer": {
                        "id": 123,
                        "account": "NO123"
                      },
                      "created": "2022-04-29T16:12:08.000Z",
                      "updated": "2022-09-29T10:11:06.000Z"
                    },
                    {
                      "id": 2,
                      "order_number": "XYZ456",
                      "status": "OPEN",
                      "type": "delivery",
                      "stops": [
                        {
                          "id": 103,
                          "route": {
                            "id": 203,
                            "date": "2023-01-04",
                            "started_ts": "2023-01-04T15:09:34.000Z"
                          }
                        }
                      ],
                      "customer": {
                        "id": 124,
                        "account": "NO124"
                      },
                      "created": "2022-04-29T16:12:08.000Z",
                      "updated": "2022-09-29T10:11:06.000Z"
                    }
                  ]
                }
              }
            }
          },
          "400": { "$ref": "#/components/responses/InvalidInput" },
          "403": { "$ref": "#/components/responses/Forbidden" },
          "500": { "$ref": "#/components/responses/ServerError" }
        }
      }
    },
    "/orders/{id}": {
      "get": {
        "summary": "Get Order by ID",
        "operationId": "getOrderById",
        "description": "Retrieve an order based on ID.",
        "tags": [
          "Orders"
        ],
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "ID of the order to retrieve."
          }
        ],
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/OrderResponse" },
                "example": {
                  "order_number": "ABC123",
                  "priority": "P1",
                  "customer_id": 101,
                  "delivery_contact_name": "John Doe",
                  "delivery_contact_number": "+1234567890",
                  "delivery_contact_email": "john.doe@example.com",
                  "delivery_address": "123 Main St 12345",
                  "delivery_lat": 12.345,
                  "delivery_lng": -67.890,
                  "delivery_notes": "Leave at the doorstep",
                  "delivery_date": "2023-01-01",
                  "delivery_duration": 30,
                  "delivery_available_days": ["MONDAY", "SUNDAY"],
                  "pickup_address": "456 Oak Ave 67890",
                  "pickup_lat": 12.678,
                  "pickup_lng": -67.432,
                  "pickup_notes": "Collect from reception",
                  "pickup_contact_name": "Jane Smith",
                  "pickup_contact_number": "+0987654321",
                  "pickup_contact_email": "jane.smith@example.com",
                  "pickup_available_days": ["TUESDAY", "WEDNESDAY"],
                  "pickup_duration": 15,
                  "status": "OPEN",
                  "type": "delivery",
                  "parts": 2,
                  "created": "2022-04-29T16:12:08.000Z",
                  "updated": "2022-09-29T10:11:06.000Z",
                  "vehicle_assignment": {
                    "vehicle_id": 67
                  },
                  "emails": [
                    {
                      "email": "example@email.com"
                    },
                    {
                      "email": "example2@email.com"
                    }
                  ],
                  "customer": {
                    "id": 123,
                    "account": "NO123"
                  },
                  "third_party": {
                    "id": 135
                  },
                  "tags": [
                    "Tag1",
                    "Tag2"
                   ],
                  "line_items": [
                    {
                      "product_name": "Widget A",
                      "product_code": "WID-A",
                      "product_quantity": 3,
                      "quantity_outstanding": 0.5,
                      "status": "PARTIALLY_DELIVERED",
                      "date": "2024-01-01",
                      "custom_fields": [
                        {
                          "id": 123,
                          "value": "Value 1",
                          "name": "Custom Field 1"
                        }
                      ]
                    },
                    {
                      "product_name": "Gadget B",
                      "product_code": "GAD-B",
                      "product_quantity": 2,
                      "quantity_outstanding": 0,
                      "capacities": [
                        {
                          "id": 201,
                          "type": "WEIGHT",
                          "capacity": 100
                        }
                      ],
                      "status": "DELIVERED",
                      "date": "2024-01-01",
                      "custom_fields": [
                        {
                          "id": 321,
                          "value": "Value 1",
                          "name": "Custom Field 2"
                        }
                      ]
                    }
                  ],
                  "capacities": [
                    {
                      "id": 201,
                      "type": "WEIGHT",
                      "capacity": 500
                    },
                    {
                      "id": 202,
                      "type": "VOLUME",
                      "capacity": 1000
                    }
                  ],
                  "custom_fields": [
                    {
                      "id": 201,
                      "name": "Cash due on Collection",
                      "value": "Yes"
                    }
                  ],
                  "time_windows": [
                    {
                      "from": "08:00",
                      "to": "12:00",
                      "type": "pickup"
                    },
                    {
                      "from": "14:00",
                      "to": "18:00",
                      "type": "delivery"
                    }
                  ],
                  "skills": [
                    "Skill A",
                    "Skill B"
                  ],
                  "stops": [
                    {
                      "id": 123,
                      "route_id": 456,
                      "address": "123 Main St",
                      "postcode": "D01 AB12",
                      "phone": "555-1234",
                      "lat": 12.345,
                      "lng": -45.678,
                      "planned_distance": 1234.5,
                      "arrival_date": "2023-12-31",
                      "departure_date": "2023-12-31",
                      "delivery_notes": "Leave at the doorstep",
                      "driver_notes": "Customer not available initially",
                      "estimated_arrival_time": "09:00",
                      "estimated_departure_time": "10:00",
                      "actual_completed_ts": "2023-12-31T10:15:00",
                      "actual_arrival_time": "2023-12-31T09:15:00",
                      "actual_completed_lat": 12.345,
                      "actual_completed_lng": -45.678,
                      "actual_duration": 60,
                      "signature": "https://api.smartroutes.io/v2/proof-of-delivery/signatures/111486",
                      "signature_lat": 12.345,
                      "signature_lng": -45.678,
                      "signed_by": "John",
                      "tracking_link": "https://tracksr.io/xyzabc",
                      "photos": [
                        "https://api.smartroutes.io/v2/proof-of-delivery/photos/491548"
                      ],
                      "vehicle_assignment": null,
                      "directions": [
                        {
                          "instruction": "Turn right onto Example Road"
                        },
                        {
                          "instruction": "At the roundabout, take the 2nd exit onto Cook Street"
                        }
                      ],
                      "driver_questionnaire_submissions": [
                        {
                          "id": 1270,
                          "driver_questionnaire": {
                            "type": "VISIT",
                            "title": "Stop Questionaire"
                          }
                        }
                      ],
                      "failed_reason": {
                        "reason": "Wrong Parcel"
                      },
                      "tags": [
                        "Fragile",
                        "Priority"
                      ],
                      "available_days": [],
                      "custom_fields": [
                        {
                          "id": 88,
                          "name": "Access Code",
                          "value": "4821"
                        }
                      ],
                      "emails": [
                        "test@example.com"
                      ],
                      "route": {
                        "id": 456,
                        "date": "2023-12-31"
                      }
                    }
                  ],
                  "attachments": [
                    {
                      "id": 35,
                      "name": "OrderFile1.pdf"
                    },
                    {
                      "id": 36,
                      "name": "OrderFile2.png"
                    }
                  ]
                }
              }
            }
          },
          "400": { "$ref": "#/components/responses/InvalidInput" },
          "404": { "$ref": "#/components/responses/NotFound" },
          "403": { "$ref": "#/components/responses/Forbidden" },
          "500": { "$ref": "#/components/responses/ServerError" }
        }
      },
      "put": {
        "summary": "Update Order by ID",
        "operationId": "updateOrderById",
        "description": "Update an order based on ID.",
        "tags": [
          "Orders"
        ],
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "ID of the order to update."
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "order_number": "ABC123",
                "priority": "P1",
                "customer_id": 101,
                "delivery_contact_name": "John Doe",
                "delivery_contact_number": "+1234567890",
                "delivery_contact_email": "john.doe@example.com",
                "delivery_address": "123 Main St 12345",
                "delivery_lat": 12.345,
                "delivery_lng": -67.890,
                "delivery_notes": "Leave at the doorstep",
                "delivery_time_windows": [
                  {
                    "from": "10:00",
                    "to": "11:00"
                  }
                ],
                "delivery_duration": 30,
                "delivery_date": "2023-01-01",
                "delivery_available_days": ["MONDAY", "TUESDAY", "THURSDAY"],
                "type": "delivery",
                "parts": 2,
                "vehicle_assignment": {
                  "vehicle_id": 1958
                },
                "emails": [
                  {
                    "email": "example@email.com"
                  },
                  {
                    "email": "example2@email.com"
                  }
                ],
                "updated": "2023-01-04T08:45:00Z",
                "third_party": {
                  "id": 134
                },
                "tags": [
                  "Tag1",
                  "Tag2"
                ],
                "line_items": [
                  {
                    "product_name": "Widget A",
                    "product_code": "WID-A",
                    "product_quantity": 3,
                    "date": "2024-01-01",
                    "custom_fields": [
                      {
                        "id": 123,
                        "value": "Value 1"
                      }
                    ]
                  },
                  {
                    "product_name": "Gadget B",
                    "product_code": "GAD-B",
                    "product_quantity": 2,
                    "date": "2024-01-01",
                    "custom_fields": [
                      {
                        "id": 321,
                        "value": "Value 1"
                      }
                    ]
                  }
                ],
                "capacities": [
                  {
                    "id": 201,
                    "type": "WEIGHT",
                    "capacity": 500
                  },
                  {
                    "id": 202,
                    "type": "VOLUME",
                    "capacity": 1000
                  }
                ],
                "custom_fields": [
                  {
                    "id": 123,
                    "value": "Value 1"
                  },
                  {
                    "name": "Cash due on Collection",
                    "value": "Yes"
                  }
                ],
                "skills": [
                  "Skill A",
                  "Skill B"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "order": {
                      "type": "object",
                      "properties": {
                        "order_number": {
                          "type": "string",
                          "description": "Order number."
                        },
                        "priority": {
                          "type": "string",
                          "description": "Priority of the order."
                        },
                        "type": {
                          "type": "string",
                          "enum": [
                            "delivery",
                            "pickup",
                            "shipment"
                          ],
                          "description": "Type of the order (delivery, pickup, or shipment)."
                        },
                        "delivery_contact_name": {
                          "type": "string",
                          "description": "Name of the contact person."
                        },
                        "delivery_contact_number": {
                          "type": "string",
                          "description": "Contact number of the person."
                        },
                        "delivery_contact_email": {
                          "type": "string",
                          "description": "Contact email of the person."
                        },
                        "delivery_address": {
                          "type": "string",
                          "description": "Delivery address."
                        },
                        "delivery_postcode": {
                          "type": "string",
                          "description": "Postcode for delivery address."
                        },
                        "delivery_lat": {
                          "type": "number",
                          "description": "Latitude of the delivery location."
                        },
                        "delivery_lng": {
                          "type": "number",
                          "description": "Longitude of the delivery location."
                        },
                        "delivery_duration": {
                          "type": "number",
                          "description": "Duration for order delivery in minutes."
                        },
                        "delivery_notes": {
                          "type": "string",
                          "description": "Notes for delivery instructions."
                        },
                        "delivery_date": {
                          "type": "string",
                          "format": "date",
                          "description": "Date for order delivery."
                        },
                        "delivery_available_days": {
                          "type": "array",
                          "items": {
                            "type": "string",
                            "description": "Available delivery days for the order.",
                            "enum": [
                              "MONDAY",
                              "TUESDAY",
                              "WEDNESDAY",
                              "THURSDAY",
                              "FRIDAY",
                              "SATURDAY",
                              "SUNDAY"
                            ]
                          },
                          "description": "List of available delivery days for the order."
                        },
                        "pickup_address": {
                          "type": "string",
                          "description": "Address for order pickup."
                        },
                        "pickup_postcode": {
                          "type": "string",
                          "description": "Postcode for pickup address."
                        },
                        "pickup_duration": {
                          "type": "number",
                          "description": "Duration for order pickup in minutes."
                        },
                        "pickup_lat": {
                          "type": "number",
                          "description": "Latitude of the pickup location."
                        },
                        "pickup_lng": {
                          "type": "number",
                          "description": "Longitude of the pickup location."
                        },
                        "pickup_notes": {
                          "type": "string",
                          "description": "Notes for pickup instructions."
                        },
                        "pickup_contact_name": {
                          "type": "string",
                          "description": "Name of the contact person for pickup."
                        },
                        "pickup_contact_number": {
                          "type": "string",
                          "description": "Contact number of the person for pickup."
                        },
                        "pickup_contact_email": {
                          "type": "string",
                          "format": "email",
                          "description": "Email of the contact person for pickup."
                        },
                        "pickup_available_days": {
                          "type": "array",
                          "items": {
                            "type": "string",
                            "description": "Available pickup days for the order.",
                            "enum": [
                              "MONDAY",
                              "TUESDAY",
                              "WEDNESDAY",
                              "THURSDAY",
                              "FRIDAY",
                              "SATURDAY",
                              "SUNDAY"
                            ]
                          },
                          "description": "List of available pickup days for the order."
                        },
                        "parts": {
                          "type": "number",
                          "description": "Number of parts in the order."
                        },
                        "vehicle_assignment": {
                          "type": "object",
                          "properties": {
                            "vehicle_id": {
                              "type": "integer",
                              "description": "ID of the assigned vehicle"
                            }
                          }
                        },
                        "emails": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "email": {
                                "type": "string",
                                "format": "email",
                                "description": "Additional emails"
                              }
                            }
                          }
                        },
                        "third_party": {
                          "type": "object",
                          "properties": {
                            "id": {
                              "type": "integer",
                              "description": "ID of the third party for the order"
                            }
                          },
                          "description": "Third party object"
                        },
                        "tags": {
                          "type": "array",
                          "description": "List of tag names",
                          "items": {
                            "type": "string"
                          }
                        },
                        "line_items": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "product_code": {
                                "type": "string",
                                "description": "Code of the product.",
                                "maxLength": 20
                              },
                              "product_name": {
                                "type": "string",
                                "description": "Name of the product.",
                                "maxLength": 75
                              },
                              "product_quantity": {
                                "type": "integer",
                                "description": "Quantity of the product."
                              },
                              "quantity_outstanding": {
                                "type": "number",
                                "format": "float",
                                "nullable": true,
                                "description": "Quantity still to be fulfilled on this line item — left to deliver on a `delivery` order, left to collect on a `pickup` order. Equal to `product_quantity` before anything is fulfilled, a value in between after a partial fulfillment, `0` when exactly the ordered quantity has been fulfilled, and **negative** when more than the ordered quantity was fulfilled. Subtract it from `product_quantity` for the amount the driver has fulfilled. **Read-only:** drivers record fulfillment in the SmartRoutes mobile app; it cannot be set through this API. Notes: `null` — not `0` — when the line item is not tracked, so treat null as unknown rather than as fully fulfilled; an over-fulfillment is reported as recorded rather than clamped; stays at `product_quantity` on `shipment` orders, which are dual-leg and not yet tracked. A value still equal to `product_quantity` does not distinguish an untouched line item from one a driver attended and fulfilled nothing on — read `status` for that (`UNDELIVERED` means attended)."
                              },
                              "capacities": {
                                "type": "array",
                                "items": {
                                  "type": "object",
                                  "properties": {
                                    "id": {
                                      "type": "integer",
                                      "description": "Id of capacity (e.g., 1, 2)."
                                    },
                                    "capacity": {
                                      "type": "number",
                                      "format": "float",
                                      "description": "Capacity value for the specified type."
                                    }
                                  },
                                  "required": [
                                    "id",
                                    "capacity"
                                  ],
                                  "description": "List of capacities with their types and values."
                                },
                                "description": "List of capacities for the line item."
                              },
                              "status": {
                                "type": "string",
                                "description": "Status of the line item."
                              },
                              "date": {
                                "type": "string",
                                "format": "date",
                                "description": "Date for the line item."
                              },
                              "custom_fields": {
                                "type": "array",
                                "items": {
                                  "type": "object",
                                  "properties": {
                                    "id": {
                                      "type": "integer",
                                      "description": "Id of custom field (e.g., 1, 2)."
                                    },
                                    "value": {
                                      "type": "string",
                                      "description": "New custom field value"
                                    },
                                    "name": {
                                      "type": "string",
                                      "description": "Name of the custom field."
                                    }
                                  }
                                },
                                "description": "List custom fields for the line item"
                              }
                            },
                            "required": [
                              "product_code",
                              "product_name",
                              "product_quantity"
                            ],
                            "description": "Details of each line item in the order."
                          },
                          "description": "List of line items in the order."
                        },
                        "time_windows": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "from": {
                                "type": "string",
                                "format": "time",
                                "description": "Start time of the time window."
                              },
                              "to": {
                                "type": "string",
                                "format": "time",
                                "description": "End time of the time window."
                              },
                              "type": {
                                "type": "string",
                                "format": "string",
                                "description": "The type of the time window, pickup or delivery."
                              }
                            },
                            "required": [
                              "from",
                              "to"
                            ],
                            "description": "Time windows for order delivery or pickup."
                          },
                          "description": "List of time windows for order delivery or pickup."
                        },
                        "skills": {
                          "type": "array",
                          "items": {
                            "type": "string",
                            "description": "List of required skills for the order."
                          },
                          "description": "List of required skills for the order."
                        },
                        "custom_fields": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "id": {
                                "type": "number",
                                "description": "ID of the custom field."
                              },
                              "name": {
                                "type": "string",
                                "description": "Name of the custom field."
                              },
                              "value": {
                                "type": "string",
                                "description": "Value of the custom field."
                              }
                            },
                            "required": [
                              "value"
                            ],
                            "description": "Custom fields to include on the order. Either id or name is required."
                          },
                          "description": "List of custom fields for the order."
                        },
                        "capacities": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "id": {
                                "type": "integer",
                                "description": "Id of capacity (e.g., 1, 2)."
                              },
                              "type": {
                                "type": "string",
                                "description": "Type of the capacity"
                              },
                              "capacity": {
                                "type": "number",
                                "format": "float",
                                "description": "Capacity value for the specified type."
                              }
                            },
                            "required": [
                              "capacity"
                            ],
                            "description": "List of capacities with their types and values."
                          },
                          "description": "List of capacities for the order. Either id or type is required."
                        }
                      },
                      "required": [],
                      "description": "Details of an order including delivery, pickup, or shipment information."
                    },
                    "errors": {
                      "type": "array"
                    }
                  },
                  "example": {
                    "order": {
                      "order_number": "ORD123",
                      "type": "delivery",
                      "delivery_contact_name": "John Doe",
                      "delivery_contact_number": "+123456789",
                      "delivery_contact_email": "john.doe@example.com",
                      "delivery_address": "123 Main St",
                      "delivery_postcode": "12345",
                      "delivery_lat": 40.7128,
                      "delivery_lng": -74.0060,
                      "delivery_duration": 30,
                      "delivery_notes": "Leave at the doorstep",
                      "delivery_date": "2023-12-31",
                      "delivery_available_days": ["MONDAY", "TUESDAY", "THURSDAY"],
                      "pickup_address": "456 Oak St",
                      "pickup_postcode": "54321",
                      "pickup_duration": 30,
                      "pickup_lat": 40.730610,
                      "pickup_lng": -73.935242,
                      "pickup_notes": "Call upon arrival",
                      "pickup_contact_name": "Jane Smith",
                      "pickup_contact_number": "+987654321",
                      "pickup_contact_email": "jane@example.com",
                      "pickup_available_days": ["MONDAY", "WEDNESDAY", "FRIDAY"],
                      "parts": 2,
                      "vehicle_assignment": {
                        "vehicle_id": 1986
                      },
                      "emails": [
                        {
                          "email": "example@email.com"
                        },
                        {
                          "email": "example2@email.com"
                        }
                      ],
                      "third_party": {
                        "id": 134
                      },
                      "tags": [
                        "Tag1",
                        "Tag2"
                      ],
                      "line_items": [
                        {
                          "product_code": "P001",
                          "product_name": "Product 1",
                          "product_quantity": 2,
                          "quantity_outstanding": 0.5,
                          "status": "PARTIALLY_DELIVERED",
                          "date": "2024-01-01",
                          "custom_fields": [
                            {
                              "id": 123,
                              "value": "Value 1",
                              "name": "Custom Field 1"
                            }
                          ]
                        },
                        {
                          "product_code": "P002",
                          "product_name": "Product 2",
                          "product_quantity": 1,
                          "capacities": [
                            {
                              "id": 201,
                              "type": "WEIGHT",
                              "capacity": 100
                            }
                          ],
                          "status": "DELIVERED",
                          "date": "2024-01-01",
                          "custom_fields": [
                            {
                              "id": 321,
                              "value": "Value 1",
                              "name": "Custom Field 2"
                            }
                          ]
                        }
                      ],
                      "time_windows": [
                        {
                          "from": "08:00",
                          "to": "12:00",
                          "type": "pickup"
                        },
                        {
                          "from": "14:00",
                          "to": "18:00",
                          "type": "delivery"
                        }
                      ],
                      "skills": [
                        "skill1",
                        "skill2"
                      ],
                      "custom_fields": [
                        {
                          "id": 123,
                          "value": "Value 1"
                        },
                        {
                          "id": 234,
                          "value": "Value 2"
                        }
                      ],
                      "capacities": [
                        {
                          "id": 1,
                          "capacity": 100
                        },
                        {
                          "id": 2,
                          "capacity": 50
                        }
                      ]
                    },
                    "errors": []
                  }
                }
              }
            }
          },
          "400": { "$ref": "#/components/responses/InvalidInput" },
          "404": { "$ref": "#/components/responses/NotFound" },
          "403": { "$ref": "#/components/responses/Forbidden" },
          "500": { "$ref": "#/components/responses/ServerError" }
        }
      }
    },
    "/orders/{id}/attachments": {
      "post": {
        "summary": "Add Attachment to Order by ID",
        "operationId": "addOrderAttachment",
        "description": "Upload a single attachment file to the order. Only one file can be uploaded per request. Supported file types: pdf, png, jpg, jpeg. Maximum file size: 10MB. Maximum of 2 attachments are allowed per order overall.",
        "tags": [
          "Orders"
        ],
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The ID of the order to attach the file to."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "properties": {
                  "attachment": {
                    "type": "string",
                    "format": "binary",
                    "description": "Upload a single file (allowed types: pdf, png, jpg, jpeg; max size 10MB)."
                  }
                },
                "required": [
                  "attachment"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Attachment successfully uploaded",
            "content": {
              "application/json": {
                "example": {
                  "id": 58,
                  "order_id": "451020",
                  "depot_id": 578,
                  "name": "SmartRoutes-Orders1.pdf",
                  "mime": "application/pdf",
                  "ext": "pdf",
                  "size": 473892,
                  "is_compressed": false,
                  "modified": "2025-09-01T14:02:02.922Z",
                  "created": "2025-09-01T14:02:02.922Z"
                }
              }
            }
          },
          "400": { "$ref": "#/components/responses/InvalidInput" },
          "404": { "$ref": "#/components/responses/NotFound" },
          "403": { "$ref": "#/components/responses/Forbidden" },
          "500": { "$ref": "#/components/responses/ServerError" }
        }
      }
    },
    "/routes/{id}/remove-orders": {
      "post": {
        "summary": "Remove Orders from a Route",
        "operationId": "removeOrdersFromRoute",
        "description": "Bulk-remove orders from a single route. The orders drop back to unrouted (their status returns to `OPEN`); they are not moved to another route. This is a partial-success bulk operation returning `{ orders, errors }` (the same envelope as `POST /orders`): one un-removable order never fails the rest of the batch.\n\nThe route id is given in the path (`/routes/{id}/remove-orders`) and scopes the whole call — every order must be on that route. Each order is identified by `id` (depot-scoped, preferred) and/or `order_number` — at least one is required per entry; if both are given they must resolve to the same order. An order that is not on the given route is reported as `NOT_ON_ROUTE`.\n\n`orders` and `errors` are NOT mutually exclusive. `orders` lists every order that resolved to a real record, each with the `stops` it was taken off (`{ id, route: { id } }`) — an empty `stops` array means nothing was removed from it. `errors` is a parallel list of problems; an order that exists but could not be removed (e.g. it is on a dispatched route, or not on the given route) appears in BOTH `orders` (with empty `stops`) and `errors`. An order reference that does not resolve at all (`ORDER_NOT_FOUND`) appears only in `errors`.\n\nEach `errors` entry is a `{ name, description, details }` envelope where `name` is the failure reason and `details` carries at least the `id` / `order_number`. Failure `name`s include `ORDER_NOT_FOUND`, `ID_NUMBER_MISMATCH`, `NOT_ON_ROUTE`, `ROUTE_DISPATCHED`, `ORDER_COMPLETED`, `STOP_REBUILD_FAILED`, `STALE_VISIT` and `REMOVAL_FAILED`. By default orders on dispatched (live) routes are reported as `ROUTE_DISPATCHED`; set `settings.allow_dispatched` to `true` to edit live routes.\n\nSet `settings.reoptimize` to `true` to re-sequence each affected route after the removal. This runs synchronously — the request blocks until each affected route has been solved and applied, so it can take seconds to minutes. The removal is applied first and the affected route is then re-sequenced. A reoptimised order is returned in `orders` with the `stops` it was taken off, the same as a normal removal. If the removal itself fails the order is reported with `REMOVAL_FAILED` (as in a non-reoptimise call); if only the re-sequencing step fails after the order was already removed, the order still counts as removed (returned in `orders`) and the re-sequencing failure is not surfaced per order.\n\nMulti-order (consolidated) stops are handled per stop: if every order on the stop is being removed the whole stop is deleted, otherwise the stop is kept and rebuilt with just the remaining orders (the removed order drops to `OPEN`, the others are unaffected). In the rare case the remaining orders cannot be re-consolidated into a single stop, that order is reported with `STOP_REBUILD_FAILED` and the stop is left untouched.",
        "tags": [
          "Routes"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Route id every order must belong to; scopes the whole call.",
            "schema": { "type": "integer", "example": 4567 }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "orders"
                ],
                "properties": {
                  "orders": {
                    "type": "array",
                    "description": "1..10 order references to remove.",
                    "minItems": 1,
                    "maxItems": 10,
                    "items": {
                      "type": "object",
                      "description": "An order reference. Provide `id` and/or `order_number` (at least one).",
                      "properties": {
                        "id": {
                          "type": "integer",
                          "description": "Order id (depot-scoped). Preferred when present.",
                          "example": 123
                        },
                        "order_number": {
                          "type": "string",
                          "maxLength": 50,
                          "description": "Order number. Used when `id` is absent.",
                          "example": "ABC123"
                        }
                      }
                    }
                  },
                  "settings": {
                    "type": "object",
                    "properties": {
                      "allow_dispatched": {
                        "type": "boolean",
                        "default": false,
                        "description": "When false (default) orders on dispatched routes are skipped (`ROUTE_DISPATCHED`). When true, dispatched routes are edited."
                      },
                      "reoptimize": {
                        "type": "boolean",
                        "default": false,
                        "description": "When true, each affected route is re-sequenced after the removal. This runs synchronously: the request blocks until the route has been solved and applied, so it can take seconds to minutes. The removal is applied first; if the re-sequencing step then fails, the order still counts as removed (returned in `orders`) and the re-sequencing failure is not surfaced. A failure to remove the order is reported with `REMOVAL_FAILED`, as in a non-reoptimise call."
                      }
                    }
                  }
                }
              },
              "example": {
                "orders": [
                  {
                    "id": 123,
                    "order_number": "ABC123"
                  },
                  {
                    "order_number": "DEF456"
                  }
                ],
                "settings": {
                  "allow_dispatched": false
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Bulk result. `orders` lists every resolved order (with the stops it was taken off); `errors` is a parallel list of problems and may reference an order also present in `orders`. Returned for fully-successful and mixed batches alike.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "orders": {
                      "type": "array",
                      "description": "Every order that resolved to a real record. An empty `stops` array means nothing was removed from it (look it up in `errors` for the reason).",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": { "type": "integer", "description": "Order id." },
                          "order_number": { "type": "string", "description": "Order number." },
                          "stops": {
                            "type": "array",
                            "description": "The stop(s) the order was taken off; empty when nothing was removed.",
                            "items": {
                              "type": "object",
                              "properties": {
                                "id": { "type": "integer", "description": "Stop (visit) id the order was removed from." },
                                "route": {
                                  "type": "object",
                                  "properties": {
                                    "id": { "type": "integer", "description": "Route id the stop belonged to." }
                                  }
                                }
                              }
                            }
                          }
                        }
                      }
                    },
                    "errors": {
                      "type": "array",
                      "description": "Orders that could not be removed.",
                      "items": {
                        "type": "object",
                        "properties": {
                          "name": { "type": "string", "description": "Failure reason code (e.g. `ROUTE_DISPATCHED`, `NOT_ON_ROUTE`)." },
                          "description": { "type": "string", "description": "Human-readable explanation." },
                          "details": {
                            "type": "object",
                            "description": "At least `id` and `order_number`; may carry extra context (e.g. `route_id`, `route_ids`).",
                            "properties": {
                              "id": { "type": "integer", "nullable": true },
                              "order_number": { "type": "string", "nullable": true }
                            }
                          }
                        }
                      }
                    }
                  }
                },
                "example": {
                  "orders": [
                    {
                      "id": 123,
                      "order_number": "ABC123",
                      "stops": [
                        { "id": 88901, "route": { "id": 4567 } }
                      ]
                    },
                    {
                      "id": 456,
                      "order_number": "DEF456",
                      "stops": []
                    }
                  ],
                  "errors": [
                    {
                      "name": "NOT_ON_ROUTE",
                      "description": "Order is not on the specified route.",
                      "details": { "id": 456, "order_number": "DEF456", "route_id": 4567 }
                    },
                    {
                      "name": "ORDER_NOT_FOUND",
                      "description": "No order was found for the provided identifier.",
                      "details": { "id": null, "order_number": "GHI789" }
                    }
                  ]
                }
              }
            }
          },
          "400": { "$ref": "#/components/responses/InvalidInput" },
          "403": { "$ref": "#/components/responses/Forbidden" },
          "404": { "$ref": "#/components/responses/NotFound" },
          "500": { "$ref": "#/components/responses/ServerError" }
        }
      }
    },
    "/orders/order-number/{order_number}": {
      "delete": {
        "summary": "Delete Orders by Order Number",
        "operationId": "deleteOrdersByOrderNumber",
        "description": "Delete orders based on order number.",
        "tags": [
          "Orders"
        ],
        "parameters": [
          {
            "in": "path",
            "name": "order_number",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Order number to delete orders."
          }
        ],
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "example": {
                  "deleted": {
                    "orders_count": 5,
                    "line_items_count": 15
                  }
                }
              }
            }
          },
          "404": { "$ref": "#/components/responses/NotFound" },
          "403": { "$ref": "#/components/responses/Forbidden" },
          "500": { "$ref": "#/components/responses/ServerError" }
        }
      }
    },
    "/plans/optimise/orders": {
      "post": {
        "summary": "Optimise Orders",
        "operationId": "optimisePlanForDate",
        "description": "Async optimisation. Returns 200 immediately with a Plan id and an optimisation job id. The optimisation runs in the background; poll `GET /plans/{id}` to check progress.\n\n**Initial response:** `{ \"optimisation\": { \"id\": \"<uuid>\", \"in_progress\": true }, \"plan\": { \"id\": <integer>, \"dispatched\": false } }`\n\n**Polling** — `GET /plans/{id}`:\n- *Completed:* `plan.routes` is non-empty (or `plan.unserved` is non-empty if no routes are viable). Either signals the optimisation has finished.\n- *Still running:* `plan.routes` and `plan.unserved` are both empty.\n- *Failed:* there is no terminal failure signal on the Plan resource today. A failed job leaves the Plan in the same \"empty arrays\" state as a still-running job. Implement a client-side hard timeout — recommended **10 minutes** — after which the job should be considered abandoned.\n\n**Recommended polling cadence:**\n- First minute: every 2 seconds.\n- After 1 minute: every 10 seconds, exponential backoff up to 30 seconds.\n- Hard timeout: 10 minutes total.\n\n**Webhook coupling:** the `plans.created` webhook fires immediately after the Plan is persisted — *before* the optimisation job has completed. A webhook delivery does not imply the optimisation finished. Consumers receiving `plans.created` should still poll `GET /plans/{id}` to learn the outcome.\n\n**Concurrency limits per depot** (queue, not timeout): STANDARD 100, LONG 100, DIST 7, BOOKING_CHECK 1. No documented per-job timeout; typical jobs complete in 5–30 seconds.\n\n**Idempotency:** Supports the `idempotency-key` request header for safe retries. See the Idempotency section in the API description.",
        "tags": [
          "Plans"
        ],
        "parameters": [
          { "$ref": "#/components/parameters/IdempotencyKeyHeader" }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "delivery_date": {
                    "type": "string",
                    "format": "date",
                    "description": "The delivery date YYYY-MM-DD for optimizing orders."
                  },
                  "plan": {
                    "type": "object",
                    "properties": {
                      "id": {
                        "type": "integer",
                        "description": "You can provide a plan id to re-use for generating your route"
                      },
                      "name": {
                        "type": "string",
                        "description": "Provide a name for the plan. This will override the existing plan name if an id is provided."
                      }
                    }
                  },
                  "settings": {
                    "type": "object",
                    "properties": {
                      "active_vehicles": {
                        "type": "boolean",
                        "description": "Flag to include only active vehicles."
                      },
                      "auto_dispatch": {
                        "type": "boolean",
                        "description": "Flag for auto_dispatch."
                      }
                    },
                    "required": [
                      "active_vehicles",
                      "auto_dispatch"
                    ]
                  },
                  "vehicles": {
                    "nullable": true,
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "integer",
                          "description": "ID of the vehicle."
                        },
                        "name": {
                          "type": "string",
                          "description": "Name of the vehicle."
                        },
                        "availability": {
                          "type": "string",
                          "description": "Availability status of the vehicle.",
                          "enum": [
                            "shift",
                            "full_day",
                            "always"
                          ]
                        },
                        "shift_start": {
                          "type": "string",
                          "format": "time",
                          "nullable": true,
                          "description": "Start time of the vehicle's shift (if availability is 'shift')."
                        },
                        "shift_end": {
                          "type": "string",
                          "format": "time",
                          "nullable": true,
                          "description": "End time of the vehicle's shift (if availability is 'shift')."
                        },
                        "start_location": {
                          "type": "string",
                          "description": "Location type where the vehicle starts.",
                          "enum": [
                            "depot",
                            "other",
                            "app-location"
                          ]
                        },
                        "start_address": {
                          "type": "string",
                          "nullable": true,
                          "description": "Address where the vehicle starts (if location is 'other')."
                        },
                        "start_lng": {
                          "type": "number",
                          "nullable": true,
                          "description": "Longitude of the starting location (if location is 'other')."
                        },
                        "start_lat": {
                          "type": "number",
                          "nullable": true,
                          "description": "Latitude of the starting location (if location is 'other')."
                        },
                        "end_location": {
                          "type": "string",
                          "description": "Location type where the vehicle ends.",
                          "enum": [
                            "depot",
                            "other",
                            "none"
                          ]
                        },
                        "end_address": {
                          "type": "string",
                          "nullable": true,
                          "description": "Address where the vehicle ends (if location is 'other')."
                        },
                        "end_lng": {
                          "type": "number",
                          "nullable": true,
                          "description": "Longitude of the ending location (if location is 'other')."
                        },
                        "end_lat": {
                          "type": "number",
                          "nullable": true,
                          "description": "Latitude of the ending location (if location is 'other')."
                        },
                        "break": {
                          "type": "boolean",
                          "description": "Flag indicating whether the vehicle has a break."
                        },
                        "break_start": {
                          "type": "string",
                          "format": "time",
                          "nullable": true,
                          "description": "Start time of the vehicle's break (if it has a break)."
                        },
                        "break_end": {
                          "type": "string",
                          "format": "time",
                          "nullable": true,
                          "description": "End time of the vehicle's break (if it has a break)."
                        },
                        "break_duration": {
                          "type": "number",
                          "nullable": true,
                          "description": "Duration of the vehicle's break in minutes (if it has a break)."
                        },
                        "active": {
                          "type": "boolean",
                          "description": "Flag indicating whether the vehicle is active."
                        },
                        "skills": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "description": "Array of skills associated with the vehicle."
                        },
                        "capacities": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "id": {
                                "type": "integer",
                                "description": "Id of capacity (e.g., 1, 2)."
                              },
                              "capacity": {
                                "type": "number",
                                "format": "float",
                                "description": "Capacity value for the specified type."
                              }
                            },
                            "required": [
                              "id",
                              "capacity"
                            ],
                            "description": "Details of each capacity associated with the vehicle."
                          },
                          "description": "Array of capacities associated with the vehicle."
                        }
                      },
                      "required": [
                        "id",
                        "availability",
                        "start_location",
                        "end_location"
                      ],
                      "description": "Override details of a vehicle for this optimisation request."
                    }
                  },
                  "zone_group_id": {
                    "type": "integer",
                    "description": "The ID of the zone group for optimization."
                  }
                },
                "required": [
                  "delivery_date",
                  "settings"
                ]
              },
              "example": {
                "delivery_date": "2023-12-31",
                "settings": {
                  "active_vehicles": true,
                  "auto_dispatch": true
                },
                "zone_group_id": 123
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Optimisation accepted and Plan created. The optimisation runs asynchronously; poll `GET /plans/{id}` for completion.",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/PlanOptimisationResponse" },
                "example": {
                  "optimisation": {
                    "id": "123e4567-e89b-12d3-a456-426614174001",
                    "in_progress": true
                  },
                  "plan": {
                    "id": 123,
                    "dispatched": true
                  }
                }
              }
            },
            "headers": {
              "idempotency-replay": { "$ref": "#/components/headers/IdempotencyReplay" }
            }
          },
          "400": { "$ref": "#/components/responses/InvalidInput" },
          "409": { "$ref": "#/components/responses/IdempotencyRequestInProgress" },
          "422": { "$ref": "#/components/responses/IdempotencyKeyReusedWithDifferentBody" },
          "403": { "$ref": "#/components/responses/Forbidden" },
          "500": { "$ref": "#/components/responses/ServerError" }
        }
      }
    },
    "/plans/optimise/orders-for-ids": {
      "post": {
        "summary": "Optimise Orders For IDs",
        "operationId": "optimisePlanForOrderIds",
        "description": "Async optimisation for a specific set of order IDs. Same lifecycle and polling semantics as `POST /plans/optimise/orders` — see that endpoint's description for completion detection, polling cadence, and the failure-signal gap. Supports the `idempotency-key` request header for safe retries.",
        "tags": [
          "Plans"
        ],
        "parameters": [
          { "$ref": "#/components/parameters/IdempotencyKeyHeader" }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "orders": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "number",
                          "description": "ID of the order"
                        }
                      }
                    }
                  },
                  "plan": {
                    "type": "object",
                    "properties": {
                      "id": {
                        "type": "integer",
                        "description": "You can provide a plan id to re-use for generating your route"
                      },
                      "name": {
                        "type": "string",
                        "description": "Provide a name for the plan. This will override the existing plan name if an id is provided."
                      },
                      "date": {
                        "type": "string",
                        "format": "date",
                        "description": "The date of your plan. Format YYYY-MM-DD"
                      }
                    }
                  },
                  "settings": {
                    "type": "object",
                    "properties": {
                      "active_vehicles": {
                        "type": "boolean",
                        "description": "Flag to include only active vehicles."
                      },
                      "auto_dispatch": {
                        "type": "boolean",
                        "description": "Flag for auto_dispatch."
                      }
                    },
                    "required": [
                      "active_vehicles",
                      "auto_dispatch"
                    ]
                  },
                  "vehicles": {
                    "nullable": true,
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "integer",
                          "description": "ID of the vehicle."
                        },
                        "name": {
                          "type": "string",
                          "description": "Name of the vehicle."
                        },
                        "availability": {
                          "type": "string",
                          "description": "Availability status of the vehicle.",
                          "enum": [
                            "shift",
                            "full_day",
                            "always"
                          ]
                        },
                        "shift_start": {
                          "type": "string",
                          "format": "time",
                          "nullable": true,
                          "description": "Start time of the vehicle's shift (if availability is 'shift')."
                        },
                        "shift_end": {
                          "type": "string",
                          "format": "time",
                          "nullable": true,
                          "description": "End time of the vehicle's shift (if availability is 'shift')."
                        },
                        "start_location": {
                          "type": "string",
                          "description": "Location type where the vehicle starts.",
                          "enum": [
                            "depot",
                            "other",
                            "app-location"
                          ]
                        },
                        "start_address": {
                          "type": "string",
                          "nullable": true,
                          "description": "Address where the vehicle starts (if location is 'other')."
                        },
                        "start_lng": {
                          "type": "number",
                          "nullable": true,
                          "description": "Longitude of the starting location (if location is 'other')."
                        },
                        "start_lat": {
                          "type": "number",
                          "nullable": true,
                          "description": "Latitude of the starting location (if location is 'other')."
                        },
                        "end_location": {
                          "type": "string",
                          "description": "Location type where the vehicle ends.",
                          "enum": [
                            "depot",
                            "other",
                            "none"
                          ]
                        },
                        "end_address": {
                          "type": "string",
                          "nullable": true,
                          "description": "Address where the vehicle ends (if location is 'other')."
                        },
                        "end_lng": {
                          "type": "number",
                          "nullable": true,
                          "description": "Longitude of the ending location (if location is 'other')."
                        },
                        "end_lat": {
                          "type": "number",
                          "nullable": true,
                          "description": "Latitude of the ending location (if location is 'other')."
                        },
                        "break": {
                          "type": "boolean",
                          "description": "Flag indicating whether the vehicle has a break."
                        },
                        "break_start": {
                          "type": "string",
                          "format": "time",
                          "nullable": true,
                          "description": "Start time of the vehicle's break (if it has a break)."
                        },
                        "break_end": {
                          "type": "string",
                          "format": "time",
                          "nullable": true,
                          "description": "End time of the vehicle's break (if it has a break)."
                        },
                        "break_duration": {
                          "type": "number",
                          "nullable": true,
                          "description": "Duration of the vehicle's break in minutes (if it has a break)."
                        },
                        "active": {
                          "type": "boolean",
                          "description": "Flag indicating whether the vehicle is active."
                        },
                        "skills": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "description": "Array of skills associated with the vehicle."
                        },
                        "capacities": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "id": {
                                "type": "integer",
                                "description": "Id of capacity (e.g., 1, 2)."
                              },
                              "capacity": {
                                "type": "number",
                                "format": "float",
                                "description": "Capacity value for the specified type."
                              }
                            },
                            "required": [
                              "id",
                              "capacity"
                            ],
                            "description": "Details of each capacity associated with the vehicle."
                          },
                          "description": "Array of capacities associated with the vehicle."
                        }
                      },
                      "required": [
                        "id",
                        "availability",
                        "start_location",
                        "end_location"
                      ],
                      "description": "Override details of a vehicle for this optimisation request."
                    }
                  },
                  "zone_group_id": {
                    "type": "integer",
                    "description": "The ID of the zone group for optimization."
                  }
                },
                "required": [
                  "settings",
                  "orders"
                ]
              },
              "example": {
                "orders": [
                  {
                    "id": 456
                  },
                  {
                    "id": 789
                  }
                ],
                "settings": {
                  "active_vehicles": true,
                  "auto_dispatch": true
                },
                "zone_group_id": 123
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Optimisation accepted and Plan created. The optimisation runs asynchronously; poll `GET /plans/{id}` for completion.",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/PlanOptimisationResponse" },
                "example": {
                  "optimisation": {
                    "id": "123e4567-e89b-12d3-a456-426614174001",
                    "in_progress": true
                  },
                  "plan": {
                    "id": 123,
                    "dispatched": true
                  }
                }
              }
            },
            "headers": {
              "idempotency-replay": { "$ref": "#/components/headers/IdempotencyReplay" }
            }
          },
          "400": { "$ref": "#/components/responses/InvalidInput" },
          "404": { "$ref": "#/components/responses/NotFound" },
          "409": { "$ref": "#/components/responses/IdempotencyRequestInProgress" },
          "422": { "$ref": "#/components/responses/IdempotencyKeyReusedWithDifferentBody" },
          "403": { "$ref": "#/components/responses/Forbidden" },
          "500": { "$ref": "#/components/responses/ServerError" }
        }
      }
    },
    "/plans/optimise/{id}": {
      "get": {
        "summary": "Get Optimisation Job by ID",
        "operationId": "getOptimisationJobById",
        "description": "Retrieve the status of a plan optimisation by UUID.",
        "tags": [
          "Plans"
        ],
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "ID of the current optimisation to retrieve."
          }
        ],
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/PlanOptimisationResponse" },
                "example": {
                  "optimisation": {
                    "id": "123e4567-e89b-12d3-a456-426614174001",
                    "in_progress": false
                  },
                  "plan": {
                    "id": 123,
                    "dispatched": true
                  }
                }
              }
            }
          },
          "404": { "$ref": "#/components/responses/NotFound" },
          "403": { "$ref": "#/components/responses/Forbidden" },
          "500": { "$ref": "#/components/responses/ServerError" }
        }
      }
    },
    "/plans/{id}": {
      "get": {
        "summary": "Get Plan by ID",
        "operationId": "getPlanById",
        "description": "Retrieve a Plan based on ID. When the plan was just created via the optimise endpoint and the optimisation job has not finished, `routes` and `unserved` are both empty arrays — see the async optimise endpoint description for polling guidance and failure-signal limitations.",
        "tags": [
          "Plans"
        ],
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "number"
            },
            "description": "ID of the plan to retrieve."
          }
        ],
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/PlanResponse" },
                "example": {
                  "plan": {
                    "id": 123,
                    "total_time": 120,
                    "routes": [
                      {
                        "id": 1234,
                        "name": "Route 1",
                        "date": "2023-12-12",
                        "start_time": "08:00",
                        "started_ts": "2024-07-09T09:00:00.000Z",
                        "end_time": "16:00",
                        "completed_ts": "2024-07-09T17:18:40.000Z",
                        "total_time": 120,
                        "travel_time": 90,
                        "planned_distance": 50,
                        "actual_distance": 45,
                        "vehicle": {
                          "vehicle_id": "vehicle-1",
                          "name": "Vehicle A",
                          "driver": "John Doe"
                        },
                        "stops": [
                          {
                            "id": 123,
                            "route_id": 456,
                            "address": "123 Main St",
                            "phone": "555-1234",
                            "lat": 12.345,
                            "lng": -45.678,
                            "planned_distance": 1234.5,
                            "arrival_date": "2023-12-31",
                            "departure_date": "2023-12-31",
                            "delivery_notes": "Leave at the doorstep",
                            "driver_notes": "Customer not available initially",
                            "estimated_arrival_time": "09:00",
                            "estimated_departure_time": "10:00",
                            "actual_completed_ts": "2023-12-31T10:15:00",
                            "actual_arrival_time": "2023-12-31T09:15:00",
                            "actual_completed_lat": 12.345,
                            "actual_completed_lng": -45.678,
                            "actual_duration": 60,
                            "signature": "https://api.smartroutes.io/v2/proof-of-delivery/signatures/111486",
                            "signature_lat": 12.345,
                            "signature_lng": -45.678,
                            "signed_by": "John",
                            "tracking_link": "https://tracksr.io/xyzabc",
                            "photos": [
                              "https://api.smartroutes.io/v2/proof-of-delivery/photos/491548"
                            ],
                            "orders": [
                              {
                                "id": 123,
                                "order_number": "ORD123",
                                "custom_fields": {
                                  "id": 789,
                                  "value": "Example Value",
                                  "name": "Example Custom Field"
                                },
                                "type": "delivery",
                                "line_items": [
                                  {
                                    "id": 456,
                                    "product_code": "1",
                                    "product_name": "1",
                                    "quantity": 10,
                                    "status": "OPEN",
                                    "date": "2024-01-12",
                                    "custom_fields": [
                                      {
                                        "id": 123,
                                        "value": "Value 1",
                                        "name": "Custom Field 1"
                                      }
                                    ]
                                  }
                                ]
                              }
                            ],
                            "vehicle_assignment": {
                              "vehicle_id": 45321
                            },
                            "emails": [
                              {
                                "email": "example@email.com"
                              },
                              {
                                "email": "example2@email.com"
                              }
                            ],
                            "driver_questionnaire_submissions": [
                              {
                                "id": 1267,
                                "driver_questionnaire": {
                                  "type": "VISIT",
                                  "title": "Stop Questionaire"
                                }
                              }
                            ],
                            "failed_reason": {
                              "reason": "Wrong Parcel"
                            },
                            "tags": [
                              "Tag1",
                              "Tag2"
                            ],
                            "available_days": ["MONDAY", "THURSDAY"]
                          }
                        ]
                      }
                    ],
                    "unserved": [
                      {
                        "id": 123,
                        "address": "456 Oak St",
                        "postcode": "67890",
                        "phone": "555-5678",
                        "lat": 40.5678,
                        "lng": -75.1234,
                        "delivery_notes": "Delivery notes for unserved visit",
                        "available_days": ["MONDAY, THURSDAY"]
                      }
                    ],
                    "created": "2022-04-29T16:12:08.000Z",
                    "updated": "2022-09-29T10:11:06.000Z",
                    "driver_questionnaire_submissions": [
                      {
                        "id": 1266,
                        "driver_questionnaire": {
                          "type": "ROUTE_VEHICLE_CHECKIN",
                          "title": "Route Start Questionnaire"
                        }
                      },
                      {
                        "id": 1268,
                        "driver_questionnaire": {
                          "type": "ROUTE_VEHICLE_CHECKIN",
                          "title": "Completed Questionnaire"
                        }
                      }
                    ]
                  }
                }
              }
            }
          },
          "404": { "$ref": "#/components/responses/NotFound" },
          "403": { "$ref": "#/components/responses/Forbidden" },
          "500": { "$ref": "#/components/responses/ServerError" }
        }
      },
      "delete": {
        "summary": "Delete Plan by ID",
        "operationId": "deletePlanById",
        "description": "Delete a plan based on ID.",
        "tags": [
          "Plans"
        ],
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "number"
            },
            "description": "ID of the plan to delete."
          }
        ],
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "example": {
                  "deleted": {
                    "plans_count": 1
                  }
                }
              }
            }
          },
          "404": { "$ref": "#/components/responses/NotFound" },
          "403": { "$ref": "#/components/responses/Forbidden" },
          "500": { "$ref": "#/components/responses/ServerError" }
        }
      }
    },
    "/plans": {
      "get": {
        "summary": "Get Plans Page",
        "operationId": "listPlans",
        "description": "Endpoint to retrieve a page of plans.",
        "tags": [
          "Plans"
        ],
        "parameters": [
          {
            "in": "query",
            "name": "page_info",
            "required": false,
            "schema": {
              "type": "string",
              "description": "Information about the page for pagination. Generated by the OpenAPI"
            },
            "description": "Information about the page for pagination. Generated by the OpenAPI"
          },
          {
            "in": "query",
            "name": "updated_at_min",
            "required": false,
            "schema": {
              "type": "string",
              "format": "date-time",
              "description": "Minimum updated date and time for filtering."
            },
            "description": "Minimum updated date and time for filtering."
          },
          {
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "type": "integer",
              "default": 100,
              "description": "Maximum number of plans to retrieve per page."
            },
            "description": "Maximum number of plans to retrieve per page."
          }
        ],
        "responses": {
          "200": {
            "description": "Successful response",
            "headers": {
              "link": {
                "description": "Link to the next page of plans. Use with the page_info parameter for pagination.",
                "schema": {
                  "type": "string"
                },
                "example": "<https://api.smartroutes.io/v2/plans?page_info=PAGE_INFO_STRING&limit=100>; rel=next"
              }
            },
            "content": {
              "application/json": {
                "example": {
                  "plans": [
                    {
                      "id": 123,
                      "dispatched": true,
                      "created": "2024-07-08T17:33:37.000Z",
                      "updated": "2024-07-08T17:33:37.000Z",
                      "total_time": 120,
                      "routes": [
                        {
                          "id": 1234,
                          "name": "Route 1",
                          "stops": 4,
                          "dispatched": true,
                          "started_ts": "2024-07-09T09:00:00.000Z",
                          "completed_ts": "2024-07-09T17:18:40.000Z",
                          "total_time": "595",
                          "travel_time": "475",
                          "operation_time": "120",
                          "date": "2024-07-11",
                          "distance": 100,
                          "actual_distance": null,
                          "created": "2024-07-08T17:18:40.000Z",
                          "updated": "2024-07-08T17:18:40.000Z"
                        }
                      ]
                    },
                    {
                      "id": 124,
                      "dispatched": true,
                      "created": "2024-07-08T17:33:37.000Z",
                      "updated": "2024-07-08T17:33:37.000Z",
                      "total_time": 120,
                      "routes": [
                        {
                          "id": 1235,
                          "name": "Route 2",
                          "stops": 4,
                          "dispatched": true,
                          "started_ts": "2024-07-09T09:00:00.000Z",
                          "completed_ts": "2024-07-09T17:18:40.000Z",
                          "total_time": "595",
                          "travel_time": "475",
                          "operation_time": "120",
                          "date": "2024-07-11",
                          "distance": 100,
                          "actual_distance": null,
                          "created": "2024-07-08T17:18:40.000Z",
                          "updated": "2024-07-08T17:18:40.000Z"
                        }
                      ]
                    }
                  ]
                }
              }
            }
          },
          "400": { "$ref": "#/components/responses/InvalidInput" },
          "403": { "$ref": "#/components/responses/Forbidden" },
          "500": { "$ref": "#/components/responses/ServerError" }
        }
      }
    },
    "/routes/{id}": {
      "get": {
        "summary": "Get Route by ID",
        "operationId": "getRouteById",
        "description": "Retrieve a route based on ID.",
        "tags": [
          "Routes"
        ],
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "number"
            },
            "description": "ID of the route to retrieve."
          }
        ],
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/RouteResponse" },
                "example": {
                  "id": 12345,
                  "plan_id": 67,
                  "name": "Route 1",
                  "dispatched": true,
                  "date": "2023-12-31",
                  "start_time": "08:00",
                  "started_ts": "2024-07-09T09:00:00.000Z",
                  "end_time": "16:00",
                  "completed_ts": "2024-07-09T17:18:40.000Z",
                  "total_time": 480,
                  "travel_time": 300,
                  "planned_distance": 50,
                  "actual_distance": 45,
                  "vehicle": {
                    "vehicle_id": "vehicle_456",
                    "name": "Delivery Van",
                    "driver": "John Doe"
                  },
                  "stops": [
                    {
                      "id": 123,
                      "route_id": 135,
                      "address": "123 Main St",
                      "phone": "555-1234",
                      "lat": 12.345,
                      "lng": -45.678,
                      "planned_distance": 1234.5,
                      "arrival_date": "2023-12-31",
                      "departure_date": "2023-12-31",
                      "delivery_notes": "Leave at the doorstep",
                      "driver_notes": "Customer not available initially",
                      "estimated_arrival_time": "09:00",
                      "estimated_departure_time": "10:00",
                      "actual_completed_ts": "2023-12-31T10:15:00",
                      "actual_completed_lat": 12.345,
                      "actual_completed_lng": -45.678,
                      "actual_arrival_time": "2023-12-31T09:15:00",
                      "actual_duration": 60,
                      "signature": "https://api.smartroutes.io/v2/proof-of-delivery/signatures/111486",
                      "signature_lat": 12.345,
                      "signature_lng": -45.678,
                      "signed_by": "John",
                      "tracking_link": "https://tracksr.io/xyzabc",
                      "photos": [
                        "https://api.smartroutes.io/v2/proof-of-delivery/photos/491548"
                      ],
                      "orders": [
                        {
                          "id": 123,
                          "order_number": "ORD123",
                          "type": "delivery",
                          "line_items": [
                            {
                              "id": 456,
                              "product_code": "1",
                              "product_name": "1",
                              "quantity": 10,
                              "status": "OPEN",
                              "date": "2024-01-12",
                              "custom_fields": [
                                {
                                  "id": 123,
                                  "value": "Value 1",
                                  "name": "Custom Field 1"
                                }
                              ]
                            }
                          ]
                        }
                      ],
                      "vehicle_assignment": {
                        "vehicle_id": 1958
                      },
                      "emails": [
                        {
                          "email": "example@email.com"
                        },
                        {
                          "email": "example2@email.com"
                        }
                      ],
                      "driver_questionnaire_submissions": [
                        {
                          "id": 1267,
                          "driver_questionnaire": {
                            "type": "VISIT",
                            "title": "Stop Questionnaire"
                          }
                        }
                      ],
                      "failed_reason": {
                        "reason": "Wrong Parcel"
                      },
                      "tags":[
                        "Tag1",
                        "Tag2"
                      ],
                      "available_days": ["MONDAY", "WEDNESDAY", "THURSDAY"]
                    }
                  ],
                  "created": "2024-06-19T08:56:43.000Z",
                  "updated": "2024-06-19T08:56:43.000Z",
                  "driver_questionnaire_submissions": [
                    {
                      "id": 1266,
                      "driver_questionnaire": {
                        "type": "ROUTE_VEHICLE_CHECKIN",
                        "title": "Route Start Questionnaire"
                      }
                    },
                    {
                      "id": 1268,
                      "driver_questionnaire": {
                        "type": "ROUTE_VEHICLE_CHECKIN",
                        "title": "Completed Questionnaire"
                      }
                    }
                  ]
                }
              }
            }
          },
          "404": { "$ref": "#/components/responses/NotFound" },
          "403": { "$ref": "#/components/responses/Forbidden" },
          "500": { "$ref": "#/components/responses/ServerError" }
        }
      }
    },
    "/routes/{id}/reverse": {
      "post": {
        "summary": "Reverse Route by ID",
        "operationId": "reverseRouteById",
        "description": "Reverse a route based on ID.",
        "tags": [
          "Routes"
        ],
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "number"
            },
            "description": "ID of the route to reverse."
          }
        ],
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "example": {
                  "id": 12345,
                  "plan_id": 67,
                  "name": "Route 1",
                  "date": "2023-12-31",
                  "start_time": "08:00",
                  "started_ts": "2024-07-09T09:00:00.000Z",
                  "end_time": "16:00",
                  "completed_ts": "2024-07-09T17:18:40.000Z",
                  "total_time": 480,
                  "travel_time": 300,
                  "planned_distance": 50,
                  "actual_distance": 45,
                  "vehicle": {
                    "vehicle_id": "vehicle_456",
                    "name": "Delivery Van",
                    "driver": "John Doe"
                  },
                  "stops": [
                    {
                      "id": 123,
                      "route_id": 456,
                      "address": "123 Main St",
                      "phone": "555-1234",
                      "lat": 12.345,
                      "lng": -45.678,
                      "planned_distance": 1278.2,
                      "arrival_date": "2023-12-31",
                      "departure_date": "2023-12-31",
                      "delivery_notes": "Leave at the doorstep",
                      "driver_notes": "Customer not available initially",
                      "estimated_arrival_time": "09:00",
                      "estimated_departure_time": "10:00",
                      "actual_completed_ts": "2023-12-31T10:15:00",
                      "actual_arrival_time": "2023-12-31T09:15:00",
                      "actual_completed_lat": 12.345,
                      "actual_completed_lng": -45.678,
                      "actual_duration": 60,
                      "signature": "https://api.smartroutes.io/v2/proof-of-delivery/signatures/111486",
                      "signature_lng": -45.678,
                      "signature_lat": 12.345,
                      "signed_by": "John",
                      "tracking_link": "https://tracksr.io/xyzabc",
                      "photos": [
                        "https://api.smartroutes.io/v2/proof-of-delivery/photos/491548"
                      ],
                      "orders": [
                        {
                          "id": 123,
                          "order_number": "ORD123"
                        }
                      ],
                      "vehicle_assignment": null,
                      "driver_questionnaire_submissions": [
                        {
                          "id": 1270,
                          "driver_questionnaire": {
                            "type": "VISIT",
                            "title": "Stop Questionaire"
                          }
                        }
                      ],
                      "tags": [
                        "Tag1",
                        "Tag2"
                      ]
                    }
                  ]
                }
              }
            }
          },
          "404": { "$ref": "#/components/responses/NotFound" },
          "403": { "$ref": "#/components/responses/Forbidden" },
          "500": { "$ref": "#/components/responses/ServerError" }
        }
      }
    },
    "/routes": {
      "get": {
        "summary": "Get Routes Page",
        "operationId": "listRoutes",
        "description": "Endpoint to retrieve a page of routes.",
        "tags": [
          "Routes"
        ],
        "parameters": [
          {
            "in": "query",
            "name": "page_info",
            "required": false,
            "schema": {
              "type": "string",
              "description": "Information about the page for pagination. Generated by the OpenAPI"
            },
            "description": "Information about the page for pagination. Generated by the OpenAPI"
          },
          {
            "in": "query",
            "name": "updated_at_min",
            "required": false,
            "schema": {
              "type": "string",
              "format": "date-time",
              "description": "Minimum updated date and time for filtering."
            },
            "description": "Minimum updated date and time for filtering."
          },
          {
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "type": "integer",
              "default": 100,
              "description": "Maximum number of routes to retrieve per page."
            },
            "description": "Maximum number of routes to retrieve per page."
          }
        ],
        "responses": {
          "200": {
            "description": "Successful response",
            "headers": {
              "link": {
                "description": "Link to the next page of routes. Use with the page_info parameter for pagination.",
                "schema": {
                  "type": "string"
                },
                "example": "<https://api.smartroutes.io/v2/routes?page_info=PAGE_INFO_STRING&limit=100>; rel=next"
              }
            },
            "content": {
              "application/json": {
                "example": {
                  "routes": [
                    {
                      "id": 12345,
                      "plan_id": 67,
                      "name": "Route 1",
                      "stops": 5,
                      "dispatched": true,
                      "started_ts": "2024-07-09T09:00:00.000Z",
                      "completed_ts": "2024-07-09T17:18:40.000Z",
                      "date": "2023-12-31",
                      "start_time": "08:00",
                      "end_time": "16:00",
                      "total_time": 480,
                      "travel_time": 300,
                      "planned_distance": 50,
                      "actual_distance": 45,
                      "created": "2024-06-19T08:56:43.000Z",
                      "updated": "2024-06-19T08:56:43.000Z"
                    },
                    {
                      "id": 12346,
                      "plan_id": 89,
                      "name": "Route 2",
                      "stops": 5,
                      "dispatched": true,
                      "started_ts": "2024-07-09T09:00:00.000Z",
                      "completed_ts": "2024-07-09T16:38:40.000Z",
                      "date": "2023-12-31",
                      "start_time": "08:00",
                      "end_time": "16:00",
                      "total_time": 480,
                      "travel_time": 300,
                      "planned_distance": 50,
                      "actual_distance": 45,
                      "created": "2024-06-19T08:56:43.000Z",
                      "updated": "2024-06-19T08:56:43.000Z"
                    }
                  ]
                }
              }
            }
          },
          "400": { "$ref": "#/components/responses/InvalidInput" },
          "403": { "$ref": "#/components/responses/Forbidden" },
          "500": { "$ref": "#/components/responses/ServerError" }
        }
      }
    },
    "/third-parties": {
      "get": {
        "summary": "Get All Third Parties",
        "operationId": "listThirdParties",
        "description": "Endpoint to retrieve all third parties.",
        "tags": [
          "Third Parties"
        ],
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "example": {
                  "third-parties": [
                    {
                      "id": 134,
                      "name": "Third Party 1"
                    },
                    {
                      "id": 135,
                      "name": "Third Party 2"
                    }
                  ]
                }
              }
            }
          },
          "403": { "$ref": "#/components/responses/Forbidden" },
          "500": { "$ref": "#/components/responses/ServerError" }
        }
      }
    },
    "/vehicles": {
      "post": {
        "summary": "Add Vehicle",
        "operationId": "createVehicle",
        "description": "Endpoint to add a vehicle.",
        "tags": [
          "Vehicles"
        ],
        "parameters": [
          { "$ref": "#/components/parameters/IdempotencyKeyHeader" }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "description": "Name of the vehicle."
                  },
                  "availability": {
                    "type": "string",
                    "description": "Availability status of the vehicle.",
                    "enum": [
                      "shift",
                      "full_day",
                      "always"
                    ]
                  },
                  "shift_start": {
                    "type": "string",
                    "format": "time",
                    "nullable": true,
                    "description": "Start time of the vehicle's shift (if availability is 'shift')."
                  },
                  "shift_end": {
                    "type": "string",
                    "format": "time",
                    "nullable": true,
                    "description": "End time of the vehicle's shift (if availability is 'shift')."
                  },
                  "start_location": {
                    "type": "string",
                    "description": "Location type where the vehicle starts.",
                    "enum": [
                      "depot",
                      "other",
                      "app-location"
                    ]
                  },
                  "start_address": {
                    "type": "string",
                    "nullable": true,
                    "description": "Address where the vehicle starts (if location is 'other')."
                  },
                  "start_lng": {
                    "type": "number",
                    "nullable": true,
                    "description": "Longitude of the starting location (if location is 'other')."
                  },
                  "start_lat": {
                    "type": "number",
                    "nullable": true,
                    "description": "Latitude of the starting location (if location is 'other')."
                  },
                  "end_location": {
                    "type": "string",
                    "description": "Location type where the vehicle ends.",
                    "enum": [
                      "depot",
                      "other",
                      "none"
                    ]
                  },
                  "end_address": {
                    "type": "string",
                    "nullable": true,
                    "description": "Address where the vehicle ends (if location is 'other')."
                  },
                  "end_lng": {
                    "type": "number",
                    "nullable": true,
                    "description": "Longitude of the ending location (if location is 'other')."
                  },
                  "end_lat": {
                    "type": "number",
                    "nullable": true,
                    "description": "Latitude of the ending location (if location is 'other')."
                  },
                  "break": {
                    "type": "boolean",
                    "description": "Flag indicating whether the vehicle has a break."
                  },
                  "break_start": {
                    "type": "string",
                    "format": "time",
                    "nullable": true,
                    "description": "Start time of the vehicle's break (if it has a break)."
                  },
                  "break_end": {
                    "type": "string",
                    "format": "time",
                    "nullable": true,
                    "description": "End time of the vehicle's break (if it has a break)."
                  },
                  "break_duration": {
                    "type": "number",
                    "nullable": true,
                    "description": "Duration of the vehicle's break in minutes (if it has a break)."
                  },
                  "active": {
                    "type": "boolean",
                    "description": "Flag indicating whether the vehicle is active."
                  },
                  "skills": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "Array of skills associated with the vehicle."
                  },
                  "capacities": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "integer",
                          "description": "Id of capacity (e.g., 1, 2)."
                        },
                        "capacity": {
                          "type": "number",
                          "format": "float",
                          "description": "Capacity value for the specified type."
                        }
                      },
                      "required": [
                        "id",
                        "capacity"
                      ],
                      "description": "Details of each capacity associated with the vehicle."
                    },
                    "description": "Array of capacities associated with the vehicle."
                  }
                },
                "required": [
                  "availability",
                  "start_location",
                  "end_location"
                ],
                "description": "Request body for creating a new vehicle.",
                "example": {
                  "name": "Vehicle Name",
                  "availability": "shift",
                  "shift_start": "08:00",
                  "shift_end": "17:30",
                  "start_location": "depot",
                  "end_location": "none",
                  "break": false,
                  "capacities": [
                    {
                      "id": 1,
                      "capacity": 500
                    }
                  ]
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/VehicleResponse" },
                "example": {
                  "vehicle": {
                    "id": 123,
                    "name": "Vehicle Name",
                    "active": true,
                    "capacities": [
                      {
                        "id": 1,
                        "type": "Capacity Type 1",
                        "capacity": 10
                      },
                      {
                        "id": 2,
                        "type": "Capacity Type 2",
                        "capacity": 15
                      }
                    ],
                    "skills": [
                      "Skill 1",
                      "Skill 2"
                    ],
                    "availability": "shift",
                    "start_location": "other",
                    "end_location": "other",
                    "shift_start": "08:00",
                    "shift_end": "17:00",
                    "start_address": "Start Location Address",
                    "start_lat": 12.345678,
                    "start_lng": -23.456789,
                    "end_address": "End Location Address",
                    "end_lat": 34.567890,
                    "end_lng": -45.678901,
                    "break": true,
                    "break_start": "12:00",
                    "break_end": "12:30",
                    "break_duration": 30
                  }
                }
              }
            },
            "headers": {
              "idempotency-replay": { "$ref": "#/components/headers/IdempotencyReplay" }
            }
          },
          "400": { "$ref": "#/components/responses/InvalidInput" },
          "409": { "$ref": "#/components/responses/IdempotencyRequestInProgress" },
          "422": { "$ref": "#/components/responses/IdempotencyKeyReusedWithDifferentBody" },
          "403": { "$ref": "#/components/responses/Forbidden" },
          "500": { "$ref": "#/components/responses/ServerError" }
        }
      },
      "get": {
        "summary": "Get All Vehicles",
        "operationId": "listVehicles",
        "description": "Endpoint to retrieve all vehicles.",
        "tags": [
          "Vehicles"
        ],
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/VehiclesListResponse" },
                "example": {
                  "vehicles": [
                    {
                      "id": 123,
                      "name": "Vehicle Name",
                      "active": true,
                      "capacities": [
                        {
                          "id": 1,
                          "type": "Capacity Type 1",
                          "capacity": 10
                        },
                        {
                          "id": 2,
                          "type": "Capacity Type 2",
                          "capacity": 15
                        }
                      ],
                      "skills": [
                        "Skill 1",
                        "Skill 2"
                      ],
                      "availability": "shift",
                      "start_location": "other",
                      "end_location": "other",
                      "created": "2024-06-19T08:56:43.000Z",
                      "updated": "2024-06-19T08:56:43.000Z",
                      "shift_start": "08:00",
                      "shift_end": "17:00",
                      "start_address": "Start Location Address",
                      "start_lat": 12.345678,
                      "start_lng": -23.456789,
                      "end_address": "End Location Address",
                      "end_lat": 34.567890,
                      "end_lng": -45.678901,
                      "break": true,
                      "break_start": "12:00",
                      "break_end": "12:30",
                      "break_duration": 30,
                      "shift": {
                        "enabled": true,
                        "availability": "shift",
                        "shift_start": "09:30",
                        "shift_end": "17:30",
                        "force_shift_start": false,
                        "max_route_duration": 720,
                        "day_of_week": "MONDAY",
                        "breaks": [
                          {
                            "enabled": true,
                            "break_start": "11:00",
                            "break_end": "13:00",
                            "break_duration": 45
                          },
                          {
                            "enabled": true,
                            "break_start": "11:00",
                            "break_end": "13:00",
                            "break_duration": 50
                          }
                        ]
                      }
                    }
                  ]
                }
              }
            }
          },
          "403": { "$ref": "#/components/responses/Forbidden" },
          "500": { "$ref": "#/components/responses/ServerError" }
        }
      }
    },
    "/vehicles/{id}": {
      "put": {
        "summary": "Update Vehicle by ID",
        "operationId": "updateVehicleById",
        "description": "Update a vehicle based on ID.",
        "tags": [
          "Vehicles"
        ],
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "number"
            },
            "description": "ID of the vehicle to update."
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "description": "Name of the vehicle."
                  },
                  "availability": {
                    "type": "string",
                    "description": "Availability status of the vehicle.",
                    "enum": [
                      "shift",
                      "full_day",
                      "always"
                    ]
                  },
                  "shift_start": {
                    "type": "string",
                    "format": "time",
                    "nullable": true,
                    "description": "Start time of the vehicle's shift (if availability is 'shift')."
                  },
                  "shift_end": {
                    "type": "string",
                    "format": "time",
                    "nullable": true,
                    "description": "End time of the vehicle's shift (if availability is 'shift')."
                  },
                  "start_location": {
                    "type": "string",
                    "description": "Location type where the vehicle starts.",
                    "enum": [
                      "depot",
                      "other",
                      "app-location"
                    ]
                  },
                  "start_address": {
                    "type": "string",
                    "nullable": true,
                    "description": "Address where the vehicle starts (if location is 'other')."
                  },
                  "start_lng": {
                    "type": "number",
                    "nullable": true,
                    "description": "Longitude of the starting location (if location is 'other')."
                  },
                  "start_lat": {
                    "type": "number",
                    "nullable": true,
                    "description": "Latitude of the starting location (if location is 'other')."
                  },
                  "end_location": {
                    "type": "string",
                    "description": "Location type where the vehicle ends.",
                    "enum": [
                      "depot",
                      "other",
                      "none"
                    ]
                  },
                  "end_address": {
                    "type": "string",
                    "nullable": true,
                    "description": "Address where the vehicle ends (if location is 'other')."
                  },
                  "end_lng": {
                    "type": "number",
                    "nullable": true,
                    "description": "Longitude of the ending location (if location is 'other')."
                  },
                  "end_lat": {
                    "type": "number",
                    "nullable": true,
                    "description": "Latitude of the ending location (if location is 'other')."
                  },
                  "break": {
                    "type": "boolean",
                    "description": "Flag indicating whether the vehicle has a break."
                  },
                  "break_start": {
                    "type": "string",
                    "format": "time",
                    "nullable": true,
                    "description": "Start time of the vehicle's break (if it has a break)."
                  },
                  "break_end": {
                    "type": "string",
                    "format": "time",
                    "nullable": true,
                    "description": "End time of the vehicle's break (if it has a break)."
                  },
                  "break_duration": {
                    "type": "number",
                    "nullable": true,
                    "description": "Duration of the vehicle's break in minutes (if it has a break)."
                  },
                  "active": {
                    "type": "boolean",
                    "description": "Flag indicating whether the vehicle is active."
                  },
                  "skills": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "Array of skills associated with the vehicle."
                  },
                  "capacities": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "integer",
                          "description": "Id of capacity (e.g., 1, 2)."
                        },
                        "capacity": {
                          "type": "number",
                          "format": "float",
                          "description": "Capacity value for the specified type."
                        }
                      },
                      "required": [
                        "id",
                        "capacity"
                      ],
                      "description": "Details of each capacity associated with the vehicle."
                    },
                    "description": "Array of capacities associated with the vehicle."
                  }
                },
                "required": [
                  "availability",
                  "start_location",
                  "end_location"
                ],
                "description": "Request body for updating a vehicle.",
                "example": {
                  "name": "Vehicle Name",
                  "availability": "shift",
                  "shift_start": "08:00",
                  "shift_end": "17:30",
                  "start_location": "depot",
                  "end_location": "none",
                  "break": false,
                  "capacities": [
                    {
                      "id": 1,
                      "capacity": 500
                    }
                  ]
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/VehicleResponse" },
                "example": {
                  "vehicle": {
                    "id": 123,
                    "name": "Vehicle Name",
                    "active": true,
                    "capacities": [
                      {
                        "id": 1,
                        "type": "Capacity Type 1",
                        "capacity": 10
                      },
                      {
                        "id": 2,
                        "type": "Capacity Type 2",
                        "capacity": 15
                      }
                    ],
                    "skills": [
                      "Skill 1",
                      "Skill 2"
                    ],
                    "availability": "shift",
                    "start_location": "other",
                    "end_location": "other",
                    "shift_start": "08:00",
                    "shift_end": "17:00",
                    "start_address": "Start Location Address",
                    "start_lat": 12.345678,
                    "start_lng": -23.456789,
                    "end_address": "End Location Address",
                    "end_lat": 34.567890,
                    "end_lng": -45.678901,
                    "break": true,
                    "break_start": "12:00",
                    "break_end": "12:30",
                    "break_duration": 30,
                    "shift": {
                      "enabled": true,
                      "availability": "shift",
                      "shift_start": "09:30",
                      "shift_end": "17:30",
                      "force_shift_start": false,
                      "max_route_duration": 720,
                      "day_of_week": "MONDAY",
                      "breaks": [
                        {
                          "enabled": true,
                          "break_start": "11:00",
                          "break_end": "13:00",
                          "break_duration": 45
                        },
                        {
                          "id": 4,
                          "vehicle_shift_id": 2533,
                          "enabled": true,
                          "break_start": "11:00",
                          "break_end": "13:00",
                          "break_duration": 50
                        }
                      ]
                    }
                  }
                }
              }
            }
          },
          "400": { "$ref": "#/components/responses/InvalidInput" },
          "404": { "$ref": "#/components/responses/NotFound" },
          "403": { "$ref": "#/components/responses/Forbidden" },
          "500": { "$ref": "#/components/responses/ServerError" }
        }
      },
      "get": {
        "summary": "Get Vehicle by ID",
        "operationId": "getVehicleById",
        "description": "Retrieve a vehicle based on ID.",
        "tags": [
          "Vehicles"
        ],
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "number"
            },
            "description": "ID of the vehicle to retrieve."
          }
        ],
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/VehicleResponse" },
                "example": {
                  "vehicle": {
                    "id": 123,
                    "name": "Vehicle Name",
                    "active": true,
                    "capacities": [
                      {
                        "id": 1,
                        "type": "Capacity Type 1",
                        "capacity": 10
                      },
                      {
                        "id": 2,
                        "type": "Capacity Type 2",
                        "capacity": 15
                      }
                    ],
                    "skills": [
                      "Skill 1",
                      "Skill 2"
                    ],
                    "availability": "shift",
                    "start_location": "other",
                    "end_location": "other",
                    "created": "2024-06-19T08:56:43.000Z",
                    "updated": "2024-06-19T08:56:43.000Z",
                    "shift_start": "08:00",
                    "shift_end": "17:00",
                    "start_address": "Start Location Address",
                    "start_lat": 12.345678,
                    "start_lng": -23.456789,
                    "end_address": "End Location Address",
                    "end_lat": 34.567890,
                    "end_lng": -45.678901,
                    "break": true,
                    "break_start": "12:00",
                    "break_end": "12:30",
                    "break_duration": 30
                  }
                }
              }
            }
          },
          "404": { "$ref": "#/components/responses/NotFound" },
          "403": { "$ref": "#/components/responses/Forbidden" },
          "500": { "$ref": "#/components/responses/ServerError" }
        }
      },
      "delete": {
        "summary": "Delete Vehicle by ID",
        "operationId": "deleteVehicleById",
        "description": "Delete a vehicle based on ID.",
        "tags": [
          "Vehicles"
        ],
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "number"
            },
            "description": "ID of the vehicle to delete."
          }
        ],
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "example": {
                  "deleted": {
                    "vehicles_count": 1
                  }
                }
              }
            }
          },
          "404": { "$ref": "#/components/responses/NotFound" },
          "403": { "$ref": "#/components/responses/Forbidden" },
          "500": { "$ref": "#/components/responses/ServerError" }
        }
      }
    },
    "/zone-groups": {
      "get": {
        "summary": "Get Zone Groups",
        "operationId": "listZoneGroups",
        "description": "Endpoint to retrieve zone groups.",
        "tags": [
          "Zone Groups"
        ],
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "example": {
                  "zone_groups": [
                    {
                      "id": 123,
                      "name": "Zone Group 1",
                      "created": "2024-06-19T08:56:43.000Z",
                      "updated": "2024-06-19T08:56:43.000Z"
                    },
                    {
                      "id": 124,
                      "name": "Zone Group 2",
                      "created": "2024-06-19T08:56:43.000Z",
                      "updated": "2024-06-19T08:56:43.000Z"
                    },
                    {
                      "id": 125,
                      "name": "Zone Group 3",
                      "created": "2024-06-19T08:56:43.000Z",
                      "updated": "2024-06-19T08:56:43.000Z"
                    }
                  ]
                }
              }
            }
          },
          "403": { "$ref": "#/components/responses/Forbidden" },
          "500": { "$ref": "#/components/responses/ServerError" }
        }
      }
    },
    "/zone-groups/{id}/bounds/contains": {
      "post": {
        "summary": "Get Zone for Location",
        "operationId": "getZoneGroupForLocation",
        "description": "Endpoint to return the zone name and zone ID for a given location within a specified zone group.",
        "tags": [
          "Zone Groups"
        ],
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "number"
            },
            "description": "ID of the zone group."
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "location": {
                    "type": "object",
                    "properties": {
                      "lat": {
                        "type": "number",
                        "format": "float",
                        "description": "Latitude of the location for booking availability."
                      },
                      "lng": {
                        "type": "number",
                        "format": "float",
                        "description": "Longitude of the location for booking availability."
                      },
                      "address": {
                        "type": "string",
                        "description": "Address of the location for booking availability."
                      },
                      "postcode": {
                        "type": "string",
                        "description": "Postcode of the location for booking availability."
                      },
                      "country": {
                        "type": "string",
                        "description": "Country of the location for booking availability."
                      }
                    },
                    "required": [],
                    "description": "Location information for zone. If no lat, lng is provided, address or postcode is required."
                  }
                },
                "required": [
                  "location"
                ],
                "description": "Request body for checking availability for bookings."
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "example": {
                  "zone": {
                    "name": "Cork City",
                    "id": 123,
                    "zone_group": {
                      "name": "Cork County",
                      "id": 321
                    }
                  }
                }
              }
            }
          },
          "400": { "$ref": "#/components/responses/InvalidInput" },
          "404": { "$ref": "#/components/responses/NotFound" },
          "403": { "$ref": "#/components/responses/Forbidden" },
          "500": { "$ref": "#/components/responses/ServerError" }
        }
      }
    },
    "/driver-questionnaire-submission/{id}": {
      "get": {
        "summary": "Get a driver questionnaire submission by ID",
        "operationId": "getDriverQuestionnaireSubmissionById",
        "tags": [
          "Driver Questionnaires"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer"
            },
            "description": "Driver Questionnaire Submission ID"
          }
        ],
        "responses": {
          "200": {
            "description": "Driver Questionnaire Submission",
            "content": {
              "application/json": {
                "example": {
                  "driver_questionnaire_submission": {
                    "id": 1266,
                    "route_id": 101838,
                    "visit_id": null,
                    "driver_questionnaire": {
                      "type": "ROUTE_VEHICLE_CHECKIN",
                      "title": "Route Questionnaire"
                    },
                    "driver_questionnaire_answers": [
                      {
                        "id": 4028,
                        "type": "CHECKBOX",
                        "data": "1",
                        "driver_questionnaire_question": {
                          "type": "CHECKBOX",
                          "question": "Checkbox Question?"
                        },
                        "images": []
                      },
                      {
                        "id": 4029,
                        "type": "TEXT",
                        "data": "Depot",
                        "driver_questionnaire_question": {
                          "type": "TEXT",
                          "question": "What is the starting location?"
                        },
                        "images": []
                      },
                      {
                        "id": 4030,
                        "type": "SELECT",
                        "data": "1",
                        "driver_questionnaire_question": {
                          "type": "SELECT",
                          "question": "Select an option?"
                        },
                        "images": []
                      },
                      {
                        "id": 4031,
                        "type": "MULTI_SELECT",
                        "data": "1",
                        "driver_questionnaire_question": {
                          "type": "MULTI_SELECT",
                          "question": "Select all that applies?"
                        },
                        "images": []
                      },
                      {
                        "id": 4032,
                        "type": "MULTI_SELECT",
                        "data": "3",
                        "driver_questionnaire_question": {
                          "type": "MULTI_SELECT",
                          "question": "Select all that applies?"
                        },
                        "images": []
                      },
                      {
                        "id": 4033,
                        "type": "MULTI_SELECT",
                        "data": "2",
                        "driver_questionnaire_question": {
                          "type": "MULTI_SELECT",
                          "question": "Select all that applies?"
                        },
                        "images": []
                      },
                      {
                        "id": 4034,
                        "type": "SIGNATURE",
                        "data": "90e4486d-dfcf-4007-90d7-7a169b5c89c0",
                        "driver_questionnaire_question": {
                          "type": "SIGNATURE",
                          "question": "Did you get a signature?"
                        },
                        "images": [
                          "https://api.smartroutes.io/v2/driver-questionnaire-submission-images/1034"
                        ]
                      },
                      {
                        "id": 4035,
                        "type": "PHOTO",
                        "data": "f6c356a0-4622-468c-a6c0-78f11446fd09",
                        "driver_questionnaire_question": {
                          "type": "PHOTO",
                          "question": "Uploaded the photo? "
                        },
                        "images": [
                          "https://api.smartroutes.io/v2/driver-questionnaire-submission-images/1035"
                        ]
                      }
                    ]
                  }
                }
              }
            }
          },
          "404": { "$ref": "#/components/responses/NotFound" },
          "403": { "$ref": "#/components/responses/Forbidden" },
          "500": { "$ref": "#/components/responses/ServerError" }
        }
      }
    },
    "/proof-of-delivery/photos/{id}": {
      "get": {
        "summary": "Get Proof of Delivery Photo",
        "operationId": "getProofOfDeliveryPhotoById",
        "description": "Retrieve the compressed proof-of-delivery photo by its ID. By default returns the raw image binary. Use the `encoding` query parameter to request a Base64-encoded JSON response instead.\n\nPhotos are compressed asynchronously after the driver uploads them. If the photo exists but compression has not finished, this endpoint returns `202 Accepted` with a `Retry-After` header and the photo's model (`id` and `is_compressed: false`) as the JSON body, instead of image data — retry after the interval given. The `photos` arrays on order and plan responses list every synced photo as soon as it exists, including photos that are still compressing, so a URL taken from one of those responses may itself return a `202` if followed before compression finishes — apply the same retry logic.",
        "tags": [
          "Proof of Delivery"
        ],
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "integer",
              "description": "The ID of the photo to retrieve."
            },
            "description": "The ID of the photo to retrieve."
          },
          {
            "in": "query",
            "name": "encoding",
            "required": false,
            "schema": {
              "type": "string",
              "enum": ["base64"],
              "description": "Set to `base64` to receive the image as a Base64-encoded string in a JSON response instead of raw binary."
            },
            "description": "Set to `base64` to receive the image as a Base64-encoded string in a JSON response instead of raw binary."
          }
        ],
        "responses": {
          "200": {
            "description": "Successful response. Returns raw image binary by default, or a JSON object when `encoding=base64` is specified.",
            "content": {
              "image/*": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "application/json": {
                "example": {
                  "data": "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk...",
                  "content_type": "image/jpeg"
                }
              }
            }
          },
          "202": { "$ref": "#/components/responses/PhotoCompressing" },
          "404": { "$ref": "#/components/responses/NotFound" },
          "403": { "$ref": "#/components/responses/Forbidden" },
          "500": { "$ref": "#/components/responses/ServerError" }
        }
      }
    },
    "/proof-of-delivery/signatures/{id}": {
      "get": {
        "summary": "Get Proof of Delivery Signature",
        "operationId": "getProofOfDeliverySignatureById",
        "description": "Retrieve a proof-of-delivery signature by its ID. By default returns the raw image binary. Use the `encoding` query parameter to request a Base64-encoded JSON response instead.",
        "tags": [
          "Proof of Delivery"
        ],
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "integer",
              "description": "The ID of the signature to retrieve."
            },
            "description": "The ID of the signature to retrieve."
          },
          {
            "in": "query",
            "name": "encoding",
            "required": false,
            "schema": {
              "type": "string",
              "enum": ["base64"],
              "description": "Set to `base64` to receive the image as a Base64-encoded string in a JSON response instead of raw binary."
            },
            "description": "Set to `base64` to receive the image as a Base64-encoded string in a JSON response instead of raw binary."
          }
        ],
        "responses": {
          "200": {
            "description": "Successful response. Returns raw image binary by default, or a JSON object when `encoding=base64` is specified.",
            "content": {
              "image/*": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "application/json": {
                "example": {
                  "data": "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk...",
                  "content_type": "image/png"
                }
              }
            }
          },
          "404": { "$ref": "#/components/responses/NotFound" },
          "403": { "$ref": "#/components/responses/Forbidden" },
          "500": { "$ref": "#/components/responses/ServerError" }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "PhotoCompressing": {
        "type": "object",
        "description": "Returned with HTTP 202 by the proof-of-delivery photo endpoint when the requested photo exists but has not finished compressing. Retry after the interval in the `Retry-After` header.",
        "required": ["photo"],
        "properties": {
          "photo": {
            "type": "object",
            "required": ["id", "is_compressed"],
            "properties": {
              "id": { "type": "integer", "description": "ID of the photo." },
              "is_compressed": { "type": "boolean", "description": "Whether compression has finished. Always `false` in this response — that is why no image data is returned yet." }
            }
          }
        },
        "example": {
          "photo": { "id": 491548, "is_compressed": false }
        }
      },
      "ErrorResponse": {
        "type": "object",
        "description": "Standard error envelope. Returned for any non-2xx response (with the exception of legacy endpoints not yet migrated). The shape is flat — no enclosing `error` wrapper.",
        "required": ["name", "statusCode", "description", "details"],
        "properties": {
          "name": {
            "type": "string",
            "description": "Machine-readable error name. Stable string identifier; safe to switch on programmatically.",
            "enum": [
              "INVALID_INPUT",
              "RESOURCE_NOT_FOUND",
              "UNAUTHORIZED",
              "FORBIDDEN",
              "PERMISSION",
              "GONE",
              "SERVICE_UNAVAILABLE",
              "INTERNAL_SERVER_ERROR",
              "INTERNAL_RESOURCE_MISSING",
              "ERROR_WARNING",
              "LATENCY_WARNING",
              "VALIDATION_REQUEST",
              "GEOCODING_FAILED",
              "REDIS_UNAVAILABLE",
              "SEND_ERROR",
              "IDEMPOTENCY_KEY_REUSED_WITH_DIFFERENT_BODY",
              "IDEMPOTENCY_REQUEST_IN_PROGRESS",
              "IDEMPOTENCY_INVALID_KEY"
            ]
          },
          "statusCode": {
            "type": "integer",
            "description": "HTTP status code matching the response status. Legacy camelCase property name; kept for backwards compatibility."
          },
          "description": {
            "type": "string",
            "description": "Human-readable description of the error. For developers; not intended for end-user display."
          },
          "details": {
            "type": "object",
            "additionalProperties": true,
            "description": "Additional structured details about the error. Always an object — never null. May be empty (`{}`). Validation errors populate this with a `validationErrors` array of Zod issues."
          }
        }
      },
      "OrderStatus": {
        "type": "string",
        "description": "Order status, derived from line-item statuses by the status service. Source: `cORDER_STATUS_TYPES` in `src/models/order-status.js`.",
        "enum": [
          "BOOKED",
          "BOOKING_DECLINED",
          "DELIVERED",
          "LOADED",
          "OPEN",
          "PARTIALLY_BOOKED",
          "PARTIALLY_BOOKING_DECLINED",
          "PARTIALLY_DELIVERED",
          "PARTIALLY_LOADED",
          "PARTIALLY_READY_FOR_COLLECTION",
          "PARTIALLY_ROUTED",
          "PARTIALLY_UNDELIVERED",
          "PARTIALLY_WAITING_CONFIRMATION",
          "READY_FOR_COLLECTION",
          "ROUTED",
          "UNDELIVERED",
          "WAITING_CONFIRMATION"
        ]
      },
      "LineItemStatus": {
        "type": "string",
        "description": "Per-line-item status. `PARTIALLY_DELIVERED` appears when a line item has been partly fulfilled — partly collected on a `pickup` order or partly delivered on a `delivery` order; how much is left to fulfil is in `quantity_outstanding`. There is no separate picked-up status: completed and partial pickups both use the `DELIVERED` family. `UNDELIVERED` covers both \"attended, nothing fulfilled\" (in which case `quantity_outstanding` still equals `product_quantity`) and a failed visit. The other `PARTIALLY_*` values are aggregates and apply only at the order level (see `OrderStatus`). Historical rows may still carry legacy values (`CANCEL`, `COMPLETED`, `DECLINED`, `NOT RECEIVED`, `ON HOLD`, `RETURNED`); these are listed for backward compatibility but are no longer written by current SR code.",
        "enum": [
          "BOOKED",
          "BOOKING_DECLINED",
          "CANCEL",
          "COMPLETED",
          "DECLINED",
          "DELIVERED",
          "LOADED",
          "NOT RECEIVED",
          "ON HOLD",
          "OPEN",
          "PARTIALLY_DELIVERED",
          "READY_FOR_COLLECTION",
          "RETURNED",
          "ROUTED",
          "UNDELIVERED",
          "WAITING_CONFIRMATION"
        ]
      },
      "Customer": {
        "type": "object",
        "nullable": true,
        "description": "Trimmed customer reference embedded in Order responses. May be `null` for orders without a customer association.",
        "properties": {
          "id": { "type": "integer", "nullable": true },
          "account": { "type": "string", "nullable": true }
        }
      },
      "CustomField": {
        "type": "object",
        "properties": {
          "id": { "type": "integer" },
          "name": { "type": "string" },
          "value": { "description": "Field value. Type varies by field definition (string, number, or boolean)." }
        }
      },
      "Capacity": {
        "type": "object",
        "properties": {
          "id": { "type": "integer" },
          "type": { "type": "string" },
          "capacity": { "type": "number" }
        }
      },
      "TimeWindow": {
        "type": "object",
        "properties": {
          "from": { "type": "string", "description": "HH:mm:ss" },
          "to": { "type": "string", "description": "HH:mm:ss" },
          "type": { "type": "string" }
        }
      },
      "LineItem": {
        "type": "object",
        "properties": {
          "product_name": { "type": "string" },
          "product_code": { "type": "string" },
          "product_quantity": { "type": "integer" },
          "quantity_outstanding": {
            "type": "number",
            "format": "float",
            "nullable": true,
            "description": "Quantity still to be fulfilled on this line item — left to deliver on a `delivery` order, left to collect on a `pickup` order. Equal to `product_quantity` before anything is fulfilled, a value in between after a partial fulfillment, `0` when exactly the ordered quantity has been fulfilled, and **negative** when more than the ordered quantity was fulfilled. Subtract it from `product_quantity` for the amount the driver has fulfilled. **Read-only:** drivers record fulfillment in the SmartRoutes mobile app; it cannot be set through this API. Notes: `null` — not `0` — when the line item is not tracked, so treat null as unknown rather than as fully fulfilled; an over-fulfillment is reported as recorded rather than clamped; stays at `product_quantity` on `shipment` orders, which are dual-leg and not yet tracked. A value still equal to `product_quantity` does not distinguish an untouched line item from one a driver attended and fulfilled nothing on — read `status` for that (`UNDELIVERED` means attended)."
          },
          "capacities": { "type": "array", "items": { "$ref": "#/components/schemas/Capacity" } },
          "status": {
            "allOf": [{ "$ref": "#/components/schemas/LineItemStatus" }],
            "nullable": true
          },
          "date": { "type": "string", "format": "date", "nullable": true },
          "custom_fields": { "type": "array", "items": { "$ref": "#/components/schemas/CustomField" } }
        }
      },
      "DriverQuestionnaireSubmission": {
        "type": "object",
        "properties": {
          "id": { "type": "integer" },
          "driver_questionnaire": {
            "type": "object",
            "properties": {
              "type": { "type": "string" },
              "title": { "type": "string" }
            }
          }
        }
      },
      "VehicleRef": {
        "type": "object",
        "description": "Trimmed vehicle reference embedded in Route responses.",
        "properties": {
          "vehicle_id": { "type": "integer" },
          "name": { "type": "string" },
          "driver": { "type": "string", "nullable": true }
        }
      },
      "StopBase": {
        "type": "object",
        "description": "Fields common to every stop projection, independent of the resource the stop is nested under. `Stop` (route context) and `OrderStop` (order context) each compose this base. POD-related fields populate as the stop is completed.",
        "properties": {
          "id": { "type": "integer" },
          "route_id": { "type": "integer" },
          "address": { "type": "string" },
          "postcode": { "type": "string" },
          "phone": { "type": "string", "nullable": true },
          "lat": { "type": "number" },
          "lng": { "type": "number" },
          "planned_distance": { "type": "number" },
          "arrival_date": { "type": "string", "format": "date" },
          "departure_date": { "type": "string", "format": "date" },
          "estimated_arrival_time": { "type": "string", "description": "HH:mm or HH:mm:ss" },
          "estimated_departure_time": { "type": "string", "description": "HH:mm or HH:mm:ss" },
          "actual_completed_ts": { "type": "string", "format": "date-time", "nullable": true },
          "actual_completed_lat": { "type": "number", "nullable": true },
          "actual_completed_lng": { "type": "number", "nullable": true },
          "delivery_notes": { "type": "string", "nullable": true },
          "driver_notes": { "type": "string", "nullable": true },
          "actual_arrival_time": { "type": "string", "nullable": true },
          "actual_duration": { "type": "number", "nullable": true },
          "signature": { "type": "string", "format": "uri", "nullable": true },
          "signature_lat": { "type": "number", "nullable": true },
          "signature_lng": { "type": "number", "nullable": true },
          "signed_by": { "type": "string", "nullable": true },
          "photos": { "type": "array", "items": { "type": "string", "format": "uri" }, "nullable": true, "description": "URLs to proof-of-delivery photos for this stop. A photo appears here as soon as it is uploaded and synced, which may be before compression has finished — following the URL of a photo that is still compressing returns `202 Accepted` with a `Retry-After` header (see the photo endpoint), so be prepared to retry. `null` when there are none." },
          "tracking_link": { "type": "string", "format": "uri", "nullable": true },
          "vehicle_assignment": {
            "type": "object",
            "nullable": true,
            "properties": { "vehicle_id": { "type": "integer" } }
          },
          "directions": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": { "instruction": { "type": "string" } }
            }
          },
          "driver_questionnaire_submissions": {
            "type": "array",
            "items": { "$ref": "#/components/schemas/DriverQuestionnaireSubmission" }
          },
          "failed_reason": {
            "type": "object",
            "nullable": true,
            "properties": { "reason": { "type": "string" } }
          },
          "tags": { "type": "array", "items": { "type": "string" } },
          "available_days": { "type": "array", "items": { "type": "integer" } },
          "emails": {
            "type": "array",
            "nullable": true,
            "items": {
              "type": "object",
              "properties": { "email": { "type": "string" } }
            }
          }
        }
      },
      "Stop": {
        "type": "object",
        "description": "A stop as returned nested under a route (GET /routes/{id}, plans). Composes `StopBase` and adds the `orders` served at this stop.",
        "allOf": [
          { "$ref": "#/components/schemas/StopBase" },
          {
            "type": "object",
            "properties": {
              "orders": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "id": { "type": "integer" },
                    "order_number": { "type": "string" },
                    "custom_fields": {
                      "type": "array",
                      "items": { "$ref": "#/components/schemas/CustomField" },
                      "nullable": true
                    },
                    "line_items": { "type": "array", "items": { "$ref": "#/components/schemas/LineItem" } },
                    "type": { "type": "string" }
                  }
                }
              }
            }
          }
        ]
      },
      "OrderStop": {
        "type": "object",
        "description": "A stop as returned nested under an order (GET /orders/{id}). Composes `StopBase` and adds the parent `route` reference and the stop's own `custom_fields`. The per-stop `orders` array is omitted — the caller already has the order.",
        "allOf": [
          { "$ref": "#/components/schemas/StopBase" },
          {
            "type": "object",
            "properties": {
              "custom_fields": { "type": "array", "items": { "$ref": "#/components/schemas/CustomField" } },
              "route": {
                "type": "object",
                "properties": {
                  "id": { "type": "integer" },
                  "date": { "type": "string", "format": "date" },
                  "started_ts": { "type": "string", "format": "date-time", "nullable": true }
                }
              }
            }
          }
        ]
      },
      "Order": {
        "type": "object",
        "description": "An order. Property set is the union of fields returned by list and get-by-id paths; individual endpoints may return a subset.",
        "properties": {
          "id": { "type": "integer" },
          "order_number": { "type": "string" },
          "type": { "type": "string" },
          "status": { "$ref": "#/components/schemas/OrderStatus" },
          "priority": { "type": "string", "nullable": true, "description": "LOW, MEDIUM, HIGH, or null." },
          "parts": { "type": "integer", "nullable": true },
          "delivery_address": { "type": "string" },
          "delivery_lat": { "type": "number" },
          "delivery_lng": { "type": "number" },
          "delivery_notes": { "type": "string", "nullable": true },
          "delivery_available_days": { "type": "array", "items": { "type": "integer" } },
          "delivery_duration": { "type": "number" },
          "delivery_date": { "type": "string", "format": "date", "nullable": true },
          "delivery_contact_name": { "type": "string", "nullable": true },
          "delivery_contact_number": { "type": "string", "nullable": true },
          "delivery_contact_email": { "type": "string", "nullable": true },
          "pickup_address": { "type": "string", "nullable": true },
          "pickup_duration": { "type": "number", "nullable": true },
          "pickup_lat": { "type": "number", "nullable": true },
          "pickup_lng": { "type": "number", "nullable": true },
          "pickup_notes": { "type": "string", "nullable": true },
          "pickup_contact_name": { "type": "string", "nullable": true },
          "pickup_contact_number": { "type": "string", "nullable": true },
          "pickup_contact_email": { "type": "string", "nullable": true },
          "pickup_available_days": { "type": "array", "items": { "type": "integer" } },
          "customer": { "$ref": "#/components/schemas/Customer" },
          "capacities": { "type": "array", "items": { "$ref": "#/components/schemas/Capacity" } },
          "custom_fields": { "type": "array", "items": { "$ref": "#/components/schemas/CustomField" } },
          "time_windows": { "type": "array", "items": { "$ref": "#/components/schemas/TimeWindow" } },
          "skills": { "type": "array", "items": { "type": "string" } },
          "attachments": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "id": { "type": "integer" },
                "name": { "type": "string" }
              }
            }
          },
          "vehicle_assignment": {
            "type": "array",
            "nullable": true,
            "items": {
              "type": "object",
              "properties": { "vehicle_id": { "type": "integer" } }
            }
          },
          "emails": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": { "email": { "type": "string" } }
            }
          },
          "third_party": {
            "type": "object",
            "properties": { "id": { "type": "integer", "nullable": true } }
          },
          "order_exchange": {
            "type": "object",
            "nullable": true,
            "description": "Present when this order is one half of an exchange (a drop + collect served together by one vehicle). The two halves share exchange_id.",
            "properties": {
              "id": { "type": "integer", "readOnly": true },
              "order_id": { "type": "integer", "readOnly": true, "description": "Server-set: the id of this order. Never accepted as input." },
              "exchange_id": { "type": "string", "readOnly": true, "description": "Server-minted uuid identifying the pair — identical on both halves. Never accepted as input." },
              "partner_order_id": { "type": "integer", "readOnly": true, "description": "Server-set: the other half's order id. Never accepted as input." },
              "reference": { "type": "string", "nullable": true, "description": "Customer-supplied swap reference (display only). The only client-settable field — provide it on the create request (order_exchange.reference)." }
            }
          },
          "tags": { "type": "array", "items": { "type": "string" } },
          "stops": { "type": "array", "items": { "$ref": "#/components/schemas/OrderStop" } },
          "line_items": { "type": "array", "items": { "$ref": "#/components/schemas/LineItem" } },
          "created": { "type": "string", "format": "date-time" },
          "updated": { "type": "string", "format": "date-time" }
        }
      },
      "Route": {
        "type": "object",
        "description": "A route belonging to a plan.",
        "properties": {
          "id": { "type": "integer" },
          "plan_id": { "type": "integer" },
          "name": { "type": "string" },
          "dispatched": { "type": "boolean" },
          "date": { "type": "string", "format": "date" },
          "start_time": { "type": "string", "description": "HH:mm:ss" },
          "end_time": { "type": "string", "description": "HH:mm:ss" },
          "started_ts": { "type": "string", "format": "date-time", "nullable": true },
          "completed_ts": { "type": "string", "format": "date-time", "nullable": true },
          "total_time": { "type": "number" },
          "travel_time": { "type": "number" },
          "planned_distance": { "type": "number" },
          "actual_distance": { "type": "number", "nullable": true },
          "vehicle": { "$ref": "#/components/schemas/VehicleRef" },
          "stops": { "type": "array", "items": { "$ref": "#/components/schemas/Stop" } },
          "driver_questionnaire_submissions": {
            "type": "array",
            "items": { "$ref": "#/components/schemas/DriverQuestionnaireSubmission" }
          },
          "created": { "type": "string", "format": "date-time" },
          "updated": { "type": "string", "format": "date-time" }
        }
      },
      "Plan": {
        "type": "object",
        "description": "A VRP plan. When no solution has been computed yet, `routes` and `unserved` are empty arrays — see the async optimise endpoint description for polling guidance.",
        "properties": {
          "id": { "type": "integer" },
          "total_time": { "type": "number" },
          "dispatched": { "type": "boolean", "nullable": true },
          "routes": { "type": "array", "items": { "$ref": "#/components/schemas/Route" } },
          "unserved": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "id": { "type": "integer" },
                "address": { "type": "string" },
                "postcode": { "type": "string" },
                "phone": { "type": "string" },
                "lat": { "type": "number" },
                "lng": { "type": "number" },
                "delivery_notes": { "type": "string" },
                "reference_id": { "type": "string" },
                "available_days": { "type": "array", "items": { "type": "integer" } }
              }
            }
          },
          "created": { "type": "string", "format": "date-time" },
          "updated": { "type": "string", "format": "date-time" }
        }
      },
      "BookingAvailabilityResponse": {
        "type": "object",
        "required": ["booking"],
        "properties": {
          "booking": {
            "type": "object",
            "required": ["available"],
            "properties": {
              "available": { "type": "boolean" }
            }
          }
        }
      },
      "OrdersListResponse": {
        "type": "object",
        "required": ["orders"],
        "properties": {
          "orders": {
            "type": "array",
            "items": { "$ref": "#/components/schemas/Order" }
          }
        }
      },
      "OrderResponse": {
        "type": "object",
        "required": ["order"],
        "properties": {
          "order": { "$ref": "#/components/schemas/Order" }
        }
      },
      "PlanOptimisationResponse": {
        "type": "object",
        "required": ["optimisation", "plan"],
        "properties": {
          "optimisation": {
            "type": "object",
            "required": ["id", "in_progress"],
            "properties": {
              "id": { "type": "string", "format": "uuid" },
              "in_progress": { "type": "boolean" }
            }
          },
          "plan": {
            "type": "object",
            "required": ["id", "dispatched"],
            "properties": {
              "id": { "type": "integer" },
              "dispatched": { "type": "boolean" }
            }
          }
        }
      },
      "PlanResponse": {
        "type": "object",
        "required": ["plan"],
        "properties": {
          "plan": { "$ref": "#/components/schemas/Plan" }
        }
      },
      "RouteResponse": {
        "type": "object",
        "required": ["route"],
        "properties": {
          "route": { "$ref": "#/components/schemas/Route" }
        }
      },
      "Vehicle": {
        "type": "object",
        "description": "A depot vehicle. Property set is the union of fields returned by list and get-by-id paths; conditional fields (shift_*, start_address/lat/lng, end_address/lat/lng, break_*) populate only when the corresponding mode is selected. Source of truth: `getExternalModel` in `src/vehicles/vehicles.service.js`.",
        "properties": {
          "id":             { "type": "integer" },
          "name":           { "type": "string" },
          "active":         { "type": "boolean" },
          "availability":   { "type": "string", "enum": ["shift", "full_day", "always"] },
          "start_location": { "type": "string", "enum": ["depot", "other", "app-location"] },
          "end_location":   { "type": "string", "enum": ["depot", "other", "none"] },
          "capacities":     {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "id":       { "type": "integer" },
                "type":     { "type": "string" },
                "capacity": { "type": "number" }
              }
            }
          },
          "skills": { "type": "array", "items": { "type": "string" } },
          "shift": {
            "type": "array",
            "description": "Weekly shift schedule. Each entry is one row of vehicle_shifts (enabled, availability, shift_start, shift_end, force_shift_start, max_route_duration, day_of_week) plus a nested vehicle_breaks array.",
            "items": {
              "type": "object",
              "properties": {
                "enabled":            { "type": "boolean" },
                "availability":       { "type": "string", "enum": ["shift", "full_day", "always"] },
                "shift_start":        { "type": "string", "nullable": true, "description": "HH:mm." },
                "shift_end":          { "type": "string", "nullable": true, "description": "HH:mm." },
                "force_shift_start":  { "type": "boolean" },
                "max_route_duration": { "type": "integer", "nullable": true, "description": "Minutes." },
                "day_of_week":        { "type": "string", "enum": ["MONDAY", "TUESDAY", "WEDNESDAY", "THURSDAY", "FRIDAY", "SATURDAY", "SUNDAY"] },
                "vehicle_breaks":     {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "enabled":        { "type": "boolean" },
                      "break_start":    { "type": "string", "nullable": true, "description": "HH:mm." },
                      "break_end":      { "type": "string", "nullable": true, "description": "HH:mm." },
                      "break_duration": { "type": "integer", "nullable": true, "description": "Minutes." }
                    }
                  }
                }
              }
            }
          },
          "created": { "type": "string", "format": "date-time" },
          "updated": { "type": "string", "format": "date-time" },
          "shift_start":    { "type": "string", "nullable": true, "description": "HH:mm. Present when availability == 'shift'." },
          "shift_end":      { "type": "string", "nullable": true, "description": "HH:mm. Present when availability == 'shift'." },
          "start_address":  { "type": "string", "nullable": true, "description": "Present when start_location == 'other'." },
          "start_lat":      { "type": "number", "nullable": true },
          "start_lng":      { "type": "number", "nullable": true },
          "end_address":    { "type": "string", "nullable": true, "description": "Present when end_location == 'other'." },
          "end_lat":        { "type": "number", "nullable": true },
          "end_lng":        { "type": "number", "nullable": true },
          "break":          { "type": "boolean" },
          "break_start":    { "type": "string", "nullable": true, "description": "HH:mm. Present when break == true." },
          "break_end":      { "type": "string", "nullable": true, "description": "HH:mm. Present when break == true." },
          "break_duration": { "type": "number", "nullable": true, "description": "Minutes. Present when break == true." }
        }
      },
      "VehicleResponse": {
        "type": "object",
        "required": ["vehicle"],
        "properties": {
          "vehicle": { "$ref": "#/components/schemas/Vehicle" }
        }
      },
      "VehiclesListResponse": {
        "type": "object",
        "required": ["vehicles"],
        "properties": {
          "vehicles": {
            "type": "array",
            "items": { "$ref": "#/components/schemas/Vehicle" }
          }
        }
      },
      "WebhookEventType": {
        "type": "string",
        "description": "Event type discriminator emitted on every webhook delivery. The integer type-ids (visible in the receiver's depot_settings.webhook_events row) are: orders.status=2, plans.created=4, plans.dispatched=5, routes.edited=6, routes.deleted=7, routes.completed=8, plans.deleted=9, orders.on_delivery=10.",
        "enum": [
          "orders.status",
          "plans.created",
          "plans.dispatched",
          "routes.edited",
          "routes.deleted",
          "routes.completed",
          "plans.deleted",
          "orders.on_delivery"
        ]
      },
      "WebhookOrdersStatusPayload": {
        "type": "object",
        "required": ["order_id", "order_number", "status"],
        "description": "orders.status payload. Produced by order-workflow.service.js whenever an order's status changes.",
        "properties": {
          "order_id":     { "type": "integer", "description": "Internal order id." },
          "order_number": { "type": "string",  "description": "User-facing order number." },
          "status":       { "$ref": "#/components/schemas/OrderStatus" }
        }
      },
      "WebhookPlanIdPayload": {
        "type": "object",
        "required": ["id"],
        "description": "Payload for plans.created / plans.dispatched / plans.deleted. Carries only the plan id.",
        "properties": {
          "id": { "type": "integer", "description": "Plan id. Fetch with GET /plans/{id}." }
        }
      },
      "WebhookRouteIdPayload": {
        "type": "object",
        "required": ["id"],
        "description": "Payload for routes.edited / routes.deleted / routes.completed. Carries only the route id.",
        "properties": {
          "id": { "type": "integer", "description": "Route id. Fetch with GET /routes/{id}." }
        }
      },
      "WebhookOnDeliveryPayload": {
        "type": "object",
        "required": ["order_id", "order_number", "route_id", "eta", "time_to_arrival"],
        "description": "orders.on_delivery payload. Emitted when an order's stop enters the on-delivery (ETA-threshold) window on a dispatched route — the arriving-soon signal. Rides on the depot's on-delivery customer notifications, so it fires once per stop and only for stops that carry contact details (phone/email + a notification template).",
        "properties": {
          "order_id":        { "type": "integer", "description": "Internal order id." },
          "order_number":    { "type": "string",  "description": "User-facing order number." },
          "route_id":        { "type": "integer", "description": "Id of the dispatched route the stop is on. Fetch with GET /routes/{id}." },
          "eta":             { "type": "string",  "description": "Estimated arrival time at the stop, local depot time, formatted \"HH:MM\"." },
          "time_to_arrival": { "type": "integer", "description": "Whole minutes until the estimated arrival." }
        }
      },
      "WebhookDelivery": {
        "type": "object",
        "required": ["type", "data"],
        "description": "Wire-shape of every webhook delivery. Always an HTTP POST with Content-Type: application/json and an HTTP Basic Authorization header. `data` is a single payload object (NOT an array) — bulk operations fan out into one delivery per event.",
        "properties": {
          "type": { "$ref": "#/components/schemas/WebhookEventType" },
          "data": {
            "oneOf": [
              { "$ref": "#/components/schemas/WebhookOrdersStatusPayload" },
              { "$ref": "#/components/schemas/WebhookPlanIdPayload" },
              { "$ref": "#/components/schemas/WebhookRouteIdPayload" },
              { "$ref": "#/components/schemas/WebhookOnDeliveryPayload" }
            ],
            "description": "Per-type payload object. Discriminate on the sibling `type` field to know which payload schema applies."
          }
        }
      }
    },
    "responses": {
      "InvalidInput": {
        "description": "Invalid input. The request body failed validation.",
        "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } }
      },
      "NotFound": {
        "description": "The requested resource was not found.",
        "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } }
      },
      "ServerError": {
        "description": "An unexpected server error occurred.",
        "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } }
      },
      "Forbidden": {
        "description": "Forbidden. Returned for rate-limit exhaustion (`error.name = FORBIDDEN`, with `details.retry_after_seconds` and `Retry-After` header) and permission gate failures (`error.name = PERMISSION`). Inspect `error.name` to disambiguate.",
        "headers": {
          "Retry-After": {
            "schema": { "type": "integer" },
            "description": "Seconds to wait before retrying. Present only when the cause is rate-limit exhaustion."
          }
        },
        "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } }
      },
      "IdempotencyRequestInProgress": {
        "description": "A request with this idempotency key is already in progress. Retry after the period given in the `Retry-After` header.",
        "headers": {
          "Retry-After": {
            "schema": { "type": "integer" },
            "description": "Seconds to wait before retrying."
          }
        },
        "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } }
      },
      "IdempotencyKeyReusedWithDifferentBody": {
        "description": "The same idempotency key was used with a different request body for this endpoint.",
        "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } }
      },
      "PhotoCompressing": {
        "description": "The photo exists but SmartRoutes has not finished compressing it yet, so no image data is returned. This is a `2xx` response, not an error — retry after the interval given in the `Retry-After` header. The body carries the photo's model with `is_compressed: false`. A photo normally becomes available within a few retries.",
        "headers": {
          "Retry-After": {
            "schema": { "type": "integer" },
            "description": "Seconds to wait before retrying."
          }
        },
        "content": { "application/json": { "schema": { "$ref": "#/components/schemas/PhotoCompressing" } } }
      }
    },
    "parameters": {
      "IdempotencyKeyHeader": {
        "name": "idempotency-key",
        "in": "header",
        "required": false,
        "description": "Optional idempotency key for safe retries. See the Idempotency section of the API description for behaviour. 1–255 characters; UUID recommended.",
        "schema": {
          "type": "string",
          "minLength": 1,
          "maxLength": 255
        }
      }
    },
    "headers": {
      "IdempotencyReplay": {
        "description": "Set to `true` when the response is a cached replay of an earlier request with the same `idempotency-key`. Absent otherwise.",
        "schema": {
          "type": "string",
          "enum": ["true"]
        }
      }
    }
  }
}
