{
    "openapi": "3.0.3",
    "info": {
        "title": "Lanewise API",
        "version": "1.0.0",
        "description": "Store points of interest (POIs), enrich them with an address, query them by attributes,\ncategories and distance, and plan routes around them.\n\nAuthenticate every request with an API key from the [dashboard](https://dash.lanewise.app)\nin the `X-API-KEY` header. Every authenticated response carries `X-RateLimit-*` headers.\nGuides: https://docs.lanewise.app\n",
        "contact": {
            "name": "Lanewise",
            "email": "hello@lanewise.app",
            "url": "https://lanewise.app"
        }
    },
    "servers": [
        {
            "url": "https://api.lanewise.app/v1"
        }
    ],
    "security": [
        {
            "ApiKey": []
        }
    ],
    "tags": [
        {
            "name": "POIs"
        },
        {
            "name": "Attributes"
        },
        {
            "name": "Categories"
        },
        {
            "name": "Geolocation"
        },
        {
            "name": "Imports"
        },
        {
            "name": "Routing"
        },
        {
            "name": "API key"
        },
        {
            "name": "Pricing"
        }
    ],
    "paths": {
        "/info": {
            "get": {
                "tags": [
                    "API key"
                ],
                "operationId": "getApiKey",
                "summary": "Retrieve the current API key",
                "description": "The key that authenticated the request, with its permissions and recent usage. Needs no permission.",
                "responses": {
                    "200": {
                        "description": "The API key.",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "data"
                                    ],
                                    "properties": {
                                        "data": {
                                            "$ref": "#/components/schemas/ApiKey"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "429": {
                        "$ref": "#/components/responses/TooManyRequests"
                    }
                }
            }
        },
        "/pois": {
            "get": {
                "tags": [
                    "POIs"
                ],
                "operationId": "listPois",
                "summary": "List POIs",
                "description": "A cursor-paginated list of your POIs, sorted by ID, with optional filters. Requires `read-pois`.\nFilter by attributes with `attributes[<name or id>]=<value>` (deep object).\n",
                "parameters": [
                    {
                        "$ref": "#/components/parameters/Limit"
                    },
                    {
                        "$ref": "#/components/parameters/Cursor"
                    },
                    {
                        "name": "attributes",
                        "in": "query",
                        "style": "deepObject",
                        "explode": true,
                        "description": "Attribute values to match, keyed by attribute name or ID, e.g. `attributes[owner_id]=123`.",
                        "schema": {
                            "type": "object",
                            "additionalProperties": {
                                "type": "string"
                            }
                        },
                        "example": {
                            "owner_id": "123"
                        }
                    },
                    {
                        "name": "category_id",
                        "in": "query",
                        "description": "ID of a category. Cannot be combined with `category_name`.",
                        "schema": {
                            "type": "string",
                            "format": "ulid"
                        }
                    },
                    {
                        "name": "category_name",
                        "in": "query",
                        "description": "Exact name of a category.",
                        "schema": {
                            "type": "string",
                            "maxLength": 255
                        },
                        "example": "Parking"
                    },
                    {
                        "name": "latitude",
                        "in": "query",
                        "description": "Latitude of the search point. Required with `longitude` or `distance`.",
                        "schema": {
                            "type": "number",
                            "minimum": -90,
                            "maximum": 90
                        },
                        "example": 41.3874
                    },
                    {
                        "name": "longitude",
                        "in": "query",
                        "description": "Longitude of the search point. Required with `latitude` or `distance`.",
                        "schema": {
                            "type": "number",
                            "minimum": -180,
                            "maximum": 180
                        },
                        "example": 2.1686
                    },
                    {
                        "name": "distance",
                        "in": "query",
                        "description": "Search radius in meters around the point. Defaults to 1000.",
                        "schema": {
                            "type": "integer",
                            "minimum": 1,
                            "maximum": 100000,
                            "default": 1000
                        },
                        "example": 500
                    },
                    {
                        "name": "country_id",
                        "in": "query",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "city_id",
                        "in": "query",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "zipcode_id",
                        "in": "query",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "A page of POIs.",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/PoiPage"
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "422": {
                        "$ref": "#/components/responses/ValidationError"
                    },
                    "429": {
                        "$ref": "#/components/responses/TooManyRequests"
                    }
                }
            },
            "post": {
                "tags": [
                    "POIs"
                ],
                "operationId": "createPoi",
                "summary": "Create a POI",
                "description": "Creates a POI and reverse-geocodes it in the background. Requires `create-pois`; returns 403 when the team reached its POI limit.",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/PoiCreate"
                            }
                        }
                    }
                },
                "responses": {
                    "201": {
                        "description": "The created POI.",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "data"
                                    ],
                                    "properties": {
                                        "data": {
                                            "$ref": "#/components/schemas/Poi"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "400": {
                        "$ref": "#/components/responses/BadRequest"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "422": {
                        "$ref": "#/components/responses/ValidationError"
                    },
                    "429": {
                        "$ref": "#/components/responses/TooManyRequests"
                    }
                }
            }
        },
        "/pois/{id}": {
            "parameters": [
                {
                    "$ref": "#/components/parameters/Id"
                }
            ],
            "get": {
                "tags": [
                    "POIs"
                ],
                "operationId": "getPoi",
                "summary": "Retrieve a POI",
                "responses": {
                    "200": {
                        "description": "The POI.",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "data"
                                    ],
                                    "properties": {
                                        "data": {
                                            "$ref": "#/components/schemas/Poi"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "429": {
                        "$ref": "#/components/responses/TooManyRequests"
                    }
                }
            },
            "put": {
                "tags": [
                    "POIs"
                ],
                "operationId": "updatePoi",
                "summary": "Update a POI",
                "description": "Send only the fields to change. Attributes are merged; `null` removes one. Moving a POI geocodes it again. Requires `update-pois`.",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/PoiUpdate"
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "The updated POI.",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "data"
                                    ],
                                    "properties": {
                                        "data": {
                                            "$ref": "#/components/schemas/Poi"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "400": {
                        "$ref": "#/components/responses/BadRequest"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "422": {
                        "$ref": "#/components/responses/ValidationError"
                    },
                    "429": {
                        "$ref": "#/components/responses/TooManyRequests"
                    }
                }
            },
            "delete": {
                "tags": [
                    "POIs"
                ],
                "operationId": "deletePoi",
                "summary": "Delete a POI",
                "description": "Requires `delete-pois`.",
                "responses": {
                    "204": {
                        "description": "Deleted.",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "429": {
                        "$ref": "#/components/responses/TooManyRequests"
                    }
                }
            }
        },
        "/attributes": {
            "get": {
                "tags": [
                    "Attributes"
                ],
                "operationId": "listAttributes",
                "summary": "List attributes",
                "description": "Requires `read-attributes`.",
                "parameters": [
                    {
                        "$ref": "#/components/parameters/Limit"
                    },
                    {
                        "$ref": "#/components/parameters/Cursor"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "A page of attributes.",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "data",
                                        "next"
                                    ],
                                    "properties": {
                                        "data": {
                                            "type": "array",
                                            "items": {
                                                "$ref": "#/components/schemas/Attribute"
                                            }
                                        },
                                        "next": {
                                            "$ref": "#/components/schemas/NextCursor"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "422": {
                        "$ref": "#/components/responses/ValidationError"
                    },
                    "429": {
                        "$ref": "#/components/responses/TooManyRequests"
                    }
                }
            },
            "post": {
                "tags": [
                    "Attributes"
                ],
                "operationId": "createAttribute",
                "summary": "Create an attribute",
                "description": "Requires `create-attributes`.",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "required": [
                                    "name"
                                ],
                                "properties": {
                                    "name": {
                                        "type": "string",
                                        "maxLength": 255,
                                        "pattern": "^[A-Za-z0-9_]+$",
                                        "description": "Unique in the team. Letters, numbers and underscores; `limit` and `cursor` are reserved."
                                    },
                                    "type": {
                                        "type": "string",
                                        "enum": [
                                            "string",
                                            "number",
                                            "boolean"
                                        ],
                                        "default": "string"
                                    }
                                },
                                "example": {
                                    "name": "owner_id",
                                    "type": "number"
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "201": {
                        "description": "The created attribute.",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "data"
                                    ],
                                    "properties": {
                                        "data": {
                                            "$ref": "#/components/schemas/Attribute"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "400": {
                        "$ref": "#/components/responses/BadRequest"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "422": {
                        "$ref": "#/components/responses/ValidationError"
                    },
                    "429": {
                        "$ref": "#/components/responses/TooManyRequests"
                    }
                }
            }
        },
        "/attributes/{id}": {
            "parameters": [
                {
                    "$ref": "#/components/parameters/Id"
                }
            ],
            "get": {
                "tags": [
                    "Attributes"
                ],
                "operationId": "getAttribute",
                "summary": "Retrieve an attribute",
                "description": "Requires `read-attributes`.",
                "responses": {
                    "200": {
                        "description": "The attribute.",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "data"
                                    ],
                                    "properties": {
                                        "data": {
                                            "$ref": "#/components/schemas/Attribute"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "429": {
                        "$ref": "#/components/responses/TooManyRequests"
                    }
                }
            },
            "put": {
                "tags": [
                    "Attributes"
                ],
                "operationId": "updateAttribute",
                "summary": "Rename an attribute",
                "description": "The type can't be changed. Requires `update-attributes`.",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "name": {
                                        "type": "string",
                                        "maxLength": 255,
                                        "pattern": "^[A-Za-z0-9_]+$"
                                    }
                                },
                                "example": {
                                    "name": "driver_id"
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "The updated attribute.",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "data"
                                    ],
                                    "properties": {
                                        "data": {
                                            "$ref": "#/components/schemas/Attribute"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "400": {
                        "$ref": "#/components/responses/BadRequest"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "422": {
                        "$ref": "#/components/responses/ValidationError"
                    },
                    "429": {
                        "$ref": "#/components/responses/TooManyRequests"
                    }
                }
            },
            "delete": {
                "tags": [
                    "Attributes"
                ],
                "operationId": "deleteAttribute",
                "summary": "Delete an attribute",
                "description": "Also deletes its values on every POI. Requires `delete-attributes`.",
                "responses": {
                    "204": {
                        "description": "Deleted.",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "429": {
                        "$ref": "#/components/responses/TooManyRequests"
                    }
                }
            }
        },
        "/categories": {
            "get": {
                "tags": [
                    "Categories"
                ],
                "operationId": "listCategories",
                "summary": "List categories",
                "description": "Requires `read-categories`.",
                "parameters": [
                    {
                        "$ref": "#/components/parameters/Limit"
                    },
                    {
                        "$ref": "#/components/parameters/Cursor"
                    },
                    {
                        "name": "name",
                        "in": "query",
                        "description": "Only categories whose name contains this text.",
                        "schema": {
                            "type": "string",
                            "maxLength": 255
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "A page of categories.",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "data",
                                        "next"
                                    ],
                                    "properties": {
                                        "data": {
                                            "type": "array",
                                            "items": {
                                                "$ref": "#/components/schemas/Category"
                                            }
                                        },
                                        "next": {
                                            "$ref": "#/components/schemas/NextCursor"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "422": {
                        "$ref": "#/components/responses/ValidationError"
                    },
                    "429": {
                        "$ref": "#/components/responses/TooManyRequests"
                    }
                }
            },
            "post": {
                "tags": [
                    "Categories"
                ],
                "operationId": "createCategory",
                "summary": "Create a category",
                "description": "Requires `create-categories`.",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "required": [
                                    "name"
                                ],
                                "properties": {
                                    "name": {
                                        "type": "string",
                                        "maxLength": 255,
                                        "description": "Unique in the team."
                                    }
                                },
                                "example": {
                                    "name": "Parking"
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "201": {
                        "description": "The created category.",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "data"
                                    ],
                                    "properties": {
                                        "data": {
                                            "$ref": "#/components/schemas/Category"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "400": {
                        "$ref": "#/components/responses/BadRequest"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "422": {
                        "$ref": "#/components/responses/ValidationError"
                    },
                    "429": {
                        "$ref": "#/components/responses/TooManyRequests"
                    }
                }
            }
        },
        "/categories/{id}": {
            "parameters": [
                {
                    "$ref": "#/components/parameters/Id"
                }
            ],
            "get": {
                "tags": [
                    "Categories"
                ],
                "operationId": "getCategory",
                "summary": "Retrieve a category",
                "description": "Requires `read-categories`.",
                "responses": {
                    "200": {
                        "description": "The category.",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "data"
                                    ],
                                    "properties": {
                                        "data": {
                                            "$ref": "#/components/schemas/Category"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "429": {
                        "$ref": "#/components/responses/TooManyRequests"
                    }
                }
            },
            "put": {
                "tags": [
                    "Categories"
                ],
                "operationId": "updateCategory",
                "summary": "Rename a category",
                "description": "Requires `update-categories`.",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "name": {
                                        "type": "string",
                                        "maxLength": 255
                                    }
                                },
                                "example": {
                                    "name": "Car parks"
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "The updated category.",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "data"
                                    ],
                                    "properties": {
                                        "data": {
                                            "$ref": "#/components/schemas/Category"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "400": {
                        "$ref": "#/components/responses/BadRequest"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "422": {
                        "$ref": "#/components/responses/ValidationError"
                    },
                    "429": {
                        "$ref": "#/components/responses/TooManyRequests"
                    }
                }
            },
            "delete": {
                "tags": [
                    "Categories"
                ],
                "operationId": "deleteCategory",
                "summary": "Delete a category",
                "description": "Its POIs are kept, without a category. Requires `delete-categories`.",
                "responses": {
                    "204": {
                        "description": "Deleted.",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "429": {
                        "$ref": "#/components/responses/TooManyRequests"
                    }
                }
            }
        },
        "/geo/countries": {
            "get": {
                "tags": [
                    "Geolocation"
                ],
                "operationId": "listCountries",
                "summary": "List the countries your POIs are in",
                "description": "Requires `read-pois`.",
                "parameters": [
                    {
                        "$ref": "#/components/parameters/Limit"
                    },
                    {
                        "$ref": "#/components/parameters/UuidCursor"
                    },
                    {
                        "$ref": "#/components/parameters/GeoName"
                    }
                ],
                "responses": {
                    "200": {
                        "$ref": "#/components/responses/PlacePage"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "422": {
                        "$ref": "#/components/responses/ValidationError"
                    },
                    "429": {
                        "$ref": "#/components/responses/TooManyRequests"
                    }
                }
            }
        },
        "/geo/cities": {
            "get": {
                "tags": [
                    "Geolocation"
                ],
                "operationId": "listCities",
                "summary": "List the cities your POIs are in",
                "description": "Requires `read-pois`.",
                "parameters": [
                    {
                        "$ref": "#/components/parameters/Limit"
                    },
                    {
                        "$ref": "#/components/parameters/UuidCursor"
                    },
                    {
                        "$ref": "#/components/parameters/GeoName"
                    },
                    {
                        "name": "country_id",
                        "in": "query",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "$ref": "#/components/responses/PlacePage"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "422": {
                        "$ref": "#/components/responses/ValidationError"
                    },
                    "429": {
                        "$ref": "#/components/responses/TooManyRequests"
                    }
                }
            }
        },
        "/geo/zipcodes": {
            "get": {
                "tags": [
                    "Geolocation"
                ],
                "operationId": "listZipcodes",
                "summary": "List the zip codes your POIs are in",
                "description": "Requires `read-pois`.",
                "parameters": [
                    {
                        "$ref": "#/components/parameters/Limit"
                    },
                    {
                        "$ref": "#/components/parameters/UuidCursor"
                    },
                    {
                        "$ref": "#/components/parameters/GeoName"
                    },
                    {
                        "name": "country_id",
                        "in": "query",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    },
                    {
                        "name": "city_id",
                        "in": "query",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "A page of zip codes.",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "data",
                                        "next"
                                    ],
                                    "properties": {
                                        "data": {
                                            "type": "array",
                                            "items": {
                                                "$ref": "#/components/schemas/Zipcode"
                                            }
                                        },
                                        "next": {
                                            "type": "string",
                                            "format": "uuid",
                                            "nullable": true
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "422": {
                        "$ref": "#/components/responses/ValidationError"
                    },
                    "429": {
                        "$ref": "#/components/responses/TooManyRequests"
                    }
                }
            }
        },
        "/imports": {
            "get": {
                "tags": [
                    "Imports"
                ],
                "operationId": "listImports",
                "summary": "List imports",
                "description": "Newest first. Requires `read-pois`.",
                "parameters": [
                    {
                        "$ref": "#/components/parameters/Limit"
                    },
                    {
                        "$ref": "#/components/parameters/Cursor"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "A page of imports.",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "data",
                                        "next"
                                    ],
                                    "properties": {
                                        "data": {
                                            "type": "array",
                                            "items": {
                                                "$ref": "#/components/schemas/Import"
                                            }
                                        },
                                        "next": {
                                            "$ref": "#/components/schemas/NextCursor"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "422": {
                        "$ref": "#/components/responses/ValidationError"
                    },
                    "429": {
                        "$ref": "#/components/responses/TooManyRequests"
                    }
                }
            },
            "post": {
                "tags": [
                    "Imports"
                ],
                "operationId": "createImport",
                "summary": "Upload a CSV file of POIs",
                "description": "Columns `name`, `latitude`, `longitude` are required; `category` is optional; any other column must be an\nattribute name (or send `create_missing_attributes=1` to create them as text attributes; columns that are not\nvalid attribute names are ignored). Comma or semicolon delimited, up to 10 MB and 50,000 rows. Processed in\nthe background; poll the returned import. Rows past the team's POI limit are reported as not imported, and\nthe upload returns 403 when the team is already at its limit. The upload counts as one request.\nRequires `create-pois`.\n",
                "requestBody": {
                    "required": true,
                    "content": {
                        "multipart/form-data": {
                            "schema": {
                                "type": "object",
                                "required": [
                                    "file"
                                ],
                                "properties": {
                                    "file": {
                                        "type": "string",
                                        "format": "binary"
                                    },
                                    "create_missing_attributes": {
                                        "type": "boolean",
                                        "default": false
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "202": {
                        "description": "The queued import.",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "data"
                                    ],
                                    "properties": {
                                        "data": {
                                            "$ref": "#/components/schemas/Import"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "422": {
                        "$ref": "#/components/responses/ValidationError"
                    },
                    "429": {
                        "$ref": "#/components/responses/TooManyRequests"
                    }
                }
            }
        },
        "/imports/{id}": {
            "parameters": [
                {
                    "$ref": "#/components/parameters/Id"
                }
            ],
            "get": {
                "tags": [
                    "Imports"
                ],
                "operationId": "getImport",
                "summary": "Retrieve an import",
                "description": "Requires `read-pois`.",
                "responses": {
                    "200": {
                        "description": "The import.",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "data"
                                    ],
                                    "properties": {
                                        "data": {
                                            "$ref": "#/components/schemas/Import"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "429": {
                        "$ref": "#/components/responses/TooManyRequests"
                    }
                }
            }
        },
        "/routes": {
            "post": {
                "tags": [
                    "Routing"
                ],
                "operationId": "planRoute",
                "summary": "Plan a route that avoids POIs",
                "description": "A route through 2 to 50 waypoints, in order. Send `avoid` to keep `radius` meters away from the POIs it\nselects, with the filters of `GET /pois` plus `poi_ids` (all filters combine). Only POIs around the waypoints\nare considered (their bounding box grown by 10% of its diagonal, at least 1 km and at most 10 km); POIs within\n`radius` of a waypoint are skipped, since the route has to reach it. Up to 500 POIs to avoid, and up to\n150 km in a straight line between waypoints when at least one POI is avoided.\n\nRequires `plan-routes`, plus `read-pois` when a waypoint is a POI or `avoid` is sent. Each call counts as one\nrequest. Returns 503 while routing is unavailable or busy, and 502 when the routing service fails to answer.\n",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/RouteRequest"
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "The route.",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "data"
                                    ],
                                    "properties": {
                                        "data": {
                                            "$ref": "#/components/schemas/Route"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "400": {
                        "$ref": "#/components/responses/BadRequest"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "422": {
                        "$ref": "#/components/responses/RoutingError"
                    },
                    "429": {
                        "$ref": "#/components/responses/TooManyRequests"
                    },
                    "502": {
                        "$ref": "#/components/responses/BadGateway"
                    },
                    "503": {
                        "$ref": "#/components/responses/ServiceUnavailable"
                    }
                }
            }
        },
        "/routes/clusters": {
            "post": {
                "tags": [
                    "Routing"
                ],
                "operationId": "clusterStops",
                "summary": "Group stops into clusters",
                "description": "Groups up to 2,000 stops into compact clusters, e.g. one per driver. Send either `stops` or a `pois` selection,\nand either `clusters` (how many) or `max_stops` (the most stops per cluster). `balanced` makes the clusters\nequal in size (they differ by at most one stop). The result is deterministic: the same input always gives the\nsame clusters. Computed with straight-line distances, so it is always available.\n\nRequires `plan-routes`, plus `read-pois` when a stop is a POI or `pois` is sent. Each call counts as one request.\n",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/ClusterRequest"
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "The clusters.",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "data"
                                    ],
                                    "properties": {
                                        "data": {
                                            "$ref": "#/components/schemas/Clusters"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "400": {
                        "$ref": "#/components/responses/BadRequest"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "422": {
                        "$ref": "#/components/responses/ValidationError"
                    },
                    "429": {
                        "$ref": "#/components/responses/TooManyRequests"
                    }
                }
            }
        },
        "/routes/optimize": {
            "post": {
                "tags": [
                    "Routing"
                ],
                "operationId": "optimizeDeliveries",
                "summary": "Optimize deliveries (VRPTW)",
                "description": "Assigns up to 50 stops to up to 3 vehicles and orders each vehicle's stops to minimize travel time, meeting\ncapacities, time windows and skills. Datetimes are ISO 8601; the response uses the offset of the first datetime\nof the request (UTC when there is none, and then vehicles leave now). Durations are in seconds, distances in meters.\nStops that cannot be served are listed in `unassigned` with a reason.\n\nRequires `plan-routes`, plus `read-pois` when a stop or depot is a POI. Each call counts as one request.\nReturns 503 while routing is unavailable or busy, and 502 when the routing service fails to answer.\n",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/OptimizeRequest"
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "The optimized routes.",
                        "headers": {
                            "X-RateLimit-Limit": {
                                "$ref": "#/components/headers/X-RateLimit-Limit"
                            },
                            "X-RateLimit-Remaining": {
                                "$ref": "#/components/headers/X-RateLimit-Remaining"
                            },
                            "X-RateLimit-Reset": {
                                "$ref": "#/components/headers/X-RateLimit-Reset"
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "data"
                                    ],
                                    "properties": {
                                        "data": {
                                            "$ref": "#/components/schemas/Optimization"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "400": {
                        "$ref": "#/components/responses/BadRequest"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "422": {
                        "$ref": "#/components/responses/RoutingError"
                    },
                    "429": {
                        "$ref": "#/components/responses/TooManyRequests"
                    },
                    "502": {
                        "$ref": "#/components/responses/BadGateway"
                    },
                    "503": {
                        "$ref": "#/components/responses/ServiceUnavailable"
                    }
                }
            }
        },
        "/pricing": {
            "get": {
                "tags": [
                    "Pricing"
                ],
                "operationId": "getPricing",
                "summary": "Pricing tiers",
                "description": "Public. Request and POI tiers with monthly prices, and the preset plans.",
                "security": [],
                "responses": {
                    "200": {
                        "description": "The pricing document.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "data"
                                    ],
                                    "properties": {
                                        "data": {
                                            "$ref": "#/components/schemas/Pricing"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "More than 60 requests per minute from your IP address.",
                        "headers": {
                            "Retry-After": {
                                "description": "Seconds until you can retry.",
                                "schema": {
                                    "type": "integer"
                                }
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        }
    },
    "components": {
        "securitySchemes": {
            "ApiKey": {
                "type": "apiKey",
                "in": "header",
                "name": "X-API-KEY",
                "description": "Create a key in the dashboard, under API keys. Each key has its own permissions: `read-`, `create-`,\n`update-` and `delete-` for `pois`, `attributes` and `categories`, and `plan-routes` for routing.\n"
            }
        },
        "parameters": {
            "Id": {
                "name": "id",
                "in": "path",
                "required": true,
                "schema": {
                    "type": "string",
                    "format": "ulid"
                },
                "example": "01JGZ8Q3N5T9B2C4D6F8H0K2M4"
            },
            "Limit": {
                "name": "limit",
                "in": "query",
                "description": "Items per page.",
                "schema": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 100,
                    "default": 15
                }
            },
            "Cursor": {
                "name": "cursor",
                "in": "query",
                "description": "The `next` value of the previous page.",
                "schema": {
                    "type": "string",
                    "format": "ulid"
                }
            },
            "UuidCursor": {
                "name": "cursor",
                "in": "query",
                "description": "The `next` value of the previous page.",
                "schema": {
                    "type": "string",
                    "format": "uuid"
                }
            },
            "GeoName": {
                "name": "name",
                "in": "query",
                "description": "Only places whose name (or code) contains this text.",
                "schema": {
                    "type": "string",
                    "maxLength": 255
                }
            }
        },
        "headers": {
            "X-RateLimit-Limit": {
                "description": "Requests per hour allowed for your team.",
                "schema": {
                    "type": "integer"
                }
            },
            "X-RateLimit-Remaining": {
                "description": "Requests left in the current hour.",
                "schema": {
                    "type": "integer"
                }
            },
            "X-RateLimit-Reset": {
                "description": "When the hourly window resets (Unix timestamp).",
                "schema": {
                    "type": "integer"
                }
            }
        },
        "responses": {
            "BadRequest": {
                "description": "The body is not valid JSON.",
                "content": {
                    "application/json": {
                        "schema": {
                            "$ref": "#/components/schemas/Error"
                        }
                    }
                }
            },
            "Unauthorized": {
                "description": "Missing, unknown, expired or inactive API key.",
                "content": {
                    "application/json": {
                        "schema": {
                            "$ref": "#/components/schemas/Error"
                        }
                    }
                }
            },
            "Forbidden": {
                "description": "The key lacks a permission, the team has no active plan, or the team reached its POI limit.",
                "content": {
                    "application/json": {
                        "schema": {
                            "$ref": "#/components/schemas/Error"
                        }
                    }
                }
            },
            "NotFound": {
                "description": "The resource doesn't exist in your team.",
                "content": {
                    "application/json": {
                        "schema": {
                            "$ref": "#/components/schemas/Error"
                        }
                    }
                }
            },
            "ValidationError": {
                "description": "Invalid parameters or body.",
                "content": {
                    "application/json": {
                        "schema": {
                            "$ref": "#/components/schemas/ValidationError"
                        }
                    }
                }
            },
            "TooManyRequests": {
                "description": "The hourly quota is used up. Requests rejected with a 429 do not count.",
                "headers": {
                    "Retry-After": {
                        "description": "Seconds until the window resets.",
                        "schema": {
                            "type": "integer"
                        }
                    },
                    "X-RateLimit-Retry-After": {
                        "description": "Same value as `Retry-After`.",
                        "schema": {
                            "type": "integer"
                        }
                    },
                    "X-RateLimit-Limit": {
                        "$ref": "#/components/headers/X-RateLimit-Limit"
                    },
                    "X-RateLimit-Remaining": {
                        "$ref": "#/components/headers/X-RateLimit-Remaining"
                    },
                    "X-RateLimit-Reset": {
                        "$ref": "#/components/headers/X-RateLimit-Reset"
                    }
                },
                "content": {
                    "application/json": {
                        "schema": {
                            "$ref": "#/components/schemas/Error"
                        }
                    }
                }
            },
            "RoutingError": {
                "description": "Invalid body or an unknown POI (with `errors` by field), or no route could be planned, e.g. a waypoint far\nfrom any road (`errors` only when a field is to blame).\n",
                "content": {
                    "application/json": {
                        "schema": {
                            "type": "object",
                            "required": [
                                "message"
                            ],
                            "properties": {
                                "message": {
                                    "type": "string"
                                },
                                "errors": {
                                    "type": "object",
                                    "additionalProperties": {
                                        "type": "array",
                                        "items": {
                                            "type": "string"
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            },
            "BadGateway": {
                "description": "The routing service failed to answer; retry in a moment.",
                "content": {
                    "application/json": {
                        "schema": {
                            "$ref": "#/components/schemas/Error"
                        }
                    }
                }
            },
            "ServiceUnavailable": {
                "description": "Routing is not available right now, or is busy; retry later.",
                "content": {
                    "application/json": {
                        "schema": {
                            "$ref": "#/components/schemas/Error"
                        }
                    }
                }
            },
            "PlacePage": {
                "description": "A page of places.",
                "content": {
                    "application/json": {
                        "schema": {
                            "type": "object",
                            "required": [
                                "data",
                                "next"
                            ],
                            "properties": {
                                "data": {
                                    "type": "array",
                                    "items": {
                                        "$ref": "#/components/schemas/Place"
                                    }
                                },
                                "next": {
                                    "type": "string",
                                    "format": "uuid",
                                    "nullable": true
                                }
                            }
                        }
                    }
                }
            }
        },
        "schemas": {
            "NextCursor": {
                "type": "string",
                "nullable": true,
                "description": "Cursor of the next page, or null on the last page."
            },
            "Error": {
                "type": "object",
                "required": [
                    "message"
                ],
                "properties": {
                    "message": {
                        "type": "string"
                    }
                }
            },
            "ValidationError": {
                "type": "object",
                "required": [
                    "message",
                    "errors"
                ],
                "properties": {
                    "message": {
                        "type": "string"
                    },
                    "errors": {
                        "type": "object",
                        "additionalProperties": {
                            "type": "array",
                            "items": {
                                "type": "string"
                            }
                        }
                    }
                }
            },
            "Place": {
                "type": "object",
                "required": [
                    "id",
                    "name"
                ],
                "properties": {
                    "id": {
                        "type": "string",
                        "format": "uuid"
                    },
                    "name": {
                        "type": "string"
                    }
                }
            },
            "Zipcode": {
                "type": "object",
                "required": [
                    "id",
                    "code"
                ],
                "properties": {
                    "id": {
                        "type": "string",
                        "format": "uuid"
                    },
                    "code": {
                        "type": "string"
                    }
                }
            },
            "Category": {
                "type": "object",
                "required": [
                    "id",
                    "name",
                    "created_at",
                    "updated_at"
                ],
                "properties": {
                    "id": {
                        "type": "string",
                        "format": "ulid"
                    },
                    "name": {
                        "type": "string"
                    },
                    "created_at": {
                        "type": "string",
                        "format": "date-time"
                    },
                    "updated_at": {
                        "type": "string",
                        "format": "date-time"
                    }
                }
            },
            "Attribute": {
                "type": "object",
                "required": [
                    "id",
                    "name",
                    "type",
                    "created_at",
                    "updated_at"
                ],
                "properties": {
                    "id": {
                        "type": "string",
                        "format": "ulid"
                    },
                    "name": {
                        "type": "string"
                    },
                    "type": {
                        "type": "string",
                        "enum": [
                            "string",
                            "number",
                            "boolean"
                        ]
                    },
                    "created_at": {
                        "type": "string",
                        "format": "date-time"
                    },
                    "updated_at": {
                        "type": "string",
                        "format": "date-time"
                    }
                }
            },
            "AttributeValues": {
                "type": "object",
                "description": "Attribute values keyed by attribute name (or ID in requests).",
                "additionalProperties": {
                    "description": "A string, number or boolean matching the attribute type; `null` removes the value on update."
                }
            },
            "Address": {
                "type": "object",
                "required": [
                    "display_name",
                    "street",
                    "city",
                    "country",
                    "zipcode",
                    "geocoded_at"
                ],
                "properties": {
                    "display_name": {
                        "type": "string",
                        "nullable": true
                    },
                    "street": {
                        "type": "string",
                        "nullable": true
                    },
                    "city": {
                        "type": "object",
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/Place"
                            }
                        ],
                        "nullable": true
                    },
                    "country": {
                        "type": "object",
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/Place"
                            }
                        ],
                        "nullable": true
                    },
                    "zipcode": {
                        "type": "object",
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/Zipcode"
                            }
                        ],
                        "nullable": true
                    },
                    "geocoded_at": {
                        "type": "string",
                        "format": "date-time",
                        "nullable": true
                    }
                }
            },
            "Poi": {
                "type": "object",
                "required": [
                    "id",
                    "name",
                    "latitude",
                    "longitude",
                    "category",
                    "attributes",
                    "address",
                    "created_at",
                    "updated_at"
                ],
                "properties": {
                    "id": {
                        "type": "string",
                        "format": "ulid"
                    },
                    "name": {
                        "type": "string"
                    },
                    "latitude": {
                        "type": "number"
                    },
                    "longitude": {
                        "type": "number"
                    },
                    "distance": {
                        "type": "number",
                        "description": "Meters from the search point; only present when filtering by distance."
                    },
                    "category": {
                        "type": "object",
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/Category"
                            }
                        ],
                        "nullable": true
                    },
                    "attributes": {
                        "$ref": "#/components/schemas/AttributeValues"
                    },
                    "address": {
                        "$ref": "#/components/schemas/Address"
                    },
                    "created_at": {
                        "type": "string",
                        "format": "date-time"
                    },
                    "updated_at": {
                        "type": "string",
                        "format": "date-time"
                    }
                }
            },
            "PoiPage": {
                "type": "object",
                "required": [
                    "data",
                    "next"
                ],
                "properties": {
                    "data": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/Poi"
                        }
                    },
                    "next": {
                        "$ref": "#/components/schemas/NextCursor"
                    }
                }
            },
            "PoiCreate": {
                "type": "object",
                "required": [
                    "name",
                    "latitude",
                    "longitude"
                ],
                "properties": {
                    "name": {
                        "type": "string",
                        "maxLength": 255
                    },
                    "latitude": {
                        "type": "number",
                        "minimum": -90,
                        "maximum": 90
                    },
                    "longitude": {
                        "type": "number",
                        "minimum": -180,
                        "maximum": 180
                    },
                    "category_id": {
                        "type": "string",
                        "format": "ulid",
                        "nullable": true
                    },
                    "attributes": {
                        "$ref": "#/components/schemas/AttributeValues"
                    }
                },
                "example": {
                    "name": "Plaça de Catalunya car park",
                    "latitude": 41.387,
                    "longitude": 2.17,
                    "attributes": {
                        "owner_id": 123,
                        "open_24h": true
                    }
                }
            },
            "PoiUpdate": {
                "type": "object",
                "properties": {
                    "name": {
                        "type": "string",
                        "maxLength": 255
                    },
                    "latitude": {
                        "type": "number",
                        "minimum": -90,
                        "maximum": 90
                    },
                    "longitude": {
                        "type": "number",
                        "minimum": -180,
                        "maximum": 180
                    },
                    "category_id": {
                        "type": "string",
                        "format": "ulid",
                        "nullable": true
                    },
                    "attributes": {
                        "$ref": "#/components/schemas/AttributeValues"
                    }
                },
                "example": {
                    "attributes": {
                        "open_24h": false
                    }
                }
            },
            "Import": {
                "type": "object",
                "required": [
                    "id",
                    "status",
                    "filename",
                    "columns",
                    "total_rows",
                    "processed_rows",
                    "created",
                    "failed",
                    "limit_reached",
                    "errors",
                    "created_at",
                    "started_at",
                    "finished_at"
                ],
                "properties": {
                    "id": {
                        "type": "string",
                        "format": "ulid"
                    },
                    "status": {
                        "type": "string",
                        "enum": [
                            "queued",
                            "processing",
                            "completed",
                            "failed"
                        ]
                    },
                    "filename": {
                        "type": "string"
                    },
                    "columns": {
                        "type": "array",
                        "items": {
                            "type": "string"
                        }
                    },
                    "total_rows": {
                        "type": "integer"
                    },
                    "processed_rows": {
                        "type": "integer"
                    },
                    "created": {
                        "type": "integer"
                    },
                    "failed": {
                        "type": "integer"
                    },
                    "limit_reached": {
                        "type": "boolean"
                    },
                    "errors": {
                        "type": "array",
                        "maxItems": 100,
                        "items": {
                            "type": "object",
                            "required": [
                                "line",
                                "message"
                            ],
                            "properties": {
                                "line": {
                                    "type": "integer",
                                    "nullable": true
                                },
                                "message": {
                                    "type": "string"
                                }
                            }
                        }
                    },
                    "created_at": {
                        "type": "string",
                        "format": "date-time"
                    },
                    "started_at": {
                        "type": "string",
                        "format": "date-time",
                        "nullable": true
                    },
                    "finished_at": {
                        "type": "string",
                        "format": "date-time",
                        "nullable": true
                    }
                }
            },
            "ApiKey": {
                "type": "object",
                "required": [
                    "id",
                    "name",
                    "last_four",
                    "last_used_at",
                    "expires_at",
                    "is_active",
                    "permissions",
                    "usage"
                ],
                "properties": {
                    "id": {
                        "type": "string",
                        "format": "ulid"
                    },
                    "name": {
                        "type": "string"
                    },
                    "last_four": {
                        "type": "string"
                    },
                    "last_used_at": {
                        "type": "string",
                        "format": "date-time",
                        "nullable": true
                    },
                    "expires_at": {
                        "type": "string",
                        "format": "date-time",
                        "nullable": true
                    },
                    "is_active": {
                        "type": "boolean"
                    },
                    "permissions": {
                        "type": "array",
                        "description": "The key's permissions: `read-pois`, `create-pois`, `update-pois`, `delete-pois`, the same four for\n`attributes` and `categories`, and `plan-routes`.\n",
                        "items": {
                            "type": "object",
                            "required": [
                                "id",
                                "name"
                            ],
                            "properties": {
                                "id": {
                                    "type": "integer"
                                },
                                "name": {
                                    "type": "string"
                                }
                            }
                        },
                        "example": [
                            {
                                "id": 22,
                                "name": "read-pois"
                            },
                            {
                                "id": 23,
                                "name": "create-pois"
                            },
                            {
                                "id": 36,
                                "name": "plan-routes"
                            }
                        ]
                    },
                    "usage": {
                        "type": "object",
                        "required": [
                            "requests_last_hour",
                            "requests_last_24h",
                            "top_endpoint"
                        ],
                        "properties": {
                            "requests_last_hour": {
                                "type": "integer"
                            },
                            "requests_last_24h": {
                                "type": "integer"
                            },
                            "top_endpoint": {
                                "type": "object",
                                "nullable": true,
                                "required": [
                                    "method",
                                    "endpoint",
                                    "count"
                                ],
                                "properties": {
                                    "method": {
                                        "type": "string"
                                    },
                                    "endpoint": {
                                        "type": "string"
                                    },
                                    "count": {
                                        "type": "integer"
                                    }
                                }
                            }
                        }
                    }
                }
            },
            "Tier": {
                "type": "object",
                "required": [
                    "limit",
                    "price"
                ],
                "properties": {
                    "limit": {
                        "type": "integer"
                    },
                    "price": {
                        "type": "integer",
                        "description": "Monthly price in whole currency units."
                    }
                }
            },
            "Pricing": {
                "type": "object",
                "required": [
                    "currency",
                    "requests_per_hour",
                    "pois",
                    "presets",
                    "contact_email"
                ],
                "properties": {
                    "currency": {
                        "type": "string",
                        "example": "EUR"
                    },
                    "requests_per_hour": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/Tier"
                        }
                    },
                    "pois": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/Tier"
                        }
                    },
                    "presets": {
                        "type": "array",
                        "items": {
                            "type": "object",
                            "required": [
                                "name",
                                "requests_per_hour",
                                "pois",
                                "price"
                            ],
                            "properties": {
                                "name": {
                                    "type": "string"
                                },
                                "requests_per_hour": {
                                    "type": "integer"
                                },
                                "pois": {
                                    "type": "integer"
                                },
                                "price": {
                                    "type": "integer",
                                    "nullable": true
                                }
                            }
                        }
                    },
                    "contact_email": {
                        "type": "string",
                        "format": "email"
                    }
                }
            },
            "Location": {
                "type": "object",
                "description": "Coordinates, or `poi_id` to use the position of one of your POIs.",
                "properties": {
                    "latitude": {
                        "type": "number",
                        "minimum": -90,
                        "maximum": 90
                    },
                    "longitude": {
                        "type": "number",
                        "minimum": -180,
                        "maximum": 180
                    },
                    "poi_id": {
                        "type": "string",
                        "format": "ulid"
                    }
                },
                "example": {
                    "latitude": 41.387,
                    "longitude": 2.1701
                }
            },
            "Stop": {
                "type": "object",
                "description": "A location with an optional `id` of yours, echoed in the response.",
                "allOf": [
                    {
                        "$ref": "#/components/schemas/Location"
                    }
                ],
                "properties": {
                    "id": {
                        "type": "string",
                        "maxLength": 100
                    }
                }
            },
            "StopRef": {
                "type": "object",
                "required": [
                    "index",
                    "id",
                    "poi_id",
                    "latitude",
                    "longitude"
                ],
                "properties": {
                    "index": {
                        "type": "integer",
                        "description": "Position of the stop in the request (or in the POI selection, by ID)."
                    },
                    "id": {
                        "type": "string",
                        "nullable": true
                    },
                    "poi_id": {
                        "type": "string",
                        "format": "ulid",
                        "nullable": true
                    },
                    "latitude": {
                        "type": "number"
                    },
                    "longitude": {
                        "type": "number"
                    }
                }
            },
            "PoiSelection": {
                "type": "object",
                "description": "Selects your POIs with the filters of `GET /pois` plus `poi_ids`. A POI must match every filter; an empty\nobject selects all your POIs.\n",
                "properties": {
                    "attributes": {
                        "$ref": "#/components/schemas/AttributeValues"
                    },
                    "category_id": {
                        "type": "string",
                        "format": "ulid"
                    },
                    "category_name": {
                        "type": "string",
                        "maxLength": 255
                    },
                    "latitude": {
                        "type": "number",
                        "minimum": -90,
                        "maximum": 90
                    },
                    "longitude": {
                        "type": "number",
                        "minimum": -180,
                        "maximum": 180
                    },
                    "distance": {
                        "type": "integer",
                        "minimum": 1,
                        "maximum": 100000,
                        "default": 1000
                    },
                    "country_id": {
                        "type": "string",
                        "format": "uuid"
                    },
                    "city_id": {
                        "type": "string",
                        "format": "uuid"
                    },
                    "zipcode_id": {
                        "type": "string",
                        "format": "uuid"
                    },
                    "poi_ids": {
                        "type": "array",
                        "items": {
                            "type": "string",
                            "format": "ulid"
                        }
                    }
                }
            },
            "Profile": {
                "type": "string",
                "enum": [
                    "driving-car",
                    "driving-hgv",
                    "cycling-regular",
                    "foot-walking"
                ],
                "default": "driving-car"
            },
            "LineString": {
                "type": "object",
                "description": "GeoJSON LineString, coordinates as [longitude, latitude].",
                "required": [
                    "type",
                    "coordinates"
                ],
                "properties": {
                    "type": {
                        "type": "string",
                        "enum": [
                            "LineString"
                        ]
                    },
                    "coordinates": {
                        "type": "array",
                        "items": {
                            "type": "array",
                            "minItems": 2,
                            "maxItems": 2,
                            "items": {
                                "type": "number"
                            }
                        }
                    }
                }
            },
            "RouteRequest": {
                "type": "object",
                "required": [
                    "waypoints"
                ],
                "properties": {
                    "profile": {
                        "$ref": "#/components/schemas/Profile"
                    },
                    "waypoints": {
                        "type": "array",
                        "minItems": 2,
                        "maxItems": 50,
                        "items": {
                            "$ref": "#/components/schemas/Location"
                        }
                    },
                    "avoid": {
                        "type": "object",
                        "description": "The POIs to keep away from.",
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/PoiSelection"
                            }
                        ],
                        "properties": {
                            "radius": {
                                "type": "integer",
                                "minimum": 10,
                                "maximum": 500,
                                "default": 50,
                                "description": "Meters to keep from every POI."
                            }
                        }
                    }
                },
                "example": {
                    "profile": "driving-car",
                    "waypoints": [
                        {
                            "latitude": 41.387,
                            "longitude": 2.1701
                        },
                        {
                            "poi_id": "01JGZ8Q3N5T9B2C4D6F8H0K2M4"
                        }
                    ],
                    "avoid": {
                        "category_name": "speed-camera",
                        "radius": 100
                    }
                }
            },
            "Route": {
                "type": "object",
                "required": [
                    "profile",
                    "distance",
                    "duration",
                    "bbox",
                    "geometry",
                    "legs",
                    "waypoints",
                    "avoided"
                ],
                "properties": {
                    "profile": {
                        "$ref": "#/components/schemas/Profile"
                    },
                    "distance": {
                        "type": "number",
                        "description": "Meters."
                    },
                    "duration": {
                        "type": "number",
                        "description": "Seconds."
                    },
                    "bbox": {
                        "type": "array",
                        "description": "[west, south, east, north]",
                        "items": {
                            "type": "number"
                        }
                    },
                    "geometry": {
                        "$ref": "#/components/schemas/LineString"
                    },
                    "legs": {
                        "type": "array",
                        "items": {
                            "type": "object",
                            "required": [
                                "from",
                                "to",
                                "distance",
                                "duration"
                            ],
                            "properties": {
                                "from": {
                                    "type": "integer",
                                    "description": "Index of the waypoint the leg starts at."
                                },
                                "to": {
                                    "type": "integer"
                                },
                                "distance": {
                                    "type": "number"
                                },
                                "duration": {
                                    "type": "number"
                                }
                            }
                        }
                    },
                    "waypoints": {
                        "type": "array",
                        "items": {
                            "type": "object",
                            "required": [
                                "poi_id",
                                "latitude",
                                "longitude"
                            ],
                            "properties": {
                                "poi_id": {
                                    "type": "string",
                                    "format": "ulid",
                                    "nullable": true
                                },
                                "latitude": {
                                    "type": "number"
                                },
                                "longitude": {
                                    "type": "number"
                                }
                            }
                        }
                    },
                    "avoided": {
                        "type": "object",
                        "nullable": true,
                        "description": "The POIs the route was planned around; null when `avoid` was not sent.",
                        "required": [
                            "radius",
                            "count",
                            "poi_ids",
                            "skipped_poi_ids"
                        ],
                        "properties": {
                            "radius": {
                                "type": "integer"
                            },
                            "count": {
                                "type": "integer"
                            },
                            "poi_ids": {
                                "type": "array",
                                "items": {
                                    "type": "string",
                                    "format": "ulid"
                                }
                            },
                            "skipped_poi_ids": {
                                "type": "array",
                                "description": "Selected POIs within `radius` of a waypoint, not avoided.",
                                "items": {
                                    "type": "string",
                                    "format": "ulid"
                                }
                            }
                        }
                    }
                },
                "example": {
                    "profile": "driving-car",
                    "distance": 2710.4,
                    "duration": 452.9,
                    "bbox": [
                        2.1652,
                        41.387,
                        2.1744,
                        41.4036
                    ],
                    "geometry": {
                        "type": "LineString",
                        "coordinates": [
                            [
                                2.1701,
                                41.387
                            ],
                            [
                                2.1652,
                                41.3951
                            ],
                            [
                                2.1744,
                                41.4036
                            ]
                        ]
                    },
                    "legs": [
                        {
                            "from": 0,
                            "to": 1,
                            "distance": 2710.4,
                            "duration": 452.9
                        }
                    ],
                    "waypoints": [
                        {
                            "poi_id": null,
                            "latitude": 41.387,
                            "longitude": 2.1701
                        },
                        {
                            "poi_id": "01JGZ8Q3N5T9B2C4D6F8H0K2M4",
                            "latitude": 41.4036,
                            "longitude": 2.1744
                        }
                    ],
                    "avoided": {
                        "radius": 100,
                        "count": 1,
                        "poi_ids": [
                            "01JGZ9A1B2C3D4E5F6G7H8J9K0"
                        ],
                        "skipped_poi_ids": []
                    }
                }
            },
            "ClusterRequest": {
                "type": "object",
                "properties": {
                    "stops": {
                        "type": "array",
                        "minItems": 1,
                        "maxItems": 2000,
                        "description": "The stops. Send this or `pois`.",
                        "items": {
                            "$ref": "#/components/schemas/Stop"
                        }
                    },
                    "pois": {
                        "description": "Your POIs to cluster (up to 2,000). Send this or `stops`.",
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/PoiSelection"
                            }
                        ]
                    },
                    "clusters": {
                        "type": "integer",
                        "minimum": 1,
                        "maximum": 100,
                        "description": "Number of clusters. Send this or `max_stops`."
                    },
                    "max_stops": {
                        "type": "integer",
                        "minimum": 1,
                        "maximum": 2000,
                        "description": "Most stops per cluster; the number of clusters is the fewest that fit them."
                    },
                    "balanced": {
                        "type": "boolean",
                        "default": false,
                        "description": "Make the clusters equal in size."
                    }
                },
                "example": {
                    "stops": [
                        {
                            "id": "order-1",
                            "latitude": 41.387,
                            "longitude": 2.1701
                        },
                        {
                            "id": "order-2",
                            "latitude": 41.4036,
                            "longitude": 2.1744
                        },
                        {
                            "id": "order-3",
                            "poi_id": "01JGZ8Q3N5T9B2C4D6F8H0K2M4"
                        }
                    ],
                    "clusters": 2,
                    "balanced": true
                }
            },
            "Clusters": {
                "type": "object",
                "required": [
                    "summary",
                    "clusters"
                ],
                "properties": {
                    "summary": {
                        "type": "object",
                        "required": [
                            "stops",
                            "clusters",
                            "balanced",
                            "max_stops"
                        ],
                        "properties": {
                            "stops": {
                                "type": "integer"
                            },
                            "clusters": {
                                "type": "integer",
                                "description": "Clusters returned; fewer than requested only when stops coincide."
                            },
                            "balanced": {
                                "type": "boolean",
                                "description": "Whether equal sizes were requested."
                            },
                            "max_stops": {
                                "type": "integer",
                                "nullable": true,
                                "description": "Most stops a cluster could get: max_stops, or the balanced size; null when unbounded."
                            }
                        }
                    },
                    "clusters": {
                        "type": "array",
                        "items": {
                            "type": "object",
                            "required": [
                                "id",
                                "centroid",
                                "count",
                                "radius",
                                "stops"
                            ],
                            "properties": {
                                "id": {
                                    "type": "integer"
                                },
                                "centroid": {
                                    "type": "object",
                                    "required": [
                                        "latitude",
                                        "longitude"
                                    ],
                                    "properties": {
                                        "latitude": {
                                            "type": "number"
                                        },
                                        "longitude": {
                                            "type": "number"
                                        }
                                    }
                                },
                                "count": {
                                    "type": "integer"
                                },
                                "radius": {
                                    "type": "number",
                                    "description": "Meters from the centroid to its farthest stop."
                                },
                                "stops": {
                                    "type": "array",
                                    "items": {
                                        "$ref": "#/components/schemas/StopRef"
                                    }
                                }
                            }
                        }
                    }
                }
            },
            "DeliveryVehicle": {
                "type": "object",
                "required": [
                    "start"
                ],
                "properties": {
                    "id": {
                        "type": "string",
                        "maxLength": 100,
                        "description": "Defaults to vehicle-1, vehicle-2…"
                    },
                    "start": {
                        "$ref": "#/components/schemas/Location"
                    },
                    "end": {
                        "description": "Where the vehicle finishes. Omit to finish at its last stop.",
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/Location"
                            }
                        ]
                    },
                    "capacity": {
                        "type": "integer",
                        "minimum": 0,
                        "description": "Most units the vehicle carries; see the stops' `demand`."
                    },
                    "time_window": {
                        "type": "array",
                        "minItems": 2,
                        "maxItems": 2,
                        "description": "Working hours, [start, end] as ISO 8601 datetimes.",
                        "items": {
                            "type": "string",
                            "format": "date-time"
                        }
                    },
                    "skills": {
                        "type": "array",
                        "maxItems": 20,
                        "items": {
                            "type": "string",
                            "maxLength": 50
                        }
                    }
                }
            },
            "DeliveryStop": {
                "type": "object",
                "allOf": [
                    {
                        "$ref": "#/components/schemas/Stop"
                    }
                ],
                "properties": {
                    "service": {
                        "type": "integer",
                        "minimum": 0,
                        "maximum": 86400,
                        "default": 0,
                        "description": "Seconds spent at the stop."
                    },
                    "demand": {
                        "type": "integer",
                        "minimum": 0,
                        "default": 1,
                        "description": "Units delivered; only counts when a vehicle has a capacity."
                    },
                    "time_windows": {
                        "type": "array",
                        "minItems": 1,
                        "maxItems": 5,
                        "description": "When the stop can be served, as [start, end] pairs of ISO 8601 datetimes.",
                        "items": {
                            "type": "array",
                            "minItems": 2,
                            "maxItems": 2,
                            "items": {
                                "type": "string",
                                "format": "date-time"
                            }
                        }
                    },
                    "skills": {
                        "type": "array",
                        "maxItems": 20,
                        "description": "Only vehicles with all these skills serve the stop.",
                        "items": {
                            "type": "string",
                            "maxLength": 50
                        }
                    }
                }
            },
            "OptimizeRequest": {
                "type": "object",
                "required": [
                    "vehicles",
                    "stops"
                ],
                "properties": {
                    "profile": {
                        "$ref": "#/components/schemas/Profile"
                    },
                    "vehicles": {
                        "type": "array",
                        "minItems": 1,
                        "maxItems": 3,
                        "items": {
                            "$ref": "#/components/schemas/DeliveryVehicle"
                        }
                    },
                    "stops": {
                        "type": "array",
                        "minItems": 1,
                        "maxItems": 50,
                        "items": {
                            "$ref": "#/components/schemas/DeliveryStop"
                        }
                    }
                },
                "example": {
                    "profile": "driving-car",
                    "vehicles": [
                        {
                            "id": "van-1",
                            "start": {
                                "latitude": 41.387,
                                "longitude": 2.1701
                            },
                            "end": {
                                "latitude": 41.387,
                                "longitude": 2.1701
                            },
                            "capacity": 10,
                            "time_window": [
                                "2026-10-01T08:00:00+02:00",
                                "2026-10-01T14:00:00+02:00"
                            ]
                        }
                    ],
                    "stops": [
                        {
                            "id": "order-1",
                            "latitude": 41.4036,
                            "longitude": 2.1744,
                            "service": 300,
                            "demand": 4,
                            "time_windows": [
                                [
                                    "2026-10-01T09:00:00+02:00",
                                    "2026-10-01T10:00:00+02:00"
                                ]
                            ]
                        },
                        {
                            "id": "order-2",
                            "poi_id": "01JGZ8Q3N5T9B2C4D6F8H0K2M4",
                            "service": 120
                        }
                    ]
                }
            },
            "Optimization": {
                "type": "object",
                "required": [
                    "summary",
                    "routes",
                    "unassigned"
                ],
                "properties": {
                    "summary": {
                        "type": "object",
                        "required": [
                            "vehicles",
                            "stops",
                            "assigned",
                            "unassigned",
                            "distance",
                            "duration",
                            "service",
                            "waiting_time"
                        ],
                        "properties": {
                            "vehicles": {
                                "type": "integer",
                                "description": "Vehicles with a route."
                            },
                            "stops": {
                                "type": "integer"
                            },
                            "assigned": {
                                "type": "integer"
                            },
                            "unassigned": {
                                "type": "integer"
                            },
                            "distance": {
                                "type": "number",
                                "description": "Meters driven by all vehicles."
                            },
                            "duration": {
                                "type": "integer",
                                "description": "Seconds driven by all vehicles."
                            },
                            "service": {
                                "type": "integer"
                            },
                            "waiting_time": {
                                "type": "integer"
                            }
                        }
                    },
                    "routes": {
                        "type": "array",
                        "items": {
                            "type": "object",
                            "required": [
                                "vehicle",
                                "stops",
                                "distance",
                                "duration",
                                "service",
                                "waiting_time",
                                "load",
                                "start_at",
                                "end_at",
                                "geometry",
                                "steps"
                            ],
                            "properties": {
                                "vehicle": {
                                    "type": "string",
                                    "description": "The vehicle's `id`."
                                },
                                "stops": {
                                    "type": "integer"
                                },
                                "distance": {
                                    "type": "number"
                                },
                                "duration": {
                                    "type": "integer",
                                    "description": "Seconds driving."
                                },
                                "service": {
                                    "type": "integer"
                                },
                                "waiting_time": {
                                    "type": "integer"
                                },
                                "load": {
                                    "type": "integer",
                                    "nullable": true,
                                    "description": "Units loaded at the start; null without capacities."
                                },
                                "start_at": {
                                    "type": "string",
                                    "format": "date-time"
                                },
                                "end_at": {
                                    "type": "string",
                                    "format": "date-time"
                                },
                                "geometry": {
                                    "type": "object",
                                    "nullable": true,
                                    "allOf": [
                                        {
                                            "$ref": "#/components/schemas/LineString"
                                        }
                                    ]
                                },
                                "steps": {
                                    "type": "array",
                                    "items": {
                                        "type": "object",
                                        "required": [
                                            "type",
                                            "latitude",
                                            "longitude",
                                            "arrival",
                                            "departure",
                                            "waiting_time",
                                            "service",
                                            "distance",
                                            "duration",
                                            "load"
                                        ],
                                        "properties": {
                                            "type": {
                                                "type": "string",
                                                "enum": [
                                                    "start",
                                                    "stop",
                                                    "end"
                                                ]
                                            },
                                            "index": {
                                                "type": "integer",
                                                "description": "Only on stops, like `id` and `poi_id`."
                                            },
                                            "id": {
                                                "type": "string",
                                                "nullable": true
                                            },
                                            "poi_id": {
                                                "type": "string",
                                                "format": "ulid",
                                                "nullable": true
                                            },
                                            "latitude": {
                                                "type": "number"
                                            },
                                            "longitude": {
                                                "type": "number"
                                            },
                                            "arrival": {
                                                "type": "string",
                                                "format": "date-time"
                                            },
                                            "departure": {
                                                "type": "string",
                                                "format": "date-time"
                                            },
                                            "waiting_time": {
                                                "type": "integer",
                                                "description": "Seconds waiting for the stop's time window."
                                            },
                                            "service": {
                                                "type": "integer"
                                            },
                                            "distance": {
                                                "type": "number",
                                                "description": "Meters driven so far."
                                            },
                                            "duration": {
                                                "type": "integer",
                                                "description": "Seconds driven so far."
                                            },
                                            "load": {
                                                "type": "integer",
                                                "nullable": true,
                                                "description": "Units on board after the step."
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "unassigned": {
                        "type": "array",
                        "items": {
                            "type": "object",
                            "required": [
                                "index",
                                "id",
                                "poi_id",
                                "latitude",
                                "longitude",
                                "reason"
                            ],
                            "properties": {
                                "index": {
                                    "type": "integer",
                                    "description": "Position of the stop in the request."
                                },
                                "id": {
                                    "type": "string",
                                    "nullable": true
                                },
                                "poi_id": {
                                    "type": "string",
                                    "format": "ulid",
                                    "nullable": true
                                },
                                "latitude": {
                                    "type": "number"
                                },
                                "longitude": {
                                    "type": "number"
                                },
                                "reason": {
                                    "type": "string"
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
