# Authenticate (https://docs.roundtrip.ai/docs/api-reference/authentication/post-authenticate)
POST /authenticate
Authenticate a client to obtain an access token using a client ID and
secret key. The access token is required to make authenticated requests to
the API. The token will expire after the duration specified in the
response.
## OpenAPI specification
```json
{
"servers": [
{
"url": "https://easyroutes.roundtrip.ai/api/2024-07"
}
],
"tags": [
"Authentication"
],
"summary": "Authenticate",
"description": "Authenticate a client to obtain an access token using a client ID and\n secret key. The access token is required to make authenticated requests to\n the API. The token will expire after the duration specified in the\n response.",
"operationId": "Authenticate",
"requestBody": {
"content": {
"application/json": {
"schema": {
"title": "AuthenticateRequest",
"required": [
"clientId",
"clientSecret"
],
"type": "object",
"properties": {
"clientId": {
"type": "string",
"description": "The client ID from EasyRoutes settings.",
"examples": [
"m2m-client-test-example-shop"
]
},
"clientSecret": {
"type": "string",
"description": "The client secret from EasyRoutes settings.",
"examples": [
"example_client_secret"
]
}
},
"description": "Request to authenticate a client and obtain an access token."
}
}
},
"required": true
},
"responses": {
"200": {
"description": "OK",
"content": {
"application/json": {
"schema": {
"title": "AuthenticateResponse",
"required": [
"accessToken",
"expiresInSeconds",
"organization"
],
"type": "object",
"properties": {
"accessToken": {
"type": "string",
"description": "The access token to use for authenticated requests.",
"examples": [
"eyJh..."
]
},
"expiresInSeconds": {
"pattern": "^[0-9]+$",
"type": "string",
"description": "The duration in seconds until the access token expires.",
"format": "int64",
"examples": [
"3600"
]
},
"organization": {
"type": "string",
"description": "The unique organization identifier. For EasyRoutes on Shopify, this will be\n the Shopify shop. For EasyRoutes on web, this is a unique identifier based\n on the organization name.",
"examples": [
"example-shop.myshopify.com"
]
}
},
"description": "Authentication response containing an access token and expiration duration."
}
}
}
},
"400": {
"description": "The request is missing a client ID or client secret.",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"code": {
"type": "integer",
"description": "The status code, which should be an enum value of [google.rpc.Code][google.rpc.Code].",
"format": "int32"
},
"message": {
"type": "string",
"description": "A developer-facing error message, which should be in English. Any user-facing error message should be localized and sent in the [google.rpc.Status.details][google.rpc.Status.details] field, or localized by the client."
},
"details": {
"type": "array",
"items": {
"type": "object",
"properties": {
"@type": {
"type": "string",
"description": "The type of the serialized message."
}
},
"additionalProperties": true,
"description": "Contains an arbitrary serialized message along with a @type that describes the type of the serialized message."
},
"description": "A list of messages that carry the error details. There is a common set of message types for APIs to use."
}
},
"description": "The `Status` type defines a logical error model that is suitable for different programming environments, including REST APIs and RPC APIs. It is used by [gRPC](https://github.com/grpc). Each `Status` message contains three pieces of data: error code, error message, and error details. You can find out more about this error model and how to work with it in the [API Design Guide](https://cloud.google.com/apis/design/errors)."
},
"examples": {
"missingClientId": {
"summary": "Missing client ID",
"value": {
"code": 3,
"message": "missing client_id"
}
},
"missingClientSecret": {
"summary": "Missing client secret",
"value": {
"code": 3,
"message": "missing client_secret"
}
}
}
}
}
},
"403": {
"description": "The client could not be authenticated, or API access is not enabled or has been blocked for the shop.",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"code": {
"type": "integer",
"description": "The status code, which should be an enum value of [google.rpc.Code][google.rpc.Code].",
"format": "int32"
},
"message": {
"type": "string",
"description": "A developer-facing error message, which should be in English. Any user-facing error message should be localized and sent in the [google.rpc.Status.details][google.rpc.Status.details] field, or localized by the client."
},
"details": {
"type": "array",
"items": {
"type": "object",
"properties": {
"@type": {
"type": "string",
"description": "The type of the serialized message."
}
},
"additionalProperties": true,
"description": "Contains an arbitrary serialized message along with a @type that describes the type of the serialized message."
},
"description": "A list of messages that carry the error details. There is a common set of message types for APIs to use."
}
},
"description": "The `Status` type defines a logical error model that is suitable for different programming environments, including REST APIs and RPC APIs. It is used by [gRPC](https://github.com/grpc). Each `Status` message contains three pieces of data: error code, error message, and error details. You can find out more about this error model and how to work with it in the [API Design Guide](https://cloud.google.com/apis/design/errors)."
},
"examples": {
"invalidCredentials": {
"summary": "Invalid client credentials",
"value": {
"code": 7,
"message": "failed to authenticate client"
}
},
"apiAccessNotEnabled": {
"summary": "API access not enabled",
"value": {
"code": 7,
"message": "API access not enabled for shop"
}
},
"apiAccessBlocked": {
"summary": "API access blocked",
"value": {
"code": 7,
"message": "API access blocked. Please contact support."
}
}
}
}
}
},
"404": {
"description": "No shop was found for the provided client ID.",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"code": {
"type": "integer",
"description": "The status code, which should be an enum value of [google.rpc.Code][google.rpc.Code].",
"format": "int32"
},
"message": {
"type": "string",
"description": "A developer-facing error message, which should be in English. Any user-facing error message should be localized and sent in the [google.rpc.Status.details][google.rpc.Status.details] field, or localized by the client."
},
"details": {
"type": "array",
"items": {
"type": "object",
"properties": {
"@type": {
"type": "string",
"description": "The type of the serialized message."
}
},
"additionalProperties": true,
"description": "Contains an arbitrary serialized message along with a @type that describes the type of the serialized message."
},
"description": "A list of messages that carry the error details. There is a common set of message types for APIs to use."
}
},
"description": "The `Status` type defines a logical error model that is suitable for different programming environments, including REST APIs and RPC APIs. It is used by [gRPC](https://github.com/grpc). Each `Status` message contains three pieces of data: error code, error message, and error details. You can find out more about this error model and how to work with it in the [API Design Guide](https://cloud.google.com/apis/design/errors)."
},
"examples": {
"default": {
"value": {
"code": 5,
"message": "shop not found"
}
}
}
}
}
},
"500": {
"description": "An internal error occurred while authenticating the client.",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"code": {
"type": "integer",
"description": "The status code, which should be an enum value of [google.rpc.Code][google.rpc.Code].",
"format": "int32"
},
"message": {
"type": "string",
"description": "A developer-facing error message, which should be in English. Any user-facing error message should be localized and sent in the [google.rpc.Status.details][google.rpc.Status.details] field, or localized by the client."
},
"details": {
"type": "array",
"items": {
"type": "object",
"properties": {
"@type": {
"type": "string",
"description": "The type of the serialized message."
}
},
"additionalProperties": true,
"description": "Contains an arbitrary serialized message along with a @type that describes the type of the serialized message."
},
"description": "A list of messages that carry the error details. There is a common set of message types for APIs to use."
}
},
"description": "The `Status` type defines a logical error model that is suitable for different programming environments, including REST APIs and RPC APIs. It is used by [gRPC](https://github.com/grpc). Each `Status` message contains three pieces of data: error code, error message, and error details. You can find out more about this error model and how to work with it in the [API Design Guide](https://cloud.google.com/apis/design/errors)."
},
"examples": {
"default": {
"value": {
"code": 13,
"message": "error looking up shop feature flags"
}
}
}
}
}
},
"default": {
"description": "Default error response",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"code": {
"type": "integer",
"description": "The status code, which should be an enum value of [google.rpc.Code][google.rpc.Code].",
"format": "int32"
},
"message": {
"type": "string",
"description": "A developer-facing error message, which should be in English. Any user-facing error message should be localized and sent in the [google.rpc.Status.details][google.rpc.Status.details] field, or localized by the client."
},
"details": {
"type": "array",
"items": {
"type": "object",
"properties": {
"@type": {
"type": "string",
"description": "The type of the serialized message."
}
},
"additionalProperties": true,
"description": "Contains an arbitrary serialized message along with a @type that describes the type of the serialized message."
},
"description": "A list of messages that carry the error details. There is a common set of message types for APIs to use."
}
},
"description": "The `Status` type defines a logical error model that is suitable for different programming environments, including REST APIs and RPC APIs. It is used by [gRPC](https://github.com/grpc). Each `Status` message contains three pieces of data: error code, error message, and error details. You can find out more about this error model and how to work with it in the [API Design Guide](https://cloud.google.com/apis/design/errors)."
}
}
}
}
},
"security": [
{}
]
}
```
# Get driver (https://docs.roundtrip.ai/docs/api-reference/drivers/get-drivers-id)
GET /drivers/{id}
Fetch a single driver by ID.
## OpenAPI specification
```json
{
"servers": [
{
"url": "https://easyroutes.roundtrip.ai/api/2024-07"
}
],
"tags": [
"Drivers"
],
"summary": "Get driver",
"description": "Fetch a single driver by ID.",
"operationId": "GetDriver",
"parameters": [
{
"name": "id",
"in": "path",
"description": "The ID of the driver to fetch.",
"required": true,
"schema": {
"type": "string",
"examples": [
"drv-123e4567-e89b-12d3-a456-426614174000"
]
}
}
],
"responses": {
"200": {
"description": "OK",
"content": {
"application/json": {
"schema": {
"title": "Driver",
"required": [
"id"
],
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Driver ID (e.g. `\"drv-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"drv-123e4567-e89b-12d3-a456-426614174000"
]
},
"firstName": {
"type": "string",
"description": "Driver first name (e.g. `\"John\"`).",
"examples": [
"John"
]
},
"lastName": {
"type": "string",
"description": "Driver last name (e.g. `\"Doe\"`).",
"examples": [
"Doe"
]
},
"phone": {
"type": "string",
"description": "Driver phone number in [E.164 format](https://en.wikipedia.org/wiki/E.164)\n (e.g. `\"+14265551000\"`).",
"examples": [
"+14265551000"
]
},
"status": {
"enum": [
"UNKNOWN",
"ACTIVE",
"INACTIVE",
"ARCHIVED"
],
"type": "string",
"description": "Shop driver status. (e.g. `ACTIVE`).",
"format": "enum",
"examples": [
"ACTIVE"
]
}
},
"description": "A driver who is assigned to a route."
}
}
}
},
"default": {
"description": "Default error response",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"code": {
"type": "integer",
"description": "The status code, which should be an enum value of [google.rpc.Code][google.rpc.Code].",
"format": "int32"
},
"message": {
"type": "string",
"description": "A developer-facing error message, which should be in English. Any user-facing error message should be localized and sent in the [google.rpc.Status.details][google.rpc.Status.details] field, or localized by the client."
},
"details": {
"type": "array",
"items": {
"type": "object",
"properties": {
"@type": {
"type": "string",
"description": "The type of the serialized message."
}
},
"additionalProperties": true,
"description": "Contains an arbitrary serialized message along with a @type that describes the type of the serialized message."
},
"description": "A list of messages that carry the error details. There is a common set of message types for APIs to use."
}
},
"description": "The `Status` type defines a logical error model that is suitable for different programming environments, including REST APIs and RPC APIs. It is used by [gRPC](https://github.com/grpc). Each `Status` message contains three pieces of data: error code, error message, and error details. You can find out more about this error model and how to work with it in the [API Design Guide](https://cloud.google.com/apis/design/errors)."
}
}
}
}
},
"security": [
{
"bearerAuth": []
}
],
"components": {
"securitySchemes": {
"bearerAuth": {
"type": "http",
"description": "Access token from `/authenticate`",
"scheme": "bearer",
"bearerFormat": "JWT"
}
}
}
}
```
# List drivers (https://docs.roundtrip.ai/docs/api-reference/drivers/get-drivers)
GET /drivers
Fetch a list of all drivers associated with the shop. By default this
returns all drivers but can optionally filter to specific statuses (i.e.
`ACTIVE`, `INACTIVE`, or `ARCHIVED`). Invited drivers that are still
pending sign-up are not returned by this API.
## OpenAPI specification
```json
{
"servers": [
{
"url": "https://easyroutes.roundtrip.ai/api/2024-07"
}
],
"tags": [
"Drivers"
],
"summary": "List drivers",
"description": "Fetch a list of all drivers associated with the shop. By default this\n returns all drivers but can optionally filter to specific statuses (i.e.\n `ACTIVE`, `INACTIVE`, or `ARCHIVED`). Invited drivers that are still\n pending sign-up are not returned by this API.",
"operationId": "ListDrivers",
"parameters": [
{
"name": "query.limit",
"in": "query",
"description": "Maximum number of drivers to return. Must be less than or equal to `200`.\n Defaults to `20`.",
"schema": {
"maximum": 200,
"type": "integer",
"format": "int32",
"examples": [
50
]
}
},
{
"name": "query.status",
"in": "query",
"description": "Filter drivers by status. You can specify multiple statuses by repeating\n the query parameter, i.e. `?status=ACTIVE&status=INACTIVE`.",
"schema": {
"type": "array",
"items": {
"enum": [
"UNKNOWN",
"ACTIVE",
"INACTIVE",
"ARCHIVED"
],
"type": "string",
"format": "enum"
},
"examples": [
[
"ACTIVE"
]
]
}
},
{
"name": "cursor",
"in": "query",
"description": "Cursor to fetch the next page of results (if available). Should only be set\n on subsequent requests.",
"schema": {
"type": "string",
"examples": [
"eyJpZCI6IjEyMyJ9"
]
}
}
],
"responses": {
"200": {
"description": "OK",
"content": {
"application/json": {
"schema": {
"title": "ListDriversResponse",
"type": "object",
"properties": {
"drivers": {
"type": "array",
"items": {
"title": "Driver",
"required": [
"id"
],
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Driver ID (e.g. `\"drv-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"drv-123e4567-e89b-12d3-a456-426614174000"
]
},
"firstName": {
"type": "string",
"description": "Driver first name (e.g. `\"John\"`).",
"examples": [
"John"
]
},
"lastName": {
"type": "string",
"description": "Driver last name (e.g. `\"Doe\"`).",
"examples": [
"Doe"
]
},
"phone": {
"type": "string",
"description": "Driver phone number in [E.164 format](https://en.wikipedia.org/wiki/E.164)\n (e.g. `\"+14265551000\"`).",
"examples": [
"+14265551000"
]
},
"status": {
"enum": [
"UNKNOWN",
"ACTIVE",
"INACTIVE",
"ARCHIVED"
],
"type": "string",
"description": "Shop driver status. (e.g. `ACTIVE`).",
"format": "enum",
"examples": [
"ACTIVE"
]
}
},
"description": "A driver who is assigned to a route."
},
"description": "List of drivers."
},
"nextCursor": {
"type": "string",
"description": "Cursor to fetch the next page of results (if available).",
"examples": [
"eyJsaW1pdCI6MjB9"
]
}
}
}
}
}
},
"default": {
"description": "Default error response",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"code": {
"type": "integer",
"description": "The status code, which should be an enum value of [google.rpc.Code][google.rpc.Code].",
"format": "int32"
},
"message": {
"type": "string",
"description": "A developer-facing error message, which should be in English. Any user-facing error message should be localized and sent in the [google.rpc.Status.details][google.rpc.Status.details] field, or localized by the client."
},
"details": {
"type": "array",
"items": {
"type": "object",
"properties": {
"@type": {
"type": "string",
"description": "The type of the serialized message."
}
},
"additionalProperties": true,
"description": "Contains an arbitrary serialized message along with a @type that describes the type of the serialized message."
},
"description": "A list of messages that carry the error details. There is a common set of message types for APIs to use."
}
},
"description": "The `Status` type defines a logical error model that is suitable for different programming environments, including REST APIs and RPC APIs. It is used by [gRPC](https://github.com/grpc). Each `Status` message contains three pieces of data: error code, error message, and error details. You can find out more about this error model and how to work with it in the [API Design Guide](https://cloud.google.com/apis/design/errors)."
}
}
}
}
},
"security": [
{
"bearerAuth": []
}
],
"components": {
"securitySchemes": {
"bearerAuth": {
"type": "http",
"description": "Access token from `/authenticate`",
"scheme": "bearer",
"bearerFormat": "JWT"
}
}
}
}
```
# API Reference (https://docs.roundtrip.ai/docs/api-reference)
The EasyRoutes API allows you to programmatically manage your routes and stops. For an overview of authentication, base URLs, error handling, and pagination, see the [Overview](https://docs.roundtrip.ai/docs.md).
## Endpoints [#endpoints]
### Authentication [#authentication]
* [**Authenticate** - POST](https://docs.roundtrip.ai/docs/api-reference/authentication/post-authenticate.md) | Authenticate a client to obtain an access token using a client ID and secret key.
### Drivers [#drivers]
* [**List drivers** - GET](https://docs.roundtrip.ai/docs/api-reference/drivers/get-drivers.md) | Fetch a list of all drivers associated with the shop.
* [**Get driver** - GET](https://docs.roundtrip.ai/docs/api-reference/drivers/get-drivers-id.md) | Fetch a single driver by ID.
### Routes [#routes]
* [**List routes** - GET](https://docs.roundtrip.ai/docs/api-reference/routes/get-routes.md) | Fetch a list of routes based on the provided query.
* [**Create route** - POST](https://docs.roundtrip.ai/docs/api-reference/routes/post-routes.md) | Create an empty route with a specified start and end location.
* [**Get route** - GET](https://docs.roundtrip.ai/docs/api-reference/routes/get-routes-id.md) | Fetch a single route by ID.
* [**Update route** - PATCH](https://docs.roundtrip.ai/docs/api-reference/routes/patch-routes-routeId.md) | Updates top-level fields on a route by route ID.
* [**Dispatch route** - POST](https://docs.roundtrip.ai/docs/api-reference/routes/post-routes-routeId-dispatch.md) | Dispatches a route, making it visible on the EasyRoutes Driver App.
* [**Undispatch route** - DELETE](https://docs.roundtrip.ai/docs/api-reference/routes/delete-routes-routeId-dispatch.md) | Undispatches a route, revoking driver access on the EasyRoutes Driver App.
* [**Unassign route driver** - DELETE](https://docs.roundtrip.ai/docs/api-reference/routes/delete-routes-routeId-driver.md) | Unassigns driver from a route by route ID.
* [**Assign route driver** - PUT](https://docs.roundtrip.ai/docs/api-reference/routes/put-routes-routeId-driver.md) | Assigns a driver to a route by route ID.
* [**Update route end location** - PATCH](https://docs.roundtrip.ai/docs/api-reference/routes/patch-routes-routeId-end-location.md) | Updates the address and/or coordinates for a route's end location by route ID, or sets one if the route currently has none (in which case `address` must be included in `updateMask`).
* [**Update route end tasks** - PUT](https://docs.roundtrip.ai/docs/api-reference/routes/put-routes-routeId-end-tasks.md) | Updates the tasks required to complete a route by route ID.
* [**Resync route orders** - POST](https://docs.roundtrip.ai/docs/api-reference/routes/post-routes-routeId-resync-orders.md) | Refreshes each order-backed stop's order data from Shopify with the latest fulfillment status, item updates, notes, and tags, and reconciles the route's stops against the changes.
* [**Update route start location** - PATCH](https://docs.roundtrip.ai/docs/api-reference/routes/patch-routes-routeId-start-location.md) | Updates the address and/or coordinates for a route's start location by route ID.
* [**Update route start tasks** - PUT](https://docs.roundtrip.ai/docs/api-reference/routes/put-routes-routeId-start-tasks.md) | Updates the tasks required before starting a route by route ID.
* [**Unassign route vehicle** - DELETE](https://docs.roundtrip.ai/docs/api-reference/routes/delete-routes-routeId-vehicle.md) | Unassigns vehicle from a route by route ID.
* [**Assign route vehicle** - PUT](https://docs.roundtrip.ai/docs/api-reference/routes/put-routes-routeId-vehicle.md) | Assigns a vehicle to a route by route ID.
### Stops [#stops]
* [**Reoptimize route** - POST](https://docs.roundtrip.ai/docs/api-reference/stops/post-routes-id-reoptimize.md) | Reoptimizes a route according to the currently configured route options.
* [**Add route stops** - POST](https://docs.roundtrip.ai/docs/api-reference/stops/post-routes-routeId-stops.md) | Adds stops to a route by route ID.
* [**Delete route stops** - DELETE](https://docs.roundtrip.ai/docs/api-reference/stops/delete-routes-routeId-stops-stopIds.md) | Deletes one or more stops from a route by route ID and stop IDs.
* [**Get route stop** - GET](https://docs.roundtrip.ai/docs/api-reference/stops/get-routes-routeId-stops-stopId.md) | Fetch a single stop on a route by route ID and stop ID.
* [**Update route stop** - PATCH](https://docs.roundtrip.ai/docs/api-reference/stops/patch-routes-routeId-stops-stopId.md) | Updates an imported stop on a route by route ID and stop ID.
* [**Update route stop items** - PUT](https://docs.roundtrip.ai/docs/api-reference/stops/put-routes-routeId-stops-stopId-items.md) | Updates the items for an imported stop on a route.
* [**Update route stop location** - PATCH](https://docs.roundtrip.ai/docs/api-reference/stops/patch-routes-routeId-stops-stopId-location.md) | Updates the address and/or planned coordinates for a stop on a route by route ID and stop ID.
* [**Reorder route stop** - PUT](https://docs.roundtrip.ai/docs/api-reference/stops/put-routes-routeId-stops-stopId-position.md) | Moves a stop on a route to a specific 0-based final index in the `stops` list.
* [**Update route stop tasks** - PUT](https://docs.roundtrip.ai/docs/api-reference/stops/put-routes-routeId-stops-stopId-tasks.md) | Updates the tasks for an imported stop on a route.
* [**List imported stops** - GET](https://docs.roundtrip.ai/docs/api-reference/stops/get-stops-imports.md) | Fetch a list of imported stops.
* [**Import stops** - POST](https://docs.roundtrip.ai/docs/api-reference/stops/post-stops-imports.md) | Import stops into EasyRoutes from an external source.
* [**Get imported stop** - GET](https://docs.roundtrip.ai/docs/api-reference/stops/get-stops-imports-id.md) | Fetch a single imported stop by ID.
* [**Update imported stop** - PATCH](https://docs.roundtrip.ai/docs/api-reference/stops/patch-stops-imports-id.md) | Updates top-level fields on an existing imported stop by ID, without needing to re-send the full stop payload via ImportStops.
* [**Delete imported stop** - DELETE](https://docs.roundtrip.ai/docs/api-reference/stops/delete-stops-imports-id.md) | Delete an imported stop by ID.
* [**Update imported stop items** - PUT](https://docs.roundtrip.ai/docs/api-reference/stops/put-stops-imports-id-items.md) | Updates the items on an existing imported stop by ID, without needing to re-send the full stop payload via ImportStops.
* [**Update imported stop location** - PATCH](https://docs.roundtrip.ai/docs/api-reference/stops/patch-stops-imports-id-location.md) | Updates the address and/or coordinates for an imported stop by ID.
* [**Get imported stop route info** - GET](https://docs.roundtrip.ai/docs/api-reference/stops/get-stops-imports-id-routes.md) | Fetch the route and stop IDs for an imported stop that has been added to one or more routes.
* [**Update imported stop tasks** - PUT](https://docs.roundtrip.ai/docs/api-reference/stops/put-stops-imports-id-tasks.md) | Updates the tasks on an existing imported stop by ID, without needing to re-send the full stop payload via ImportStops.
* [**Get Shopify stop route info** - GET](https://docs.roundtrip.ai/docs/api-reference/stops/get-stops-shopify-id-routes.md) | Fetch the route and stop IDs for a Shopify order that has been added to one or more routes.
### Vehicles [#vehicles]
* [**List vehicles** - GET](https://docs.roundtrip.ai/docs/api-reference/vehicles/get-vehicles.md) | Fetch a paginated list of vehicles associated with the shop.
* [**Get vehicle** - GET](https://docs.roundtrip.ai/docs/api-reference/vehicles/get-vehicles-id.md) | Fetch a single vehicle by ID.
### Webhooks [#webhooks]
* [**List webhook subscriptions** - GET](https://docs.roundtrip.ai/docs/api-reference/webhooks/get-webhooks.md) | Fetch a list of all webhook subscriptions.
* [**Subscribe webhook** - POST](https://docs.roundtrip.ai/docs/api-reference/webhooks/post-webhooks.md) | Creates a new webhook subscription to receive events from EasyRoutes.
* [**Unsubscribe webhook** - DELETE](https://docs.roundtrip.ai/docs/api-reference/webhooks/delete-webhooks-id.md) | Unsubscribe from a webhook by ID.
# Undispatch route (https://docs.roundtrip.ai/docs/api-reference/routes/delete-routes-routeId-dispatch)
DELETE /routes/{routeId}/dispatch
Undispatches a route, revoking driver access on the EasyRoutes Driver App.
If the route is not currently dispatched, this endpoint will result in a
no-op. The response will include the updated route.
## OpenAPI specification
```json
{
"servers": [
{
"url": "https://easyroutes.roundtrip.ai/api/2024-07"
}
],
"tags": [
"Routes"
],
"summary": "Undispatch route",
"description": "Undispatches a route, revoking driver access on the EasyRoutes Driver App.\n If the route is not currently dispatched, this endpoint will result in a\n no-op. The response will include the updated route.",
"operationId": "UndispatchRoute",
"parameters": [
{
"name": "routeId",
"in": "path",
"description": "The ID of the route to undispatch.",
"required": true,
"schema": {
"type": "string",
"examples": [
"rte-123e4567-e89b-12d3-a456-426614174000"
]
}
},
{
"name": "Idempotency-Key",
"in": "header",
"description": "A unique key for safely retrying this operation. For more information read [our guide](https://docs.roundtrip.ai/docs/concepts/idempotency.md).",
"schema": {
"maxLength": 255,
"minLength": 1,
"type": "string"
},
"examples": {
"default": {
"value": "550e8400-e29b-41d4-a716-446655440000"
}
}
}
],
"responses": {
"200": {
"description": "OK",
"headers": {
"Idempotency-Key": {
"description": "The idempotency key associated with the response.",
"schema": {
"type": "string"
}
},
"Idempotency-Replayed": {
"description": "Whether the response was replayed from a previous request.",
"schema": {
"type": "boolean"
}
}
},
"content": {
"application/json": {
"schema": {
"title": "Route",
"required": [
"id",
"name",
"stops",
"createdAt",
"updatedAt",
"totalDistanceMeters",
"totalItemQuantity",
"totalItemGrams",
"optimized"
],
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Route ID (e.g. `\"rte-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"rte-123e4567-e89b-12d3-a456-426614174000"
]
},
"name": {
"type": "string",
"description": "Route name (e.g. `\"Morning route\"`).",
"examples": [
"Morning route"
]
},
"driver": {
"allOf": [
{
"title": "Driver",
"required": [
"id"
],
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Driver ID (e.g. `\"drv-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"drv-123e4567-e89b-12d3-a456-426614174000"
]
},
"firstName": {
"type": "string",
"description": "Driver first name (e.g. `\"John\"`).",
"examples": [
"John"
]
},
"lastName": {
"type": "string",
"description": "Driver last name (e.g. `\"Doe\"`).",
"examples": [
"Doe"
]
},
"phone": {
"type": "string",
"description": "Driver phone number in [E.164 format](https://en.wikipedia.org/wiki/E.164)\n (e.g. `\"+14265551000\"`).",
"examples": [
"+14265551000"
]
},
"status": {
"enum": [
"UNKNOWN",
"ACTIVE",
"INACTIVE",
"ARCHIVED"
],
"type": "string",
"description": "Shop driver status. (e.g. `ACTIVE`).",
"format": "enum",
"examples": [
"ACTIVE"
]
}
},
"description": "A driver who is assigned to a route."
}
],
"description": "Assigned driver for the route."
},
"start": {
"allOf": [
{
"title": "RouteStart",
"type": "object",
"properties": {
"address": {
"allOf": [
{
"title": "Address",
"type": "object",
"properties": {
"address1": {
"type": "string",
"description": "Street address line 1 (e.g. `\"123 Main St\"`).",
"examples": [
"123 Main St"
]
},
"address2": {
"type": "string",
"description": "Street address line 2 (e.g. `\"Apt 101\"`).",
"examples": [
"Apt 3B"
]
},
"city": {
"type": "string",
"description": "City name (e.g. `\"New York\"`).",
"examples": [
"New York"
]
},
"provinceCode": {
"type": "string",
"description": "Province or state as subdivision codes in\n [ISO 3166-2](https://en.wikipedia.org/wiki/ISO_3166-2) format without the\n country prefix (e.g. `\"NY\"` for New York).",
"examples": [
"NY"
]
},
"countryCode": {
"type": "string",
"description": "Country code (e.g. `\"US\"`).",
"examples": [
"US"
]
},
"zip": {
"type": "string",
"description": "Postal or ZIP code (e.g. `\"10001\"`).",
"examples": [
"10001"
]
}
},
"description": "A physical street address."
}
],
"description": "The start address of the route.",
"examples": [
{
"address1": "123 Main St",
"address2": "Apt 3B",
"city": "New York",
"provinceCode": "NY",
"countryCode": "US",
"zip": "10001"
}
]
},
"tasks": {
"type": "array",
"items": {
"title": "Task",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Task ID (e.g. `\"tsk-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"tsk-123e4567-e89b-12d3-a456-426614174000"
]
},
"title": {
"type": "string",
"description": "Task title (e.g. `\"Delivery checklist\"`).",
"examples": [
"Delivery checklist"
]
},
"type": {
"enum": [
"UNKNOWN",
"CHECKBOXES",
"RADIO_BUTTONS",
"TEXT_INPUT",
"DECIMAL_INPUT",
"SCANNER_INPUT"
],
"type": "string",
"description": "Task type.",
"format": "enum",
"examples": [
"TEXT_INPUT"
]
},
"items": {
"type": "array",
"items": {
"title": "TaskItem",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Item ID (e.g. `\"itm-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"itm-123e4567-e89b-12d3-a456-426614174000"
]
},
"title": {
"type": "string",
"description": "Item title (e.g. `\"Pick up package\"`).",
"examples": [
"Pick up package"
]
},
"complete": {
"type": "boolean",
"description": "Whether the item is completed.",
"examples": [
true
]
},
"updatedAt": {
"type": "string",
"description": "Timestamp when the item was last updated.",
"format": "date-time",
"examples": [
"2026-03-30T13:00:00Z"
]
}
},
"description": "An item within a task. For `CHECKBOXES`, each item on a task may be completed\n independently. For `RADIO_BUTTONS`, at most one item will be completed."
},
"description": "Task items (populated for `CHECKBOXES` and `RADIO_BUTTONS`).",
"examples": [
[]
]
},
"input": {
"allOf": [
{
"title": "TaskInput",
"type": "object",
"properties": {
"value": {
"type": "string",
"description": "Input value.",
"examples": [
"020123456789"
]
},
"updatedAt": {
"type": "string",
"description": "Timestamp when the input was last updated.",
"format": "date-time",
"examples": [
"2026-03-30T13:00:00Z"
]
},
"inputMethod": {
"enum": [
"UNKNOWN",
"SCANNED"
],
"type": "string",
"description": "Whether input was scanned (e.g. a scanned barcode)",
"format": "enum",
"examples": [
"SCANNED"
]
}
},
"description": "Captured driver input for a task. The value may be text for `TEXT_INPUT`\n tasks or a string decimal number for `DECIMAL_INPUT` tasks."
}
],
"description": "Task input (populated for `TEXT_INPUT` and `DECIMAL_INPUT`)."
},
"requiredToMarkStopAsDelivered": {
"type": "boolean",
"description": "Whether the task is required to mark the stop as completed. In the case of\n tasks on `RouteStart`, this represents tasks required for starting the\n route. In the case of tasks on `RouteEnd`, this represents tasks required\n for completing the route.",
"examples": [
true
]
},
"requiredToMarkStopAsAttempted": {
"type": "boolean",
"description": "Whether the task is required to mark the stop as attempted.",
"examples": [
true
]
}
},
"description": "A task to be completed at a stop, or at the start or end of a route. Tasks\n may have one or more items for `CHECKBOXES` or `RADIO_BUTTONS`, or may have\n an input for `TEXT_INPUT` or `DECIMAL_INPUT`."
},
"description": "Tasks to complete before starting the route."
},
"status": {
"enum": [
"UNKNOWN",
"STARTED"
],
"type": "string",
"description": "Status indicating whether the route has been started.",
"format": "enum",
"examples": [
"STARTED"
]
},
"updatedStart": {
"type": "string",
"description": "Updated start time for the route. If the route is started, this will be the\n actual start time.",
"format": "date-time",
"examples": [
"2026-03-30T09:05:00Z"
]
},
"scheduledStart": {
"type": "string",
"description": "Scheduled start time for the route (same as `scheduledFor` on the route).",
"format": "date-time",
"examples": [
"2026-03-30T09:00:00Z"
]
},
"photos": {
"type": "array",
"items": {
"title": "StopAttachment",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Attachment ID (e.g. `\"att-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"att-123e4567-e89b-12d3-a456-426614174000"
]
},
"createdAt": {
"type": "string",
"description": "Timestamp when the attachment was created.",
"format": "date-time",
"examples": [
"2026-03-30T09:05:00Z"
]
},
"url": {
"type": "string",
"description": "URL to fetch the attachment.",
"examples": [
"https://example.com/stop-attachment/attachment-2025-06-03-1"
]
}
},
"description": "An attachment to a stop, such as a proof of delivery photo or signature."
},
"description": "Photos for the route start. Photos may be fetched using the URLs on the\n attachments."
}
},
"description": "The start location of a route and any driver tasks to complete before\n beginning the route."
}
],
"description": "Route start address and tasks."
},
"end": {
"allOf": [
{
"title": "RouteEnd",
"type": "object",
"properties": {
"address": {
"allOf": [
{
"title": "Address",
"type": "object",
"properties": {
"address1": {
"type": "string",
"description": "Street address line 1 (e.g. `\"123 Main St\"`).",
"examples": [
"123 Main St"
]
},
"address2": {
"type": "string",
"description": "Street address line 2 (e.g. `\"Apt 101\"`).",
"examples": [
"Apt 3B"
]
},
"city": {
"type": "string",
"description": "City name (e.g. `\"New York\"`).",
"examples": [
"New York"
]
},
"provinceCode": {
"type": "string",
"description": "Province or state as subdivision codes in\n [ISO 3166-2](https://en.wikipedia.org/wiki/ISO_3166-2) format without the\n country prefix (e.g. `\"NY\"` for New York).",
"examples": [
"NY"
]
},
"countryCode": {
"type": "string",
"description": "Country code (e.g. `\"US\"`).",
"examples": [
"US"
]
},
"zip": {
"type": "string",
"description": "Postal or ZIP code (e.g. `\"10001\"`).",
"examples": [
"10001"
]
}
},
"description": "A physical street address."
}
],
"description": "The end address of the route.",
"examples": [
{
"address1": "123 Main St",
"address2": "Apt 3B",
"city": "New York",
"provinceCode": "NY",
"countryCode": "US",
"zip": "10001"
}
]
},
"tasks": {
"type": "array",
"items": {
"title": "Task",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Task ID (e.g. `\"tsk-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"tsk-123e4567-e89b-12d3-a456-426614174000"
]
},
"title": {
"type": "string",
"description": "Task title (e.g. `\"Delivery checklist\"`).",
"examples": [
"Delivery checklist"
]
},
"type": {
"enum": [
"UNKNOWN",
"CHECKBOXES",
"RADIO_BUTTONS",
"TEXT_INPUT",
"DECIMAL_INPUT",
"SCANNER_INPUT"
],
"type": "string",
"description": "Task type.",
"format": "enum",
"examples": [
"TEXT_INPUT"
]
},
"items": {
"type": "array",
"items": {
"title": "TaskItem",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Item ID (e.g. `\"itm-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"itm-123e4567-e89b-12d3-a456-426614174000"
]
},
"title": {
"type": "string",
"description": "Item title (e.g. `\"Pick up package\"`).",
"examples": [
"Pick up package"
]
},
"complete": {
"type": "boolean",
"description": "Whether the item is completed.",
"examples": [
true
]
},
"updatedAt": {
"type": "string",
"description": "Timestamp when the item was last updated.",
"format": "date-time",
"examples": [
"2026-03-30T13:00:00Z"
]
}
},
"description": "An item within a task. For `CHECKBOXES`, each item on a task may be completed\n independently. For `RADIO_BUTTONS`, at most one item will be completed."
},
"description": "Task items (populated for `CHECKBOXES` and `RADIO_BUTTONS`).",
"examples": [
[]
]
},
"input": {
"allOf": [
{
"title": "TaskInput",
"type": "object",
"properties": {
"value": {
"type": "string",
"description": "Input value.",
"examples": [
"020123456789"
]
},
"updatedAt": {
"type": "string",
"description": "Timestamp when the input was last updated.",
"format": "date-time",
"examples": [
"2026-03-30T13:00:00Z"
]
},
"inputMethod": {
"enum": [
"UNKNOWN",
"SCANNED"
],
"type": "string",
"description": "Whether input was scanned (e.g. a scanned barcode)",
"format": "enum",
"examples": [
"SCANNED"
]
}
},
"description": "Captured driver input for a task. The value may be text for `TEXT_INPUT`\n tasks or a string decimal number for `DECIMAL_INPUT` tasks."
}
],
"description": "Task input (populated for `TEXT_INPUT` and `DECIMAL_INPUT`)."
},
"requiredToMarkStopAsDelivered": {
"type": "boolean",
"description": "Whether the task is required to mark the stop as completed. In the case of\n tasks on `RouteStart`, this represents tasks required for starting the\n route. In the case of tasks on `RouteEnd`, this represents tasks required\n for completing the route.",
"examples": [
true
]
},
"requiredToMarkStopAsAttempted": {
"type": "boolean",
"description": "Whether the task is required to mark the stop as attempted.",
"examples": [
true
]
}
},
"description": "A task to be completed at a stop, or at the start or end of a route. Tasks\n may have one or more items for `CHECKBOXES` or `RADIO_BUTTONS`, or may have\n an input for `TEXT_INPUT` or `DECIMAL_INPUT`."
},
"description": "Tasks to complete before finishing the route."
},
"plannedArrival": {
"type": "string",
"description": "Planned arrival time at the end of the route.",
"format": "date-time",
"examples": [
"2026-03-30T17:00:00Z"
]
},
"distanceMeters": {
"type": "number",
"description": "The distance in meters from the previous stop.",
"format": "double",
"examples": [
1234.56
]
},
"updatedArrival": {
"type": "string",
"description": "Estimated arrival time at the end of the route. If the route is completed,\n this will be the actual arrival time.",
"format": "date-time",
"examples": [
"2026-03-30T17:05:00Z"
]
},
"status": {
"enum": [
"UNKNOWN",
"COMPLETED"
],
"type": "string",
"description": "Status indicating whether the route has been completed.",
"format": "enum",
"examples": [
"COMPLETED"
]
},
"photos": {
"type": "array",
"items": {
"title": "StopAttachment",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Attachment ID (e.g. `\"att-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"att-123e4567-e89b-12d3-a456-426614174000"
]
},
"createdAt": {
"type": "string",
"description": "Timestamp when the attachment was created.",
"format": "date-time",
"examples": [
"2026-03-30T09:05:00Z"
]
},
"url": {
"type": "string",
"description": "URL to fetch the attachment.",
"examples": [
"https://example.com/stop-attachment/attachment-2025-06-03-1"
]
}
},
"description": "An attachment to a stop, such as a proof of delivery photo or signature."
},
"description": "Photos for the route end. Photos may be fetched using the URLs on the\n attachments."
}
},
"description": "The end location of a route and any driver tasks to complete after completing\n the route."
}
],
"description": "Route end address and tasks."
},
"stops": {
"type": "array",
"items": {
"title": "RouteStop",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Stop ID (e.g. `\"rst-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"rst-123e4567-e89b-12d3-a456-426614174000"
]
},
"type": {
"enum": [
"UNKNOWN",
"DELIVERY",
"BREAK",
"PICKUP",
"TASK"
],
"type": "string",
"description": "The type of stop (DELIVERY, BREAK, PICKUP, or TASK).",
"format": "enum",
"examples": [
"DELIVERY"
]
},
"deliveryStatus": {
"enum": [
"UNKNOWN",
"DELIVERED",
"OUT_FOR_DELIVERY",
"ATTEMPTED_DELIVERY",
"READY_FOR_DELIVERY"
],
"type": "string",
"description": "The status for DELIVERY, PICKUP, or TASK stops.",
"format": "enum",
"examples": [
"ATTEMPTED_DELIVERY"
]
},
"breakStatus": {
"enum": [
"UNKNOWN",
"COMPLETED"
],
"type": "string",
"description": "The status for BREAK stops.",
"format": "enum",
"examples": [
"COMPLETED"
]
},
"updatedAt": {
"type": "string",
"description": "Timestamp when the stop status was last updated. Note that this timestamp\n corresponds only to major status updates (i.e. stop marked as DELIVERED).\n Minor updates like task completion or adding proof of delivery will not\n advance this timestamp. For those events, use the timestamps on the task or\n proof of delivery attachment.",
"format": "date-time",
"examples": [
"2026-03-30T13:15:00Z"
]
},
"duration": {
"pattern": "^-?(?:0|[1-9][0-9]{0,11})(?:\\.[0-9]{1,9})?s$",
"type": "string",
"description": "Planned duration of the stop in seconds.",
"examples": [
"300s"
]
},
"plannedArrival": {
"type": "string",
"description": "Planned arrival time at the stop.",
"format": "date-time",
"examples": [
"2026-03-30T13:00:00Z"
]
},
"note": {
"type": "string",
"description": "Top-level note for the stop, as entered manually by route planners,\n inherited from a saved or imported stop, or set by order import automation\n rules.",
"examples": [
"Leave at door."
]
},
"address": {
"allOf": [
{
"title": "Address",
"type": "object",
"properties": {
"address1": {
"type": "string",
"description": "Street address line 1 (e.g. `\"123 Main St\"`).",
"examples": [
"123 Main St"
]
},
"address2": {
"type": "string",
"description": "Street address line 2 (e.g. `\"Apt 101\"`).",
"examples": [
"Apt 3B"
]
},
"city": {
"type": "string",
"description": "City name (e.g. `\"New York\"`).",
"examples": [
"New York"
]
},
"provinceCode": {
"type": "string",
"description": "Province or state as subdivision codes in\n [ISO 3166-2](https://en.wikipedia.org/wiki/ISO_3166-2) format without the\n country prefix (e.g. `\"NY\"` for New York).",
"examples": [
"NY"
]
},
"countryCode": {
"type": "string",
"description": "Country code (e.g. `\"US\"`).",
"examples": [
"US"
]
},
"zip": {
"type": "string",
"description": "Postal or ZIP code (e.g. `\"10001\"`).",
"examples": [
"10001"
]
}
},
"description": "A physical street address."
}
],
"description": "Delivery address for the stop.",
"examples": [
{
"address1": "123 Main St",
"address2": "Apt 3B",
"city": "New York",
"provinceCode": "NY",
"countryCode": "US",
"zip": "10001"
}
]
},
"contact": {
"allOf": [
{
"title": "Contact",
"type": "object",
"properties": {
"firstName": {
"type": "string",
"description": "First name (e.g. `\"John\"`).",
"examples": [
"John"
]
},
"lastName": {
"type": "string",
"description": "Last name (e.g. `\"Doe\"`).",
"examples": [
"Doe"
]
},
"company": {
"type": "string",
"description": "Company name (e.g. `\"Roundtrip Systems Inc\"`).",
"examples": [
"Roundtrip Systems Inc"
]
},
"phone": {
"type": "string",
"description": "Phone number in [E.164 format](https://en.wikipedia.org/wiki/E.164) (e.g.\n `\"+14265551000\"`).",
"examples": [
"+14265551000"
]
},
"email": {
"type": "string",
"description": "Email address (e.g. `\"john.doe@roundtrip.ai\"`)",
"examples": [
"john.doe@roundtrip.ai"
]
}
},
"description": "Contact information for a person or company."
}
],
"description": "Contact information for the stop delivery recipient.",
"examples": [
{
"firstName": "John",
"lastName": "Doe",
"company": "Roundtrip Systems Inc",
"phone": "+14265551000",
"email": "john.doe@roundtrip.ai"
}
]
},
"plannedCoordinates": {
"allOf": [
{
"type": "object",
"properties": {
"latitude": {
"type": "number",
"description": "The latitude in degrees. It must be in the range [-90.0, +90.0].",
"format": "double"
},
"longitude": {
"type": "number",
"description": "The longitude in degrees. It must be in the range [-180.0, +180.0].",
"format": "double"
}
},
"description": "An object that represents a latitude/longitude pair. This is expressed as a\n pair of doubles to represent degrees latitude and degrees longitude. Unless\n specified otherwise, this must conform to the\n WGS84\n standard. Values must be within normalized ranges."
}
],
"description": "Planned coordinates for the stop.",
"examples": [
{
"latitude": 40.7128,
"longitude": -74.006
}
]
},
"items": {
"type": "array",
"items": {
"title": "StopItem",
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "Item name (e.g. `\"Bananas\"`).",
"examples": [
"Bananas"
]
},
"quantity": {
"type": "integer",
"description": "Quantity of the item (e.g. `5`).",
"format": "int32",
"examples": [
5
]
},
"grams": {
"type": "integer",
"description": "Weight of the item in grams (e.g. `500`).",
"format": "int32",
"examples": [
500
]
},
"sku": {
"type": "string",
"description": "Stock keeping unit (e.g. `\"BANANA-001\"`).",
"examples": [
"BANANA-001"
]
}
},
"description": "An item to be delivered at a stop."
},
"description": "Items to deliver at the stop."
},
"source": {
"enum": [
"UNKNOWN",
"SHOPIFY_ORDER",
"SAVED_STOP",
"IMPORTED_STOP"
],
"type": "string",
"description": "The source of the stop, which may be populated for `DELIVERY` stops. The\n source can be a `SHOPIFY_ORDER`, an EasyRoutes `SAVED_STOP`, or an\n `IMPORTED_STOP` from an external source (such as CSV file).",
"format": "enum",
"examples": [
"IMPORTED_STOP"
]
},
"shopifyOrderId": {
"type": "string",
"description": "The Shopify order ID, populated when the stop source is a `SHOPIFY_ORDER`.",
"examples": [
"6229749334323"
]
},
"savedStopId": {
"type": "string",
"description": "The saved stop ID, populated when the stop source is a `SAVED_STOP`.",
"examples": [
"sst-123e4567-e89b-12d3-a456-426614174000"
]
},
"deliveredCoordinates": {
"allOf": [
{
"type": "object",
"properties": {
"latitude": {
"type": "number",
"description": "The latitude in degrees. It must be in the range [-90.0, +90.0].",
"format": "double"
},
"longitude": {
"type": "number",
"description": "The longitude in degrees. It must be in the range [-180.0, +180.0].",
"format": "double"
}
},
"description": "An object that represents a latitude/longitude pair. This is expressed as a\n pair of doubles to represent degrees latitude and degrees longitude. Unless\n specified otherwise, this must conform to the\n WGS84\n standard. Values must be within normalized ranges."
}
],
"description": "Delivered coordinates for the stop."
},
"proofOfDeliveryNote": {
"type": "string",
"description": "Proof of delivery note for the stop.",
"examples": [
"Left at door."
]
},
"proofOfDeliveryPhotos": {
"type": "array",
"items": {
"title": "StopAttachment",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Attachment ID (e.g. `\"att-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"att-123e4567-e89b-12d3-a456-426614174000"
]
},
"createdAt": {
"type": "string",
"description": "Timestamp when the attachment was created.",
"format": "date-time",
"examples": [
"2026-03-30T09:05:00Z"
]
},
"url": {
"type": "string",
"description": "URL to fetch the attachment.",
"examples": [
"https://example.com/stop-attachment/attachment-2025-06-03-1"
]
}
},
"description": "An attachment to a stop, such as a proof of delivery photo or signature."
},
"description": "Proof of delivery photos for the stop. Photos may be fetched using the URLs\n on the attachments."
},
"proofOfDeliverySignatures": {
"type": "array",
"items": {
"title": "StopAttachment",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Attachment ID (e.g. `\"att-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"att-123e4567-e89b-12d3-a456-426614174000"
]
},
"createdAt": {
"type": "string",
"description": "Timestamp when the attachment was created.",
"format": "date-time",
"examples": [
"2026-03-30T09:05:00Z"
]
},
"url": {
"type": "string",
"description": "URL to fetch the attachment.",
"examples": [
"https://example.com/stop-attachment/attachment-2025-06-03-1"
]
}
},
"description": "An attachment to a stop, such as a proof of delivery photo or signature."
},
"description": "Proof of delivery signatures for the stop. Signatures may be fetched using\n the URLs on the attachments."
},
"tasks": {
"type": "array",
"items": {
"title": "Task",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Task ID (e.g. `\"tsk-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"tsk-123e4567-e89b-12d3-a456-426614174000"
]
},
"title": {
"type": "string",
"description": "Task title (e.g. `\"Delivery checklist\"`).",
"examples": [
"Delivery checklist"
]
},
"type": {
"enum": [
"UNKNOWN",
"CHECKBOXES",
"RADIO_BUTTONS",
"TEXT_INPUT",
"DECIMAL_INPUT",
"SCANNER_INPUT"
],
"type": "string",
"description": "Task type.",
"format": "enum",
"examples": [
"TEXT_INPUT"
]
},
"items": {
"type": "array",
"items": {
"title": "TaskItem",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Item ID (e.g. `\"itm-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"itm-123e4567-e89b-12d3-a456-426614174000"
]
},
"title": {
"type": "string",
"description": "Item title (e.g. `\"Pick up package\"`).",
"examples": [
"Pick up package"
]
},
"complete": {
"type": "boolean",
"description": "Whether the item is completed.",
"examples": [
true
]
},
"updatedAt": {
"type": "string",
"description": "Timestamp when the item was last updated.",
"format": "date-time",
"examples": [
"2026-03-30T13:00:00Z"
]
}
},
"description": "An item within a task. For `CHECKBOXES`, each item on a task may be completed\n independently. For `RADIO_BUTTONS`, at most one item will be completed."
},
"description": "Task items (populated for `CHECKBOXES` and `RADIO_BUTTONS`).",
"examples": [
[]
]
},
"input": {
"allOf": [
{
"title": "TaskInput",
"type": "object",
"properties": {
"value": {
"type": "string",
"description": "Input value.",
"examples": [
"020123456789"
]
},
"updatedAt": {
"type": "string",
"description": "Timestamp when the input was last updated.",
"format": "date-time",
"examples": [
"2026-03-30T13:00:00Z"
]
},
"inputMethod": {
"enum": [
"UNKNOWN",
"SCANNED"
],
"type": "string",
"description": "Whether input was scanned (e.g. a scanned barcode)",
"format": "enum",
"examples": [
"SCANNED"
]
}
},
"description": "Captured driver input for a task. The value may be text for `TEXT_INPUT`\n tasks or a string decimal number for `DECIMAL_INPUT` tasks."
}
],
"description": "Task input (populated for `TEXT_INPUT` and `DECIMAL_INPUT`)."
},
"requiredToMarkStopAsDelivered": {
"type": "boolean",
"description": "Whether the task is required to mark the stop as completed. In the case of\n tasks on `RouteStart`, this represents tasks required for starting the\n route. In the case of tasks on `RouteEnd`, this represents tasks required\n for completing the route.",
"examples": [
true
]
},
"requiredToMarkStopAsAttempted": {
"type": "boolean",
"description": "Whether the task is required to mark the stop as attempted.",
"examples": [
true
]
}
},
"description": "A task to be completed at a stop, or at the start or end of a route. Tasks\n may have one or more items for `CHECKBOXES` or `RADIO_BUTTONS`, or may have\n an input for `TEXT_INPUT` or `DECIMAL_INPUT`."
},
"description": "Driver tasks for the stop, including completed items and any input from the\n driver."
},
"priority": {
"maximum": 10,
"type": "integer",
"description": "Priority of the stop for route planning. The valid range for stop priority\n is between `1` (low) and `10` (high), with default priority corresponding\n to a value of `5`. A priority value of `0` is considered unset and is\n treated the same as \"default\" priority. Stops with higher priority will be\n preferred when generating routes with constraints.",
"format": "int32",
"examples": [
8
]
},
"importedStopId": {
"type": "string",
"description": "The imported stop ID, populated when the stop source is `IMPORTED_STOP`.",
"examples": [
"ist-123e4567-e89b-12d3-a456-426614174000"
]
},
"orderName": {
"type": "string",
"description": "The name of the order associated with the stop. For Shopify orders, the\n name is generated by combining the `orderNumber` property with the order\n prefix and suffix that are set in the merchant's general settings. For\n EasyRoutes imported orders, this field is populated with the order name\n provided on import.",
"examples": [
"#1234"
]
},
"distanceMeters": {
"type": "number",
"description": "The distance in meters from the previous stop.",
"format": "double",
"examples": [
123.45
]
},
"updatedArrival": {
"type": "string",
"description": "Estimated arrival time at the stop. If the stop is completed, this will be\n the actual arrival time.",
"format": "date-time",
"examples": [
"2026-03-30T13:05:00Z"
]
},
"timeWindows": {
"type": "array",
"items": {
"title": "TimeWindow",
"type": "object",
"properties": {
"start": {
"allOf": [
{
"title": "TimeOfDay",
"type": "object",
"properties": {
"hours": {
"maximum": 23,
"type": "integer",
"description": "Hours of day in 24 hour format. Must be from 0 to 23.",
"format": "int32",
"examples": [
13
]
},
"minutes": {
"maximum": 59,
"type": "integer",
"description": "Minutes of hour of day. Must be from 0 to 59.",
"format": "int32",
"examples": [
37
]
},
"seconds": {
"maximum": 59,
"type": "integer",
"description": "Seconds of minutes of the time. Must be from 0 to 59.",
"format": "int32",
"examples": [
16
]
}
},
"description": "A time of day, independent of a particular date or timezone."
}
],
"description": "The start time of the time window (optional)."
},
"end": {
"allOf": [
{
"title": "TimeOfDay",
"type": "object",
"properties": {
"hours": {
"maximum": 23,
"type": "integer",
"description": "Hours of day in 24 hour format. Must be from 0 to 23.",
"format": "int32",
"examples": [
13
]
},
"minutes": {
"maximum": 59,
"type": "integer",
"description": "Minutes of hour of day. Must be from 0 to 59.",
"format": "int32",
"examples": [
37
]
},
"seconds": {
"maximum": 59,
"type": "integer",
"description": "Seconds of minutes of the time. Must be from 0 to 59.",
"format": "int32",
"examples": [
16
]
}
},
"description": "A time of day, independent of a particular date or timezone."
}
],
"description": "The end time of the time window (optional)."
}
},
"description": "A time window for a stop. The time window may be open-ended, but one or both\n of the start and end times should be provided. The end time must be >= the\n start time."
},
"description": "The time window for the stop. Note that we currently support at most one\n time window but may support multiple time windows in the future.",
"examples": [
[
{
"start": {
"hours": 9
},
"end": {
"hours": 17
}
}
]
]
},
"deliveryDate": {
"allOf": [
{
"title": "Date",
"required": [
"year",
"month",
"day"
],
"type": "object",
"properties": {
"year": {
"maximum": 9999,
"minimum": 1,
"type": "integer",
"description": "Year of the date. Must be from 1 to 9999.",
"format": "int32",
"examples": [
2019
]
},
"month": {
"maximum": 12,
"minimum": 1,
"type": "integer",
"description": "Month of a year. Must be from 1 to 12.",
"format": "int32",
"examples": [
11
]
},
"day": {
"maximum": 31,
"minimum": 1,
"type": "integer",
"description": "Day of a month. Must be from 1 to 31.",
"format": "int32",
"examples": [
15
]
}
},
"description": "A date in year-month-day format."
}
],
"description": "The planned delivery date for the stop.",
"examples": [
{
"year": 2025,
"month": 12,
"day": 16
}
]
},
"attributes": {
"type": "array",
"items": {
"title": "Attribute",
"type": "object",
"properties": {
"key": {
"type": "string",
"description": "Attribute key. Must be non-empty.",
"examples": [
"delivery_date"
]
},
"value": {
"type": "string",
"description": "Attribute value.",
"examples": [
"2025-12-16"
]
}
},
"description": "A key-value pair for storing additional information on a stop, such as order\n details, delivery instructions, or custom fields."
},
"description": "Additional attributes for the stop. Attributes are key-value pairs for\n storing additional structured data on stops. These may be populated from\n the Shopify order or set on import.",
"examples": [
[
{
"key": "color",
"value": "blue"
}
]
]
},
"clientStopId": {
"type": "string",
"description": "The client-provided ID associated with the stop, if provided on import.",
"examples": [
"test-order-1234"
]
},
"tags": {
"type": "array",
"items": {
"type": "string"
},
"description": "The tags for the stop. Tags are used to categorize stops and can be used\n for filtering and grouping stops in the EasyRoutes web app. These may be\n populated from the Shopify order or set on import.",
"examples": [
[
"foo",
"bar"
]
]
},
"attemptedReason": {
"enum": [
"UNKNOWN",
"NOT_AVAILABLE",
"ACCESS_DENIED",
"INCORRECT_ADDRESS",
"SAFE_PLACE_UNAVAILABLE",
"REFUSED",
"EXTERNAL",
"INCORRECT_ITEMS",
"OTHER",
"CANCELED"
],
"type": "string",
"description": "The reason for marking the stop as attempted. This is only populated when\n `deliveryStatus = ATTEMPTED_DELIVERY`.",
"format": "enum",
"examples": [
"NOT_AVAILABLE"
]
},
"attemptedNote": {
"type": "string",
"description": "Optional note related to the reason for marking the stop as attempted. This\n is optionally populated when `deliveryStatus = ATTEMPTED_DELIVERY`.",
"examples": [
"Customer did not answer the door."
]
},
"customerRating": {
"allOf": [
{
"title": "CustomerRating",
"type": "object",
"properties": {
"rating": {
"maximum": 5,
"minimum": 1,
"type": "integer",
"description": "Rating from 1-5",
"format": "int32",
"examples": [
5
]
},
"comment": {
"type": "string",
"description": "Customer comment related to rating",
"examples": [
"Excellent delivery"
]
},
"createdAt": {
"type": "string",
"description": "Timestamp when rating was left by customer.",
"format": "date-time",
"examples": [
"2026-03-30T18:00:00Z"
]
}
},
"description": "Customer rating and feedback left on a stop."
}
],
"description": "Rating left by customer. This can only be populated once `deliveryStatus =\n DELIVERED`."
},
"customSignatureDisclosure": {
"type": "string",
"description": "Optional custom signature disclosure that is shown to customers in the\n driver app.",
"examples": [
"I acknowledge that I have received this delivery."
]
},
"shopifyOrder": {
"allOf": [
{
"title": "ShopifyOrder",
"type": "object",
"properties": {
"orderNote": {
"type": "string",
"description": "The Shopify order note.",
"examples": [
"Customer has paid."
]
},
"customerNote": {
"type": "string",
"description": "The Shopify customer note for the order.",
"examples": [
"Leave at door."
]
}
},
"description": "Shopify-specific information for a RouteStop."
}
],
"description": "Information from the associated Shopify order, if applicable. Populated if\n stop source is `SHOPIFY_ORDER`"
},
"proofOfDeliveryBarcodes": {
"type": "array",
"items": {
"title": "ScannedBarcode",
"type": "object",
"properties": {
"value": {
"type": "string",
"description": "Barcode value (e.g. `\"123456789012\"`).",
"examples": [
"123456789012"
]
},
"createdAt": {
"type": "string",
"description": "Timestamp when the barcode was scanned.",
"format": "date-time",
"examples": [
"2026-03-30T13:10:00Z"
]
}
},
"description": "A proof of delivery barcode scanned at a stop."
},
"description": "Proof of delivery barcodes scanned at the stop."
},
"proofOfDeliveryBarcodeIssues": {
"type": "array",
"items": {
"title": "ScannedBarcodeIssue",
"type": "object",
"properties": {
"reason": {
"enum": [
"UNKNOWN",
"ITEM_MISSING",
"NOT_SCANNABLE",
"INCORRECT"
],
"type": "string",
"description": "The reported reason for the barcode issue.",
"format": "enum",
"examples": [
"ITEM_MISSING"
]
},
"note": {
"type": "string",
"description": "Optional note related to the reason for reporting a barcode issue.",
"examples": [
"Item was not packed."
]
},
"createdAt": {
"type": "string",
"description": "Timestamp when the issue was reported.",
"format": "date-time",
"examples": [
"2026-03-30T13:10:00Z"
]
}
},
"description": "A reported issue related to scanning barcodes at a stop."
},
"description": "Proof of delivery barcode issues reported at the stop."
},
"orderReferenceUrl": {
"type": "string",
"description": "A reference URL for the order associated with the stop (e.g. a link to the\n order in your order management system). Must be a valid HTTPS URL. This\n field can only be populated for imported stops.",
"examples": [
"https://orders.example.com/orders/148977776"
]
}
},
"description": "A stop on a route. A stop may correspond to a delivery or a driver break as\n determined by the type. A delivery stop will have location and contact\n information, items to deliver, optional order details, status, arrival time\n and stop duration, driver tasks and any proof of delivery information. A\n break stop will have start time and duration, and status."
},
"description": "Route stops. See RouteStop for stop fields."
},
"createdAt": {
"type": "string",
"description": "Timestamp when the route was created.",
"format": "date-time",
"examples": [
"2026-03-29T08:00:00Z"
]
},
"updatedAt": {
"type": "string",
"description": "Timestamp when the route was last updated (by the planner).",
"format": "date-time",
"examples": [
"2026-03-30T13:15:00Z"
]
},
"archivedAt": {
"type": "string",
"description": "Timestamp when the route was archived.",
"format": "date-time",
"examples": [
"2026-04-05T00:00:00Z"
]
},
"scheduledFor": {
"type": "string",
"description": "Timestamp when the route is scheduled for.",
"format": "date-time",
"examples": [
"2026-03-30T09:00:00Z"
]
},
"totalDistanceMeters": {
"type": "number",
"description": "The distance in meters for the entire route.",
"format": "double",
"examples": [
2387.2
]
},
"totalItemQuantity": {
"type": "integer",
"description": "The total quantity of items to deliver on the route.",
"format": "int32",
"examples": [
50
]
},
"totalItemGrams": {
"type": "string",
"description": "The total weight in grams for the items on the route.",
"examples": [
"6000"
]
},
"optimized": {
"type": "boolean",
"description": "Whether the route has been optimized. Adding or removing stops, reordering\n stops, or changing route options generally set this field to false until\n the route is reoptimized.",
"examples": [
true
]
},
"dispatchedUntil": {
"type": "string",
"description": "Timestamp until which the route is dispatched and accessible in the driver\n app.",
"format": "date-time",
"examples": [
"2026-03-30T20:00:00Z"
]
},
"note": {
"type": "string",
"description": "Top-level note for the route, as entered manually by route planners.",
"examples": [
"Fragile items."
]
},
"tags": {
"type": "array",
"items": {
"type": "string"
},
"description": "The tags for the route. Tags are used to categorize routes and can be\n used for filtering and grouping routes in the EasyRoutes web app.",
"examples": [
[
"foo",
"bar"
]
]
},
"defaultStopDuration": {
"pattern": "^-?(?:0|[1-9][0-9]{0,11})(?:\\.[0-9]{1,9})?s$",
"type": "string",
"description": "The default duration for stops on the route. Used to estimate arrival\n times for stops that do not have their own duration specified.\n Specified as a duration string in the format \"300s\" for 5 minutes, \"60s\"\n for 1 minute, etc.",
"examples": [
"300s"
]
},
"maxDuration": {
"pattern": "^-?(?:0|[1-9][0-9]{0,11})(?:\\.[0-9]{1,9})?s$",
"type": "string",
"description": "The maximum duration of the route. Specified as a duration string in the\n format \"3600s\" for 1 hour, \"7200s\" for 2 hours, etc.",
"examples": [
"28800s"
]
},
"maxStops": {
"type": "integer",
"description": "The maximum number of stops on the route.",
"format": "int32",
"examples": [
50
]
},
"maxItemCount": {
"type": "integer",
"description": "The maximum total item count across all stops on the route.",
"format": "int32",
"examples": [
200
]
},
"maxKilograms": {
"type": "number",
"description": "The maximum total weight in kilograms across all stops on the route.",
"format": "double",
"examples": [
500
]
},
"avoidTolls": {
"type": "boolean",
"description": "Whether to avoid toll roads during optimization.",
"examples": [
true
]
},
"avoidUTurns": {
"type": "boolean",
"description": "Whether to avoid U-turns during optimization.",
"examples": [
true
]
},
"speedFactor": {
"type": "number",
"description": "A speed factor for the route used during optimization to adjust estimated\n travel times. A value of 1.0 represents normal speed. Values less than 1.0\n indicate slower travel (e.g. 0.5 = half speed), and values greater than\n 1.0 indicate faster travel (e.g. 1.5 = 50% faster). Must be between 0.1\n and 1.9. A value of 0 (or unset) uses the default speed.",
"format": "double",
"examples": [
0.8
]
},
"vehicle": {
"allOf": [
{
"title": "Vehicle",
"required": [
"id"
],
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Vehicle ID.",
"examples": [
"veh-123e4567-e89b-12d3-a456-426614174000"
]
},
"name": {
"type": "string",
"description": "Vehicle name.",
"examples": [
"Delivery Van 1"
]
},
"make": {
"type": "string",
"description": "Vehicle make.",
"examples": [
"Ford"
]
},
"model": {
"type": "string",
"description": "Vehicle model.",
"examples": [
"Transit"
]
},
"year": {
"type": "integer",
"description": "Vehicle model year.",
"format": "int32",
"examples": [
2023
]
},
"type": {
"enum": [
"UNKNOWN",
"CAR",
"CARGO_VAN",
"PICKUP_TRUCK",
"BOX_TRUCK",
"MOTORCYCLE",
"BICYCLE",
"DRONE",
"OTHER"
],
"type": "string",
"description": "Vehicle type.",
"format": "enum",
"examples": [
"CARGO_VAN"
]
},
"vin": {
"type": "string",
"description": "Vehicle Identification Number.",
"examples": [
"1FTBW2CM5NKA12345"
]
},
"license": {
"type": "string",
"description": "Vehicle license plate.",
"examples": [
"ABC-1234"
]
},
"isArchived": {
"type": "boolean",
"description": "Whether the vehicle is archived.",
"examples": [
false
]
},
"createdTimestamp": {
"type": "string",
"description": "Timestamp when the vehicle was created.",
"format": "date-time",
"examples": [
"2026-07-30T12:00:00Z"
]
}
},
"description": "A vehicle that can be assigned to a route."
}
],
"description": "Assigned vehicle for the route."
}
},
"description": "A route of stops, optionally with an assigned driver."
}
}
}
},
"default": {
"description": "Default error response",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"code": {
"type": "integer",
"description": "The status code, which should be an enum value of [google.rpc.Code][google.rpc.Code].",
"format": "int32"
},
"message": {
"type": "string",
"description": "A developer-facing error message, which should be in English. Any user-facing error message should be localized and sent in the [google.rpc.Status.details][google.rpc.Status.details] field, or localized by the client."
},
"details": {
"type": "array",
"items": {
"type": "object",
"properties": {
"@type": {
"type": "string",
"description": "The type of the serialized message."
}
},
"additionalProperties": true,
"description": "Contains an arbitrary serialized message along with a @type that describes the type of the serialized message."
},
"description": "A list of messages that carry the error details. There is a common set of message types for APIs to use."
}
},
"description": "The `Status` type defines a logical error model that is suitable for different programming environments, including REST APIs and RPC APIs. It is used by [gRPC](https://github.com/grpc). Each `Status` message contains three pieces of data: error code, error message, and error details. You can find out more about this error model and how to work with it in the [API Design Guide](https://cloud.google.com/apis/design/errors)."
}
}
}
}
},
"security": [
{
"bearerAuth": []
}
],
"components": {
"securitySchemes": {
"bearerAuth": {
"type": "http",
"description": "Access token from `/authenticate`",
"scheme": "bearer",
"bearerFormat": "JWT"
}
}
}
}
```
# Unassign route driver (https://docs.roundtrip.ai/docs/api-reference/routes/delete-routes-routeId-driver)
DELETE /routes/{routeId}/driver
Unassigns driver from a route by route ID. The response will include the
updated route with no driver assigned.
## OpenAPI specification
```json
{
"servers": [
{
"url": "https://easyroutes.roundtrip.ai/api/2024-07"
}
],
"tags": [
"Routes"
],
"summary": "Unassign route driver",
"description": "Unassigns driver from a route by route ID. The response will include the\n updated route with no driver assigned.",
"operationId": "UnassignRouteDriver",
"parameters": [
{
"name": "routeId",
"in": "path",
"description": "The route ID to unassign the driver from.",
"required": true,
"schema": {
"type": "string",
"examples": [
"rte-123e4567-e89b-12d3-a456-426614174000"
]
}
},
{
"name": "Idempotency-Key",
"in": "header",
"description": "A unique key for safely retrying this operation. For more information read [our guide](https://docs.roundtrip.ai/docs/concepts/idempotency.md).",
"schema": {
"maxLength": 255,
"minLength": 1,
"type": "string"
},
"examples": {
"default": {
"value": "550e8400-e29b-41d4-a716-446655440000"
}
}
}
],
"responses": {
"200": {
"description": "OK",
"headers": {
"Idempotency-Key": {
"description": "The idempotency key associated with the response.",
"schema": {
"type": "string"
}
},
"Idempotency-Replayed": {
"description": "Whether the response was replayed from a previous request.",
"schema": {
"type": "boolean"
}
}
},
"content": {
"application/json": {
"schema": {
"title": "Route",
"required": [
"id",
"name",
"stops",
"createdAt",
"updatedAt",
"totalDistanceMeters",
"totalItemQuantity",
"totalItemGrams",
"optimized"
],
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Route ID (e.g. `\"rte-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"rte-123e4567-e89b-12d3-a456-426614174000"
]
},
"name": {
"type": "string",
"description": "Route name (e.g. `\"Morning route\"`).",
"examples": [
"Morning route"
]
},
"driver": {
"allOf": [
{
"title": "Driver",
"required": [
"id"
],
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Driver ID (e.g. `\"drv-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"drv-123e4567-e89b-12d3-a456-426614174000"
]
},
"firstName": {
"type": "string",
"description": "Driver first name (e.g. `\"John\"`).",
"examples": [
"John"
]
},
"lastName": {
"type": "string",
"description": "Driver last name (e.g. `\"Doe\"`).",
"examples": [
"Doe"
]
},
"phone": {
"type": "string",
"description": "Driver phone number in [E.164 format](https://en.wikipedia.org/wiki/E.164)\n (e.g. `\"+14265551000\"`).",
"examples": [
"+14265551000"
]
},
"status": {
"enum": [
"UNKNOWN",
"ACTIVE",
"INACTIVE",
"ARCHIVED"
],
"type": "string",
"description": "Shop driver status. (e.g. `ACTIVE`).",
"format": "enum",
"examples": [
"ACTIVE"
]
}
},
"description": "A driver who is assigned to a route."
}
],
"description": "Assigned driver for the route."
},
"start": {
"allOf": [
{
"title": "RouteStart",
"type": "object",
"properties": {
"address": {
"allOf": [
{
"title": "Address",
"type": "object",
"properties": {
"address1": {
"type": "string",
"description": "Street address line 1 (e.g. `\"123 Main St\"`).",
"examples": [
"123 Main St"
]
},
"address2": {
"type": "string",
"description": "Street address line 2 (e.g. `\"Apt 101\"`).",
"examples": [
"Apt 3B"
]
},
"city": {
"type": "string",
"description": "City name (e.g. `\"New York\"`).",
"examples": [
"New York"
]
},
"provinceCode": {
"type": "string",
"description": "Province or state as subdivision codes in\n [ISO 3166-2](https://en.wikipedia.org/wiki/ISO_3166-2) format without the\n country prefix (e.g. `\"NY\"` for New York).",
"examples": [
"NY"
]
},
"countryCode": {
"type": "string",
"description": "Country code (e.g. `\"US\"`).",
"examples": [
"US"
]
},
"zip": {
"type": "string",
"description": "Postal or ZIP code (e.g. `\"10001\"`).",
"examples": [
"10001"
]
}
},
"description": "A physical street address."
}
],
"description": "The start address of the route.",
"examples": [
{
"address1": "123 Main St",
"address2": "Apt 3B",
"city": "New York",
"provinceCode": "NY",
"countryCode": "US",
"zip": "10001"
}
]
},
"tasks": {
"type": "array",
"items": {
"title": "Task",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Task ID (e.g. `\"tsk-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"tsk-123e4567-e89b-12d3-a456-426614174000"
]
},
"title": {
"type": "string",
"description": "Task title (e.g. `\"Delivery checklist\"`).",
"examples": [
"Delivery checklist"
]
},
"type": {
"enum": [
"UNKNOWN",
"CHECKBOXES",
"RADIO_BUTTONS",
"TEXT_INPUT",
"DECIMAL_INPUT",
"SCANNER_INPUT"
],
"type": "string",
"description": "Task type.",
"format": "enum",
"examples": [
"TEXT_INPUT"
]
},
"items": {
"type": "array",
"items": {
"title": "TaskItem",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Item ID (e.g. `\"itm-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"itm-123e4567-e89b-12d3-a456-426614174000"
]
},
"title": {
"type": "string",
"description": "Item title (e.g. `\"Pick up package\"`).",
"examples": [
"Pick up package"
]
},
"complete": {
"type": "boolean",
"description": "Whether the item is completed.",
"examples": [
true
]
},
"updatedAt": {
"type": "string",
"description": "Timestamp when the item was last updated.",
"format": "date-time",
"examples": [
"2026-03-30T13:00:00Z"
]
}
},
"description": "An item within a task. For `CHECKBOXES`, each item on a task may be completed\n independently. For `RADIO_BUTTONS`, at most one item will be completed."
},
"description": "Task items (populated for `CHECKBOXES` and `RADIO_BUTTONS`).",
"examples": [
[]
]
},
"input": {
"allOf": [
{
"title": "TaskInput",
"type": "object",
"properties": {
"value": {
"type": "string",
"description": "Input value.",
"examples": [
"020123456789"
]
},
"updatedAt": {
"type": "string",
"description": "Timestamp when the input was last updated.",
"format": "date-time",
"examples": [
"2026-03-30T13:00:00Z"
]
},
"inputMethod": {
"enum": [
"UNKNOWN",
"SCANNED"
],
"type": "string",
"description": "Whether input was scanned (e.g. a scanned barcode)",
"format": "enum",
"examples": [
"SCANNED"
]
}
},
"description": "Captured driver input for a task. The value may be text for `TEXT_INPUT`\n tasks or a string decimal number for `DECIMAL_INPUT` tasks."
}
],
"description": "Task input (populated for `TEXT_INPUT` and `DECIMAL_INPUT`)."
},
"requiredToMarkStopAsDelivered": {
"type": "boolean",
"description": "Whether the task is required to mark the stop as completed. In the case of\n tasks on `RouteStart`, this represents tasks required for starting the\n route. In the case of tasks on `RouteEnd`, this represents tasks required\n for completing the route.",
"examples": [
true
]
},
"requiredToMarkStopAsAttempted": {
"type": "boolean",
"description": "Whether the task is required to mark the stop as attempted.",
"examples": [
true
]
}
},
"description": "A task to be completed at a stop, or at the start or end of a route. Tasks\n may have one or more items for `CHECKBOXES` or `RADIO_BUTTONS`, or may have\n an input for `TEXT_INPUT` or `DECIMAL_INPUT`."
},
"description": "Tasks to complete before starting the route."
},
"status": {
"enum": [
"UNKNOWN",
"STARTED"
],
"type": "string",
"description": "Status indicating whether the route has been started.",
"format": "enum",
"examples": [
"STARTED"
]
},
"updatedStart": {
"type": "string",
"description": "Updated start time for the route. If the route is started, this will be the\n actual start time.",
"format": "date-time",
"examples": [
"2026-03-30T09:05:00Z"
]
},
"scheduledStart": {
"type": "string",
"description": "Scheduled start time for the route (same as `scheduledFor` on the route).",
"format": "date-time",
"examples": [
"2026-03-30T09:00:00Z"
]
},
"photos": {
"type": "array",
"items": {
"title": "StopAttachment",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Attachment ID (e.g. `\"att-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"att-123e4567-e89b-12d3-a456-426614174000"
]
},
"createdAt": {
"type": "string",
"description": "Timestamp when the attachment was created.",
"format": "date-time",
"examples": [
"2026-03-30T09:05:00Z"
]
},
"url": {
"type": "string",
"description": "URL to fetch the attachment.",
"examples": [
"https://example.com/stop-attachment/attachment-2025-06-03-1"
]
}
},
"description": "An attachment to a stop, such as a proof of delivery photo or signature."
},
"description": "Photos for the route start. Photos may be fetched using the URLs on the\n attachments."
}
},
"description": "The start location of a route and any driver tasks to complete before\n beginning the route."
}
],
"description": "Route start address and tasks."
},
"end": {
"allOf": [
{
"title": "RouteEnd",
"type": "object",
"properties": {
"address": {
"allOf": [
{
"title": "Address",
"type": "object",
"properties": {
"address1": {
"type": "string",
"description": "Street address line 1 (e.g. `\"123 Main St\"`).",
"examples": [
"123 Main St"
]
},
"address2": {
"type": "string",
"description": "Street address line 2 (e.g. `\"Apt 101\"`).",
"examples": [
"Apt 3B"
]
},
"city": {
"type": "string",
"description": "City name (e.g. `\"New York\"`).",
"examples": [
"New York"
]
},
"provinceCode": {
"type": "string",
"description": "Province or state as subdivision codes in\n [ISO 3166-2](https://en.wikipedia.org/wiki/ISO_3166-2) format without the\n country prefix (e.g. `\"NY\"` for New York).",
"examples": [
"NY"
]
},
"countryCode": {
"type": "string",
"description": "Country code (e.g. `\"US\"`).",
"examples": [
"US"
]
},
"zip": {
"type": "string",
"description": "Postal or ZIP code (e.g. `\"10001\"`).",
"examples": [
"10001"
]
}
},
"description": "A physical street address."
}
],
"description": "The end address of the route.",
"examples": [
{
"address1": "123 Main St",
"address2": "Apt 3B",
"city": "New York",
"provinceCode": "NY",
"countryCode": "US",
"zip": "10001"
}
]
},
"tasks": {
"type": "array",
"items": {
"title": "Task",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Task ID (e.g. `\"tsk-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"tsk-123e4567-e89b-12d3-a456-426614174000"
]
},
"title": {
"type": "string",
"description": "Task title (e.g. `\"Delivery checklist\"`).",
"examples": [
"Delivery checklist"
]
},
"type": {
"enum": [
"UNKNOWN",
"CHECKBOXES",
"RADIO_BUTTONS",
"TEXT_INPUT",
"DECIMAL_INPUT",
"SCANNER_INPUT"
],
"type": "string",
"description": "Task type.",
"format": "enum",
"examples": [
"TEXT_INPUT"
]
},
"items": {
"type": "array",
"items": {
"title": "TaskItem",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Item ID (e.g. `\"itm-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"itm-123e4567-e89b-12d3-a456-426614174000"
]
},
"title": {
"type": "string",
"description": "Item title (e.g. `\"Pick up package\"`).",
"examples": [
"Pick up package"
]
},
"complete": {
"type": "boolean",
"description": "Whether the item is completed.",
"examples": [
true
]
},
"updatedAt": {
"type": "string",
"description": "Timestamp when the item was last updated.",
"format": "date-time",
"examples": [
"2026-03-30T13:00:00Z"
]
}
},
"description": "An item within a task. For `CHECKBOXES`, each item on a task may be completed\n independently. For `RADIO_BUTTONS`, at most one item will be completed."
},
"description": "Task items (populated for `CHECKBOXES` and `RADIO_BUTTONS`).",
"examples": [
[]
]
},
"input": {
"allOf": [
{
"title": "TaskInput",
"type": "object",
"properties": {
"value": {
"type": "string",
"description": "Input value.",
"examples": [
"020123456789"
]
},
"updatedAt": {
"type": "string",
"description": "Timestamp when the input was last updated.",
"format": "date-time",
"examples": [
"2026-03-30T13:00:00Z"
]
},
"inputMethod": {
"enum": [
"UNKNOWN",
"SCANNED"
],
"type": "string",
"description": "Whether input was scanned (e.g. a scanned barcode)",
"format": "enum",
"examples": [
"SCANNED"
]
}
},
"description": "Captured driver input for a task. The value may be text for `TEXT_INPUT`\n tasks or a string decimal number for `DECIMAL_INPUT` tasks."
}
],
"description": "Task input (populated for `TEXT_INPUT` and `DECIMAL_INPUT`)."
},
"requiredToMarkStopAsDelivered": {
"type": "boolean",
"description": "Whether the task is required to mark the stop as completed. In the case of\n tasks on `RouteStart`, this represents tasks required for starting the\n route. In the case of tasks on `RouteEnd`, this represents tasks required\n for completing the route.",
"examples": [
true
]
},
"requiredToMarkStopAsAttempted": {
"type": "boolean",
"description": "Whether the task is required to mark the stop as attempted.",
"examples": [
true
]
}
},
"description": "A task to be completed at a stop, or at the start or end of a route. Tasks\n may have one or more items for `CHECKBOXES` or `RADIO_BUTTONS`, or may have\n an input for `TEXT_INPUT` or `DECIMAL_INPUT`."
},
"description": "Tasks to complete before finishing the route."
},
"plannedArrival": {
"type": "string",
"description": "Planned arrival time at the end of the route.",
"format": "date-time",
"examples": [
"2026-03-30T17:00:00Z"
]
},
"distanceMeters": {
"type": "number",
"description": "The distance in meters from the previous stop.",
"format": "double",
"examples": [
1234.56
]
},
"updatedArrival": {
"type": "string",
"description": "Estimated arrival time at the end of the route. If the route is completed,\n this will be the actual arrival time.",
"format": "date-time",
"examples": [
"2026-03-30T17:05:00Z"
]
},
"status": {
"enum": [
"UNKNOWN",
"COMPLETED"
],
"type": "string",
"description": "Status indicating whether the route has been completed.",
"format": "enum",
"examples": [
"COMPLETED"
]
},
"photos": {
"type": "array",
"items": {
"title": "StopAttachment",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Attachment ID (e.g. `\"att-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"att-123e4567-e89b-12d3-a456-426614174000"
]
},
"createdAt": {
"type": "string",
"description": "Timestamp when the attachment was created.",
"format": "date-time",
"examples": [
"2026-03-30T09:05:00Z"
]
},
"url": {
"type": "string",
"description": "URL to fetch the attachment.",
"examples": [
"https://example.com/stop-attachment/attachment-2025-06-03-1"
]
}
},
"description": "An attachment to a stop, such as a proof of delivery photo or signature."
},
"description": "Photos for the route end. Photos may be fetched using the URLs on the\n attachments."
}
},
"description": "The end location of a route and any driver tasks to complete after completing\n the route."
}
],
"description": "Route end address and tasks."
},
"stops": {
"type": "array",
"items": {
"title": "RouteStop",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Stop ID (e.g. `\"rst-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"rst-123e4567-e89b-12d3-a456-426614174000"
]
},
"type": {
"enum": [
"UNKNOWN",
"DELIVERY",
"BREAK",
"PICKUP",
"TASK"
],
"type": "string",
"description": "The type of stop (DELIVERY, BREAK, PICKUP, or TASK).",
"format": "enum",
"examples": [
"DELIVERY"
]
},
"deliveryStatus": {
"enum": [
"UNKNOWN",
"DELIVERED",
"OUT_FOR_DELIVERY",
"ATTEMPTED_DELIVERY",
"READY_FOR_DELIVERY"
],
"type": "string",
"description": "The status for DELIVERY, PICKUP, or TASK stops.",
"format": "enum",
"examples": [
"ATTEMPTED_DELIVERY"
]
},
"breakStatus": {
"enum": [
"UNKNOWN",
"COMPLETED"
],
"type": "string",
"description": "The status for BREAK stops.",
"format": "enum",
"examples": [
"COMPLETED"
]
},
"updatedAt": {
"type": "string",
"description": "Timestamp when the stop status was last updated. Note that this timestamp\n corresponds only to major status updates (i.e. stop marked as DELIVERED).\n Minor updates like task completion or adding proof of delivery will not\n advance this timestamp. For those events, use the timestamps on the task or\n proof of delivery attachment.",
"format": "date-time",
"examples": [
"2026-03-30T13:15:00Z"
]
},
"duration": {
"pattern": "^-?(?:0|[1-9][0-9]{0,11})(?:\\.[0-9]{1,9})?s$",
"type": "string",
"description": "Planned duration of the stop in seconds.",
"examples": [
"300s"
]
},
"plannedArrival": {
"type": "string",
"description": "Planned arrival time at the stop.",
"format": "date-time",
"examples": [
"2026-03-30T13:00:00Z"
]
},
"note": {
"type": "string",
"description": "Top-level note for the stop, as entered manually by route planners,\n inherited from a saved or imported stop, or set by order import automation\n rules.",
"examples": [
"Leave at door."
]
},
"address": {
"allOf": [
{
"title": "Address",
"type": "object",
"properties": {
"address1": {
"type": "string",
"description": "Street address line 1 (e.g. `\"123 Main St\"`).",
"examples": [
"123 Main St"
]
},
"address2": {
"type": "string",
"description": "Street address line 2 (e.g. `\"Apt 101\"`).",
"examples": [
"Apt 3B"
]
},
"city": {
"type": "string",
"description": "City name (e.g. `\"New York\"`).",
"examples": [
"New York"
]
},
"provinceCode": {
"type": "string",
"description": "Province or state as subdivision codes in\n [ISO 3166-2](https://en.wikipedia.org/wiki/ISO_3166-2) format without the\n country prefix (e.g. `\"NY\"` for New York).",
"examples": [
"NY"
]
},
"countryCode": {
"type": "string",
"description": "Country code (e.g. `\"US\"`).",
"examples": [
"US"
]
},
"zip": {
"type": "string",
"description": "Postal or ZIP code (e.g. `\"10001\"`).",
"examples": [
"10001"
]
}
},
"description": "A physical street address."
}
],
"description": "Delivery address for the stop.",
"examples": [
{
"address1": "123 Main St",
"address2": "Apt 3B",
"city": "New York",
"provinceCode": "NY",
"countryCode": "US",
"zip": "10001"
}
]
},
"contact": {
"allOf": [
{
"title": "Contact",
"type": "object",
"properties": {
"firstName": {
"type": "string",
"description": "First name (e.g. `\"John\"`).",
"examples": [
"John"
]
},
"lastName": {
"type": "string",
"description": "Last name (e.g. `\"Doe\"`).",
"examples": [
"Doe"
]
},
"company": {
"type": "string",
"description": "Company name (e.g. `\"Roundtrip Systems Inc\"`).",
"examples": [
"Roundtrip Systems Inc"
]
},
"phone": {
"type": "string",
"description": "Phone number in [E.164 format](https://en.wikipedia.org/wiki/E.164) (e.g.\n `\"+14265551000\"`).",
"examples": [
"+14265551000"
]
},
"email": {
"type": "string",
"description": "Email address (e.g. `\"john.doe@roundtrip.ai\"`)",
"examples": [
"john.doe@roundtrip.ai"
]
}
},
"description": "Contact information for a person or company."
}
],
"description": "Contact information for the stop delivery recipient.",
"examples": [
{
"firstName": "John",
"lastName": "Doe",
"company": "Roundtrip Systems Inc",
"phone": "+14265551000",
"email": "john.doe@roundtrip.ai"
}
]
},
"plannedCoordinates": {
"allOf": [
{
"type": "object",
"properties": {
"latitude": {
"type": "number",
"description": "The latitude in degrees. It must be in the range [-90.0, +90.0].",
"format": "double"
},
"longitude": {
"type": "number",
"description": "The longitude in degrees. It must be in the range [-180.0, +180.0].",
"format": "double"
}
},
"description": "An object that represents a latitude/longitude pair. This is expressed as a\n pair of doubles to represent degrees latitude and degrees longitude. Unless\n specified otherwise, this must conform to the\n WGS84\n standard. Values must be within normalized ranges."
}
],
"description": "Planned coordinates for the stop.",
"examples": [
{
"latitude": 40.7128,
"longitude": -74.006
}
]
},
"items": {
"type": "array",
"items": {
"title": "StopItem",
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "Item name (e.g. `\"Bananas\"`).",
"examples": [
"Bananas"
]
},
"quantity": {
"type": "integer",
"description": "Quantity of the item (e.g. `5`).",
"format": "int32",
"examples": [
5
]
},
"grams": {
"type": "integer",
"description": "Weight of the item in grams (e.g. `500`).",
"format": "int32",
"examples": [
500
]
},
"sku": {
"type": "string",
"description": "Stock keeping unit (e.g. `\"BANANA-001\"`).",
"examples": [
"BANANA-001"
]
}
},
"description": "An item to be delivered at a stop."
},
"description": "Items to deliver at the stop."
},
"source": {
"enum": [
"UNKNOWN",
"SHOPIFY_ORDER",
"SAVED_STOP",
"IMPORTED_STOP"
],
"type": "string",
"description": "The source of the stop, which may be populated for `DELIVERY` stops. The\n source can be a `SHOPIFY_ORDER`, an EasyRoutes `SAVED_STOP`, or an\n `IMPORTED_STOP` from an external source (such as CSV file).",
"format": "enum",
"examples": [
"IMPORTED_STOP"
]
},
"shopifyOrderId": {
"type": "string",
"description": "The Shopify order ID, populated when the stop source is a `SHOPIFY_ORDER`.",
"examples": [
"6229749334323"
]
},
"savedStopId": {
"type": "string",
"description": "The saved stop ID, populated when the stop source is a `SAVED_STOP`.",
"examples": [
"sst-123e4567-e89b-12d3-a456-426614174000"
]
},
"deliveredCoordinates": {
"allOf": [
{
"type": "object",
"properties": {
"latitude": {
"type": "number",
"description": "The latitude in degrees. It must be in the range [-90.0, +90.0].",
"format": "double"
},
"longitude": {
"type": "number",
"description": "The longitude in degrees. It must be in the range [-180.0, +180.0].",
"format": "double"
}
},
"description": "An object that represents a latitude/longitude pair. This is expressed as a\n pair of doubles to represent degrees latitude and degrees longitude. Unless\n specified otherwise, this must conform to the\n WGS84\n standard. Values must be within normalized ranges."
}
],
"description": "Delivered coordinates for the stop."
},
"proofOfDeliveryNote": {
"type": "string",
"description": "Proof of delivery note for the stop.",
"examples": [
"Left at door."
]
},
"proofOfDeliveryPhotos": {
"type": "array",
"items": {
"title": "StopAttachment",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Attachment ID (e.g. `\"att-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"att-123e4567-e89b-12d3-a456-426614174000"
]
},
"createdAt": {
"type": "string",
"description": "Timestamp when the attachment was created.",
"format": "date-time",
"examples": [
"2026-03-30T09:05:00Z"
]
},
"url": {
"type": "string",
"description": "URL to fetch the attachment.",
"examples": [
"https://example.com/stop-attachment/attachment-2025-06-03-1"
]
}
},
"description": "An attachment to a stop, such as a proof of delivery photo or signature."
},
"description": "Proof of delivery photos for the stop. Photos may be fetched using the URLs\n on the attachments."
},
"proofOfDeliverySignatures": {
"type": "array",
"items": {
"title": "StopAttachment",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Attachment ID (e.g. `\"att-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"att-123e4567-e89b-12d3-a456-426614174000"
]
},
"createdAt": {
"type": "string",
"description": "Timestamp when the attachment was created.",
"format": "date-time",
"examples": [
"2026-03-30T09:05:00Z"
]
},
"url": {
"type": "string",
"description": "URL to fetch the attachment.",
"examples": [
"https://example.com/stop-attachment/attachment-2025-06-03-1"
]
}
},
"description": "An attachment to a stop, such as a proof of delivery photo or signature."
},
"description": "Proof of delivery signatures for the stop. Signatures may be fetched using\n the URLs on the attachments."
},
"tasks": {
"type": "array",
"items": {
"title": "Task",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Task ID (e.g. `\"tsk-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"tsk-123e4567-e89b-12d3-a456-426614174000"
]
},
"title": {
"type": "string",
"description": "Task title (e.g. `\"Delivery checklist\"`).",
"examples": [
"Delivery checklist"
]
},
"type": {
"enum": [
"UNKNOWN",
"CHECKBOXES",
"RADIO_BUTTONS",
"TEXT_INPUT",
"DECIMAL_INPUT",
"SCANNER_INPUT"
],
"type": "string",
"description": "Task type.",
"format": "enum",
"examples": [
"TEXT_INPUT"
]
},
"items": {
"type": "array",
"items": {
"title": "TaskItem",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Item ID (e.g. `\"itm-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"itm-123e4567-e89b-12d3-a456-426614174000"
]
},
"title": {
"type": "string",
"description": "Item title (e.g. `\"Pick up package\"`).",
"examples": [
"Pick up package"
]
},
"complete": {
"type": "boolean",
"description": "Whether the item is completed.",
"examples": [
true
]
},
"updatedAt": {
"type": "string",
"description": "Timestamp when the item was last updated.",
"format": "date-time",
"examples": [
"2026-03-30T13:00:00Z"
]
}
},
"description": "An item within a task. For `CHECKBOXES`, each item on a task may be completed\n independently. For `RADIO_BUTTONS`, at most one item will be completed."
},
"description": "Task items (populated for `CHECKBOXES` and `RADIO_BUTTONS`).",
"examples": [
[]
]
},
"input": {
"allOf": [
{
"title": "TaskInput",
"type": "object",
"properties": {
"value": {
"type": "string",
"description": "Input value.",
"examples": [
"020123456789"
]
},
"updatedAt": {
"type": "string",
"description": "Timestamp when the input was last updated.",
"format": "date-time",
"examples": [
"2026-03-30T13:00:00Z"
]
},
"inputMethod": {
"enum": [
"UNKNOWN",
"SCANNED"
],
"type": "string",
"description": "Whether input was scanned (e.g. a scanned barcode)",
"format": "enum",
"examples": [
"SCANNED"
]
}
},
"description": "Captured driver input for a task. The value may be text for `TEXT_INPUT`\n tasks or a string decimal number for `DECIMAL_INPUT` tasks."
}
],
"description": "Task input (populated for `TEXT_INPUT` and `DECIMAL_INPUT`)."
},
"requiredToMarkStopAsDelivered": {
"type": "boolean",
"description": "Whether the task is required to mark the stop as completed. In the case of\n tasks on `RouteStart`, this represents tasks required for starting the\n route. In the case of tasks on `RouteEnd`, this represents tasks required\n for completing the route.",
"examples": [
true
]
},
"requiredToMarkStopAsAttempted": {
"type": "boolean",
"description": "Whether the task is required to mark the stop as attempted.",
"examples": [
true
]
}
},
"description": "A task to be completed at a stop, or at the start or end of a route. Tasks\n may have one or more items for `CHECKBOXES` or `RADIO_BUTTONS`, or may have\n an input for `TEXT_INPUT` or `DECIMAL_INPUT`."
},
"description": "Driver tasks for the stop, including completed items and any input from the\n driver."
},
"priority": {
"maximum": 10,
"type": "integer",
"description": "Priority of the stop for route planning. The valid range for stop priority\n is between `1` (low) and `10` (high), with default priority corresponding\n to a value of `5`. A priority value of `0` is considered unset and is\n treated the same as \"default\" priority. Stops with higher priority will be\n preferred when generating routes with constraints.",
"format": "int32",
"examples": [
8
]
},
"importedStopId": {
"type": "string",
"description": "The imported stop ID, populated when the stop source is `IMPORTED_STOP`.",
"examples": [
"ist-123e4567-e89b-12d3-a456-426614174000"
]
},
"orderName": {
"type": "string",
"description": "The name of the order associated with the stop. For Shopify orders, the\n name is generated by combining the `orderNumber` property with the order\n prefix and suffix that are set in the merchant's general settings. For\n EasyRoutes imported orders, this field is populated with the order name\n provided on import.",
"examples": [
"#1234"
]
},
"distanceMeters": {
"type": "number",
"description": "The distance in meters from the previous stop.",
"format": "double",
"examples": [
123.45
]
},
"updatedArrival": {
"type": "string",
"description": "Estimated arrival time at the stop. If the stop is completed, this will be\n the actual arrival time.",
"format": "date-time",
"examples": [
"2026-03-30T13:05:00Z"
]
},
"timeWindows": {
"type": "array",
"items": {
"title": "TimeWindow",
"type": "object",
"properties": {
"start": {
"allOf": [
{
"title": "TimeOfDay",
"type": "object",
"properties": {
"hours": {
"maximum": 23,
"type": "integer",
"description": "Hours of day in 24 hour format. Must be from 0 to 23.",
"format": "int32",
"examples": [
13
]
},
"minutes": {
"maximum": 59,
"type": "integer",
"description": "Minutes of hour of day. Must be from 0 to 59.",
"format": "int32",
"examples": [
37
]
},
"seconds": {
"maximum": 59,
"type": "integer",
"description": "Seconds of minutes of the time. Must be from 0 to 59.",
"format": "int32",
"examples": [
16
]
}
},
"description": "A time of day, independent of a particular date or timezone."
}
],
"description": "The start time of the time window (optional)."
},
"end": {
"allOf": [
{
"title": "TimeOfDay",
"type": "object",
"properties": {
"hours": {
"maximum": 23,
"type": "integer",
"description": "Hours of day in 24 hour format. Must be from 0 to 23.",
"format": "int32",
"examples": [
13
]
},
"minutes": {
"maximum": 59,
"type": "integer",
"description": "Minutes of hour of day. Must be from 0 to 59.",
"format": "int32",
"examples": [
37
]
},
"seconds": {
"maximum": 59,
"type": "integer",
"description": "Seconds of minutes of the time. Must be from 0 to 59.",
"format": "int32",
"examples": [
16
]
}
},
"description": "A time of day, independent of a particular date or timezone."
}
],
"description": "The end time of the time window (optional)."
}
},
"description": "A time window for a stop. The time window may be open-ended, but one or both\n of the start and end times should be provided. The end time must be >= the\n start time."
},
"description": "The time window for the stop. Note that we currently support at most one\n time window but may support multiple time windows in the future.",
"examples": [
[
{
"start": {
"hours": 9
},
"end": {
"hours": 17
}
}
]
]
},
"deliveryDate": {
"allOf": [
{
"title": "Date",
"required": [
"year",
"month",
"day"
],
"type": "object",
"properties": {
"year": {
"maximum": 9999,
"minimum": 1,
"type": "integer",
"description": "Year of the date. Must be from 1 to 9999.",
"format": "int32",
"examples": [
2019
]
},
"month": {
"maximum": 12,
"minimum": 1,
"type": "integer",
"description": "Month of a year. Must be from 1 to 12.",
"format": "int32",
"examples": [
11
]
},
"day": {
"maximum": 31,
"minimum": 1,
"type": "integer",
"description": "Day of a month. Must be from 1 to 31.",
"format": "int32",
"examples": [
15
]
}
},
"description": "A date in year-month-day format."
}
],
"description": "The planned delivery date for the stop.",
"examples": [
{
"year": 2025,
"month": 12,
"day": 16
}
]
},
"attributes": {
"type": "array",
"items": {
"title": "Attribute",
"type": "object",
"properties": {
"key": {
"type": "string",
"description": "Attribute key. Must be non-empty.",
"examples": [
"delivery_date"
]
},
"value": {
"type": "string",
"description": "Attribute value.",
"examples": [
"2025-12-16"
]
}
},
"description": "A key-value pair for storing additional information on a stop, such as order\n details, delivery instructions, or custom fields."
},
"description": "Additional attributes for the stop. Attributes are key-value pairs for\n storing additional structured data on stops. These may be populated from\n the Shopify order or set on import.",
"examples": [
[
{
"key": "color",
"value": "blue"
}
]
]
},
"clientStopId": {
"type": "string",
"description": "The client-provided ID associated with the stop, if provided on import.",
"examples": [
"test-order-1234"
]
},
"tags": {
"type": "array",
"items": {
"type": "string"
},
"description": "The tags for the stop. Tags are used to categorize stops and can be used\n for filtering and grouping stops in the EasyRoutes web app. These may be\n populated from the Shopify order or set on import.",
"examples": [
[
"foo",
"bar"
]
]
},
"attemptedReason": {
"enum": [
"UNKNOWN",
"NOT_AVAILABLE",
"ACCESS_DENIED",
"INCORRECT_ADDRESS",
"SAFE_PLACE_UNAVAILABLE",
"REFUSED",
"EXTERNAL",
"INCORRECT_ITEMS",
"OTHER",
"CANCELED"
],
"type": "string",
"description": "The reason for marking the stop as attempted. This is only populated when\n `deliveryStatus = ATTEMPTED_DELIVERY`.",
"format": "enum",
"examples": [
"NOT_AVAILABLE"
]
},
"attemptedNote": {
"type": "string",
"description": "Optional note related to the reason for marking the stop as attempted. This\n is optionally populated when `deliveryStatus = ATTEMPTED_DELIVERY`.",
"examples": [
"Customer did not answer the door."
]
},
"customerRating": {
"allOf": [
{
"title": "CustomerRating",
"type": "object",
"properties": {
"rating": {
"maximum": 5,
"minimum": 1,
"type": "integer",
"description": "Rating from 1-5",
"format": "int32",
"examples": [
5
]
},
"comment": {
"type": "string",
"description": "Customer comment related to rating",
"examples": [
"Excellent delivery"
]
},
"createdAt": {
"type": "string",
"description": "Timestamp when rating was left by customer.",
"format": "date-time",
"examples": [
"2026-03-30T18:00:00Z"
]
}
},
"description": "Customer rating and feedback left on a stop."
}
],
"description": "Rating left by customer. This can only be populated once `deliveryStatus =\n DELIVERED`."
},
"customSignatureDisclosure": {
"type": "string",
"description": "Optional custom signature disclosure that is shown to customers in the\n driver app.",
"examples": [
"I acknowledge that I have received this delivery."
]
},
"shopifyOrder": {
"allOf": [
{
"title": "ShopifyOrder",
"type": "object",
"properties": {
"orderNote": {
"type": "string",
"description": "The Shopify order note.",
"examples": [
"Customer has paid."
]
},
"customerNote": {
"type": "string",
"description": "The Shopify customer note for the order.",
"examples": [
"Leave at door."
]
}
},
"description": "Shopify-specific information for a RouteStop."
}
],
"description": "Information from the associated Shopify order, if applicable. Populated if\n stop source is `SHOPIFY_ORDER`"
},
"proofOfDeliveryBarcodes": {
"type": "array",
"items": {
"title": "ScannedBarcode",
"type": "object",
"properties": {
"value": {
"type": "string",
"description": "Barcode value (e.g. `\"123456789012\"`).",
"examples": [
"123456789012"
]
},
"createdAt": {
"type": "string",
"description": "Timestamp when the barcode was scanned.",
"format": "date-time",
"examples": [
"2026-03-30T13:10:00Z"
]
}
},
"description": "A proof of delivery barcode scanned at a stop."
},
"description": "Proof of delivery barcodes scanned at the stop."
},
"proofOfDeliveryBarcodeIssues": {
"type": "array",
"items": {
"title": "ScannedBarcodeIssue",
"type": "object",
"properties": {
"reason": {
"enum": [
"UNKNOWN",
"ITEM_MISSING",
"NOT_SCANNABLE",
"INCORRECT"
],
"type": "string",
"description": "The reported reason for the barcode issue.",
"format": "enum",
"examples": [
"ITEM_MISSING"
]
},
"note": {
"type": "string",
"description": "Optional note related to the reason for reporting a barcode issue.",
"examples": [
"Item was not packed."
]
},
"createdAt": {
"type": "string",
"description": "Timestamp when the issue was reported.",
"format": "date-time",
"examples": [
"2026-03-30T13:10:00Z"
]
}
},
"description": "A reported issue related to scanning barcodes at a stop."
},
"description": "Proof of delivery barcode issues reported at the stop."
},
"orderReferenceUrl": {
"type": "string",
"description": "A reference URL for the order associated with the stop (e.g. a link to the\n order in your order management system). Must be a valid HTTPS URL. This\n field can only be populated for imported stops.",
"examples": [
"https://orders.example.com/orders/148977776"
]
}
},
"description": "A stop on a route. A stop may correspond to a delivery or a driver break as\n determined by the type. A delivery stop will have location and contact\n information, items to deliver, optional order details, status, arrival time\n and stop duration, driver tasks and any proof of delivery information. A\n break stop will have start time and duration, and status."
},
"description": "Route stops. See RouteStop for stop fields."
},
"createdAt": {
"type": "string",
"description": "Timestamp when the route was created.",
"format": "date-time",
"examples": [
"2026-03-29T08:00:00Z"
]
},
"updatedAt": {
"type": "string",
"description": "Timestamp when the route was last updated (by the planner).",
"format": "date-time",
"examples": [
"2026-03-30T13:15:00Z"
]
},
"archivedAt": {
"type": "string",
"description": "Timestamp when the route was archived.",
"format": "date-time",
"examples": [
"2026-04-05T00:00:00Z"
]
},
"scheduledFor": {
"type": "string",
"description": "Timestamp when the route is scheduled for.",
"format": "date-time",
"examples": [
"2026-03-30T09:00:00Z"
]
},
"totalDistanceMeters": {
"type": "number",
"description": "The distance in meters for the entire route.",
"format": "double",
"examples": [
2387.2
]
},
"totalItemQuantity": {
"type": "integer",
"description": "The total quantity of items to deliver on the route.",
"format": "int32",
"examples": [
50
]
},
"totalItemGrams": {
"type": "string",
"description": "The total weight in grams for the items on the route.",
"examples": [
"6000"
]
},
"optimized": {
"type": "boolean",
"description": "Whether the route has been optimized. Adding or removing stops, reordering\n stops, or changing route options generally set this field to false until\n the route is reoptimized.",
"examples": [
true
]
},
"dispatchedUntil": {
"type": "string",
"description": "Timestamp until which the route is dispatched and accessible in the driver\n app.",
"format": "date-time",
"examples": [
"2026-03-30T20:00:00Z"
]
},
"note": {
"type": "string",
"description": "Top-level note for the route, as entered manually by route planners.",
"examples": [
"Fragile items."
]
},
"tags": {
"type": "array",
"items": {
"type": "string"
},
"description": "The tags for the route. Tags are used to categorize routes and can be\n used for filtering and grouping routes in the EasyRoutes web app.",
"examples": [
[
"foo",
"bar"
]
]
},
"defaultStopDuration": {
"pattern": "^-?(?:0|[1-9][0-9]{0,11})(?:\\.[0-9]{1,9})?s$",
"type": "string",
"description": "The default duration for stops on the route. Used to estimate arrival\n times for stops that do not have their own duration specified.\n Specified as a duration string in the format \"300s\" for 5 minutes, \"60s\"\n for 1 minute, etc.",
"examples": [
"300s"
]
},
"maxDuration": {
"pattern": "^-?(?:0|[1-9][0-9]{0,11})(?:\\.[0-9]{1,9})?s$",
"type": "string",
"description": "The maximum duration of the route. Specified as a duration string in the\n format \"3600s\" for 1 hour, \"7200s\" for 2 hours, etc.",
"examples": [
"28800s"
]
},
"maxStops": {
"type": "integer",
"description": "The maximum number of stops on the route.",
"format": "int32",
"examples": [
50
]
},
"maxItemCount": {
"type": "integer",
"description": "The maximum total item count across all stops on the route.",
"format": "int32",
"examples": [
200
]
},
"maxKilograms": {
"type": "number",
"description": "The maximum total weight in kilograms across all stops on the route.",
"format": "double",
"examples": [
500
]
},
"avoidTolls": {
"type": "boolean",
"description": "Whether to avoid toll roads during optimization.",
"examples": [
true
]
},
"avoidUTurns": {
"type": "boolean",
"description": "Whether to avoid U-turns during optimization.",
"examples": [
true
]
},
"speedFactor": {
"type": "number",
"description": "A speed factor for the route used during optimization to adjust estimated\n travel times. A value of 1.0 represents normal speed. Values less than 1.0\n indicate slower travel (e.g. 0.5 = half speed), and values greater than\n 1.0 indicate faster travel (e.g. 1.5 = 50% faster). Must be between 0.1\n and 1.9. A value of 0 (or unset) uses the default speed.",
"format": "double",
"examples": [
0.8
]
},
"vehicle": {
"allOf": [
{
"title": "Vehicle",
"required": [
"id"
],
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Vehicle ID.",
"examples": [
"veh-123e4567-e89b-12d3-a456-426614174000"
]
},
"name": {
"type": "string",
"description": "Vehicle name.",
"examples": [
"Delivery Van 1"
]
},
"make": {
"type": "string",
"description": "Vehicle make.",
"examples": [
"Ford"
]
},
"model": {
"type": "string",
"description": "Vehicle model.",
"examples": [
"Transit"
]
},
"year": {
"type": "integer",
"description": "Vehicle model year.",
"format": "int32",
"examples": [
2023
]
},
"type": {
"enum": [
"UNKNOWN",
"CAR",
"CARGO_VAN",
"PICKUP_TRUCK",
"BOX_TRUCK",
"MOTORCYCLE",
"BICYCLE",
"DRONE",
"OTHER"
],
"type": "string",
"description": "Vehicle type.",
"format": "enum",
"examples": [
"CARGO_VAN"
]
},
"vin": {
"type": "string",
"description": "Vehicle Identification Number.",
"examples": [
"1FTBW2CM5NKA12345"
]
},
"license": {
"type": "string",
"description": "Vehicle license plate.",
"examples": [
"ABC-1234"
]
},
"isArchived": {
"type": "boolean",
"description": "Whether the vehicle is archived.",
"examples": [
false
]
},
"createdTimestamp": {
"type": "string",
"description": "Timestamp when the vehicle was created.",
"format": "date-time",
"examples": [
"2026-07-30T12:00:00Z"
]
}
},
"description": "A vehicle that can be assigned to a route."
}
],
"description": "Assigned vehicle for the route."
}
},
"description": "A route of stops, optionally with an assigned driver."
}
}
}
},
"default": {
"description": "Default error response",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"code": {
"type": "integer",
"description": "The status code, which should be an enum value of [google.rpc.Code][google.rpc.Code].",
"format": "int32"
},
"message": {
"type": "string",
"description": "A developer-facing error message, which should be in English. Any user-facing error message should be localized and sent in the [google.rpc.Status.details][google.rpc.Status.details] field, or localized by the client."
},
"details": {
"type": "array",
"items": {
"type": "object",
"properties": {
"@type": {
"type": "string",
"description": "The type of the serialized message."
}
},
"additionalProperties": true,
"description": "Contains an arbitrary serialized message along with a @type that describes the type of the serialized message."
},
"description": "A list of messages that carry the error details. There is a common set of message types for APIs to use."
}
},
"description": "The `Status` type defines a logical error model that is suitable for different programming environments, including REST APIs and RPC APIs. It is used by [gRPC](https://github.com/grpc). Each `Status` message contains three pieces of data: error code, error message, and error details. You can find out more about this error model and how to work with it in the [API Design Guide](https://cloud.google.com/apis/design/errors)."
}
}
}
}
},
"security": [
{
"bearerAuth": []
}
],
"components": {
"securitySchemes": {
"bearerAuth": {
"type": "http",
"description": "Access token from `/authenticate`",
"scheme": "bearer",
"bearerFormat": "JWT"
}
}
}
}
```
# Unassign route vehicle (https://docs.roundtrip.ai/docs/api-reference/routes/delete-routes-routeId-vehicle)
DELETE /routes/{routeId}/vehicle
Unassigns vehicle from a route by route ID. The response will include the
updated route with no vehicle assigned.
## OpenAPI specification
```json
{
"servers": [
{
"url": "https://easyroutes.roundtrip.ai/api/2024-07"
}
],
"tags": [
"Routes"
],
"summary": "Unassign route vehicle",
"description": "Unassigns vehicle from a route by route ID. The response will include the\n updated route with no vehicle assigned.",
"operationId": "UnassignRouteVehicle",
"parameters": [
{
"name": "routeId",
"in": "path",
"description": "The route ID to unassign the vehicle from.",
"required": true,
"schema": {
"type": "string",
"examples": [
"rte-123e4567-e89b-12d3-a456-426614174000"
]
}
},
{
"name": "Idempotency-Key",
"in": "header",
"description": "A unique key for safely retrying this operation. For more information read [our guide](https://docs.roundtrip.ai/docs/concepts/idempotency.md).",
"schema": {
"maxLength": 255,
"minLength": 1,
"type": "string"
},
"examples": {
"default": {
"value": "550e8400-e29b-41d4-a716-446655440000"
}
}
}
],
"responses": {
"200": {
"description": "OK",
"headers": {
"Idempotency-Key": {
"description": "The idempotency key associated with the response.",
"schema": {
"type": "string"
}
},
"Idempotency-Replayed": {
"description": "Whether the response was replayed from a previous request.",
"schema": {
"type": "boolean"
}
}
},
"content": {
"application/json": {
"schema": {
"title": "Route",
"required": [
"id",
"name",
"stops",
"createdAt",
"updatedAt",
"totalDistanceMeters",
"totalItemQuantity",
"totalItemGrams",
"optimized"
],
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Route ID (e.g. `\"rte-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"rte-123e4567-e89b-12d3-a456-426614174000"
]
},
"name": {
"type": "string",
"description": "Route name (e.g. `\"Morning route\"`).",
"examples": [
"Morning route"
]
},
"driver": {
"allOf": [
{
"title": "Driver",
"required": [
"id"
],
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Driver ID (e.g. `\"drv-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"drv-123e4567-e89b-12d3-a456-426614174000"
]
},
"firstName": {
"type": "string",
"description": "Driver first name (e.g. `\"John\"`).",
"examples": [
"John"
]
},
"lastName": {
"type": "string",
"description": "Driver last name (e.g. `\"Doe\"`).",
"examples": [
"Doe"
]
},
"phone": {
"type": "string",
"description": "Driver phone number in [E.164 format](https://en.wikipedia.org/wiki/E.164)\n (e.g. `\"+14265551000\"`).",
"examples": [
"+14265551000"
]
},
"status": {
"enum": [
"UNKNOWN",
"ACTIVE",
"INACTIVE",
"ARCHIVED"
],
"type": "string",
"description": "Shop driver status. (e.g. `ACTIVE`).",
"format": "enum",
"examples": [
"ACTIVE"
]
}
},
"description": "A driver who is assigned to a route."
}
],
"description": "Assigned driver for the route."
},
"start": {
"allOf": [
{
"title": "RouteStart",
"type": "object",
"properties": {
"address": {
"allOf": [
{
"title": "Address",
"type": "object",
"properties": {
"address1": {
"type": "string",
"description": "Street address line 1 (e.g. `\"123 Main St\"`).",
"examples": [
"123 Main St"
]
},
"address2": {
"type": "string",
"description": "Street address line 2 (e.g. `\"Apt 101\"`).",
"examples": [
"Apt 3B"
]
},
"city": {
"type": "string",
"description": "City name (e.g. `\"New York\"`).",
"examples": [
"New York"
]
},
"provinceCode": {
"type": "string",
"description": "Province or state as subdivision codes in\n [ISO 3166-2](https://en.wikipedia.org/wiki/ISO_3166-2) format without the\n country prefix (e.g. `\"NY\"` for New York).",
"examples": [
"NY"
]
},
"countryCode": {
"type": "string",
"description": "Country code (e.g. `\"US\"`).",
"examples": [
"US"
]
},
"zip": {
"type": "string",
"description": "Postal or ZIP code (e.g. `\"10001\"`).",
"examples": [
"10001"
]
}
},
"description": "A physical street address."
}
],
"description": "The start address of the route.",
"examples": [
{
"address1": "123 Main St",
"address2": "Apt 3B",
"city": "New York",
"provinceCode": "NY",
"countryCode": "US",
"zip": "10001"
}
]
},
"tasks": {
"type": "array",
"items": {
"title": "Task",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Task ID (e.g. `\"tsk-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"tsk-123e4567-e89b-12d3-a456-426614174000"
]
},
"title": {
"type": "string",
"description": "Task title (e.g. `\"Delivery checklist\"`).",
"examples": [
"Delivery checklist"
]
},
"type": {
"enum": [
"UNKNOWN",
"CHECKBOXES",
"RADIO_BUTTONS",
"TEXT_INPUT",
"DECIMAL_INPUT",
"SCANNER_INPUT"
],
"type": "string",
"description": "Task type.",
"format": "enum",
"examples": [
"TEXT_INPUT"
]
},
"items": {
"type": "array",
"items": {
"title": "TaskItem",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Item ID (e.g. `\"itm-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"itm-123e4567-e89b-12d3-a456-426614174000"
]
},
"title": {
"type": "string",
"description": "Item title (e.g. `\"Pick up package\"`).",
"examples": [
"Pick up package"
]
},
"complete": {
"type": "boolean",
"description": "Whether the item is completed.",
"examples": [
true
]
},
"updatedAt": {
"type": "string",
"description": "Timestamp when the item was last updated.",
"format": "date-time",
"examples": [
"2026-03-30T13:00:00Z"
]
}
},
"description": "An item within a task. For `CHECKBOXES`, each item on a task may be completed\n independently. For `RADIO_BUTTONS`, at most one item will be completed."
},
"description": "Task items (populated for `CHECKBOXES` and `RADIO_BUTTONS`).",
"examples": [
[]
]
},
"input": {
"allOf": [
{
"title": "TaskInput",
"type": "object",
"properties": {
"value": {
"type": "string",
"description": "Input value.",
"examples": [
"020123456789"
]
},
"updatedAt": {
"type": "string",
"description": "Timestamp when the input was last updated.",
"format": "date-time",
"examples": [
"2026-03-30T13:00:00Z"
]
},
"inputMethod": {
"enum": [
"UNKNOWN",
"SCANNED"
],
"type": "string",
"description": "Whether input was scanned (e.g. a scanned barcode)",
"format": "enum",
"examples": [
"SCANNED"
]
}
},
"description": "Captured driver input for a task. The value may be text for `TEXT_INPUT`\n tasks or a string decimal number for `DECIMAL_INPUT` tasks."
}
],
"description": "Task input (populated for `TEXT_INPUT` and `DECIMAL_INPUT`)."
},
"requiredToMarkStopAsDelivered": {
"type": "boolean",
"description": "Whether the task is required to mark the stop as completed. In the case of\n tasks on `RouteStart`, this represents tasks required for starting the\n route. In the case of tasks on `RouteEnd`, this represents tasks required\n for completing the route.",
"examples": [
true
]
},
"requiredToMarkStopAsAttempted": {
"type": "boolean",
"description": "Whether the task is required to mark the stop as attempted.",
"examples": [
true
]
}
},
"description": "A task to be completed at a stop, or at the start or end of a route. Tasks\n may have one or more items for `CHECKBOXES` or `RADIO_BUTTONS`, or may have\n an input for `TEXT_INPUT` or `DECIMAL_INPUT`."
},
"description": "Tasks to complete before starting the route."
},
"status": {
"enum": [
"UNKNOWN",
"STARTED"
],
"type": "string",
"description": "Status indicating whether the route has been started.",
"format": "enum",
"examples": [
"STARTED"
]
},
"updatedStart": {
"type": "string",
"description": "Updated start time for the route. If the route is started, this will be the\n actual start time.",
"format": "date-time",
"examples": [
"2026-03-30T09:05:00Z"
]
},
"scheduledStart": {
"type": "string",
"description": "Scheduled start time for the route (same as `scheduledFor` on the route).",
"format": "date-time",
"examples": [
"2026-03-30T09:00:00Z"
]
},
"photos": {
"type": "array",
"items": {
"title": "StopAttachment",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Attachment ID (e.g. `\"att-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"att-123e4567-e89b-12d3-a456-426614174000"
]
},
"createdAt": {
"type": "string",
"description": "Timestamp when the attachment was created.",
"format": "date-time",
"examples": [
"2026-03-30T09:05:00Z"
]
},
"url": {
"type": "string",
"description": "URL to fetch the attachment.",
"examples": [
"https://example.com/stop-attachment/attachment-2025-06-03-1"
]
}
},
"description": "An attachment to a stop, such as a proof of delivery photo or signature."
},
"description": "Photos for the route start. Photos may be fetched using the URLs on the\n attachments."
}
},
"description": "The start location of a route and any driver tasks to complete before\n beginning the route."
}
],
"description": "Route start address and tasks."
},
"end": {
"allOf": [
{
"title": "RouteEnd",
"type": "object",
"properties": {
"address": {
"allOf": [
{
"title": "Address",
"type": "object",
"properties": {
"address1": {
"type": "string",
"description": "Street address line 1 (e.g. `\"123 Main St\"`).",
"examples": [
"123 Main St"
]
},
"address2": {
"type": "string",
"description": "Street address line 2 (e.g. `\"Apt 101\"`).",
"examples": [
"Apt 3B"
]
},
"city": {
"type": "string",
"description": "City name (e.g. `\"New York\"`).",
"examples": [
"New York"
]
},
"provinceCode": {
"type": "string",
"description": "Province or state as subdivision codes in\n [ISO 3166-2](https://en.wikipedia.org/wiki/ISO_3166-2) format without the\n country prefix (e.g. `\"NY\"` for New York).",
"examples": [
"NY"
]
},
"countryCode": {
"type": "string",
"description": "Country code (e.g. `\"US\"`).",
"examples": [
"US"
]
},
"zip": {
"type": "string",
"description": "Postal or ZIP code (e.g. `\"10001\"`).",
"examples": [
"10001"
]
}
},
"description": "A physical street address."
}
],
"description": "The end address of the route.",
"examples": [
{
"address1": "123 Main St",
"address2": "Apt 3B",
"city": "New York",
"provinceCode": "NY",
"countryCode": "US",
"zip": "10001"
}
]
},
"tasks": {
"type": "array",
"items": {
"title": "Task",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Task ID (e.g. `\"tsk-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"tsk-123e4567-e89b-12d3-a456-426614174000"
]
},
"title": {
"type": "string",
"description": "Task title (e.g. `\"Delivery checklist\"`).",
"examples": [
"Delivery checklist"
]
},
"type": {
"enum": [
"UNKNOWN",
"CHECKBOXES",
"RADIO_BUTTONS",
"TEXT_INPUT",
"DECIMAL_INPUT",
"SCANNER_INPUT"
],
"type": "string",
"description": "Task type.",
"format": "enum",
"examples": [
"TEXT_INPUT"
]
},
"items": {
"type": "array",
"items": {
"title": "TaskItem",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Item ID (e.g. `\"itm-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"itm-123e4567-e89b-12d3-a456-426614174000"
]
},
"title": {
"type": "string",
"description": "Item title (e.g. `\"Pick up package\"`).",
"examples": [
"Pick up package"
]
},
"complete": {
"type": "boolean",
"description": "Whether the item is completed.",
"examples": [
true
]
},
"updatedAt": {
"type": "string",
"description": "Timestamp when the item was last updated.",
"format": "date-time",
"examples": [
"2026-03-30T13:00:00Z"
]
}
},
"description": "An item within a task. For `CHECKBOXES`, each item on a task may be completed\n independently. For `RADIO_BUTTONS`, at most one item will be completed."
},
"description": "Task items (populated for `CHECKBOXES` and `RADIO_BUTTONS`).",
"examples": [
[]
]
},
"input": {
"allOf": [
{
"title": "TaskInput",
"type": "object",
"properties": {
"value": {
"type": "string",
"description": "Input value.",
"examples": [
"020123456789"
]
},
"updatedAt": {
"type": "string",
"description": "Timestamp when the input was last updated.",
"format": "date-time",
"examples": [
"2026-03-30T13:00:00Z"
]
},
"inputMethod": {
"enum": [
"UNKNOWN",
"SCANNED"
],
"type": "string",
"description": "Whether input was scanned (e.g. a scanned barcode)",
"format": "enum",
"examples": [
"SCANNED"
]
}
},
"description": "Captured driver input for a task. The value may be text for `TEXT_INPUT`\n tasks or a string decimal number for `DECIMAL_INPUT` tasks."
}
],
"description": "Task input (populated for `TEXT_INPUT` and `DECIMAL_INPUT`)."
},
"requiredToMarkStopAsDelivered": {
"type": "boolean",
"description": "Whether the task is required to mark the stop as completed. In the case of\n tasks on `RouteStart`, this represents tasks required for starting the\n route. In the case of tasks on `RouteEnd`, this represents tasks required\n for completing the route.",
"examples": [
true
]
},
"requiredToMarkStopAsAttempted": {
"type": "boolean",
"description": "Whether the task is required to mark the stop as attempted.",
"examples": [
true
]
}
},
"description": "A task to be completed at a stop, or at the start or end of a route. Tasks\n may have one or more items for `CHECKBOXES` or `RADIO_BUTTONS`, or may have\n an input for `TEXT_INPUT` or `DECIMAL_INPUT`."
},
"description": "Tasks to complete before finishing the route."
},
"plannedArrival": {
"type": "string",
"description": "Planned arrival time at the end of the route.",
"format": "date-time",
"examples": [
"2026-03-30T17:00:00Z"
]
},
"distanceMeters": {
"type": "number",
"description": "The distance in meters from the previous stop.",
"format": "double",
"examples": [
1234.56
]
},
"updatedArrival": {
"type": "string",
"description": "Estimated arrival time at the end of the route. If the route is completed,\n this will be the actual arrival time.",
"format": "date-time",
"examples": [
"2026-03-30T17:05:00Z"
]
},
"status": {
"enum": [
"UNKNOWN",
"COMPLETED"
],
"type": "string",
"description": "Status indicating whether the route has been completed.",
"format": "enum",
"examples": [
"COMPLETED"
]
},
"photos": {
"type": "array",
"items": {
"title": "StopAttachment",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Attachment ID (e.g. `\"att-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"att-123e4567-e89b-12d3-a456-426614174000"
]
},
"createdAt": {
"type": "string",
"description": "Timestamp when the attachment was created.",
"format": "date-time",
"examples": [
"2026-03-30T09:05:00Z"
]
},
"url": {
"type": "string",
"description": "URL to fetch the attachment.",
"examples": [
"https://example.com/stop-attachment/attachment-2025-06-03-1"
]
}
},
"description": "An attachment to a stop, such as a proof of delivery photo or signature."
},
"description": "Photos for the route end. Photos may be fetched using the URLs on the\n attachments."
}
},
"description": "The end location of a route and any driver tasks to complete after completing\n the route."
}
],
"description": "Route end address and tasks."
},
"stops": {
"type": "array",
"items": {
"title": "RouteStop",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Stop ID (e.g. `\"rst-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"rst-123e4567-e89b-12d3-a456-426614174000"
]
},
"type": {
"enum": [
"UNKNOWN",
"DELIVERY",
"BREAK",
"PICKUP",
"TASK"
],
"type": "string",
"description": "The type of stop (DELIVERY, BREAK, PICKUP, or TASK).",
"format": "enum",
"examples": [
"DELIVERY"
]
},
"deliveryStatus": {
"enum": [
"UNKNOWN",
"DELIVERED",
"OUT_FOR_DELIVERY",
"ATTEMPTED_DELIVERY",
"READY_FOR_DELIVERY"
],
"type": "string",
"description": "The status for DELIVERY, PICKUP, or TASK stops.",
"format": "enum",
"examples": [
"ATTEMPTED_DELIVERY"
]
},
"breakStatus": {
"enum": [
"UNKNOWN",
"COMPLETED"
],
"type": "string",
"description": "The status for BREAK stops.",
"format": "enum",
"examples": [
"COMPLETED"
]
},
"updatedAt": {
"type": "string",
"description": "Timestamp when the stop status was last updated. Note that this timestamp\n corresponds only to major status updates (i.e. stop marked as DELIVERED).\n Minor updates like task completion or adding proof of delivery will not\n advance this timestamp. For those events, use the timestamps on the task or\n proof of delivery attachment.",
"format": "date-time",
"examples": [
"2026-03-30T13:15:00Z"
]
},
"duration": {
"pattern": "^-?(?:0|[1-9][0-9]{0,11})(?:\\.[0-9]{1,9})?s$",
"type": "string",
"description": "Planned duration of the stop in seconds.",
"examples": [
"300s"
]
},
"plannedArrival": {
"type": "string",
"description": "Planned arrival time at the stop.",
"format": "date-time",
"examples": [
"2026-03-30T13:00:00Z"
]
},
"note": {
"type": "string",
"description": "Top-level note for the stop, as entered manually by route planners,\n inherited from a saved or imported stop, or set by order import automation\n rules.",
"examples": [
"Leave at door."
]
},
"address": {
"allOf": [
{
"title": "Address",
"type": "object",
"properties": {
"address1": {
"type": "string",
"description": "Street address line 1 (e.g. `\"123 Main St\"`).",
"examples": [
"123 Main St"
]
},
"address2": {
"type": "string",
"description": "Street address line 2 (e.g. `\"Apt 101\"`).",
"examples": [
"Apt 3B"
]
},
"city": {
"type": "string",
"description": "City name (e.g. `\"New York\"`).",
"examples": [
"New York"
]
},
"provinceCode": {
"type": "string",
"description": "Province or state as subdivision codes in\n [ISO 3166-2](https://en.wikipedia.org/wiki/ISO_3166-2) format without the\n country prefix (e.g. `\"NY\"` for New York).",
"examples": [
"NY"
]
},
"countryCode": {
"type": "string",
"description": "Country code (e.g. `\"US\"`).",
"examples": [
"US"
]
},
"zip": {
"type": "string",
"description": "Postal or ZIP code (e.g. `\"10001\"`).",
"examples": [
"10001"
]
}
},
"description": "A physical street address."
}
],
"description": "Delivery address for the stop.",
"examples": [
{
"address1": "123 Main St",
"address2": "Apt 3B",
"city": "New York",
"provinceCode": "NY",
"countryCode": "US",
"zip": "10001"
}
]
},
"contact": {
"allOf": [
{
"title": "Contact",
"type": "object",
"properties": {
"firstName": {
"type": "string",
"description": "First name (e.g. `\"John\"`).",
"examples": [
"John"
]
},
"lastName": {
"type": "string",
"description": "Last name (e.g. `\"Doe\"`).",
"examples": [
"Doe"
]
},
"company": {
"type": "string",
"description": "Company name (e.g. `\"Roundtrip Systems Inc\"`).",
"examples": [
"Roundtrip Systems Inc"
]
},
"phone": {
"type": "string",
"description": "Phone number in [E.164 format](https://en.wikipedia.org/wiki/E.164) (e.g.\n `\"+14265551000\"`).",
"examples": [
"+14265551000"
]
},
"email": {
"type": "string",
"description": "Email address (e.g. `\"john.doe@roundtrip.ai\"`)",
"examples": [
"john.doe@roundtrip.ai"
]
}
},
"description": "Contact information for a person or company."
}
],
"description": "Contact information for the stop delivery recipient.",
"examples": [
{
"firstName": "John",
"lastName": "Doe",
"company": "Roundtrip Systems Inc",
"phone": "+14265551000",
"email": "john.doe@roundtrip.ai"
}
]
},
"plannedCoordinates": {
"allOf": [
{
"type": "object",
"properties": {
"latitude": {
"type": "number",
"description": "The latitude in degrees. It must be in the range [-90.0, +90.0].",
"format": "double"
},
"longitude": {
"type": "number",
"description": "The longitude in degrees. It must be in the range [-180.0, +180.0].",
"format": "double"
}
},
"description": "An object that represents a latitude/longitude pair. This is expressed as a\n pair of doubles to represent degrees latitude and degrees longitude. Unless\n specified otherwise, this must conform to the\n WGS84\n standard. Values must be within normalized ranges."
}
],
"description": "Planned coordinates for the stop.",
"examples": [
{
"latitude": 40.7128,
"longitude": -74.006
}
]
},
"items": {
"type": "array",
"items": {
"title": "StopItem",
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "Item name (e.g. `\"Bananas\"`).",
"examples": [
"Bananas"
]
},
"quantity": {
"type": "integer",
"description": "Quantity of the item (e.g. `5`).",
"format": "int32",
"examples": [
5
]
},
"grams": {
"type": "integer",
"description": "Weight of the item in grams (e.g. `500`).",
"format": "int32",
"examples": [
500
]
},
"sku": {
"type": "string",
"description": "Stock keeping unit (e.g. `\"BANANA-001\"`).",
"examples": [
"BANANA-001"
]
}
},
"description": "An item to be delivered at a stop."
},
"description": "Items to deliver at the stop."
},
"source": {
"enum": [
"UNKNOWN",
"SHOPIFY_ORDER",
"SAVED_STOP",
"IMPORTED_STOP"
],
"type": "string",
"description": "The source of the stop, which may be populated for `DELIVERY` stops. The\n source can be a `SHOPIFY_ORDER`, an EasyRoutes `SAVED_STOP`, or an\n `IMPORTED_STOP` from an external source (such as CSV file).",
"format": "enum",
"examples": [
"IMPORTED_STOP"
]
},
"shopifyOrderId": {
"type": "string",
"description": "The Shopify order ID, populated when the stop source is a `SHOPIFY_ORDER`.",
"examples": [
"6229749334323"
]
},
"savedStopId": {
"type": "string",
"description": "The saved stop ID, populated when the stop source is a `SAVED_STOP`.",
"examples": [
"sst-123e4567-e89b-12d3-a456-426614174000"
]
},
"deliveredCoordinates": {
"allOf": [
{
"type": "object",
"properties": {
"latitude": {
"type": "number",
"description": "The latitude in degrees. It must be in the range [-90.0, +90.0].",
"format": "double"
},
"longitude": {
"type": "number",
"description": "The longitude in degrees. It must be in the range [-180.0, +180.0].",
"format": "double"
}
},
"description": "An object that represents a latitude/longitude pair. This is expressed as a\n pair of doubles to represent degrees latitude and degrees longitude. Unless\n specified otherwise, this must conform to the\n WGS84\n standard. Values must be within normalized ranges."
}
],
"description": "Delivered coordinates for the stop."
},
"proofOfDeliveryNote": {
"type": "string",
"description": "Proof of delivery note for the stop.",
"examples": [
"Left at door."
]
},
"proofOfDeliveryPhotos": {
"type": "array",
"items": {
"title": "StopAttachment",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Attachment ID (e.g. `\"att-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"att-123e4567-e89b-12d3-a456-426614174000"
]
},
"createdAt": {
"type": "string",
"description": "Timestamp when the attachment was created.",
"format": "date-time",
"examples": [
"2026-03-30T09:05:00Z"
]
},
"url": {
"type": "string",
"description": "URL to fetch the attachment.",
"examples": [
"https://example.com/stop-attachment/attachment-2025-06-03-1"
]
}
},
"description": "An attachment to a stop, such as a proof of delivery photo or signature."
},
"description": "Proof of delivery photos for the stop. Photos may be fetched using the URLs\n on the attachments."
},
"proofOfDeliverySignatures": {
"type": "array",
"items": {
"title": "StopAttachment",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Attachment ID (e.g. `\"att-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"att-123e4567-e89b-12d3-a456-426614174000"
]
},
"createdAt": {
"type": "string",
"description": "Timestamp when the attachment was created.",
"format": "date-time",
"examples": [
"2026-03-30T09:05:00Z"
]
},
"url": {
"type": "string",
"description": "URL to fetch the attachment.",
"examples": [
"https://example.com/stop-attachment/attachment-2025-06-03-1"
]
}
},
"description": "An attachment to a stop, such as a proof of delivery photo or signature."
},
"description": "Proof of delivery signatures for the stop. Signatures may be fetched using\n the URLs on the attachments."
},
"tasks": {
"type": "array",
"items": {
"title": "Task",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Task ID (e.g. `\"tsk-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"tsk-123e4567-e89b-12d3-a456-426614174000"
]
},
"title": {
"type": "string",
"description": "Task title (e.g. `\"Delivery checklist\"`).",
"examples": [
"Delivery checklist"
]
},
"type": {
"enum": [
"UNKNOWN",
"CHECKBOXES",
"RADIO_BUTTONS",
"TEXT_INPUT",
"DECIMAL_INPUT",
"SCANNER_INPUT"
],
"type": "string",
"description": "Task type.",
"format": "enum",
"examples": [
"TEXT_INPUT"
]
},
"items": {
"type": "array",
"items": {
"title": "TaskItem",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Item ID (e.g. `\"itm-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"itm-123e4567-e89b-12d3-a456-426614174000"
]
},
"title": {
"type": "string",
"description": "Item title (e.g. `\"Pick up package\"`).",
"examples": [
"Pick up package"
]
},
"complete": {
"type": "boolean",
"description": "Whether the item is completed.",
"examples": [
true
]
},
"updatedAt": {
"type": "string",
"description": "Timestamp when the item was last updated.",
"format": "date-time",
"examples": [
"2026-03-30T13:00:00Z"
]
}
},
"description": "An item within a task. For `CHECKBOXES`, each item on a task may be completed\n independently. For `RADIO_BUTTONS`, at most one item will be completed."
},
"description": "Task items (populated for `CHECKBOXES` and `RADIO_BUTTONS`).",
"examples": [
[]
]
},
"input": {
"allOf": [
{
"title": "TaskInput",
"type": "object",
"properties": {
"value": {
"type": "string",
"description": "Input value.",
"examples": [
"020123456789"
]
},
"updatedAt": {
"type": "string",
"description": "Timestamp when the input was last updated.",
"format": "date-time",
"examples": [
"2026-03-30T13:00:00Z"
]
},
"inputMethod": {
"enum": [
"UNKNOWN",
"SCANNED"
],
"type": "string",
"description": "Whether input was scanned (e.g. a scanned barcode)",
"format": "enum",
"examples": [
"SCANNED"
]
}
},
"description": "Captured driver input for a task. The value may be text for `TEXT_INPUT`\n tasks or a string decimal number for `DECIMAL_INPUT` tasks."
}
],
"description": "Task input (populated for `TEXT_INPUT` and `DECIMAL_INPUT`)."
},
"requiredToMarkStopAsDelivered": {
"type": "boolean",
"description": "Whether the task is required to mark the stop as completed. In the case of\n tasks on `RouteStart`, this represents tasks required for starting the\n route. In the case of tasks on `RouteEnd`, this represents tasks required\n for completing the route.",
"examples": [
true
]
},
"requiredToMarkStopAsAttempted": {
"type": "boolean",
"description": "Whether the task is required to mark the stop as attempted.",
"examples": [
true
]
}
},
"description": "A task to be completed at a stop, or at the start or end of a route. Tasks\n may have one or more items for `CHECKBOXES` or `RADIO_BUTTONS`, or may have\n an input for `TEXT_INPUT` or `DECIMAL_INPUT`."
},
"description": "Driver tasks for the stop, including completed items and any input from the\n driver."
},
"priority": {
"maximum": 10,
"type": "integer",
"description": "Priority of the stop for route planning. The valid range for stop priority\n is between `1` (low) and `10` (high), with default priority corresponding\n to a value of `5`. A priority value of `0` is considered unset and is\n treated the same as \"default\" priority. Stops with higher priority will be\n preferred when generating routes with constraints.",
"format": "int32",
"examples": [
8
]
},
"importedStopId": {
"type": "string",
"description": "The imported stop ID, populated when the stop source is `IMPORTED_STOP`.",
"examples": [
"ist-123e4567-e89b-12d3-a456-426614174000"
]
},
"orderName": {
"type": "string",
"description": "The name of the order associated with the stop. For Shopify orders, the\n name is generated by combining the `orderNumber` property with the order\n prefix and suffix that are set in the merchant's general settings. For\n EasyRoutes imported orders, this field is populated with the order name\n provided on import.",
"examples": [
"#1234"
]
},
"distanceMeters": {
"type": "number",
"description": "The distance in meters from the previous stop.",
"format": "double",
"examples": [
123.45
]
},
"updatedArrival": {
"type": "string",
"description": "Estimated arrival time at the stop. If the stop is completed, this will be\n the actual arrival time.",
"format": "date-time",
"examples": [
"2026-03-30T13:05:00Z"
]
},
"timeWindows": {
"type": "array",
"items": {
"title": "TimeWindow",
"type": "object",
"properties": {
"start": {
"allOf": [
{
"title": "TimeOfDay",
"type": "object",
"properties": {
"hours": {
"maximum": 23,
"type": "integer",
"description": "Hours of day in 24 hour format. Must be from 0 to 23.",
"format": "int32",
"examples": [
13
]
},
"minutes": {
"maximum": 59,
"type": "integer",
"description": "Minutes of hour of day. Must be from 0 to 59.",
"format": "int32",
"examples": [
37
]
},
"seconds": {
"maximum": 59,
"type": "integer",
"description": "Seconds of minutes of the time. Must be from 0 to 59.",
"format": "int32",
"examples": [
16
]
}
},
"description": "A time of day, independent of a particular date or timezone."
}
],
"description": "The start time of the time window (optional)."
},
"end": {
"allOf": [
{
"title": "TimeOfDay",
"type": "object",
"properties": {
"hours": {
"maximum": 23,
"type": "integer",
"description": "Hours of day in 24 hour format. Must be from 0 to 23.",
"format": "int32",
"examples": [
13
]
},
"minutes": {
"maximum": 59,
"type": "integer",
"description": "Minutes of hour of day. Must be from 0 to 59.",
"format": "int32",
"examples": [
37
]
},
"seconds": {
"maximum": 59,
"type": "integer",
"description": "Seconds of minutes of the time. Must be from 0 to 59.",
"format": "int32",
"examples": [
16
]
}
},
"description": "A time of day, independent of a particular date or timezone."
}
],
"description": "The end time of the time window (optional)."
}
},
"description": "A time window for a stop. The time window may be open-ended, but one or both\n of the start and end times should be provided. The end time must be >= the\n start time."
},
"description": "The time window for the stop. Note that we currently support at most one\n time window but may support multiple time windows in the future.",
"examples": [
[
{
"start": {
"hours": 9
},
"end": {
"hours": 17
}
}
]
]
},
"deliveryDate": {
"allOf": [
{
"title": "Date",
"required": [
"year",
"month",
"day"
],
"type": "object",
"properties": {
"year": {
"maximum": 9999,
"minimum": 1,
"type": "integer",
"description": "Year of the date. Must be from 1 to 9999.",
"format": "int32",
"examples": [
2019
]
},
"month": {
"maximum": 12,
"minimum": 1,
"type": "integer",
"description": "Month of a year. Must be from 1 to 12.",
"format": "int32",
"examples": [
11
]
},
"day": {
"maximum": 31,
"minimum": 1,
"type": "integer",
"description": "Day of a month. Must be from 1 to 31.",
"format": "int32",
"examples": [
15
]
}
},
"description": "A date in year-month-day format."
}
],
"description": "The planned delivery date for the stop.",
"examples": [
{
"year": 2025,
"month": 12,
"day": 16
}
]
},
"attributes": {
"type": "array",
"items": {
"title": "Attribute",
"type": "object",
"properties": {
"key": {
"type": "string",
"description": "Attribute key. Must be non-empty.",
"examples": [
"delivery_date"
]
},
"value": {
"type": "string",
"description": "Attribute value.",
"examples": [
"2025-12-16"
]
}
},
"description": "A key-value pair for storing additional information on a stop, such as order\n details, delivery instructions, or custom fields."
},
"description": "Additional attributes for the stop. Attributes are key-value pairs for\n storing additional structured data on stops. These may be populated from\n the Shopify order or set on import.",
"examples": [
[
{
"key": "color",
"value": "blue"
}
]
]
},
"clientStopId": {
"type": "string",
"description": "The client-provided ID associated with the stop, if provided on import.",
"examples": [
"test-order-1234"
]
},
"tags": {
"type": "array",
"items": {
"type": "string"
},
"description": "The tags for the stop. Tags are used to categorize stops and can be used\n for filtering and grouping stops in the EasyRoutes web app. These may be\n populated from the Shopify order or set on import.",
"examples": [
[
"foo",
"bar"
]
]
},
"attemptedReason": {
"enum": [
"UNKNOWN",
"NOT_AVAILABLE",
"ACCESS_DENIED",
"INCORRECT_ADDRESS",
"SAFE_PLACE_UNAVAILABLE",
"REFUSED",
"EXTERNAL",
"INCORRECT_ITEMS",
"OTHER",
"CANCELED"
],
"type": "string",
"description": "The reason for marking the stop as attempted. This is only populated when\n `deliveryStatus = ATTEMPTED_DELIVERY`.",
"format": "enum",
"examples": [
"NOT_AVAILABLE"
]
},
"attemptedNote": {
"type": "string",
"description": "Optional note related to the reason for marking the stop as attempted. This\n is optionally populated when `deliveryStatus = ATTEMPTED_DELIVERY`.",
"examples": [
"Customer did not answer the door."
]
},
"customerRating": {
"allOf": [
{
"title": "CustomerRating",
"type": "object",
"properties": {
"rating": {
"maximum": 5,
"minimum": 1,
"type": "integer",
"description": "Rating from 1-5",
"format": "int32",
"examples": [
5
]
},
"comment": {
"type": "string",
"description": "Customer comment related to rating",
"examples": [
"Excellent delivery"
]
},
"createdAt": {
"type": "string",
"description": "Timestamp when rating was left by customer.",
"format": "date-time",
"examples": [
"2026-03-30T18:00:00Z"
]
}
},
"description": "Customer rating and feedback left on a stop."
}
],
"description": "Rating left by customer. This can only be populated once `deliveryStatus =\n DELIVERED`."
},
"customSignatureDisclosure": {
"type": "string",
"description": "Optional custom signature disclosure that is shown to customers in the\n driver app.",
"examples": [
"I acknowledge that I have received this delivery."
]
},
"shopifyOrder": {
"allOf": [
{
"title": "ShopifyOrder",
"type": "object",
"properties": {
"orderNote": {
"type": "string",
"description": "The Shopify order note.",
"examples": [
"Customer has paid."
]
},
"customerNote": {
"type": "string",
"description": "The Shopify customer note for the order.",
"examples": [
"Leave at door."
]
}
},
"description": "Shopify-specific information for a RouteStop."
}
],
"description": "Information from the associated Shopify order, if applicable. Populated if\n stop source is `SHOPIFY_ORDER`"
},
"proofOfDeliveryBarcodes": {
"type": "array",
"items": {
"title": "ScannedBarcode",
"type": "object",
"properties": {
"value": {
"type": "string",
"description": "Barcode value (e.g. `\"123456789012\"`).",
"examples": [
"123456789012"
]
},
"createdAt": {
"type": "string",
"description": "Timestamp when the barcode was scanned.",
"format": "date-time",
"examples": [
"2026-03-30T13:10:00Z"
]
}
},
"description": "A proof of delivery barcode scanned at a stop."
},
"description": "Proof of delivery barcodes scanned at the stop."
},
"proofOfDeliveryBarcodeIssues": {
"type": "array",
"items": {
"title": "ScannedBarcodeIssue",
"type": "object",
"properties": {
"reason": {
"enum": [
"UNKNOWN",
"ITEM_MISSING",
"NOT_SCANNABLE",
"INCORRECT"
],
"type": "string",
"description": "The reported reason for the barcode issue.",
"format": "enum",
"examples": [
"ITEM_MISSING"
]
},
"note": {
"type": "string",
"description": "Optional note related to the reason for reporting a barcode issue.",
"examples": [
"Item was not packed."
]
},
"createdAt": {
"type": "string",
"description": "Timestamp when the issue was reported.",
"format": "date-time",
"examples": [
"2026-03-30T13:10:00Z"
]
}
},
"description": "A reported issue related to scanning barcodes at a stop."
},
"description": "Proof of delivery barcode issues reported at the stop."
},
"orderReferenceUrl": {
"type": "string",
"description": "A reference URL for the order associated with the stop (e.g. a link to the\n order in your order management system). Must be a valid HTTPS URL. This\n field can only be populated for imported stops.",
"examples": [
"https://orders.example.com/orders/148977776"
]
}
},
"description": "A stop on a route. A stop may correspond to a delivery or a driver break as\n determined by the type. A delivery stop will have location and contact\n information, items to deliver, optional order details, status, arrival time\n and stop duration, driver tasks and any proof of delivery information. A\n break stop will have start time and duration, and status."
},
"description": "Route stops. See RouteStop for stop fields."
},
"createdAt": {
"type": "string",
"description": "Timestamp when the route was created.",
"format": "date-time",
"examples": [
"2026-03-29T08:00:00Z"
]
},
"updatedAt": {
"type": "string",
"description": "Timestamp when the route was last updated (by the planner).",
"format": "date-time",
"examples": [
"2026-03-30T13:15:00Z"
]
},
"archivedAt": {
"type": "string",
"description": "Timestamp when the route was archived.",
"format": "date-time",
"examples": [
"2026-04-05T00:00:00Z"
]
},
"scheduledFor": {
"type": "string",
"description": "Timestamp when the route is scheduled for.",
"format": "date-time",
"examples": [
"2026-03-30T09:00:00Z"
]
},
"totalDistanceMeters": {
"type": "number",
"description": "The distance in meters for the entire route.",
"format": "double",
"examples": [
2387.2
]
},
"totalItemQuantity": {
"type": "integer",
"description": "The total quantity of items to deliver on the route.",
"format": "int32",
"examples": [
50
]
},
"totalItemGrams": {
"type": "string",
"description": "The total weight in grams for the items on the route.",
"examples": [
"6000"
]
},
"optimized": {
"type": "boolean",
"description": "Whether the route has been optimized. Adding or removing stops, reordering\n stops, or changing route options generally set this field to false until\n the route is reoptimized.",
"examples": [
true
]
},
"dispatchedUntil": {
"type": "string",
"description": "Timestamp until which the route is dispatched and accessible in the driver\n app.",
"format": "date-time",
"examples": [
"2026-03-30T20:00:00Z"
]
},
"note": {
"type": "string",
"description": "Top-level note for the route, as entered manually by route planners.",
"examples": [
"Fragile items."
]
},
"tags": {
"type": "array",
"items": {
"type": "string"
},
"description": "The tags for the route. Tags are used to categorize routes and can be\n used for filtering and grouping routes in the EasyRoutes web app.",
"examples": [
[
"foo",
"bar"
]
]
},
"defaultStopDuration": {
"pattern": "^-?(?:0|[1-9][0-9]{0,11})(?:\\.[0-9]{1,9})?s$",
"type": "string",
"description": "The default duration for stops on the route. Used to estimate arrival\n times for stops that do not have their own duration specified.\n Specified as a duration string in the format \"300s\" for 5 minutes, \"60s\"\n for 1 minute, etc.",
"examples": [
"300s"
]
},
"maxDuration": {
"pattern": "^-?(?:0|[1-9][0-9]{0,11})(?:\\.[0-9]{1,9})?s$",
"type": "string",
"description": "The maximum duration of the route. Specified as a duration string in the\n format \"3600s\" for 1 hour, \"7200s\" for 2 hours, etc.",
"examples": [
"28800s"
]
},
"maxStops": {
"type": "integer",
"description": "The maximum number of stops on the route.",
"format": "int32",
"examples": [
50
]
},
"maxItemCount": {
"type": "integer",
"description": "The maximum total item count across all stops on the route.",
"format": "int32",
"examples": [
200
]
},
"maxKilograms": {
"type": "number",
"description": "The maximum total weight in kilograms across all stops on the route.",
"format": "double",
"examples": [
500
]
},
"avoidTolls": {
"type": "boolean",
"description": "Whether to avoid toll roads during optimization.",
"examples": [
true
]
},
"avoidUTurns": {
"type": "boolean",
"description": "Whether to avoid U-turns during optimization.",
"examples": [
true
]
},
"speedFactor": {
"type": "number",
"description": "A speed factor for the route used during optimization to adjust estimated\n travel times. A value of 1.0 represents normal speed. Values less than 1.0\n indicate slower travel (e.g. 0.5 = half speed), and values greater than\n 1.0 indicate faster travel (e.g. 1.5 = 50% faster). Must be between 0.1\n and 1.9. A value of 0 (or unset) uses the default speed.",
"format": "double",
"examples": [
0.8
]
},
"vehicle": {
"allOf": [
{
"title": "Vehicle",
"required": [
"id"
],
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Vehicle ID.",
"examples": [
"veh-123e4567-e89b-12d3-a456-426614174000"
]
},
"name": {
"type": "string",
"description": "Vehicle name.",
"examples": [
"Delivery Van 1"
]
},
"make": {
"type": "string",
"description": "Vehicle make.",
"examples": [
"Ford"
]
},
"model": {
"type": "string",
"description": "Vehicle model.",
"examples": [
"Transit"
]
},
"year": {
"type": "integer",
"description": "Vehicle model year.",
"format": "int32",
"examples": [
2023
]
},
"type": {
"enum": [
"UNKNOWN",
"CAR",
"CARGO_VAN",
"PICKUP_TRUCK",
"BOX_TRUCK",
"MOTORCYCLE",
"BICYCLE",
"DRONE",
"OTHER"
],
"type": "string",
"description": "Vehicle type.",
"format": "enum",
"examples": [
"CARGO_VAN"
]
},
"vin": {
"type": "string",
"description": "Vehicle Identification Number.",
"examples": [
"1FTBW2CM5NKA12345"
]
},
"license": {
"type": "string",
"description": "Vehicle license plate.",
"examples": [
"ABC-1234"
]
},
"isArchived": {
"type": "boolean",
"description": "Whether the vehicle is archived.",
"examples": [
false
]
},
"createdTimestamp": {
"type": "string",
"description": "Timestamp when the vehicle was created.",
"format": "date-time",
"examples": [
"2026-07-30T12:00:00Z"
]
}
},
"description": "A vehicle that can be assigned to a route."
}
],
"description": "Assigned vehicle for the route."
}
},
"description": "A route of stops, optionally with an assigned driver."
}
}
}
},
"default": {
"description": "Default error response",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"code": {
"type": "integer",
"description": "The status code, which should be an enum value of [google.rpc.Code][google.rpc.Code].",
"format": "int32"
},
"message": {
"type": "string",
"description": "A developer-facing error message, which should be in English. Any user-facing error message should be localized and sent in the [google.rpc.Status.details][google.rpc.Status.details] field, or localized by the client."
},
"details": {
"type": "array",
"items": {
"type": "object",
"properties": {
"@type": {
"type": "string",
"description": "The type of the serialized message."
}
},
"additionalProperties": true,
"description": "Contains an arbitrary serialized message along with a @type that describes the type of the serialized message."
},
"description": "A list of messages that carry the error details. There is a common set of message types for APIs to use."
}
},
"description": "The `Status` type defines a logical error model that is suitable for different programming environments, including REST APIs and RPC APIs. It is used by [gRPC](https://github.com/grpc). Each `Status` message contains three pieces of data: error code, error message, and error details. You can find out more about this error model and how to work with it in the [API Design Guide](https://cloud.google.com/apis/design/errors)."
}
}
}
}
},
"security": [
{
"bearerAuth": []
}
],
"components": {
"securitySchemes": {
"bearerAuth": {
"type": "http",
"description": "Access token from `/authenticate`",
"scheme": "bearer",
"bearerFormat": "JWT"
}
}
}
}
```
# Get route (https://docs.roundtrip.ai/docs/api-reference/routes/get-routes-id)
GET /routes/{id}
Fetch a single route by ID.
## OpenAPI specification
```json
{
"servers": [
{
"url": "https://easyroutes.roundtrip.ai/api/2024-07"
}
],
"tags": [
"Routes"
],
"summary": "Get route",
"description": "Fetch a single route by ID.",
"operationId": "GetRoute",
"parameters": [
{
"name": "id",
"in": "path",
"description": "The ID of the route to fetch.",
"required": true,
"schema": {
"type": "string",
"examples": [
"rte-123e4567-e89b-12d3-a456-426614174000"
]
}
}
],
"responses": {
"200": {
"description": "OK",
"content": {
"application/json": {
"schema": {
"title": "Route",
"required": [
"id",
"name",
"stops",
"createdAt",
"updatedAt",
"totalDistanceMeters",
"totalItemQuantity",
"totalItemGrams",
"optimized"
],
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Route ID (e.g. `\"rte-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"rte-123e4567-e89b-12d3-a456-426614174000"
]
},
"name": {
"type": "string",
"description": "Route name (e.g. `\"Morning route\"`).",
"examples": [
"Morning route"
]
},
"driver": {
"allOf": [
{
"title": "Driver",
"required": [
"id"
],
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Driver ID (e.g. `\"drv-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"drv-123e4567-e89b-12d3-a456-426614174000"
]
},
"firstName": {
"type": "string",
"description": "Driver first name (e.g. `\"John\"`).",
"examples": [
"John"
]
},
"lastName": {
"type": "string",
"description": "Driver last name (e.g. `\"Doe\"`).",
"examples": [
"Doe"
]
},
"phone": {
"type": "string",
"description": "Driver phone number in [E.164 format](https://en.wikipedia.org/wiki/E.164)\n (e.g. `\"+14265551000\"`).",
"examples": [
"+14265551000"
]
},
"status": {
"enum": [
"UNKNOWN",
"ACTIVE",
"INACTIVE",
"ARCHIVED"
],
"type": "string",
"description": "Shop driver status. (e.g. `ACTIVE`).",
"format": "enum",
"examples": [
"ACTIVE"
]
}
},
"description": "A driver who is assigned to a route."
}
],
"description": "Assigned driver for the route."
},
"start": {
"allOf": [
{
"title": "RouteStart",
"type": "object",
"properties": {
"address": {
"allOf": [
{
"title": "Address",
"type": "object",
"properties": {
"address1": {
"type": "string",
"description": "Street address line 1 (e.g. `\"123 Main St\"`).",
"examples": [
"123 Main St"
]
},
"address2": {
"type": "string",
"description": "Street address line 2 (e.g. `\"Apt 101\"`).",
"examples": [
"Apt 3B"
]
},
"city": {
"type": "string",
"description": "City name (e.g. `\"New York\"`).",
"examples": [
"New York"
]
},
"provinceCode": {
"type": "string",
"description": "Province or state as subdivision codes in\n [ISO 3166-2](https://en.wikipedia.org/wiki/ISO_3166-2) format without the\n country prefix (e.g. `\"NY\"` for New York).",
"examples": [
"NY"
]
},
"countryCode": {
"type": "string",
"description": "Country code (e.g. `\"US\"`).",
"examples": [
"US"
]
},
"zip": {
"type": "string",
"description": "Postal or ZIP code (e.g. `\"10001\"`).",
"examples": [
"10001"
]
}
},
"description": "A physical street address."
}
],
"description": "The start address of the route.",
"examples": [
{
"address1": "123 Main St",
"address2": "Apt 3B",
"city": "New York",
"provinceCode": "NY",
"countryCode": "US",
"zip": "10001"
}
]
},
"tasks": {
"type": "array",
"items": {
"title": "Task",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Task ID (e.g. `\"tsk-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"tsk-123e4567-e89b-12d3-a456-426614174000"
]
},
"title": {
"type": "string",
"description": "Task title (e.g. `\"Delivery checklist\"`).",
"examples": [
"Delivery checklist"
]
},
"type": {
"enum": [
"UNKNOWN",
"CHECKBOXES",
"RADIO_BUTTONS",
"TEXT_INPUT",
"DECIMAL_INPUT",
"SCANNER_INPUT"
],
"type": "string",
"description": "Task type.",
"format": "enum",
"examples": [
"TEXT_INPUT"
]
},
"items": {
"type": "array",
"items": {
"title": "TaskItem",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Item ID (e.g. `\"itm-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"itm-123e4567-e89b-12d3-a456-426614174000"
]
},
"title": {
"type": "string",
"description": "Item title (e.g. `\"Pick up package\"`).",
"examples": [
"Pick up package"
]
},
"complete": {
"type": "boolean",
"description": "Whether the item is completed.",
"examples": [
true
]
},
"updatedAt": {
"type": "string",
"description": "Timestamp when the item was last updated.",
"format": "date-time",
"examples": [
"2026-03-30T13:00:00Z"
]
}
},
"description": "An item within a task. For `CHECKBOXES`, each item on a task may be completed\n independently. For `RADIO_BUTTONS`, at most one item will be completed."
},
"description": "Task items (populated for `CHECKBOXES` and `RADIO_BUTTONS`).",
"examples": [
[]
]
},
"input": {
"allOf": [
{
"title": "TaskInput",
"type": "object",
"properties": {
"value": {
"type": "string",
"description": "Input value.",
"examples": [
"020123456789"
]
},
"updatedAt": {
"type": "string",
"description": "Timestamp when the input was last updated.",
"format": "date-time",
"examples": [
"2026-03-30T13:00:00Z"
]
},
"inputMethod": {
"enum": [
"UNKNOWN",
"SCANNED"
],
"type": "string",
"description": "Whether input was scanned (e.g. a scanned barcode)",
"format": "enum",
"examples": [
"SCANNED"
]
}
},
"description": "Captured driver input for a task. The value may be text for `TEXT_INPUT`\n tasks or a string decimal number for `DECIMAL_INPUT` tasks."
}
],
"description": "Task input (populated for `TEXT_INPUT` and `DECIMAL_INPUT`)."
},
"requiredToMarkStopAsDelivered": {
"type": "boolean",
"description": "Whether the task is required to mark the stop as completed. In the case of\n tasks on `RouteStart`, this represents tasks required for starting the\n route. In the case of tasks on `RouteEnd`, this represents tasks required\n for completing the route.",
"examples": [
true
]
},
"requiredToMarkStopAsAttempted": {
"type": "boolean",
"description": "Whether the task is required to mark the stop as attempted.",
"examples": [
true
]
}
},
"description": "A task to be completed at a stop, or at the start or end of a route. Tasks\n may have one or more items for `CHECKBOXES` or `RADIO_BUTTONS`, or may have\n an input for `TEXT_INPUT` or `DECIMAL_INPUT`."
},
"description": "Tasks to complete before starting the route."
},
"status": {
"enum": [
"UNKNOWN",
"STARTED"
],
"type": "string",
"description": "Status indicating whether the route has been started.",
"format": "enum",
"examples": [
"STARTED"
]
},
"updatedStart": {
"type": "string",
"description": "Updated start time for the route. If the route is started, this will be the\n actual start time.",
"format": "date-time",
"examples": [
"2026-03-30T09:05:00Z"
]
},
"scheduledStart": {
"type": "string",
"description": "Scheduled start time for the route (same as `scheduledFor` on the route).",
"format": "date-time",
"examples": [
"2026-03-30T09:00:00Z"
]
},
"photos": {
"type": "array",
"items": {
"title": "StopAttachment",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Attachment ID (e.g. `\"att-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"att-123e4567-e89b-12d3-a456-426614174000"
]
},
"createdAt": {
"type": "string",
"description": "Timestamp when the attachment was created.",
"format": "date-time",
"examples": [
"2026-03-30T09:05:00Z"
]
},
"url": {
"type": "string",
"description": "URL to fetch the attachment.",
"examples": [
"https://example.com/stop-attachment/attachment-2025-06-03-1"
]
}
},
"description": "An attachment to a stop, such as a proof of delivery photo or signature."
},
"description": "Photos for the route start. Photos may be fetched using the URLs on the\n attachments."
}
},
"description": "The start location of a route and any driver tasks to complete before\n beginning the route."
}
],
"description": "Route start address and tasks."
},
"end": {
"allOf": [
{
"title": "RouteEnd",
"type": "object",
"properties": {
"address": {
"allOf": [
{
"title": "Address",
"type": "object",
"properties": {
"address1": {
"type": "string",
"description": "Street address line 1 (e.g. `\"123 Main St\"`).",
"examples": [
"123 Main St"
]
},
"address2": {
"type": "string",
"description": "Street address line 2 (e.g. `\"Apt 101\"`).",
"examples": [
"Apt 3B"
]
},
"city": {
"type": "string",
"description": "City name (e.g. `\"New York\"`).",
"examples": [
"New York"
]
},
"provinceCode": {
"type": "string",
"description": "Province or state as subdivision codes in\n [ISO 3166-2](https://en.wikipedia.org/wiki/ISO_3166-2) format without the\n country prefix (e.g. `\"NY\"` for New York).",
"examples": [
"NY"
]
},
"countryCode": {
"type": "string",
"description": "Country code (e.g. `\"US\"`).",
"examples": [
"US"
]
},
"zip": {
"type": "string",
"description": "Postal or ZIP code (e.g. `\"10001\"`).",
"examples": [
"10001"
]
}
},
"description": "A physical street address."
}
],
"description": "The end address of the route.",
"examples": [
{
"address1": "123 Main St",
"address2": "Apt 3B",
"city": "New York",
"provinceCode": "NY",
"countryCode": "US",
"zip": "10001"
}
]
},
"tasks": {
"type": "array",
"items": {
"title": "Task",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Task ID (e.g. `\"tsk-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"tsk-123e4567-e89b-12d3-a456-426614174000"
]
},
"title": {
"type": "string",
"description": "Task title (e.g. `\"Delivery checklist\"`).",
"examples": [
"Delivery checklist"
]
},
"type": {
"enum": [
"UNKNOWN",
"CHECKBOXES",
"RADIO_BUTTONS",
"TEXT_INPUT",
"DECIMAL_INPUT",
"SCANNER_INPUT"
],
"type": "string",
"description": "Task type.",
"format": "enum",
"examples": [
"TEXT_INPUT"
]
},
"items": {
"type": "array",
"items": {
"title": "TaskItem",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Item ID (e.g. `\"itm-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"itm-123e4567-e89b-12d3-a456-426614174000"
]
},
"title": {
"type": "string",
"description": "Item title (e.g. `\"Pick up package\"`).",
"examples": [
"Pick up package"
]
},
"complete": {
"type": "boolean",
"description": "Whether the item is completed.",
"examples": [
true
]
},
"updatedAt": {
"type": "string",
"description": "Timestamp when the item was last updated.",
"format": "date-time",
"examples": [
"2026-03-30T13:00:00Z"
]
}
},
"description": "An item within a task. For `CHECKBOXES`, each item on a task may be completed\n independently. For `RADIO_BUTTONS`, at most one item will be completed."
},
"description": "Task items (populated for `CHECKBOXES` and `RADIO_BUTTONS`).",
"examples": [
[]
]
},
"input": {
"allOf": [
{
"title": "TaskInput",
"type": "object",
"properties": {
"value": {
"type": "string",
"description": "Input value.",
"examples": [
"020123456789"
]
},
"updatedAt": {
"type": "string",
"description": "Timestamp when the input was last updated.",
"format": "date-time",
"examples": [
"2026-03-30T13:00:00Z"
]
},
"inputMethod": {
"enum": [
"UNKNOWN",
"SCANNED"
],
"type": "string",
"description": "Whether input was scanned (e.g. a scanned barcode)",
"format": "enum",
"examples": [
"SCANNED"
]
}
},
"description": "Captured driver input for a task. The value may be text for `TEXT_INPUT`\n tasks or a string decimal number for `DECIMAL_INPUT` tasks."
}
],
"description": "Task input (populated for `TEXT_INPUT` and `DECIMAL_INPUT`)."
},
"requiredToMarkStopAsDelivered": {
"type": "boolean",
"description": "Whether the task is required to mark the stop as completed. In the case of\n tasks on `RouteStart`, this represents tasks required for starting the\n route. In the case of tasks on `RouteEnd`, this represents tasks required\n for completing the route.",
"examples": [
true
]
},
"requiredToMarkStopAsAttempted": {
"type": "boolean",
"description": "Whether the task is required to mark the stop as attempted.",
"examples": [
true
]
}
},
"description": "A task to be completed at a stop, or at the start or end of a route. Tasks\n may have one or more items for `CHECKBOXES` or `RADIO_BUTTONS`, or may have\n an input for `TEXT_INPUT` or `DECIMAL_INPUT`."
},
"description": "Tasks to complete before finishing the route."
},
"plannedArrival": {
"type": "string",
"description": "Planned arrival time at the end of the route.",
"format": "date-time",
"examples": [
"2026-03-30T17:00:00Z"
]
},
"distanceMeters": {
"type": "number",
"description": "The distance in meters from the previous stop.",
"format": "double",
"examples": [
1234.56
]
},
"updatedArrival": {
"type": "string",
"description": "Estimated arrival time at the end of the route. If the route is completed,\n this will be the actual arrival time.",
"format": "date-time",
"examples": [
"2026-03-30T17:05:00Z"
]
},
"status": {
"enum": [
"UNKNOWN",
"COMPLETED"
],
"type": "string",
"description": "Status indicating whether the route has been completed.",
"format": "enum",
"examples": [
"COMPLETED"
]
},
"photos": {
"type": "array",
"items": {
"title": "StopAttachment",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Attachment ID (e.g. `\"att-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"att-123e4567-e89b-12d3-a456-426614174000"
]
},
"createdAt": {
"type": "string",
"description": "Timestamp when the attachment was created.",
"format": "date-time",
"examples": [
"2026-03-30T09:05:00Z"
]
},
"url": {
"type": "string",
"description": "URL to fetch the attachment.",
"examples": [
"https://example.com/stop-attachment/attachment-2025-06-03-1"
]
}
},
"description": "An attachment to a stop, such as a proof of delivery photo or signature."
},
"description": "Photos for the route end. Photos may be fetched using the URLs on the\n attachments."
}
},
"description": "The end location of a route and any driver tasks to complete after completing\n the route."
}
],
"description": "Route end address and tasks."
},
"stops": {
"type": "array",
"items": {
"title": "RouteStop",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Stop ID (e.g. `\"rst-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"rst-123e4567-e89b-12d3-a456-426614174000"
]
},
"type": {
"enum": [
"UNKNOWN",
"DELIVERY",
"BREAK",
"PICKUP",
"TASK"
],
"type": "string",
"description": "The type of stop (DELIVERY, BREAK, PICKUP, or TASK).",
"format": "enum",
"examples": [
"DELIVERY"
]
},
"deliveryStatus": {
"enum": [
"UNKNOWN",
"DELIVERED",
"OUT_FOR_DELIVERY",
"ATTEMPTED_DELIVERY",
"READY_FOR_DELIVERY"
],
"type": "string",
"description": "The status for DELIVERY, PICKUP, or TASK stops.",
"format": "enum",
"examples": [
"ATTEMPTED_DELIVERY"
]
},
"breakStatus": {
"enum": [
"UNKNOWN",
"COMPLETED"
],
"type": "string",
"description": "The status for BREAK stops.",
"format": "enum",
"examples": [
"COMPLETED"
]
},
"updatedAt": {
"type": "string",
"description": "Timestamp when the stop status was last updated. Note that this timestamp\n corresponds only to major status updates (i.e. stop marked as DELIVERED).\n Minor updates like task completion or adding proof of delivery will not\n advance this timestamp. For those events, use the timestamps on the task or\n proof of delivery attachment.",
"format": "date-time",
"examples": [
"2026-03-30T13:15:00Z"
]
},
"duration": {
"pattern": "^-?(?:0|[1-9][0-9]{0,11})(?:\\.[0-9]{1,9})?s$",
"type": "string",
"description": "Planned duration of the stop in seconds.",
"examples": [
"300s"
]
},
"plannedArrival": {
"type": "string",
"description": "Planned arrival time at the stop.",
"format": "date-time",
"examples": [
"2026-03-30T13:00:00Z"
]
},
"note": {
"type": "string",
"description": "Top-level note for the stop, as entered manually by route planners,\n inherited from a saved or imported stop, or set by order import automation\n rules.",
"examples": [
"Leave at door."
]
},
"address": {
"allOf": [
{
"title": "Address",
"type": "object",
"properties": {
"address1": {
"type": "string",
"description": "Street address line 1 (e.g. `\"123 Main St\"`).",
"examples": [
"123 Main St"
]
},
"address2": {
"type": "string",
"description": "Street address line 2 (e.g. `\"Apt 101\"`).",
"examples": [
"Apt 3B"
]
},
"city": {
"type": "string",
"description": "City name (e.g. `\"New York\"`).",
"examples": [
"New York"
]
},
"provinceCode": {
"type": "string",
"description": "Province or state as subdivision codes in\n [ISO 3166-2](https://en.wikipedia.org/wiki/ISO_3166-2) format without the\n country prefix (e.g. `\"NY\"` for New York).",
"examples": [
"NY"
]
},
"countryCode": {
"type": "string",
"description": "Country code (e.g. `\"US\"`).",
"examples": [
"US"
]
},
"zip": {
"type": "string",
"description": "Postal or ZIP code (e.g. `\"10001\"`).",
"examples": [
"10001"
]
}
},
"description": "A physical street address."
}
],
"description": "Delivery address for the stop.",
"examples": [
{
"address1": "123 Main St",
"address2": "Apt 3B",
"city": "New York",
"provinceCode": "NY",
"countryCode": "US",
"zip": "10001"
}
]
},
"contact": {
"allOf": [
{
"title": "Contact",
"type": "object",
"properties": {
"firstName": {
"type": "string",
"description": "First name (e.g. `\"John\"`).",
"examples": [
"John"
]
},
"lastName": {
"type": "string",
"description": "Last name (e.g. `\"Doe\"`).",
"examples": [
"Doe"
]
},
"company": {
"type": "string",
"description": "Company name (e.g. `\"Roundtrip Systems Inc\"`).",
"examples": [
"Roundtrip Systems Inc"
]
},
"phone": {
"type": "string",
"description": "Phone number in [E.164 format](https://en.wikipedia.org/wiki/E.164) (e.g.\n `\"+14265551000\"`).",
"examples": [
"+14265551000"
]
},
"email": {
"type": "string",
"description": "Email address (e.g. `\"john.doe@roundtrip.ai\"`)",
"examples": [
"john.doe@roundtrip.ai"
]
}
},
"description": "Contact information for a person or company."
}
],
"description": "Contact information for the stop delivery recipient.",
"examples": [
{
"firstName": "John",
"lastName": "Doe",
"company": "Roundtrip Systems Inc",
"phone": "+14265551000",
"email": "john.doe@roundtrip.ai"
}
]
},
"plannedCoordinates": {
"allOf": [
{
"type": "object",
"properties": {
"latitude": {
"type": "number",
"description": "The latitude in degrees. It must be in the range [-90.0, +90.0].",
"format": "double"
},
"longitude": {
"type": "number",
"description": "The longitude in degrees. It must be in the range [-180.0, +180.0].",
"format": "double"
}
},
"description": "An object that represents a latitude/longitude pair. This is expressed as a\n pair of doubles to represent degrees latitude and degrees longitude. Unless\n specified otherwise, this must conform to the\n WGS84\n standard. Values must be within normalized ranges."
}
],
"description": "Planned coordinates for the stop.",
"examples": [
{
"latitude": 40.7128,
"longitude": -74.006
}
]
},
"items": {
"type": "array",
"items": {
"title": "StopItem",
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "Item name (e.g. `\"Bananas\"`).",
"examples": [
"Bananas"
]
},
"quantity": {
"type": "integer",
"description": "Quantity of the item (e.g. `5`).",
"format": "int32",
"examples": [
5
]
},
"grams": {
"type": "integer",
"description": "Weight of the item in grams (e.g. `500`).",
"format": "int32",
"examples": [
500
]
},
"sku": {
"type": "string",
"description": "Stock keeping unit (e.g. `\"BANANA-001\"`).",
"examples": [
"BANANA-001"
]
}
},
"description": "An item to be delivered at a stop."
},
"description": "Items to deliver at the stop."
},
"source": {
"enum": [
"UNKNOWN",
"SHOPIFY_ORDER",
"SAVED_STOP",
"IMPORTED_STOP"
],
"type": "string",
"description": "The source of the stop, which may be populated for `DELIVERY` stops. The\n source can be a `SHOPIFY_ORDER`, an EasyRoutes `SAVED_STOP`, or an\n `IMPORTED_STOP` from an external source (such as CSV file).",
"format": "enum",
"examples": [
"IMPORTED_STOP"
]
},
"shopifyOrderId": {
"type": "string",
"description": "The Shopify order ID, populated when the stop source is a `SHOPIFY_ORDER`.",
"examples": [
"6229749334323"
]
},
"savedStopId": {
"type": "string",
"description": "The saved stop ID, populated when the stop source is a `SAVED_STOP`.",
"examples": [
"sst-123e4567-e89b-12d3-a456-426614174000"
]
},
"deliveredCoordinates": {
"allOf": [
{
"type": "object",
"properties": {
"latitude": {
"type": "number",
"description": "The latitude in degrees. It must be in the range [-90.0, +90.0].",
"format": "double"
},
"longitude": {
"type": "number",
"description": "The longitude in degrees. It must be in the range [-180.0, +180.0].",
"format": "double"
}
},
"description": "An object that represents a latitude/longitude pair. This is expressed as a\n pair of doubles to represent degrees latitude and degrees longitude. Unless\n specified otherwise, this must conform to the\n WGS84\n standard. Values must be within normalized ranges."
}
],
"description": "Delivered coordinates for the stop."
},
"proofOfDeliveryNote": {
"type": "string",
"description": "Proof of delivery note for the stop.",
"examples": [
"Left at door."
]
},
"proofOfDeliveryPhotos": {
"type": "array",
"items": {
"title": "StopAttachment",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Attachment ID (e.g. `\"att-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"att-123e4567-e89b-12d3-a456-426614174000"
]
},
"createdAt": {
"type": "string",
"description": "Timestamp when the attachment was created.",
"format": "date-time",
"examples": [
"2026-03-30T09:05:00Z"
]
},
"url": {
"type": "string",
"description": "URL to fetch the attachment.",
"examples": [
"https://example.com/stop-attachment/attachment-2025-06-03-1"
]
}
},
"description": "An attachment to a stop, such as a proof of delivery photo or signature."
},
"description": "Proof of delivery photos for the stop. Photos may be fetched using the URLs\n on the attachments."
},
"proofOfDeliverySignatures": {
"type": "array",
"items": {
"title": "StopAttachment",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Attachment ID (e.g. `\"att-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"att-123e4567-e89b-12d3-a456-426614174000"
]
},
"createdAt": {
"type": "string",
"description": "Timestamp when the attachment was created.",
"format": "date-time",
"examples": [
"2026-03-30T09:05:00Z"
]
},
"url": {
"type": "string",
"description": "URL to fetch the attachment.",
"examples": [
"https://example.com/stop-attachment/attachment-2025-06-03-1"
]
}
},
"description": "An attachment to a stop, such as a proof of delivery photo or signature."
},
"description": "Proof of delivery signatures for the stop. Signatures may be fetched using\n the URLs on the attachments."
},
"tasks": {
"type": "array",
"items": {
"title": "Task",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Task ID (e.g. `\"tsk-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"tsk-123e4567-e89b-12d3-a456-426614174000"
]
},
"title": {
"type": "string",
"description": "Task title (e.g. `\"Delivery checklist\"`).",
"examples": [
"Delivery checklist"
]
},
"type": {
"enum": [
"UNKNOWN",
"CHECKBOXES",
"RADIO_BUTTONS",
"TEXT_INPUT",
"DECIMAL_INPUT",
"SCANNER_INPUT"
],
"type": "string",
"description": "Task type.",
"format": "enum",
"examples": [
"TEXT_INPUT"
]
},
"items": {
"type": "array",
"items": {
"title": "TaskItem",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Item ID (e.g. `\"itm-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"itm-123e4567-e89b-12d3-a456-426614174000"
]
},
"title": {
"type": "string",
"description": "Item title (e.g. `\"Pick up package\"`).",
"examples": [
"Pick up package"
]
},
"complete": {
"type": "boolean",
"description": "Whether the item is completed.",
"examples": [
true
]
},
"updatedAt": {
"type": "string",
"description": "Timestamp when the item was last updated.",
"format": "date-time",
"examples": [
"2026-03-30T13:00:00Z"
]
}
},
"description": "An item within a task. For `CHECKBOXES`, each item on a task may be completed\n independently. For `RADIO_BUTTONS`, at most one item will be completed."
},
"description": "Task items (populated for `CHECKBOXES` and `RADIO_BUTTONS`).",
"examples": [
[]
]
},
"input": {
"allOf": [
{
"title": "TaskInput",
"type": "object",
"properties": {
"value": {
"type": "string",
"description": "Input value.",
"examples": [
"020123456789"
]
},
"updatedAt": {
"type": "string",
"description": "Timestamp when the input was last updated.",
"format": "date-time",
"examples": [
"2026-03-30T13:00:00Z"
]
},
"inputMethod": {
"enum": [
"UNKNOWN",
"SCANNED"
],
"type": "string",
"description": "Whether input was scanned (e.g. a scanned barcode)",
"format": "enum",
"examples": [
"SCANNED"
]
}
},
"description": "Captured driver input for a task. The value may be text for `TEXT_INPUT`\n tasks or a string decimal number for `DECIMAL_INPUT` tasks."
}
],
"description": "Task input (populated for `TEXT_INPUT` and `DECIMAL_INPUT`)."
},
"requiredToMarkStopAsDelivered": {
"type": "boolean",
"description": "Whether the task is required to mark the stop as completed. In the case of\n tasks on `RouteStart`, this represents tasks required for starting the\n route. In the case of tasks on `RouteEnd`, this represents tasks required\n for completing the route.",
"examples": [
true
]
},
"requiredToMarkStopAsAttempted": {
"type": "boolean",
"description": "Whether the task is required to mark the stop as attempted.",
"examples": [
true
]
}
},
"description": "A task to be completed at a stop, or at the start or end of a route. Tasks\n may have one or more items for `CHECKBOXES` or `RADIO_BUTTONS`, or may have\n an input for `TEXT_INPUT` or `DECIMAL_INPUT`."
},
"description": "Driver tasks for the stop, including completed items and any input from the\n driver."
},
"priority": {
"maximum": 10,
"type": "integer",
"description": "Priority of the stop for route planning. The valid range for stop priority\n is between `1` (low) and `10` (high), with default priority corresponding\n to a value of `5`. A priority value of `0` is considered unset and is\n treated the same as \"default\" priority. Stops with higher priority will be\n preferred when generating routes with constraints.",
"format": "int32",
"examples": [
8
]
},
"importedStopId": {
"type": "string",
"description": "The imported stop ID, populated when the stop source is `IMPORTED_STOP`.",
"examples": [
"ist-123e4567-e89b-12d3-a456-426614174000"
]
},
"orderName": {
"type": "string",
"description": "The name of the order associated with the stop. For Shopify orders, the\n name is generated by combining the `orderNumber` property with the order\n prefix and suffix that are set in the merchant's general settings. For\n EasyRoutes imported orders, this field is populated with the order name\n provided on import.",
"examples": [
"#1234"
]
},
"distanceMeters": {
"type": "number",
"description": "The distance in meters from the previous stop.",
"format": "double",
"examples": [
123.45
]
},
"updatedArrival": {
"type": "string",
"description": "Estimated arrival time at the stop. If the stop is completed, this will be\n the actual arrival time.",
"format": "date-time",
"examples": [
"2026-03-30T13:05:00Z"
]
},
"timeWindows": {
"type": "array",
"items": {
"title": "TimeWindow",
"type": "object",
"properties": {
"start": {
"allOf": [
{
"title": "TimeOfDay",
"type": "object",
"properties": {
"hours": {
"maximum": 23,
"type": "integer",
"description": "Hours of day in 24 hour format. Must be from 0 to 23.",
"format": "int32",
"examples": [
13
]
},
"minutes": {
"maximum": 59,
"type": "integer",
"description": "Minutes of hour of day. Must be from 0 to 59.",
"format": "int32",
"examples": [
37
]
},
"seconds": {
"maximum": 59,
"type": "integer",
"description": "Seconds of minutes of the time. Must be from 0 to 59.",
"format": "int32",
"examples": [
16
]
}
},
"description": "A time of day, independent of a particular date or timezone."
}
],
"description": "The start time of the time window (optional)."
},
"end": {
"allOf": [
{
"title": "TimeOfDay",
"type": "object",
"properties": {
"hours": {
"maximum": 23,
"type": "integer",
"description": "Hours of day in 24 hour format. Must be from 0 to 23.",
"format": "int32",
"examples": [
13
]
},
"minutes": {
"maximum": 59,
"type": "integer",
"description": "Minutes of hour of day. Must be from 0 to 59.",
"format": "int32",
"examples": [
37
]
},
"seconds": {
"maximum": 59,
"type": "integer",
"description": "Seconds of minutes of the time. Must be from 0 to 59.",
"format": "int32",
"examples": [
16
]
}
},
"description": "A time of day, independent of a particular date or timezone."
}
],
"description": "The end time of the time window (optional)."
}
},
"description": "A time window for a stop. The time window may be open-ended, but one or both\n of the start and end times should be provided. The end time must be >= the\n start time."
},
"description": "The time window for the stop. Note that we currently support at most one\n time window but may support multiple time windows in the future.",
"examples": [
[
{
"start": {
"hours": 9
},
"end": {
"hours": 17
}
}
]
]
},
"deliveryDate": {
"allOf": [
{
"title": "Date",
"required": [
"year",
"month",
"day"
],
"type": "object",
"properties": {
"year": {
"maximum": 9999,
"minimum": 1,
"type": "integer",
"description": "Year of the date. Must be from 1 to 9999.",
"format": "int32",
"examples": [
2019
]
},
"month": {
"maximum": 12,
"minimum": 1,
"type": "integer",
"description": "Month of a year. Must be from 1 to 12.",
"format": "int32",
"examples": [
11
]
},
"day": {
"maximum": 31,
"minimum": 1,
"type": "integer",
"description": "Day of a month. Must be from 1 to 31.",
"format": "int32",
"examples": [
15
]
}
},
"description": "A date in year-month-day format."
}
],
"description": "The planned delivery date for the stop.",
"examples": [
{
"year": 2025,
"month": 12,
"day": 16
}
]
},
"attributes": {
"type": "array",
"items": {
"title": "Attribute",
"type": "object",
"properties": {
"key": {
"type": "string",
"description": "Attribute key. Must be non-empty.",
"examples": [
"delivery_date"
]
},
"value": {
"type": "string",
"description": "Attribute value.",
"examples": [
"2025-12-16"
]
}
},
"description": "A key-value pair for storing additional information on a stop, such as order\n details, delivery instructions, or custom fields."
},
"description": "Additional attributes for the stop. Attributes are key-value pairs for\n storing additional structured data on stops. These may be populated from\n the Shopify order or set on import.",
"examples": [
[
{
"key": "color",
"value": "blue"
}
]
]
},
"clientStopId": {
"type": "string",
"description": "The client-provided ID associated with the stop, if provided on import.",
"examples": [
"test-order-1234"
]
},
"tags": {
"type": "array",
"items": {
"type": "string"
},
"description": "The tags for the stop. Tags are used to categorize stops and can be used\n for filtering and grouping stops in the EasyRoutes web app. These may be\n populated from the Shopify order or set on import.",
"examples": [
[
"foo",
"bar"
]
]
},
"attemptedReason": {
"enum": [
"UNKNOWN",
"NOT_AVAILABLE",
"ACCESS_DENIED",
"INCORRECT_ADDRESS",
"SAFE_PLACE_UNAVAILABLE",
"REFUSED",
"EXTERNAL",
"INCORRECT_ITEMS",
"OTHER",
"CANCELED"
],
"type": "string",
"description": "The reason for marking the stop as attempted. This is only populated when\n `deliveryStatus = ATTEMPTED_DELIVERY`.",
"format": "enum",
"examples": [
"NOT_AVAILABLE"
]
},
"attemptedNote": {
"type": "string",
"description": "Optional note related to the reason for marking the stop as attempted. This\n is optionally populated when `deliveryStatus = ATTEMPTED_DELIVERY`.",
"examples": [
"Customer did not answer the door."
]
},
"customerRating": {
"allOf": [
{
"title": "CustomerRating",
"type": "object",
"properties": {
"rating": {
"maximum": 5,
"minimum": 1,
"type": "integer",
"description": "Rating from 1-5",
"format": "int32",
"examples": [
5
]
},
"comment": {
"type": "string",
"description": "Customer comment related to rating",
"examples": [
"Excellent delivery"
]
},
"createdAt": {
"type": "string",
"description": "Timestamp when rating was left by customer.",
"format": "date-time",
"examples": [
"2026-03-30T18:00:00Z"
]
}
},
"description": "Customer rating and feedback left on a stop."
}
],
"description": "Rating left by customer. This can only be populated once `deliveryStatus =\n DELIVERED`."
},
"customSignatureDisclosure": {
"type": "string",
"description": "Optional custom signature disclosure that is shown to customers in the\n driver app.",
"examples": [
"I acknowledge that I have received this delivery."
]
},
"shopifyOrder": {
"allOf": [
{
"title": "ShopifyOrder",
"type": "object",
"properties": {
"orderNote": {
"type": "string",
"description": "The Shopify order note.",
"examples": [
"Customer has paid."
]
},
"customerNote": {
"type": "string",
"description": "The Shopify customer note for the order.",
"examples": [
"Leave at door."
]
}
},
"description": "Shopify-specific information for a RouteStop."
}
],
"description": "Information from the associated Shopify order, if applicable. Populated if\n stop source is `SHOPIFY_ORDER`"
},
"proofOfDeliveryBarcodes": {
"type": "array",
"items": {
"title": "ScannedBarcode",
"type": "object",
"properties": {
"value": {
"type": "string",
"description": "Barcode value (e.g. `\"123456789012\"`).",
"examples": [
"123456789012"
]
},
"createdAt": {
"type": "string",
"description": "Timestamp when the barcode was scanned.",
"format": "date-time",
"examples": [
"2026-03-30T13:10:00Z"
]
}
},
"description": "A proof of delivery barcode scanned at a stop."
},
"description": "Proof of delivery barcodes scanned at the stop."
},
"proofOfDeliveryBarcodeIssues": {
"type": "array",
"items": {
"title": "ScannedBarcodeIssue",
"type": "object",
"properties": {
"reason": {
"enum": [
"UNKNOWN",
"ITEM_MISSING",
"NOT_SCANNABLE",
"INCORRECT"
],
"type": "string",
"description": "The reported reason for the barcode issue.",
"format": "enum",
"examples": [
"ITEM_MISSING"
]
},
"note": {
"type": "string",
"description": "Optional note related to the reason for reporting a barcode issue.",
"examples": [
"Item was not packed."
]
},
"createdAt": {
"type": "string",
"description": "Timestamp when the issue was reported.",
"format": "date-time",
"examples": [
"2026-03-30T13:10:00Z"
]
}
},
"description": "A reported issue related to scanning barcodes at a stop."
},
"description": "Proof of delivery barcode issues reported at the stop."
},
"orderReferenceUrl": {
"type": "string",
"description": "A reference URL for the order associated with the stop (e.g. a link to the\n order in your order management system). Must be a valid HTTPS URL. This\n field can only be populated for imported stops.",
"examples": [
"https://orders.example.com/orders/148977776"
]
}
},
"description": "A stop on a route. A stop may correspond to a delivery or a driver break as\n determined by the type. A delivery stop will have location and contact\n information, items to deliver, optional order details, status, arrival time\n and stop duration, driver tasks and any proof of delivery information. A\n break stop will have start time and duration, and status."
},
"description": "Route stops. See RouteStop for stop fields."
},
"createdAt": {
"type": "string",
"description": "Timestamp when the route was created.",
"format": "date-time",
"examples": [
"2026-03-29T08:00:00Z"
]
},
"updatedAt": {
"type": "string",
"description": "Timestamp when the route was last updated (by the planner).",
"format": "date-time",
"examples": [
"2026-03-30T13:15:00Z"
]
},
"archivedAt": {
"type": "string",
"description": "Timestamp when the route was archived.",
"format": "date-time",
"examples": [
"2026-04-05T00:00:00Z"
]
},
"scheduledFor": {
"type": "string",
"description": "Timestamp when the route is scheduled for.",
"format": "date-time",
"examples": [
"2026-03-30T09:00:00Z"
]
},
"totalDistanceMeters": {
"type": "number",
"description": "The distance in meters for the entire route.",
"format": "double",
"examples": [
2387.2
]
},
"totalItemQuantity": {
"type": "integer",
"description": "The total quantity of items to deliver on the route.",
"format": "int32",
"examples": [
50
]
},
"totalItemGrams": {
"type": "string",
"description": "The total weight in grams for the items on the route.",
"examples": [
"6000"
]
},
"optimized": {
"type": "boolean",
"description": "Whether the route has been optimized. Adding or removing stops, reordering\n stops, or changing route options generally set this field to false until\n the route is reoptimized.",
"examples": [
true
]
},
"dispatchedUntil": {
"type": "string",
"description": "Timestamp until which the route is dispatched and accessible in the driver\n app.",
"format": "date-time",
"examples": [
"2026-03-30T20:00:00Z"
]
},
"note": {
"type": "string",
"description": "Top-level note for the route, as entered manually by route planners.",
"examples": [
"Fragile items."
]
},
"tags": {
"type": "array",
"items": {
"type": "string"
},
"description": "The tags for the route. Tags are used to categorize routes and can be\n used for filtering and grouping routes in the EasyRoutes web app.",
"examples": [
[
"foo",
"bar"
]
]
},
"defaultStopDuration": {
"pattern": "^-?(?:0|[1-9][0-9]{0,11})(?:\\.[0-9]{1,9})?s$",
"type": "string",
"description": "The default duration for stops on the route. Used to estimate arrival\n times for stops that do not have their own duration specified.\n Specified as a duration string in the format \"300s\" for 5 minutes, \"60s\"\n for 1 minute, etc.",
"examples": [
"300s"
]
},
"maxDuration": {
"pattern": "^-?(?:0|[1-9][0-9]{0,11})(?:\\.[0-9]{1,9})?s$",
"type": "string",
"description": "The maximum duration of the route. Specified as a duration string in the\n format \"3600s\" for 1 hour, \"7200s\" for 2 hours, etc.",
"examples": [
"28800s"
]
},
"maxStops": {
"type": "integer",
"description": "The maximum number of stops on the route.",
"format": "int32",
"examples": [
50
]
},
"maxItemCount": {
"type": "integer",
"description": "The maximum total item count across all stops on the route.",
"format": "int32",
"examples": [
200
]
},
"maxKilograms": {
"type": "number",
"description": "The maximum total weight in kilograms across all stops on the route.",
"format": "double",
"examples": [
500
]
},
"avoidTolls": {
"type": "boolean",
"description": "Whether to avoid toll roads during optimization.",
"examples": [
true
]
},
"avoidUTurns": {
"type": "boolean",
"description": "Whether to avoid U-turns during optimization.",
"examples": [
true
]
},
"speedFactor": {
"type": "number",
"description": "A speed factor for the route used during optimization to adjust estimated\n travel times. A value of 1.0 represents normal speed. Values less than 1.0\n indicate slower travel (e.g. 0.5 = half speed), and values greater than\n 1.0 indicate faster travel (e.g. 1.5 = 50% faster). Must be between 0.1\n and 1.9. A value of 0 (or unset) uses the default speed.",
"format": "double",
"examples": [
0.8
]
},
"vehicle": {
"allOf": [
{
"title": "Vehicle",
"required": [
"id"
],
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Vehicle ID.",
"examples": [
"veh-123e4567-e89b-12d3-a456-426614174000"
]
},
"name": {
"type": "string",
"description": "Vehicle name.",
"examples": [
"Delivery Van 1"
]
},
"make": {
"type": "string",
"description": "Vehicle make.",
"examples": [
"Ford"
]
},
"model": {
"type": "string",
"description": "Vehicle model.",
"examples": [
"Transit"
]
},
"year": {
"type": "integer",
"description": "Vehicle model year.",
"format": "int32",
"examples": [
2023
]
},
"type": {
"enum": [
"UNKNOWN",
"CAR",
"CARGO_VAN",
"PICKUP_TRUCK",
"BOX_TRUCK",
"MOTORCYCLE",
"BICYCLE",
"DRONE",
"OTHER"
],
"type": "string",
"description": "Vehicle type.",
"format": "enum",
"examples": [
"CARGO_VAN"
]
},
"vin": {
"type": "string",
"description": "Vehicle Identification Number.",
"examples": [
"1FTBW2CM5NKA12345"
]
},
"license": {
"type": "string",
"description": "Vehicle license plate.",
"examples": [
"ABC-1234"
]
},
"isArchived": {
"type": "boolean",
"description": "Whether the vehicle is archived.",
"examples": [
false
]
},
"createdTimestamp": {
"type": "string",
"description": "Timestamp when the vehicle was created.",
"format": "date-time",
"examples": [
"2026-07-30T12:00:00Z"
]
}
},
"description": "A vehicle that can be assigned to a route."
}
],
"description": "Assigned vehicle for the route."
}
},
"description": "A route of stops, optionally with an assigned driver."
}
}
}
},
"default": {
"description": "Default error response",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"code": {
"type": "integer",
"description": "The status code, which should be an enum value of [google.rpc.Code][google.rpc.Code].",
"format": "int32"
},
"message": {
"type": "string",
"description": "A developer-facing error message, which should be in English. Any user-facing error message should be localized and sent in the [google.rpc.Status.details][google.rpc.Status.details] field, or localized by the client."
},
"details": {
"type": "array",
"items": {
"type": "object",
"properties": {
"@type": {
"type": "string",
"description": "The type of the serialized message."
}
},
"additionalProperties": true,
"description": "Contains an arbitrary serialized message along with a @type that describes the type of the serialized message."
},
"description": "A list of messages that carry the error details. There is a common set of message types for APIs to use."
}
},
"description": "The `Status` type defines a logical error model that is suitable for different programming environments, including REST APIs and RPC APIs. It is used by [gRPC](https://github.com/grpc). Each `Status` message contains three pieces of data: error code, error message, and error details. You can find out more about this error model and how to work with it in the [API Design Guide](https://cloud.google.com/apis/design/errors)."
}
}
}
}
},
"security": [
{
"bearerAuth": []
}
],
"components": {
"securitySchemes": {
"bearerAuth": {
"type": "http",
"description": "Access token from `/authenticate`",
"scheme": "bearer",
"bearerFormat": "JWT"
}
}
}
}
```
# List routes (https://docs.roundtrip.ai/docs/api-reference/routes/get-routes)
GET /routes
Fetch a list of routes based on the provided query. The query may include a
limit, sort key, timestamp bounds, and whether to include archived routes.
The response will include a list of routes and a cursor to fetch the next
page of results. Subsequent requests should include the cursor only and no
list query arguments (which are encoded in the cursor).
## OpenAPI specification
```json
{
"servers": [
{
"url": "https://easyroutes.roundtrip.ai/api/2024-07"
}
],
"tags": [
"Routes"
],
"summary": "List routes",
"description": "Fetch a list of routes based on the provided query. The query may include a\n limit, sort key, timestamp bounds, and whether to include archived routes.\n The response will include a list of routes and a cursor to fetch the next\n page of results. Subsequent requests should include the cursor only and no\n list query arguments (which are encoded in the cursor).",
"operationId": "ListRoutes",
"parameters": [
{
"name": "query.limit",
"in": "query",
"description": "Maximum number of routes to return. Must be less than or equal to `200`.\n Defaults to `20`.",
"schema": {
"maximum": 200,
"type": "integer",
"format": "int32",
"examples": [
50
]
}
},
{
"name": "query.sortKey",
"in": "query",
"description": "Sort key for the returned routes. This determines the ordering of returned\n routes.",
"schema": {
"enum": [
"UNKNOWN",
"CREATED_AT",
"UPDATED_AT",
"SCHEDULED_AT"
],
"type": "string",
"format": "enum",
"examples": [
"CREATED_AT"
]
}
},
{
"name": "query.timestampStart",
"in": "query",
"description": "Lower bound timestamp for the returned routes. This bound is applied to\n either the route created time or updated time, depending on the sort key.",
"schema": {
"type": "string",
"format": "date-time",
"examples": [
"2026-03-01T00:00:00Z"
]
}
},
{
"name": "query.timestampEnd",
"in": "query",
"description": "Upper bound timestamp for the returned routes. This bound is applied to\n either the route created time or updated time, depending on the sort key.",
"schema": {
"type": "string",
"format": "date-time",
"examples": [
"2026-03-31T23:59:59Z"
]
}
},
{
"name": "query.includeArchived",
"in": "query",
"description": "Whether to include archived routes in the results.",
"schema": {
"type": "boolean",
"examples": [
false
]
}
},
{
"name": "cursor",
"in": "query",
"description": "Must be empty on initial request, must be set on subsequent.",
"schema": {
"type": "string",
"examples": [
"eyJpZCI6IjEyMyJ9"
]
}
}
],
"responses": {
"200": {
"description": "OK",
"content": {
"application/json": {
"schema": {
"title": "ListRoutesResponse",
"required": [
"routes"
],
"type": "object",
"properties": {
"routes": {
"type": "array",
"items": {
"title": "Route",
"required": [
"id",
"name",
"stops",
"createdAt",
"updatedAt",
"totalDistanceMeters",
"totalItemQuantity",
"totalItemGrams",
"optimized"
],
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Route ID (e.g. `\"rte-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"rte-123e4567-e89b-12d3-a456-426614174000"
]
},
"name": {
"type": "string",
"description": "Route name (e.g. `\"Morning route\"`).",
"examples": [
"Morning route"
]
},
"driver": {
"allOf": [
{
"title": "Driver",
"required": [
"id"
],
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Driver ID (e.g. `\"drv-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"drv-123e4567-e89b-12d3-a456-426614174000"
]
},
"firstName": {
"type": "string",
"description": "Driver first name (e.g. `\"John\"`).",
"examples": [
"John"
]
},
"lastName": {
"type": "string",
"description": "Driver last name (e.g. `\"Doe\"`).",
"examples": [
"Doe"
]
},
"phone": {
"type": "string",
"description": "Driver phone number in [E.164 format](https://en.wikipedia.org/wiki/E.164)\n (e.g. `\"+14265551000\"`).",
"examples": [
"+14265551000"
]
},
"status": {
"enum": [
"UNKNOWN",
"ACTIVE",
"INACTIVE",
"ARCHIVED"
],
"type": "string",
"description": "Shop driver status. (e.g. `ACTIVE`).",
"format": "enum",
"examples": [
"ACTIVE"
]
}
},
"description": "A driver who is assigned to a route."
}
],
"description": "Assigned driver for the route."
},
"start": {
"allOf": [
{
"title": "RouteStart",
"type": "object",
"properties": {
"address": {
"allOf": [
{
"title": "Address",
"type": "object",
"properties": {
"address1": {
"type": "string",
"description": "Street address line 1 (e.g. `\"123 Main St\"`).",
"examples": [
"123 Main St"
]
},
"address2": {
"type": "string",
"description": "Street address line 2 (e.g. `\"Apt 101\"`).",
"examples": [
"Apt 3B"
]
},
"city": {
"type": "string",
"description": "City name (e.g. `\"New York\"`).",
"examples": [
"New York"
]
},
"provinceCode": {
"type": "string",
"description": "Province or state as subdivision codes in\n [ISO 3166-2](https://en.wikipedia.org/wiki/ISO_3166-2) format without the\n country prefix (e.g. `\"NY\"` for New York).",
"examples": [
"NY"
]
},
"countryCode": {
"type": "string",
"description": "Country code (e.g. `\"US\"`).",
"examples": [
"US"
]
},
"zip": {
"type": "string",
"description": "Postal or ZIP code (e.g. `\"10001\"`).",
"examples": [
"10001"
]
}
},
"description": "A physical street address."
}
],
"description": "The start address of the route.",
"examples": [
{
"address1": "123 Main St",
"address2": "Apt 3B",
"city": "New York",
"provinceCode": "NY",
"countryCode": "US",
"zip": "10001"
}
]
},
"tasks": {
"type": "array",
"items": {
"title": "Task",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Task ID (e.g. `\"tsk-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"tsk-123e4567-e89b-12d3-a456-426614174000"
]
},
"title": {
"type": "string",
"description": "Task title (e.g. `\"Delivery checklist\"`).",
"examples": [
"Delivery checklist"
]
},
"type": {
"enum": [
"UNKNOWN",
"CHECKBOXES",
"RADIO_BUTTONS",
"TEXT_INPUT",
"DECIMAL_INPUT",
"SCANNER_INPUT"
],
"type": "string",
"description": "Task type.",
"format": "enum",
"examples": [
"TEXT_INPUT"
]
},
"items": {
"type": "array",
"items": {
"title": "TaskItem",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Item ID (e.g. `\"itm-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"itm-123e4567-e89b-12d3-a456-426614174000"
]
},
"title": {
"type": "string",
"description": "Item title (e.g. `\"Pick up package\"`).",
"examples": [
"Pick up package"
]
},
"complete": {
"type": "boolean",
"description": "Whether the item is completed.",
"examples": [
true
]
},
"updatedAt": {
"type": "string",
"description": "Timestamp when the item was last updated.",
"format": "date-time",
"examples": [
"2026-03-30T13:00:00Z"
]
}
},
"description": "An item within a task. For `CHECKBOXES`, each item on a task may be completed\n independently. For `RADIO_BUTTONS`, at most one item will be completed."
},
"description": "Task items (populated for `CHECKBOXES` and `RADIO_BUTTONS`).",
"examples": [
[]
]
},
"input": {
"allOf": [
{
"title": "TaskInput",
"type": "object",
"properties": {
"value": {
"type": "string",
"description": "Input value.",
"examples": [
"020123456789"
]
},
"updatedAt": {
"type": "string",
"description": "Timestamp when the input was last updated.",
"format": "date-time",
"examples": [
"2026-03-30T13:00:00Z"
]
},
"inputMethod": {
"enum": [
"UNKNOWN",
"SCANNED"
],
"type": "string",
"description": "Whether input was scanned (e.g. a scanned barcode)",
"format": "enum",
"examples": [
"SCANNED"
]
}
},
"description": "Captured driver input for a task. The value may be text for `TEXT_INPUT`\n tasks or a string decimal number for `DECIMAL_INPUT` tasks."
}
],
"description": "Task input (populated for `TEXT_INPUT` and `DECIMAL_INPUT`)."
},
"requiredToMarkStopAsDelivered": {
"type": "boolean",
"description": "Whether the task is required to mark the stop as completed. In the case of\n tasks on `RouteStart`, this represents tasks required for starting the\n route. In the case of tasks on `RouteEnd`, this represents tasks required\n for completing the route.",
"examples": [
true
]
},
"requiredToMarkStopAsAttempted": {
"type": "boolean",
"description": "Whether the task is required to mark the stop as attempted.",
"examples": [
true
]
}
},
"description": "A task to be completed at a stop, or at the start or end of a route. Tasks\n may have one or more items for `CHECKBOXES` or `RADIO_BUTTONS`, or may have\n an input for `TEXT_INPUT` or `DECIMAL_INPUT`."
},
"description": "Tasks to complete before starting the route."
},
"status": {
"enum": [
"UNKNOWN",
"STARTED"
],
"type": "string",
"description": "Status indicating whether the route has been started.",
"format": "enum",
"examples": [
"STARTED"
]
},
"updatedStart": {
"type": "string",
"description": "Updated start time for the route. If the route is started, this will be the\n actual start time.",
"format": "date-time",
"examples": [
"2026-03-30T09:05:00Z"
]
},
"scheduledStart": {
"type": "string",
"description": "Scheduled start time for the route (same as `scheduledFor` on the route).",
"format": "date-time",
"examples": [
"2026-03-30T09:00:00Z"
]
},
"photos": {
"type": "array",
"items": {
"title": "StopAttachment",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Attachment ID (e.g. `\"att-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"att-123e4567-e89b-12d3-a456-426614174000"
]
},
"createdAt": {
"type": "string",
"description": "Timestamp when the attachment was created.",
"format": "date-time",
"examples": [
"2026-03-30T09:05:00Z"
]
},
"url": {
"type": "string",
"description": "URL to fetch the attachment.",
"examples": [
"https://example.com/stop-attachment/attachment-2025-06-03-1"
]
}
},
"description": "An attachment to a stop, such as a proof of delivery photo or signature."
},
"description": "Photos for the route start. Photos may be fetched using the URLs on the\n attachments."
}
},
"description": "The start location of a route and any driver tasks to complete before\n beginning the route."
}
],
"description": "Route start address and tasks."
},
"end": {
"allOf": [
{
"title": "RouteEnd",
"type": "object",
"properties": {
"address": {
"allOf": [
{
"title": "Address",
"type": "object",
"properties": {
"address1": {
"type": "string",
"description": "Street address line 1 (e.g. `\"123 Main St\"`).",
"examples": [
"123 Main St"
]
},
"address2": {
"type": "string",
"description": "Street address line 2 (e.g. `\"Apt 101\"`).",
"examples": [
"Apt 3B"
]
},
"city": {
"type": "string",
"description": "City name (e.g. `\"New York\"`).",
"examples": [
"New York"
]
},
"provinceCode": {
"type": "string",
"description": "Province or state as subdivision codes in\n [ISO 3166-2](https://en.wikipedia.org/wiki/ISO_3166-2) format without the\n country prefix (e.g. `\"NY\"` for New York).",
"examples": [
"NY"
]
},
"countryCode": {
"type": "string",
"description": "Country code (e.g. `\"US\"`).",
"examples": [
"US"
]
},
"zip": {
"type": "string",
"description": "Postal or ZIP code (e.g. `\"10001\"`).",
"examples": [
"10001"
]
}
},
"description": "A physical street address."
}
],
"description": "The end address of the route.",
"examples": [
{
"address1": "123 Main St",
"address2": "Apt 3B",
"city": "New York",
"provinceCode": "NY",
"countryCode": "US",
"zip": "10001"
}
]
},
"tasks": {
"type": "array",
"items": {
"title": "Task",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Task ID (e.g. `\"tsk-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"tsk-123e4567-e89b-12d3-a456-426614174000"
]
},
"title": {
"type": "string",
"description": "Task title (e.g. `\"Delivery checklist\"`).",
"examples": [
"Delivery checklist"
]
},
"type": {
"enum": [
"UNKNOWN",
"CHECKBOXES",
"RADIO_BUTTONS",
"TEXT_INPUT",
"DECIMAL_INPUT",
"SCANNER_INPUT"
],
"type": "string",
"description": "Task type.",
"format": "enum",
"examples": [
"TEXT_INPUT"
]
},
"items": {
"type": "array",
"items": {
"title": "TaskItem",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Item ID (e.g. `\"itm-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"itm-123e4567-e89b-12d3-a456-426614174000"
]
},
"title": {
"type": "string",
"description": "Item title (e.g. `\"Pick up package\"`).",
"examples": [
"Pick up package"
]
},
"complete": {
"type": "boolean",
"description": "Whether the item is completed.",
"examples": [
true
]
},
"updatedAt": {
"type": "string",
"description": "Timestamp when the item was last updated.",
"format": "date-time",
"examples": [
"2026-03-30T13:00:00Z"
]
}
},
"description": "An item within a task. For `CHECKBOXES`, each item on a task may be completed\n independently. For `RADIO_BUTTONS`, at most one item will be completed."
},
"description": "Task items (populated for `CHECKBOXES` and `RADIO_BUTTONS`).",
"examples": [
[]
]
},
"input": {
"allOf": [
{
"title": "TaskInput",
"type": "object",
"properties": {
"value": {
"type": "string",
"description": "Input value.",
"examples": [
"020123456789"
]
},
"updatedAt": {
"type": "string",
"description": "Timestamp when the input was last updated.",
"format": "date-time",
"examples": [
"2026-03-30T13:00:00Z"
]
},
"inputMethod": {
"enum": [
"UNKNOWN",
"SCANNED"
],
"type": "string",
"description": "Whether input was scanned (e.g. a scanned barcode)",
"format": "enum",
"examples": [
"SCANNED"
]
}
},
"description": "Captured driver input for a task. The value may be text for `TEXT_INPUT`\n tasks or a string decimal number for `DECIMAL_INPUT` tasks."
}
],
"description": "Task input (populated for `TEXT_INPUT` and `DECIMAL_INPUT`)."
},
"requiredToMarkStopAsDelivered": {
"type": "boolean",
"description": "Whether the task is required to mark the stop as completed. In the case of\n tasks on `RouteStart`, this represents tasks required for starting the\n route. In the case of tasks on `RouteEnd`, this represents tasks required\n for completing the route.",
"examples": [
true
]
},
"requiredToMarkStopAsAttempted": {
"type": "boolean",
"description": "Whether the task is required to mark the stop as attempted.",
"examples": [
true
]
}
},
"description": "A task to be completed at a stop, or at the start or end of a route. Tasks\n may have one or more items for `CHECKBOXES` or `RADIO_BUTTONS`, or may have\n an input for `TEXT_INPUT` or `DECIMAL_INPUT`."
},
"description": "Tasks to complete before finishing the route."
},
"plannedArrival": {
"type": "string",
"description": "Planned arrival time at the end of the route.",
"format": "date-time",
"examples": [
"2026-03-30T17:00:00Z"
]
},
"distanceMeters": {
"type": "number",
"description": "The distance in meters from the previous stop.",
"format": "double",
"examples": [
1234.56
]
},
"updatedArrival": {
"type": "string",
"description": "Estimated arrival time at the end of the route. If the route is completed,\n this will be the actual arrival time.",
"format": "date-time",
"examples": [
"2026-03-30T17:05:00Z"
]
},
"status": {
"enum": [
"UNKNOWN",
"COMPLETED"
],
"type": "string",
"description": "Status indicating whether the route has been completed.",
"format": "enum",
"examples": [
"COMPLETED"
]
},
"photos": {
"type": "array",
"items": {
"title": "StopAttachment",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Attachment ID (e.g. `\"att-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"att-123e4567-e89b-12d3-a456-426614174000"
]
},
"createdAt": {
"type": "string",
"description": "Timestamp when the attachment was created.",
"format": "date-time",
"examples": [
"2026-03-30T09:05:00Z"
]
},
"url": {
"type": "string",
"description": "URL to fetch the attachment.",
"examples": [
"https://example.com/stop-attachment/attachment-2025-06-03-1"
]
}
},
"description": "An attachment to a stop, such as a proof of delivery photo or signature."
},
"description": "Photos for the route end. Photos may be fetched using the URLs on the\n attachments."
}
},
"description": "The end location of a route and any driver tasks to complete after completing\n the route."
}
],
"description": "Route end address and tasks."
},
"stops": {
"type": "array",
"items": {
"title": "RouteStop",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Stop ID (e.g. `\"rst-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"rst-123e4567-e89b-12d3-a456-426614174000"
]
},
"type": {
"enum": [
"UNKNOWN",
"DELIVERY",
"BREAK",
"PICKUP",
"TASK"
],
"type": "string",
"description": "The type of stop (DELIVERY, BREAK, PICKUP, or TASK).",
"format": "enum",
"examples": [
"DELIVERY"
]
},
"deliveryStatus": {
"enum": [
"UNKNOWN",
"DELIVERED",
"OUT_FOR_DELIVERY",
"ATTEMPTED_DELIVERY",
"READY_FOR_DELIVERY"
],
"type": "string",
"description": "The status for DELIVERY, PICKUP, or TASK stops.",
"format": "enum",
"examples": [
"ATTEMPTED_DELIVERY"
]
},
"breakStatus": {
"enum": [
"UNKNOWN",
"COMPLETED"
],
"type": "string",
"description": "The status for BREAK stops.",
"format": "enum",
"examples": [
"COMPLETED"
]
},
"updatedAt": {
"type": "string",
"description": "Timestamp when the stop status was last updated. Note that this timestamp\n corresponds only to major status updates (i.e. stop marked as DELIVERED).\n Minor updates like task completion or adding proof of delivery will not\n advance this timestamp. For those events, use the timestamps on the task or\n proof of delivery attachment.",
"format": "date-time",
"examples": [
"2026-03-30T13:15:00Z"
]
},
"duration": {
"pattern": "^-?(?:0|[1-9][0-9]{0,11})(?:\\.[0-9]{1,9})?s$",
"type": "string",
"description": "Planned duration of the stop in seconds.",
"examples": [
"300s"
]
},
"plannedArrival": {
"type": "string",
"description": "Planned arrival time at the stop.",
"format": "date-time",
"examples": [
"2026-03-30T13:00:00Z"
]
},
"note": {
"type": "string",
"description": "Top-level note for the stop, as entered manually by route planners,\n inherited from a saved or imported stop, or set by order import automation\n rules.",
"examples": [
"Leave at door."
]
},
"address": {
"allOf": [
{
"title": "Address",
"type": "object",
"properties": {
"address1": {
"type": "string",
"description": "Street address line 1 (e.g. `\"123 Main St\"`).",
"examples": [
"123 Main St"
]
},
"address2": {
"type": "string",
"description": "Street address line 2 (e.g. `\"Apt 101\"`).",
"examples": [
"Apt 3B"
]
},
"city": {
"type": "string",
"description": "City name (e.g. `\"New York\"`).",
"examples": [
"New York"
]
},
"provinceCode": {
"type": "string",
"description": "Province or state as subdivision codes in\n [ISO 3166-2](https://en.wikipedia.org/wiki/ISO_3166-2) format without the\n country prefix (e.g. `\"NY\"` for New York).",
"examples": [
"NY"
]
},
"countryCode": {
"type": "string",
"description": "Country code (e.g. `\"US\"`).",
"examples": [
"US"
]
},
"zip": {
"type": "string",
"description": "Postal or ZIP code (e.g. `\"10001\"`).",
"examples": [
"10001"
]
}
},
"description": "A physical street address."
}
],
"description": "Delivery address for the stop.",
"examples": [
{
"address1": "123 Main St",
"address2": "Apt 3B",
"city": "New York",
"provinceCode": "NY",
"countryCode": "US",
"zip": "10001"
}
]
},
"contact": {
"allOf": [
{
"title": "Contact",
"type": "object",
"properties": {
"firstName": {
"type": "string",
"description": "First name (e.g. `\"John\"`).",
"examples": [
"John"
]
},
"lastName": {
"type": "string",
"description": "Last name (e.g. `\"Doe\"`).",
"examples": [
"Doe"
]
},
"company": {
"type": "string",
"description": "Company name (e.g. `\"Roundtrip Systems Inc\"`).",
"examples": [
"Roundtrip Systems Inc"
]
},
"phone": {
"type": "string",
"description": "Phone number in [E.164 format](https://en.wikipedia.org/wiki/E.164) (e.g.\n `\"+14265551000\"`).",
"examples": [
"+14265551000"
]
},
"email": {
"type": "string",
"description": "Email address (e.g. `\"john.doe@roundtrip.ai\"`)",
"examples": [
"john.doe@roundtrip.ai"
]
}
},
"description": "Contact information for a person or company."
}
],
"description": "Contact information for the stop delivery recipient.",
"examples": [
{
"firstName": "John",
"lastName": "Doe",
"company": "Roundtrip Systems Inc",
"phone": "+14265551000",
"email": "john.doe@roundtrip.ai"
}
]
},
"plannedCoordinates": {
"allOf": [
{
"type": "object",
"properties": {
"latitude": {
"type": "number",
"description": "The latitude in degrees. It must be in the range [-90.0, +90.0].",
"format": "double"
},
"longitude": {
"type": "number",
"description": "The longitude in degrees. It must be in the range [-180.0, +180.0].",
"format": "double"
}
},
"description": "An object that represents a latitude/longitude pair. This is expressed as a\n pair of doubles to represent degrees latitude and degrees longitude. Unless\n specified otherwise, this must conform to the\n WGS84\n standard. Values must be within normalized ranges."
}
],
"description": "Planned coordinates for the stop.",
"examples": [
{
"latitude": 40.7128,
"longitude": -74.006
}
]
},
"items": {
"type": "array",
"items": {
"title": "StopItem",
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "Item name (e.g. `\"Bananas\"`).",
"examples": [
"Bananas"
]
},
"quantity": {
"type": "integer",
"description": "Quantity of the item (e.g. `5`).",
"format": "int32",
"examples": [
5
]
},
"grams": {
"type": "integer",
"description": "Weight of the item in grams (e.g. `500`).",
"format": "int32",
"examples": [
500
]
},
"sku": {
"type": "string",
"description": "Stock keeping unit (e.g. `\"BANANA-001\"`).",
"examples": [
"BANANA-001"
]
}
},
"description": "An item to be delivered at a stop."
},
"description": "Items to deliver at the stop."
},
"source": {
"enum": [
"UNKNOWN",
"SHOPIFY_ORDER",
"SAVED_STOP",
"IMPORTED_STOP"
],
"type": "string",
"description": "The source of the stop, which may be populated for `DELIVERY` stops. The\n source can be a `SHOPIFY_ORDER`, an EasyRoutes `SAVED_STOP`, or an\n `IMPORTED_STOP` from an external source (such as CSV file).",
"format": "enum",
"examples": [
"IMPORTED_STOP"
]
},
"shopifyOrderId": {
"type": "string",
"description": "The Shopify order ID, populated when the stop source is a `SHOPIFY_ORDER`.",
"examples": [
"6229749334323"
]
},
"savedStopId": {
"type": "string",
"description": "The saved stop ID, populated when the stop source is a `SAVED_STOP`.",
"examples": [
"sst-123e4567-e89b-12d3-a456-426614174000"
]
},
"deliveredCoordinates": {
"allOf": [
{
"type": "object",
"properties": {
"latitude": {
"type": "number",
"description": "The latitude in degrees. It must be in the range [-90.0, +90.0].",
"format": "double"
},
"longitude": {
"type": "number",
"description": "The longitude in degrees. It must be in the range [-180.0, +180.0].",
"format": "double"
}
},
"description": "An object that represents a latitude/longitude pair. This is expressed as a\n pair of doubles to represent degrees latitude and degrees longitude. Unless\n specified otherwise, this must conform to the\n WGS84\n standard. Values must be within normalized ranges."
}
],
"description": "Delivered coordinates for the stop."
},
"proofOfDeliveryNote": {
"type": "string",
"description": "Proof of delivery note for the stop.",
"examples": [
"Left at door."
]
},
"proofOfDeliveryPhotos": {
"type": "array",
"items": {
"title": "StopAttachment",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Attachment ID (e.g. `\"att-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"att-123e4567-e89b-12d3-a456-426614174000"
]
},
"createdAt": {
"type": "string",
"description": "Timestamp when the attachment was created.",
"format": "date-time",
"examples": [
"2026-03-30T09:05:00Z"
]
},
"url": {
"type": "string",
"description": "URL to fetch the attachment.",
"examples": [
"https://example.com/stop-attachment/attachment-2025-06-03-1"
]
}
},
"description": "An attachment to a stop, such as a proof of delivery photo or signature."
},
"description": "Proof of delivery photos for the stop. Photos may be fetched using the URLs\n on the attachments."
},
"proofOfDeliverySignatures": {
"type": "array",
"items": {
"title": "StopAttachment",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Attachment ID (e.g. `\"att-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"att-123e4567-e89b-12d3-a456-426614174000"
]
},
"createdAt": {
"type": "string",
"description": "Timestamp when the attachment was created.",
"format": "date-time",
"examples": [
"2026-03-30T09:05:00Z"
]
},
"url": {
"type": "string",
"description": "URL to fetch the attachment.",
"examples": [
"https://example.com/stop-attachment/attachment-2025-06-03-1"
]
}
},
"description": "An attachment to a stop, such as a proof of delivery photo or signature."
},
"description": "Proof of delivery signatures for the stop. Signatures may be fetched using\n the URLs on the attachments."
},
"tasks": {
"type": "array",
"items": {
"title": "Task",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Task ID (e.g. `\"tsk-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"tsk-123e4567-e89b-12d3-a456-426614174000"
]
},
"title": {
"type": "string",
"description": "Task title (e.g. `\"Delivery checklist\"`).",
"examples": [
"Delivery checklist"
]
},
"type": {
"enum": [
"UNKNOWN",
"CHECKBOXES",
"RADIO_BUTTONS",
"TEXT_INPUT",
"DECIMAL_INPUT",
"SCANNER_INPUT"
],
"type": "string",
"description": "Task type.",
"format": "enum",
"examples": [
"TEXT_INPUT"
]
},
"items": {
"type": "array",
"items": {
"title": "TaskItem",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Item ID (e.g. `\"itm-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"itm-123e4567-e89b-12d3-a456-426614174000"
]
},
"title": {
"type": "string",
"description": "Item title (e.g. `\"Pick up package\"`).",
"examples": [
"Pick up package"
]
},
"complete": {
"type": "boolean",
"description": "Whether the item is completed.",
"examples": [
true
]
},
"updatedAt": {
"type": "string",
"description": "Timestamp when the item was last updated.",
"format": "date-time",
"examples": [
"2026-03-30T13:00:00Z"
]
}
},
"description": "An item within a task. For `CHECKBOXES`, each item on a task may be completed\n independently. For `RADIO_BUTTONS`, at most one item will be completed."
},
"description": "Task items (populated for `CHECKBOXES` and `RADIO_BUTTONS`).",
"examples": [
[]
]
},
"input": {
"allOf": [
{
"title": "TaskInput",
"type": "object",
"properties": {
"value": {
"type": "string",
"description": "Input value.",
"examples": [
"020123456789"
]
},
"updatedAt": {
"type": "string",
"description": "Timestamp when the input was last updated.",
"format": "date-time",
"examples": [
"2026-03-30T13:00:00Z"
]
},
"inputMethod": {
"enum": [
"UNKNOWN",
"SCANNED"
],
"type": "string",
"description": "Whether input was scanned (e.g. a scanned barcode)",
"format": "enum",
"examples": [
"SCANNED"
]
}
},
"description": "Captured driver input for a task. The value may be text for `TEXT_INPUT`\n tasks or a string decimal number for `DECIMAL_INPUT` tasks."
}
],
"description": "Task input (populated for `TEXT_INPUT` and `DECIMAL_INPUT`)."
},
"requiredToMarkStopAsDelivered": {
"type": "boolean",
"description": "Whether the task is required to mark the stop as completed. In the case of\n tasks on `RouteStart`, this represents tasks required for starting the\n route. In the case of tasks on `RouteEnd`, this represents tasks required\n for completing the route.",
"examples": [
true
]
},
"requiredToMarkStopAsAttempted": {
"type": "boolean",
"description": "Whether the task is required to mark the stop as attempted.",
"examples": [
true
]
}
},
"description": "A task to be completed at a stop, or at the start or end of a route. Tasks\n may have one or more items for `CHECKBOXES` or `RADIO_BUTTONS`, or may have\n an input for `TEXT_INPUT` or `DECIMAL_INPUT`."
},
"description": "Driver tasks for the stop, including completed items and any input from the\n driver."
},
"priority": {
"maximum": 10,
"type": "integer",
"description": "Priority of the stop for route planning. The valid range for stop priority\n is between `1` (low) and `10` (high), with default priority corresponding\n to a value of `5`. A priority value of `0` is considered unset and is\n treated the same as \"default\" priority. Stops with higher priority will be\n preferred when generating routes with constraints.",
"format": "int32",
"examples": [
8
]
},
"importedStopId": {
"type": "string",
"description": "The imported stop ID, populated when the stop source is `IMPORTED_STOP`.",
"examples": [
"ist-123e4567-e89b-12d3-a456-426614174000"
]
},
"orderName": {
"type": "string",
"description": "The name of the order associated with the stop. For Shopify orders, the\n name is generated by combining the `orderNumber` property with the order\n prefix and suffix that are set in the merchant's general settings. For\n EasyRoutes imported orders, this field is populated with the order name\n provided on import.",
"examples": [
"#1234"
]
},
"distanceMeters": {
"type": "number",
"description": "The distance in meters from the previous stop.",
"format": "double",
"examples": [
123.45
]
},
"updatedArrival": {
"type": "string",
"description": "Estimated arrival time at the stop. If the stop is completed, this will be\n the actual arrival time.",
"format": "date-time",
"examples": [
"2026-03-30T13:05:00Z"
]
},
"timeWindows": {
"type": "array",
"items": {
"title": "TimeWindow",
"type": "object",
"properties": {
"start": {
"allOf": [
{
"title": "TimeOfDay",
"type": "object",
"properties": {
"hours": {
"maximum": 23,
"type": "integer",
"description": "Hours of day in 24 hour format. Must be from 0 to 23.",
"format": "int32",
"examples": [
13
]
},
"minutes": {
"maximum": 59,
"type": "integer",
"description": "Minutes of hour of day. Must be from 0 to 59.",
"format": "int32",
"examples": [
37
]
},
"seconds": {
"maximum": 59,
"type": "integer",
"description": "Seconds of minutes of the time. Must be from 0 to 59.",
"format": "int32",
"examples": [
16
]
}
},
"description": "A time of day, independent of a particular date or timezone."
}
],
"description": "The start time of the time window (optional)."
},
"end": {
"allOf": [
{
"title": "TimeOfDay",
"type": "object",
"properties": {
"hours": {
"maximum": 23,
"type": "integer",
"description": "Hours of day in 24 hour format. Must be from 0 to 23.",
"format": "int32",
"examples": [
13
]
},
"minutes": {
"maximum": 59,
"type": "integer",
"description": "Minutes of hour of day. Must be from 0 to 59.",
"format": "int32",
"examples": [
37
]
},
"seconds": {
"maximum": 59,
"type": "integer",
"description": "Seconds of minutes of the time. Must be from 0 to 59.",
"format": "int32",
"examples": [
16
]
}
},
"description": "A time of day, independent of a particular date or timezone."
}
],
"description": "The end time of the time window (optional)."
}
},
"description": "A time window for a stop. The time window may be open-ended, but one or both\n of the start and end times should be provided. The end time must be >= the\n start time."
},
"description": "The time window for the stop. Note that we currently support at most one\n time window but may support multiple time windows in the future.",
"examples": [
[
{
"start": {
"hours": 9
},
"end": {
"hours": 17
}
}
]
]
},
"deliveryDate": {
"allOf": [
{
"title": "Date",
"required": [
"year",
"month",
"day"
],
"type": "object",
"properties": {
"year": {
"maximum": 9999,
"minimum": 1,
"type": "integer",
"description": "Year of the date. Must be from 1 to 9999.",
"format": "int32",
"examples": [
2019
]
},
"month": {
"maximum": 12,
"minimum": 1,
"type": "integer",
"description": "Month of a year. Must be from 1 to 12.",
"format": "int32",
"examples": [
11
]
},
"day": {
"maximum": 31,
"minimum": 1,
"type": "integer",
"description": "Day of a month. Must be from 1 to 31.",
"format": "int32",
"examples": [
15
]
}
},
"description": "A date in year-month-day format."
}
],
"description": "The planned delivery date for the stop.",
"examples": [
{
"year": 2025,
"month": 12,
"day": 16
}
]
},
"attributes": {
"type": "array",
"items": {
"title": "Attribute",
"type": "object",
"properties": {
"key": {
"type": "string",
"description": "Attribute key. Must be non-empty.",
"examples": [
"delivery_date"
]
},
"value": {
"type": "string",
"description": "Attribute value.",
"examples": [
"2025-12-16"
]
}
},
"description": "A key-value pair for storing additional information on a stop, such as order\n details, delivery instructions, or custom fields."
},
"description": "Additional attributes for the stop. Attributes are key-value pairs for\n storing additional structured data on stops. These may be populated from\n the Shopify order or set on import.",
"examples": [
[
{
"key": "color",
"value": "blue"
}
]
]
},
"clientStopId": {
"type": "string",
"description": "The client-provided ID associated with the stop, if provided on import.",
"examples": [
"test-order-1234"
]
},
"tags": {
"type": "array",
"items": {
"type": "string"
},
"description": "The tags for the stop. Tags are used to categorize stops and can be used\n for filtering and grouping stops in the EasyRoutes web app. These may be\n populated from the Shopify order or set on import.",
"examples": [
[
"foo",
"bar"
]
]
},
"attemptedReason": {
"enum": [
"UNKNOWN",
"NOT_AVAILABLE",
"ACCESS_DENIED",
"INCORRECT_ADDRESS",
"SAFE_PLACE_UNAVAILABLE",
"REFUSED",
"EXTERNAL",
"INCORRECT_ITEMS",
"OTHER",
"CANCELED"
],
"type": "string",
"description": "The reason for marking the stop as attempted. This is only populated when\n `deliveryStatus = ATTEMPTED_DELIVERY`.",
"format": "enum",
"examples": [
"NOT_AVAILABLE"
]
},
"attemptedNote": {
"type": "string",
"description": "Optional note related to the reason for marking the stop as attempted. This\n is optionally populated when `deliveryStatus = ATTEMPTED_DELIVERY`.",
"examples": [
"Customer did not answer the door."
]
},
"customerRating": {
"allOf": [
{
"title": "CustomerRating",
"type": "object",
"properties": {
"rating": {
"maximum": 5,
"minimum": 1,
"type": "integer",
"description": "Rating from 1-5",
"format": "int32",
"examples": [
5
]
},
"comment": {
"type": "string",
"description": "Customer comment related to rating",
"examples": [
"Excellent delivery"
]
},
"createdAt": {
"type": "string",
"description": "Timestamp when rating was left by customer.",
"format": "date-time",
"examples": [
"2026-03-30T18:00:00Z"
]
}
},
"description": "Customer rating and feedback left on a stop."
}
],
"description": "Rating left by customer. This can only be populated once `deliveryStatus =\n DELIVERED`."
},
"customSignatureDisclosure": {
"type": "string",
"description": "Optional custom signature disclosure that is shown to customers in the\n driver app.",
"examples": [
"I acknowledge that I have received this delivery."
]
},
"shopifyOrder": {
"allOf": [
{
"title": "ShopifyOrder",
"type": "object",
"properties": {
"orderNote": {
"type": "string",
"description": "The Shopify order note.",
"examples": [
"Customer has paid."
]
},
"customerNote": {
"type": "string",
"description": "The Shopify customer note for the order.",
"examples": [
"Leave at door."
]
}
},
"description": "Shopify-specific information for a RouteStop."
}
],
"description": "Information from the associated Shopify order, if applicable. Populated if\n stop source is `SHOPIFY_ORDER`"
},
"proofOfDeliveryBarcodes": {
"type": "array",
"items": {
"title": "ScannedBarcode",
"type": "object",
"properties": {
"value": {
"type": "string",
"description": "Barcode value (e.g. `\"123456789012\"`).",
"examples": [
"123456789012"
]
},
"createdAt": {
"type": "string",
"description": "Timestamp when the barcode was scanned.",
"format": "date-time",
"examples": [
"2026-03-30T13:10:00Z"
]
}
},
"description": "A proof of delivery barcode scanned at a stop."
},
"description": "Proof of delivery barcodes scanned at the stop."
},
"proofOfDeliveryBarcodeIssues": {
"type": "array",
"items": {
"title": "ScannedBarcodeIssue",
"type": "object",
"properties": {
"reason": {
"enum": [
"UNKNOWN",
"ITEM_MISSING",
"NOT_SCANNABLE",
"INCORRECT"
],
"type": "string",
"description": "The reported reason for the barcode issue.",
"format": "enum",
"examples": [
"ITEM_MISSING"
]
},
"note": {
"type": "string",
"description": "Optional note related to the reason for reporting a barcode issue.",
"examples": [
"Item was not packed."
]
},
"createdAt": {
"type": "string",
"description": "Timestamp when the issue was reported.",
"format": "date-time",
"examples": [
"2026-03-30T13:10:00Z"
]
}
},
"description": "A reported issue related to scanning barcodes at a stop."
},
"description": "Proof of delivery barcode issues reported at the stop."
},
"orderReferenceUrl": {
"type": "string",
"description": "A reference URL for the order associated with the stop (e.g. a link to the\n order in your order management system). Must be a valid HTTPS URL. This\n field can only be populated for imported stops.",
"examples": [
"https://orders.example.com/orders/148977776"
]
}
},
"description": "A stop on a route. A stop may correspond to a delivery or a driver break as\n determined by the type. A delivery stop will have location and contact\n information, items to deliver, optional order details, status, arrival time\n and stop duration, driver tasks and any proof of delivery information. A\n break stop will have start time and duration, and status."
},
"description": "Route stops. See RouteStop for stop fields."
},
"createdAt": {
"type": "string",
"description": "Timestamp when the route was created.",
"format": "date-time",
"examples": [
"2026-03-29T08:00:00Z"
]
},
"updatedAt": {
"type": "string",
"description": "Timestamp when the route was last updated (by the planner).",
"format": "date-time",
"examples": [
"2026-03-30T13:15:00Z"
]
},
"archivedAt": {
"type": "string",
"description": "Timestamp when the route was archived.",
"format": "date-time",
"examples": [
"2026-04-05T00:00:00Z"
]
},
"scheduledFor": {
"type": "string",
"description": "Timestamp when the route is scheduled for.",
"format": "date-time",
"examples": [
"2026-03-30T09:00:00Z"
]
},
"totalDistanceMeters": {
"type": "number",
"description": "The distance in meters for the entire route.",
"format": "double",
"examples": [
2387.2
]
},
"totalItemQuantity": {
"type": "integer",
"description": "The total quantity of items to deliver on the route.",
"format": "int32",
"examples": [
50
]
},
"totalItemGrams": {
"type": "string",
"description": "The total weight in grams for the items on the route.",
"examples": [
"6000"
]
},
"optimized": {
"type": "boolean",
"description": "Whether the route has been optimized. Adding or removing stops, reordering\n stops, or changing route options generally set this field to false until\n the route is reoptimized.",
"examples": [
true
]
},
"dispatchedUntil": {
"type": "string",
"description": "Timestamp until which the route is dispatched and accessible in the driver\n app.",
"format": "date-time",
"examples": [
"2026-03-30T20:00:00Z"
]
},
"note": {
"type": "string",
"description": "Top-level note for the route, as entered manually by route planners.",
"examples": [
"Fragile items."
]
},
"tags": {
"type": "array",
"items": {
"type": "string"
},
"description": "The tags for the route. Tags are used to categorize routes and can be\n used for filtering and grouping routes in the EasyRoutes web app.",
"examples": [
[
"foo",
"bar"
]
]
},
"defaultStopDuration": {
"pattern": "^-?(?:0|[1-9][0-9]{0,11})(?:\\.[0-9]{1,9})?s$",
"type": "string",
"description": "The default duration for stops on the route. Used to estimate arrival\n times for stops that do not have their own duration specified.\n Specified as a duration string in the format \"300s\" for 5 minutes, \"60s\"\n for 1 minute, etc.",
"examples": [
"300s"
]
},
"maxDuration": {
"pattern": "^-?(?:0|[1-9][0-9]{0,11})(?:\\.[0-9]{1,9})?s$",
"type": "string",
"description": "The maximum duration of the route. Specified as a duration string in the\n format \"3600s\" for 1 hour, \"7200s\" for 2 hours, etc.",
"examples": [
"28800s"
]
},
"maxStops": {
"type": "integer",
"description": "The maximum number of stops on the route.",
"format": "int32",
"examples": [
50
]
},
"maxItemCount": {
"type": "integer",
"description": "The maximum total item count across all stops on the route.",
"format": "int32",
"examples": [
200
]
},
"maxKilograms": {
"type": "number",
"description": "The maximum total weight in kilograms across all stops on the route.",
"format": "double",
"examples": [
500
]
},
"avoidTolls": {
"type": "boolean",
"description": "Whether to avoid toll roads during optimization.",
"examples": [
true
]
},
"avoidUTurns": {
"type": "boolean",
"description": "Whether to avoid U-turns during optimization.",
"examples": [
true
]
},
"speedFactor": {
"type": "number",
"description": "A speed factor for the route used during optimization to adjust estimated\n travel times. A value of 1.0 represents normal speed. Values less than 1.0\n indicate slower travel (e.g. 0.5 = half speed), and values greater than\n 1.0 indicate faster travel (e.g. 1.5 = 50% faster). Must be between 0.1\n and 1.9. A value of 0 (or unset) uses the default speed.",
"format": "double",
"examples": [
0.8
]
},
"vehicle": {
"allOf": [
{
"title": "Vehicle",
"required": [
"id"
],
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Vehicle ID.",
"examples": [
"veh-123e4567-e89b-12d3-a456-426614174000"
]
},
"name": {
"type": "string",
"description": "Vehicle name.",
"examples": [
"Delivery Van 1"
]
},
"make": {
"type": "string",
"description": "Vehicle make.",
"examples": [
"Ford"
]
},
"model": {
"type": "string",
"description": "Vehicle model.",
"examples": [
"Transit"
]
},
"year": {
"type": "integer",
"description": "Vehicle model year.",
"format": "int32",
"examples": [
2023
]
},
"type": {
"enum": [
"UNKNOWN",
"CAR",
"CARGO_VAN",
"PICKUP_TRUCK",
"BOX_TRUCK",
"MOTORCYCLE",
"BICYCLE",
"DRONE",
"OTHER"
],
"type": "string",
"description": "Vehicle type.",
"format": "enum",
"examples": [
"CARGO_VAN"
]
},
"vin": {
"type": "string",
"description": "Vehicle Identification Number.",
"examples": [
"1FTBW2CM5NKA12345"
]
},
"license": {
"type": "string",
"description": "Vehicle license plate.",
"examples": [
"ABC-1234"
]
},
"isArchived": {
"type": "boolean",
"description": "Whether the vehicle is archived.",
"examples": [
false
]
},
"createdTimestamp": {
"type": "string",
"description": "Timestamp when the vehicle was created.",
"format": "date-time",
"examples": [
"2026-07-30T12:00:00Z"
]
}
},
"description": "A vehicle that can be assigned to a route."
}
],
"description": "Assigned vehicle for the route."
}
},
"description": "A route of stops, optionally with an assigned driver."
},
"description": "List of routes."
},
"nextCursor": {
"type": "string",
"description": "Cursor to fetch the next page of results (if available).",
"examples": [
"eyJpZCI6IjEyMyJ9"
]
}
},
"description": "Response containing a list of routes and an optional cursor to fetch the next\n page."
}
}
}
},
"default": {
"description": "Default error response",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"code": {
"type": "integer",
"description": "The status code, which should be an enum value of [google.rpc.Code][google.rpc.Code].",
"format": "int32"
},
"message": {
"type": "string",
"description": "A developer-facing error message, which should be in English. Any user-facing error message should be localized and sent in the [google.rpc.Status.details][google.rpc.Status.details] field, or localized by the client."
},
"details": {
"type": "array",
"items": {
"type": "object",
"properties": {
"@type": {
"type": "string",
"description": "The type of the serialized message."
}
},
"additionalProperties": true,
"description": "Contains an arbitrary serialized message along with a @type that describes the type of the serialized message."
},
"description": "A list of messages that carry the error details. There is a common set of message types for APIs to use."
}
},
"description": "The `Status` type defines a logical error model that is suitable for different programming environments, including REST APIs and RPC APIs. It is used by [gRPC](https://github.com/grpc). Each `Status` message contains three pieces of data: error code, error message, and error details. You can find out more about this error model and how to work with it in the [API Design Guide](https://cloud.google.com/apis/design/errors)."
}
}
}
}
},
"security": [
{
"bearerAuth": []
}
],
"components": {
"securitySchemes": {
"bearerAuth": {
"type": "http",
"description": "Access token from `/authenticate`",
"scheme": "bearer",
"bearerFormat": "JWT"
}
}
}
}
```
# Update route end location (https://docs.roundtrip.ai/docs/api-reference/routes/patch-routes-routeId-end-location)
PATCH /routes/{routeId}/end/location
Updates the address and/or coordinates for a route's end location by
route ID, or sets one if the route currently has none (in which case
`address` must be included in `updateMask`). This is a partial update:
provide the fields to change in `end` and list their paths in
`updateMask`, which must contain at least one of `address` or
`coordinates`. Changing the end location affects the
route's distances and ETAs and marks the route as not optimized; fetch
the route to see the updated directions, and call ReoptimizeRoute if the
stop order should be adjusted. The route must not be archived. The
response returns the full updated route.
## OpenAPI specification
```json
{
"servers": [
{
"url": "https://easyroutes.roundtrip.ai/api/2024-07"
}
],
"tags": [
"Routes"
],
"summary": "Update route end location",
"description": "Updates the address and/or coordinates for a route's end location by\n route ID, or sets one if the route currently has none (in which case\n `address` must be included in `updateMask`). This is a partial update:\n provide the fields to change in `end` and list their paths in\n `updateMask`, which must contain at least one of `address` or\n `coordinates`. Changing the end location affects the\n route's distances and ETAs and marks the route as not optimized; fetch\n the route to see the updated directions, and call ReoptimizeRoute if the\n stop order should be adjusted. The route must not be archived. The\n response returns the full updated route.",
"operationId": "UpdateRouteEndLocation",
"parameters": [
{
"name": "routeId",
"in": "path",
"description": "The ID of the route to update.",
"required": true,
"schema": {
"type": "string",
"examples": [
"rte-123e4567-e89b-12d3-a456-426614174000"
]
}
},
{
"name": "Idempotency-Key",
"in": "header",
"description": "A unique key for safely retrying this operation. For more information read [our guide](https://docs.roundtrip.ai/docs/concepts/idempotency.md).",
"schema": {
"maxLength": 255,
"minLength": 1,
"type": "string"
},
"examples": {
"default": {
"value": "550e8400-e29b-41d4-a716-446655440000"
}
}
}
],
"requestBody": {
"content": {
"application/json": {
"schema": {
"title": "UpdateRouteEndLocationRequest",
"required": [
"end",
"updateMask"
],
"type": "object",
"properties": {
"end": {
"allOf": [
{
"title": "RouteLocationUpdate",
"type": "object",
"properties": {
"address": {
"allOf": [
{
"title": "Address",
"type": "object",
"properties": {
"address1": {
"type": "string",
"description": "Street address line 1 (e.g. `\"123 Main St\"`).",
"examples": [
"123 Main St"
]
},
"address2": {
"type": "string",
"description": "Street address line 2 (e.g. `\"Apt 101\"`).",
"examples": [
"Apt 3B"
]
},
"city": {
"type": "string",
"description": "City name (e.g. `\"New York\"`).",
"examples": [
"New York"
]
},
"provinceCode": {
"type": "string",
"description": "Province or state as subdivision codes in\n [ISO 3166-2](https://en.wikipedia.org/wiki/ISO_3166-2) format without the\n country prefix (e.g. `\"NY\"` for New York).",
"examples": [
"NY"
]
},
"countryCode": {
"type": "string",
"description": "Country code (e.g. `\"US\"`).",
"examples": [
"US"
]
},
"zip": {
"type": "string",
"description": "Postal or ZIP code (e.g. `\"10001\"`).",
"examples": [
"10001"
]
}
},
"description": "A physical street address."
}
],
"description": "The new address for the route's start/end location. If `coordinates` is\n not included in `updateMask`, this address is geocoded to determine the\n new coordinates, and the request fails if the address cannot be\n geocoded. Exception: if the location's coordinates are currently set\n manually (e.g. via a prior call with `coordinates`), an address-only\n update leaves the existing manual coordinates untouched rather than\n re-geocoding; include `coordinates` in `updateMask` to change them.",
"examples": [
{
"address1": "123 Main St",
"address2": "Apt 3B",
"city": "New York",
"provinceCode": "NY",
"countryCode": "US",
"zip": "10001"
}
]
},
"coordinates": {
"allOf": [
{
"type": "object",
"properties": {
"latitude": {
"type": "number",
"description": "The latitude in degrees. It must be in the range [-90.0, +90.0].",
"format": "double"
},
"longitude": {
"type": "number",
"description": "The longitude in degrees. It must be in the range [-180.0, +180.0].",
"format": "double"
}
},
"description": "An object that represents a latitude/longitude pair. This is expressed as a\n pair of doubles to represent degrees latitude and degrees longitude. Unless\n specified otherwise, this must conform to the\n WGS84\n standard. Values must be within normalized ranges."
}
],
"description": "The new coordinates for the location. If included in `updateMask`, these\n coordinates are used directly instead of geocoding the address, and are\n treated as a manual override of the location.",
"examples": [
{
"latitude": 40.7128,
"longitude": -74.006
}
]
}
}
}
],
"description": "Update for the route's end location. If the route currently has no end\n location, `address` must be included in `updateMask` to set one."
},
"updateMask": {
"type": "string",
"description": "Comma-separated list of [field mask](https://docs.roundtrip.ai/docs/concepts/field-masks.md) paths in `end` to apply. Only listed paths are updated; omitted fields are left unchanged. Must contain at least one of `address` or `coordinates`.",
"format": "field-mask"
}
}
}
}
},
"required": true
},
"responses": {
"200": {
"description": "OK",
"headers": {
"Idempotency-Key": {
"description": "The idempotency key associated with the response.",
"schema": {
"type": "string"
}
},
"Idempotency-Replayed": {
"description": "Whether the response was replayed from a previous request.",
"schema": {
"type": "boolean"
}
}
},
"content": {
"application/json": {
"schema": {
"title": "Route",
"required": [
"id",
"name",
"stops",
"createdAt",
"updatedAt",
"totalDistanceMeters",
"totalItemQuantity",
"totalItemGrams",
"optimized"
],
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Route ID (e.g. `\"rte-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"rte-123e4567-e89b-12d3-a456-426614174000"
]
},
"name": {
"type": "string",
"description": "Route name (e.g. `\"Morning route\"`).",
"examples": [
"Morning route"
]
},
"driver": {
"allOf": [
{
"title": "Driver",
"required": [
"id"
],
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Driver ID (e.g. `\"drv-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"drv-123e4567-e89b-12d3-a456-426614174000"
]
},
"firstName": {
"type": "string",
"description": "Driver first name (e.g. `\"John\"`).",
"examples": [
"John"
]
},
"lastName": {
"type": "string",
"description": "Driver last name (e.g. `\"Doe\"`).",
"examples": [
"Doe"
]
},
"phone": {
"type": "string",
"description": "Driver phone number in [E.164 format](https://en.wikipedia.org/wiki/E.164)\n (e.g. `\"+14265551000\"`).",
"examples": [
"+14265551000"
]
},
"status": {
"enum": [
"UNKNOWN",
"ACTIVE",
"INACTIVE",
"ARCHIVED"
],
"type": "string",
"description": "Shop driver status. (e.g. `ACTIVE`).",
"format": "enum",
"examples": [
"ACTIVE"
]
}
},
"description": "A driver who is assigned to a route."
}
],
"description": "Assigned driver for the route."
},
"start": {
"allOf": [
{
"title": "RouteStart",
"type": "object",
"properties": {
"address": {
"allOf": [
{
"title": "Address",
"type": "object",
"properties": {
"address1": {
"type": "string",
"description": "Street address line 1 (e.g. `\"123 Main St\"`).",
"examples": [
"123 Main St"
]
},
"address2": {
"type": "string",
"description": "Street address line 2 (e.g. `\"Apt 101\"`).",
"examples": [
"Apt 3B"
]
},
"city": {
"type": "string",
"description": "City name (e.g. `\"New York\"`).",
"examples": [
"New York"
]
},
"provinceCode": {
"type": "string",
"description": "Province or state as subdivision codes in\n [ISO 3166-2](https://en.wikipedia.org/wiki/ISO_3166-2) format without the\n country prefix (e.g. `\"NY\"` for New York).",
"examples": [
"NY"
]
},
"countryCode": {
"type": "string",
"description": "Country code (e.g. `\"US\"`).",
"examples": [
"US"
]
},
"zip": {
"type": "string",
"description": "Postal or ZIP code (e.g. `\"10001\"`).",
"examples": [
"10001"
]
}
},
"description": "A physical street address."
}
],
"description": "The start address of the route.",
"examples": [
{
"address1": "123 Main St",
"address2": "Apt 3B",
"city": "New York",
"provinceCode": "NY",
"countryCode": "US",
"zip": "10001"
}
]
},
"tasks": {
"type": "array",
"items": {
"title": "Task",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Task ID (e.g. `\"tsk-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"tsk-123e4567-e89b-12d3-a456-426614174000"
]
},
"title": {
"type": "string",
"description": "Task title (e.g. `\"Delivery checklist\"`).",
"examples": [
"Delivery checklist"
]
},
"type": {
"enum": [
"UNKNOWN",
"CHECKBOXES",
"RADIO_BUTTONS",
"TEXT_INPUT",
"DECIMAL_INPUT",
"SCANNER_INPUT"
],
"type": "string",
"description": "Task type.",
"format": "enum",
"examples": [
"TEXT_INPUT"
]
},
"items": {
"type": "array",
"items": {
"title": "TaskItem",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Item ID (e.g. `\"itm-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"itm-123e4567-e89b-12d3-a456-426614174000"
]
},
"title": {
"type": "string",
"description": "Item title (e.g. `\"Pick up package\"`).",
"examples": [
"Pick up package"
]
},
"complete": {
"type": "boolean",
"description": "Whether the item is completed.",
"examples": [
true
]
},
"updatedAt": {
"type": "string",
"description": "Timestamp when the item was last updated.",
"format": "date-time",
"examples": [
"2026-03-30T13:00:00Z"
]
}
},
"description": "An item within a task. For `CHECKBOXES`, each item on a task may be completed\n independently. For `RADIO_BUTTONS`, at most one item will be completed."
},
"description": "Task items (populated for `CHECKBOXES` and `RADIO_BUTTONS`).",
"examples": [
[]
]
},
"input": {
"allOf": [
{
"title": "TaskInput",
"type": "object",
"properties": {
"value": {
"type": "string",
"description": "Input value.",
"examples": [
"020123456789"
]
},
"updatedAt": {
"type": "string",
"description": "Timestamp when the input was last updated.",
"format": "date-time",
"examples": [
"2026-03-30T13:00:00Z"
]
},
"inputMethod": {
"enum": [
"UNKNOWN",
"SCANNED"
],
"type": "string",
"description": "Whether input was scanned (e.g. a scanned barcode)",
"format": "enum",
"examples": [
"SCANNED"
]
}
},
"description": "Captured driver input for a task. The value may be text for `TEXT_INPUT`\n tasks or a string decimal number for `DECIMAL_INPUT` tasks."
}
],
"description": "Task input (populated for `TEXT_INPUT` and `DECIMAL_INPUT`)."
},
"requiredToMarkStopAsDelivered": {
"type": "boolean",
"description": "Whether the task is required to mark the stop as completed. In the case of\n tasks on `RouteStart`, this represents tasks required for starting the\n route. In the case of tasks on `RouteEnd`, this represents tasks required\n for completing the route.",
"examples": [
true
]
},
"requiredToMarkStopAsAttempted": {
"type": "boolean",
"description": "Whether the task is required to mark the stop as attempted.",
"examples": [
true
]
}
},
"description": "A task to be completed at a stop, or at the start or end of a route. Tasks\n may have one or more items for `CHECKBOXES` or `RADIO_BUTTONS`, or may have\n an input for `TEXT_INPUT` or `DECIMAL_INPUT`."
},
"description": "Tasks to complete before starting the route."
},
"status": {
"enum": [
"UNKNOWN",
"STARTED"
],
"type": "string",
"description": "Status indicating whether the route has been started.",
"format": "enum",
"examples": [
"STARTED"
]
},
"updatedStart": {
"type": "string",
"description": "Updated start time for the route. If the route is started, this will be the\n actual start time.",
"format": "date-time",
"examples": [
"2026-03-30T09:05:00Z"
]
},
"scheduledStart": {
"type": "string",
"description": "Scheduled start time for the route (same as `scheduledFor` on the route).",
"format": "date-time",
"examples": [
"2026-03-30T09:00:00Z"
]
},
"photos": {
"type": "array",
"items": {
"title": "StopAttachment",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Attachment ID (e.g. `\"att-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"att-123e4567-e89b-12d3-a456-426614174000"
]
},
"createdAt": {
"type": "string",
"description": "Timestamp when the attachment was created.",
"format": "date-time",
"examples": [
"2026-03-30T09:05:00Z"
]
},
"url": {
"type": "string",
"description": "URL to fetch the attachment.",
"examples": [
"https://example.com/stop-attachment/attachment-2025-06-03-1"
]
}
},
"description": "An attachment to a stop, such as a proof of delivery photo or signature."
},
"description": "Photos for the route start. Photos may be fetched using the URLs on the\n attachments."
}
},
"description": "The start location of a route and any driver tasks to complete before\n beginning the route."
}
],
"description": "Route start address and tasks."
},
"end": {
"allOf": [
{
"title": "RouteEnd",
"type": "object",
"properties": {
"address": {
"allOf": [
{
"title": "Address",
"type": "object",
"properties": {
"address1": {
"type": "string",
"description": "Street address line 1 (e.g. `\"123 Main St\"`).",
"examples": [
"123 Main St"
]
},
"address2": {
"type": "string",
"description": "Street address line 2 (e.g. `\"Apt 101\"`).",
"examples": [
"Apt 3B"
]
},
"city": {
"type": "string",
"description": "City name (e.g. `\"New York\"`).",
"examples": [
"New York"
]
},
"provinceCode": {
"type": "string",
"description": "Province or state as subdivision codes in\n [ISO 3166-2](https://en.wikipedia.org/wiki/ISO_3166-2) format without the\n country prefix (e.g. `\"NY\"` for New York).",
"examples": [
"NY"
]
},
"countryCode": {
"type": "string",
"description": "Country code (e.g. `\"US\"`).",
"examples": [
"US"
]
},
"zip": {
"type": "string",
"description": "Postal or ZIP code (e.g. `\"10001\"`).",
"examples": [
"10001"
]
}
},
"description": "A physical street address."
}
],
"description": "The end address of the route.",
"examples": [
{
"address1": "123 Main St",
"address2": "Apt 3B",
"city": "New York",
"provinceCode": "NY",
"countryCode": "US",
"zip": "10001"
}
]
},
"tasks": {
"type": "array",
"items": {
"title": "Task",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Task ID (e.g. `\"tsk-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"tsk-123e4567-e89b-12d3-a456-426614174000"
]
},
"title": {
"type": "string",
"description": "Task title (e.g. `\"Delivery checklist\"`).",
"examples": [
"Delivery checklist"
]
},
"type": {
"enum": [
"UNKNOWN",
"CHECKBOXES",
"RADIO_BUTTONS",
"TEXT_INPUT",
"DECIMAL_INPUT",
"SCANNER_INPUT"
],
"type": "string",
"description": "Task type.",
"format": "enum",
"examples": [
"TEXT_INPUT"
]
},
"items": {
"type": "array",
"items": {
"title": "TaskItem",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Item ID (e.g. `\"itm-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"itm-123e4567-e89b-12d3-a456-426614174000"
]
},
"title": {
"type": "string",
"description": "Item title (e.g. `\"Pick up package\"`).",
"examples": [
"Pick up package"
]
},
"complete": {
"type": "boolean",
"description": "Whether the item is completed.",
"examples": [
true
]
},
"updatedAt": {
"type": "string",
"description": "Timestamp when the item was last updated.",
"format": "date-time",
"examples": [
"2026-03-30T13:00:00Z"
]
}
},
"description": "An item within a task. For `CHECKBOXES`, each item on a task may be completed\n independently. For `RADIO_BUTTONS`, at most one item will be completed."
},
"description": "Task items (populated for `CHECKBOXES` and `RADIO_BUTTONS`).",
"examples": [
[]
]
},
"input": {
"allOf": [
{
"title": "TaskInput",
"type": "object",
"properties": {
"value": {
"type": "string",
"description": "Input value.",
"examples": [
"020123456789"
]
},
"updatedAt": {
"type": "string",
"description": "Timestamp when the input was last updated.",
"format": "date-time",
"examples": [
"2026-03-30T13:00:00Z"
]
},
"inputMethod": {
"enum": [
"UNKNOWN",
"SCANNED"
],
"type": "string",
"description": "Whether input was scanned (e.g. a scanned barcode)",
"format": "enum",
"examples": [
"SCANNED"
]
}
},
"description": "Captured driver input for a task. The value may be text for `TEXT_INPUT`\n tasks or a string decimal number for `DECIMAL_INPUT` tasks."
}
],
"description": "Task input (populated for `TEXT_INPUT` and `DECIMAL_INPUT`)."
},
"requiredToMarkStopAsDelivered": {
"type": "boolean",
"description": "Whether the task is required to mark the stop as completed. In the case of\n tasks on `RouteStart`, this represents tasks required for starting the\n route. In the case of tasks on `RouteEnd`, this represents tasks required\n for completing the route.",
"examples": [
true
]
},
"requiredToMarkStopAsAttempted": {
"type": "boolean",
"description": "Whether the task is required to mark the stop as attempted.",
"examples": [
true
]
}
},
"description": "A task to be completed at a stop, or at the start or end of a route. Tasks\n may have one or more items for `CHECKBOXES` or `RADIO_BUTTONS`, or may have\n an input for `TEXT_INPUT` or `DECIMAL_INPUT`."
},
"description": "Tasks to complete before finishing the route."
},
"plannedArrival": {
"type": "string",
"description": "Planned arrival time at the end of the route.",
"format": "date-time",
"examples": [
"2026-03-30T17:00:00Z"
]
},
"distanceMeters": {
"type": "number",
"description": "The distance in meters from the previous stop.",
"format": "double",
"examples": [
1234.56
]
},
"updatedArrival": {
"type": "string",
"description": "Estimated arrival time at the end of the route. If the route is completed,\n this will be the actual arrival time.",
"format": "date-time",
"examples": [
"2026-03-30T17:05:00Z"
]
},
"status": {
"enum": [
"UNKNOWN",
"COMPLETED"
],
"type": "string",
"description": "Status indicating whether the route has been completed.",
"format": "enum",
"examples": [
"COMPLETED"
]
},
"photos": {
"type": "array",
"items": {
"title": "StopAttachment",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Attachment ID (e.g. `\"att-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"att-123e4567-e89b-12d3-a456-426614174000"
]
},
"createdAt": {
"type": "string",
"description": "Timestamp when the attachment was created.",
"format": "date-time",
"examples": [
"2026-03-30T09:05:00Z"
]
},
"url": {
"type": "string",
"description": "URL to fetch the attachment.",
"examples": [
"https://example.com/stop-attachment/attachment-2025-06-03-1"
]
}
},
"description": "An attachment to a stop, such as a proof of delivery photo or signature."
},
"description": "Photos for the route end. Photos may be fetched using the URLs on the\n attachments."
}
},
"description": "The end location of a route and any driver tasks to complete after completing\n the route."
}
],
"description": "Route end address and tasks."
},
"stops": {
"type": "array",
"items": {
"title": "RouteStop",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Stop ID (e.g. `\"rst-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"rst-123e4567-e89b-12d3-a456-426614174000"
]
},
"type": {
"enum": [
"UNKNOWN",
"DELIVERY",
"BREAK",
"PICKUP",
"TASK"
],
"type": "string",
"description": "The type of stop (DELIVERY, BREAK, PICKUP, or TASK).",
"format": "enum",
"examples": [
"DELIVERY"
]
},
"deliveryStatus": {
"enum": [
"UNKNOWN",
"DELIVERED",
"OUT_FOR_DELIVERY",
"ATTEMPTED_DELIVERY",
"READY_FOR_DELIVERY"
],
"type": "string",
"description": "The status for DELIVERY, PICKUP, or TASK stops.",
"format": "enum",
"examples": [
"ATTEMPTED_DELIVERY"
]
},
"breakStatus": {
"enum": [
"UNKNOWN",
"COMPLETED"
],
"type": "string",
"description": "The status for BREAK stops.",
"format": "enum",
"examples": [
"COMPLETED"
]
},
"updatedAt": {
"type": "string",
"description": "Timestamp when the stop status was last updated. Note that this timestamp\n corresponds only to major status updates (i.e. stop marked as DELIVERED).\n Minor updates like task completion or adding proof of delivery will not\n advance this timestamp. For those events, use the timestamps on the task or\n proof of delivery attachment.",
"format": "date-time",
"examples": [
"2026-03-30T13:15:00Z"
]
},
"duration": {
"pattern": "^-?(?:0|[1-9][0-9]{0,11})(?:\\.[0-9]{1,9})?s$",
"type": "string",
"description": "Planned duration of the stop in seconds.",
"examples": [
"300s"
]
},
"plannedArrival": {
"type": "string",
"description": "Planned arrival time at the stop.",
"format": "date-time",
"examples": [
"2026-03-30T13:00:00Z"
]
},
"note": {
"type": "string",
"description": "Top-level note for the stop, as entered manually by route planners,\n inherited from a saved or imported stop, or set by order import automation\n rules.",
"examples": [
"Leave at door."
]
},
"address": {
"allOf": [
{
"title": "Address",
"type": "object",
"properties": {
"address1": {
"type": "string",
"description": "Street address line 1 (e.g. `\"123 Main St\"`).",
"examples": [
"123 Main St"
]
},
"address2": {
"type": "string",
"description": "Street address line 2 (e.g. `\"Apt 101\"`).",
"examples": [
"Apt 3B"
]
},
"city": {
"type": "string",
"description": "City name (e.g. `\"New York\"`).",
"examples": [
"New York"
]
},
"provinceCode": {
"type": "string",
"description": "Province or state as subdivision codes in\n [ISO 3166-2](https://en.wikipedia.org/wiki/ISO_3166-2) format without the\n country prefix (e.g. `\"NY\"` for New York).",
"examples": [
"NY"
]
},
"countryCode": {
"type": "string",
"description": "Country code (e.g. `\"US\"`).",
"examples": [
"US"
]
},
"zip": {
"type": "string",
"description": "Postal or ZIP code (e.g. `\"10001\"`).",
"examples": [
"10001"
]
}
},
"description": "A physical street address."
}
],
"description": "Delivery address for the stop.",
"examples": [
{
"address1": "123 Main St",
"address2": "Apt 3B",
"city": "New York",
"provinceCode": "NY",
"countryCode": "US",
"zip": "10001"
}
]
},
"contact": {
"allOf": [
{
"title": "Contact",
"type": "object",
"properties": {
"firstName": {
"type": "string",
"description": "First name (e.g. `\"John\"`).",
"examples": [
"John"
]
},
"lastName": {
"type": "string",
"description": "Last name (e.g. `\"Doe\"`).",
"examples": [
"Doe"
]
},
"company": {
"type": "string",
"description": "Company name (e.g. `\"Roundtrip Systems Inc\"`).",
"examples": [
"Roundtrip Systems Inc"
]
},
"phone": {
"type": "string",
"description": "Phone number in [E.164 format](https://en.wikipedia.org/wiki/E.164) (e.g.\n `\"+14265551000\"`).",
"examples": [
"+14265551000"
]
},
"email": {
"type": "string",
"description": "Email address (e.g. `\"john.doe@roundtrip.ai\"`)",
"examples": [
"john.doe@roundtrip.ai"
]
}
},
"description": "Contact information for a person or company."
}
],
"description": "Contact information for the stop delivery recipient.",
"examples": [
{
"firstName": "John",
"lastName": "Doe",
"company": "Roundtrip Systems Inc",
"phone": "+14265551000",
"email": "john.doe@roundtrip.ai"
}
]
},
"plannedCoordinates": {
"allOf": [
{
"type": "object",
"properties": {
"latitude": {
"type": "number",
"description": "The latitude in degrees. It must be in the range [-90.0, +90.0].",
"format": "double"
},
"longitude": {
"type": "number",
"description": "The longitude in degrees. It must be in the range [-180.0, +180.0].",
"format": "double"
}
},
"description": "An object that represents a latitude/longitude pair. This is expressed as a\n pair of doubles to represent degrees latitude and degrees longitude. Unless\n specified otherwise, this must conform to the\n WGS84\n standard. Values must be within normalized ranges."
}
],
"description": "Planned coordinates for the stop.",
"examples": [
{
"latitude": 40.7128,
"longitude": -74.006
}
]
},
"items": {
"type": "array",
"items": {
"title": "StopItem",
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "Item name (e.g. `\"Bananas\"`).",
"examples": [
"Bananas"
]
},
"quantity": {
"type": "integer",
"description": "Quantity of the item (e.g. `5`).",
"format": "int32",
"examples": [
5
]
},
"grams": {
"type": "integer",
"description": "Weight of the item in grams (e.g. `500`).",
"format": "int32",
"examples": [
500
]
},
"sku": {
"type": "string",
"description": "Stock keeping unit (e.g. `\"BANANA-001\"`).",
"examples": [
"BANANA-001"
]
}
},
"description": "An item to be delivered at a stop."
},
"description": "Items to deliver at the stop."
},
"source": {
"enum": [
"UNKNOWN",
"SHOPIFY_ORDER",
"SAVED_STOP",
"IMPORTED_STOP"
],
"type": "string",
"description": "The source of the stop, which may be populated for `DELIVERY` stops. The\n source can be a `SHOPIFY_ORDER`, an EasyRoutes `SAVED_STOP`, or an\n `IMPORTED_STOP` from an external source (such as CSV file).",
"format": "enum",
"examples": [
"IMPORTED_STOP"
]
},
"shopifyOrderId": {
"type": "string",
"description": "The Shopify order ID, populated when the stop source is a `SHOPIFY_ORDER`.",
"examples": [
"6229749334323"
]
},
"savedStopId": {
"type": "string",
"description": "The saved stop ID, populated when the stop source is a `SAVED_STOP`.",
"examples": [
"sst-123e4567-e89b-12d3-a456-426614174000"
]
},
"deliveredCoordinates": {
"allOf": [
{
"type": "object",
"properties": {
"latitude": {
"type": "number",
"description": "The latitude in degrees. It must be in the range [-90.0, +90.0].",
"format": "double"
},
"longitude": {
"type": "number",
"description": "The longitude in degrees. It must be in the range [-180.0, +180.0].",
"format": "double"
}
},
"description": "An object that represents a latitude/longitude pair. This is expressed as a\n pair of doubles to represent degrees latitude and degrees longitude. Unless\n specified otherwise, this must conform to the\n WGS84\n standard. Values must be within normalized ranges."
}
],
"description": "Delivered coordinates for the stop."
},
"proofOfDeliveryNote": {
"type": "string",
"description": "Proof of delivery note for the stop.",
"examples": [
"Left at door."
]
},
"proofOfDeliveryPhotos": {
"type": "array",
"items": {
"title": "StopAttachment",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Attachment ID (e.g. `\"att-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"att-123e4567-e89b-12d3-a456-426614174000"
]
},
"createdAt": {
"type": "string",
"description": "Timestamp when the attachment was created.",
"format": "date-time",
"examples": [
"2026-03-30T09:05:00Z"
]
},
"url": {
"type": "string",
"description": "URL to fetch the attachment.",
"examples": [
"https://example.com/stop-attachment/attachment-2025-06-03-1"
]
}
},
"description": "An attachment to a stop, such as a proof of delivery photo or signature."
},
"description": "Proof of delivery photos for the stop. Photos may be fetched using the URLs\n on the attachments."
},
"proofOfDeliverySignatures": {
"type": "array",
"items": {
"title": "StopAttachment",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Attachment ID (e.g. `\"att-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"att-123e4567-e89b-12d3-a456-426614174000"
]
},
"createdAt": {
"type": "string",
"description": "Timestamp when the attachment was created.",
"format": "date-time",
"examples": [
"2026-03-30T09:05:00Z"
]
},
"url": {
"type": "string",
"description": "URL to fetch the attachment.",
"examples": [
"https://example.com/stop-attachment/attachment-2025-06-03-1"
]
}
},
"description": "An attachment to a stop, such as a proof of delivery photo or signature."
},
"description": "Proof of delivery signatures for the stop. Signatures may be fetched using\n the URLs on the attachments."
},
"tasks": {
"type": "array",
"items": {
"title": "Task",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Task ID (e.g. `\"tsk-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"tsk-123e4567-e89b-12d3-a456-426614174000"
]
},
"title": {
"type": "string",
"description": "Task title (e.g. `\"Delivery checklist\"`).",
"examples": [
"Delivery checklist"
]
},
"type": {
"enum": [
"UNKNOWN",
"CHECKBOXES",
"RADIO_BUTTONS",
"TEXT_INPUT",
"DECIMAL_INPUT",
"SCANNER_INPUT"
],
"type": "string",
"description": "Task type.",
"format": "enum",
"examples": [
"TEXT_INPUT"
]
},
"items": {
"type": "array",
"items": {
"title": "TaskItem",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Item ID (e.g. `\"itm-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"itm-123e4567-e89b-12d3-a456-426614174000"
]
},
"title": {
"type": "string",
"description": "Item title (e.g. `\"Pick up package\"`).",
"examples": [
"Pick up package"
]
},
"complete": {
"type": "boolean",
"description": "Whether the item is completed.",
"examples": [
true
]
},
"updatedAt": {
"type": "string",
"description": "Timestamp when the item was last updated.",
"format": "date-time",
"examples": [
"2026-03-30T13:00:00Z"
]
}
},
"description": "An item within a task. For `CHECKBOXES`, each item on a task may be completed\n independently. For `RADIO_BUTTONS`, at most one item will be completed."
},
"description": "Task items (populated for `CHECKBOXES` and `RADIO_BUTTONS`).",
"examples": [
[]
]
},
"input": {
"allOf": [
{
"title": "TaskInput",
"type": "object",
"properties": {
"value": {
"type": "string",
"description": "Input value.",
"examples": [
"020123456789"
]
},
"updatedAt": {
"type": "string",
"description": "Timestamp when the input was last updated.",
"format": "date-time",
"examples": [
"2026-03-30T13:00:00Z"
]
},
"inputMethod": {
"enum": [
"UNKNOWN",
"SCANNED"
],
"type": "string",
"description": "Whether input was scanned (e.g. a scanned barcode)",
"format": "enum",
"examples": [
"SCANNED"
]
}
},
"description": "Captured driver input for a task. The value may be text for `TEXT_INPUT`\n tasks or a string decimal number for `DECIMAL_INPUT` tasks."
}
],
"description": "Task input (populated for `TEXT_INPUT` and `DECIMAL_INPUT`)."
},
"requiredToMarkStopAsDelivered": {
"type": "boolean",
"description": "Whether the task is required to mark the stop as completed. In the case of\n tasks on `RouteStart`, this represents tasks required for starting the\n route. In the case of tasks on `RouteEnd`, this represents tasks required\n for completing the route.",
"examples": [
true
]
},
"requiredToMarkStopAsAttempted": {
"type": "boolean",
"description": "Whether the task is required to mark the stop as attempted.",
"examples": [
true
]
}
},
"description": "A task to be completed at a stop, or at the start or end of a route. Tasks\n may have one or more items for `CHECKBOXES` or `RADIO_BUTTONS`, or may have\n an input for `TEXT_INPUT` or `DECIMAL_INPUT`."
},
"description": "Driver tasks for the stop, including completed items and any input from the\n driver."
},
"priority": {
"maximum": 10,
"type": "integer",
"description": "Priority of the stop for route planning. The valid range for stop priority\n is between `1` (low) and `10` (high), with default priority corresponding\n to a value of `5`. A priority value of `0` is considered unset and is\n treated the same as \"default\" priority. Stops with higher priority will be\n preferred when generating routes with constraints.",
"format": "int32",
"examples": [
8
]
},
"importedStopId": {
"type": "string",
"description": "The imported stop ID, populated when the stop source is `IMPORTED_STOP`.",
"examples": [
"ist-123e4567-e89b-12d3-a456-426614174000"
]
},
"orderName": {
"type": "string",
"description": "The name of the order associated with the stop. For Shopify orders, the\n name is generated by combining the `orderNumber` property with the order\n prefix and suffix that are set in the merchant's general settings. For\n EasyRoutes imported orders, this field is populated with the order name\n provided on import.",
"examples": [
"#1234"
]
},
"distanceMeters": {
"type": "number",
"description": "The distance in meters from the previous stop.",
"format": "double",
"examples": [
123.45
]
},
"updatedArrival": {
"type": "string",
"description": "Estimated arrival time at the stop. If the stop is completed, this will be\n the actual arrival time.",
"format": "date-time",
"examples": [
"2026-03-30T13:05:00Z"
]
},
"timeWindows": {
"type": "array",
"items": {
"title": "TimeWindow",
"type": "object",
"properties": {
"start": {
"allOf": [
{
"title": "TimeOfDay",
"type": "object",
"properties": {
"hours": {
"maximum": 23,
"type": "integer",
"description": "Hours of day in 24 hour format. Must be from 0 to 23.",
"format": "int32",
"examples": [
13
]
},
"minutes": {
"maximum": 59,
"type": "integer",
"description": "Minutes of hour of day. Must be from 0 to 59.",
"format": "int32",
"examples": [
37
]
},
"seconds": {
"maximum": 59,
"type": "integer",
"description": "Seconds of minutes of the time. Must be from 0 to 59.",
"format": "int32",
"examples": [
16
]
}
},
"description": "A time of day, independent of a particular date or timezone."
}
],
"description": "The start time of the time window (optional)."
},
"end": {
"allOf": [
{
"title": "TimeOfDay",
"type": "object",
"properties": {
"hours": {
"maximum": 23,
"type": "integer",
"description": "Hours of day in 24 hour format. Must be from 0 to 23.",
"format": "int32",
"examples": [
13
]
},
"minutes": {
"maximum": 59,
"type": "integer",
"description": "Minutes of hour of day. Must be from 0 to 59.",
"format": "int32",
"examples": [
37
]
},
"seconds": {
"maximum": 59,
"type": "integer",
"description": "Seconds of minutes of the time. Must be from 0 to 59.",
"format": "int32",
"examples": [
16
]
}
},
"description": "A time of day, independent of a particular date or timezone."
}
],
"description": "The end time of the time window (optional)."
}
},
"description": "A time window for a stop. The time window may be open-ended, but one or both\n of the start and end times should be provided. The end time must be >= the\n start time."
},
"description": "The time window for the stop. Note that we currently support at most one\n time window but may support multiple time windows in the future.",
"examples": [
[
{
"start": {
"hours": 9
},
"end": {
"hours": 17
}
}
]
]
},
"deliveryDate": {
"allOf": [
{
"title": "Date",
"required": [
"year",
"month",
"day"
],
"type": "object",
"properties": {
"year": {
"maximum": 9999,
"minimum": 1,
"type": "integer",
"description": "Year of the date. Must be from 1 to 9999.",
"format": "int32",
"examples": [
2019
]
},
"month": {
"maximum": 12,
"minimum": 1,
"type": "integer",
"description": "Month of a year. Must be from 1 to 12.",
"format": "int32",
"examples": [
11
]
},
"day": {
"maximum": 31,
"minimum": 1,
"type": "integer",
"description": "Day of a month. Must be from 1 to 31.",
"format": "int32",
"examples": [
15
]
}
},
"description": "A date in year-month-day format."
}
],
"description": "The planned delivery date for the stop.",
"examples": [
{
"year": 2025,
"month": 12,
"day": 16
}
]
},
"attributes": {
"type": "array",
"items": {
"title": "Attribute",
"type": "object",
"properties": {
"key": {
"type": "string",
"description": "Attribute key. Must be non-empty.",
"examples": [
"delivery_date"
]
},
"value": {
"type": "string",
"description": "Attribute value.",
"examples": [
"2025-12-16"
]
}
},
"description": "A key-value pair for storing additional information on a stop, such as order\n details, delivery instructions, or custom fields."
},
"description": "Additional attributes for the stop. Attributes are key-value pairs for\n storing additional structured data on stops. These may be populated from\n the Shopify order or set on import.",
"examples": [
[
{
"key": "color",
"value": "blue"
}
]
]
},
"clientStopId": {
"type": "string",
"description": "The client-provided ID associated with the stop, if provided on import.",
"examples": [
"test-order-1234"
]
},
"tags": {
"type": "array",
"items": {
"type": "string"
},
"description": "The tags for the stop. Tags are used to categorize stops and can be used\n for filtering and grouping stops in the EasyRoutes web app. These may be\n populated from the Shopify order or set on import.",
"examples": [
[
"foo",
"bar"
]
]
},
"attemptedReason": {
"enum": [
"UNKNOWN",
"NOT_AVAILABLE",
"ACCESS_DENIED",
"INCORRECT_ADDRESS",
"SAFE_PLACE_UNAVAILABLE",
"REFUSED",
"EXTERNAL",
"INCORRECT_ITEMS",
"OTHER",
"CANCELED"
],
"type": "string",
"description": "The reason for marking the stop as attempted. This is only populated when\n `deliveryStatus = ATTEMPTED_DELIVERY`.",
"format": "enum",
"examples": [
"NOT_AVAILABLE"
]
},
"attemptedNote": {
"type": "string",
"description": "Optional note related to the reason for marking the stop as attempted. This\n is optionally populated when `deliveryStatus = ATTEMPTED_DELIVERY`.",
"examples": [
"Customer did not answer the door."
]
},
"customerRating": {
"allOf": [
{
"title": "CustomerRating",
"type": "object",
"properties": {
"rating": {
"maximum": 5,
"minimum": 1,
"type": "integer",
"description": "Rating from 1-5",
"format": "int32",
"examples": [
5
]
},
"comment": {
"type": "string",
"description": "Customer comment related to rating",
"examples": [
"Excellent delivery"
]
},
"createdAt": {
"type": "string",
"description": "Timestamp when rating was left by customer.",
"format": "date-time",
"examples": [
"2026-03-30T18:00:00Z"
]
}
},
"description": "Customer rating and feedback left on a stop."
}
],
"description": "Rating left by customer. This can only be populated once `deliveryStatus =\n DELIVERED`."
},
"customSignatureDisclosure": {
"type": "string",
"description": "Optional custom signature disclosure that is shown to customers in the\n driver app.",
"examples": [
"I acknowledge that I have received this delivery."
]
},
"shopifyOrder": {
"allOf": [
{
"title": "ShopifyOrder",
"type": "object",
"properties": {
"orderNote": {
"type": "string",
"description": "The Shopify order note.",
"examples": [
"Customer has paid."
]
},
"customerNote": {
"type": "string",
"description": "The Shopify customer note for the order.",
"examples": [
"Leave at door."
]
}
},
"description": "Shopify-specific information for a RouteStop."
}
],
"description": "Information from the associated Shopify order, if applicable. Populated if\n stop source is `SHOPIFY_ORDER`"
},
"proofOfDeliveryBarcodes": {
"type": "array",
"items": {
"title": "ScannedBarcode",
"type": "object",
"properties": {
"value": {
"type": "string",
"description": "Barcode value (e.g. `\"123456789012\"`).",
"examples": [
"123456789012"
]
},
"createdAt": {
"type": "string",
"description": "Timestamp when the barcode was scanned.",
"format": "date-time",
"examples": [
"2026-03-30T13:10:00Z"
]
}
},
"description": "A proof of delivery barcode scanned at a stop."
},
"description": "Proof of delivery barcodes scanned at the stop."
},
"proofOfDeliveryBarcodeIssues": {
"type": "array",
"items": {
"title": "ScannedBarcodeIssue",
"type": "object",
"properties": {
"reason": {
"enum": [
"UNKNOWN",
"ITEM_MISSING",
"NOT_SCANNABLE",
"INCORRECT"
],
"type": "string",
"description": "The reported reason for the barcode issue.",
"format": "enum",
"examples": [
"ITEM_MISSING"
]
},
"note": {
"type": "string",
"description": "Optional note related to the reason for reporting a barcode issue.",
"examples": [
"Item was not packed."
]
},
"createdAt": {
"type": "string",
"description": "Timestamp when the issue was reported.",
"format": "date-time",
"examples": [
"2026-03-30T13:10:00Z"
]
}
},
"description": "A reported issue related to scanning barcodes at a stop."
},
"description": "Proof of delivery barcode issues reported at the stop."
},
"orderReferenceUrl": {
"type": "string",
"description": "A reference URL for the order associated with the stop (e.g. a link to the\n order in your order management system). Must be a valid HTTPS URL. This\n field can only be populated for imported stops.",
"examples": [
"https://orders.example.com/orders/148977776"
]
}
},
"description": "A stop on a route. A stop may correspond to a delivery or a driver break as\n determined by the type. A delivery stop will have location and contact\n information, items to deliver, optional order details, status, arrival time\n and stop duration, driver tasks and any proof of delivery information. A\n break stop will have start time and duration, and status."
},
"description": "Route stops. See RouteStop for stop fields."
},
"createdAt": {
"type": "string",
"description": "Timestamp when the route was created.",
"format": "date-time",
"examples": [
"2026-03-29T08:00:00Z"
]
},
"updatedAt": {
"type": "string",
"description": "Timestamp when the route was last updated (by the planner).",
"format": "date-time",
"examples": [
"2026-03-30T13:15:00Z"
]
},
"archivedAt": {
"type": "string",
"description": "Timestamp when the route was archived.",
"format": "date-time",
"examples": [
"2026-04-05T00:00:00Z"
]
},
"scheduledFor": {
"type": "string",
"description": "Timestamp when the route is scheduled for.",
"format": "date-time",
"examples": [
"2026-03-30T09:00:00Z"
]
},
"totalDistanceMeters": {
"type": "number",
"description": "The distance in meters for the entire route.",
"format": "double",
"examples": [
2387.2
]
},
"totalItemQuantity": {
"type": "integer",
"description": "The total quantity of items to deliver on the route.",
"format": "int32",
"examples": [
50
]
},
"totalItemGrams": {
"type": "string",
"description": "The total weight in grams for the items on the route.",
"examples": [
"6000"
]
},
"optimized": {
"type": "boolean",
"description": "Whether the route has been optimized. Adding or removing stops, reordering\n stops, or changing route options generally set this field to false until\n the route is reoptimized.",
"examples": [
true
]
},
"dispatchedUntil": {
"type": "string",
"description": "Timestamp until which the route is dispatched and accessible in the driver\n app.",
"format": "date-time",
"examples": [
"2026-03-30T20:00:00Z"
]
},
"note": {
"type": "string",
"description": "Top-level note for the route, as entered manually by route planners.",
"examples": [
"Fragile items."
]
},
"tags": {
"type": "array",
"items": {
"type": "string"
},
"description": "The tags for the route. Tags are used to categorize routes and can be\n used for filtering and grouping routes in the EasyRoutes web app.",
"examples": [
[
"foo",
"bar"
]
]
},
"defaultStopDuration": {
"pattern": "^-?(?:0|[1-9][0-9]{0,11})(?:\\.[0-9]{1,9})?s$",
"type": "string",
"description": "The default duration for stops on the route. Used to estimate arrival\n times for stops that do not have their own duration specified.\n Specified as a duration string in the format \"300s\" for 5 minutes, \"60s\"\n for 1 minute, etc.",
"examples": [
"300s"
]
},
"maxDuration": {
"pattern": "^-?(?:0|[1-9][0-9]{0,11})(?:\\.[0-9]{1,9})?s$",
"type": "string",
"description": "The maximum duration of the route. Specified as a duration string in the\n format \"3600s\" for 1 hour, \"7200s\" for 2 hours, etc.",
"examples": [
"28800s"
]
},
"maxStops": {
"type": "integer",
"description": "The maximum number of stops on the route.",
"format": "int32",
"examples": [
50
]
},
"maxItemCount": {
"type": "integer",
"description": "The maximum total item count across all stops on the route.",
"format": "int32",
"examples": [
200
]
},
"maxKilograms": {
"type": "number",
"description": "The maximum total weight in kilograms across all stops on the route.",
"format": "double",
"examples": [
500
]
},
"avoidTolls": {
"type": "boolean",
"description": "Whether to avoid toll roads during optimization.",
"examples": [
true
]
},
"avoidUTurns": {
"type": "boolean",
"description": "Whether to avoid U-turns during optimization.",
"examples": [
true
]
},
"speedFactor": {
"type": "number",
"description": "A speed factor for the route used during optimization to adjust estimated\n travel times. A value of 1.0 represents normal speed. Values less than 1.0\n indicate slower travel (e.g. 0.5 = half speed), and values greater than\n 1.0 indicate faster travel (e.g. 1.5 = 50% faster). Must be between 0.1\n and 1.9. A value of 0 (or unset) uses the default speed.",
"format": "double",
"examples": [
0.8
]
},
"vehicle": {
"allOf": [
{
"title": "Vehicle",
"required": [
"id"
],
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Vehicle ID.",
"examples": [
"veh-123e4567-e89b-12d3-a456-426614174000"
]
},
"name": {
"type": "string",
"description": "Vehicle name.",
"examples": [
"Delivery Van 1"
]
},
"make": {
"type": "string",
"description": "Vehicle make.",
"examples": [
"Ford"
]
},
"model": {
"type": "string",
"description": "Vehicle model.",
"examples": [
"Transit"
]
},
"year": {
"type": "integer",
"description": "Vehicle model year.",
"format": "int32",
"examples": [
2023
]
},
"type": {
"enum": [
"UNKNOWN",
"CAR",
"CARGO_VAN",
"PICKUP_TRUCK",
"BOX_TRUCK",
"MOTORCYCLE",
"BICYCLE",
"DRONE",
"OTHER"
],
"type": "string",
"description": "Vehicle type.",
"format": "enum",
"examples": [
"CARGO_VAN"
]
},
"vin": {
"type": "string",
"description": "Vehicle Identification Number.",
"examples": [
"1FTBW2CM5NKA12345"
]
},
"license": {
"type": "string",
"description": "Vehicle license plate.",
"examples": [
"ABC-1234"
]
},
"isArchived": {
"type": "boolean",
"description": "Whether the vehicle is archived.",
"examples": [
false
]
},
"createdTimestamp": {
"type": "string",
"description": "Timestamp when the vehicle was created.",
"format": "date-time",
"examples": [
"2026-07-30T12:00:00Z"
]
}
},
"description": "A vehicle that can be assigned to a route."
}
],
"description": "Assigned vehicle for the route."
}
},
"description": "A route of stops, optionally with an assigned driver."
}
}
}
},
"default": {
"description": "Default error response",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"code": {
"type": "integer",
"description": "The status code, which should be an enum value of [google.rpc.Code][google.rpc.Code].",
"format": "int32"
},
"message": {
"type": "string",
"description": "A developer-facing error message, which should be in English. Any user-facing error message should be localized and sent in the [google.rpc.Status.details][google.rpc.Status.details] field, or localized by the client."
},
"details": {
"type": "array",
"items": {
"type": "object",
"properties": {
"@type": {
"type": "string",
"description": "The type of the serialized message."
}
},
"additionalProperties": true,
"description": "Contains an arbitrary serialized message along with a @type that describes the type of the serialized message."
},
"description": "A list of messages that carry the error details. There is a common set of message types for APIs to use."
}
},
"description": "The `Status` type defines a logical error model that is suitable for different programming environments, including REST APIs and RPC APIs. It is used by [gRPC](https://github.com/grpc). Each `Status` message contains three pieces of data: error code, error message, and error details. You can find out more about this error model and how to work with it in the [API Design Guide](https://cloud.google.com/apis/design/errors)."
}
}
}
}
},
"security": [
{
"bearerAuth": []
}
],
"components": {
"securitySchemes": {
"bearerAuth": {
"type": "http",
"description": "Access token from `/authenticate`",
"scheme": "bearer",
"bearerFormat": "JWT"
}
}
}
}
```
# Update route start location (https://docs.roundtrip.ai/docs/api-reference/routes/patch-routes-routeId-start-location)
PATCH /routes/{routeId}/start/location
Updates the address and/or coordinates for a route's start location by
route ID. This is a partial update: provide the fields to change in
`start` and list their paths in `updateMask`, which must contain at
least one of `address` or `coordinates`. Changing the start
location affects the route's distances and ETAs and marks the route as
not optimized; fetch the route to see the updated directions, and call
ReoptimizeRoute if the stop order should be adjusted. The route must not
be archived. The response returns the full updated route.
## OpenAPI specification
```json
{
"servers": [
{
"url": "https://easyroutes.roundtrip.ai/api/2024-07"
}
],
"tags": [
"Routes"
],
"summary": "Update route start location",
"description": "Updates the address and/or coordinates for a route's start location by\n route ID. This is a partial update: provide the fields to change in\n `start` and list their paths in `updateMask`, which must contain at\n least one of `address` or `coordinates`. Changing the start\n location affects the route's distances and ETAs and marks the route as\n not optimized; fetch the route to see the updated directions, and call\n ReoptimizeRoute if the stop order should be adjusted. The route must not\n be archived. The response returns the full updated route.",
"operationId": "UpdateRouteStartLocation",
"parameters": [
{
"name": "routeId",
"in": "path",
"description": "The ID of the route to update.",
"required": true,
"schema": {
"type": "string",
"examples": [
"rte-123e4567-e89b-12d3-a456-426614174000"
]
}
},
{
"name": "Idempotency-Key",
"in": "header",
"description": "A unique key for safely retrying this operation. For more information read [our guide](https://docs.roundtrip.ai/docs/concepts/idempotency.md).",
"schema": {
"maxLength": 255,
"minLength": 1,
"type": "string"
},
"examples": {
"default": {
"value": "550e8400-e29b-41d4-a716-446655440000"
}
}
}
],
"requestBody": {
"content": {
"application/json": {
"schema": {
"title": "UpdateRouteStartLocationRequest",
"required": [
"start",
"updateMask"
],
"type": "object",
"properties": {
"start": {
"allOf": [
{
"title": "RouteLocationUpdate",
"type": "object",
"properties": {
"address": {
"allOf": [
{
"title": "Address",
"type": "object",
"properties": {
"address1": {
"type": "string",
"description": "Street address line 1 (e.g. `\"123 Main St\"`).",
"examples": [
"123 Main St"
]
},
"address2": {
"type": "string",
"description": "Street address line 2 (e.g. `\"Apt 101\"`).",
"examples": [
"Apt 3B"
]
},
"city": {
"type": "string",
"description": "City name (e.g. `\"New York\"`).",
"examples": [
"New York"
]
},
"provinceCode": {
"type": "string",
"description": "Province or state as subdivision codes in\n [ISO 3166-2](https://en.wikipedia.org/wiki/ISO_3166-2) format without the\n country prefix (e.g. `\"NY\"` for New York).",
"examples": [
"NY"
]
},
"countryCode": {
"type": "string",
"description": "Country code (e.g. `\"US\"`).",
"examples": [
"US"
]
},
"zip": {
"type": "string",
"description": "Postal or ZIP code (e.g. `\"10001\"`).",
"examples": [
"10001"
]
}
},
"description": "A physical street address."
}
],
"description": "The new address for the route's start/end location. If `coordinates` is\n not included in `updateMask`, this address is geocoded to determine the\n new coordinates, and the request fails if the address cannot be\n geocoded. Exception: if the location's coordinates are currently set\n manually (e.g. via a prior call with `coordinates`), an address-only\n update leaves the existing manual coordinates untouched rather than\n re-geocoding; include `coordinates` in `updateMask` to change them.",
"examples": [
{
"address1": "123 Main St",
"address2": "Apt 3B",
"city": "New York",
"provinceCode": "NY",
"countryCode": "US",
"zip": "10001"
}
]
},
"coordinates": {
"allOf": [
{
"type": "object",
"properties": {
"latitude": {
"type": "number",
"description": "The latitude in degrees. It must be in the range [-90.0, +90.0].",
"format": "double"
},
"longitude": {
"type": "number",
"description": "The longitude in degrees. It must be in the range [-180.0, +180.0].",
"format": "double"
}
},
"description": "An object that represents a latitude/longitude pair. This is expressed as a\n pair of doubles to represent degrees latitude and degrees longitude. Unless\n specified otherwise, this must conform to the\n WGS84\n standard. Values must be within normalized ranges."
}
],
"description": "The new coordinates for the location. If included in `updateMask`, these\n coordinates are used directly instead of geocoding the address, and are\n treated as a manual override of the location.",
"examples": [
{
"latitude": 40.7128,
"longitude": -74.006
}
]
}
}
}
],
"description": "Update for the route's start location."
},
"updateMask": {
"type": "string",
"description": "Comma-separated list of [field mask](https://docs.roundtrip.ai/docs/concepts/field-masks.md) paths in `start` to apply. Only listed paths are updated; omitted fields are left unchanged. Must contain at least one of `address` or `coordinates`.",
"format": "field-mask"
}
}
}
}
},
"required": true
},
"responses": {
"200": {
"description": "OK",
"headers": {
"Idempotency-Key": {
"description": "The idempotency key associated with the response.",
"schema": {
"type": "string"
}
},
"Idempotency-Replayed": {
"description": "Whether the response was replayed from a previous request.",
"schema": {
"type": "boolean"
}
}
},
"content": {
"application/json": {
"schema": {
"title": "Route",
"required": [
"id",
"name",
"stops",
"createdAt",
"updatedAt",
"totalDistanceMeters",
"totalItemQuantity",
"totalItemGrams",
"optimized"
],
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Route ID (e.g. `\"rte-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"rte-123e4567-e89b-12d3-a456-426614174000"
]
},
"name": {
"type": "string",
"description": "Route name (e.g. `\"Morning route\"`).",
"examples": [
"Morning route"
]
},
"driver": {
"allOf": [
{
"title": "Driver",
"required": [
"id"
],
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Driver ID (e.g. `\"drv-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"drv-123e4567-e89b-12d3-a456-426614174000"
]
},
"firstName": {
"type": "string",
"description": "Driver first name (e.g. `\"John\"`).",
"examples": [
"John"
]
},
"lastName": {
"type": "string",
"description": "Driver last name (e.g. `\"Doe\"`).",
"examples": [
"Doe"
]
},
"phone": {
"type": "string",
"description": "Driver phone number in [E.164 format](https://en.wikipedia.org/wiki/E.164)\n (e.g. `\"+14265551000\"`).",
"examples": [
"+14265551000"
]
},
"status": {
"enum": [
"UNKNOWN",
"ACTIVE",
"INACTIVE",
"ARCHIVED"
],
"type": "string",
"description": "Shop driver status. (e.g. `ACTIVE`).",
"format": "enum",
"examples": [
"ACTIVE"
]
}
},
"description": "A driver who is assigned to a route."
}
],
"description": "Assigned driver for the route."
},
"start": {
"allOf": [
{
"title": "RouteStart",
"type": "object",
"properties": {
"address": {
"allOf": [
{
"title": "Address",
"type": "object",
"properties": {
"address1": {
"type": "string",
"description": "Street address line 1 (e.g. `\"123 Main St\"`).",
"examples": [
"123 Main St"
]
},
"address2": {
"type": "string",
"description": "Street address line 2 (e.g. `\"Apt 101\"`).",
"examples": [
"Apt 3B"
]
},
"city": {
"type": "string",
"description": "City name (e.g. `\"New York\"`).",
"examples": [
"New York"
]
},
"provinceCode": {
"type": "string",
"description": "Province or state as subdivision codes in\n [ISO 3166-2](https://en.wikipedia.org/wiki/ISO_3166-2) format without the\n country prefix (e.g. `\"NY\"` for New York).",
"examples": [
"NY"
]
},
"countryCode": {
"type": "string",
"description": "Country code (e.g. `\"US\"`).",
"examples": [
"US"
]
},
"zip": {
"type": "string",
"description": "Postal or ZIP code (e.g. `\"10001\"`).",
"examples": [
"10001"
]
}
},
"description": "A physical street address."
}
],
"description": "The start address of the route.",
"examples": [
{
"address1": "123 Main St",
"address2": "Apt 3B",
"city": "New York",
"provinceCode": "NY",
"countryCode": "US",
"zip": "10001"
}
]
},
"tasks": {
"type": "array",
"items": {
"title": "Task",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Task ID (e.g. `\"tsk-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"tsk-123e4567-e89b-12d3-a456-426614174000"
]
},
"title": {
"type": "string",
"description": "Task title (e.g. `\"Delivery checklist\"`).",
"examples": [
"Delivery checklist"
]
},
"type": {
"enum": [
"UNKNOWN",
"CHECKBOXES",
"RADIO_BUTTONS",
"TEXT_INPUT",
"DECIMAL_INPUT",
"SCANNER_INPUT"
],
"type": "string",
"description": "Task type.",
"format": "enum",
"examples": [
"TEXT_INPUT"
]
},
"items": {
"type": "array",
"items": {
"title": "TaskItem",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Item ID (e.g. `\"itm-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"itm-123e4567-e89b-12d3-a456-426614174000"
]
},
"title": {
"type": "string",
"description": "Item title (e.g. `\"Pick up package\"`).",
"examples": [
"Pick up package"
]
},
"complete": {
"type": "boolean",
"description": "Whether the item is completed.",
"examples": [
true
]
},
"updatedAt": {
"type": "string",
"description": "Timestamp when the item was last updated.",
"format": "date-time",
"examples": [
"2026-03-30T13:00:00Z"
]
}
},
"description": "An item within a task. For `CHECKBOXES`, each item on a task may be completed\n independently. For `RADIO_BUTTONS`, at most one item will be completed."
},
"description": "Task items (populated for `CHECKBOXES` and `RADIO_BUTTONS`).",
"examples": [
[]
]
},
"input": {
"allOf": [
{
"title": "TaskInput",
"type": "object",
"properties": {
"value": {
"type": "string",
"description": "Input value.",
"examples": [
"020123456789"
]
},
"updatedAt": {
"type": "string",
"description": "Timestamp when the input was last updated.",
"format": "date-time",
"examples": [
"2026-03-30T13:00:00Z"
]
},
"inputMethod": {
"enum": [
"UNKNOWN",
"SCANNED"
],
"type": "string",
"description": "Whether input was scanned (e.g. a scanned barcode)",
"format": "enum",
"examples": [
"SCANNED"
]
}
},
"description": "Captured driver input for a task. The value may be text for `TEXT_INPUT`\n tasks or a string decimal number for `DECIMAL_INPUT` tasks."
}
],
"description": "Task input (populated for `TEXT_INPUT` and `DECIMAL_INPUT`)."
},
"requiredToMarkStopAsDelivered": {
"type": "boolean",
"description": "Whether the task is required to mark the stop as completed. In the case of\n tasks on `RouteStart`, this represents tasks required for starting the\n route. In the case of tasks on `RouteEnd`, this represents tasks required\n for completing the route.",
"examples": [
true
]
},
"requiredToMarkStopAsAttempted": {
"type": "boolean",
"description": "Whether the task is required to mark the stop as attempted.",
"examples": [
true
]
}
},
"description": "A task to be completed at a stop, or at the start or end of a route. Tasks\n may have one or more items for `CHECKBOXES` or `RADIO_BUTTONS`, or may have\n an input for `TEXT_INPUT` or `DECIMAL_INPUT`."
},
"description": "Tasks to complete before starting the route."
},
"status": {
"enum": [
"UNKNOWN",
"STARTED"
],
"type": "string",
"description": "Status indicating whether the route has been started.",
"format": "enum",
"examples": [
"STARTED"
]
},
"updatedStart": {
"type": "string",
"description": "Updated start time for the route. If the route is started, this will be the\n actual start time.",
"format": "date-time",
"examples": [
"2026-03-30T09:05:00Z"
]
},
"scheduledStart": {
"type": "string",
"description": "Scheduled start time for the route (same as `scheduledFor` on the route).",
"format": "date-time",
"examples": [
"2026-03-30T09:00:00Z"
]
},
"photos": {
"type": "array",
"items": {
"title": "StopAttachment",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Attachment ID (e.g. `\"att-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"att-123e4567-e89b-12d3-a456-426614174000"
]
},
"createdAt": {
"type": "string",
"description": "Timestamp when the attachment was created.",
"format": "date-time",
"examples": [
"2026-03-30T09:05:00Z"
]
},
"url": {
"type": "string",
"description": "URL to fetch the attachment.",
"examples": [
"https://example.com/stop-attachment/attachment-2025-06-03-1"
]
}
},
"description": "An attachment to a stop, such as a proof of delivery photo or signature."
},
"description": "Photos for the route start. Photos may be fetched using the URLs on the\n attachments."
}
},
"description": "The start location of a route and any driver tasks to complete before\n beginning the route."
}
],
"description": "Route start address and tasks."
},
"end": {
"allOf": [
{
"title": "RouteEnd",
"type": "object",
"properties": {
"address": {
"allOf": [
{
"title": "Address",
"type": "object",
"properties": {
"address1": {
"type": "string",
"description": "Street address line 1 (e.g. `\"123 Main St\"`).",
"examples": [
"123 Main St"
]
},
"address2": {
"type": "string",
"description": "Street address line 2 (e.g. `\"Apt 101\"`).",
"examples": [
"Apt 3B"
]
},
"city": {
"type": "string",
"description": "City name (e.g. `\"New York\"`).",
"examples": [
"New York"
]
},
"provinceCode": {
"type": "string",
"description": "Province or state as subdivision codes in\n [ISO 3166-2](https://en.wikipedia.org/wiki/ISO_3166-2) format without the\n country prefix (e.g. `\"NY\"` for New York).",
"examples": [
"NY"
]
},
"countryCode": {
"type": "string",
"description": "Country code (e.g. `\"US\"`).",
"examples": [
"US"
]
},
"zip": {
"type": "string",
"description": "Postal or ZIP code (e.g. `\"10001\"`).",
"examples": [
"10001"
]
}
},
"description": "A physical street address."
}
],
"description": "The end address of the route.",
"examples": [
{
"address1": "123 Main St",
"address2": "Apt 3B",
"city": "New York",
"provinceCode": "NY",
"countryCode": "US",
"zip": "10001"
}
]
},
"tasks": {
"type": "array",
"items": {
"title": "Task",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Task ID (e.g. `\"tsk-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"tsk-123e4567-e89b-12d3-a456-426614174000"
]
},
"title": {
"type": "string",
"description": "Task title (e.g. `\"Delivery checklist\"`).",
"examples": [
"Delivery checklist"
]
},
"type": {
"enum": [
"UNKNOWN",
"CHECKBOXES",
"RADIO_BUTTONS",
"TEXT_INPUT",
"DECIMAL_INPUT",
"SCANNER_INPUT"
],
"type": "string",
"description": "Task type.",
"format": "enum",
"examples": [
"TEXT_INPUT"
]
},
"items": {
"type": "array",
"items": {
"title": "TaskItem",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Item ID (e.g. `\"itm-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"itm-123e4567-e89b-12d3-a456-426614174000"
]
},
"title": {
"type": "string",
"description": "Item title (e.g. `\"Pick up package\"`).",
"examples": [
"Pick up package"
]
},
"complete": {
"type": "boolean",
"description": "Whether the item is completed.",
"examples": [
true
]
},
"updatedAt": {
"type": "string",
"description": "Timestamp when the item was last updated.",
"format": "date-time",
"examples": [
"2026-03-30T13:00:00Z"
]
}
},
"description": "An item within a task. For `CHECKBOXES`, each item on a task may be completed\n independently. For `RADIO_BUTTONS`, at most one item will be completed."
},
"description": "Task items (populated for `CHECKBOXES` and `RADIO_BUTTONS`).",
"examples": [
[]
]
},
"input": {
"allOf": [
{
"title": "TaskInput",
"type": "object",
"properties": {
"value": {
"type": "string",
"description": "Input value.",
"examples": [
"020123456789"
]
},
"updatedAt": {
"type": "string",
"description": "Timestamp when the input was last updated.",
"format": "date-time",
"examples": [
"2026-03-30T13:00:00Z"
]
},
"inputMethod": {
"enum": [
"UNKNOWN",
"SCANNED"
],
"type": "string",
"description": "Whether input was scanned (e.g. a scanned barcode)",
"format": "enum",
"examples": [
"SCANNED"
]
}
},
"description": "Captured driver input for a task. The value may be text for `TEXT_INPUT`\n tasks or a string decimal number for `DECIMAL_INPUT` tasks."
}
],
"description": "Task input (populated for `TEXT_INPUT` and `DECIMAL_INPUT`)."
},
"requiredToMarkStopAsDelivered": {
"type": "boolean",
"description": "Whether the task is required to mark the stop as completed. In the case of\n tasks on `RouteStart`, this represents tasks required for starting the\n route. In the case of tasks on `RouteEnd`, this represents tasks required\n for completing the route.",
"examples": [
true
]
},
"requiredToMarkStopAsAttempted": {
"type": "boolean",
"description": "Whether the task is required to mark the stop as attempted.",
"examples": [
true
]
}
},
"description": "A task to be completed at a stop, or at the start or end of a route. Tasks\n may have one or more items for `CHECKBOXES` or `RADIO_BUTTONS`, or may have\n an input for `TEXT_INPUT` or `DECIMAL_INPUT`."
},
"description": "Tasks to complete before finishing the route."
},
"plannedArrival": {
"type": "string",
"description": "Planned arrival time at the end of the route.",
"format": "date-time",
"examples": [
"2026-03-30T17:00:00Z"
]
},
"distanceMeters": {
"type": "number",
"description": "The distance in meters from the previous stop.",
"format": "double",
"examples": [
1234.56
]
},
"updatedArrival": {
"type": "string",
"description": "Estimated arrival time at the end of the route. If the route is completed,\n this will be the actual arrival time.",
"format": "date-time",
"examples": [
"2026-03-30T17:05:00Z"
]
},
"status": {
"enum": [
"UNKNOWN",
"COMPLETED"
],
"type": "string",
"description": "Status indicating whether the route has been completed.",
"format": "enum",
"examples": [
"COMPLETED"
]
},
"photos": {
"type": "array",
"items": {
"title": "StopAttachment",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Attachment ID (e.g. `\"att-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"att-123e4567-e89b-12d3-a456-426614174000"
]
},
"createdAt": {
"type": "string",
"description": "Timestamp when the attachment was created.",
"format": "date-time",
"examples": [
"2026-03-30T09:05:00Z"
]
},
"url": {
"type": "string",
"description": "URL to fetch the attachment.",
"examples": [
"https://example.com/stop-attachment/attachment-2025-06-03-1"
]
}
},
"description": "An attachment to a stop, such as a proof of delivery photo or signature."
},
"description": "Photos for the route end. Photos may be fetched using the URLs on the\n attachments."
}
},
"description": "The end location of a route and any driver tasks to complete after completing\n the route."
}
],
"description": "Route end address and tasks."
},
"stops": {
"type": "array",
"items": {
"title": "RouteStop",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Stop ID (e.g. `\"rst-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"rst-123e4567-e89b-12d3-a456-426614174000"
]
},
"type": {
"enum": [
"UNKNOWN",
"DELIVERY",
"BREAK",
"PICKUP",
"TASK"
],
"type": "string",
"description": "The type of stop (DELIVERY, BREAK, PICKUP, or TASK).",
"format": "enum",
"examples": [
"DELIVERY"
]
},
"deliveryStatus": {
"enum": [
"UNKNOWN",
"DELIVERED",
"OUT_FOR_DELIVERY",
"ATTEMPTED_DELIVERY",
"READY_FOR_DELIVERY"
],
"type": "string",
"description": "The status for DELIVERY, PICKUP, or TASK stops.",
"format": "enum",
"examples": [
"ATTEMPTED_DELIVERY"
]
},
"breakStatus": {
"enum": [
"UNKNOWN",
"COMPLETED"
],
"type": "string",
"description": "The status for BREAK stops.",
"format": "enum",
"examples": [
"COMPLETED"
]
},
"updatedAt": {
"type": "string",
"description": "Timestamp when the stop status was last updated. Note that this timestamp\n corresponds only to major status updates (i.e. stop marked as DELIVERED).\n Minor updates like task completion or adding proof of delivery will not\n advance this timestamp. For those events, use the timestamps on the task or\n proof of delivery attachment.",
"format": "date-time",
"examples": [
"2026-03-30T13:15:00Z"
]
},
"duration": {
"pattern": "^-?(?:0|[1-9][0-9]{0,11})(?:\\.[0-9]{1,9})?s$",
"type": "string",
"description": "Planned duration of the stop in seconds.",
"examples": [
"300s"
]
},
"plannedArrival": {
"type": "string",
"description": "Planned arrival time at the stop.",
"format": "date-time",
"examples": [
"2026-03-30T13:00:00Z"
]
},
"note": {
"type": "string",
"description": "Top-level note for the stop, as entered manually by route planners,\n inherited from a saved or imported stop, or set by order import automation\n rules.",
"examples": [
"Leave at door."
]
},
"address": {
"allOf": [
{
"title": "Address",
"type": "object",
"properties": {
"address1": {
"type": "string",
"description": "Street address line 1 (e.g. `\"123 Main St\"`).",
"examples": [
"123 Main St"
]
},
"address2": {
"type": "string",
"description": "Street address line 2 (e.g. `\"Apt 101\"`).",
"examples": [
"Apt 3B"
]
},
"city": {
"type": "string",
"description": "City name (e.g. `\"New York\"`).",
"examples": [
"New York"
]
},
"provinceCode": {
"type": "string",
"description": "Province or state as subdivision codes in\n [ISO 3166-2](https://en.wikipedia.org/wiki/ISO_3166-2) format without the\n country prefix (e.g. `\"NY\"` for New York).",
"examples": [
"NY"
]
},
"countryCode": {
"type": "string",
"description": "Country code (e.g. `\"US\"`).",
"examples": [
"US"
]
},
"zip": {
"type": "string",
"description": "Postal or ZIP code (e.g. `\"10001\"`).",
"examples": [
"10001"
]
}
},
"description": "A physical street address."
}
],
"description": "Delivery address for the stop.",
"examples": [
{
"address1": "123 Main St",
"address2": "Apt 3B",
"city": "New York",
"provinceCode": "NY",
"countryCode": "US",
"zip": "10001"
}
]
},
"contact": {
"allOf": [
{
"title": "Contact",
"type": "object",
"properties": {
"firstName": {
"type": "string",
"description": "First name (e.g. `\"John\"`).",
"examples": [
"John"
]
},
"lastName": {
"type": "string",
"description": "Last name (e.g. `\"Doe\"`).",
"examples": [
"Doe"
]
},
"company": {
"type": "string",
"description": "Company name (e.g. `\"Roundtrip Systems Inc\"`).",
"examples": [
"Roundtrip Systems Inc"
]
},
"phone": {
"type": "string",
"description": "Phone number in [E.164 format](https://en.wikipedia.org/wiki/E.164) (e.g.\n `\"+14265551000\"`).",
"examples": [
"+14265551000"
]
},
"email": {
"type": "string",
"description": "Email address (e.g. `\"john.doe@roundtrip.ai\"`)",
"examples": [
"john.doe@roundtrip.ai"
]
}
},
"description": "Contact information for a person or company."
}
],
"description": "Contact information for the stop delivery recipient.",
"examples": [
{
"firstName": "John",
"lastName": "Doe",
"company": "Roundtrip Systems Inc",
"phone": "+14265551000",
"email": "john.doe@roundtrip.ai"
}
]
},
"plannedCoordinates": {
"allOf": [
{
"type": "object",
"properties": {
"latitude": {
"type": "number",
"description": "The latitude in degrees. It must be in the range [-90.0, +90.0].",
"format": "double"
},
"longitude": {
"type": "number",
"description": "The longitude in degrees. It must be in the range [-180.0, +180.0].",
"format": "double"
}
},
"description": "An object that represents a latitude/longitude pair. This is expressed as a\n pair of doubles to represent degrees latitude and degrees longitude. Unless\n specified otherwise, this must conform to the\n WGS84\n standard. Values must be within normalized ranges."
}
],
"description": "Planned coordinates for the stop.",
"examples": [
{
"latitude": 40.7128,
"longitude": -74.006
}
]
},
"items": {
"type": "array",
"items": {
"title": "StopItem",
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "Item name (e.g. `\"Bananas\"`).",
"examples": [
"Bananas"
]
},
"quantity": {
"type": "integer",
"description": "Quantity of the item (e.g. `5`).",
"format": "int32",
"examples": [
5
]
},
"grams": {
"type": "integer",
"description": "Weight of the item in grams (e.g. `500`).",
"format": "int32",
"examples": [
500
]
},
"sku": {
"type": "string",
"description": "Stock keeping unit (e.g. `\"BANANA-001\"`).",
"examples": [
"BANANA-001"
]
}
},
"description": "An item to be delivered at a stop."
},
"description": "Items to deliver at the stop."
},
"source": {
"enum": [
"UNKNOWN",
"SHOPIFY_ORDER",
"SAVED_STOP",
"IMPORTED_STOP"
],
"type": "string",
"description": "The source of the stop, which may be populated for `DELIVERY` stops. The\n source can be a `SHOPIFY_ORDER`, an EasyRoutes `SAVED_STOP`, or an\n `IMPORTED_STOP` from an external source (such as CSV file).",
"format": "enum",
"examples": [
"IMPORTED_STOP"
]
},
"shopifyOrderId": {
"type": "string",
"description": "The Shopify order ID, populated when the stop source is a `SHOPIFY_ORDER`.",
"examples": [
"6229749334323"
]
},
"savedStopId": {
"type": "string",
"description": "The saved stop ID, populated when the stop source is a `SAVED_STOP`.",
"examples": [
"sst-123e4567-e89b-12d3-a456-426614174000"
]
},
"deliveredCoordinates": {
"allOf": [
{
"type": "object",
"properties": {
"latitude": {
"type": "number",
"description": "The latitude in degrees. It must be in the range [-90.0, +90.0].",
"format": "double"
},
"longitude": {
"type": "number",
"description": "The longitude in degrees. It must be in the range [-180.0, +180.0].",
"format": "double"
}
},
"description": "An object that represents a latitude/longitude pair. This is expressed as a\n pair of doubles to represent degrees latitude and degrees longitude. Unless\n specified otherwise, this must conform to the\n WGS84\n standard. Values must be within normalized ranges."
}
],
"description": "Delivered coordinates for the stop."
},
"proofOfDeliveryNote": {
"type": "string",
"description": "Proof of delivery note for the stop.",
"examples": [
"Left at door."
]
},
"proofOfDeliveryPhotos": {
"type": "array",
"items": {
"title": "StopAttachment",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Attachment ID (e.g. `\"att-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"att-123e4567-e89b-12d3-a456-426614174000"
]
},
"createdAt": {
"type": "string",
"description": "Timestamp when the attachment was created.",
"format": "date-time",
"examples": [
"2026-03-30T09:05:00Z"
]
},
"url": {
"type": "string",
"description": "URL to fetch the attachment.",
"examples": [
"https://example.com/stop-attachment/attachment-2025-06-03-1"
]
}
},
"description": "An attachment to a stop, such as a proof of delivery photo or signature."
},
"description": "Proof of delivery photos for the stop. Photos may be fetched using the URLs\n on the attachments."
},
"proofOfDeliverySignatures": {
"type": "array",
"items": {
"title": "StopAttachment",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Attachment ID (e.g. `\"att-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"att-123e4567-e89b-12d3-a456-426614174000"
]
},
"createdAt": {
"type": "string",
"description": "Timestamp when the attachment was created.",
"format": "date-time",
"examples": [
"2026-03-30T09:05:00Z"
]
},
"url": {
"type": "string",
"description": "URL to fetch the attachment.",
"examples": [
"https://example.com/stop-attachment/attachment-2025-06-03-1"
]
}
},
"description": "An attachment to a stop, such as a proof of delivery photo or signature."
},
"description": "Proof of delivery signatures for the stop. Signatures may be fetched using\n the URLs on the attachments."
},
"tasks": {
"type": "array",
"items": {
"title": "Task",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Task ID (e.g. `\"tsk-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"tsk-123e4567-e89b-12d3-a456-426614174000"
]
},
"title": {
"type": "string",
"description": "Task title (e.g. `\"Delivery checklist\"`).",
"examples": [
"Delivery checklist"
]
},
"type": {
"enum": [
"UNKNOWN",
"CHECKBOXES",
"RADIO_BUTTONS",
"TEXT_INPUT",
"DECIMAL_INPUT",
"SCANNER_INPUT"
],
"type": "string",
"description": "Task type.",
"format": "enum",
"examples": [
"TEXT_INPUT"
]
},
"items": {
"type": "array",
"items": {
"title": "TaskItem",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Item ID (e.g. `\"itm-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"itm-123e4567-e89b-12d3-a456-426614174000"
]
},
"title": {
"type": "string",
"description": "Item title (e.g. `\"Pick up package\"`).",
"examples": [
"Pick up package"
]
},
"complete": {
"type": "boolean",
"description": "Whether the item is completed.",
"examples": [
true
]
},
"updatedAt": {
"type": "string",
"description": "Timestamp when the item was last updated.",
"format": "date-time",
"examples": [
"2026-03-30T13:00:00Z"
]
}
},
"description": "An item within a task. For `CHECKBOXES`, each item on a task may be completed\n independently. For `RADIO_BUTTONS`, at most one item will be completed."
},
"description": "Task items (populated for `CHECKBOXES` and `RADIO_BUTTONS`).",
"examples": [
[]
]
},
"input": {
"allOf": [
{
"title": "TaskInput",
"type": "object",
"properties": {
"value": {
"type": "string",
"description": "Input value.",
"examples": [
"020123456789"
]
},
"updatedAt": {
"type": "string",
"description": "Timestamp when the input was last updated.",
"format": "date-time",
"examples": [
"2026-03-30T13:00:00Z"
]
},
"inputMethod": {
"enum": [
"UNKNOWN",
"SCANNED"
],
"type": "string",
"description": "Whether input was scanned (e.g. a scanned barcode)",
"format": "enum",
"examples": [
"SCANNED"
]
}
},
"description": "Captured driver input for a task. The value may be text for `TEXT_INPUT`\n tasks or a string decimal number for `DECIMAL_INPUT` tasks."
}
],
"description": "Task input (populated for `TEXT_INPUT` and `DECIMAL_INPUT`)."
},
"requiredToMarkStopAsDelivered": {
"type": "boolean",
"description": "Whether the task is required to mark the stop as completed. In the case of\n tasks on `RouteStart`, this represents tasks required for starting the\n route. In the case of tasks on `RouteEnd`, this represents tasks required\n for completing the route.",
"examples": [
true
]
},
"requiredToMarkStopAsAttempted": {
"type": "boolean",
"description": "Whether the task is required to mark the stop as attempted.",
"examples": [
true
]
}
},
"description": "A task to be completed at a stop, or at the start or end of a route. Tasks\n may have one or more items for `CHECKBOXES` or `RADIO_BUTTONS`, or may have\n an input for `TEXT_INPUT` or `DECIMAL_INPUT`."
},
"description": "Driver tasks for the stop, including completed items and any input from the\n driver."
},
"priority": {
"maximum": 10,
"type": "integer",
"description": "Priority of the stop for route planning. The valid range for stop priority\n is between `1` (low) and `10` (high), with default priority corresponding\n to a value of `5`. A priority value of `0` is considered unset and is\n treated the same as \"default\" priority. Stops with higher priority will be\n preferred when generating routes with constraints.",
"format": "int32",
"examples": [
8
]
},
"importedStopId": {
"type": "string",
"description": "The imported stop ID, populated when the stop source is `IMPORTED_STOP`.",
"examples": [
"ist-123e4567-e89b-12d3-a456-426614174000"
]
},
"orderName": {
"type": "string",
"description": "The name of the order associated with the stop. For Shopify orders, the\n name is generated by combining the `orderNumber` property with the order\n prefix and suffix that are set in the merchant's general settings. For\n EasyRoutes imported orders, this field is populated with the order name\n provided on import.",
"examples": [
"#1234"
]
},
"distanceMeters": {
"type": "number",
"description": "The distance in meters from the previous stop.",
"format": "double",
"examples": [
123.45
]
},
"updatedArrival": {
"type": "string",
"description": "Estimated arrival time at the stop. If the stop is completed, this will be\n the actual arrival time.",
"format": "date-time",
"examples": [
"2026-03-30T13:05:00Z"
]
},
"timeWindows": {
"type": "array",
"items": {
"title": "TimeWindow",
"type": "object",
"properties": {
"start": {
"allOf": [
{
"title": "TimeOfDay",
"type": "object",
"properties": {
"hours": {
"maximum": 23,
"type": "integer",
"description": "Hours of day in 24 hour format. Must be from 0 to 23.",
"format": "int32",
"examples": [
13
]
},
"minutes": {
"maximum": 59,
"type": "integer",
"description": "Minutes of hour of day. Must be from 0 to 59.",
"format": "int32",
"examples": [
37
]
},
"seconds": {
"maximum": 59,
"type": "integer",
"description": "Seconds of minutes of the time. Must be from 0 to 59.",
"format": "int32",
"examples": [
16
]
}
},
"description": "A time of day, independent of a particular date or timezone."
}
],
"description": "The start time of the time window (optional)."
},
"end": {
"allOf": [
{
"title": "TimeOfDay",
"type": "object",
"properties": {
"hours": {
"maximum": 23,
"type": "integer",
"description": "Hours of day in 24 hour format. Must be from 0 to 23.",
"format": "int32",
"examples": [
13
]
},
"minutes": {
"maximum": 59,
"type": "integer",
"description": "Minutes of hour of day. Must be from 0 to 59.",
"format": "int32",
"examples": [
37
]
},
"seconds": {
"maximum": 59,
"type": "integer",
"description": "Seconds of minutes of the time. Must be from 0 to 59.",
"format": "int32",
"examples": [
16
]
}
},
"description": "A time of day, independent of a particular date or timezone."
}
],
"description": "The end time of the time window (optional)."
}
},
"description": "A time window for a stop. The time window may be open-ended, but one or both\n of the start and end times should be provided. The end time must be >= the\n start time."
},
"description": "The time window for the stop. Note that we currently support at most one\n time window but may support multiple time windows in the future.",
"examples": [
[
{
"start": {
"hours": 9
},
"end": {
"hours": 17
}
}
]
]
},
"deliveryDate": {
"allOf": [
{
"title": "Date",
"required": [
"year",
"month",
"day"
],
"type": "object",
"properties": {
"year": {
"maximum": 9999,
"minimum": 1,
"type": "integer",
"description": "Year of the date. Must be from 1 to 9999.",
"format": "int32",
"examples": [
2019
]
},
"month": {
"maximum": 12,
"minimum": 1,
"type": "integer",
"description": "Month of a year. Must be from 1 to 12.",
"format": "int32",
"examples": [
11
]
},
"day": {
"maximum": 31,
"minimum": 1,
"type": "integer",
"description": "Day of a month. Must be from 1 to 31.",
"format": "int32",
"examples": [
15
]
}
},
"description": "A date in year-month-day format."
}
],
"description": "The planned delivery date for the stop.",
"examples": [
{
"year": 2025,
"month": 12,
"day": 16
}
]
},
"attributes": {
"type": "array",
"items": {
"title": "Attribute",
"type": "object",
"properties": {
"key": {
"type": "string",
"description": "Attribute key. Must be non-empty.",
"examples": [
"delivery_date"
]
},
"value": {
"type": "string",
"description": "Attribute value.",
"examples": [
"2025-12-16"
]
}
},
"description": "A key-value pair for storing additional information on a stop, such as order\n details, delivery instructions, or custom fields."
},
"description": "Additional attributes for the stop. Attributes are key-value pairs for\n storing additional structured data on stops. These may be populated from\n the Shopify order or set on import.",
"examples": [
[
{
"key": "color",
"value": "blue"
}
]
]
},
"clientStopId": {
"type": "string",
"description": "The client-provided ID associated with the stop, if provided on import.",
"examples": [
"test-order-1234"
]
},
"tags": {
"type": "array",
"items": {
"type": "string"
},
"description": "The tags for the stop. Tags are used to categorize stops and can be used\n for filtering and grouping stops in the EasyRoutes web app. These may be\n populated from the Shopify order or set on import.",
"examples": [
[
"foo",
"bar"
]
]
},
"attemptedReason": {
"enum": [
"UNKNOWN",
"NOT_AVAILABLE",
"ACCESS_DENIED",
"INCORRECT_ADDRESS",
"SAFE_PLACE_UNAVAILABLE",
"REFUSED",
"EXTERNAL",
"INCORRECT_ITEMS",
"OTHER",
"CANCELED"
],
"type": "string",
"description": "The reason for marking the stop as attempted. This is only populated when\n `deliveryStatus = ATTEMPTED_DELIVERY`.",
"format": "enum",
"examples": [
"NOT_AVAILABLE"
]
},
"attemptedNote": {
"type": "string",
"description": "Optional note related to the reason for marking the stop as attempted. This\n is optionally populated when `deliveryStatus = ATTEMPTED_DELIVERY`.",
"examples": [
"Customer did not answer the door."
]
},
"customerRating": {
"allOf": [
{
"title": "CustomerRating",
"type": "object",
"properties": {
"rating": {
"maximum": 5,
"minimum": 1,
"type": "integer",
"description": "Rating from 1-5",
"format": "int32",
"examples": [
5
]
},
"comment": {
"type": "string",
"description": "Customer comment related to rating",
"examples": [
"Excellent delivery"
]
},
"createdAt": {
"type": "string",
"description": "Timestamp when rating was left by customer.",
"format": "date-time",
"examples": [
"2026-03-30T18:00:00Z"
]
}
},
"description": "Customer rating and feedback left on a stop."
}
],
"description": "Rating left by customer. This can only be populated once `deliveryStatus =\n DELIVERED`."
},
"customSignatureDisclosure": {
"type": "string",
"description": "Optional custom signature disclosure that is shown to customers in the\n driver app.",
"examples": [
"I acknowledge that I have received this delivery."
]
},
"shopifyOrder": {
"allOf": [
{
"title": "ShopifyOrder",
"type": "object",
"properties": {
"orderNote": {
"type": "string",
"description": "The Shopify order note.",
"examples": [
"Customer has paid."
]
},
"customerNote": {
"type": "string",
"description": "The Shopify customer note for the order.",
"examples": [
"Leave at door."
]
}
},
"description": "Shopify-specific information for a RouteStop."
}
],
"description": "Information from the associated Shopify order, if applicable. Populated if\n stop source is `SHOPIFY_ORDER`"
},
"proofOfDeliveryBarcodes": {
"type": "array",
"items": {
"title": "ScannedBarcode",
"type": "object",
"properties": {
"value": {
"type": "string",
"description": "Barcode value (e.g. `\"123456789012\"`).",
"examples": [
"123456789012"
]
},
"createdAt": {
"type": "string",
"description": "Timestamp when the barcode was scanned.",
"format": "date-time",
"examples": [
"2026-03-30T13:10:00Z"
]
}
},
"description": "A proof of delivery barcode scanned at a stop."
},
"description": "Proof of delivery barcodes scanned at the stop."
},
"proofOfDeliveryBarcodeIssues": {
"type": "array",
"items": {
"title": "ScannedBarcodeIssue",
"type": "object",
"properties": {
"reason": {
"enum": [
"UNKNOWN",
"ITEM_MISSING",
"NOT_SCANNABLE",
"INCORRECT"
],
"type": "string",
"description": "The reported reason for the barcode issue.",
"format": "enum",
"examples": [
"ITEM_MISSING"
]
},
"note": {
"type": "string",
"description": "Optional note related to the reason for reporting a barcode issue.",
"examples": [
"Item was not packed."
]
},
"createdAt": {
"type": "string",
"description": "Timestamp when the issue was reported.",
"format": "date-time",
"examples": [
"2026-03-30T13:10:00Z"
]
}
},
"description": "A reported issue related to scanning barcodes at a stop."
},
"description": "Proof of delivery barcode issues reported at the stop."
},
"orderReferenceUrl": {
"type": "string",
"description": "A reference URL for the order associated with the stop (e.g. a link to the\n order in your order management system). Must be a valid HTTPS URL. This\n field can only be populated for imported stops.",
"examples": [
"https://orders.example.com/orders/148977776"
]
}
},
"description": "A stop on a route. A stop may correspond to a delivery or a driver break as\n determined by the type. A delivery stop will have location and contact\n information, items to deliver, optional order details, status, arrival time\n and stop duration, driver tasks and any proof of delivery information. A\n break stop will have start time and duration, and status."
},
"description": "Route stops. See RouteStop for stop fields."
},
"createdAt": {
"type": "string",
"description": "Timestamp when the route was created.",
"format": "date-time",
"examples": [
"2026-03-29T08:00:00Z"
]
},
"updatedAt": {
"type": "string",
"description": "Timestamp when the route was last updated (by the planner).",
"format": "date-time",
"examples": [
"2026-03-30T13:15:00Z"
]
},
"archivedAt": {
"type": "string",
"description": "Timestamp when the route was archived.",
"format": "date-time",
"examples": [
"2026-04-05T00:00:00Z"
]
},
"scheduledFor": {
"type": "string",
"description": "Timestamp when the route is scheduled for.",
"format": "date-time",
"examples": [
"2026-03-30T09:00:00Z"
]
},
"totalDistanceMeters": {
"type": "number",
"description": "The distance in meters for the entire route.",
"format": "double",
"examples": [
2387.2
]
},
"totalItemQuantity": {
"type": "integer",
"description": "The total quantity of items to deliver on the route.",
"format": "int32",
"examples": [
50
]
},
"totalItemGrams": {
"type": "string",
"description": "The total weight in grams for the items on the route.",
"examples": [
"6000"
]
},
"optimized": {
"type": "boolean",
"description": "Whether the route has been optimized. Adding or removing stops, reordering\n stops, or changing route options generally set this field to false until\n the route is reoptimized.",
"examples": [
true
]
},
"dispatchedUntil": {
"type": "string",
"description": "Timestamp until which the route is dispatched and accessible in the driver\n app.",
"format": "date-time",
"examples": [
"2026-03-30T20:00:00Z"
]
},
"note": {
"type": "string",
"description": "Top-level note for the route, as entered manually by route planners.",
"examples": [
"Fragile items."
]
},
"tags": {
"type": "array",
"items": {
"type": "string"
},
"description": "The tags for the route. Tags are used to categorize routes and can be\n used for filtering and grouping routes in the EasyRoutes web app.",
"examples": [
[
"foo",
"bar"
]
]
},
"defaultStopDuration": {
"pattern": "^-?(?:0|[1-9][0-9]{0,11})(?:\\.[0-9]{1,9})?s$",
"type": "string",
"description": "The default duration for stops on the route. Used to estimate arrival\n times for stops that do not have their own duration specified.\n Specified as a duration string in the format \"300s\" for 5 minutes, \"60s\"\n for 1 minute, etc.",
"examples": [
"300s"
]
},
"maxDuration": {
"pattern": "^-?(?:0|[1-9][0-9]{0,11})(?:\\.[0-9]{1,9})?s$",
"type": "string",
"description": "The maximum duration of the route. Specified as a duration string in the\n format \"3600s\" for 1 hour, \"7200s\" for 2 hours, etc.",
"examples": [
"28800s"
]
},
"maxStops": {
"type": "integer",
"description": "The maximum number of stops on the route.",
"format": "int32",
"examples": [
50
]
},
"maxItemCount": {
"type": "integer",
"description": "The maximum total item count across all stops on the route.",
"format": "int32",
"examples": [
200
]
},
"maxKilograms": {
"type": "number",
"description": "The maximum total weight in kilograms across all stops on the route.",
"format": "double",
"examples": [
500
]
},
"avoidTolls": {
"type": "boolean",
"description": "Whether to avoid toll roads during optimization.",
"examples": [
true
]
},
"avoidUTurns": {
"type": "boolean",
"description": "Whether to avoid U-turns during optimization.",
"examples": [
true
]
},
"speedFactor": {
"type": "number",
"description": "A speed factor for the route used during optimization to adjust estimated\n travel times. A value of 1.0 represents normal speed. Values less than 1.0\n indicate slower travel (e.g. 0.5 = half speed), and values greater than\n 1.0 indicate faster travel (e.g. 1.5 = 50% faster). Must be between 0.1\n and 1.9. A value of 0 (or unset) uses the default speed.",
"format": "double",
"examples": [
0.8
]
},
"vehicle": {
"allOf": [
{
"title": "Vehicle",
"required": [
"id"
],
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Vehicle ID.",
"examples": [
"veh-123e4567-e89b-12d3-a456-426614174000"
]
},
"name": {
"type": "string",
"description": "Vehicle name.",
"examples": [
"Delivery Van 1"
]
},
"make": {
"type": "string",
"description": "Vehicle make.",
"examples": [
"Ford"
]
},
"model": {
"type": "string",
"description": "Vehicle model.",
"examples": [
"Transit"
]
},
"year": {
"type": "integer",
"description": "Vehicle model year.",
"format": "int32",
"examples": [
2023
]
},
"type": {
"enum": [
"UNKNOWN",
"CAR",
"CARGO_VAN",
"PICKUP_TRUCK",
"BOX_TRUCK",
"MOTORCYCLE",
"BICYCLE",
"DRONE",
"OTHER"
],
"type": "string",
"description": "Vehicle type.",
"format": "enum",
"examples": [
"CARGO_VAN"
]
},
"vin": {
"type": "string",
"description": "Vehicle Identification Number.",
"examples": [
"1FTBW2CM5NKA12345"
]
},
"license": {
"type": "string",
"description": "Vehicle license plate.",
"examples": [
"ABC-1234"
]
},
"isArchived": {
"type": "boolean",
"description": "Whether the vehicle is archived.",
"examples": [
false
]
},
"createdTimestamp": {
"type": "string",
"description": "Timestamp when the vehicle was created.",
"format": "date-time",
"examples": [
"2026-07-30T12:00:00Z"
]
}
},
"description": "A vehicle that can be assigned to a route."
}
],
"description": "Assigned vehicle for the route."
}
},
"description": "A route of stops, optionally with an assigned driver."
}
}
}
},
"default": {
"description": "Default error response",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"code": {
"type": "integer",
"description": "The status code, which should be an enum value of [google.rpc.Code][google.rpc.Code].",
"format": "int32"
},
"message": {
"type": "string",
"description": "A developer-facing error message, which should be in English. Any user-facing error message should be localized and sent in the [google.rpc.Status.details][google.rpc.Status.details] field, or localized by the client."
},
"details": {
"type": "array",
"items": {
"type": "object",
"properties": {
"@type": {
"type": "string",
"description": "The type of the serialized message."
}
},
"additionalProperties": true,
"description": "Contains an arbitrary serialized message along with a @type that describes the type of the serialized message."
},
"description": "A list of messages that carry the error details. There is a common set of message types for APIs to use."
}
},
"description": "The `Status` type defines a logical error model that is suitable for different programming environments, including REST APIs and RPC APIs. It is used by [gRPC](https://github.com/grpc). Each `Status` message contains three pieces of data: error code, error message, and error details. You can find out more about this error model and how to work with it in the [API Design Guide](https://cloud.google.com/apis/design/errors)."
}
}
}
}
},
"security": [
{
"bearerAuth": []
}
],
"components": {
"securitySchemes": {
"bearerAuth": {
"type": "http",
"description": "Access token from `/authenticate`",
"scheme": "bearer",
"bearerFormat": "JWT"
}
}
}
}
```
# Update route (https://docs.roundtrip.ai/docs/api-reference/routes/patch-routes-routeId)
PATCH /routes/{routeId}
Updates top-level fields on a route by route ID. This is a partial
update: provide the fields to change in `route` and list their paths in
`updateMask`. Only the paths listed in `updateMask` are applied; omitted
fields are left unchanged. The route must not be archived. See
UpdateRouteStartLocation/UpdateRouteEndLocation to update the route's
start/end location. The response returns the full updated route.
## OpenAPI specification
```json
{
"servers": [
{
"url": "https://easyroutes.roundtrip.ai/api/2024-07"
}
],
"tags": [
"Routes"
],
"summary": "Update route",
"description": "Updates top-level fields on a route by route ID. This is a partial\n update: provide the fields to change in `route` and list their paths in\n `updateMask`. Only the paths listed in `updateMask` are applied; omitted\n fields are left unchanged. The route must not be archived. See\n UpdateRouteStartLocation/UpdateRouteEndLocation to update the route's\n start/end location. The response returns the full updated route.",
"operationId": "UpdateRoute",
"parameters": [
{
"name": "routeId",
"in": "path",
"description": "The ID of the route to update.",
"required": true,
"schema": {
"type": "string",
"examples": [
"rte-123e4567-e89b-12d3-a456-426614174000"
]
}
},
{
"name": "Idempotency-Key",
"in": "header",
"description": "A unique key for safely retrying this operation. For more information read [our guide](https://docs.roundtrip.ai/docs/concepts/idempotency.md).",
"schema": {
"maxLength": 255,
"minLength": 1,
"type": "string"
},
"examples": {
"default": {
"value": "550e8400-e29b-41d4-a716-446655440000"
}
}
}
],
"requestBody": {
"content": {
"application/json": {
"schema": {
"title": "UpdateRouteRequest",
"required": [
"route",
"updateMask"
],
"type": "object",
"properties": {
"route": {
"allOf": [
{
"title": "RouteUpdate",
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "Route name (e.g. `\"Morning route\"`).",
"examples": [
"Morning route"
]
},
"note": {
"type": "string",
"description": "Top-level note for the route, as entered manually by route planners.",
"examples": [
"Fragile items."
]
},
"tags": {
"type": "array",
"items": {
"type": "string"
},
"description": "The tags for the route. Tags are used to categorize routes and can be\n used for filtering and grouping routes in the EasyRoutes web app. You may\n specify up to 10 tags per route.",
"examples": [
[
"foo",
"bar"
]
]
},
"defaultStopDuration": {
"pattern": "^-?(?:0|[1-9][0-9]{0,11})(?:\\.[0-9]{1,9})?s$",
"type": "string",
"description": "The default duration for stops on the route. Used to estimate arrival\n times for stops that do not have their own duration specified.\n Specified as a duration string in the format \"300s\" for 5 minutes, \"60s\"\n for 1 minute, etc.",
"examples": [
"300s"
]
},
"scheduledFor": {
"allOf": [
{
"type": "object",
"properties": {
"year": {
"type": "integer",
"description": "Required. Year of date. Must be from 1 to 9999.",
"format": "int32"
},
"month": {
"type": "integer",
"description": "Required. Month of year. Must be from 1 to 12.",
"format": "int32"
},
"day": {
"type": "integer",
"description": "Required. Day of month. Must be from 1 to 31 and valid for the year and\n month.",
"format": "int32"
},
"hours": {
"type": "integer",
"description": "Required. Hours of day in 24 hour format. Should be from 0 to 23.",
"format": "int32"
},
"minutes": {
"type": "integer",
"description": "Required. Minutes of hour of day. Must be from 0 to 59.",
"format": "int32"
},
"seconds": {
"type": "integer",
"description": "Required. Seconds of minutes of the time. Must normally be from 0 to 59.",
"format": "int32"
},
"nanos": {
"type": "integer",
"description": "Required. Fractions of seconds in nanoseconds. Must be from 0 to\n 999,999,999.",
"format": "int32"
},
"timezone": {
"type": "string",
"description": "Required. IANA Time Zone Database time zone, e.g.\n \"America/New_York\"."
}
},
"description": "A date and time with a timezone."
}
],
"description": "The date and time the route is scheduled for.",
"examples": [
{
"year": 2026,
"month": 3,
"day": 30,
"hours": 9,
"minutes": 0,
"seconds": 0,
"nanos": 0,
"timezone": "America/Toronto"
}
]
},
"maxDuration": {
"pattern": "^-?(?:0|[1-9][0-9]{0,11})(?:\\.[0-9]{1,9})?s$",
"type": "string",
"description": "The maximum duration of the route. Specified as a duration string in the\n format \"3600s\" for 1 hour, \"7200s\" for 2 hours, etc.",
"examples": [
"28800s"
]
},
"maxStops": {
"type": "integer",
"description": "The maximum number of stops on the route.",
"format": "int32",
"examples": [
50
]
},
"maxItemCount": {
"type": "integer",
"description": "The maximum total item count across all stops on the route.",
"format": "int32",
"examples": [
200
]
},
"maxKilograms": {
"type": "number",
"description": "The maximum total weight in kilograms across all stops on the route.",
"format": "double",
"examples": [
500
]
},
"avoidTolls": {
"type": "boolean",
"description": "Whether to avoid toll roads during optimization.",
"examples": [
true
]
},
"avoidUTurns": {
"type": "boolean",
"description": "Whether to avoid U-turns during optimization.",
"examples": [
true
]
},
"speedFactor": {
"type": "number",
"description": "A speed factor for the route used during optimization to adjust estimated\n travel times. A value of 1.0 represents normal speed. Values less than 1.0\n indicate slower travel (e.g. 0.5 = half speed), and values greater than\n 1.0 indicate faster travel (e.g. 1.5 = 50% faster). Must be between 0.1\n and 1.9. A value of 0 (or unset) uses the default speed.",
"format": "double",
"examples": [
0.8
]
}
}
}
],
"description": "Update for Route fields to apply to the specified route."
},
"updateMask": {
"type": "string",
"description": "Comma-separated list of [field mask](https://docs.roundtrip.ai/docs/concepts/field-masks.md) paths in `route` to apply. Only listed paths are updated; omitted fields are left unchanged.",
"format": "field-mask"
}
}
}
}
},
"required": true
},
"responses": {
"200": {
"description": "OK",
"headers": {
"Idempotency-Key": {
"description": "The idempotency key associated with the response.",
"schema": {
"type": "string"
}
},
"Idempotency-Replayed": {
"description": "Whether the response was replayed from a previous request.",
"schema": {
"type": "boolean"
}
}
},
"content": {
"application/json": {
"schema": {
"title": "Route",
"required": [
"id",
"name",
"stops",
"createdAt",
"updatedAt",
"totalDistanceMeters",
"totalItemQuantity",
"totalItemGrams",
"optimized"
],
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Route ID (e.g. `\"rte-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"rte-123e4567-e89b-12d3-a456-426614174000"
]
},
"name": {
"type": "string",
"description": "Route name (e.g. `\"Morning route\"`).",
"examples": [
"Morning route"
]
},
"driver": {
"allOf": [
{
"title": "Driver",
"required": [
"id"
],
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Driver ID (e.g. `\"drv-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"drv-123e4567-e89b-12d3-a456-426614174000"
]
},
"firstName": {
"type": "string",
"description": "Driver first name (e.g. `\"John\"`).",
"examples": [
"John"
]
},
"lastName": {
"type": "string",
"description": "Driver last name (e.g. `\"Doe\"`).",
"examples": [
"Doe"
]
},
"phone": {
"type": "string",
"description": "Driver phone number in [E.164 format](https://en.wikipedia.org/wiki/E.164)\n (e.g. `\"+14265551000\"`).",
"examples": [
"+14265551000"
]
},
"status": {
"enum": [
"UNKNOWN",
"ACTIVE",
"INACTIVE",
"ARCHIVED"
],
"type": "string",
"description": "Shop driver status. (e.g. `ACTIVE`).",
"format": "enum",
"examples": [
"ACTIVE"
]
}
},
"description": "A driver who is assigned to a route."
}
],
"description": "Assigned driver for the route."
},
"start": {
"allOf": [
{
"title": "RouteStart",
"type": "object",
"properties": {
"address": {
"allOf": [
{
"title": "Address",
"type": "object",
"properties": {
"address1": {
"type": "string",
"description": "Street address line 1 (e.g. `\"123 Main St\"`).",
"examples": [
"123 Main St"
]
},
"address2": {
"type": "string",
"description": "Street address line 2 (e.g. `\"Apt 101\"`).",
"examples": [
"Apt 3B"
]
},
"city": {
"type": "string",
"description": "City name (e.g. `\"New York\"`).",
"examples": [
"New York"
]
},
"provinceCode": {
"type": "string",
"description": "Province or state as subdivision codes in\n [ISO 3166-2](https://en.wikipedia.org/wiki/ISO_3166-2) format without the\n country prefix (e.g. `\"NY\"` for New York).",
"examples": [
"NY"
]
},
"countryCode": {
"type": "string",
"description": "Country code (e.g. `\"US\"`).",
"examples": [
"US"
]
},
"zip": {
"type": "string",
"description": "Postal or ZIP code (e.g. `\"10001\"`).",
"examples": [
"10001"
]
}
},
"description": "A physical street address."
}
],
"description": "The start address of the route.",
"examples": [
{
"address1": "123 Main St",
"address2": "Apt 3B",
"city": "New York",
"provinceCode": "NY",
"countryCode": "US",
"zip": "10001"
}
]
},
"tasks": {
"type": "array",
"items": {
"title": "Task",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Task ID (e.g. `\"tsk-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"tsk-123e4567-e89b-12d3-a456-426614174000"
]
},
"title": {
"type": "string",
"description": "Task title (e.g. `\"Delivery checklist\"`).",
"examples": [
"Delivery checklist"
]
},
"type": {
"enum": [
"UNKNOWN",
"CHECKBOXES",
"RADIO_BUTTONS",
"TEXT_INPUT",
"DECIMAL_INPUT",
"SCANNER_INPUT"
],
"type": "string",
"description": "Task type.",
"format": "enum",
"examples": [
"TEXT_INPUT"
]
},
"items": {
"type": "array",
"items": {
"title": "TaskItem",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Item ID (e.g. `\"itm-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"itm-123e4567-e89b-12d3-a456-426614174000"
]
},
"title": {
"type": "string",
"description": "Item title (e.g. `\"Pick up package\"`).",
"examples": [
"Pick up package"
]
},
"complete": {
"type": "boolean",
"description": "Whether the item is completed.",
"examples": [
true
]
},
"updatedAt": {
"type": "string",
"description": "Timestamp when the item was last updated.",
"format": "date-time",
"examples": [
"2026-03-30T13:00:00Z"
]
}
},
"description": "An item within a task. For `CHECKBOXES`, each item on a task may be completed\n independently. For `RADIO_BUTTONS`, at most one item will be completed."
},
"description": "Task items (populated for `CHECKBOXES` and `RADIO_BUTTONS`).",
"examples": [
[]
]
},
"input": {
"allOf": [
{
"title": "TaskInput",
"type": "object",
"properties": {
"value": {
"type": "string",
"description": "Input value.",
"examples": [
"020123456789"
]
},
"updatedAt": {
"type": "string",
"description": "Timestamp when the input was last updated.",
"format": "date-time",
"examples": [
"2026-03-30T13:00:00Z"
]
},
"inputMethod": {
"enum": [
"UNKNOWN",
"SCANNED"
],
"type": "string",
"description": "Whether input was scanned (e.g. a scanned barcode)",
"format": "enum",
"examples": [
"SCANNED"
]
}
},
"description": "Captured driver input for a task. The value may be text for `TEXT_INPUT`\n tasks or a string decimal number for `DECIMAL_INPUT` tasks."
}
],
"description": "Task input (populated for `TEXT_INPUT` and `DECIMAL_INPUT`)."
},
"requiredToMarkStopAsDelivered": {
"type": "boolean",
"description": "Whether the task is required to mark the stop as completed. In the case of\n tasks on `RouteStart`, this represents tasks required for starting the\n route. In the case of tasks on `RouteEnd`, this represents tasks required\n for completing the route.",
"examples": [
true
]
},
"requiredToMarkStopAsAttempted": {
"type": "boolean",
"description": "Whether the task is required to mark the stop as attempted.",
"examples": [
true
]
}
},
"description": "A task to be completed at a stop, or at the start or end of a route. Tasks\n may have one or more items for `CHECKBOXES` or `RADIO_BUTTONS`, or may have\n an input for `TEXT_INPUT` or `DECIMAL_INPUT`."
},
"description": "Tasks to complete before starting the route."
},
"status": {
"enum": [
"UNKNOWN",
"STARTED"
],
"type": "string",
"description": "Status indicating whether the route has been started.",
"format": "enum",
"examples": [
"STARTED"
]
},
"updatedStart": {
"type": "string",
"description": "Updated start time for the route. If the route is started, this will be the\n actual start time.",
"format": "date-time",
"examples": [
"2026-03-30T09:05:00Z"
]
},
"scheduledStart": {
"type": "string",
"description": "Scheduled start time for the route (same as `scheduledFor` on the route).",
"format": "date-time",
"examples": [
"2026-03-30T09:00:00Z"
]
},
"photos": {
"type": "array",
"items": {
"title": "StopAttachment",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Attachment ID (e.g. `\"att-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"att-123e4567-e89b-12d3-a456-426614174000"
]
},
"createdAt": {
"type": "string",
"description": "Timestamp when the attachment was created.",
"format": "date-time",
"examples": [
"2026-03-30T09:05:00Z"
]
},
"url": {
"type": "string",
"description": "URL to fetch the attachment.",
"examples": [
"https://example.com/stop-attachment/attachment-2025-06-03-1"
]
}
},
"description": "An attachment to a stop, such as a proof of delivery photo or signature."
},
"description": "Photos for the route start. Photos may be fetched using the URLs on the\n attachments."
}
},
"description": "The start location of a route and any driver tasks to complete before\n beginning the route."
}
],
"description": "Route start address and tasks."
},
"end": {
"allOf": [
{
"title": "RouteEnd",
"type": "object",
"properties": {
"address": {
"allOf": [
{
"title": "Address",
"type": "object",
"properties": {
"address1": {
"type": "string",
"description": "Street address line 1 (e.g. `\"123 Main St\"`).",
"examples": [
"123 Main St"
]
},
"address2": {
"type": "string",
"description": "Street address line 2 (e.g. `\"Apt 101\"`).",
"examples": [
"Apt 3B"
]
},
"city": {
"type": "string",
"description": "City name (e.g. `\"New York\"`).",
"examples": [
"New York"
]
},
"provinceCode": {
"type": "string",
"description": "Province or state as subdivision codes in\n [ISO 3166-2](https://en.wikipedia.org/wiki/ISO_3166-2) format without the\n country prefix (e.g. `\"NY\"` for New York).",
"examples": [
"NY"
]
},
"countryCode": {
"type": "string",
"description": "Country code (e.g. `\"US\"`).",
"examples": [
"US"
]
},
"zip": {
"type": "string",
"description": "Postal or ZIP code (e.g. `\"10001\"`).",
"examples": [
"10001"
]
}
},
"description": "A physical street address."
}
],
"description": "The end address of the route.",
"examples": [
{
"address1": "123 Main St",
"address2": "Apt 3B",
"city": "New York",
"provinceCode": "NY",
"countryCode": "US",
"zip": "10001"
}
]
},
"tasks": {
"type": "array",
"items": {
"title": "Task",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Task ID (e.g. `\"tsk-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"tsk-123e4567-e89b-12d3-a456-426614174000"
]
},
"title": {
"type": "string",
"description": "Task title (e.g. `\"Delivery checklist\"`).",
"examples": [
"Delivery checklist"
]
},
"type": {
"enum": [
"UNKNOWN",
"CHECKBOXES",
"RADIO_BUTTONS",
"TEXT_INPUT",
"DECIMAL_INPUT",
"SCANNER_INPUT"
],
"type": "string",
"description": "Task type.",
"format": "enum",
"examples": [
"TEXT_INPUT"
]
},
"items": {
"type": "array",
"items": {
"title": "TaskItem",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Item ID (e.g. `\"itm-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"itm-123e4567-e89b-12d3-a456-426614174000"
]
},
"title": {
"type": "string",
"description": "Item title (e.g. `\"Pick up package\"`).",
"examples": [
"Pick up package"
]
},
"complete": {
"type": "boolean",
"description": "Whether the item is completed.",
"examples": [
true
]
},
"updatedAt": {
"type": "string",
"description": "Timestamp when the item was last updated.",
"format": "date-time",
"examples": [
"2026-03-30T13:00:00Z"
]
}
},
"description": "An item within a task. For `CHECKBOXES`, each item on a task may be completed\n independently. For `RADIO_BUTTONS`, at most one item will be completed."
},
"description": "Task items (populated for `CHECKBOXES` and `RADIO_BUTTONS`).",
"examples": [
[]
]
},
"input": {
"allOf": [
{
"title": "TaskInput",
"type": "object",
"properties": {
"value": {
"type": "string",
"description": "Input value.",
"examples": [
"020123456789"
]
},
"updatedAt": {
"type": "string",
"description": "Timestamp when the input was last updated.",
"format": "date-time",
"examples": [
"2026-03-30T13:00:00Z"
]
},
"inputMethod": {
"enum": [
"UNKNOWN",
"SCANNED"
],
"type": "string",
"description": "Whether input was scanned (e.g. a scanned barcode)",
"format": "enum",
"examples": [
"SCANNED"
]
}
},
"description": "Captured driver input for a task. The value may be text for `TEXT_INPUT`\n tasks or a string decimal number for `DECIMAL_INPUT` tasks."
}
],
"description": "Task input (populated for `TEXT_INPUT` and `DECIMAL_INPUT`)."
},
"requiredToMarkStopAsDelivered": {
"type": "boolean",
"description": "Whether the task is required to mark the stop as completed. In the case of\n tasks on `RouteStart`, this represents tasks required for starting the\n route. In the case of tasks on `RouteEnd`, this represents tasks required\n for completing the route.",
"examples": [
true
]
},
"requiredToMarkStopAsAttempted": {
"type": "boolean",
"description": "Whether the task is required to mark the stop as attempted.",
"examples": [
true
]
}
},
"description": "A task to be completed at a stop, or at the start or end of a route. Tasks\n may have one or more items for `CHECKBOXES` or `RADIO_BUTTONS`, or may have\n an input for `TEXT_INPUT` or `DECIMAL_INPUT`."
},
"description": "Tasks to complete before finishing the route."
},
"plannedArrival": {
"type": "string",
"description": "Planned arrival time at the end of the route.",
"format": "date-time",
"examples": [
"2026-03-30T17:00:00Z"
]
},
"distanceMeters": {
"type": "number",
"description": "The distance in meters from the previous stop.",
"format": "double",
"examples": [
1234.56
]
},
"updatedArrival": {
"type": "string",
"description": "Estimated arrival time at the end of the route. If the route is completed,\n this will be the actual arrival time.",
"format": "date-time",
"examples": [
"2026-03-30T17:05:00Z"
]
},
"status": {
"enum": [
"UNKNOWN",
"COMPLETED"
],
"type": "string",
"description": "Status indicating whether the route has been completed.",
"format": "enum",
"examples": [
"COMPLETED"
]
},
"photos": {
"type": "array",
"items": {
"title": "StopAttachment",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Attachment ID (e.g. `\"att-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"att-123e4567-e89b-12d3-a456-426614174000"
]
},
"createdAt": {
"type": "string",
"description": "Timestamp when the attachment was created.",
"format": "date-time",
"examples": [
"2026-03-30T09:05:00Z"
]
},
"url": {
"type": "string",
"description": "URL to fetch the attachment.",
"examples": [
"https://example.com/stop-attachment/attachment-2025-06-03-1"
]
}
},
"description": "An attachment to a stop, such as a proof of delivery photo or signature."
},
"description": "Photos for the route end. Photos may be fetched using the URLs on the\n attachments."
}
},
"description": "The end location of a route and any driver tasks to complete after completing\n the route."
}
],
"description": "Route end address and tasks."
},
"stops": {
"type": "array",
"items": {
"title": "RouteStop",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Stop ID (e.g. `\"rst-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"rst-123e4567-e89b-12d3-a456-426614174000"
]
},
"type": {
"enum": [
"UNKNOWN",
"DELIVERY",
"BREAK",
"PICKUP",
"TASK"
],
"type": "string",
"description": "The type of stop (DELIVERY, BREAK, PICKUP, or TASK).",
"format": "enum",
"examples": [
"DELIVERY"
]
},
"deliveryStatus": {
"enum": [
"UNKNOWN",
"DELIVERED",
"OUT_FOR_DELIVERY",
"ATTEMPTED_DELIVERY",
"READY_FOR_DELIVERY"
],
"type": "string",
"description": "The status for DELIVERY, PICKUP, or TASK stops.",
"format": "enum",
"examples": [
"ATTEMPTED_DELIVERY"
]
},
"breakStatus": {
"enum": [
"UNKNOWN",
"COMPLETED"
],
"type": "string",
"description": "The status for BREAK stops.",
"format": "enum",
"examples": [
"COMPLETED"
]
},
"updatedAt": {
"type": "string",
"description": "Timestamp when the stop status was last updated. Note that this timestamp\n corresponds only to major status updates (i.e. stop marked as DELIVERED).\n Minor updates like task completion or adding proof of delivery will not\n advance this timestamp. For those events, use the timestamps on the task or\n proof of delivery attachment.",
"format": "date-time",
"examples": [
"2026-03-30T13:15:00Z"
]
},
"duration": {
"pattern": "^-?(?:0|[1-9][0-9]{0,11})(?:\\.[0-9]{1,9})?s$",
"type": "string",
"description": "Planned duration of the stop in seconds.",
"examples": [
"300s"
]
},
"plannedArrival": {
"type": "string",
"description": "Planned arrival time at the stop.",
"format": "date-time",
"examples": [
"2026-03-30T13:00:00Z"
]
},
"note": {
"type": "string",
"description": "Top-level note for the stop, as entered manually by route planners,\n inherited from a saved or imported stop, or set by order import automation\n rules.",
"examples": [
"Leave at door."
]
},
"address": {
"allOf": [
{
"title": "Address",
"type": "object",
"properties": {
"address1": {
"type": "string",
"description": "Street address line 1 (e.g. `\"123 Main St\"`).",
"examples": [
"123 Main St"
]
},
"address2": {
"type": "string",
"description": "Street address line 2 (e.g. `\"Apt 101\"`).",
"examples": [
"Apt 3B"
]
},
"city": {
"type": "string",
"description": "City name (e.g. `\"New York\"`).",
"examples": [
"New York"
]
},
"provinceCode": {
"type": "string",
"description": "Province or state as subdivision codes in\n [ISO 3166-2](https://en.wikipedia.org/wiki/ISO_3166-2) format without the\n country prefix (e.g. `\"NY\"` for New York).",
"examples": [
"NY"
]
},
"countryCode": {
"type": "string",
"description": "Country code (e.g. `\"US\"`).",
"examples": [
"US"
]
},
"zip": {
"type": "string",
"description": "Postal or ZIP code (e.g. `\"10001\"`).",
"examples": [
"10001"
]
}
},
"description": "A physical street address."
}
],
"description": "Delivery address for the stop.",
"examples": [
{
"address1": "123 Main St",
"address2": "Apt 3B",
"city": "New York",
"provinceCode": "NY",
"countryCode": "US",
"zip": "10001"
}
]
},
"contact": {
"allOf": [
{
"title": "Contact",
"type": "object",
"properties": {
"firstName": {
"type": "string",
"description": "First name (e.g. `\"John\"`).",
"examples": [
"John"
]
},
"lastName": {
"type": "string",
"description": "Last name (e.g. `\"Doe\"`).",
"examples": [
"Doe"
]
},
"company": {
"type": "string",
"description": "Company name (e.g. `\"Roundtrip Systems Inc\"`).",
"examples": [
"Roundtrip Systems Inc"
]
},
"phone": {
"type": "string",
"description": "Phone number in [E.164 format](https://en.wikipedia.org/wiki/E.164) (e.g.\n `\"+14265551000\"`).",
"examples": [
"+14265551000"
]
},
"email": {
"type": "string",
"description": "Email address (e.g. `\"john.doe@roundtrip.ai\"`)",
"examples": [
"john.doe@roundtrip.ai"
]
}
},
"description": "Contact information for a person or company."
}
],
"description": "Contact information for the stop delivery recipient.",
"examples": [
{
"firstName": "John",
"lastName": "Doe",
"company": "Roundtrip Systems Inc",
"phone": "+14265551000",
"email": "john.doe@roundtrip.ai"
}
]
},
"plannedCoordinates": {
"allOf": [
{
"type": "object",
"properties": {
"latitude": {
"type": "number",
"description": "The latitude in degrees. It must be in the range [-90.0, +90.0].",
"format": "double"
},
"longitude": {
"type": "number",
"description": "The longitude in degrees. It must be in the range [-180.0, +180.0].",
"format": "double"
}
},
"description": "An object that represents a latitude/longitude pair. This is expressed as a\n pair of doubles to represent degrees latitude and degrees longitude. Unless\n specified otherwise, this must conform to the\n WGS84\n standard. Values must be within normalized ranges."
}
],
"description": "Planned coordinates for the stop.",
"examples": [
{
"latitude": 40.7128,
"longitude": -74.006
}
]
},
"items": {
"type": "array",
"items": {
"title": "StopItem",
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "Item name (e.g. `\"Bananas\"`).",
"examples": [
"Bananas"
]
},
"quantity": {
"type": "integer",
"description": "Quantity of the item (e.g. `5`).",
"format": "int32",
"examples": [
5
]
},
"grams": {
"type": "integer",
"description": "Weight of the item in grams (e.g. `500`).",
"format": "int32",
"examples": [
500
]
},
"sku": {
"type": "string",
"description": "Stock keeping unit (e.g. `\"BANANA-001\"`).",
"examples": [
"BANANA-001"
]
}
},
"description": "An item to be delivered at a stop."
},
"description": "Items to deliver at the stop."
},
"source": {
"enum": [
"UNKNOWN",
"SHOPIFY_ORDER",
"SAVED_STOP",
"IMPORTED_STOP"
],
"type": "string",
"description": "The source of the stop, which may be populated for `DELIVERY` stops. The\n source can be a `SHOPIFY_ORDER`, an EasyRoutes `SAVED_STOP`, or an\n `IMPORTED_STOP` from an external source (such as CSV file).",
"format": "enum",
"examples": [
"IMPORTED_STOP"
]
},
"shopifyOrderId": {
"type": "string",
"description": "The Shopify order ID, populated when the stop source is a `SHOPIFY_ORDER`.",
"examples": [
"6229749334323"
]
},
"savedStopId": {
"type": "string",
"description": "The saved stop ID, populated when the stop source is a `SAVED_STOP`.",
"examples": [
"sst-123e4567-e89b-12d3-a456-426614174000"
]
},
"deliveredCoordinates": {
"allOf": [
{
"type": "object",
"properties": {
"latitude": {
"type": "number",
"description": "The latitude in degrees. It must be in the range [-90.0, +90.0].",
"format": "double"
},
"longitude": {
"type": "number",
"description": "The longitude in degrees. It must be in the range [-180.0, +180.0].",
"format": "double"
}
},
"description": "An object that represents a latitude/longitude pair. This is expressed as a\n pair of doubles to represent degrees latitude and degrees longitude. Unless\n specified otherwise, this must conform to the\n WGS84\n standard. Values must be within normalized ranges."
}
],
"description": "Delivered coordinates for the stop."
},
"proofOfDeliveryNote": {
"type": "string",
"description": "Proof of delivery note for the stop.",
"examples": [
"Left at door."
]
},
"proofOfDeliveryPhotos": {
"type": "array",
"items": {
"title": "StopAttachment",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Attachment ID (e.g. `\"att-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"att-123e4567-e89b-12d3-a456-426614174000"
]
},
"createdAt": {
"type": "string",
"description": "Timestamp when the attachment was created.",
"format": "date-time",
"examples": [
"2026-03-30T09:05:00Z"
]
},
"url": {
"type": "string",
"description": "URL to fetch the attachment.",
"examples": [
"https://example.com/stop-attachment/attachment-2025-06-03-1"
]
}
},
"description": "An attachment to a stop, such as a proof of delivery photo or signature."
},
"description": "Proof of delivery photos for the stop. Photos may be fetched using the URLs\n on the attachments."
},
"proofOfDeliverySignatures": {
"type": "array",
"items": {
"title": "StopAttachment",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Attachment ID (e.g. `\"att-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"att-123e4567-e89b-12d3-a456-426614174000"
]
},
"createdAt": {
"type": "string",
"description": "Timestamp when the attachment was created.",
"format": "date-time",
"examples": [
"2026-03-30T09:05:00Z"
]
},
"url": {
"type": "string",
"description": "URL to fetch the attachment.",
"examples": [
"https://example.com/stop-attachment/attachment-2025-06-03-1"
]
}
},
"description": "An attachment to a stop, such as a proof of delivery photo or signature."
},
"description": "Proof of delivery signatures for the stop. Signatures may be fetched using\n the URLs on the attachments."
},
"tasks": {
"type": "array",
"items": {
"title": "Task",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Task ID (e.g. `\"tsk-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"tsk-123e4567-e89b-12d3-a456-426614174000"
]
},
"title": {
"type": "string",
"description": "Task title (e.g. `\"Delivery checklist\"`).",
"examples": [
"Delivery checklist"
]
},
"type": {
"enum": [
"UNKNOWN",
"CHECKBOXES",
"RADIO_BUTTONS",
"TEXT_INPUT",
"DECIMAL_INPUT",
"SCANNER_INPUT"
],
"type": "string",
"description": "Task type.",
"format": "enum",
"examples": [
"TEXT_INPUT"
]
},
"items": {
"type": "array",
"items": {
"title": "TaskItem",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Item ID (e.g. `\"itm-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"itm-123e4567-e89b-12d3-a456-426614174000"
]
},
"title": {
"type": "string",
"description": "Item title (e.g. `\"Pick up package\"`).",
"examples": [
"Pick up package"
]
},
"complete": {
"type": "boolean",
"description": "Whether the item is completed.",
"examples": [
true
]
},
"updatedAt": {
"type": "string",
"description": "Timestamp when the item was last updated.",
"format": "date-time",
"examples": [
"2026-03-30T13:00:00Z"
]
}
},
"description": "An item within a task. For `CHECKBOXES`, each item on a task may be completed\n independently. For `RADIO_BUTTONS`, at most one item will be completed."
},
"description": "Task items (populated for `CHECKBOXES` and `RADIO_BUTTONS`).",
"examples": [
[]
]
},
"input": {
"allOf": [
{
"title": "TaskInput",
"type": "object",
"properties": {
"value": {
"type": "string",
"description": "Input value.",
"examples": [
"020123456789"
]
},
"updatedAt": {
"type": "string",
"description": "Timestamp when the input was last updated.",
"format": "date-time",
"examples": [
"2026-03-30T13:00:00Z"
]
},
"inputMethod": {
"enum": [
"UNKNOWN",
"SCANNED"
],
"type": "string",
"description": "Whether input was scanned (e.g. a scanned barcode)",
"format": "enum",
"examples": [
"SCANNED"
]
}
},
"description": "Captured driver input for a task. The value may be text for `TEXT_INPUT`\n tasks or a string decimal number for `DECIMAL_INPUT` tasks."
}
],
"description": "Task input (populated for `TEXT_INPUT` and `DECIMAL_INPUT`)."
},
"requiredToMarkStopAsDelivered": {
"type": "boolean",
"description": "Whether the task is required to mark the stop as completed. In the case of\n tasks on `RouteStart`, this represents tasks required for starting the\n route. In the case of tasks on `RouteEnd`, this represents tasks required\n for completing the route.",
"examples": [
true
]
},
"requiredToMarkStopAsAttempted": {
"type": "boolean",
"description": "Whether the task is required to mark the stop as attempted.",
"examples": [
true
]
}
},
"description": "A task to be completed at a stop, or at the start or end of a route. Tasks\n may have one or more items for `CHECKBOXES` or `RADIO_BUTTONS`, or may have\n an input for `TEXT_INPUT` or `DECIMAL_INPUT`."
},
"description": "Driver tasks for the stop, including completed items and any input from the\n driver."
},
"priority": {
"maximum": 10,
"type": "integer",
"description": "Priority of the stop for route planning. The valid range for stop priority\n is between `1` (low) and `10` (high), with default priority corresponding\n to a value of `5`. A priority value of `0` is considered unset and is\n treated the same as \"default\" priority. Stops with higher priority will be\n preferred when generating routes with constraints.",
"format": "int32",
"examples": [
8
]
},
"importedStopId": {
"type": "string",
"description": "The imported stop ID, populated when the stop source is `IMPORTED_STOP`.",
"examples": [
"ist-123e4567-e89b-12d3-a456-426614174000"
]
},
"orderName": {
"type": "string",
"description": "The name of the order associated with the stop. For Shopify orders, the\n name is generated by combining the `orderNumber` property with the order\n prefix and suffix that are set in the merchant's general settings. For\n EasyRoutes imported orders, this field is populated with the order name\n provided on import.",
"examples": [
"#1234"
]
},
"distanceMeters": {
"type": "number",
"description": "The distance in meters from the previous stop.",
"format": "double",
"examples": [
123.45
]
},
"updatedArrival": {
"type": "string",
"description": "Estimated arrival time at the stop. If the stop is completed, this will be\n the actual arrival time.",
"format": "date-time",
"examples": [
"2026-03-30T13:05:00Z"
]
},
"timeWindows": {
"type": "array",
"items": {
"title": "TimeWindow",
"type": "object",
"properties": {
"start": {
"allOf": [
{
"title": "TimeOfDay",
"type": "object",
"properties": {
"hours": {
"maximum": 23,
"type": "integer",
"description": "Hours of day in 24 hour format. Must be from 0 to 23.",
"format": "int32",
"examples": [
13
]
},
"minutes": {
"maximum": 59,
"type": "integer",
"description": "Minutes of hour of day. Must be from 0 to 59.",
"format": "int32",
"examples": [
37
]
},
"seconds": {
"maximum": 59,
"type": "integer",
"description": "Seconds of minutes of the time. Must be from 0 to 59.",
"format": "int32",
"examples": [
16
]
}
},
"description": "A time of day, independent of a particular date or timezone."
}
],
"description": "The start time of the time window (optional)."
},
"end": {
"allOf": [
{
"title": "TimeOfDay",
"type": "object",
"properties": {
"hours": {
"maximum": 23,
"type": "integer",
"description": "Hours of day in 24 hour format. Must be from 0 to 23.",
"format": "int32",
"examples": [
13
]
},
"minutes": {
"maximum": 59,
"type": "integer",
"description": "Minutes of hour of day. Must be from 0 to 59.",
"format": "int32",
"examples": [
37
]
},
"seconds": {
"maximum": 59,
"type": "integer",
"description": "Seconds of minutes of the time. Must be from 0 to 59.",
"format": "int32",
"examples": [
16
]
}
},
"description": "A time of day, independent of a particular date or timezone."
}
],
"description": "The end time of the time window (optional)."
}
},
"description": "A time window for a stop. The time window may be open-ended, but one or both\n of the start and end times should be provided. The end time must be >= the\n start time."
},
"description": "The time window for the stop. Note that we currently support at most one\n time window but may support multiple time windows in the future.",
"examples": [
[
{
"start": {
"hours": 9
},
"end": {
"hours": 17
}
}
]
]
},
"deliveryDate": {
"allOf": [
{
"title": "Date",
"required": [
"year",
"month",
"day"
],
"type": "object",
"properties": {
"year": {
"maximum": 9999,
"minimum": 1,
"type": "integer",
"description": "Year of the date. Must be from 1 to 9999.",
"format": "int32",
"examples": [
2019
]
},
"month": {
"maximum": 12,
"minimum": 1,
"type": "integer",
"description": "Month of a year. Must be from 1 to 12.",
"format": "int32",
"examples": [
11
]
},
"day": {
"maximum": 31,
"minimum": 1,
"type": "integer",
"description": "Day of a month. Must be from 1 to 31.",
"format": "int32",
"examples": [
15
]
}
},
"description": "A date in year-month-day format."
}
],
"description": "The planned delivery date for the stop.",
"examples": [
{
"year": 2025,
"month": 12,
"day": 16
}
]
},
"attributes": {
"type": "array",
"items": {
"title": "Attribute",
"type": "object",
"properties": {
"key": {
"type": "string",
"description": "Attribute key. Must be non-empty.",
"examples": [
"delivery_date"
]
},
"value": {
"type": "string",
"description": "Attribute value.",
"examples": [
"2025-12-16"
]
}
},
"description": "A key-value pair for storing additional information on a stop, such as order\n details, delivery instructions, or custom fields."
},
"description": "Additional attributes for the stop. Attributes are key-value pairs for\n storing additional structured data on stops. These may be populated from\n the Shopify order or set on import.",
"examples": [
[
{
"key": "color",
"value": "blue"
}
]
]
},
"clientStopId": {
"type": "string",
"description": "The client-provided ID associated with the stop, if provided on import.",
"examples": [
"test-order-1234"
]
},
"tags": {
"type": "array",
"items": {
"type": "string"
},
"description": "The tags for the stop. Tags are used to categorize stops and can be used\n for filtering and grouping stops in the EasyRoutes web app. These may be\n populated from the Shopify order or set on import.",
"examples": [
[
"foo",
"bar"
]
]
},
"attemptedReason": {
"enum": [
"UNKNOWN",
"NOT_AVAILABLE",
"ACCESS_DENIED",
"INCORRECT_ADDRESS",
"SAFE_PLACE_UNAVAILABLE",
"REFUSED",
"EXTERNAL",
"INCORRECT_ITEMS",
"OTHER",
"CANCELED"
],
"type": "string",
"description": "The reason for marking the stop as attempted. This is only populated when\n `deliveryStatus = ATTEMPTED_DELIVERY`.",
"format": "enum",
"examples": [
"NOT_AVAILABLE"
]
},
"attemptedNote": {
"type": "string",
"description": "Optional note related to the reason for marking the stop as attempted. This\n is optionally populated when `deliveryStatus = ATTEMPTED_DELIVERY`.",
"examples": [
"Customer did not answer the door."
]
},
"customerRating": {
"allOf": [
{
"title": "CustomerRating",
"type": "object",
"properties": {
"rating": {
"maximum": 5,
"minimum": 1,
"type": "integer",
"description": "Rating from 1-5",
"format": "int32",
"examples": [
5
]
},
"comment": {
"type": "string",
"description": "Customer comment related to rating",
"examples": [
"Excellent delivery"
]
},
"createdAt": {
"type": "string",
"description": "Timestamp when rating was left by customer.",
"format": "date-time",
"examples": [
"2026-03-30T18:00:00Z"
]
}
},
"description": "Customer rating and feedback left on a stop."
}
],
"description": "Rating left by customer. This can only be populated once `deliveryStatus =\n DELIVERED`."
},
"customSignatureDisclosure": {
"type": "string",
"description": "Optional custom signature disclosure that is shown to customers in the\n driver app.",
"examples": [
"I acknowledge that I have received this delivery."
]
},
"shopifyOrder": {
"allOf": [
{
"title": "ShopifyOrder",
"type": "object",
"properties": {
"orderNote": {
"type": "string",
"description": "The Shopify order note.",
"examples": [
"Customer has paid."
]
},
"customerNote": {
"type": "string",
"description": "The Shopify customer note for the order.",
"examples": [
"Leave at door."
]
}
},
"description": "Shopify-specific information for a RouteStop."
}
],
"description": "Information from the associated Shopify order, if applicable. Populated if\n stop source is `SHOPIFY_ORDER`"
},
"proofOfDeliveryBarcodes": {
"type": "array",
"items": {
"title": "ScannedBarcode",
"type": "object",
"properties": {
"value": {
"type": "string",
"description": "Barcode value (e.g. `\"123456789012\"`).",
"examples": [
"123456789012"
]
},
"createdAt": {
"type": "string",
"description": "Timestamp when the barcode was scanned.",
"format": "date-time",
"examples": [
"2026-03-30T13:10:00Z"
]
}
},
"description": "A proof of delivery barcode scanned at a stop."
},
"description": "Proof of delivery barcodes scanned at the stop."
},
"proofOfDeliveryBarcodeIssues": {
"type": "array",
"items": {
"title": "ScannedBarcodeIssue",
"type": "object",
"properties": {
"reason": {
"enum": [
"UNKNOWN",
"ITEM_MISSING",
"NOT_SCANNABLE",
"INCORRECT"
],
"type": "string",
"description": "The reported reason for the barcode issue.",
"format": "enum",
"examples": [
"ITEM_MISSING"
]
},
"note": {
"type": "string",
"description": "Optional note related to the reason for reporting a barcode issue.",
"examples": [
"Item was not packed."
]
},
"createdAt": {
"type": "string",
"description": "Timestamp when the issue was reported.",
"format": "date-time",
"examples": [
"2026-03-30T13:10:00Z"
]
}
},
"description": "A reported issue related to scanning barcodes at a stop."
},
"description": "Proof of delivery barcode issues reported at the stop."
},
"orderReferenceUrl": {
"type": "string",
"description": "A reference URL for the order associated with the stop (e.g. a link to the\n order in your order management system). Must be a valid HTTPS URL. This\n field can only be populated for imported stops.",
"examples": [
"https://orders.example.com/orders/148977776"
]
}
},
"description": "A stop on a route. A stop may correspond to a delivery or a driver break as\n determined by the type. A delivery stop will have location and contact\n information, items to deliver, optional order details, status, arrival time\n and stop duration, driver tasks and any proof of delivery information. A\n break stop will have start time and duration, and status."
},
"description": "Route stops. See RouteStop for stop fields."
},
"createdAt": {
"type": "string",
"description": "Timestamp when the route was created.",
"format": "date-time",
"examples": [
"2026-03-29T08:00:00Z"
]
},
"updatedAt": {
"type": "string",
"description": "Timestamp when the route was last updated (by the planner).",
"format": "date-time",
"examples": [
"2026-03-30T13:15:00Z"
]
},
"archivedAt": {
"type": "string",
"description": "Timestamp when the route was archived.",
"format": "date-time",
"examples": [
"2026-04-05T00:00:00Z"
]
},
"scheduledFor": {
"type": "string",
"description": "Timestamp when the route is scheduled for.",
"format": "date-time",
"examples": [
"2026-03-30T09:00:00Z"
]
},
"totalDistanceMeters": {
"type": "number",
"description": "The distance in meters for the entire route.",
"format": "double",
"examples": [
2387.2
]
},
"totalItemQuantity": {
"type": "integer",
"description": "The total quantity of items to deliver on the route.",
"format": "int32",
"examples": [
50
]
},
"totalItemGrams": {
"type": "string",
"description": "The total weight in grams for the items on the route.",
"examples": [
"6000"
]
},
"optimized": {
"type": "boolean",
"description": "Whether the route has been optimized. Adding or removing stops, reordering\n stops, or changing route options generally set this field to false until\n the route is reoptimized.",
"examples": [
true
]
},
"dispatchedUntil": {
"type": "string",
"description": "Timestamp until which the route is dispatched and accessible in the driver\n app.",
"format": "date-time",
"examples": [
"2026-03-30T20:00:00Z"
]
},
"note": {
"type": "string",
"description": "Top-level note for the route, as entered manually by route planners.",
"examples": [
"Fragile items."
]
},
"tags": {
"type": "array",
"items": {
"type": "string"
},
"description": "The tags for the route. Tags are used to categorize routes and can be\n used for filtering and grouping routes in the EasyRoutes web app.",
"examples": [
[
"foo",
"bar"
]
]
},
"defaultStopDuration": {
"pattern": "^-?(?:0|[1-9][0-9]{0,11})(?:\\.[0-9]{1,9})?s$",
"type": "string",
"description": "The default duration for stops on the route. Used to estimate arrival\n times for stops that do not have their own duration specified.\n Specified as a duration string in the format \"300s\" for 5 minutes, \"60s\"\n for 1 minute, etc.",
"examples": [
"300s"
]
},
"maxDuration": {
"pattern": "^-?(?:0|[1-9][0-9]{0,11})(?:\\.[0-9]{1,9})?s$",
"type": "string",
"description": "The maximum duration of the route. Specified as a duration string in the\n format \"3600s\" for 1 hour, \"7200s\" for 2 hours, etc.",
"examples": [
"28800s"
]
},
"maxStops": {
"type": "integer",
"description": "The maximum number of stops on the route.",
"format": "int32",
"examples": [
50
]
},
"maxItemCount": {
"type": "integer",
"description": "The maximum total item count across all stops on the route.",
"format": "int32",
"examples": [
200
]
},
"maxKilograms": {
"type": "number",
"description": "The maximum total weight in kilograms across all stops on the route.",
"format": "double",
"examples": [
500
]
},
"avoidTolls": {
"type": "boolean",
"description": "Whether to avoid toll roads during optimization.",
"examples": [
true
]
},
"avoidUTurns": {
"type": "boolean",
"description": "Whether to avoid U-turns during optimization.",
"examples": [
true
]
},
"speedFactor": {
"type": "number",
"description": "A speed factor for the route used during optimization to adjust estimated\n travel times. A value of 1.0 represents normal speed. Values less than 1.0\n indicate slower travel (e.g. 0.5 = half speed), and values greater than\n 1.0 indicate faster travel (e.g. 1.5 = 50% faster). Must be between 0.1\n and 1.9. A value of 0 (or unset) uses the default speed.",
"format": "double",
"examples": [
0.8
]
},
"vehicle": {
"allOf": [
{
"title": "Vehicle",
"required": [
"id"
],
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Vehicle ID.",
"examples": [
"veh-123e4567-e89b-12d3-a456-426614174000"
]
},
"name": {
"type": "string",
"description": "Vehicle name.",
"examples": [
"Delivery Van 1"
]
},
"make": {
"type": "string",
"description": "Vehicle make.",
"examples": [
"Ford"
]
},
"model": {
"type": "string",
"description": "Vehicle model.",
"examples": [
"Transit"
]
},
"year": {
"type": "integer",
"description": "Vehicle model year.",
"format": "int32",
"examples": [
2023
]
},
"type": {
"enum": [
"UNKNOWN",
"CAR",
"CARGO_VAN",
"PICKUP_TRUCK",
"BOX_TRUCK",
"MOTORCYCLE",
"BICYCLE",
"DRONE",
"OTHER"
],
"type": "string",
"description": "Vehicle type.",
"format": "enum",
"examples": [
"CARGO_VAN"
]
},
"vin": {
"type": "string",
"description": "Vehicle Identification Number.",
"examples": [
"1FTBW2CM5NKA12345"
]
},
"license": {
"type": "string",
"description": "Vehicle license plate.",
"examples": [
"ABC-1234"
]
},
"isArchived": {
"type": "boolean",
"description": "Whether the vehicle is archived.",
"examples": [
false
]
},
"createdTimestamp": {
"type": "string",
"description": "Timestamp when the vehicle was created.",
"format": "date-time",
"examples": [
"2026-07-30T12:00:00Z"
]
}
},
"description": "A vehicle that can be assigned to a route."
}
],
"description": "Assigned vehicle for the route."
}
},
"description": "A route of stops, optionally with an assigned driver."
}
}
}
},
"default": {
"description": "Default error response",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"code": {
"type": "integer",
"description": "The status code, which should be an enum value of [google.rpc.Code][google.rpc.Code].",
"format": "int32"
},
"message": {
"type": "string",
"description": "A developer-facing error message, which should be in English. Any user-facing error message should be localized and sent in the [google.rpc.Status.details][google.rpc.Status.details] field, or localized by the client."
},
"details": {
"type": "array",
"items": {
"type": "object",
"properties": {
"@type": {
"type": "string",
"description": "The type of the serialized message."
}
},
"additionalProperties": true,
"description": "Contains an arbitrary serialized message along with a @type that describes the type of the serialized message."
},
"description": "A list of messages that carry the error details. There is a common set of message types for APIs to use."
}
},
"description": "The `Status` type defines a logical error model that is suitable for different programming environments, including REST APIs and RPC APIs. It is used by [gRPC](https://github.com/grpc). Each `Status` message contains three pieces of data: error code, error message, and error details. You can find out more about this error model and how to work with it in the [API Design Guide](https://cloud.google.com/apis/design/errors)."
}
}
}
}
},
"security": [
{
"bearerAuth": []
}
],
"components": {
"securitySchemes": {
"bearerAuth": {
"type": "http",
"description": "Access token from `/authenticate`",
"scheme": "bearer",
"bearerFormat": "JWT"
}
}
}
}
```
# Dispatch route (https://docs.roundtrip.ai/docs/api-reference/routes/post-routes-routeId-dispatch)
POST /routes/{routeId}/dispatch
Dispatches a route, making it visible on the EasyRoutes Driver App. The
dispatch duration is determined by the shop's configured route expiry
setting. If the route is already dispatched, this will result in a no-op.
Shopify order updates configured in the app on dispatch are not performed
by this endpoint - use ResyncRouteOrders beforehand if you need the route's
orders refreshed from Shopify before dispatching. The response will
include the updated route.
## OpenAPI specification
```json
{
"servers": [
{
"url": "https://easyroutes.roundtrip.ai/api/2024-07"
}
],
"tags": [
"Routes"
],
"summary": "Dispatch route",
"description": "Dispatches a route, making it visible on the EasyRoutes Driver App. The\n dispatch duration is determined by the shop's configured route expiry\n setting. If the route is already dispatched, this will result in a no-op.\n Shopify order updates configured in the app on dispatch are not performed\n by this endpoint - use ResyncRouteOrders beforehand if you need the route's\n orders refreshed from Shopify before dispatching. The response will\n include the updated route.",
"operationId": "DispatchRoute",
"parameters": [
{
"name": "routeId",
"in": "path",
"description": "The ID of the route to dispatch.",
"required": true,
"schema": {
"type": "string",
"examples": [
"rte-123e4567-e89b-12d3-a456-426614174000"
]
}
},
{
"name": "Idempotency-Key",
"in": "header",
"description": "A unique key for safely retrying this operation. For more information read [our guide](https://docs.roundtrip.ai/docs/concepts/idempotency.md).",
"schema": {
"maxLength": 255,
"minLength": 1,
"type": "string"
},
"examples": {
"default": {
"value": "550e8400-e29b-41d4-a716-446655440000"
}
}
}
],
"responses": {
"200": {
"description": "OK",
"headers": {
"Idempotency-Key": {
"description": "The idempotency key associated with the response.",
"schema": {
"type": "string"
}
},
"Idempotency-Replayed": {
"description": "Whether the response was replayed from a previous request.",
"schema": {
"type": "boolean"
}
}
},
"content": {
"application/json": {
"schema": {
"title": "Route",
"required": [
"id",
"name",
"stops",
"createdAt",
"updatedAt",
"totalDistanceMeters",
"totalItemQuantity",
"totalItemGrams",
"optimized"
],
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Route ID (e.g. `\"rte-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"rte-123e4567-e89b-12d3-a456-426614174000"
]
},
"name": {
"type": "string",
"description": "Route name (e.g. `\"Morning route\"`).",
"examples": [
"Morning route"
]
},
"driver": {
"allOf": [
{
"title": "Driver",
"required": [
"id"
],
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Driver ID (e.g. `\"drv-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"drv-123e4567-e89b-12d3-a456-426614174000"
]
},
"firstName": {
"type": "string",
"description": "Driver first name (e.g. `\"John\"`).",
"examples": [
"John"
]
},
"lastName": {
"type": "string",
"description": "Driver last name (e.g. `\"Doe\"`).",
"examples": [
"Doe"
]
},
"phone": {
"type": "string",
"description": "Driver phone number in [E.164 format](https://en.wikipedia.org/wiki/E.164)\n (e.g. `\"+14265551000\"`).",
"examples": [
"+14265551000"
]
},
"status": {
"enum": [
"UNKNOWN",
"ACTIVE",
"INACTIVE",
"ARCHIVED"
],
"type": "string",
"description": "Shop driver status. (e.g. `ACTIVE`).",
"format": "enum",
"examples": [
"ACTIVE"
]
}
},
"description": "A driver who is assigned to a route."
}
],
"description": "Assigned driver for the route."
},
"start": {
"allOf": [
{
"title": "RouteStart",
"type": "object",
"properties": {
"address": {
"allOf": [
{
"title": "Address",
"type": "object",
"properties": {
"address1": {
"type": "string",
"description": "Street address line 1 (e.g. `\"123 Main St\"`).",
"examples": [
"123 Main St"
]
},
"address2": {
"type": "string",
"description": "Street address line 2 (e.g. `\"Apt 101\"`).",
"examples": [
"Apt 3B"
]
},
"city": {
"type": "string",
"description": "City name (e.g. `\"New York\"`).",
"examples": [
"New York"
]
},
"provinceCode": {
"type": "string",
"description": "Province or state as subdivision codes in\n [ISO 3166-2](https://en.wikipedia.org/wiki/ISO_3166-2) format without the\n country prefix (e.g. `\"NY\"` for New York).",
"examples": [
"NY"
]
},
"countryCode": {
"type": "string",
"description": "Country code (e.g. `\"US\"`).",
"examples": [
"US"
]
},
"zip": {
"type": "string",
"description": "Postal or ZIP code (e.g. `\"10001\"`).",
"examples": [
"10001"
]
}
},
"description": "A physical street address."
}
],
"description": "The start address of the route.",
"examples": [
{
"address1": "123 Main St",
"address2": "Apt 3B",
"city": "New York",
"provinceCode": "NY",
"countryCode": "US",
"zip": "10001"
}
]
},
"tasks": {
"type": "array",
"items": {
"title": "Task",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Task ID (e.g. `\"tsk-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"tsk-123e4567-e89b-12d3-a456-426614174000"
]
},
"title": {
"type": "string",
"description": "Task title (e.g. `\"Delivery checklist\"`).",
"examples": [
"Delivery checklist"
]
},
"type": {
"enum": [
"UNKNOWN",
"CHECKBOXES",
"RADIO_BUTTONS",
"TEXT_INPUT",
"DECIMAL_INPUT",
"SCANNER_INPUT"
],
"type": "string",
"description": "Task type.",
"format": "enum",
"examples": [
"TEXT_INPUT"
]
},
"items": {
"type": "array",
"items": {
"title": "TaskItem",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Item ID (e.g. `\"itm-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"itm-123e4567-e89b-12d3-a456-426614174000"
]
},
"title": {
"type": "string",
"description": "Item title (e.g. `\"Pick up package\"`).",
"examples": [
"Pick up package"
]
},
"complete": {
"type": "boolean",
"description": "Whether the item is completed.",
"examples": [
true
]
},
"updatedAt": {
"type": "string",
"description": "Timestamp when the item was last updated.",
"format": "date-time",
"examples": [
"2026-03-30T13:00:00Z"
]
}
},
"description": "An item within a task. For `CHECKBOXES`, each item on a task may be completed\n independently. For `RADIO_BUTTONS`, at most one item will be completed."
},
"description": "Task items (populated for `CHECKBOXES` and `RADIO_BUTTONS`).",
"examples": [
[]
]
},
"input": {
"allOf": [
{
"title": "TaskInput",
"type": "object",
"properties": {
"value": {
"type": "string",
"description": "Input value.",
"examples": [
"020123456789"
]
},
"updatedAt": {
"type": "string",
"description": "Timestamp when the input was last updated.",
"format": "date-time",
"examples": [
"2026-03-30T13:00:00Z"
]
},
"inputMethod": {
"enum": [
"UNKNOWN",
"SCANNED"
],
"type": "string",
"description": "Whether input was scanned (e.g. a scanned barcode)",
"format": "enum",
"examples": [
"SCANNED"
]
}
},
"description": "Captured driver input for a task. The value may be text for `TEXT_INPUT`\n tasks or a string decimal number for `DECIMAL_INPUT` tasks."
}
],
"description": "Task input (populated for `TEXT_INPUT` and `DECIMAL_INPUT`)."
},
"requiredToMarkStopAsDelivered": {
"type": "boolean",
"description": "Whether the task is required to mark the stop as completed. In the case of\n tasks on `RouteStart`, this represents tasks required for starting the\n route. In the case of tasks on `RouteEnd`, this represents tasks required\n for completing the route.",
"examples": [
true
]
},
"requiredToMarkStopAsAttempted": {
"type": "boolean",
"description": "Whether the task is required to mark the stop as attempted.",
"examples": [
true
]
}
},
"description": "A task to be completed at a stop, or at the start or end of a route. Tasks\n may have one or more items for `CHECKBOXES` or `RADIO_BUTTONS`, or may have\n an input for `TEXT_INPUT` or `DECIMAL_INPUT`."
},
"description": "Tasks to complete before starting the route."
},
"status": {
"enum": [
"UNKNOWN",
"STARTED"
],
"type": "string",
"description": "Status indicating whether the route has been started.",
"format": "enum",
"examples": [
"STARTED"
]
},
"updatedStart": {
"type": "string",
"description": "Updated start time for the route. If the route is started, this will be the\n actual start time.",
"format": "date-time",
"examples": [
"2026-03-30T09:05:00Z"
]
},
"scheduledStart": {
"type": "string",
"description": "Scheduled start time for the route (same as `scheduledFor` on the route).",
"format": "date-time",
"examples": [
"2026-03-30T09:00:00Z"
]
},
"photos": {
"type": "array",
"items": {
"title": "StopAttachment",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Attachment ID (e.g. `\"att-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"att-123e4567-e89b-12d3-a456-426614174000"
]
},
"createdAt": {
"type": "string",
"description": "Timestamp when the attachment was created.",
"format": "date-time",
"examples": [
"2026-03-30T09:05:00Z"
]
},
"url": {
"type": "string",
"description": "URL to fetch the attachment.",
"examples": [
"https://example.com/stop-attachment/attachment-2025-06-03-1"
]
}
},
"description": "An attachment to a stop, such as a proof of delivery photo or signature."
},
"description": "Photos for the route start. Photos may be fetched using the URLs on the\n attachments."
}
},
"description": "The start location of a route and any driver tasks to complete before\n beginning the route."
}
],
"description": "Route start address and tasks."
},
"end": {
"allOf": [
{
"title": "RouteEnd",
"type": "object",
"properties": {
"address": {
"allOf": [
{
"title": "Address",
"type": "object",
"properties": {
"address1": {
"type": "string",
"description": "Street address line 1 (e.g. `\"123 Main St\"`).",
"examples": [
"123 Main St"
]
},
"address2": {
"type": "string",
"description": "Street address line 2 (e.g. `\"Apt 101\"`).",
"examples": [
"Apt 3B"
]
},
"city": {
"type": "string",
"description": "City name (e.g. `\"New York\"`).",
"examples": [
"New York"
]
},
"provinceCode": {
"type": "string",
"description": "Province or state as subdivision codes in\n [ISO 3166-2](https://en.wikipedia.org/wiki/ISO_3166-2) format without the\n country prefix (e.g. `\"NY\"` for New York).",
"examples": [
"NY"
]
},
"countryCode": {
"type": "string",
"description": "Country code (e.g. `\"US\"`).",
"examples": [
"US"
]
},
"zip": {
"type": "string",
"description": "Postal or ZIP code (e.g. `\"10001\"`).",
"examples": [
"10001"
]
}
},
"description": "A physical street address."
}
],
"description": "The end address of the route.",
"examples": [
{
"address1": "123 Main St",
"address2": "Apt 3B",
"city": "New York",
"provinceCode": "NY",
"countryCode": "US",
"zip": "10001"
}
]
},
"tasks": {
"type": "array",
"items": {
"title": "Task",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Task ID (e.g. `\"tsk-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"tsk-123e4567-e89b-12d3-a456-426614174000"
]
},
"title": {
"type": "string",
"description": "Task title (e.g. `\"Delivery checklist\"`).",
"examples": [
"Delivery checklist"
]
},
"type": {
"enum": [
"UNKNOWN",
"CHECKBOXES",
"RADIO_BUTTONS",
"TEXT_INPUT",
"DECIMAL_INPUT",
"SCANNER_INPUT"
],
"type": "string",
"description": "Task type.",
"format": "enum",
"examples": [
"TEXT_INPUT"
]
},
"items": {
"type": "array",
"items": {
"title": "TaskItem",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Item ID (e.g. `\"itm-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"itm-123e4567-e89b-12d3-a456-426614174000"
]
},
"title": {
"type": "string",
"description": "Item title (e.g. `\"Pick up package\"`).",
"examples": [
"Pick up package"
]
},
"complete": {
"type": "boolean",
"description": "Whether the item is completed.",
"examples": [
true
]
},
"updatedAt": {
"type": "string",
"description": "Timestamp when the item was last updated.",
"format": "date-time",
"examples": [
"2026-03-30T13:00:00Z"
]
}
},
"description": "An item within a task. For `CHECKBOXES`, each item on a task may be completed\n independently. For `RADIO_BUTTONS`, at most one item will be completed."
},
"description": "Task items (populated for `CHECKBOXES` and `RADIO_BUTTONS`).",
"examples": [
[]
]
},
"input": {
"allOf": [
{
"title": "TaskInput",
"type": "object",
"properties": {
"value": {
"type": "string",
"description": "Input value.",
"examples": [
"020123456789"
]
},
"updatedAt": {
"type": "string",
"description": "Timestamp when the input was last updated.",
"format": "date-time",
"examples": [
"2026-03-30T13:00:00Z"
]
},
"inputMethod": {
"enum": [
"UNKNOWN",
"SCANNED"
],
"type": "string",
"description": "Whether input was scanned (e.g. a scanned barcode)",
"format": "enum",
"examples": [
"SCANNED"
]
}
},
"description": "Captured driver input for a task. The value may be text for `TEXT_INPUT`\n tasks or a string decimal number for `DECIMAL_INPUT` tasks."
}
],
"description": "Task input (populated for `TEXT_INPUT` and `DECIMAL_INPUT`)."
},
"requiredToMarkStopAsDelivered": {
"type": "boolean",
"description": "Whether the task is required to mark the stop as completed. In the case of\n tasks on `RouteStart`, this represents tasks required for starting the\n route. In the case of tasks on `RouteEnd`, this represents tasks required\n for completing the route.",
"examples": [
true
]
},
"requiredToMarkStopAsAttempted": {
"type": "boolean",
"description": "Whether the task is required to mark the stop as attempted.",
"examples": [
true
]
}
},
"description": "A task to be completed at a stop, or at the start or end of a route. Tasks\n may have one or more items for `CHECKBOXES` or `RADIO_BUTTONS`, or may have\n an input for `TEXT_INPUT` or `DECIMAL_INPUT`."
},
"description": "Tasks to complete before finishing the route."
},
"plannedArrival": {
"type": "string",
"description": "Planned arrival time at the end of the route.",
"format": "date-time",
"examples": [
"2026-03-30T17:00:00Z"
]
},
"distanceMeters": {
"type": "number",
"description": "The distance in meters from the previous stop.",
"format": "double",
"examples": [
1234.56
]
},
"updatedArrival": {
"type": "string",
"description": "Estimated arrival time at the end of the route. If the route is completed,\n this will be the actual arrival time.",
"format": "date-time",
"examples": [
"2026-03-30T17:05:00Z"
]
},
"status": {
"enum": [
"UNKNOWN",
"COMPLETED"
],
"type": "string",
"description": "Status indicating whether the route has been completed.",
"format": "enum",
"examples": [
"COMPLETED"
]
},
"photos": {
"type": "array",
"items": {
"title": "StopAttachment",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Attachment ID (e.g. `\"att-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"att-123e4567-e89b-12d3-a456-426614174000"
]
},
"createdAt": {
"type": "string",
"description": "Timestamp when the attachment was created.",
"format": "date-time",
"examples": [
"2026-03-30T09:05:00Z"
]
},
"url": {
"type": "string",
"description": "URL to fetch the attachment.",
"examples": [
"https://example.com/stop-attachment/attachment-2025-06-03-1"
]
}
},
"description": "An attachment to a stop, such as a proof of delivery photo or signature."
},
"description": "Photos for the route end. Photos may be fetched using the URLs on the\n attachments."
}
},
"description": "The end location of a route and any driver tasks to complete after completing\n the route."
}
],
"description": "Route end address and tasks."
},
"stops": {
"type": "array",
"items": {
"title": "RouteStop",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Stop ID (e.g. `\"rst-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"rst-123e4567-e89b-12d3-a456-426614174000"
]
},
"type": {
"enum": [
"UNKNOWN",
"DELIVERY",
"BREAK",
"PICKUP",
"TASK"
],
"type": "string",
"description": "The type of stop (DELIVERY, BREAK, PICKUP, or TASK).",
"format": "enum",
"examples": [
"DELIVERY"
]
},
"deliveryStatus": {
"enum": [
"UNKNOWN",
"DELIVERED",
"OUT_FOR_DELIVERY",
"ATTEMPTED_DELIVERY",
"READY_FOR_DELIVERY"
],
"type": "string",
"description": "The status for DELIVERY, PICKUP, or TASK stops.",
"format": "enum",
"examples": [
"ATTEMPTED_DELIVERY"
]
},
"breakStatus": {
"enum": [
"UNKNOWN",
"COMPLETED"
],
"type": "string",
"description": "The status for BREAK stops.",
"format": "enum",
"examples": [
"COMPLETED"
]
},
"updatedAt": {
"type": "string",
"description": "Timestamp when the stop status was last updated. Note that this timestamp\n corresponds only to major status updates (i.e. stop marked as DELIVERED).\n Minor updates like task completion or adding proof of delivery will not\n advance this timestamp. For those events, use the timestamps on the task or\n proof of delivery attachment.",
"format": "date-time",
"examples": [
"2026-03-30T13:15:00Z"
]
},
"duration": {
"pattern": "^-?(?:0|[1-9][0-9]{0,11})(?:\\.[0-9]{1,9})?s$",
"type": "string",
"description": "Planned duration of the stop in seconds.",
"examples": [
"300s"
]
},
"plannedArrival": {
"type": "string",
"description": "Planned arrival time at the stop.",
"format": "date-time",
"examples": [
"2026-03-30T13:00:00Z"
]
},
"note": {
"type": "string",
"description": "Top-level note for the stop, as entered manually by route planners,\n inherited from a saved or imported stop, or set by order import automation\n rules.",
"examples": [
"Leave at door."
]
},
"address": {
"allOf": [
{
"title": "Address",
"type": "object",
"properties": {
"address1": {
"type": "string",
"description": "Street address line 1 (e.g. `\"123 Main St\"`).",
"examples": [
"123 Main St"
]
},
"address2": {
"type": "string",
"description": "Street address line 2 (e.g. `\"Apt 101\"`).",
"examples": [
"Apt 3B"
]
},
"city": {
"type": "string",
"description": "City name (e.g. `\"New York\"`).",
"examples": [
"New York"
]
},
"provinceCode": {
"type": "string",
"description": "Province or state as subdivision codes in\n [ISO 3166-2](https://en.wikipedia.org/wiki/ISO_3166-2) format without the\n country prefix (e.g. `\"NY\"` for New York).",
"examples": [
"NY"
]
},
"countryCode": {
"type": "string",
"description": "Country code (e.g. `\"US\"`).",
"examples": [
"US"
]
},
"zip": {
"type": "string",
"description": "Postal or ZIP code (e.g. `\"10001\"`).",
"examples": [
"10001"
]
}
},
"description": "A physical street address."
}
],
"description": "Delivery address for the stop.",
"examples": [
{
"address1": "123 Main St",
"address2": "Apt 3B",
"city": "New York",
"provinceCode": "NY",
"countryCode": "US",
"zip": "10001"
}
]
},
"contact": {
"allOf": [
{
"title": "Contact",
"type": "object",
"properties": {
"firstName": {
"type": "string",
"description": "First name (e.g. `\"John\"`).",
"examples": [
"John"
]
},
"lastName": {
"type": "string",
"description": "Last name (e.g. `\"Doe\"`).",
"examples": [
"Doe"
]
},
"company": {
"type": "string",
"description": "Company name (e.g. `\"Roundtrip Systems Inc\"`).",
"examples": [
"Roundtrip Systems Inc"
]
},
"phone": {
"type": "string",
"description": "Phone number in [E.164 format](https://en.wikipedia.org/wiki/E.164) (e.g.\n `\"+14265551000\"`).",
"examples": [
"+14265551000"
]
},
"email": {
"type": "string",
"description": "Email address (e.g. `\"john.doe@roundtrip.ai\"`)",
"examples": [
"john.doe@roundtrip.ai"
]
}
},
"description": "Contact information for a person or company."
}
],
"description": "Contact information for the stop delivery recipient.",
"examples": [
{
"firstName": "John",
"lastName": "Doe",
"company": "Roundtrip Systems Inc",
"phone": "+14265551000",
"email": "john.doe@roundtrip.ai"
}
]
},
"plannedCoordinates": {
"allOf": [
{
"type": "object",
"properties": {
"latitude": {
"type": "number",
"description": "The latitude in degrees. It must be in the range [-90.0, +90.0].",
"format": "double"
},
"longitude": {
"type": "number",
"description": "The longitude in degrees. It must be in the range [-180.0, +180.0].",
"format": "double"
}
},
"description": "An object that represents a latitude/longitude pair. This is expressed as a\n pair of doubles to represent degrees latitude and degrees longitude. Unless\n specified otherwise, this must conform to the\n WGS84\n standard. Values must be within normalized ranges."
}
],
"description": "Planned coordinates for the stop.",
"examples": [
{
"latitude": 40.7128,
"longitude": -74.006
}
]
},
"items": {
"type": "array",
"items": {
"title": "StopItem",
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "Item name (e.g. `\"Bananas\"`).",
"examples": [
"Bananas"
]
},
"quantity": {
"type": "integer",
"description": "Quantity of the item (e.g. `5`).",
"format": "int32",
"examples": [
5
]
},
"grams": {
"type": "integer",
"description": "Weight of the item in grams (e.g. `500`).",
"format": "int32",
"examples": [
500
]
},
"sku": {
"type": "string",
"description": "Stock keeping unit (e.g. `\"BANANA-001\"`).",
"examples": [
"BANANA-001"
]
}
},
"description": "An item to be delivered at a stop."
},
"description": "Items to deliver at the stop."
},
"source": {
"enum": [
"UNKNOWN",
"SHOPIFY_ORDER",
"SAVED_STOP",
"IMPORTED_STOP"
],
"type": "string",
"description": "The source of the stop, which may be populated for `DELIVERY` stops. The\n source can be a `SHOPIFY_ORDER`, an EasyRoutes `SAVED_STOP`, or an\n `IMPORTED_STOP` from an external source (such as CSV file).",
"format": "enum",
"examples": [
"IMPORTED_STOP"
]
},
"shopifyOrderId": {
"type": "string",
"description": "The Shopify order ID, populated when the stop source is a `SHOPIFY_ORDER`.",
"examples": [
"6229749334323"
]
},
"savedStopId": {
"type": "string",
"description": "The saved stop ID, populated when the stop source is a `SAVED_STOP`.",
"examples": [
"sst-123e4567-e89b-12d3-a456-426614174000"
]
},
"deliveredCoordinates": {
"allOf": [
{
"type": "object",
"properties": {
"latitude": {
"type": "number",
"description": "The latitude in degrees. It must be in the range [-90.0, +90.0].",
"format": "double"
},
"longitude": {
"type": "number",
"description": "The longitude in degrees. It must be in the range [-180.0, +180.0].",
"format": "double"
}
},
"description": "An object that represents a latitude/longitude pair. This is expressed as a\n pair of doubles to represent degrees latitude and degrees longitude. Unless\n specified otherwise, this must conform to the\n WGS84\n standard. Values must be within normalized ranges."
}
],
"description": "Delivered coordinates for the stop."
},
"proofOfDeliveryNote": {
"type": "string",
"description": "Proof of delivery note for the stop.",
"examples": [
"Left at door."
]
},
"proofOfDeliveryPhotos": {
"type": "array",
"items": {
"title": "StopAttachment",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Attachment ID (e.g. `\"att-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"att-123e4567-e89b-12d3-a456-426614174000"
]
},
"createdAt": {
"type": "string",
"description": "Timestamp when the attachment was created.",
"format": "date-time",
"examples": [
"2026-03-30T09:05:00Z"
]
},
"url": {
"type": "string",
"description": "URL to fetch the attachment.",
"examples": [
"https://example.com/stop-attachment/attachment-2025-06-03-1"
]
}
},
"description": "An attachment to a stop, such as a proof of delivery photo or signature."
},
"description": "Proof of delivery photos for the stop. Photos may be fetched using the URLs\n on the attachments."
},
"proofOfDeliverySignatures": {
"type": "array",
"items": {
"title": "StopAttachment",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Attachment ID (e.g. `\"att-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"att-123e4567-e89b-12d3-a456-426614174000"
]
},
"createdAt": {
"type": "string",
"description": "Timestamp when the attachment was created.",
"format": "date-time",
"examples": [
"2026-03-30T09:05:00Z"
]
},
"url": {
"type": "string",
"description": "URL to fetch the attachment.",
"examples": [
"https://example.com/stop-attachment/attachment-2025-06-03-1"
]
}
},
"description": "An attachment to a stop, such as a proof of delivery photo or signature."
},
"description": "Proof of delivery signatures for the stop. Signatures may be fetched using\n the URLs on the attachments."
},
"tasks": {
"type": "array",
"items": {
"title": "Task",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Task ID (e.g. `\"tsk-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"tsk-123e4567-e89b-12d3-a456-426614174000"
]
},
"title": {
"type": "string",
"description": "Task title (e.g. `\"Delivery checklist\"`).",
"examples": [
"Delivery checklist"
]
},
"type": {
"enum": [
"UNKNOWN",
"CHECKBOXES",
"RADIO_BUTTONS",
"TEXT_INPUT",
"DECIMAL_INPUT",
"SCANNER_INPUT"
],
"type": "string",
"description": "Task type.",
"format": "enum",
"examples": [
"TEXT_INPUT"
]
},
"items": {
"type": "array",
"items": {
"title": "TaskItem",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Item ID (e.g. `\"itm-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"itm-123e4567-e89b-12d3-a456-426614174000"
]
},
"title": {
"type": "string",
"description": "Item title (e.g. `\"Pick up package\"`).",
"examples": [
"Pick up package"
]
},
"complete": {
"type": "boolean",
"description": "Whether the item is completed.",
"examples": [
true
]
},
"updatedAt": {
"type": "string",
"description": "Timestamp when the item was last updated.",
"format": "date-time",
"examples": [
"2026-03-30T13:00:00Z"
]
}
},
"description": "An item within a task. For `CHECKBOXES`, each item on a task may be completed\n independently. For `RADIO_BUTTONS`, at most one item will be completed."
},
"description": "Task items (populated for `CHECKBOXES` and `RADIO_BUTTONS`).",
"examples": [
[]
]
},
"input": {
"allOf": [
{
"title": "TaskInput",
"type": "object",
"properties": {
"value": {
"type": "string",
"description": "Input value.",
"examples": [
"020123456789"
]
},
"updatedAt": {
"type": "string",
"description": "Timestamp when the input was last updated.",
"format": "date-time",
"examples": [
"2026-03-30T13:00:00Z"
]
},
"inputMethod": {
"enum": [
"UNKNOWN",
"SCANNED"
],
"type": "string",
"description": "Whether input was scanned (e.g. a scanned barcode)",
"format": "enum",
"examples": [
"SCANNED"
]
}
},
"description": "Captured driver input for a task. The value may be text for `TEXT_INPUT`\n tasks or a string decimal number for `DECIMAL_INPUT` tasks."
}
],
"description": "Task input (populated for `TEXT_INPUT` and `DECIMAL_INPUT`)."
},
"requiredToMarkStopAsDelivered": {
"type": "boolean",
"description": "Whether the task is required to mark the stop as completed. In the case of\n tasks on `RouteStart`, this represents tasks required for starting the\n route. In the case of tasks on `RouteEnd`, this represents tasks required\n for completing the route.",
"examples": [
true
]
},
"requiredToMarkStopAsAttempted": {
"type": "boolean",
"description": "Whether the task is required to mark the stop as attempted.",
"examples": [
true
]
}
},
"description": "A task to be completed at a stop, or at the start or end of a route. Tasks\n may have one or more items for `CHECKBOXES` or `RADIO_BUTTONS`, or may have\n an input for `TEXT_INPUT` or `DECIMAL_INPUT`."
},
"description": "Driver tasks for the stop, including completed items and any input from the\n driver."
},
"priority": {
"maximum": 10,
"type": "integer",
"description": "Priority of the stop for route planning. The valid range for stop priority\n is between `1` (low) and `10` (high), with default priority corresponding\n to a value of `5`. A priority value of `0` is considered unset and is\n treated the same as \"default\" priority. Stops with higher priority will be\n preferred when generating routes with constraints.",
"format": "int32",
"examples": [
8
]
},
"importedStopId": {
"type": "string",
"description": "The imported stop ID, populated when the stop source is `IMPORTED_STOP`.",
"examples": [
"ist-123e4567-e89b-12d3-a456-426614174000"
]
},
"orderName": {
"type": "string",
"description": "The name of the order associated with the stop. For Shopify orders, the\n name is generated by combining the `orderNumber` property with the order\n prefix and suffix that are set in the merchant's general settings. For\n EasyRoutes imported orders, this field is populated with the order name\n provided on import.",
"examples": [
"#1234"
]
},
"distanceMeters": {
"type": "number",
"description": "The distance in meters from the previous stop.",
"format": "double",
"examples": [
123.45
]
},
"updatedArrival": {
"type": "string",
"description": "Estimated arrival time at the stop. If the stop is completed, this will be\n the actual arrival time.",
"format": "date-time",
"examples": [
"2026-03-30T13:05:00Z"
]
},
"timeWindows": {
"type": "array",
"items": {
"title": "TimeWindow",
"type": "object",
"properties": {
"start": {
"allOf": [
{
"title": "TimeOfDay",
"type": "object",
"properties": {
"hours": {
"maximum": 23,
"type": "integer",
"description": "Hours of day in 24 hour format. Must be from 0 to 23.",
"format": "int32",
"examples": [
13
]
},
"minutes": {
"maximum": 59,
"type": "integer",
"description": "Minutes of hour of day. Must be from 0 to 59.",
"format": "int32",
"examples": [
37
]
},
"seconds": {
"maximum": 59,
"type": "integer",
"description": "Seconds of minutes of the time. Must be from 0 to 59.",
"format": "int32",
"examples": [
16
]
}
},
"description": "A time of day, independent of a particular date or timezone."
}
],
"description": "The start time of the time window (optional)."
},
"end": {
"allOf": [
{
"title": "TimeOfDay",
"type": "object",
"properties": {
"hours": {
"maximum": 23,
"type": "integer",
"description": "Hours of day in 24 hour format. Must be from 0 to 23.",
"format": "int32",
"examples": [
13
]
},
"minutes": {
"maximum": 59,
"type": "integer",
"description": "Minutes of hour of day. Must be from 0 to 59.",
"format": "int32",
"examples": [
37
]
},
"seconds": {
"maximum": 59,
"type": "integer",
"description": "Seconds of minutes of the time. Must be from 0 to 59.",
"format": "int32",
"examples": [
16
]
}
},
"description": "A time of day, independent of a particular date or timezone."
}
],
"description": "The end time of the time window (optional)."
}
},
"description": "A time window for a stop. The time window may be open-ended, but one or both\n of the start and end times should be provided. The end time must be >= the\n start time."
},
"description": "The time window for the stop. Note that we currently support at most one\n time window but may support multiple time windows in the future.",
"examples": [
[
{
"start": {
"hours": 9
},
"end": {
"hours": 17
}
}
]
]
},
"deliveryDate": {
"allOf": [
{
"title": "Date",
"required": [
"year",
"month",
"day"
],
"type": "object",
"properties": {
"year": {
"maximum": 9999,
"minimum": 1,
"type": "integer",
"description": "Year of the date. Must be from 1 to 9999.",
"format": "int32",
"examples": [
2019
]
},
"month": {
"maximum": 12,
"minimum": 1,
"type": "integer",
"description": "Month of a year. Must be from 1 to 12.",
"format": "int32",
"examples": [
11
]
},
"day": {
"maximum": 31,
"minimum": 1,
"type": "integer",
"description": "Day of a month. Must be from 1 to 31.",
"format": "int32",
"examples": [
15
]
}
},
"description": "A date in year-month-day format."
}
],
"description": "The planned delivery date for the stop.",
"examples": [
{
"year": 2025,
"month": 12,
"day": 16
}
]
},
"attributes": {
"type": "array",
"items": {
"title": "Attribute",
"type": "object",
"properties": {
"key": {
"type": "string",
"description": "Attribute key. Must be non-empty.",
"examples": [
"delivery_date"
]
},
"value": {
"type": "string",
"description": "Attribute value.",
"examples": [
"2025-12-16"
]
}
},
"description": "A key-value pair for storing additional information on a stop, such as order\n details, delivery instructions, or custom fields."
},
"description": "Additional attributes for the stop. Attributes are key-value pairs for\n storing additional structured data on stops. These may be populated from\n the Shopify order or set on import.",
"examples": [
[
{
"key": "color",
"value": "blue"
}
]
]
},
"clientStopId": {
"type": "string",
"description": "The client-provided ID associated with the stop, if provided on import.",
"examples": [
"test-order-1234"
]
},
"tags": {
"type": "array",
"items": {
"type": "string"
},
"description": "The tags for the stop. Tags are used to categorize stops and can be used\n for filtering and grouping stops in the EasyRoutes web app. These may be\n populated from the Shopify order or set on import.",
"examples": [
[
"foo",
"bar"
]
]
},
"attemptedReason": {
"enum": [
"UNKNOWN",
"NOT_AVAILABLE",
"ACCESS_DENIED",
"INCORRECT_ADDRESS",
"SAFE_PLACE_UNAVAILABLE",
"REFUSED",
"EXTERNAL",
"INCORRECT_ITEMS",
"OTHER",
"CANCELED"
],
"type": "string",
"description": "The reason for marking the stop as attempted. This is only populated when\n `deliveryStatus = ATTEMPTED_DELIVERY`.",
"format": "enum",
"examples": [
"NOT_AVAILABLE"
]
},
"attemptedNote": {
"type": "string",
"description": "Optional note related to the reason for marking the stop as attempted. This\n is optionally populated when `deliveryStatus = ATTEMPTED_DELIVERY`.",
"examples": [
"Customer did not answer the door."
]
},
"customerRating": {
"allOf": [
{
"title": "CustomerRating",
"type": "object",
"properties": {
"rating": {
"maximum": 5,
"minimum": 1,
"type": "integer",
"description": "Rating from 1-5",
"format": "int32",
"examples": [
5
]
},
"comment": {
"type": "string",
"description": "Customer comment related to rating",
"examples": [
"Excellent delivery"
]
},
"createdAt": {
"type": "string",
"description": "Timestamp when rating was left by customer.",
"format": "date-time",
"examples": [
"2026-03-30T18:00:00Z"
]
}
},
"description": "Customer rating and feedback left on a stop."
}
],
"description": "Rating left by customer. This can only be populated once `deliveryStatus =\n DELIVERED`."
},
"customSignatureDisclosure": {
"type": "string",
"description": "Optional custom signature disclosure that is shown to customers in the\n driver app.",
"examples": [
"I acknowledge that I have received this delivery."
]
},
"shopifyOrder": {
"allOf": [
{
"title": "ShopifyOrder",
"type": "object",
"properties": {
"orderNote": {
"type": "string",
"description": "The Shopify order note.",
"examples": [
"Customer has paid."
]
},
"customerNote": {
"type": "string",
"description": "The Shopify customer note for the order.",
"examples": [
"Leave at door."
]
}
},
"description": "Shopify-specific information for a RouteStop."
}
],
"description": "Information from the associated Shopify order, if applicable. Populated if\n stop source is `SHOPIFY_ORDER`"
},
"proofOfDeliveryBarcodes": {
"type": "array",
"items": {
"title": "ScannedBarcode",
"type": "object",
"properties": {
"value": {
"type": "string",
"description": "Barcode value (e.g. `\"123456789012\"`).",
"examples": [
"123456789012"
]
},
"createdAt": {
"type": "string",
"description": "Timestamp when the barcode was scanned.",
"format": "date-time",
"examples": [
"2026-03-30T13:10:00Z"
]
}
},
"description": "A proof of delivery barcode scanned at a stop."
},
"description": "Proof of delivery barcodes scanned at the stop."
},
"proofOfDeliveryBarcodeIssues": {
"type": "array",
"items": {
"title": "ScannedBarcodeIssue",
"type": "object",
"properties": {
"reason": {
"enum": [
"UNKNOWN",
"ITEM_MISSING",
"NOT_SCANNABLE",
"INCORRECT"
],
"type": "string",
"description": "The reported reason for the barcode issue.",
"format": "enum",
"examples": [
"ITEM_MISSING"
]
},
"note": {
"type": "string",
"description": "Optional note related to the reason for reporting a barcode issue.",
"examples": [
"Item was not packed."
]
},
"createdAt": {
"type": "string",
"description": "Timestamp when the issue was reported.",
"format": "date-time",
"examples": [
"2026-03-30T13:10:00Z"
]
}
},
"description": "A reported issue related to scanning barcodes at a stop."
},
"description": "Proof of delivery barcode issues reported at the stop."
},
"orderReferenceUrl": {
"type": "string",
"description": "A reference URL for the order associated with the stop (e.g. a link to the\n order in your order management system). Must be a valid HTTPS URL. This\n field can only be populated for imported stops.",
"examples": [
"https://orders.example.com/orders/148977776"
]
}
},
"description": "A stop on a route. A stop may correspond to a delivery or a driver break as\n determined by the type. A delivery stop will have location and contact\n information, items to deliver, optional order details, status, arrival time\n and stop duration, driver tasks and any proof of delivery information. A\n break stop will have start time and duration, and status."
},
"description": "Route stops. See RouteStop for stop fields."
},
"createdAt": {
"type": "string",
"description": "Timestamp when the route was created.",
"format": "date-time",
"examples": [
"2026-03-29T08:00:00Z"
]
},
"updatedAt": {
"type": "string",
"description": "Timestamp when the route was last updated (by the planner).",
"format": "date-time",
"examples": [
"2026-03-30T13:15:00Z"
]
},
"archivedAt": {
"type": "string",
"description": "Timestamp when the route was archived.",
"format": "date-time",
"examples": [
"2026-04-05T00:00:00Z"
]
},
"scheduledFor": {
"type": "string",
"description": "Timestamp when the route is scheduled for.",
"format": "date-time",
"examples": [
"2026-03-30T09:00:00Z"
]
},
"totalDistanceMeters": {
"type": "number",
"description": "The distance in meters for the entire route.",
"format": "double",
"examples": [
2387.2
]
},
"totalItemQuantity": {
"type": "integer",
"description": "The total quantity of items to deliver on the route.",
"format": "int32",
"examples": [
50
]
},
"totalItemGrams": {
"type": "string",
"description": "The total weight in grams for the items on the route.",
"examples": [
"6000"
]
},
"optimized": {
"type": "boolean",
"description": "Whether the route has been optimized. Adding or removing stops, reordering\n stops, or changing route options generally set this field to false until\n the route is reoptimized.",
"examples": [
true
]
},
"dispatchedUntil": {
"type": "string",
"description": "Timestamp until which the route is dispatched and accessible in the driver\n app.",
"format": "date-time",
"examples": [
"2026-03-30T20:00:00Z"
]
},
"note": {
"type": "string",
"description": "Top-level note for the route, as entered manually by route planners.",
"examples": [
"Fragile items."
]
},
"tags": {
"type": "array",
"items": {
"type": "string"
},
"description": "The tags for the route. Tags are used to categorize routes and can be\n used for filtering and grouping routes in the EasyRoutes web app.",
"examples": [
[
"foo",
"bar"
]
]
},
"defaultStopDuration": {
"pattern": "^-?(?:0|[1-9][0-9]{0,11})(?:\\.[0-9]{1,9})?s$",
"type": "string",
"description": "The default duration for stops on the route. Used to estimate arrival\n times for stops that do not have their own duration specified.\n Specified as a duration string in the format \"300s\" for 5 minutes, \"60s\"\n for 1 minute, etc.",
"examples": [
"300s"
]
},
"maxDuration": {
"pattern": "^-?(?:0|[1-9][0-9]{0,11})(?:\\.[0-9]{1,9})?s$",
"type": "string",
"description": "The maximum duration of the route. Specified as a duration string in the\n format \"3600s\" for 1 hour, \"7200s\" for 2 hours, etc.",
"examples": [
"28800s"
]
},
"maxStops": {
"type": "integer",
"description": "The maximum number of stops on the route.",
"format": "int32",
"examples": [
50
]
},
"maxItemCount": {
"type": "integer",
"description": "The maximum total item count across all stops on the route.",
"format": "int32",
"examples": [
200
]
},
"maxKilograms": {
"type": "number",
"description": "The maximum total weight in kilograms across all stops on the route.",
"format": "double",
"examples": [
500
]
},
"avoidTolls": {
"type": "boolean",
"description": "Whether to avoid toll roads during optimization.",
"examples": [
true
]
},
"avoidUTurns": {
"type": "boolean",
"description": "Whether to avoid U-turns during optimization.",
"examples": [
true
]
},
"speedFactor": {
"type": "number",
"description": "A speed factor for the route used during optimization to adjust estimated\n travel times. A value of 1.0 represents normal speed. Values less than 1.0\n indicate slower travel (e.g. 0.5 = half speed), and values greater than\n 1.0 indicate faster travel (e.g. 1.5 = 50% faster). Must be between 0.1\n and 1.9. A value of 0 (or unset) uses the default speed.",
"format": "double",
"examples": [
0.8
]
},
"vehicle": {
"allOf": [
{
"title": "Vehicle",
"required": [
"id"
],
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Vehicle ID.",
"examples": [
"veh-123e4567-e89b-12d3-a456-426614174000"
]
},
"name": {
"type": "string",
"description": "Vehicle name.",
"examples": [
"Delivery Van 1"
]
},
"make": {
"type": "string",
"description": "Vehicle make.",
"examples": [
"Ford"
]
},
"model": {
"type": "string",
"description": "Vehicle model.",
"examples": [
"Transit"
]
},
"year": {
"type": "integer",
"description": "Vehicle model year.",
"format": "int32",
"examples": [
2023
]
},
"type": {
"enum": [
"UNKNOWN",
"CAR",
"CARGO_VAN",
"PICKUP_TRUCK",
"BOX_TRUCK",
"MOTORCYCLE",
"BICYCLE",
"DRONE",
"OTHER"
],
"type": "string",
"description": "Vehicle type.",
"format": "enum",
"examples": [
"CARGO_VAN"
]
},
"vin": {
"type": "string",
"description": "Vehicle Identification Number.",
"examples": [
"1FTBW2CM5NKA12345"
]
},
"license": {
"type": "string",
"description": "Vehicle license plate.",
"examples": [
"ABC-1234"
]
},
"isArchived": {
"type": "boolean",
"description": "Whether the vehicle is archived.",
"examples": [
false
]
},
"createdTimestamp": {
"type": "string",
"description": "Timestamp when the vehicle was created.",
"format": "date-time",
"examples": [
"2026-07-30T12:00:00Z"
]
}
},
"description": "A vehicle that can be assigned to a route."
}
],
"description": "Assigned vehicle for the route."
}
},
"description": "A route of stops, optionally with an assigned driver."
}
}
}
},
"default": {
"description": "Default error response",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"code": {
"type": "integer",
"description": "The status code, which should be an enum value of [google.rpc.Code][google.rpc.Code].",
"format": "int32"
},
"message": {
"type": "string",
"description": "A developer-facing error message, which should be in English. Any user-facing error message should be localized and sent in the [google.rpc.Status.details][google.rpc.Status.details] field, or localized by the client."
},
"details": {
"type": "array",
"items": {
"type": "object",
"properties": {
"@type": {
"type": "string",
"description": "The type of the serialized message."
}
},
"additionalProperties": true,
"description": "Contains an arbitrary serialized message along with a @type that describes the type of the serialized message."
},
"description": "A list of messages that carry the error details. There is a common set of message types for APIs to use."
}
},
"description": "The `Status` type defines a logical error model that is suitable for different programming environments, including REST APIs and RPC APIs. It is used by [gRPC](https://github.com/grpc). Each `Status` message contains three pieces of data: error code, error message, and error details. You can find out more about this error model and how to work with it in the [API Design Guide](https://cloud.google.com/apis/design/errors)."
}
}
}
}
},
"security": [
{
"bearerAuth": []
}
],
"components": {
"securitySchemes": {
"bearerAuth": {
"type": "http",
"description": "Access token from `/authenticate`",
"scheme": "bearer",
"bearerFormat": "JWT"
}
}
}
}
```
# Resync route orders (https://docs.roundtrip.ai/docs/api-reference/routes/post-routes-routeId-resync-orders)
POST /routes/{routeId}/resync-orders
Refreshes each order-backed stop's order data from Shopify with the
latest fulfillment status, item updates, notes, and tags, and
reconciles the route's stops against the changes. Routes with no
Shopify order-backed stops are left untouched. The response will
include the updated route.
## OpenAPI specification
```json
{
"servers": [
{
"url": "https://easyroutes.roundtrip.ai/api/2024-07"
}
],
"tags": [
"Routes"
],
"summary": "Resync route orders",
"description": "Refreshes each order-backed stop's order data from Shopify with the\n latest fulfillment status, item updates, notes, and tags, and\n reconciles the route's stops against the changes. Routes with no\n Shopify order-backed stops are left untouched. The response will\n include the updated route.",
"operationId": "ResyncRouteOrders",
"parameters": [
{
"name": "routeId",
"in": "path",
"description": "The ID of the route to resync orders for.",
"required": true,
"schema": {
"type": "string",
"examples": [
"rte-123e4567-e89b-12d3-a456-426614174000"
]
}
},
{
"name": "Idempotency-Key",
"in": "header",
"description": "A unique key for safely retrying this operation. For more information read [our guide](https://docs.roundtrip.ai/docs/concepts/idempotency.md).",
"schema": {
"maxLength": 255,
"minLength": 1,
"type": "string"
},
"examples": {
"default": {
"value": "550e8400-e29b-41d4-a716-446655440000"
}
}
}
],
"responses": {
"200": {
"description": "OK",
"headers": {
"Idempotency-Key": {
"description": "The idempotency key associated with the response.",
"schema": {
"type": "string"
}
},
"Idempotency-Replayed": {
"description": "Whether the response was replayed from a previous request.",
"schema": {
"type": "boolean"
}
}
},
"content": {
"application/json": {
"schema": {
"title": "Route",
"required": [
"id",
"name",
"stops",
"createdAt",
"updatedAt",
"totalDistanceMeters",
"totalItemQuantity",
"totalItemGrams",
"optimized"
],
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Route ID (e.g. `\"rte-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"rte-123e4567-e89b-12d3-a456-426614174000"
]
},
"name": {
"type": "string",
"description": "Route name (e.g. `\"Morning route\"`).",
"examples": [
"Morning route"
]
},
"driver": {
"allOf": [
{
"title": "Driver",
"required": [
"id"
],
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Driver ID (e.g. `\"drv-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"drv-123e4567-e89b-12d3-a456-426614174000"
]
},
"firstName": {
"type": "string",
"description": "Driver first name (e.g. `\"John\"`).",
"examples": [
"John"
]
},
"lastName": {
"type": "string",
"description": "Driver last name (e.g. `\"Doe\"`).",
"examples": [
"Doe"
]
},
"phone": {
"type": "string",
"description": "Driver phone number in [E.164 format](https://en.wikipedia.org/wiki/E.164)\n (e.g. `\"+14265551000\"`).",
"examples": [
"+14265551000"
]
},
"status": {
"enum": [
"UNKNOWN",
"ACTIVE",
"INACTIVE",
"ARCHIVED"
],
"type": "string",
"description": "Shop driver status. (e.g. `ACTIVE`).",
"format": "enum",
"examples": [
"ACTIVE"
]
}
},
"description": "A driver who is assigned to a route."
}
],
"description": "Assigned driver for the route."
},
"start": {
"allOf": [
{
"title": "RouteStart",
"type": "object",
"properties": {
"address": {
"allOf": [
{
"title": "Address",
"type": "object",
"properties": {
"address1": {
"type": "string",
"description": "Street address line 1 (e.g. `\"123 Main St\"`).",
"examples": [
"123 Main St"
]
},
"address2": {
"type": "string",
"description": "Street address line 2 (e.g. `\"Apt 101\"`).",
"examples": [
"Apt 3B"
]
},
"city": {
"type": "string",
"description": "City name (e.g. `\"New York\"`).",
"examples": [
"New York"
]
},
"provinceCode": {
"type": "string",
"description": "Province or state as subdivision codes in\n [ISO 3166-2](https://en.wikipedia.org/wiki/ISO_3166-2) format without the\n country prefix (e.g. `\"NY\"` for New York).",
"examples": [
"NY"
]
},
"countryCode": {
"type": "string",
"description": "Country code (e.g. `\"US\"`).",
"examples": [
"US"
]
},
"zip": {
"type": "string",
"description": "Postal or ZIP code (e.g. `\"10001\"`).",
"examples": [
"10001"
]
}
},
"description": "A physical street address."
}
],
"description": "The start address of the route.",
"examples": [
{
"address1": "123 Main St",
"address2": "Apt 3B",
"city": "New York",
"provinceCode": "NY",
"countryCode": "US",
"zip": "10001"
}
]
},
"tasks": {
"type": "array",
"items": {
"title": "Task",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Task ID (e.g. `\"tsk-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"tsk-123e4567-e89b-12d3-a456-426614174000"
]
},
"title": {
"type": "string",
"description": "Task title (e.g. `\"Delivery checklist\"`).",
"examples": [
"Delivery checklist"
]
},
"type": {
"enum": [
"UNKNOWN",
"CHECKBOXES",
"RADIO_BUTTONS",
"TEXT_INPUT",
"DECIMAL_INPUT",
"SCANNER_INPUT"
],
"type": "string",
"description": "Task type.",
"format": "enum",
"examples": [
"TEXT_INPUT"
]
},
"items": {
"type": "array",
"items": {
"title": "TaskItem",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Item ID (e.g. `\"itm-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"itm-123e4567-e89b-12d3-a456-426614174000"
]
},
"title": {
"type": "string",
"description": "Item title (e.g. `\"Pick up package\"`).",
"examples": [
"Pick up package"
]
},
"complete": {
"type": "boolean",
"description": "Whether the item is completed.",
"examples": [
true
]
},
"updatedAt": {
"type": "string",
"description": "Timestamp when the item was last updated.",
"format": "date-time",
"examples": [
"2026-03-30T13:00:00Z"
]
}
},
"description": "An item within a task. For `CHECKBOXES`, each item on a task may be completed\n independently. For `RADIO_BUTTONS`, at most one item will be completed."
},
"description": "Task items (populated for `CHECKBOXES` and `RADIO_BUTTONS`).",
"examples": [
[]
]
},
"input": {
"allOf": [
{
"title": "TaskInput",
"type": "object",
"properties": {
"value": {
"type": "string",
"description": "Input value.",
"examples": [
"020123456789"
]
},
"updatedAt": {
"type": "string",
"description": "Timestamp when the input was last updated.",
"format": "date-time",
"examples": [
"2026-03-30T13:00:00Z"
]
},
"inputMethod": {
"enum": [
"UNKNOWN",
"SCANNED"
],
"type": "string",
"description": "Whether input was scanned (e.g. a scanned barcode)",
"format": "enum",
"examples": [
"SCANNED"
]
}
},
"description": "Captured driver input for a task. The value may be text for `TEXT_INPUT`\n tasks or a string decimal number for `DECIMAL_INPUT` tasks."
}
],
"description": "Task input (populated for `TEXT_INPUT` and `DECIMAL_INPUT`)."
},
"requiredToMarkStopAsDelivered": {
"type": "boolean",
"description": "Whether the task is required to mark the stop as completed. In the case of\n tasks on `RouteStart`, this represents tasks required for starting the\n route. In the case of tasks on `RouteEnd`, this represents tasks required\n for completing the route.",
"examples": [
true
]
},
"requiredToMarkStopAsAttempted": {
"type": "boolean",
"description": "Whether the task is required to mark the stop as attempted.",
"examples": [
true
]
}
},
"description": "A task to be completed at a stop, or at the start or end of a route. Tasks\n may have one or more items for `CHECKBOXES` or `RADIO_BUTTONS`, or may have\n an input for `TEXT_INPUT` or `DECIMAL_INPUT`."
},
"description": "Tasks to complete before starting the route."
},
"status": {
"enum": [
"UNKNOWN",
"STARTED"
],
"type": "string",
"description": "Status indicating whether the route has been started.",
"format": "enum",
"examples": [
"STARTED"
]
},
"updatedStart": {
"type": "string",
"description": "Updated start time for the route. If the route is started, this will be the\n actual start time.",
"format": "date-time",
"examples": [
"2026-03-30T09:05:00Z"
]
},
"scheduledStart": {
"type": "string",
"description": "Scheduled start time for the route (same as `scheduledFor` on the route).",
"format": "date-time",
"examples": [
"2026-03-30T09:00:00Z"
]
},
"photos": {
"type": "array",
"items": {
"title": "StopAttachment",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Attachment ID (e.g. `\"att-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"att-123e4567-e89b-12d3-a456-426614174000"
]
},
"createdAt": {
"type": "string",
"description": "Timestamp when the attachment was created.",
"format": "date-time",
"examples": [
"2026-03-30T09:05:00Z"
]
},
"url": {
"type": "string",
"description": "URL to fetch the attachment.",
"examples": [
"https://example.com/stop-attachment/attachment-2025-06-03-1"
]
}
},
"description": "An attachment to a stop, such as a proof of delivery photo or signature."
},
"description": "Photos for the route start. Photos may be fetched using the URLs on the\n attachments."
}
},
"description": "The start location of a route and any driver tasks to complete before\n beginning the route."
}
],
"description": "Route start address and tasks."
},
"end": {
"allOf": [
{
"title": "RouteEnd",
"type": "object",
"properties": {
"address": {
"allOf": [
{
"title": "Address",
"type": "object",
"properties": {
"address1": {
"type": "string",
"description": "Street address line 1 (e.g. `\"123 Main St\"`).",
"examples": [
"123 Main St"
]
},
"address2": {
"type": "string",
"description": "Street address line 2 (e.g. `\"Apt 101\"`).",
"examples": [
"Apt 3B"
]
},
"city": {
"type": "string",
"description": "City name (e.g. `\"New York\"`).",
"examples": [
"New York"
]
},
"provinceCode": {
"type": "string",
"description": "Province or state as subdivision codes in\n [ISO 3166-2](https://en.wikipedia.org/wiki/ISO_3166-2) format without the\n country prefix (e.g. `\"NY\"` for New York).",
"examples": [
"NY"
]
},
"countryCode": {
"type": "string",
"description": "Country code (e.g. `\"US\"`).",
"examples": [
"US"
]
},
"zip": {
"type": "string",
"description": "Postal or ZIP code (e.g. `\"10001\"`).",
"examples": [
"10001"
]
}
},
"description": "A physical street address."
}
],
"description": "The end address of the route.",
"examples": [
{
"address1": "123 Main St",
"address2": "Apt 3B",
"city": "New York",
"provinceCode": "NY",
"countryCode": "US",
"zip": "10001"
}
]
},
"tasks": {
"type": "array",
"items": {
"title": "Task",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Task ID (e.g. `\"tsk-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"tsk-123e4567-e89b-12d3-a456-426614174000"
]
},
"title": {
"type": "string",
"description": "Task title (e.g. `\"Delivery checklist\"`).",
"examples": [
"Delivery checklist"
]
},
"type": {
"enum": [
"UNKNOWN",
"CHECKBOXES",
"RADIO_BUTTONS",
"TEXT_INPUT",
"DECIMAL_INPUT",
"SCANNER_INPUT"
],
"type": "string",
"description": "Task type.",
"format": "enum",
"examples": [
"TEXT_INPUT"
]
},
"items": {
"type": "array",
"items": {
"title": "TaskItem",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Item ID (e.g. `\"itm-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"itm-123e4567-e89b-12d3-a456-426614174000"
]
},
"title": {
"type": "string",
"description": "Item title (e.g. `\"Pick up package\"`).",
"examples": [
"Pick up package"
]
},
"complete": {
"type": "boolean",
"description": "Whether the item is completed.",
"examples": [
true
]
},
"updatedAt": {
"type": "string",
"description": "Timestamp when the item was last updated.",
"format": "date-time",
"examples": [
"2026-03-30T13:00:00Z"
]
}
},
"description": "An item within a task. For `CHECKBOXES`, each item on a task may be completed\n independently. For `RADIO_BUTTONS`, at most one item will be completed."
},
"description": "Task items (populated for `CHECKBOXES` and `RADIO_BUTTONS`).",
"examples": [
[]
]
},
"input": {
"allOf": [
{
"title": "TaskInput",
"type": "object",
"properties": {
"value": {
"type": "string",
"description": "Input value.",
"examples": [
"020123456789"
]
},
"updatedAt": {
"type": "string",
"description": "Timestamp when the input was last updated.",
"format": "date-time",
"examples": [
"2026-03-30T13:00:00Z"
]
},
"inputMethod": {
"enum": [
"UNKNOWN",
"SCANNED"
],
"type": "string",
"description": "Whether input was scanned (e.g. a scanned barcode)",
"format": "enum",
"examples": [
"SCANNED"
]
}
},
"description": "Captured driver input for a task. The value may be text for `TEXT_INPUT`\n tasks or a string decimal number for `DECIMAL_INPUT` tasks."
}
],
"description": "Task input (populated for `TEXT_INPUT` and `DECIMAL_INPUT`)."
},
"requiredToMarkStopAsDelivered": {
"type": "boolean",
"description": "Whether the task is required to mark the stop as completed. In the case of\n tasks on `RouteStart`, this represents tasks required for starting the\n route. In the case of tasks on `RouteEnd`, this represents tasks required\n for completing the route.",
"examples": [
true
]
},
"requiredToMarkStopAsAttempted": {
"type": "boolean",
"description": "Whether the task is required to mark the stop as attempted.",
"examples": [
true
]
}
},
"description": "A task to be completed at a stop, or at the start or end of a route. Tasks\n may have one or more items for `CHECKBOXES` or `RADIO_BUTTONS`, or may have\n an input for `TEXT_INPUT` or `DECIMAL_INPUT`."
},
"description": "Tasks to complete before finishing the route."
},
"plannedArrival": {
"type": "string",
"description": "Planned arrival time at the end of the route.",
"format": "date-time",
"examples": [
"2026-03-30T17:00:00Z"
]
},
"distanceMeters": {
"type": "number",
"description": "The distance in meters from the previous stop.",
"format": "double",
"examples": [
1234.56
]
},
"updatedArrival": {
"type": "string",
"description": "Estimated arrival time at the end of the route. If the route is completed,\n this will be the actual arrival time.",
"format": "date-time",
"examples": [
"2026-03-30T17:05:00Z"
]
},
"status": {
"enum": [
"UNKNOWN",
"COMPLETED"
],
"type": "string",
"description": "Status indicating whether the route has been completed.",
"format": "enum",
"examples": [
"COMPLETED"
]
},
"photos": {
"type": "array",
"items": {
"title": "StopAttachment",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Attachment ID (e.g. `\"att-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"att-123e4567-e89b-12d3-a456-426614174000"
]
},
"createdAt": {
"type": "string",
"description": "Timestamp when the attachment was created.",
"format": "date-time",
"examples": [
"2026-03-30T09:05:00Z"
]
},
"url": {
"type": "string",
"description": "URL to fetch the attachment.",
"examples": [
"https://example.com/stop-attachment/attachment-2025-06-03-1"
]
}
},
"description": "An attachment to a stop, such as a proof of delivery photo or signature."
},
"description": "Photos for the route end. Photos may be fetched using the URLs on the\n attachments."
}
},
"description": "The end location of a route and any driver tasks to complete after completing\n the route."
}
],
"description": "Route end address and tasks."
},
"stops": {
"type": "array",
"items": {
"title": "RouteStop",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Stop ID (e.g. `\"rst-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"rst-123e4567-e89b-12d3-a456-426614174000"
]
},
"type": {
"enum": [
"UNKNOWN",
"DELIVERY",
"BREAK",
"PICKUP",
"TASK"
],
"type": "string",
"description": "The type of stop (DELIVERY, BREAK, PICKUP, or TASK).",
"format": "enum",
"examples": [
"DELIVERY"
]
},
"deliveryStatus": {
"enum": [
"UNKNOWN",
"DELIVERED",
"OUT_FOR_DELIVERY",
"ATTEMPTED_DELIVERY",
"READY_FOR_DELIVERY"
],
"type": "string",
"description": "The status for DELIVERY, PICKUP, or TASK stops.",
"format": "enum",
"examples": [
"ATTEMPTED_DELIVERY"
]
},
"breakStatus": {
"enum": [
"UNKNOWN",
"COMPLETED"
],
"type": "string",
"description": "The status for BREAK stops.",
"format": "enum",
"examples": [
"COMPLETED"
]
},
"updatedAt": {
"type": "string",
"description": "Timestamp when the stop status was last updated. Note that this timestamp\n corresponds only to major status updates (i.e. stop marked as DELIVERED).\n Minor updates like task completion or adding proof of delivery will not\n advance this timestamp. For those events, use the timestamps on the task or\n proof of delivery attachment.",
"format": "date-time",
"examples": [
"2026-03-30T13:15:00Z"
]
},
"duration": {
"pattern": "^-?(?:0|[1-9][0-9]{0,11})(?:\\.[0-9]{1,9})?s$",
"type": "string",
"description": "Planned duration of the stop in seconds.",
"examples": [
"300s"
]
},
"plannedArrival": {
"type": "string",
"description": "Planned arrival time at the stop.",
"format": "date-time",
"examples": [
"2026-03-30T13:00:00Z"
]
},
"note": {
"type": "string",
"description": "Top-level note for the stop, as entered manually by route planners,\n inherited from a saved or imported stop, or set by order import automation\n rules.",
"examples": [
"Leave at door."
]
},
"address": {
"allOf": [
{
"title": "Address",
"type": "object",
"properties": {
"address1": {
"type": "string",
"description": "Street address line 1 (e.g. `\"123 Main St\"`).",
"examples": [
"123 Main St"
]
},
"address2": {
"type": "string",
"description": "Street address line 2 (e.g. `\"Apt 101\"`).",
"examples": [
"Apt 3B"
]
},
"city": {
"type": "string",
"description": "City name (e.g. `\"New York\"`).",
"examples": [
"New York"
]
},
"provinceCode": {
"type": "string",
"description": "Province or state as subdivision codes in\n [ISO 3166-2](https://en.wikipedia.org/wiki/ISO_3166-2) format without the\n country prefix (e.g. `\"NY\"` for New York).",
"examples": [
"NY"
]
},
"countryCode": {
"type": "string",
"description": "Country code (e.g. `\"US\"`).",
"examples": [
"US"
]
},
"zip": {
"type": "string",
"description": "Postal or ZIP code (e.g. `\"10001\"`).",
"examples": [
"10001"
]
}
},
"description": "A physical street address."
}
],
"description": "Delivery address for the stop.",
"examples": [
{
"address1": "123 Main St",
"address2": "Apt 3B",
"city": "New York",
"provinceCode": "NY",
"countryCode": "US",
"zip": "10001"
}
]
},
"contact": {
"allOf": [
{
"title": "Contact",
"type": "object",
"properties": {
"firstName": {
"type": "string",
"description": "First name (e.g. `\"John\"`).",
"examples": [
"John"
]
},
"lastName": {
"type": "string",
"description": "Last name (e.g. `\"Doe\"`).",
"examples": [
"Doe"
]
},
"company": {
"type": "string",
"description": "Company name (e.g. `\"Roundtrip Systems Inc\"`).",
"examples": [
"Roundtrip Systems Inc"
]
},
"phone": {
"type": "string",
"description": "Phone number in [E.164 format](https://en.wikipedia.org/wiki/E.164) (e.g.\n `\"+14265551000\"`).",
"examples": [
"+14265551000"
]
},
"email": {
"type": "string",
"description": "Email address (e.g. `\"john.doe@roundtrip.ai\"`)",
"examples": [
"john.doe@roundtrip.ai"
]
}
},
"description": "Contact information for a person or company."
}
],
"description": "Contact information for the stop delivery recipient.",
"examples": [
{
"firstName": "John",
"lastName": "Doe",
"company": "Roundtrip Systems Inc",
"phone": "+14265551000",
"email": "john.doe@roundtrip.ai"
}
]
},
"plannedCoordinates": {
"allOf": [
{
"type": "object",
"properties": {
"latitude": {
"type": "number",
"description": "The latitude in degrees. It must be in the range [-90.0, +90.0].",
"format": "double"
},
"longitude": {
"type": "number",
"description": "The longitude in degrees. It must be in the range [-180.0, +180.0].",
"format": "double"
}
},
"description": "An object that represents a latitude/longitude pair. This is expressed as a\n pair of doubles to represent degrees latitude and degrees longitude. Unless\n specified otherwise, this must conform to the\n WGS84\n standard. Values must be within normalized ranges."
}
],
"description": "Planned coordinates for the stop.",
"examples": [
{
"latitude": 40.7128,
"longitude": -74.006
}
]
},
"items": {
"type": "array",
"items": {
"title": "StopItem",
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "Item name (e.g. `\"Bananas\"`).",
"examples": [
"Bananas"
]
},
"quantity": {
"type": "integer",
"description": "Quantity of the item (e.g. `5`).",
"format": "int32",
"examples": [
5
]
},
"grams": {
"type": "integer",
"description": "Weight of the item in grams (e.g. `500`).",
"format": "int32",
"examples": [
500
]
},
"sku": {
"type": "string",
"description": "Stock keeping unit (e.g. `\"BANANA-001\"`).",
"examples": [
"BANANA-001"
]
}
},
"description": "An item to be delivered at a stop."
},
"description": "Items to deliver at the stop."
},
"source": {
"enum": [
"UNKNOWN",
"SHOPIFY_ORDER",
"SAVED_STOP",
"IMPORTED_STOP"
],
"type": "string",
"description": "The source of the stop, which may be populated for `DELIVERY` stops. The\n source can be a `SHOPIFY_ORDER`, an EasyRoutes `SAVED_STOP`, or an\n `IMPORTED_STOP` from an external source (such as CSV file).",
"format": "enum",
"examples": [
"IMPORTED_STOP"
]
},
"shopifyOrderId": {
"type": "string",
"description": "The Shopify order ID, populated when the stop source is a `SHOPIFY_ORDER`.",
"examples": [
"6229749334323"
]
},
"savedStopId": {
"type": "string",
"description": "The saved stop ID, populated when the stop source is a `SAVED_STOP`.",
"examples": [
"sst-123e4567-e89b-12d3-a456-426614174000"
]
},
"deliveredCoordinates": {
"allOf": [
{
"type": "object",
"properties": {
"latitude": {
"type": "number",
"description": "The latitude in degrees. It must be in the range [-90.0, +90.0].",
"format": "double"
},
"longitude": {
"type": "number",
"description": "The longitude in degrees. It must be in the range [-180.0, +180.0].",
"format": "double"
}
},
"description": "An object that represents a latitude/longitude pair. This is expressed as a\n pair of doubles to represent degrees latitude and degrees longitude. Unless\n specified otherwise, this must conform to the\n WGS84\n standard. Values must be within normalized ranges."
}
],
"description": "Delivered coordinates for the stop."
},
"proofOfDeliveryNote": {
"type": "string",
"description": "Proof of delivery note for the stop.",
"examples": [
"Left at door."
]
},
"proofOfDeliveryPhotos": {
"type": "array",
"items": {
"title": "StopAttachment",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Attachment ID (e.g. `\"att-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"att-123e4567-e89b-12d3-a456-426614174000"
]
},
"createdAt": {
"type": "string",
"description": "Timestamp when the attachment was created.",
"format": "date-time",
"examples": [
"2026-03-30T09:05:00Z"
]
},
"url": {
"type": "string",
"description": "URL to fetch the attachment.",
"examples": [
"https://example.com/stop-attachment/attachment-2025-06-03-1"
]
}
},
"description": "An attachment to a stop, such as a proof of delivery photo or signature."
},
"description": "Proof of delivery photos for the stop. Photos may be fetched using the URLs\n on the attachments."
},
"proofOfDeliverySignatures": {
"type": "array",
"items": {
"title": "StopAttachment",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Attachment ID (e.g. `\"att-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"att-123e4567-e89b-12d3-a456-426614174000"
]
},
"createdAt": {
"type": "string",
"description": "Timestamp when the attachment was created.",
"format": "date-time",
"examples": [
"2026-03-30T09:05:00Z"
]
},
"url": {
"type": "string",
"description": "URL to fetch the attachment.",
"examples": [
"https://example.com/stop-attachment/attachment-2025-06-03-1"
]
}
},
"description": "An attachment to a stop, such as a proof of delivery photo or signature."
},
"description": "Proof of delivery signatures for the stop. Signatures may be fetched using\n the URLs on the attachments."
},
"tasks": {
"type": "array",
"items": {
"title": "Task",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Task ID (e.g. `\"tsk-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"tsk-123e4567-e89b-12d3-a456-426614174000"
]
},
"title": {
"type": "string",
"description": "Task title (e.g. `\"Delivery checklist\"`).",
"examples": [
"Delivery checklist"
]
},
"type": {
"enum": [
"UNKNOWN",
"CHECKBOXES",
"RADIO_BUTTONS",
"TEXT_INPUT",
"DECIMAL_INPUT",
"SCANNER_INPUT"
],
"type": "string",
"description": "Task type.",
"format": "enum",
"examples": [
"TEXT_INPUT"
]
},
"items": {
"type": "array",
"items": {
"title": "TaskItem",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Item ID (e.g. `\"itm-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"itm-123e4567-e89b-12d3-a456-426614174000"
]
},
"title": {
"type": "string",
"description": "Item title (e.g. `\"Pick up package\"`).",
"examples": [
"Pick up package"
]
},
"complete": {
"type": "boolean",
"description": "Whether the item is completed.",
"examples": [
true
]
},
"updatedAt": {
"type": "string",
"description": "Timestamp when the item was last updated.",
"format": "date-time",
"examples": [
"2026-03-30T13:00:00Z"
]
}
},
"description": "An item within a task. For `CHECKBOXES`, each item on a task may be completed\n independently. For `RADIO_BUTTONS`, at most one item will be completed."
},
"description": "Task items (populated for `CHECKBOXES` and `RADIO_BUTTONS`).",
"examples": [
[]
]
},
"input": {
"allOf": [
{
"title": "TaskInput",
"type": "object",
"properties": {
"value": {
"type": "string",
"description": "Input value.",
"examples": [
"020123456789"
]
},
"updatedAt": {
"type": "string",
"description": "Timestamp when the input was last updated.",
"format": "date-time",
"examples": [
"2026-03-30T13:00:00Z"
]
},
"inputMethod": {
"enum": [
"UNKNOWN",
"SCANNED"
],
"type": "string",
"description": "Whether input was scanned (e.g. a scanned barcode)",
"format": "enum",
"examples": [
"SCANNED"
]
}
},
"description": "Captured driver input for a task. The value may be text for `TEXT_INPUT`\n tasks or a string decimal number for `DECIMAL_INPUT` tasks."
}
],
"description": "Task input (populated for `TEXT_INPUT` and `DECIMAL_INPUT`)."
},
"requiredToMarkStopAsDelivered": {
"type": "boolean",
"description": "Whether the task is required to mark the stop as completed. In the case of\n tasks on `RouteStart`, this represents tasks required for starting the\n route. In the case of tasks on `RouteEnd`, this represents tasks required\n for completing the route.",
"examples": [
true
]
},
"requiredToMarkStopAsAttempted": {
"type": "boolean",
"description": "Whether the task is required to mark the stop as attempted.",
"examples": [
true
]
}
},
"description": "A task to be completed at a stop, or at the start or end of a route. Tasks\n may have one or more items for `CHECKBOXES` or `RADIO_BUTTONS`, or may have\n an input for `TEXT_INPUT` or `DECIMAL_INPUT`."
},
"description": "Driver tasks for the stop, including completed items and any input from the\n driver."
},
"priority": {
"maximum": 10,
"type": "integer",
"description": "Priority of the stop for route planning. The valid range for stop priority\n is between `1` (low) and `10` (high), with default priority corresponding\n to a value of `5`. A priority value of `0` is considered unset and is\n treated the same as \"default\" priority. Stops with higher priority will be\n preferred when generating routes with constraints.",
"format": "int32",
"examples": [
8
]
},
"importedStopId": {
"type": "string",
"description": "The imported stop ID, populated when the stop source is `IMPORTED_STOP`.",
"examples": [
"ist-123e4567-e89b-12d3-a456-426614174000"
]
},
"orderName": {
"type": "string",
"description": "The name of the order associated with the stop. For Shopify orders, the\n name is generated by combining the `orderNumber` property with the order\n prefix and suffix that are set in the merchant's general settings. For\n EasyRoutes imported orders, this field is populated with the order name\n provided on import.",
"examples": [
"#1234"
]
},
"distanceMeters": {
"type": "number",
"description": "The distance in meters from the previous stop.",
"format": "double",
"examples": [
123.45
]
},
"updatedArrival": {
"type": "string",
"description": "Estimated arrival time at the stop. If the stop is completed, this will be\n the actual arrival time.",
"format": "date-time",
"examples": [
"2026-03-30T13:05:00Z"
]
},
"timeWindows": {
"type": "array",
"items": {
"title": "TimeWindow",
"type": "object",
"properties": {
"start": {
"allOf": [
{
"title": "TimeOfDay",
"type": "object",
"properties": {
"hours": {
"maximum": 23,
"type": "integer",
"description": "Hours of day in 24 hour format. Must be from 0 to 23.",
"format": "int32",
"examples": [
13
]
},
"minutes": {
"maximum": 59,
"type": "integer",
"description": "Minutes of hour of day. Must be from 0 to 59.",
"format": "int32",
"examples": [
37
]
},
"seconds": {
"maximum": 59,
"type": "integer",
"description": "Seconds of minutes of the time. Must be from 0 to 59.",
"format": "int32",
"examples": [
16
]
}
},
"description": "A time of day, independent of a particular date or timezone."
}
],
"description": "The start time of the time window (optional)."
},
"end": {
"allOf": [
{
"title": "TimeOfDay",
"type": "object",
"properties": {
"hours": {
"maximum": 23,
"type": "integer",
"description": "Hours of day in 24 hour format. Must be from 0 to 23.",
"format": "int32",
"examples": [
13
]
},
"minutes": {
"maximum": 59,
"type": "integer",
"description": "Minutes of hour of day. Must be from 0 to 59.",
"format": "int32",
"examples": [
37
]
},
"seconds": {
"maximum": 59,
"type": "integer",
"description": "Seconds of minutes of the time. Must be from 0 to 59.",
"format": "int32",
"examples": [
16
]
}
},
"description": "A time of day, independent of a particular date or timezone."
}
],
"description": "The end time of the time window (optional)."
}
},
"description": "A time window for a stop. The time window may be open-ended, but one or both\n of the start and end times should be provided. The end time must be >= the\n start time."
},
"description": "The time window for the stop. Note that we currently support at most one\n time window but may support multiple time windows in the future.",
"examples": [
[
{
"start": {
"hours": 9
},
"end": {
"hours": 17
}
}
]
]
},
"deliveryDate": {
"allOf": [
{
"title": "Date",
"required": [
"year",
"month",
"day"
],
"type": "object",
"properties": {
"year": {
"maximum": 9999,
"minimum": 1,
"type": "integer",
"description": "Year of the date. Must be from 1 to 9999.",
"format": "int32",
"examples": [
2019
]
},
"month": {
"maximum": 12,
"minimum": 1,
"type": "integer",
"description": "Month of a year. Must be from 1 to 12.",
"format": "int32",
"examples": [
11
]
},
"day": {
"maximum": 31,
"minimum": 1,
"type": "integer",
"description": "Day of a month. Must be from 1 to 31.",
"format": "int32",
"examples": [
15
]
}
},
"description": "A date in year-month-day format."
}
],
"description": "The planned delivery date for the stop.",
"examples": [
{
"year": 2025,
"month": 12,
"day": 16
}
]
},
"attributes": {
"type": "array",
"items": {
"title": "Attribute",
"type": "object",
"properties": {
"key": {
"type": "string",
"description": "Attribute key. Must be non-empty.",
"examples": [
"delivery_date"
]
},
"value": {
"type": "string",
"description": "Attribute value.",
"examples": [
"2025-12-16"
]
}
},
"description": "A key-value pair for storing additional information on a stop, such as order\n details, delivery instructions, or custom fields."
},
"description": "Additional attributes for the stop. Attributes are key-value pairs for\n storing additional structured data on stops. These may be populated from\n the Shopify order or set on import.",
"examples": [
[
{
"key": "color",
"value": "blue"
}
]
]
},
"clientStopId": {
"type": "string",
"description": "The client-provided ID associated with the stop, if provided on import.",
"examples": [
"test-order-1234"
]
},
"tags": {
"type": "array",
"items": {
"type": "string"
},
"description": "The tags for the stop. Tags are used to categorize stops and can be used\n for filtering and grouping stops in the EasyRoutes web app. These may be\n populated from the Shopify order or set on import.",
"examples": [
[
"foo",
"bar"
]
]
},
"attemptedReason": {
"enum": [
"UNKNOWN",
"NOT_AVAILABLE",
"ACCESS_DENIED",
"INCORRECT_ADDRESS",
"SAFE_PLACE_UNAVAILABLE",
"REFUSED",
"EXTERNAL",
"INCORRECT_ITEMS",
"OTHER",
"CANCELED"
],
"type": "string",
"description": "The reason for marking the stop as attempted. This is only populated when\n `deliveryStatus = ATTEMPTED_DELIVERY`.",
"format": "enum",
"examples": [
"NOT_AVAILABLE"
]
},
"attemptedNote": {
"type": "string",
"description": "Optional note related to the reason for marking the stop as attempted. This\n is optionally populated when `deliveryStatus = ATTEMPTED_DELIVERY`.",
"examples": [
"Customer did not answer the door."
]
},
"customerRating": {
"allOf": [
{
"title": "CustomerRating",
"type": "object",
"properties": {
"rating": {
"maximum": 5,
"minimum": 1,
"type": "integer",
"description": "Rating from 1-5",
"format": "int32",
"examples": [
5
]
},
"comment": {
"type": "string",
"description": "Customer comment related to rating",
"examples": [
"Excellent delivery"
]
},
"createdAt": {
"type": "string",
"description": "Timestamp when rating was left by customer.",
"format": "date-time",
"examples": [
"2026-03-30T18:00:00Z"
]
}
},
"description": "Customer rating and feedback left on a stop."
}
],
"description": "Rating left by customer. This can only be populated once `deliveryStatus =\n DELIVERED`."
},
"customSignatureDisclosure": {
"type": "string",
"description": "Optional custom signature disclosure that is shown to customers in the\n driver app.",
"examples": [
"I acknowledge that I have received this delivery."
]
},
"shopifyOrder": {
"allOf": [
{
"title": "ShopifyOrder",
"type": "object",
"properties": {
"orderNote": {
"type": "string",
"description": "The Shopify order note.",
"examples": [
"Customer has paid."
]
},
"customerNote": {
"type": "string",
"description": "The Shopify customer note for the order.",
"examples": [
"Leave at door."
]
}
},
"description": "Shopify-specific information for a RouteStop."
}
],
"description": "Information from the associated Shopify order, if applicable. Populated if\n stop source is `SHOPIFY_ORDER`"
},
"proofOfDeliveryBarcodes": {
"type": "array",
"items": {
"title": "ScannedBarcode",
"type": "object",
"properties": {
"value": {
"type": "string",
"description": "Barcode value (e.g. `\"123456789012\"`).",
"examples": [
"123456789012"
]
},
"createdAt": {
"type": "string",
"description": "Timestamp when the barcode was scanned.",
"format": "date-time",
"examples": [
"2026-03-30T13:10:00Z"
]
}
},
"description": "A proof of delivery barcode scanned at a stop."
},
"description": "Proof of delivery barcodes scanned at the stop."
},
"proofOfDeliveryBarcodeIssues": {
"type": "array",
"items": {
"title": "ScannedBarcodeIssue",
"type": "object",
"properties": {
"reason": {
"enum": [
"UNKNOWN",
"ITEM_MISSING",
"NOT_SCANNABLE",
"INCORRECT"
],
"type": "string",
"description": "The reported reason for the barcode issue.",
"format": "enum",
"examples": [
"ITEM_MISSING"
]
},
"note": {
"type": "string",
"description": "Optional note related to the reason for reporting a barcode issue.",
"examples": [
"Item was not packed."
]
},
"createdAt": {
"type": "string",
"description": "Timestamp when the issue was reported.",
"format": "date-time",
"examples": [
"2026-03-30T13:10:00Z"
]
}
},
"description": "A reported issue related to scanning barcodes at a stop."
},
"description": "Proof of delivery barcode issues reported at the stop."
},
"orderReferenceUrl": {
"type": "string",
"description": "A reference URL for the order associated with the stop (e.g. a link to the\n order in your order management system). Must be a valid HTTPS URL. This\n field can only be populated for imported stops.",
"examples": [
"https://orders.example.com/orders/148977776"
]
}
},
"description": "A stop on a route. A stop may correspond to a delivery or a driver break as\n determined by the type. A delivery stop will have location and contact\n information, items to deliver, optional order details, status, arrival time\n and stop duration, driver tasks and any proof of delivery information. A\n break stop will have start time and duration, and status."
},
"description": "Route stops. See RouteStop for stop fields."
},
"createdAt": {
"type": "string",
"description": "Timestamp when the route was created.",
"format": "date-time",
"examples": [
"2026-03-29T08:00:00Z"
]
},
"updatedAt": {
"type": "string",
"description": "Timestamp when the route was last updated (by the planner).",
"format": "date-time",
"examples": [
"2026-03-30T13:15:00Z"
]
},
"archivedAt": {
"type": "string",
"description": "Timestamp when the route was archived.",
"format": "date-time",
"examples": [
"2026-04-05T00:00:00Z"
]
},
"scheduledFor": {
"type": "string",
"description": "Timestamp when the route is scheduled for.",
"format": "date-time",
"examples": [
"2026-03-30T09:00:00Z"
]
},
"totalDistanceMeters": {
"type": "number",
"description": "The distance in meters for the entire route.",
"format": "double",
"examples": [
2387.2
]
},
"totalItemQuantity": {
"type": "integer",
"description": "The total quantity of items to deliver on the route.",
"format": "int32",
"examples": [
50
]
},
"totalItemGrams": {
"type": "string",
"description": "The total weight in grams for the items on the route.",
"examples": [
"6000"
]
},
"optimized": {
"type": "boolean",
"description": "Whether the route has been optimized. Adding or removing stops, reordering\n stops, or changing route options generally set this field to false until\n the route is reoptimized.",
"examples": [
true
]
},
"dispatchedUntil": {
"type": "string",
"description": "Timestamp until which the route is dispatched and accessible in the driver\n app.",
"format": "date-time",
"examples": [
"2026-03-30T20:00:00Z"
]
},
"note": {
"type": "string",
"description": "Top-level note for the route, as entered manually by route planners.",
"examples": [
"Fragile items."
]
},
"tags": {
"type": "array",
"items": {
"type": "string"
},
"description": "The tags for the route. Tags are used to categorize routes and can be\n used for filtering and grouping routes in the EasyRoutes web app.",
"examples": [
[
"foo",
"bar"
]
]
},
"defaultStopDuration": {
"pattern": "^-?(?:0|[1-9][0-9]{0,11})(?:\\.[0-9]{1,9})?s$",
"type": "string",
"description": "The default duration for stops on the route. Used to estimate arrival\n times for stops that do not have their own duration specified.\n Specified as a duration string in the format \"300s\" for 5 minutes, \"60s\"\n for 1 minute, etc.",
"examples": [
"300s"
]
},
"maxDuration": {
"pattern": "^-?(?:0|[1-9][0-9]{0,11})(?:\\.[0-9]{1,9})?s$",
"type": "string",
"description": "The maximum duration of the route. Specified as a duration string in the\n format \"3600s\" for 1 hour, \"7200s\" for 2 hours, etc.",
"examples": [
"28800s"
]
},
"maxStops": {
"type": "integer",
"description": "The maximum number of stops on the route.",
"format": "int32",
"examples": [
50
]
},
"maxItemCount": {
"type": "integer",
"description": "The maximum total item count across all stops on the route.",
"format": "int32",
"examples": [
200
]
},
"maxKilograms": {
"type": "number",
"description": "The maximum total weight in kilograms across all stops on the route.",
"format": "double",
"examples": [
500
]
},
"avoidTolls": {
"type": "boolean",
"description": "Whether to avoid toll roads during optimization.",
"examples": [
true
]
},
"avoidUTurns": {
"type": "boolean",
"description": "Whether to avoid U-turns during optimization.",
"examples": [
true
]
},
"speedFactor": {
"type": "number",
"description": "A speed factor for the route used during optimization to adjust estimated\n travel times. A value of 1.0 represents normal speed. Values less than 1.0\n indicate slower travel (e.g. 0.5 = half speed), and values greater than\n 1.0 indicate faster travel (e.g. 1.5 = 50% faster). Must be between 0.1\n and 1.9. A value of 0 (or unset) uses the default speed.",
"format": "double",
"examples": [
0.8
]
},
"vehicle": {
"allOf": [
{
"title": "Vehicle",
"required": [
"id"
],
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Vehicle ID.",
"examples": [
"veh-123e4567-e89b-12d3-a456-426614174000"
]
},
"name": {
"type": "string",
"description": "Vehicle name.",
"examples": [
"Delivery Van 1"
]
},
"make": {
"type": "string",
"description": "Vehicle make.",
"examples": [
"Ford"
]
},
"model": {
"type": "string",
"description": "Vehicle model.",
"examples": [
"Transit"
]
},
"year": {
"type": "integer",
"description": "Vehicle model year.",
"format": "int32",
"examples": [
2023
]
},
"type": {
"enum": [
"UNKNOWN",
"CAR",
"CARGO_VAN",
"PICKUP_TRUCK",
"BOX_TRUCK",
"MOTORCYCLE",
"BICYCLE",
"DRONE",
"OTHER"
],
"type": "string",
"description": "Vehicle type.",
"format": "enum",
"examples": [
"CARGO_VAN"
]
},
"vin": {
"type": "string",
"description": "Vehicle Identification Number.",
"examples": [
"1FTBW2CM5NKA12345"
]
},
"license": {
"type": "string",
"description": "Vehicle license plate.",
"examples": [
"ABC-1234"
]
},
"isArchived": {
"type": "boolean",
"description": "Whether the vehicle is archived.",
"examples": [
false
]
},
"createdTimestamp": {
"type": "string",
"description": "Timestamp when the vehicle was created.",
"format": "date-time",
"examples": [
"2026-07-30T12:00:00Z"
]
}
},
"description": "A vehicle that can be assigned to a route."
}
],
"description": "Assigned vehicle for the route."
}
},
"description": "A route of stops, optionally with an assigned driver."
}
}
}
},
"default": {
"description": "Default error response",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"code": {
"type": "integer",
"description": "The status code, which should be an enum value of [google.rpc.Code][google.rpc.Code].",
"format": "int32"
},
"message": {
"type": "string",
"description": "A developer-facing error message, which should be in English. Any user-facing error message should be localized and sent in the [google.rpc.Status.details][google.rpc.Status.details] field, or localized by the client."
},
"details": {
"type": "array",
"items": {
"type": "object",
"properties": {
"@type": {
"type": "string",
"description": "The type of the serialized message."
}
},
"additionalProperties": true,
"description": "Contains an arbitrary serialized message along with a @type that describes the type of the serialized message."
},
"description": "A list of messages that carry the error details. There is a common set of message types for APIs to use."
}
},
"description": "The `Status` type defines a logical error model that is suitable for different programming environments, including REST APIs and RPC APIs. It is used by [gRPC](https://github.com/grpc). Each `Status` message contains three pieces of data: error code, error message, and error details. You can find out more about this error model and how to work with it in the [API Design Guide](https://cloud.google.com/apis/design/errors)."
}
}
}
}
},
"security": [
{
"bearerAuth": []
}
],
"components": {
"securitySchemes": {
"bearerAuth": {
"type": "http",
"description": "Access token from `/authenticate`",
"scheme": "bearer",
"bearerFormat": "JWT"
}
}
}
}
```
# Create route (https://docs.roundtrip.ai/docs/api-reference/routes/post-routes)
POST /routes
Create an empty route with a specified start and end location. The request
body should include a start location and an optional end location. The
returned response is the created route.
## OpenAPI specification
```json
{
"servers": [
{
"url": "https://easyroutes.roundtrip.ai/api/2024-07"
}
],
"tags": [
"Routes"
],
"summary": "Create route",
"description": "Create an empty route with a specified start and end location. The request\n body should include a start location and an optional end location. The\n returned response is the created route.",
"operationId": "CreateRoute",
"parameters": [
{
"name": "Idempotency-Key",
"in": "header",
"description": "A unique key for safely retrying this operation. For more information read [our guide](https://docs.roundtrip.ai/docs/concepts/idempotency.md).",
"schema": {
"maxLength": 255,
"minLength": 1,
"type": "string"
},
"examples": {
"default": {
"value": "550e8400-e29b-41d4-a716-446655440000"
}
}
}
],
"requestBody": {
"content": {
"application/json": {
"schema": {
"title": "CreateRouteRequest",
"required": [
"start"
],
"type": "object",
"properties": {
"start": {
"allOf": [
{
"title": "CreateRouteLocation",
"required": [
"address"
],
"type": "object",
"properties": {
"address": {
"allOf": [
{
"title": "Address",
"type": "object",
"properties": {
"address1": {
"type": "string",
"description": "Street address line 1 (e.g. `\"123 Main St\"`).",
"examples": [
"123 Main St"
]
},
"address2": {
"type": "string",
"description": "Street address line 2 (e.g. `\"Apt 101\"`).",
"examples": [
"Apt 3B"
]
},
"city": {
"type": "string",
"description": "City name (e.g. `\"New York\"`).",
"examples": [
"New York"
]
},
"provinceCode": {
"type": "string",
"description": "Province or state as subdivision codes in\n [ISO 3166-2](https://en.wikipedia.org/wiki/ISO_3166-2) format without the\n country prefix (e.g. `\"NY\"` for New York).",
"examples": [
"NY"
]
},
"countryCode": {
"type": "string",
"description": "Country code (e.g. `\"US\"`).",
"examples": [
"US"
]
},
"zip": {
"type": "string",
"description": "Postal or ZIP code (e.g. `\"10001\"`).",
"examples": [
"10001"
]
}
},
"description": "A physical street address."
}
],
"description": "The address for the location.",
"examples": [
{
"address1": "123 Main St",
"address2": "Apt 3B",
"city": "New York",
"provinceCode": "NY",
"countryCode": "US",
"zip": "10001"
}
]
},
"coordinates": {
"allOf": [
{
"type": "object",
"properties": {
"latitude": {
"type": "number",
"description": "The latitude in degrees. It must be in the range [-90.0, +90.0].",
"format": "double"
},
"longitude": {
"type": "number",
"description": "The longitude in degrees. It must be in the range [-180.0, +180.0].",
"format": "double"
}
},
"description": "An object that represents a latitude/longitude pair. This is expressed as a\n pair of doubles to represent degrees latitude and degrees longitude. Unless\n specified otherwise, this must conform to the\n WGS84\n standard. Values must be within normalized ranges."
}
],
"description": "(Optional) The coordinates for the location. If not provided, the\n coordinates will be geocoded from the address.",
"examples": [
{
"latitude": 40.7128,
"longitude": -74.006
}
]
}
}
}
],
"description": "The start location of the route."
},
"end": {
"allOf": [
{
"title": "CreateRouteLocation",
"required": [
"address"
],
"type": "object",
"properties": {
"address": {
"allOf": [
{
"title": "Address",
"type": "object",
"properties": {
"address1": {
"type": "string",
"description": "Street address line 1 (e.g. `\"123 Main St\"`).",
"examples": [
"123 Main St"
]
},
"address2": {
"type": "string",
"description": "Street address line 2 (e.g. `\"Apt 101\"`).",
"examples": [
"Apt 3B"
]
},
"city": {
"type": "string",
"description": "City name (e.g. `\"New York\"`).",
"examples": [
"New York"
]
},
"provinceCode": {
"type": "string",
"description": "Province or state as subdivision codes in\n [ISO 3166-2](https://en.wikipedia.org/wiki/ISO_3166-2) format without the\n country prefix (e.g. `\"NY\"` for New York).",
"examples": [
"NY"
]
},
"countryCode": {
"type": "string",
"description": "Country code (e.g. `\"US\"`).",
"examples": [
"US"
]
},
"zip": {
"type": "string",
"description": "Postal or ZIP code (e.g. `\"10001\"`).",
"examples": [
"10001"
]
}
},
"description": "A physical street address."
}
],
"description": "The address for the location.",
"examples": [
{
"address1": "123 Main St",
"address2": "Apt 3B",
"city": "New York",
"provinceCode": "NY",
"countryCode": "US",
"zip": "10001"
}
]
},
"coordinates": {
"allOf": [
{
"type": "object",
"properties": {
"latitude": {
"type": "number",
"description": "The latitude in degrees. It must be in the range [-90.0, +90.0].",
"format": "double"
},
"longitude": {
"type": "number",
"description": "The longitude in degrees. It must be in the range [-180.0, +180.0].",
"format": "double"
}
},
"description": "An object that represents a latitude/longitude pair. This is expressed as a\n pair of doubles to represent degrees latitude and degrees longitude. Unless\n specified otherwise, this must conform to the\n WGS84\n standard. Values must be within normalized ranges."
}
],
"description": "(Optional) The coordinates for the location. If not provided, the\n coordinates will be geocoded from the address.",
"examples": [
{
"latitude": 40.7128,
"longitude": -74.006
}
]
}
}
}
],
"description": "(Optional) The end location of the route."
},
"options": {
"allOf": [
{
"title": "RouteOptions",
"type": "object",
"properties": {
"scheduledFor": {
"allOf": [
{
"type": "object",
"properties": {
"year": {
"type": "integer",
"description": "Required. Year of date. Must be from 1 to 9999.",
"format": "int32"
},
"month": {
"type": "integer",
"description": "Required. Month of year. Must be from 1 to 12.",
"format": "int32"
},
"day": {
"type": "integer",
"description": "Required. Day of month. Must be from 1 to 31 and valid for the year and\n month.",
"format": "int32"
},
"hours": {
"type": "integer",
"description": "Required. Hours of day in 24 hour format. Should be from 0 to 23.",
"format": "int32"
},
"minutes": {
"type": "integer",
"description": "Required. Minutes of hour of day. Must be from 0 to 59.",
"format": "int32"
},
"seconds": {
"type": "integer",
"description": "Required. Seconds of minutes of the time. Must normally be from 0 to 59.",
"format": "int32"
},
"nanos": {
"type": "integer",
"description": "Required. Fractions of seconds in nanoseconds. Must be from 0 to\n 999,999,999.",
"format": "int32"
},
"timezone": {
"type": "string",
"description": "Required. IANA Time Zone Database time zone, e.g.\n \"America/New_York\"."
}
},
"description": "A date and time with a timezone."
}
],
"description": "The date and time the route is scheduled for.",
"examples": [
{
"year": 2026,
"month": 3,
"day": 30,
"hours": 9,
"minutes": 0,
"seconds": 0,
"nanos": 0,
"timezone": "America/Toronto"
}
]
},
"maxDuration": {
"pattern": "^-?(?:0|[1-9][0-9]{0,11})(?:\\.[0-9]{1,9})?s$",
"type": "string",
"description": "The maximum duration of the route. Specified as a duration string in the\n format \"3600s\" for 1 hour, \"7200s\" for 2 hours, etc.",
"examples": [
"28800s"
]
},
"maxStops": {
"type": "integer",
"description": "The maximum number of stops on the route.",
"format": "int32",
"examples": [
50
]
},
"maxItemCount": {
"type": "integer",
"description": "The maximum total item count across all stops on the route.",
"format": "int32",
"examples": [
200
]
},
"maxKilograms": {
"type": "number",
"description": "The maximum total weight in kilograms across all stops on the route.",
"format": "double",
"examples": [
500
]
},
"avoidTolls": {
"type": "boolean",
"description": "Whether to avoid toll roads during optimization.",
"examples": [
true
]
},
"avoidUTurns": {
"type": "boolean",
"description": "Whether to avoid U-turns during optimization.",
"examples": [
true
]
},
"name": {
"type": "string",
"description": "The name of the route. If not provided, a default name will be generated.",
"examples": [
"Default Route"
]
},
"speedFactor": {
"type": "number",
"description": "A speed factor for the route used during optimization to adjust estimated\n travel times. A value of 1.0 represents normal speed. Values less than 1.0\n indicate slower travel (e.g. 0.5 = half speed), and values greater than 1.0\n indicate faster travel (e.g. 1.5 = 50% faster). Must be between 0.1 and\n 1.9. A value of 0 (or unset) uses the default speed.",
"format": "double",
"examples": [
0.8
]
}
},
"description": "Optional configuration for a route."
}
],
"description": "(Optional) Route options."
}
},
"description": "Request to create an empty route."
}
}
},
"required": true
},
"responses": {
"200": {
"description": "OK",
"headers": {
"Idempotency-Key": {
"description": "The idempotency key associated with the response.",
"schema": {
"type": "string"
}
},
"Idempotency-Replayed": {
"description": "Whether the response was replayed from a previous request.",
"schema": {
"type": "boolean"
}
}
},
"content": {
"application/json": {
"schema": {
"title": "Route",
"required": [
"id",
"name",
"stops",
"createdAt",
"updatedAt",
"totalDistanceMeters",
"totalItemQuantity",
"totalItemGrams",
"optimized"
],
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Route ID (e.g. `\"rte-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"rte-123e4567-e89b-12d3-a456-426614174000"
]
},
"name": {
"type": "string",
"description": "Route name (e.g. `\"Morning route\"`).",
"examples": [
"Morning route"
]
},
"driver": {
"allOf": [
{
"title": "Driver",
"required": [
"id"
],
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Driver ID (e.g. `\"drv-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"drv-123e4567-e89b-12d3-a456-426614174000"
]
},
"firstName": {
"type": "string",
"description": "Driver first name (e.g. `\"John\"`).",
"examples": [
"John"
]
},
"lastName": {
"type": "string",
"description": "Driver last name (e.g. `\"Doe\"`).",
"examples": [
"Doe"
]
},
"phone": {
"type": "string",
"description": "Driver phone number in [E.164 format](https://en.wikipedia.org/wiki/E.164)\n (e.g. `\"+14265551000\"`).",
"examples": [
"+14265551000"
]
},
"status": {
"enum": [
"UNKNOWN",
"ACTIVE",
"INACTIVE",
"ARCHIVED"
],
"type": "string",
"description": "Shop driver status. (e.g. `ACTIVE`).",
"format": "enum",
"examples": [
"ACTIVE"
]
}
},
"description": "A driver who is assigned to a route."
}
],
"description": "Assigned driver for the route."
},
"start": {
"allOf": [
{
"title": "RouteStart",
"type": "object",
"properties": {
"address": {
"allOf": [
{
"title": "Address",
"type": "object",
"properties": {
"address1": {
"type": "string",
"description": "Street address line 1 (e.g. `\"123 Main St\"`).",
"examples": [
"123 Main St"
]
},
"address2": {
"type": "string",
"description": "Street address line 2 (e.g. `\"Apt 101\"`).",
"examples": [
"Apt 3B"
]
},
"city": {
"type": "string",
"description": "City name (e.g. `\"New York\"`).",
"examples": [
"New York"
]
},
"provinceCode": {
"type": "string",
"description": "Province or state as subdivision codes in\n [ISO 3166-2](https://en.wikipedia.org/wiki/ISO_3166-2) format without the\n country prefix (e.g. `\"NY\"` for New York).",
"examples": [
"NY"
]
},
"countryCode": {
"type": "string",
"description": "Country code (e.g. `\"US\"`).",
"examples": [
"US"
]
},
"zip": {
"type": "string",
"description": "Postal or ZIP code (e.g. `\"10001\"`).",
"examples": [
"10001"
]
}
},
"description": "A physical street address."
}
],
"description": "The start address of the route.",
"examples": [
{
"address1": "123 Main St",
"address2": "Apt 3B",
"city": "New York",
"provinceCode": "NY",
"countryCode": "US",
"zip": "10001"
}
]
},
"tasks": {
"type": "array",
"items": {
"title": "Task",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Task ID (e.g. `\"tsk-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"tsk-123e4567-e89b-12d3-a456-426614174000"
]
},
"title": {
"type": "string",
"description": "Task title (e.g. `\"Delivery checklist\"`).",
"examples": [
"Delivery checklist"
]
},
"type": {
"enum": [
"UNKNOWN",
"CHECKBOXES",
"RADIO_BUTTONS",
"TEXT_INPUT",
"DECIMAL_INPUT",
"SCANNER_INPUT"
],
"type": "string",
"description": "Task type.",
"format": "enum",
"examples": [
"TEXT_INPUT"
]
},
"items": {
"type": "array",
"items": {
"title": "TaskItem",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Item ID (e.g. `\"itm-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"itm-123e4567-e89b-12d3-a456-426614174000"
]
},
"title": {
"type": "string",
"description": "Item title (e.g. `\"Pick up package\"`).",
"examples": [
"Pick up package"
]
},
"complete": {
"type": "boolean",
"description": "Whether the item is completed.",
"examples": [
true
]
},
"updatedAt": {
"type": "string",
"description": "Timestamp when the item was last updated.",
"format": "date-time",
"examples": [
"2026-03-30T13:00:00Z"
]
}
},
"description": "An item within a task. For `CHECKBOXES`, each item on a task may be completed\n independently. For `RADIO_BUTTONS`, at most one item will be completed."
},
"description": "Task items (populated for `CHECKBOXES` and `RADIO_BUTTONS`).",
"examples": [
[]
]
},
"input": {
"allOf": [
{
"title": "TaskInput",
"type": "object",
"properties": {
"value": {
"type": "string",
"description": "Input value.",
"examples": [
"020123456789"
]
},
"updatedAt": {
"type": "string",
"description": "Timestamp when the input was last updated.",
"format": "date-time",
"examples": [
"2026-03-30T13:00:00Z"
]
},
"inputMethod": {
"enum": [
"UNKNOWN",
"SCANNED"
],
"type": "string",
"description": "Whether input was scanned (e.g. a scanned barcode)",
"format": "enum",
"examples": [
"SCANNED"
]
}
},
"description": "Captured driver input for a task. The value may be text for `TEXT_INPUT`\n tasks or a string decimal number for `DECIMAL_INPUT` tasks."
}
],
"description": "Task input (populated for `TEXT_INPUT` and `DECIMAL_INPUT`)."
},
"requiredToMarkStopAsDelivered": {
"type": "boolean",
"description": "Whether the task is required to mark the stop as completed. In the case of\n tasks on `RouteStart`, this represents tasks required for starting the\n route. In the case of tasks on `RouteEnd`, this represents tasks required\n for completing the route.",
"examples": [
true
]
},
"requiredToMarkStopAsAttempted": {
"type": "boolean",
"description": "Whether the task is required to mark the stop as attempted.",
"examples": [
true
]
}
},
"description": "A task to be completed at a stop, or at the start or end of a route. Tasks\n may have one or more items for `CHECKBOXES` or `RADIO_BUTTONS`, or may have\n an input for `TEXT_INPUT` or `DECIMAL_INPUT`."
},
"description": "Tasks to complete before starting the route."
},
"status": {
"enum": [
"UNKNOWN",
"STARTED"
],
"type": "string",
"description": "Status indicating whether the route has been started.",
"format": "enum",
"examples": [
"STARTED"
]
},
"updatedStart": {
"type": "string",
"description": "Updated start time for the route. If the route is started, this will be the\n actual start time.",
"format": "date-time",
"examples": [
"2026-03-30T09:05:00Z"
]
},
"scheduledStart": {
"type": "string",
"description": "Scheduled start time for the route (same as `scheduledFor` on the route).",
"format": "date-time",
"examples": [
"2026-03-30T09:00:00Z"
]
},
"photos": {
"type": "array",
"items": {
"title": "StopAttachment",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Attachment ID (e.g. `\"att-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"att-123e4567-e89b-12d3-a456-426614174000"
]
},
"createdAt": {
"type": "string",
"description": "Timestamp when the attachment was created.",
"format": "date-time",
"examples": [
"2026-03-30T09:05:00Z"
]
},
"url": {
"type": "string",
"description": "URL to fetch the attachment.",
"examples": [
"https://example.com/stop-attachment/attachment-2025-06-03-1"
]
}
},
"description": "An attachment to a stop, such as a proof of delivery photo or signature."
},
"description": "Photos for the route start. Photos may be fetched using the URLs on the\n attachments."
}
},
"description": "The start location of a route and any driver tasks to complete before\n beginning the route."
}
],
"description": "Route start address and tasks."
},
"end": {
"allOf": [
{
"title": "RouteEnd",
"type": "object",
"properties": {
"address": {
"allOf": [
{
"title": "Address",
"type": "object",
"properties": {
"address1": {
"type": "string",
"description": "Street address line 1 (e.g. `\"123 Main St\"`).",
"examples": [
"123 Main St"
]
},
"address2": {
"type": "string",
"description": "Street address line 2 (e.g. `\"Apt 101\"`).",
"examples": [
"Apt 3B"
]
},
"city": {
"type": "string",
"description": "City name (e.g. `\"New York\"`).",
"examples": [
"New York"
]
},
"provinceCode": {
"type": "string",
"description": "Province or state as subdivision codes in\n [ISO 3166-2](https://en.wikipedia.org/wiki/ISO_3166-2) format without the\n country prefix (e.g. `\"NY\"` for New York).",
"examples": [
"NY"
]
},
"countryCode": {
"type": "string",
"description": "Country code (e.g. `\"US\"`).",
"examples": [
"US"
]
},
"zip": {
"type": "string",
"description": "Postal or ZIP code (e.g. `\"10001\"`).",
"examples": [
"10001"
]
}
},
"description": "A physical street address."
}
],
"description": "The end address of the route.",
"examples": [
{
"address1": "123 Main St",
"address2": "Apt 3B",
"city": "New York",
"provinceCode": "NY",
"countryCode": "US",
"zip": "10001"
}
]
},
"tasks": {
"type": "array",
"items": {
"title": "Task",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Task ID (e.g. `\"tsk-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"tsk-123e4567-e89b-12d3-a456-426614174000"
]
},
"title": {
"type": "string",
"description": "Task title (e.g. `\"Delivery checklist\"`).",
"examples": [
"Delivery checklist"
]
},
"type": {
"enum": [
"UNKNOWN",
"CHECKBOXES",
"RADIO_BUTTONS",
"TEXT_INPUT",
"DECIMAL_INPUT",
"SCANNER_INPUT"
],
"type": "string",
"description": "Task type.",
"format": "enum",
"examples": [
"TEXT_INPUT"
]
},
"items": {
"type": "array",
"items": {
"title": "TaskItem",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Item ID (e.g. `\"itm-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"itm-123e4567-e89b-12d3-a456-426614174000"
]
},
"title": {
"type": "string",
"description": "Item title (e.g. `\"Pick up package\"`).",
"examples": [
"Pick up package"
]
},
"complete": {
"type": "boolean",
"description": "Whether the item is completed.",
"examples": [
true
]
},
"updatedAt": {
"type": "string",
"description": "Timestamp when the item was last updated.",
"format": "date-time",
"examples": [
"2026-03-30T13:00:00Z"
]
}
},
"description": "An item within a task. For `CHECKBOXES`, each item on a task may be completed\n independently. For `RADIO_BUTTONS`, at most one item will be completed."
},
"description": "Task items (populated for `CHECKBOXES` and `RADIO_BUTTONS`).",
"examples": [
[]
]
},
"input": {
"allOf": [
{
"title": "TaskInput",
"type": "object",
"properties": {
"value": {
"type": "string",
"description": "Input value.",
"examples": [
"020123456789"
]
},
"updatedAt": {
"type": "string",
"description": "Timestamp when the input was last updated.",
"format": "date-time",
"examples": [
"2026-03-30T13:00:00Z"
]
},
"inputMethod": {
"enum": [
"UNKNOWN",
"SCANNED"
],
"type": "string",
"description": "Whether input was scanned (e.g. a scanned barcode)",
"format": "enum",
"examples": [
"SCANNED"
]
}
},
"description": "Captured driver input for a task. The value may be text for `TEXT_INPUT`\n tasks or a string decimal number for `DECIMAL_INPUT` tasks."
}
],
"description": "Task input (populated for `TEXT_INPUT` and `DECIMAL_INPUT`)."
},
"requiredToMarkStopAsDelivered": {
"type": "boolean",
"description": "Whether the task is required to mark the stop as completed. In the case of\n tasks on `RouteStart`, this represents tasks required for starting the\n route. In the case of tasks on `RouteEnd`, this represents tasks required\n for completing the route.",
"examples": [
true
]
},
"requiredToMarkStopAsAttempted": {
"type": "boolean",
"description": "Whether the task is required to mark the stop as attempted.",
"examples": [
true
]
}
},
"description": "A task to be completed at a stop, or at the start or end of a route. Tasks\n may have one or more items for `CHECKBOXES` or `RADIO_BUTTONS`, or may have\n an input for `TEXT_INPUT` or `DECIMAL_INPUT`."
},
"description": "Tasks to complete before finishing the route."
},
"plannedArrival": {
"type": "string",
"description": "Planned arrival time at the end of the route.",
"format": "date-time",
"examples": [
"2026-03-30T17:00:00Z"
]
},
"distanceMeters": {
"type": "number",
"description": "The distance in meters from the previous stop.",
"format": "double",
"examples": [
1234.56
]
},
"updatedArrival": {
"type": "string",
"description": "Estimated arrival time at the end of the route. If the route is completed,\n this will be the actual arrival time.",
"format": "date-time",
"examples": [
"2026-03-30T17:05:00Z"
]
},
"status": {
"enum": [
"UNKNOWN",
"COMPLETED"
],
"type": "string",
"description": "Status indicating whether the route has been completed.",
"format": "enum",
"examples": [
"COMPLETED"
]
},
"photos": {
"type": "array",
"items": {
"title": "StopAttachment",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Attachment ID (e.g. `\"att-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"att-123e4567-e89b-12d3-a456-426614174000"
]
},
"createdAt": {
"type": "string",
"description": "Timestamp when the attachment was created.",
"format": "date-time",
"examples": [
"2026-03-30T09:05:00Z"
]
},
"url": {
"type": "string",
"description": "URL to fetch the attachment.",
"examples": [
"https://example.com/stop-attachment/attachment-2025-06-03-1"
]
}
},
"description": "An attachment to a stop, such as a proof of delivery photo or signature."
},
"description": "Photos for the route end. Photos may be fetched using the URLs on the\n attachments."
}
},
"description": "The end location of a route and any driver tasks to complete after completing\n the route."
}
],
"description": "Route end address and tasks."
},
"stops": {
"type": "array",
"items": {
"title": "RouteStop",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Stop ID (e.g. `\"rst-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"rst-123e4567-e89b-12d3-a456-426614174000"
]
},
"type": {
"enum": [
"UNKNOWN",
"DELIVERY",
"BREAK",
"PICKUP",
"TASK"
],
"type": "string",
"description": "The type of stop (DELIVERY, BREAK, PICKUP, or TASK).",
"format": "enum",
"examples": [
"DELIVERY"
]
},
"deliveryStatus": {
"enum": [
"UNKNOWN",
"DELIVERED",
"OUT_FOR_DELIVERY",
"ATTEMPTED_DELIVERY",
"READY_FOR_DELIVERY"
],
"type": "string",
"description": "The status for DELIVERY, PICKUP, or TASK stops.",
"format": "enum",
"examples": [
"ATTEMPTED_DELIVERY"
]
},
"breakStatus": {
"enum": [
"UNKNOWN",
"COMPLETED"
],
"type": "string",
"description": "The status for BREAK stops.",
"format": "enum",
"examples": [
"COMPLETED"
]
},
"updatedAt": {
"type": "string",
"description": "Timestamp when the stop status was last updated. Note that this timestamp\n corresponds only to major status updates (i.e. stop marked as DELIVERED).\n Minor updates like task completion or adding proof of delivery will not\n advance this timestamp. For those events, use the timestamps on the task or\n proof of delivery attachment.",
"format": "date-time",
"examples": [
"2026-03-30T13:15:00Z"
]
},
"duration": {
"pattern": "^-?(?:0|[1-9][0-9]{0,11})(?:\\.[0-9]{1,9})?s$",
"type": "string",
"description": "Planned duration of the stop in seconds.",
"examples": [
"300s"
]
},
"plannedArrival": {
"type": "string",
"description": "Planned arrival time at the stop.",
"format": "date-time",
"examples": [
"2026-03-30T13:00:00Z"
]
},
"note": {
"type": "string",
"description": "Top-level note for the stop, as entered manually by route planners,\n inherited from a saved or imported stop, or set by order import automation\n rules.",
"examples": [
"Leave at door."
]
},
"address": {
"allOf": [
{
"title": "Address",
"type": "object",
"properties": {
"address1": {
"type": "string",
"description": "Street address line 1 (e.g. `\"123 Main St\"`).",
"examples": [
"123 Main St"
]
},
"address2": {
"type": "string",
"description": "Street address line 2 (e.g. `\"Apt 101\"`).",
"examples": [
"Apt 3B"
]
},
"city": {
"type": "string",
"description": "City name (e.g. `\"New York\"`).",
"examples": [
"New York"
]
},
"provinceCode": {
"type": "string",
"description": "Province or state as subdivision codes in\n [ISO 3166-2](https://en.wikipedia.org/wiki/ISO_3166-2) format without the\n country prefix (e.g. `\"NY\"` for New York).",
"examples": [
"NY"
]
},
"countryCode": {
"type": "string",
"description": "Country code (e.g. `\"US\"`).",
"examples": [
"US"
]
},
"zip": {
"type": "string",
"description": "Postal or ZIP code (e.g. `\"10001\"`).",
"examples": [
"10001"
]
}
},
"description": "A physical street address."
}
],
"description": "Delivery address for the stop.",
"examples": [
{
"address1": "123 Main St",
"address2": "Apt 3B",
"city": "New York",
"provinceCode": "NY",
"countryCode": "US",
"zip": "10001"
}
]
},
"contact": {
"allOf": [
{
"title": "Contact",
"type": "object",
"properties": {
"firstName": {
"type": "string",
"description": "First name (e.g. `\"John\"`).",
"examples": [
"John"
]
},
"lastName": {
"type": "string",
"description": "Last name (e.g. `\"Doe\"`).",
"examples": [
"Doe"
]
},
"company": {
"type": "string",
"description": "Company name (e.g. `\"Roundtrip Systems Inc\"`).",
"examples": [
"Roundtrip Systems Inc"
]
},
"phone": {
"type": "string",
"description": "Phone number in [E.164 format](https://en.wikipedia.org/wiki/E.164) (e.g.\n `\"+14265551000\"`).",
"examples": [
"+14265551000"
]
},
"email": {
"type": "string",
"description": "Email address (e.g. `\"john.doe@roundtrip.ai\"`)",
"examples": [
"john.doe@roundtrip.ai"
]
}
},
"description": "Contact information for a person or company."
}
],
"description": "Contact information for the stop delivery recipient.",
"examples": [
{
"firstName": "John",
"lastName": "Doe",
"company": "Roundtrip Systems Inc",
"phone": "+14265551000",
"email": "john.doe@roundtrip.ai"
}
]
},
"plannedCoordinates": {
"allOf": [
{
"type": "object",
"properties": {
"latitude": {
"type": "number",
"description": "The latitude in degrees. It must be in the range [-90.0, +90.0].",
"format": "double"
},
"longitude": {
"type": "number",
"description": "The longitude in degrees. It must be in the range [-180.0, +180.0].",
"format": "double"
}
},
"description": "An object that represents a latitude/longitude pair. This is expressed as a\n pair of doubles to represent degrees latitude and degrees longitude. Unless\n specified otherwise, this must conform to the\n WGS84\n standard. Values must be within normalized ranges."
}
],
"description": "Planned coordinates for the stop.",
"examples": [
{
"latitude": 40.7128,
"longitude": -74.006
}
]
},
"items": {
"type": "array",
"items": {
"title": "StopItem",
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "Item name (e.g. `\"Bananas\"`).",
"examples": [
"Bananas"
]
},
"quantity": {
"type": "integer",
"description": "Quantity of the item (e.g. `5`).",
"format": "int32",
"examples": [
5
]
},
"grams": {
"type": "integer",
"description": "Weight of the item in grams (e.g. `500`).",
"format": "int32",
"examples": [
500
]
},
"sku": {
"type": "string",
"description": "Stock keeping unit (e.g. `\"BANANA-001\"`).",
"examples": [
"BANANA-001"
]
}
},
"description": "An item to be delivered at a stop."
},
"description": "Items to deliver at the stop."
},
"source": {
"enum": [
"UNKNOWN",
"SHOPIFY_ORDER",
"SAVED_STOP",
"IMPORTED_STOP"
],
"type": "string",
"description": "The source of the stop, which may be populated for `DELIVERY` stops. The\n source can be a `SHOPIFY_ORDER`, an EasyRoutes `SAVED_STOP`, or an\n `IMPORTED_STOP` from an external source (such as CSV file).",
"format": "enum",
"examples": [
"IMPORTED_STOP"
]
},
"shopifyOrderId": {
"type": "string",
"description": "The Shopify order ID, populated when the stop source is a `SHOPIFY_ORDER`.",
"examples": [
"6229749334323"
]
},
"savedStopId": {
"type": "string",
"description": "The saved stop ID, populated when the stop source is a `SAVED_STOP`.",
"examples": [
"sst-123e4567-e89b-12d3-a456-426614174000"
]
},
"deliveredCoordinates": {
"allOf": [
{
"type": "object",
"properties": {
"latitude": {
"type": "number",
"description": "The latitude in degrees. It must be in the range [-90.0, +90.0].",
"format": "double"
},
"longitude": {
"type": "number",
"description": "The longitude in degrees. It must be in the range [-180.0, +180.0].",
"format": "double"
}
},
"description": "An object that represents a latitude/longitude pair. This is expressed as a\n pair of doubles to represent degrees latitude and degrees longitude. Unless\n specified otherwise, this must conform to the\n WGS84\n standard. Values must be within normalized ranges."
}
],
"description": "Delivered coordinates for the stop."
},
"proofOfDeliveryNote": {
"type": "string",
"description": "Proof of delivery note for the stop.",
"examples": [
"Left at door."
]
},
"proofOfDeliveryPhotos": {
"type": "array",
"items": {
"title": "StopAttachment",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Attachment ID (e.g. `\"att-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"att-123e4567-e89b-12d3-a456-426614174000"
]
},
"createdAt": {
"type": "string",
"description": "Timestamp when the attachment was created.",
"format": "date-time",
"examples": [
"2026-03-30T09:05:00Z"
]
},
"url": {
"type": "string",
"description": "URL to fetch the attachment.",
"examples": [
"https://example.com/stop-attachment/attachment-2025-06-03-1"
]
}
},
"description": "An attachment to a stop, such as a proof of delivery photo or signature."
},
"description": "Proof of delivery photos for the stop. Photos may be fetched using the URLs\n on the attachments."
},
"proofOfDeliverySignatures": {
"type": "array",
"items": {
"title": "StopAttachment",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Attachment ID (e.g. `\"att-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"att-123e4567-e89b-12d3-a456-426614174000"
]
},
"createdAt": {
"type": "string",
"description": "Timestamp when the attachment was created.",
"format": "date-time",
"examples": [
"2026-03-30T09:05:00Z"
]
},
"url": {
"type": "string",
"description": "URL to fetch the attachment.",
"examples": [
"https://example.com/stop-attachment/attachment-2025-06-03-1"
]
}
},
"description": "An attachment to a stop, such as a proof of delivery photo or signature."
},
"description": "Proof of delivery signatures for the stop. Signatures may be fetched using\n the URLs on the attachments."
},
"tasks": {
"type": "array",
"items": {
"title": "Task",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Task ID (e.g. `\"tsk-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"tsk-123e4567-e89b-12d3-a456-426614174000"
]
},
"title": {
"type": "string",
"description": "Task title (e.g. `\"Delivery checklist\"`).",
"examples": [
"Delivery checklist"
]
},
"type": {
"enum": [
"UNKNOWN",
"CHECKBOXES",
"RADIO_BUTTONS",
"TEXT_INPUT",
"DECIMAL_INPUT",
"SCANNER_INPUT"
],
"type": "string",
"description": "Task type.",
"format": "enum",
"examples": [
"TEXT_INPUT"
]
},
"items": {
"type": "array",
"items": {
"title": "TaskItem",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Item ID (e.g. `\"itm-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"itm-123e4567-e89b-12d3-a456-426614174000"
]
},
"title": {
"type": "string",
"description": "Item title (e.g. `\"Pick up package\"`).",
"examples": [
"Pick up package"
]
},
"complete": {
"type": "boolean",
"description": "Whether the item is completed.",
"examples": [
true
]
},
"updatedAt": {
"type": "string",
"description": "Timestamp when the item was last updated.",
"format": "date-time",
"examples": [
"2026-03-30T13:00:00Z"
]
}
},
"description": "An item within a task. For `CHECKBOXES`, each item on a task may be completed\n independently. For `RADIO_BUTTONS`, at most one item will be completed."
},
"description": "Task items (populated for `CHECKBOXES` and `RADIO_BUTTONS`).",
"examples": [
[]
]
},
"input": {
"allOf": [
{
"title": "TaskInput",
"type": "object",
"properties": {
"value": {
"type": "string",
"description": "Input value.",
"examples": [
"020123456789"
]
},
"updatedAt": {
"type": "string",
"description": "Timestamp when the input was last updated.",
"format": "date-time",
"examples": [
"2026-03-30T13:00:00Z"
]
},
"inputMethod": {
"enum": [
"UNKNOWN",
"SCANNED"
],
"type": "string",
"description": "Whether input was scanned (e.g. a scanned barcode)",
"format": "enum",
"examples": [
"SCANNED"
]
}
},
"description": "Captured driver input for a task. The value may be text for `TEXT_INPUT`\n tasks or a string decimal number for `DECIMAL_INPUT` tasks."
}
],
"description": "Task input (populated for `TEXT_INPUT` and `DECIMAL_INPUT`)."
},
"requiredToMarkStopAsDelivered": {
"type": "boolean",
"description": "Whether the task is required to mark the stop as completed. In the case of\n tasks on `RouteStart`, this represents tasks required for starting the\n route. In the case of tasks on `RouteEnd`, this represents tasks required\n for completing the route.",
"examples": [
true
]
},
"requiredToMarkStopAsAttempted": {
"type": "boolean",
"description": "Whether the task is required to mark the stop as attempted.",
"examples": [
true
]
}
},
"description": "A task to be completed at a stop, or at the start or end of a route. Tasks\n may have one or more items for `CHECKBOXES` or `RADIO_BUTTONS`, or may have\n an input for `TEXT_INPUT` or `DECIMAL_INPUT`."
},
"description": "Driver tasks for the stop, including completed items and any input from the\n driver."
},
"priority": {
"maximum": 10,
"type": "integer",
"description": "Priority of the stop for route planning. The valid range for stop priority\n is between `1` (low) and `10` (high), with default priority corresponding\n to a value of `5`. A priority value of `0` is considered unset and is\n treated the same as \"default\" priority. Stops with higher priority will be\n preferred when generating routes with constraints.",
"format": "int32",
"examples": [
8
]
},
"importedStopId": {
"type": "string",
"description": "The imported stop ID, populated when the stop source is `IMPORTED_STOP`.",
"examples": [
"ist-123e4567-e89b-12d3-a456-426614174000"
]
},
"orderName": {
"type": "string",
"description": "The name of the order associated with the stop. For Shopify orders, the\n name is generated by combining the `orderNumber` property with the order\n prefix and suffix that are set in the merchant's general settings. For\n EasyRoutes imported orders, this field is populated with the order name\n provided on import.",
"examples": [
"#1234"
]
},
"distanceMeters": {
"type": "number",
"description": "The distance in meters from the previous stop.",
"format": "double",
"examples": [
123.45
]
},
"updatedArrival": {
"type": "string",
"description": "Estimated arrival time at the stop. If the stop is completed, this will be\n the actual arrival time.",
"format": "date-time",
"examples": [
"2026-03-30T13:05:00Z"
]
},
"timeWindows": {
"type": "array",
"items": {
"title": "TimeWindow",
"type": "object",
"properties": {
"start": {
"allOf": [
{
"title": "TimeOfDay",
"type": "object",
"properties": {
"hours": {
"maximum": 23,
"type": "integer",
"description": "Hours of day in 24 hour format. Must be from 0 to 23.",
"format": "int32",
"examples": [
13
]
},
"minutes": {
"maximum": 59,
"type": "integer",
"description": "Minutes of hour of day. Must be from 0 to 59.",
"format": "int32",
"examples": [
37
]
},
"seconds": {
"maximum": 59,
"type": "integer",
"description": "Seconds of minutes of the time. Must be from 0 to 59.",
"format": "int32",
"examples": [
16
]
}
},
"description": "A time of day, independent of a particular date or timezone."
}
],
"description": "The start time of the time window (optional)."
},
"end": {
"allOf": [
{
"title": "TimeOfDay",
"type": "object",
"properties": {
"hours": {
"maximum": 23,
"type": "integer",
"description": "Hours of day in 24 hour format. Must be from 0 to 23.",
"format": "int32",
"examples": [
13
]
},
"minutes": {
"maximum": 59,
"type": "integer",
"description": "Minutes of hour of day. Must be from 0 to 59.",
"format": "int32",
"examples": [
37
]
},
"seconds": {
"maximum": 59,
"type": "integer",
"description": "Seconds of minutes of the time. Must be from 0 to 59.",
"format": "int32",
"examples": [
16
]
}
},
"description": "A time of day, independent of a particular date or timezone."
}
],
"description": "The end time of the time window (optional)."
}
},
"description": "A time window for a stop. The time window may be open-ended, but one or both\n of the start and end times should be provided. The end time must be >= the\n start time."
},
"description": "The time window for the stop. Note that we currently support at most one\n time window but may support multiple time windows in the future.",
"examples": [
[
{
"start": {
"hours": 9
},
"end": {
"hours": 17
}
}
]
]
},
"deliveryDate": {
"allOf": [
{
"title": "Date",
"required": [
"year",
"month",
"day"
],
"type": "object",
"properties": {
"year": {
"maximum": 9999,
"minimum": 1,
"type": "integer",
"description": "Year of the date. Must be from 1 to 9999.",
"format": "int32",
"examples": [
2019
]
},
"month": {
"maximum": 12,
"minimum": 1,
"type": "integer",
"description": "Month of a year. Must be from 1 to 12.",
"format": "int32",
"examples": [
11
]
},
"day": {
"maximum": 31,
"minimum": 1,
"type": "integer",
"description": "Day of a month. Must be from 1 to 31.",
"format": "int32",
"examples": [
15
]
}
},
"description": "A date in year-month-day format."
}
],
"description": "The planned delivery date for the stop.",
"examples": [
{
"year": 2025,
"month": 12,
"day": 16
}
]
},
"attributes": {
"type": "array",
"items": {
"title": "Attribute",
"type": "object",
"properties": {
"key": {
"type": "string",
"description": "Attribute key. Must be non-empty.",
"examples": [
"delivery_date"
]
},
"value": {
"type": "string",
"description": "Attribute value.",
"examples": [
"2025-12-16"
]
}
},
"description": "A key-value pair for storing additional information on a stop, such as order\n details, delivery instructions, or custom fields."
},
"description": "Additional attributes for the stop. Attributes are key-value pairs for\n storing additional structured data on stops. These may be populated from\n the Shopify order or set on import.",
"examples": [
[
{
"key": "color",
"value": "blue"
}
]
]
},
"clientStopId": {
"type": "string",
"description": "The client-provided ID associated with the stop, if provided on import.",
"examples": [
"test-order-1234"
]
},
"tags": {
"type": "array",
"items": {
"type": "string"
},
"description": "The tags for the stop. Tags are used to categorize stops and can be used\n for filtering and grouping stops in the EasyRoutes web app. These may be\n populated from the Shopify order or set on import.",
"examples": [
[
"foo",
"bar"
]
]
},
"attemptedReason": {
"enum": [
"UNKNOWN",
"NOT_AVAILABLE",
"ACCESS_DENIED",
"INCORRECT_ADDRESS",
"SAFE_PLACE_UNAVAILABLE",
"REFUSED",
"EXTERNAL",
"INCORRECT_ITEMS",
"OTHER",
"CANCELED"
],
"type": "string",
"description": "The reason for marking the stop as attempted. This is only populated when\n `deliveryStatus = ATTEMPTED_DELIVERY`.",
"format": "enum",
"examples": [
"NOT_AVAILABLE"
]
},
"attemptedNote": {
"type": "string",
"description": "Optional note related to the reason for marking the stop as attempted. This\n is optionally populated when `deliveryStatus = ATTEMPTED_DELIVERY`.",
"examples": [
"Customer did not answer the door."
]
},
"customerRating": {
"allOf": [
{
"title": "CustomerRating",
"type": "object",
"properties": {
"rating": {
"maximum": 5,
"minimum": 1,
"type": "integer",
"description": "Rating from 1-5",
"format": "int32",
"examples": [
5
]
},
"comment": {
"type": "string",
"description": "Customer comment related to rating",
"examples": [
"Excellent delivery"
]
},
"createdAt": {
"type": "string",
"description": "Timestamp when rating was left by customer.",
"format": "date-time",
"examples": [
"2026-03-30T18:00:00Z"
]
}
},
"description": "Customer rating and feedback left on a stop."
}
],
"description": "Rating left by customer. This can only be populated once `deliveryStatus =\n DELIVERED`."
},
"customSignatureDisclosure": {
"type": "string",
"description": "Optional custom signature disclosure that is shown to customers in the\n driver app.",
"examples": [
"I acknowledge that I have received this delivery."
]
},
"shopifyOrder": {
"allOf": [
{
"title": "ShopifyOrder",
"type": "object",
"properties": {
"orderNote": {
"type": "string",
"description": "The Shopify order note.",
"examples": [
"Customer has paid."
]
},
"customerNote": {
"type": "string",
"description": "The Shopify customer note for the order.",
"examples": [
"Leave at door."
]
}
},
"description": "Shopify-specific information for a RouteStop."
}
],
"description": "Information from the associated Shopify order, if applicable. Populated if\n stop source is `SHOPIFY_ORDER`"
},
"proofOfDeliveryBarcodes": {
"type": "array",
"items": {
"title": "ScannedBarcode",
"type": "object",
"properties": {
"value": {
"type": "string",
"description": "Barcode value (e.g. `\"123456789012\"`).",
"examples": [
"123456789012"
]
},
"createdAt": {
"type": "string",
"description": "Timestamp when the barcode was scanned.",
"format": "date-time",
"examples": [
"2026-03-30T13:10:00Z"
]
}
},
"description": "A proof of delivery barcode scanned at a stop."
},
"description": "Proof of delivery barcodes scanned at the stop."
},
"proofOfDeliveryBarcodeIssues": {
"type": "array",
"items": {
"title": "ScannedBarcodeIssue",
"type": "object",
"properties": {
"reason": {
"enum": [
"UNKNOWN",
"ITEM_MISSING",
"NOT_SCANNABLE",
"INCORRECT"
],
"type": "string",
"description": "The reported reason for the barcode issue.",
"format": "enum",
"examples": [
"ITEM_MISSING"
]
},
"note": {
"type": "string",
"description": "Optional note related to the reason for reporting a barcode issue.",
"examples": [
"Item was not packed."
]
},
"createdAt": {
"type": "string",
"description": "Timestamp when the issue was reported.",
"format": "date-time",
"examples": [
"2026-03-30T13:10:00Z"
]
}
},
"description": "A reported issue related to scanning barcodes at a stop."
},
"description": "Proof of delivery barcode issues reported at the stop."
},
"orderReferenceUrl": {
"type": "string",
"description": "A reference URL for the order associated with the stop (e.g. a link to the\n order in your order management system). Must be a valid HTTPS URL. This\n field can only be populated for imported stops.",
"examples": [
"https://orders.example.com/orders/148977776"
]
}
},
"description": "A stop on a route. A stop may correspond to a delivery or a driver break as\n determined by the type. A delivery stop will have location and contact\n information, items to deliver, optional order details, status, arrival time\n and stop duration, driver tasks and any proof of delivery information. A\n break stop will have start time and duration, and status."
},
"description": "Route stops. See RouteStop for stop fields."
},
"createdAt": {
"type": "string",
"description": "Timestamp when the route was created.",
"format": "date-time",
"examples": [
"2026-03-29T08:00:00Z"
]
},
"updatedAt": {
"type": "string",
"description": "Timestamp when the route was last updated (by the planner).",
"format": "date-time",
"examples": [
"2026-03-30T13:15:00Z"
]
},
"archivedAt": {
"type": "string",
"description": "Timestamp when the route was archived.",
"format": "date-time",
"examples": [
"2026-04-05T00:00:00Z"
]
},
"scheduledFor": {
"type": "string",
"description": "Timestamp when the route is scheduled for.",
"format": "date-time",
"examples": [
"2026-03-30T09:00:00Z"
]
},
"totalDistanceMeters": {
"type": "number",
"description": "The distance in meters for the entire route.",
"format": "double",
"examples": [
2387.2
]
},
"totalItemQuantity": {
"type": "integer",
"description": "The total quantity of items to deliver on the route.",
"format": "int32",
"examples": [
50
]
},
"totalItemGrams": {
"type": "string",
"description": "The total weight in grams for the items on the route.",
"examples": [
"6000"
]
},
"optimized": {
"type": "boolean",
"description": "Whether the route has been optimized. Adding or removing stops, reordering\n stops, or changing route options generally set this field to false until\n the route is reoptimized.",
"examples": [
true
]
},
"dispatchedUntil": {
"type": "string",
"description": "Timestamp until which the route is dispatched and accessible in the driver\n app.",
"format": "date-time",
"examples": [
"2026-03-30T20:00:00Z"
]
},
"note": {
"type": "string",
"description": "Top-level note for the route, as entered manually by route planners.",
"examples": [
"Fragile items."
]
},
"tags": {
"type": "array",
"items": {
"type": "string"
},
"description": "The tags for the route. Tags are used to categorize routes and can be\n used for filtering and grouping routes in the EasyRoutes web app.",
"examples": [
[
"foo",
"bar"
]
]
},
"defaultStopDuration": {
"pattern": "^-?(?:0|[1-9][0-9]{0,11})(?:\\.[0-9]{1,9})?s$",
"type": "string",
"description": "The default duration for stops on the route. Used to estimate arrival\n times for stops that do not have their own duration specified.\n Specified as a duration string in the format \"300s\" for 5 minutes, \"60s\"\n for 1 minute, etc.",
"examples": [
"300s"
]
},
"maxDuration": {
"pattern": "^-?(?:0|[1-9][0-9]{0,11})(?:\\.[0-9]{1,9})?s$",
"type": "string",
"description": "The maximum duration of the route. Specified as a duration string in the\n format \"3600s\" for 1 hour, \"7200s\" for 2 hours, etc.",
"examples": [
"28800s"
]
},
"maxStops": {
"type": "integer",
"description": "The maximum number of stops on the route.",
"format": "int32",
"examples": [
50
]
},
"maxItemCount": {
"type": "integer",
"description": "The maximum total item count across all stops on the route.",
"format": "int32",
"examples": [
200
]
},
"maxKilograms": {
"type": "number",
"description": "The maximum total weight in kilograms across all stops on the route.",
"format": "double",
"examples": [
500
]
},
"avoidTolls": {
"type": "boolean",
"description": "Whether to avoid toll roads during optimization.",
"examples": [
true
]
},
"avoidUTurns": {
"type": "boolean",
"description": "Whether to avoid U-turns during optimization.",
"examples": [
true
]
},
"speedFactor": {
"type": "number",
"description": "A speed factor for the route used during optimization to adjust estimated\n travel times. A value of 1.0 represents normal speed. Values less than 1.0\n indicate slower travel (e.g. 0.5 = half speed), and values greater than\n 1.0 indicate faster travel (e.g. 1.5 = 50% faster). Must be between 0.1\n and 1.9. A value of 0 (or unset) uses the default speed.",
"format": "double",
"examples": [
0.8
]
},
"vehicle": {
"allOf": [
{
"title": "Vehicle",
"required": [
"id"
],
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Vehicle ID.",
"examples": [
"veh-123e4567-e89b-12d3-a456-426614174000"
]
},
"name": {
"type": "string",
"description": "Vehicle name.",
"examples": [
"Delivery Van 1"
]
},
"make": {
"type": "string",
"description": "Vehicle make.",
"examples": [
"Ford"
]
},
"model": {
"type": "string",
"description": "Vehicle model.",
"examples": [
"Transit"
]
},
"year": {
"type": "integer",
"description": "Vehicle model year.",
"format": "int32",
"examples": [
2023
]
},
"type": {
"enum": [
"UNKNOWN",
"CAR",
"CARGO_VAN",
"PICKUP_TRUCK",
"BOX_TRUCK",
"MOTORCYCLE",
"BICYCLE",
"DRONE",
"OTHER"
],
"type": "string",
"description": "Vehicle type.",
"format": "enum",
"examples": [
"CARGO_VAN"
]
},
"vin": {
"type": "string",
"description": "Vehicle Identification Number.",
"examples": [
"1FTBW2CM5NKA12345"
]
},
"license": {
"type": "string",
"description": "Vehicle license plate.",
"examples": [
"ABC-1234"
]
},
"isArchived": {
"type": "boolean",
"description": "Whether the vehicle is archived.",
"examples": [
false
]
},
"createdTimestamp": {
"type": "string",
"description": "Timestamp when the vehicle was created.",
"format": "date-time",
"examples": [
"2026-07-30T12:00:00Z"
]
}
},
"description": "A vehicle that can be assigned to a route."
}
],
"description": "Assigned vehicle for the route."
}
},
"description": "A route of stops, optionally with an assigned driver."
}
}
}
},
"default": {
"description": "Default error response",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"code": {
"type": "integer",
"description": "The status code, which should be an enum value of [google.rpc.Code][google.rpc.Code].",
"format": "int32"
},
"message": {
"type": "string",
"description": "A developer-facing error message, which should be in English. Any user-facing error message should be localized and sent in the [google.rpc.Status.details][google.rpc.Status.details] field, or localized by the client."
},
"details": {
"type": "array",
"items": {
"type": "object",
"properties": {
"@type": {
"type": "string",
"description": "The type of the serialized message."
}
},
"additionalProperties": true,
"description": "Contains an arbitrary serialized message along with a @type that describes the type of the serialized message."
},
"description": "A list of messages that carry the error details. There is a common set of message types for APIs to use."
}
},
"description": "The `Status` type defines a logical error model that is suitable for different programming environments, including REST APIs and RPC APIs. It is used by [gRPC](https://github.com/grpc). Each `Status` message contains three pieces of data: error code, error message, and error details. You can find out more about this error model and how to work with it in the [API Design Guide](https://cloud.google.com/apis/design/errors)."
}
}
}
}
},
"security": [
{
"bearerAuth": []
}
],
"components": {
"securitySchemes": {
"bearerAuth": {
"type": "http",
"description": "Access token from `/authenticate`",
"scheme": "bearer",
"bearerFormat": "JWT"
}
}
}
}
```
# Assign route driver (https://docs.roundtrip.ai/docs/api-reference/routes/put-routes-routeId-driver)
PUT /routes/{routeId}/driver
Assigns a driver to a route by route ID. The response will include the
updated route with the new driver assigned.
## OpenAPI specification
```json
{
"servers": [
{
"url": "https://easyroutes.roundtrip.ai/api/2024-07"
}
],
"tags": [
"Routes"
],
"summary": "Assign route driver",
"description": "Assigns a driver to a route by route ID. The response will include the\n updated route with the new driver assigned.",
"operationId": "AssignRouteDriver",
"parameters": [
{
"name": "routeId",
"in": "path",
"description": "The route ID to assign the driver to.",
"required": true,
"schema": {
"type": "string",
"examples": [
"rte-123e4567-e89b-12d3-a456-426614174000"
]
}
},
{
"name": "Idempotency-Key",
"in": "header",
"description": "A unique key for safely retrying this operation. For more information read [our guide](https://docs.roundtrip.ai/docs/concepts/idempotency.md).",
"schema": {
"maxLength": 255,
"minLength": 1,
"type": "string"
},
"examples": {
"default": {
"value": "550e8400-e29b-41d4-a716-446655440000"
}
}
}
],
"requestBody": {
"content": {
"application/json": {
"schema": {
"title": "AssignRouteDriverRequest",
"required": [
"driverId"
],
"type": "object",
"properties": {
"driverId": {
"type": "string",
"description": "The ID of the driver to assign to a route.",
"examples": [
"drv-123e4567-e89b-12d3-a456-426614174000"
]
}
}
}
}
},
"required": true
},
"responses": {
"200": {
"description": "OK",
"headers": {
"Idempotency-Key": {
"description": "The idempotency key associated with the response.",
"schema": {
"type": "string"
}
},
"Idempotency-Replayed": {
"description": "Whether the response was replayed from a previous request.",
"schema": {
"type": "boolean"
}
}
},
"content": {
"application/json": {
"schema": {
"title": "Route",
"required": [
"id",
"name",
"stops",
"createdAt",
"updatedAt",
"totalDistanceMeters",
"totalItemQuantity",
"totalItemGrams",
"optimized"
],
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Route ID (e.g. `\"rte-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"rte-123e4567-e89b-12d3-a456-426614174000"
]
},
"name": {
"type": "string",
"description": "Route name (e.g. `\"Morning route\"`).",
"examples": [
"Morning route"
]
},
"driver": {
"allOf": [
{
"title": "Driver",
"required": [
"id"
],
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Driver ID (e.g. `\"drv-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"drv-123e4567-e89b-12d3-a456-426614174000"
]
},
"firstName": {
"type": "string",
"description": "Driver first name (e.g. `\"John\"`).",
"examples": [
"John"
]
},
"lastName": {
"type": "string",
"description": "Driver last name (e.g. `\"Doe\"`).",
"examples": [
"Doe"
]
},
"phone": {
"type": "string",
"description": "Driver phone number in [E.164 format](https://en.wikipedia.org/wiki/E.164)\n (e.g. `\"+14265551000\"`).",
"examples": [
"+14265551000"
]
},
"status": {
"enum": [
"UNKNOWN",
"ACTIVE",
"INACTIVE",
"ARCHIVED"
],
"type": "string",
"description": "Shop driver status. (e.g. `ACTIVE`).",
"format": "enum",
"examples": [
"ACTIVE"
]
}
},
"description": "A driver who is assigned to a route."
}
],
"description": "Assigned driver for the route."
},
"start": {
"allOf": [
{
"title": "RouteStart",
"type": "object",
"properties": {
"address": {
"allOf": [
{
"title": "Address",
"type": "object",
"properties": {
"address1": {
"type": "string",
"description": "Street address line 1 (e.g. `\"123 Main St\"`).",
"examples": [
"123 Main St"
]
},
"address2": {
"type": "string",
"description": "Street address line 2 (e.g. `\"Apt 101\"`).",
"examples": [
"Apt 3B"
]
},
"city": {
"type": "string",
"description": "City name (e.g. `\"New York\"`).",
"examples": [
"New York"
]
},
"provinceCode": {
"type": "string",
"description": "Province or state as subdivision codes in\n [ISO 3166-2](https://en.wikipedia.org/wiki/ISO_3166-2) format without the\n country prefix (e.g. `\"NY\"` for New York).",
"examples": [
"NY"
]
},
"countryCode": {
"type": "string",
"description": "Country code (e.g. `\"US\"`).",
"examples": [
"US"
]
},
"zip": {
"type": "string",
"description": "Postal or ZIP code (e.g. `\"10001\"`).",
"examples": [
"10001"
]
}
},
"description": "A physical street address."
}
],
"description": "The start address of the route.",
"examples": [
{
"address1": "123 Main St",
"address2": "Apt 3B",
"city": "New York",
"provinceCode": "NY",
"countryCode": "US",
"zip": "10001"
}
]
},
"tasks": {
"type": "array",
"items": {
"title": "Task",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Task ID (e.g. `\"tsk-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"tsk-123e4567-e89b-12d3-a456-426614174000"
]
},
"title": {
"type": "string",
"description": "Task title (e.g. `\"Delivery checklist\"`).",
"examples": [
"Delivery checklist"
]
},
"type": {
"enum": [
"UNKNOWN",
"CHECKBOXES",
"RADIO_BUTTONS",
"TEXT_INPUT",
"DECIMAL_INPUT",
"SCANNER_INPUT"
],
"type": "string",
"description": "Task type.",
"format": "enum",
"examples": [
"TEXT_INPUT"
]
},
"items": {
"type": "array",
"items": {
"title": "TaskItem",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Item ID (e.g. `\"itm-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"itm-123e4567-e89b-12d3-a456-426614174000"
]
},
"title": {
"type": "string",
"description": "Item title (e.g. `\"Pick up package\"`).",
"examples": [
"Pick up package"
]
},
"complete": {
"type": "boolean",
"description": "Whether the item is completed.",
"examples": [
true
]
},
"updatedAt": {
"type": "string",
"description": "Timestamp when the item was last updated.",
"format": "date-time",
"examples": [
"2026-03-30T13:00:00Z"
]
}
},
"description": "An item within a task. For `CHECKBOXES`, each item on a task may be completed\n independently. For `RADIO_BUTTONS`, at most one item will be completed."
},
"description": "Task items (populated for `CHECKBOXES` and `RADIO_BUTTONS`).",
"examples": [
[]
]
},
"input": {
"allOf": [
{
"title": "TaskInput",
"type": "object",
"properties": {
"value": {
"type": "string",
"description": "Input value.",
"examples": [
"020123456789"
]
},
"updatedAt": {
"type": "string",
"description": "Timestamp when the input was last updated.",
"format": "date-time",
"examples": [
"2026-03-30T13:00:00Z"
]
},
"inputMethod": {
"enum": [
"UNKNOWN",
"SCANNED"
],
"type": "string",
"description": "Whether input was scanned (e.g. a scanned barcode)",
"format": "enum",
"examples": [
"SCANNED"
]
}
},
"description": "Captured driver input for a task. The value may be text for `TEXT_INPUT`\n tasks or a string decimal number for `DECIMAL_INPUT` tasks."
}
],
"description": "Task input (populated for `TEXT_INPUT` and `DECIMAL_INPUT`)."
},
"requiredToMarkStopAsDelivered": {
"type": "boolean",
"description": "Whether the task is required to mark the stop as completed. In the case of\n tasks on `RouteStart`, this represents tasks required for starting the\n route. In the case of tasks on `RouteEnd`, this represents tasks required\n for completing the route.",
"examples": [
true
]
},
"requiredToMarkStopAsAttempted": {
"type": "boolean",
"description": "Whether the task is required to mark the stop as attempted.",
"examples": [
true
]
}
},
"description": "A task to be completed at a stop, or at the start or end of a route. Tasks\n may have one or more items for `CHECKBOXES` or `RADIO_BUTTONS`, or may have\n an input for `TEXT_INPUT` or `DECIMAL_INPUT`."
},
"description": "Tasks to complete before starting the route."
},
"status": {
"enum": [
"UNKNOWN",
"STARTED"
],
"type": "string",
"description": "Status indicating whether the route has been started.",
"format": "enum",
"examples": [
"STARTED"
]
},
"updatedStart": {
"type": "string",
"description": "Updated start time for the route. If the route is started, this will be the\n actual start time.",
"format": "date-time",
"examples": [
"2026-03-30T09:05:00Z"
]
},
"scheduledStart": {
"type": "string",
"description": "Scheduled start time for the route (same as `scheduledFor` on the route).",
"format": "date-time",
"examples": [
"2026-03-30T09:00:00Z"
]
},
"photos": {
"type": "array",
"items": {
"title": "StopAttachment",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Attachment ID (e.g. `\"att-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"att-123e4567-e89b-12d3-a456-426614174000"
]
},
"createdAt": {
"type": "string",
"description": "Timestamp when the attachment was created.",
"format": "date-time",
"examples": [
"2026-03-30T09:05:00Z"
]
},
"url": {
"type": "string",
"description": "URL to fetch the attachment.",
"examples": [
"https://example.com/stop-attachment/attachment-2025-06-03-1"
]
}
},
"description": "An attachment to a stop, such as a proof of delivery photo or signature."
},
"description": "Photos for the route start. Photos may be fetched using the URLs on the\n attachments."
}
},
"description": "The start location of a route and any driver tasks to complete before\n beginning the route."
}
],
"description": "Route start address and tasks."
},
"end": {
"allOf": [
{
"title": "RouteEnd",
"type": "object",
"properties": {
"address": {
"allOf": [
{
"title": "Address",
"type": "object",
"properties": {
"address1": {
"type": "string",
"description": "Street address line 1 (e.g. `\"123 Main St\"`).",
"examples": [
"123 Main St"
]
},
"address2": {
"type": "string",
"description": "Street address line 2 (e.g. `\"Apt 101\"`).",
"examples": [
"Apt 3B"
]
},
"city": {
"type": "string",
"description": "City name (e.g. `\"New York\"`).",
"examples": [
"New York"
]
},
"provinceCode": {
"type": "string",
"description": "Province or state as subdivision codes in\n [ISO 3166-2](https://en.wikipedia.org/wiki/ISO_3166-2) format without the\n country prefix (e.g. `\"NY\"` for New York).",
"examples": [
"NY"
]
},
"countryCode": {
"type": "string",
"description": "Country code (e.g. `\"US\"`).",
"examples": [
"US"
]
},
"zip": {
"type": "string",
"description": "Postal or ZIP code (e.g. `\"10001\"`).",
"examples": [
"10001"
]
}
},
"description": "A physical street address."
}
],
"description": "The end address of the route.",
"examples": [
{
"address1": "123 Main St",
"address2": "Apt 3B",
"city": "New York",
"provinceCode": "NY",
"countryCode": "US",
"zip": "10001"
}
]
},
"tasks": {
"type": "array",
"items": {
"title": "Task",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Task ID (e.g. `\"tsk-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"tsk-123e4567-e89b-12d3-a456-426614174000"
]
},
"title": {
"type": "string",
"description": "Task title (e.g. `\"Delivery checklist\"`).",
"examples": [
"Delivery checklist"
]
},
"type": {
"enum": [
"UNKNOWN",
"CHECKBOXES",
"RADIO_BUTTONS",
"TEXT_INPUT",
"DECIMAL_INPUT",
"SCANNER_INPUT"
],
"type": "string",
"description": "Task type.",
"format": "enum",
"examples": [
"TEXT_INPUT"
]
},
"items": {
"type": "array",
"items": {
"title": "TaskItem",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Item ID (e.g. `\"itm-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"itm-123e4567-e89b-12d3-a456-426614174000"
]
},
"title": {
"type": "string",
"description": "Item title (e.g. `\"Pick up package\"`).",
"examples": [
"Pick up package"
]
},
"complete": {
"type": "boolean",
"description": "Whether the item is completed.",
"examples": [
true
]
},
"updatedAt": {
"type": "string",
"description": "Timestamp when the item was last updated.",
"format": "date-time",
"examples": [
"2026-03-30T13:00:00Z"
]
}
},
"description": "An item within a task. For `CHECKBOXES`, each item on a task may be completed\n independently. For `RADIO_BUTTONS`, at most one item will be completed."
},
"description": "Task items (populated for `CHECKBOXES` and `RADIO_BUTTONS`).",
"examples": [
[]
]
},
"input": {
"allOf": [
{
"title": "TaskInput",
"type": "object",
"properties": {
"value": {
"type": "string",
"description": "Input value.",
"examples": [
"020123456789"
]
},
"updatedAt": {
"type": "string",
"description": "Timestamp when the input was last updated.",
"format": "date-time",
"examples": [
"2026-03-30T13:00:00Z"
]
},
"inputMethod": {
"enum": [
"UNKNOWN",
"SCANNED"
],
"type": "string",
"description": "Whether input was scanned (e.g. a scanned barcode)",
"format": "enum",
"examples": [
"SCANNED"
]
}
},
"description": "Captured driver input for a task. The value may be text for `TEXT_INPUT`\n tasks or a string decimal number for `DECIMAL_INPUT` tasks."
}
],
"description": "Task input (populated for `TEXT_INPUT` and `DECIMAL_INPUT`)."
},
"requiredToMarkStopAsDelivered": {
"type": "boolean",
"description": "Whether the task is required to mark the stop as completed. In the case of\n tasks on `RouteStart`, this represents tasks required for starting the\n route. In the case of tasks on `RouteEnd`, this represents tasks required\n for completing the route.",
"examples": [
true
]
},
"requiredToMarkStopAsAttempted": {
"type": "boolean",
"description": "Whether the task is required to mark the stop as attempted.",
"examples": [
true
]
}
},
"description": "A task to be completed at a stop, or at the start or end of a route. Tasks\n may have one or more items for `CHECKBOXES` or `RADIO_BUTTONS`, or may have\n an input for `TEXT_INPUT` or `DECIMAL_INPUT`."
},
"description": "Tasks to complete before finishing the route."
},
"plannedArrival": {
"type": "string",
"description": "Planned arrival time at the end of the route.",
"format": "date-time",
"examples": [
"2026-03-30T17:00:00Z"
]
},
"distanceMeters": {
"type": "number",
"description": "The distance in meters from the previous stop.",
"format": "double",
"examples": [
1234.56
]
},
"updatedArrival": {
"type": "string",
"description": "Estimated arrival time at the end of the route. If the route is completed,\n this will be the actual arrival time.",
"format": "date-time",
"examples": [
"2026-03-30T17:05:00Z"
]
},
"status": {
"enum": [
"UNKNOWN",
"COMPLETED"
],
"type": "string",
"description": "Status indicating whether the route has been completed.",
"format": "enum",
"examples": [
"COMPLETED"
]
},
"photos": {
"type": "array",
"items": {
"title": "StopAttachment",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Attachment ID (e.g. `\"att-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"att-123e4567-e89b-12d3-a456-426614174000"
]
},
"createdAt": {
"type": "string",
"description": "Timestamp when the attachment was created.",
"format": "date-time",
"examples": [
"2026-03-30T09:05:00Z"
]
},
"url": {
"type": "string",
"description": "URL to fetch the attachment.",
"examples": [
"https://example.com/stop-attachment/attachment-2025-06-03-1"
]
}
},
"description": "An attachment to a stop, such as a proof of delivery photo or signature."
},
"description": "Photos for the route end. Photos may be fetched using the URLs on the\n attachments."
}
},
"description": "The end location of a route and any driver tasks to complete after completing\n the route."
}
],
"description": "Route end address and tasks."
},
"stops": {
"type": "array",
"items": {
"title": "RouteStop",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Stop ID (e.g. `\"rst-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"rst-123e4567-e89b-12d3-a456-426614174000"
]
},
"type": {
"enum": [
"UNKNOWN",
"DELIVERY",
"BREAK",
"PICKUP",
"TASK"
],
"type": "string",
"description": "The type of stop (DELIVERY, BREAK, PICKUP, or TASK).",
"format": "enum",
"examples": [
"DELIVERY"
]
},
"deliveryStatus": {
"enum": [
"UNKNOWN",
"DELIVERED",
"OUT_FOR_DELIVERY",
"ATTEMPTED_DELIVERY",
"READY_FOR_DELIVERY"
],
"type": "string",
"description": "The status for DELIVERY, PICKUP, or TASK stops.",
"format": "enum",
"examples": [
"ATTEMPTED_DELIVERY"
]
},
"breakStatus": {
"enum": [
"UNKNOWN",
"COMPLETED"
],
"type": "string",
"description": "The status for BREAK stops.",
"format": "enum",
"examples": [
"COMPLETED"
]
},
"updatedAt": {
"type": "string",
"description": "Timestamp when the stop status was last updated. Note that this timestamp\n corresponds only to major status updates (i.e. stop marked as DELIVERED).\n Minor updates like task completion or adding proof of delivery will not\n advance this timestamp. For those events, use the timestamps on the task or\n proof of delivery attachment.",
"format": "date-time",
"examples": [
"2026-03-30T13:15:00Z"
]
},
"duration": {
"pattern": "^-?(?:0|[1-9][0-9]{0,11})(?:\\.[0-9]{1,9})?s$",
"type": "string",
"description": "Planned duration of the stop in seconds.",
"examples": [
"300s"
]
},
"plannedArrival": {
"type": "string",
"description": "Planned arrival time at the stop.",
"format": "date-time",
"examples": [
"2026-03-30T13:00:00Z"
]
},
"note": {
"type": "string",
"description": "Top-level note for the stop, as entered manually by route planners,\n inherited from a saved or imported stop, or set by order import automation\n rules.",
"examples": [
"Leave at door."
]
},
"address": {
"allOf": [
{
"title": "Address",
"type": "object",
"properties": {
"address1": {
"type": "string",
"description": "Street address line 1 (e.g. `\"123 Main St\"`).",
"examples": [
"123 Main St"
]
},
"address2": {
"type": "string",
"description": "Street address line 2 (e.g. `\"Apt 101\"`).",
"examples": [
"Apt 3B"
]
},
"city": {
"type": "string",
"description": "City name (e.g. `\"New York\"`).",
"examples": [
"New York"
]
},
"provinceCode": {
"type": "string",
"description": "Province or state as subdivision codes in\n [ISO 3166-2](https://en.wikipedia.org/wiki/ISO_3166-2) format without the\n country prefix (e.g. `\"NY\"` for New York).",
"examples": [
"NY"
]
},
"countryCode": {
"type": "string",
"description": "Country code (e.g. `\"US\"`).",
"examples": [
"US"
]
},
"zip": {
"type": "string",
"description": "Postal or ZIP code (e.g. `\"10001\"`).",
"examples": [
"10001"
]
}
},
"description": "A physical street address."
}
],
"description": "Delivery address for the stop.",
"examples": [
{
"address1": "123 Main St",
"address2": "Apt 3B",
"city": "New York",
"provinceCode": "NY",
"countryCode": "US",
"zip": "10001"
}
]
},
"contact": {
"allOf": [
{
"title": "Contact",
"type": "object",
"properties": {
"firstName": {
"type": "string",
"description": "First name (e.g. `\"John\"`).",
"examples": [
"John"
]
},
"lastName": {
"type": "string",
"description": "Last name (e.g. `\"Doe\"`).",
"examples": [
"Doe"
]
},
"company": {
"type": "string",
"description": "Company name (e.g. `\"Roundtrip Systems Inc\"`).",
"examples": [
"Roundtrip Systems Inc"
]
},
"phone": {
"type": "string",
"description": "Phone number in [E.164 format](https://en.wikipedia.org/wiki/E.164) (e.g.\n `\"+14265551000\"`).",
"examples": [
"+14265551000"
]
},
"email": {
"type": "string",
"description": "Email address (e.g. `\"john.doe@roundtrip.ai\"`)",
"examples": [
"john.doe@roundtrip.ai"
]
}
},
"description": "Contact information for a person or company."
}
],
"description": "Contact information for the stop delivery recipient.",
"examples": [
{
"firstName": "John",
"lastName": "Doe",
"company": "Roundtrip Systems Inc",
"phone": "+14265551000",
"email": "john.doe@roundtrip.ai"
}
]
},
"plannedCoordinates": {
"allOf": [
{
"type": "object",
"properties": {
"latitude": {
"type": "number",
"description": "The latitude in degrees. It must be in the range [-90.0, +90.0].",
"format": "double"
},
"longitude": {
"type": "number",
"description": "The longitude in degrees. It must be in the range [-180.0, +180.0].",
"format": "double"
}
},
"description": "An object that represents a latitude/longitude pair. This is expressed as a\n pair of doubles to represent degrees latitude and degrees longitude. Unless\n specified otherwise, this must conform to the\n WGS84\n standard. Values must be within normalized ranges."
}
],
"description": "Planned coordinates for the stop.",
"examples": [
{
"latitude": 40.7128,
"longitude": -74.006
}
]
},
"items": {
"type": "array",
"items": {
"title": "StopItem",
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "Item name (e.g. `\"Bananas\"`).",
"examples": [
"Bananas"
]
},
"quantity": {
"type": "integer",
"description": "Quantity of the item (e.g. `5`).",
"format": "int32",
"examples": [
5
]
},
"grams": {
"type": "integer",
"description": "Weight of the item in grams (e.g. `500`).",
"format": "int32",
"examples": [
500
]
},
"sku": {
"type": "string",
"description": "Stock keeping unit (e.g. `\"BANANA-001\"`).",
"examples": [
"BANANA-001"
]
}
},
"description": "An item to be delivered at a stop."
},
"description": "Items to deliver at the stop."
},
"source": {
"enum": [
"UNKNOWN",
"SHOPIFY_ORDER",
"SAVED_STOP",
"IMPORTED_STOP"
],
"type": "string",
"description": "The source of the stop, which may be populated for `DELIVERY` stops. The\n source can be a `SHOPIFY_ORDER`, an EasyRoutes `SAVED_STOP`, or an\n `IMPORTED_STOP` from an external source (such as CSV file).",
"format": "enum",
"examples": [
"IMPORTED_STOP"
]
},
"shopifyOrderId": {
"type": "string",
"description": "The Shopify order ID, populated when the stop source is a `SHOPIFY_ORDER`.",
"examples": [
"6229749334323"
]
},
"savedStopId": {
"type": "string",
"description": "The saved stop ID, populated when the stop source is a `SAVED_STOP`.",
"examples": [
"sst-123e4567-e89b-12d3-a456-426614174000"
]
},
"deliveredCoordinates": {
"allOf": [
{
"type": "object",
"properties": {
"latitude": {
"type": "number",
"description": "The latitude in degrees. It must be in the range [-90.0, +90.0].",
"format": "double"
},
"longitude": {
"type": "number",
"description": "The longitude in degrees. It must be in the range [-180.0, +180.0].",
"format": "double"
}
},
"description": "An object that represents a latitude/longitude pair. This is expressed as a\n pair of doubles to represent degrees latitude and degrees longitude. Unless\n specified otherwise, this must conform to the\n WGS84\n standard. Values must be within normalized ranges."
}
],
"description": "Delivered coordinates for the stop."
},
"proofOfDeliveryNote": {
"type": "string",
"description": "Proof of delivery note for the stop.",
"examples": [
"Left at door."
]
},
"proofOfDeliveryPhotos": {
"type": "array",
"items": {
"title": "StopAttachment",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Attachment ID (e.g. `\"att-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"att-123e4567-e89b-12d3-a456-426614174000"
]
},
"createdAt": {
"type": "string",
"description": "Timestamp when the attachment was created.",
"format": "date-time",
"examples": [
"2026-03-30T09:05:00Z"
]
},
"url": {
"type": "string",
"description": "URL to fetch the attachment.",
"examples": [
"https://example.com/stop-attachment/attachment-2025-06-03-1"
]
}
},
"description": "An attachment to a stop, such as a proof of delivery photo or signature."
},
"description": "Proof of delivery photos for the stop. Photos may be fetched using the URLs\n on the attachments."
},
"proofOfDeliverySignatures": {
"type": "array",
"items": {
"title": "StopAttachment",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Attachment ID (e.g. `\"att-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"att-123e4567-e89b-12d3-a456-426614174000"
]
},
"createdAt": {
"type": "string",
"description": "Timestamp when the attachment was created.",
"format": "date-time",
"examples": [
"2026-03-30T09:05:00Z"
]
},
"url": {
"type": "string",
"description": "URL to fetch the attachment.",
"examples": [
"https://example.com/stop-attachment/attachment-2025-06-03-1"
]
}
},
"description": "An attachment to a stop, such as a proof of delivery photo or signature."
},
"description": "Proof of delivery signatures for the stop. Signatures may be fetched using\n the URLs on the attachments."
},
"tasks": {
"type": "array",
"items": {
"title": "Task",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Task ID (e.g. `\"tsk-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"tsk-123e4567-e89b-12d3-a456-426614174000"
]
},
"title": {
"type": "string",
"description": "Task title (e.g. `\"Delivery checklist\"`).",
"examples": [
"Delivery checklist"
]
},
"type": {
"enum": [
"UNKNOWN",
"CHECKBOXES",
"RADIO_BUTTONS",
"TEXT_INPUT",
"DECIMAL_INPUT",
"SCANNER_INPUT"
],
"type": "string",
"description": "Task type.",
"format": "enum",
"examples": [
"TEXT_INPUT"
]
},
"items": {
"type": "array",
"items": {
"title": "TaskItem",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Item ID (e.g. `\"itm-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"itm-123e4567-e89b-12d3-a456-426614174000"
]
},
"title": {
"type": "string",
"description": "Item title (e.g. `\"Pick up package\"`).",
"examples": [
"Pick up package"
]
},
"complete": {
"type": "boolean",
"description": "Whether the item is completed.",
"examples": [
true
]
},
"updatedAt": {
"type": "string",
"description": "Timestamp when the item was last updated.",
"format": "date-time",
"examples": [
"2026-03-30T13:00:00Z"
]
}
},
"description": "An item within a task. For `CHECKBOXES`, each item on a task may be completed\n independently. For `RADIO_BUTTONS`, at most one item will be completed."
},
"description": "Task items (populated for `CHECKBOXES` and `RADIO_BUTTONS`).",
"examples": [
[]
]
},
"input": {
"allOf": [
{
"title": "TaskInput",
"type": "object",
"properties": {
"value": {
"type": "string",
"description": "Input value.",
"examples": [
"020123456789"
]
},
"updatedAt": {
"type": "string",
"description": "Timestamp when the input was last updated.",
"format": "date-time",
"examples": [
"2026-03-30T13:00:00Z"
]
},
"inputMethod": {
"enum": [
"UNKNOWN",
"SCANNED"
],
"type": "string",
"description": "Whether input was scanned (e.g. a scanned barcode)",
"format": "enum",
"examples": [
"SCANNED"
]
}
},
"description": "Captured driver input for a task. The value may be text for `TEXT_INPUT`\n tasks or a string decimal number for `DECIMAL_INPUT` tasks."
}
],
"description": "Task input (populated for `TEXT_INPUT` and `DECIMAL_INPUT`)."
},
"requiredToMarkStopAsDelivered": {
"type": "boolean",
"description": "Whether the task is required to mark the stop as completed. In the case of\n tasks on `RouteStart`, this represents tasks required for starting the\n route. In the case of tasks on `RouteEnd`, this represents tasks required\n for completing the route.",
"examples": [
true
]
},
"requiredToMarkStopAsAttempted": {
"type": "boolean",
"description": "Whether the task is required to mark the stop as attempted.",
"examples": [
true
]
}
},
"description": "A task to be completed at a stop, or at the start or end of a route. Tasks\n may have one or more items for `CHECKBOXES` or `RADIO_BUTTONS`, or may have\n an input for `TEXT_INPUT` or `DECIMAL_INPUT`."
},
"description": "Driver tasks for the stop, including completed items and any input from the\n driver."
},
"priority": {
"maximum": 10,
"type": "integer",
"description": "Priority of the stop for route planning. The valid range for stop priority\n is between `1` (low) and `10` (high), with default priority corresponding\n to a value of `5`. A priority value of `0` is considered unset and is\n treated the same as \"default\" priority. Stops with higher priority will be\n preferred when generating routes with constraints.",
"format": "int32",
"examples": [
8
]
},
"importedStopId": {
"type": "string",
"description": "The imported stop ID, populated when the stop source is `IMPORTED_STOP`.",
"examples": [
"ist-123e4567-e89b-12d3-a456-426614174000"
]
},
"orderName": {
"type": "string",
"description": "The name of the order associated with the stop. For Shopify orders, the\n name is generated by combining the `orderNumber` property with the order\n prefix and suffix that are set in the merchant's general settings. For\n EasyRoutes imported orders, this field is populated with the order name\n provided on import.",
"examples": [
"#1234"
]
},
"distanceMeters": {
"type": "number",
"description": "The distance in meters from the previous stop.",
"format": "double",
"examples": [
123.45
]
},
"updatedArrival": {
"type": "string",
"description": "Estimated arrival time at the stop. If the stop is completed, this will be\n the actual arrival time.",
"format": "date-time",
"examples": [
"2026-03-30T13:05:00Z"
]
},
"timeWindows": {
"type": "array",
"items": {
"title": "TimeWindow",
"type": "object",
"properties": {
"start": {
"allOf": [
{
"title": "TimeOfDay",
"type": "object",
"properties": {
"hours": {
"maximum": 23,
"type": "integer",
"description": "Hours of day in 24 hour format. Must be from 0 to 23.",
"format": "int32",
"examples": [
13
]
},
"minutes": {
"maximum": 59,
"type": "integer",
"description": "Minutes of hour of day. Must be from 0 to 59.",
"format": "int32",
"examples": [
37
]
},
"seconds": {
"maximum": 59,
"type": "integer",
"description": "Seconds of minutes of the time. Must be from 0 to 59.",
"format": "int32",
"examples": [
16
]
}
},
"description": "A time of day, independent of a particular date or timezone."
}
],
"description": "The start time of the time window (optional)."
},
"end": {
"allOf": [
{
"title": "TimeOfDay",
"type": "object",
"properties": {
"hours": {
"maximum": 23,
"type": "integer",
"description": "Hours of day in 24 hour format. Must be from 0 to 23.",
"format": "int32",
"examples": [
13
]
},
"minutes": {
"maximum": 59,
"type": "integer",
"description": "Minutes of hour of day. Must be from 0 to 59.",
"format": "int32",
"examples": [
37
]
},
"seconds": {
"maximum": 59,
"type": "integer",
"description": "Seconds of minutes of the time. Must be from 0 to 59.",
"format": "int32",
"examples": [
16
]
}
},
"description": "A time of day, independent of a particular date or timezone."
}
],
"description": "The end time of the time window (optional)."
}
},
"description": "A time window for a stop. The time window may be open-ended, but one or both\n of the start and end times should be provided. The end time must be >= the\n start time."
},
"description": "The time window for the stop. Note that we currently support at most one\n time window but may support multiple time windows in the future.",
"examples": [
[
{
"start": {
"hours": 9
},
"end": {
"hours": 17
}
}
]
]
},
"deliveryDate": {
"allOf": [
{
"title": "Date",
"required": [
"year",
"month",
"day"
],
"type": "object",
"properties": {
"year": {
"maximum": 9999,
"minimum": 1,
"type": "integer",
"description": "Year of the date. Must be from 1 to 9999.",
"format": "int32",
"examples": [
2019
]
},
"month": {
"maximum": 12,
"minimum": 1,
"type": "integer",
"description": "Month of a year. Must be from 1 to 12.",
"format": "int32",
"examples": [
11
]
},
"day": {
"maximum": 31,
"minimum": 1,
"type": "integer",
"description": "Day of a month. Must be from 1 to 31.",
"format": "int32",
"examples": [
15
]
}
},
"description": "A date in year-month-day format."
}
],
"description": "The planned delivery date for the stop.",
"examples": [
{
"year": 2025,
"month": 12,
"day": 16
}
]
},
"attributes": {
"type": "array",
"items": {
"title": "Attribute",
"type": "object",
"properties": {
"key": {
"type": "string",
"description": "Attribute key. Must be non-empty.",
"examples": [
"delivery_date"
]
},
"value": {
"type": "string",
"description": "Attribute value.",
"examples": [
"2025-12-16"
]
}
},
"description": "A key-value pair for storing additional information on a stop, such as order\n details, delivery instructions, or custom fields."
},
"description": "Additional attributes for the stop. Attributes are key-value pairs for\n storing additional structured data on stops. These may be populated from\n the Shopify order or set on import.",
"examples": [
[
{
"key": "color",
"value": "blue"
}
]
]
},
"clientStopId": {
"type": "string",
"description": "The client-provided ID associated with the stop, if provided on import.",
"examples": [
"test-order-1234"
]
},
"tags": {
"type": "array",
"items": {
"type": "string"
},
"description": "The tags for the stop. Tags are used to categorize stops and can be used\n for filtering and grouping stops in the EasyRoutes web app. These may be\n populated from the Shopify order or set on import.",
"examples": [
[
"foo",
"bar"
]
]
},
"attemptedReason": {
"enum": [
"UNKNOWN",
"NOT_AVAILABLE",
"ACCESS_DENIED",
"INCORRECT_ADDRESS",
"SAFE_PLACE_UNAVAILABLE",
"REFUSED",
"EXTERNAL",
"INCORRECT_ITEMS",
"OTHER",
"CANCELED"
],
"type": "string",
"description": "The reason for marking the stop as attempted. This is only populated when\n `deliveryStatus = ATTEMPTED_DELIVERY`.",
"format": "enum",
"examples": [
"NOT_AVAILABLE"
]
},
"attemptedNote": {
"type": "string",
"description": "Optional note related to the reason for marking the stop as attempted. This\n is optionally populated when `deliveryStatus = ATTEMPTED_DELIVERY`.",
"examples": [
"Customer did not answer the door."
]
},
"customerRating": {
"allOf": [
{
"title": "CustomerRating",
"type": "object",
"properties": {
"rating": {
"maximum": 5,
"minimum": 1,
"type": "integer",
"description": "Rating from 1-5",
"format": "int32",
"examples": [
5
]
},
"comment": {
"type": "string",
"description": "Customer comment related to rating",
"examples": [
"Excellent delivery"
]
},
"createdAt": {
"type": "string",
"description": "Timestamp when rating was left by customer.",
"format": "date-time",
"examples": [
"2026-03-30T18:00:00Z"
]
}
},
"description": "Customer rating and feedback left on a stop."
}
],
"description": "Rating left by customer. This can only be populated once `deliveryStatus =\n DELIVERED`."
},
"customSignatureDisclosure": {
"type": "string",
"description": "Optional custom signature disclosure that is shown to customers in the\n driver app.",
"examples": [
"I acknowledge that I have received this delivery."
]
},
"shopifyOrder": {
"allOf": [
{
"title": "ShopifyOrder",
"type": "object",
"properties": {
"orderNote": {
"type": "string",
"description": "The Shopify order note.",
"examples": [
"Customer has paid."
]
},
"customerNote": {
"type": "string",
"description": "The Shopify customer note for the order.",
"examples": [
"Leave at door."
]
}
},
"description": "Shopify-specific information for a RouteStop."
}
],
"description": "Information from the associated Shopify order, if applicable. Populated if\n stop source is `SHOPIFY_ORDER`"
},
"proofOfDeliveryBarcodes": {
"type": "array",
"items": {
"title": "ScannedBarcode",
"type": "object",
"properties": {
"value": {
"type": "string",
"description": "Barcode value (e.g. `\"123456789012\"`).",
"examples": [
"123456789012"
]
},
"createdAt": {
"type": "string",
"description": "Timestamp when the barcode was scanned.",
"format": "date-time",
"examples": [
"2026-03-30T13:10:00Z"
]
}
},
"description": "A proof of delivery barcode scanned at a stop."
},
"description": "Proof of delivery barcodes scanned at the stop."
},
"proofOfDeliveryBarcodeIssues": {
"type": "array",
"items": {
"title": "ScannedBarcodeIssue",
"type": "object",
"properties": {
"reason": {
"enum": [
"UNKNOWN",
"ITEM_MISSING",
"NOT_SCANNABLE",
"INCORRECT"
],
"type": "string",
"description": "The reported reason for the barcode issue.",
"format": "enum",
"examples": [
"ITEM_MISSING"
]
},
"note": {
"type": "string",
"description": "Optional note related to the reason for reporting a barcode issue.",
"examples": [
"Item was not packed."
]
},
"createdAt": {
"type": "string",
"description": "Timestamp when the issue was reported.",
"format": "date-time",
"examples": [
"2026-03-30T13:10:00Z"
]
}
},
"description": "A reported issue related to scanning barcodes at a stop."
},
"description": "Proof of delivery barcode issues reported at the stop."
},
"orderReferenceUrl": {
"type": "string",
"description": "A reference URL for the order associated with the stop (e.g. a link to the\n order in your order management system). Must be a valid HTTPS URL. This\n field can only be populated for imported stops.",
"examples": [
"https://orders.example.com/orders/148977776"
]
}
},
"description": "A stop on a route. A stop may correspond to a delivery or a driver break as\n determined by the type. A delivery stop will have location and contact\n information, items to deliver, optional order details, status, arrival time\n and stop duration, driver tasks and any proof of delivery information. A\n break stop will have start time and duration, and status."
},
"description": "Route stops. See RouteStop for stop fields."
},
"createdAt": {
"type": "string",
"description": "Timestamp when the route was created.",
"format": "date-time",
"examples": [
"2026-03-29T08:00:00Z"
]
},
"updatedAt": {
"type": "string",
"description": "Timestamp when the route was last updated (by the planner).",
"format": "date-time",
"examples": [
"2026-03-30T13:15:00Z"
]
},
"archivedAt": {
"type": "string",
"description": "Timestamp when the route was archived.",
"format": "date-time",
"examples": [
"2026-04-05T00:00:00Z"
]
},
"scheduledFor": {
"type": "string",
"description": "Timestamp when the route is scheduled for.",
"format": "date-time",
"examples": [
"2026-03-30T09:00:00Z"
]
},
"totalDistanceMeters": {
"type": "number",
"description": "The distance in meters for the entire route.",
"format": "double",
"examples": [
2387.2
]
},
"totalItemQuantity": {
"type": "integer",
"description": "The total quantity of items to deliver on the route.",
"format": "int32",
"examples": [
50
]
},
"totalItemGrams": {
"type": "string",
"description": "The total weight in grams for the items on the route.",
"examples": [
"6000"
]
},
"optimized": {
"type": "boolean",
"description": "Whether the route has been optimized. Adding or removing stops, reordering\n stops, or changing route options generally set this field to false until\n the route is reoptimized.",
"examples": [
true
]
},
"dispatchedUntil": {
"type": "string",
"description": "Timestamp until which the route is dispatched and accessible in the driver\n app.",
"format": "date-time",
"examples": [
"2026-03-30T20:00:00Z"
]
},
"note": {
"type": "string",
"description": "Top-level note for the route, as entered manually by route planners.",
"examples": [
"Fragile items."
]
},
"tags": {
"type": "array",
"items": {
"type": "string"
},
"description": "The tags for the route. Tags are used to categorize routes and can be\n used for filtering and grouping routes in the EasyRoutes web app.",
"examples": [
[
"foo",
"bar"
]
]
},
"defaultStopDuration": {
"pattern": "^-?(?:0|[1-9][0-9]{0,11})(?:\\.[0-9]{1,9})?s$",
"type": "string",
"description": "The default duration for stops on the route. Used to estimate arrival\n times for stops that do not have their own duration specified.\n Specified as a duration string in the format \"300s\" for 5 minutes, \"60s\"\n for 1 minute, etc.",
"examples": [
"300s"
]
},
"maxDuration": {
"pattern": "^-?(?:0|[1-9][0-9]{0,11})(?:\\.[0-9]{1,9})?s$",
"type": "string",
"description": "The maximum duration of the route. Specified as a duration string in the\n format \"3600s\" for 1 hour, \"7200s\" for 2 hours, etc.",
"examples": [
"28800s"
]
},
"maxStops": {
"type": "integer",
"description": "The maximum number of stops on the route.",
"format": "int32",
"examples": [
50
]
},
"maxItemCount": {
"type": "integer",
"description": "The maximum total item count across all stops on the route.",
"format": "int32",
"examples": [
200
]
},
"maxKilograms": {
"type": "number",
"description": "The maximum total weight in kilograms across all stops on the route.",
"format": "double",
"examples": [
500
]
},
"avoidTolls": {
"type": "boolean",
"description": "Whether to avoid toll roads during optimization.",
"examples": [
true
]
},
"avoidUTurns": {
"type": "boolean",
"description": "Whether to avoid U-turns during optimization.",
"examples": [
true
]
},
"speedFactor": {
"type": "number",
"description": "A speed factor for the route used during optimization to adjust estimated\n travel times. A value of 1.0 represents normal speed. Values less than 1.0\n indicate slower travel (e.g. 0.5 = half speed), and values greater than\n 1.0 indicate faster travel (e.g. 1.5 = 50% faster). Must be between 0.1\n and 1.9. A value of 0 (or unset) uses the default speed.",
"format": "double",
"examples": [
0.8
]
},
"vehicle": {
"allOf": [
{
"title": "Vehicle",
"required": [
"id"
],
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Vehicle ID.",
"examples": [
"veh-123e4567-e89b-12d3-a456-426614174000"
]
},
"name": {
"type": "string",
"description": "Vehicle name.",
"examples": [
"Delivery Van 1"
]
},
"make": {
"type": "string",
"description": "Vehicle make.",
"examples": [
"Ford"
]
},
"model": {
"type": "string",
"description": "Vehicle model.",
"examples": [
"Transit"
]
},
"year": {
"type": "integer",
"description": "Vehicle model year.",
"format": "int32",
"examples": [
2023
]
},
"type": {
"enum": [
"UNKNOWN",
"CAR",
"CARGO_VAN",
"PICKUP_TRUCK",
"BOX_TRUCK",
"MOTORCYCLE",
"BICYCLE",
"DRONE",
"OTHER"
],
"type": "string",
"description": "Vehicle type.",
"format": "enum",
"examples": [
"CARGO_VAN"
]
},
"vin": {
"type": "string",
"description": "Vehicle Identification Number.",
"examples": [
"1FTBW2CM5NKA12345"
]
},
"license": {
"type": "string",
"description": "Vehicle license plate.",
"examples": [
"ABC-1234"
]
},
"isArchived": {
"type": "boolean",
"description": "Whether the vehicle is archived.",
"examples": [
false
]
},
"createdTimestamp": {
"type": "string",
"description": "Timestamp when the vehicle was created.",
"format": "date-time",
"examples": [
"2026-07-30T12:00:00Z"
]
}
},
"description": "A vehicle that can be assigned to a route."
}
],
"description": "Assigned vehicle for the route."
}
},
"description": "A route of stops, optionally with an assigned driver."
}
}
}
},
"default": {
"description": "Default error response",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"code": {
"type": "integer",
"description": "The status code, which should be an enum value of [google.rpc.Code][google.rpc.Code].",
"format": "int32"
},
"message": {
"type": "string",
"description": "A developer-facing error message, which should be in English. Any user-facing error message should be localized and sent in the [google.rpc.Status.details][google.rpc.Status.details] field, or localized by the client."
},
"details": {
"type": "array",
"items": {
"type": "object",
"properties": {
"@type": {
"type": "string",
"description": "The type of the serialized message."
}
},
"additionalProperties": true,
"description": "Contains an arbitrary serialized message along with a @type that describes the type of the serialized message."
},
"description": "A list of messages that carry the error details. There is a common set of message types for APIs to use."
}
},
"description": "The `Status` type defines a logical error model that is suitable for different programming environments, including REST APIs and RPC APIs. It is used by [gRPC](https://github.com/grpc). Each `Status` message contains three pieces of data: error code, error message, and error details. You can find out more about this error model and how to work with it in the [API Design Guide](https://cloud.google.com/apis/design/errors)."
}
}
}
}
},
"security": [
{
"bearerAuth": []
}
],
"components": {
"securitySchemes": {
"bearerAuth": {
"type": "http",
"description": "Access token from `/authenticate`",
"scheme": "bearer",
"bearerFormat": "JWT"
}
}
}
}
```
# Update route end tasks (https://docs.roundtrip.ai/docs/api-reference/routes/put-routes-routeId-end-tasks)
PUT /routes/{routeId}/end/tasks
Updates the tasks required to complete a route by route ID. This is a
full replacement: the entire list of tasks on the route end is replaced
with the task templates provided in the request body, so existing tasks
not included in the request will be removed. Task and item IDs are always
regenerated by the server, and any existing completion state, input, or
timestamps are cleared, since only the driver (via the driver app) can
mark a task or item complete or provide input. The route must have an end
location and must not be archived. The response returns the full updated
route.
## OpenAPI specification
```json
{
"servers": [
{
"url": "https://easyroutes.roundtrip.ai/api/2024-07"
}
],
"tags": [
"Routes"
],
"summary": "Update route end tasks",
"description": "Updates the tasks required to complete a route by route ID. This is a\n full replacement: the entire list of tasks on the route end is replaced\n with the task templates provided in the request body, so existing tasks\n not included in the request will be removed. Task and item IDs are always\n regenerated by the server, and any existing completion state, input, or\n timestamps are cleared, since only the driver (via the driver app) can\n mark a task or item complete or provide input. The route must have an end\n location and must not be archived. The response returns the full updated\n route.",
"operationId": "UpdateRouteEndTasks",
"parameters": [
{
"name": "routeId",
"in": "path",
"description": "The ID of the route to update end tasks.",
"required": true,
"schema": {
"type": "string",
"examples": [
"rte-123e4567-e89b-12d3-a456-426614174000"
]
}
},
{
"name": "Idempotency-Key",
"in": "header",
"description": "A unique key for safely retrying this operation. For more information read [our guide](https://docs.roundtrip.ai/docs/concepts/idempotency.md).",
"schema": {
"maxLength": 255,
"minLength": 1,
"type": "string"
},
"examples": {
"default": {
"value": "550e8400-e29b-41d4-a716-446655440000"
}
}
}
],
"requestBody": {
"content": {
"application/json": {
"schema": {
"type": "array",
"items": {
"title": "TaskTemplate",
"type": "object",
"properties": {
"title": {
"type": "string",
"description": "Task title (e.g. `\"Delivery checklist\"`).",
"examples": [
"Delivery checklist"
]
},
"type": {
"enum": [
"UNKNOWN",
"CHECKBOXES",
"RADIO_BUTTONS",
"TEXT_INPUT",
"DECIMAL_INPUT",
"SCANNER_INPUT"
],
"type": "string",
"description": "Task type.",
"format": "enum",
"examples": [
"CHECKBOXES"
]
},
"items": {
"type": "array",
"items": {
"title": "TaskItemTemplate",
"type": "object",
"properties": {
"title": {
"type": "string",
"description": "Item title (e.g. `\"Pick up package\"`).",
"examples": [
"Pick up package"
]
}
},
"description": "An item template for a task. For `CHECKBOXES`, each item on a task may be\n completed independently. For `RADIO_BUTTONS`, at most one item will be\n completed."
},
"description": "Task items, which are required for `CHECKBOXES` and `RADIO_BUTTONS`."
},
"requiredToMarkStopAsDelivered": {
"type": "boolean",
"description": "Whether the task is required to mark the stop as completed.",
"examples": [
true
]
},
"requiredToMarkStopAsAttempted": {
"type": "boolean",
"description": "Whether the task is required to mark the stop as attempted.",
"examples": [
true
]
}
},
"description": "A template for creating tasks at a stop. Task templates may have one or more\n items for `CHECKBOXES` or `RADIO_BUTTONS`. Imported stops may have task\n templates that are used to create tasks when the stop is added to a route."
}
}
}
},
"required": true
},
"responses": {
"200": {
"description": "OK",
"headers": {
"Idempotency-Key": {
"description": "The idempotency key associated with the response.",
"schema": {
"type": "string"
}
},
"Idempotency-Replayed": {
"description": "Whether the response was replayed from a previous request.",
"schema": {
"type": "boolean"
}
}
},
"content": {
"application/json": {
"schema": {
"title": "Route",
"required": [
"id",
"name",
"stops",
"createdAt",
"updatedAt",
"totalDistanceMeters",
"totalItemQuantity",
"totalItemGrams",
"optimized"
],
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Route ID (e.g. `\"rte-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"rte-123e4567-e89b-12d3-a456-426614174000"
]
},
"name": {
"type": "string",
"description": "Route name (e.g. `\"Morning route\"`).",
"examples": [
"Morning route"
]
},
"driver": {
"allOf": [
{
"title": "Driver",
"required": [
"id"
],
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Driver ID (e.g. `\"drv-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"drv-123e4567-e89b-12d3-a456-426614174000"
]
},
"firstName": {
"type": "string",
"description": "Driver first name (e.g. `\"John\"`).",
"examples": [
"John"
]
},
"lastName": {
"type": "string",
"description": "Driver last name (e.g. `\"Doe\"`).",
"examples": [
"Doe"
]
},
"phone": {
"type": "string",
"description": "Driver phone number in [E.164 format](https://en.wikipedia.org/wiki/E.164)\n (e.g. `\"+14265551000\"`).",
"examples": [
"+14265551000"
]
},
"status": {
"enum": [
"UNKNOWN",
"ACTIVE",
"INACTIVE",
"ARCHIVED"
],
"type": "string",
"description": "Shop driver status. (e.g. `ACTIVE`).",
"format": "enum",
"examples": [
"ACTIVE"
]
}
},
"description": "A driver who is assigned to a route."
}
],
"description": "Assigned driver for the route."
},
"start": {
"allOf": [
{
"title": "RouteStart",
"type": "object",
"properties": {
"address": {
"allOf": [
{
"title": "Address",
"type": "object",
"properties": {
"address1": {
"type": "string",
"description": "Street address line 1 (e.g. `\"123 Main St\"`).",
"examples": [
"123 Main St"
]
},
"address2": {
"type": "string",
"description": "Street address line 2 (e.g. `\"Apt 101\"`).",
"examples": [
"Apt 3B"
]
},
"city": {
"type": "string",
"description": "City name (e.g. `\"New York\"`).",
"examples": [
"New York"
]
},
"provinceCode": {
"type": "string",
"description": "Province or state as subdivision codes in\n [ISO 3166-2](https://en.wikipedia.org/wiki/ISO_3166-2) format without the\n country prefix (e.g. `\"NY\"` for New York).",
"examples": [
"NY"
]
},
"countryCode": {
"type": "string",
"description": "Country code (e.g. `\"US\"`).",
"examples": [
"US"
]
},
"zip": {
"type": "string",
"description": "Postal or ZIP code (e.g. `\"10001\"`).",
"examples": [
"10001"
]
}
},
"description": "A physical street address."
}
],
"description": "The start address of the route.",
"examples": [
{
"address1": "123 Main St",
"address2": "Apt 3B",
"city": "New York",
"provinceCode": "NY",
"countryCode": "US",
"zip": "10001"
}
]
},
"tasks": {
"type": "array",
"items": {
"title": "Task",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Task ID (e.g. `\"tsk-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"tsk-123e4567-e89b-12d3-a456-426614174000"
]
},
"title": {
"type": "string",
"description": "Task title (e.g. `\"Delivery checklist\"`).",
"examples": [
"Delivery checklist"
]
},
"type": {
"enum": [
"UNKNOWN",
"CHECKBOXES",
"RADIO_BUTTONS",
"TEXT_INPUT",
"DECIMAL_INPUT",
"SCANNER_INPUT"
],
"type": "string",
"description": "Task type.",
"format": "enum",
"examples": [
"TEXT_INPUT"
]
},
"items": {
"type": "array",
"items": {
"title": "TaskItem",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Item ID (e.g. `\"itm-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"itm-123e4567-e89b-12d3-a456-426614174000"
]
},
"title": {
"type": "string",
"description": "Item title (e.g. `\"Pick up package\"`).",
"examples": [
"Pick up package"
]
},
"complete": {
"type": "boolean",
"description": "Whether the item is completed.",
"examples": [
true
]
},
"updatedAt": {
"type": "string",
"description": "Timestamp when the item was last updated.",
"format": "date-time",
"examples": [
"2026-03-30T13:00:00Z"
]
}
},
"description": "An item within a task. For `CHECKBOXES`, each item on a task may be completed\n independently. For `RADIO_BUTTONS`, at most one item will be completed."
},
"description": "Task items (populated for `CHECKBOXES` and `RADIO_BUTTONS`).",
"examples": [
[]
]
},
"input": {
"allOf": [
{
"title": "TaskInput",
"type": "object",
"properties": {
"value": {
"type": "string",
"description": "Input value.",
"examples": [
"020123456789"
]
},
"updatedAt": {
"type": "string",
"description": "Timestamp when the input was last updated.",
"format": "date-time",
"examples": [
"2026-03-30T13:00:00Z"
]
},
"inputMethod": {
"enum": [
"UNKNOWN",
"SCANNED"
],
"type": "string",
"description": "Whether input was scanned (e.g. a scanned barcode)",
"format": "enum",
"examples": [
"SCANNED"
]
}
},
"description": "Captured driver input for a task. The value may be text for `TEXT_INPUT`\n tasks or a string decimal number for `DECIMAL_INPUT` tasks."
}
],
"description": "Task input (populated for `TEXT_INPUT` and `DECIMAL_INPUT`)."
},
"requiredToMarkStopAsDelivered": {
"type": "boolean",
"description": "Whether the task is required to mark the stop as completed. In the case of\n tasks on `RouteStart`, this represents tasks required for starting the\n route. In the case of tasks on `RouteEnd`, this represents tasks required\n for completing the route.",
"examples": [
true
]
},
"requiredToMarkStopAsAttempted": {
"type": "boolean",
"description": "Whether the task is required to mark the stop as attempted.",
"examples": [
true
]
}
},
"description": "A task to be completed at a stop, or at the start or end of a route. Tasks\n may have one or more items for `CHECKBOXES` or `RADIO_BUTTONS`, or may have\n an input for `TEXT_INPUT` or `DECIMAL_INPUT`."
},
"description": "Tasks to complete before starting the route."
},
"status": {
"enum": [
"UNKNOWN",
"STARTED"
],
"type": "string",
"description": "Status indicating whether the route has been started.",
"format": "enum",
"examples": [
"STARTED"
]
},
"updatedStart": {
"type": "string",
"description": "Updated start time for the route. If the route is started, this will be the\n actual start time.",
"format": "date-time",
"examples": [
"2026-03-30T09:05:00Z"
]
},
"scheduledStart": {
"type": "string",
"description": "Scheduled start time for the route (same as `scheduledFor` on the route).",
"format": "date-time",
"examples": [
"2026-03-30T09:00:00Z"
]
},
"photos": {
"type": "array",
"items": {
"title": "StopAttachment",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Attachment ID (e.g. `\"att-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"att-123e4567-e89b-12d3-a456-426614174000"
]
},
"createdAt": {
"type": "string",
"description": "Timestamp when the attachment was created.",
"format": "date-time",
"examples": [
"2026-03-30T09:05:00Z"
]
},
"url": {
"type": "string",
"description": "URL to fetch the attachment.",
"examples": [
"https://example.com/stop-attachment/attachment-2025-06-03-1"
]
}
},
"description": "An attachment to a stop, such as a proof of delivery photo or signature."
},
"description": "Photos for the route start. Photos may be fetched using the URLs on the\n attachments."
}
},
"description": "The start location of a route and any driver tasks to complete before\n beginning the route."
}
],
"description": "Route start address and tasks."
},
"end": {
"allOf": [
{
"title": "RouteEnd",
"type": "object",
"properties": {
"address": {
"allOf": [
{
"title": "Address",
"type": "object",
"properties": {
"address1": {
"type": "string",
"description": "Street address line 1 (e.g. `\"123 Main St\"`).",
"examples": [
"123 Main St"
]
},
"address2": {
"type": "string",
"description": "Street address line 2 (e.g. `\"Apt 101\"`).",
"examples": [
"Apt 3B"
]
},
"city": {
"type": "string",
"description": "City name (e.g. `\"New York\"`).",
"examples": [
"New York"
]
},
"provinceCode": {
"type": "string",
"description": "Province or state as subdivision codes in\n [ISO 3166-2](https://en.wikipedia.org/wiki/ISO_3166-2) format without the\n country prefix (e.g. `\"NY\"` for New York).",
"examples": [
"NY"
]
},
"countryCode": {
"type": "string",
"description": "Country code (e.g. `\"US\"`).",
"examples": [
"US"
]
},
"zip": {
"type": "string",
"description": "Postal or ZIP code (e.g. `\"10001\"`).",
"examples": [
"10001"
]
}
},
"description": "A physical street address."
}
],
"description": "The end address of the route.",
"examples": [
{
"address1": "123 Main St",
"address2": "Apt 3B",
"city": "New York",
"provinceCode": "NY",
"countryCode": "US",
"zip": "10001"
}
]
},
"tasks": {
"type": "array",
"items": {
"title": "Task",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Task ID (e.g. `\"tsk-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"tsk-123e4567-e89b-12d3-a456-426614174000"
]
},
"title": {
"type": "string",
"description": "Task title (e.g. `\"Delivery checklist\"`).",
"examples": [
"Delivery checklist"
]
},
"type": {
"enum": [
"UNKNOWN",
"CHECKBOXES",
"RADIO_BUTTONS",
"TEXT_INPUT",
"DECIMAL_INPUT",
"SCANNER_INPUT"
],
"type": "string",
"description": "Task type.",
"format": "enum",
"examples": [
"TEXT_INPUT"
]
},
"items": {
"type": "array",
"items": {
"title": "TaskItem",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Item ID (e.g. `\"itm-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"itm-123e4567-e89b-12d3-a456-426614174000"
]
},
"title": {
"type": "string",
"description": "Item title (e.g. `\"Pick up package\"`).",
"examples": [
"Pick up package"
]
},
"complete": {
"type": "boolean",
"description": "Whether the item is completed.",
"examples": [
true
]
},
"updatedAt": {
"type": "string",
"description": "Timestamp when the item was last updated.",
"format": "date-time",
"examples": [
"2026-03-30T13:00:00Z"
]
}
},
"description": "An item within a task. For `CHECKBOXES`, each item on a task may be completed\n independently. For `RADIO_BUTTONS`, at most one item will be completed."
},
"description": "Task items (populated for `CHECKBOXES` and `RADIO_BUTTONS`).",
"examples": [
[]
]
},
"input": {
"allOf": [
{
"title": "TaskInput",
"type": "object",
"properties": {
"value": {
"type": "string",
"description": "Input value.",
"examples": [
"020123456789"
]
},
"updatedAt": {
"type": "string",
"description": "Timestamp when the input was last updated.",
"format": "date-time",
"examples": [
"2026-03-30T13:00:00Z"
]
},
"inputMethod": {
"enum": [
"UNKNOWN",
"SCANNED"
],
"type": "string",
"description": "Whether input was scanned (e.g. a scanned barcode)",
"format": "enum",
"examples": [
"SCANNED"
]
}
},
"description": "Captured driver input for a task. The value may be text for `TEXT_INPUT`\n tasks or a string decimal number for `DECIMAL_INPUT` tasks."
}
],
"description": "Task input (populated for `TEXT_INPUT` and `DECIMAL_INPUT`)."
},
"requiredToMarkStopAsDelivered": {
"type": "boolean",
"description": "Whether the task is required to mark the stop as completed. In the case of\n tasks on `RouteStart`, this represents tasks required for starting the\n route. In the case of tasks on `RouteEnd`, this represents tasks required\n for completing the route.",
"examples": [
true
]
},
"requiredToMarkStopAsAttempted": {
"type": "boolean",
"description": "Whether the task is required to mark the stop as attempted.",
"examples": [
true
]
}
},
"description": "A task to be completed at a stop, or at the start or end of a route. Tasks\n may have one or more items for `CHECKBOXES` or `RADIO_BUTTONS`, or may have\n an input for `TEXT_INPUT` or `DECIMAL_INPUT`."
},
"description": "Tasks to complete before finishing the route."
},
"plannedArrival": {
"type": "string",
"description": "Planned arrival time at the end of the route.",
"format": "date-time",
"examples": [
"2026-03-30T17:00:00Z"
]
},
"distanceMeters": {
"type": "number",
"description": "The distance in meters from the previous stop.",
"format": "double",
"examples": [
1234.56
]
},
"updatedArrival": {
"type": "string",
"description": "Estimated arrival time at the end of the route. If the route is completed,\n this will be the actual arrival time.",
"format": "date-time",
"examples": [
"2026-03-30T17:05:00Z"
]
},
"status": {
"enum": [
"UNKNOWN",
"COMPLETED"
],
"type": "string",
"description": "Status indicating whether the route has been completed.",
"format": "enum",
"examples": [
"COMPLETED"
]
},
"photos": {
"type": "array",
"items": {
"title": "StopAttachment",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Attachment ID (e.g. `\"att-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"att-123e4567-e89b-12d3-a456-426614174000"
]
},
"createdAt": {
"type": "string",
"description": "Timestamp when the attachment was created.",
"format": "date-time",
"examples": [
"2026-03-30T09:05:00Z"
]
},
"url": {
"type": "string",
"description": "URL to fetch the attachment.",
"examples": [
"https://example.com/stop-attachment/attachment-2025-06-03-1"
]
}
},
"description": "An attachment to a stop, such as a proof of delivery photo or signature."
},
"description": "Photos for the route end. Photos may be fetched using the URLs on the\n attachments."
}
},
"description": "The end location of a route and any driver tasks to complete after completing\n the route."
}
],
"description": "Route end address and tasks."
},
"stops": {
"type": "array",
"items": {
"title": "RouteStop",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Stop ID (e.g. `\"rst-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"rst-123e4567-e89b-12d3-a456-426614174000"
]
},
"type": {
"enum": [
"UNKNOWN",
"DELIVERY",
"BREAK",
"PICKUP",
"TASK"
],
"type": "string",
"description": "The type of stop (DELIVERY, BREAK, PICKUP, or TASK).",
"format": "enum",
"examples": [
"DELIVERY"
]
},
"deliveryStatus": {
"enum": [
"UNKNOWN",
"DELIVERED",
"OUT_FOR_DELIVERY",
"ATTEMPTED_DELIVERY",
"READY_FOR_DELIVERY"
],
"type": "string",
"description": "The status for DELIVERY, PICKUP, or TASK stops.",
"format": "enum",
"examples": [
"ATTEMPTED_DELIVERY"
]
},
"breakStatus": {
"enum": [
"UNKNOWN",
"COMPLETED"
],
"type": "string",
"description": "The status for BREAK stops.",
"format": "enum",
"examples": [
"COMPLETED"
]
},
"updatedAt": {
"type": "string",
"description": "Timestamp when the stop status was last updated. Note that this timestamp\n corresponds only to major status updates (i.e. stop marked as DELIVERED).\n Minor updates like task completion or adding proof of delivery will not\n advance this timestamp. For those events, use the timestamps on the task or\n proof of delivery attachment.",
"format": "date-time",
"examples": [
"2026-03-30T13:15:00Z"
]
},
"duration": {
"pattern": "^-?(?:0|[1-9][0-9]{0,11})(?:\\.[0-9]{1,9})?s$",
"type": "string",
"description": "Planned duration of the stop in seconds.",
"examples": [
"300s"
]
},
"plannedArrival": {
"type": "string",
"description": "Planned arrival time at the stop.",
"format": "date-time",
"examples": [
"2026-03-30T13:00:00Z"
]
},
"note": {
"type": "string",
"description": "Top-level note for the stop, as entered manually by route planners,\n inherited from a saved or imported stop, or set by order import automation\n rules.",
"examples": [
"Leave at door."
]
},
"address": {
"allOf": [
{
"title": "Address",
"type": "object",
"properties": {
"address1": {
"type": "string",
"description": "Street address line 1 (e.g. `\"123 Main St\"`).",
"examples": [
"123 Main St"
]
},
"address2": {
"type": "string",
"description": "Street address line 2 (e.g. `\"Apt 101\"`).",
"examples": [
"Apt 3B"
]
},
"city": {
"type": "string",
"description": "City name (e.g. `\"New York\"`).",
"examples": [
"New York"
]
},
"provinceCode": {
"type": "string",
"description": "Province or state as subdivision codes in\n [ISO 3166-2](https://en.wikipedia.org/wiki/ISO_3166-2) format without the\n country prefix (e.g. `\"NY\"` for New York).",
"examples": [
"NY"
]
},
"countryCode": {
"type": "string",
"description": "Country code (e.g. `\"US\"`).",
"examples": [
"US"
]
},
"zip": {
"type": "string",
"description": "Postal or ZIP code (e.g. `\"10001\"`).",
"examples": [
"10001"
]
}
},
"description": "A physical street address."
}
],
"description": "Delivery address for the stop.",
"examples": [
{
"address1": "123 Main St",
"address2": "Apt 3B",
"city": "New York",
"provinceCode": "NY",
"countryCode": "US",
"zip": "10001"
}
]
},
"contact": {
"allOf": [
{
"title": "Contact",
"type": "object",
"properties": {
"firstName": {
"type": "string",
"description": "First name (e.g. `\"John\"`).",
"examples": [
"John"
]
},
"lastName": {
"type": "string",
"description": "Last name (e.g. `\"Doe\"`).",
"examples": [
"Doe"
]
},
"company": {
"type": "string",
"description": "Company name (e.g. `\"Roundtrip Systems Inc\"`).",
"examples": [
"Roundtrip Systems Inc"
]
},
"phone": {
"type": "string",
"description": "Phone number in [E.164 format](https://en.wikipedia.org/wiki/E.164) (e.g.\n `\"+14265551000\"`).",
"examples": [
"+14265551000"
]
},
"email": {
"type": "string",
"description": "Email address (e.g. `\"john.doe@roundtrip.ai\"`)",
"examples": [
"john.doe@roundtrip.ai"
]
}
},
"description": "Contact information for a person or company."
}
],
"description": "Contact information for the stop delivery recipient.",
"examples": [
{
"firstName": "John",
"lastName": "Doe",
"company": "Roundtrip Systems Inc",
"phone": "+14265551000",
"email": "john.doe@roundtrip.ai"
}
]
},
"plannedCoordinates": {
"allOf": [
{
"type": "object",
"properties": {
"latitude": {
"type": "number",
"description": "The latitude in degrees. It must be in the range [-90.0, +90.0].",
"format": "double"
},
"longitude": {
"type": "number",
"description": "The longitude in degrees. It must be in the range [-180.0, +180.0].",
"format": "double"
}
},
"description": "An object that represents a latitude/longitude pair. This is expressed as a\n pair of doubles to represent degrees latitude and degrees longitude. Unless\n specified otherwise, this must conform to the\n WGS84\n standard. Values must be within normalized ranges."
}
],
"description": "Planned coordinates for the stop.",
"examples": [
{
"latitude": 40.7128,
"longitude": -74.006
}
]
},
"items": {
"type": "array",
"items": {
"title": "StopItem",
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "Item name (e.g. `\"Bananas\"`).",
"examples": [
"Bananas"
]
},
"quantity": {
"type": "integer",
"description": "Quantity of the item (e.g. `5`).",
"format": "int32",
"examples": [
5
]
},
"grams": {
"type": "integer",
"description": "Weight of the item in grams (e.g. `500`).",
"format": "int32",
"examples": [
500
]
},
"sku": {
"type": "string",
"description": "Stock keeping unit (e.g. `\"BANANA-001\"`).",
"examples": [
"BANANA-001"
]
}
},
"description": "An item to be delivered at a stop."
},
"description": "Items to deliver at the stop."
},
"source": {
"enum": [
"UNKNOWN",
"SHOPIFY_ORDER",
"SAVED_STOP",
"IMPORTED_STOP"
],
"type": "string",
"description": "The source of the stop, which may be populated for `DELIVERY` stops. The\n source can be a `SHOPIFY_ORDER`, an EasyRoutes `SAVED_STOP`, or an\n `IMPORTED_STOP` from an external source (such as CSV file).",
"format": "enum",
"examples": [
"IMPORTED_STOP"
]
},
"shopifyOrderId": {
"type": "string",
"description": "The Shopify order ID, populated when the stop source is a `SHOPIFY_ORDER`.",
"examples": [
"6229749334323"
]
},
"savedStopId": {
"type": "string",
"description": "The saved stop ID, populated when the stop source is a `SAVED_STOP`.",
"examples": [
"sst-123e4567-e89b-12d3-a456-426614174000"
]
},
"deliveredCoordinates": {
"allOf": [
{
"type": "object",
"properties": {
"latitude": {
"type": "number",
"description": "The latitude in degrees. It must be in the range [-90.0, +90.0].",
"format": "double"
},
"longitude": {
"type": "number",
"description": "The longitude in degrees. It must be in the range [-180.0, +180.0].",
"format": "double"
}
},
"description": "An object that represents a latitude/longitude pair. This is expressed as a\n pair of doubles to represent degrees latitude and degrees longitude. Unless\n specified otherwise, this must conform to the\n WGS84\n standard. Values must be within normalized ranges."
}
],
"description": "Delivered coordinates for the stop."
},
"proofOfDeliveryNote": {
"type": "string",
"description": "Proof of delivery note for the stop.",
"examples": [
"Left at door."
]
},
"proofOfDeliveryPhotos": {
"type": "array",
"items": {
"title": "StopAttachment",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Attachment ID (e.g. `\"att-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"att-123e4567-e89b-12d3-a456-426614174000"
]
},
"createdAt": {
"type": "string",
"description": "Timestamp when the attachment was created.",
"format": "date-time",
"examples": [
"2026-03-30T09:05:00Z"
]
},
"url": {
"type": "string",
"description": "URL to fetch the attachment.",
"examples": [
"https://example.com/stop-attachment/attachment-2025-06-03-1"
]
}
},
"description": "An attachment to a stop, such as a proof of delivery photo or signature."
},
"description": "Proof of delivery photos for the stop. Photos may be fetched using the URLs\n on the attachments."
},
"proofOfDeliverySignatures": {
"type": "array",
"items": {
"title": "StopAttachment",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Attachment ID (e.g. `\"att-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"att-123e4567-e89b-12d3-a456-426614174000"
]
},
"createdAt": {
"type": "string",
"description": "Timestamp when the attachment was created.",
"format": "date-time",
"examples": [
"2026-03-30T09:05:00Z"
]
},
"url": {
"type": "string",
"description": "URL to fetch the attachment.",
"examples": [
"https://example.com/stop-attachment/attachment-2025-06-03-1"
]
}
},
"description": "An attachment to a stop, such as a proof of delivery photo or signature."
},
"description": "Proof of delivery signatures for the stop. Signatures may be fetched using\n the URLs on the attachments."
},
"tasks": {
"type": "array",
"items": {
"title": "Task",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Task ID (e.g. `\"tsk-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"tsk-123e4567-e89b-12d3-a456-426614174000"
]
},
"title": {
"type": "string",
"description": "Task title (e.g. `\"Delivery checklist\"`).",
"examples": [
"Delivery checklist"
]
},
"type": {
"enum": [
"UNKNOWN",
"CHECKBOXES",
"RADIO_BUTTONS",
"TEXT_INPUT",
"DECIMAL_INPUT",
"SCANNER_INPUT"
],
"type": "string",
"description": "Task type.",
"format": "enum",
"examples": [
"TEXT_INPUT"
]
},
"items": {
"type": "array",
"items": {
"title": "TaskItem",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Item ID (e.g. `\"itm-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"itm-123e4567-e89b-12d3-a456-426614174000"
]
},
"title": {
"type": "string",
"description": "Item title (e.g. `\"Pick up package\"`).",
"examples": [
"Pick up package"
]
},
"complete": {
"type": "boolean",
"description": "Whether the item is completed.",
"examples": [
true
]
},
"updatedAt": {
"type": "string",
"description": "Timestamp when the item was last updated.",
"format": "date-time",
"examples": [
"2026-03-30T13:00:00Z"
]
}
},
"description": "An item within a task. For `CHECKBOXES`, each item on a task may be completed\n independently. For `RADIO_BUTTONS`, at most one item will be completed."
},
"description": "Task items (populated for `CHECKBOXES` and `RADIO_BUTTONS`).",
"examples": [
[]
]
},
"input": {
"allOf": [
{
"title": "TaskInput",
"type": "object",
"properties": {
"value": {
"type": "string",
"description": "Input value.",
"examples": [
"020123456789"
]
},
"updatedAt": {
"type": "string",
"description": "Timestamp when the input was last updated.",
"format": "date-time",
"examples": [
"2026-03-30T13:00:00Z"
]
},
"inputMethod": {
"enum": [
"UNKNOWN",
"SCANNED"
],
"type": "string",
"description": "Whether input was scanned (e.g. a scanned barcode)",
"format": "enum",
"examples": [
"SCANNED"
]
}
},
"description": "Captured driver input for a task. The value may be text for `TEXT_INPUT`\n tasks or a string decimal number for `DECIMAL_INPUT` tasks."
}
],
"description": "Task input (populated for `TEXT_INPUT` and `DECIMAL_INPUT`)."
},
"requiredToMarkStopAsDelivered": {
"type": "boolean",
"description": "Whether the task is required to mark the stop as completed. In the case of\n tasks on `RouteStart`, this represents tasks required for starting the\n route. In the case of tasks on `RouteEnd`, this represents tasks required\n for completing the route.",
"examples": [
true
]
},
"requiredToMarkStopAsAttempted": {
"type": "boolean",
"description": "Whether the task is required to mark the stop as attempted.",
"examples": [
true
]
}
},
"description": "A task to be completed at a stop, or at the start or end of a route. Tasks\n may have one or more items for `CHECKBOXES` or `RADIO_BUTTONS`, or may have\n an input for `TEXT_INPUT` or `DECIMAL_INPUT`."
},
"description": "Driver tasks for the stop, including completed items and any input from the\n driver."
},
"priority": {
"maximum": 10,
"type": "integer",
"description": "Priority of the stop for route planning. The valid range for stop priority\n is between `1` (low) and `10` (high), with default priority corresponding\n to a value of `5`. A priority value of `0` is considered unset and is\n treated the same as \"default\" priority. Stops with higher priority will be\n preferred when generating routes with constraints.",
"format": "int32",
"examples": [
8
]
},
"importedStopId": {
"type": "string",
"description": "The imported stop ID, populated when the stop source is `IMPORTED_STOP`.",
"examples": [
"ist-123e4567-e89b-12d3-a456-426614174000"
]
},
"orderName": {
"type": "string",
"description": "The name of the order associated with the stop. For Shopify orders, the\n name is generated by combining the `orderNumber` property with the order\n prefix and suffix that are set in the merchant's general settings. For\n EasyRoutes imported orders, this field is populated with the order name\n provided on import.",
"examples": [
"#1234"
]
},
"distanceMeters": {
"type": "number",
"description": "The distance in meters from the previous stop.",
"format": "double",
"examples": [
123.45
]
},
"updatedArrival": {
"type": "string",
"description": "Estimated arrival time at the stop. If the stop is completed, this will be\n the actual arrival time.",
"format": "date-time",
"examples": [
"2026-03-30T13:05:00Z"
]
},
"timeWindows": {
"type": "array",
"items": {
"title": "TimeWindow",
"type": "object",
"properties": {
"start": {
"allOf": [
{
"title": "TimeOfDay",
"type": "object",
"properties": {
"hours": {
"maximum": 23,
"type": "integer",
"description": "Hours of day in 24 hour format. Must be from 0 to 23.",
"format": "int32",
"examples": [
13
]
},
"minutes": {
"maximum": 59,
"type": "integer",
"description": "Minutes of hour of day. Must be from 0 to 59.",
"format": "int32",
"examples": [
37
]
},
"seconds": {
"maximum": 59,
"type": "integer",
"description": "Seconds of minutes of the time. Must be from 0 to 59.",
"format": "int32",
"examples": [
16
]
}
},
"description": "A time of day, independent of a particular date or timezone."
}
],
"description": "The start time of the time window (optional)."
},
"end": {
"allOf": [
{
"title": "TimeOfDay",
"type": "object",
"properties": {
"hours": {
"maximum": 23,
"type": "integer",
"description": "Hours of day in 24 hour format. Must be from 0 to 23.",
"format": "int32",
"examples": [
13
]
},
"minutes": {
"maximum": 59,
"type": "integer",
"description": "Minutes of hour of day. Must be from 0 to 59.",
"format": "int32",
"examples": [
37
]
},
"seconds": {
"maximum": 59,
"type": "integer",
"description": "Seconds of minutes of the time. Must be from 0 to 59.",
"format": "int32",
"examples": [
16
]
}
},
"description": "A time of day, independent of a particular date or timezone."
}
],
"description": "The end time of the time window (optional)."
}
},
"description": "A time window for a stop. The time window may be open-ended, but one or both\n of the start and end times should be provided. The end time must be >= the\n start time."
},
"description": "The time window for the stop. Note that we currently support at most one\n time window but may support multiple time windows in the future.",
"examples": [
[
{
"start": {
"hours": 9
},
"end": {
"hours": 17
}
}
]
]
},
"deliveryDate": {
"allOf": [
{
"title": "Date",
"required": [
"year",
"month",
"day"
],
"type": "object",
"properties": {
"year": {
"maximum": 9999,
"minimum": 1,
"type": "integer",
"description": "Year of the date. Must be from 1 to 9999.",
"format": "int32",
"examples": [
2019
]
},
"month": {
"maximum": 12,
"minimum": 1,
"type": "integer",
"description": "Month of a year. Must be from 1 to 12.",
"format": "int32",
"examples": [
11
]
},
"day": {
"maximum": 31,
"minimum": 1,
"type": "integer",
"description": "Day of a month. Must be from 1 to 31.",
"format": "int32",
"examples": [
15
]
}
},
"description": "A date in year-month-day format."
}
],
"description": "The planned delivery date for the stop.",
"examples": [
{
"year": 2025,
"month": 12,
"day": 16
}
]
},
"attributes": {
"type": "array",
"items": {
"title": "Attribute",
"type": "object",
"properties": {
"key": {
"type": "string",
"description": "Attribute key. Must be non-empty.",
"examples": [
"delivery_date"
]
},
"value": {
"type": "string",
"description": "Attribute value.",
"examples": [
"2025-12-16"
]
}
},
"description": "A key-value pair for storing additional information on a stop, such as order\n details, delivery instructions, or custom fields."
},
"description": "Additional attributes for the stop. Attributes are key-value pairs for\n storing additional structured data on stops. These may be populated from\n the Shopify order or set on import.",
"examples": [
[
{
"key": "color",
"value": "blue"
}
]
]
},
"clientStopId": {
"type": "string",
"description": "The client-provided ID associated with the stop, if provided on import.",
"examples": [
"test-order-1234"
]
},
"tags": {
"type": "array",
"items": {
"type": "string"
},
"description": "The tags for the stop. Tags are used to categorize stops and can be used\n for filtering and grouping stops in the EasyRoutes web app. These may be\n populated from the Shopify order or set on import.",
"examples": [
[
"foo",
"bar"
]
]
},
"attemptedReason": {
"enum": [
"UNKNOWN",
"NOT_AVAILABLE",
"ACCESS_DENIED",
"INCORRECT_ADDRESS",
"SAFE_PLACE_UNAVAILABLE",
"REFUSED",
"EXTERNAL",
"INCORRECT_ITEMS",
"OTHER",
"CANCELED"
],
"type": "string",
"description": "The reason for marking the stop as attempted. This is only populated when\n `deliveryStatus = ATTEMPTED_DELIVERY`.",
"format": "enum",
"examples": [
"NOT_AVAILABLE"
]
},
"attemptedNote": {
"type": "string",
"description": "Optional note related to the reason for marking the stop as attempted. This\n is optionally populated when `deliveryStatus = ATTEMPTED_DELIVERY`.",
"examples": [
"Customer did not answer the door."
]
},
"customerRating": {
"allOf": [
{
"title": "CustomerRating",
"type": "object",
"properties": {
"rating": {
"maximum": 5,
"minimum": 1,
"type": "integer",
"description": "Rating from 1-5",
"format": "int32",
"examples": [
5
]
},
"comment": {
"type": "string",
"description": "Customer comment related to rating",
"examples": [
"Excellent delivery"
]
},
"createdAt": {
"type": "string",
"description": "Timestamp when rating was left by customer.",
"format": "date-time",
"examples": [
"2026-03-30T18:00:00Z"
]
}
},
"description": "Customer rating and feedback left on a stop."
}
],
"description": "Rating left by customer. This can only be populated once `deliveryStatus =\n DELIVERED`."
},
"customSignatureDisclosure": {
"type": "string",
"description": "Optional custom signature disclosure that is shown to customers in the\n driver app.",
"examples": [
"I acknowledge that I have received this delivery."
]
},
"shopifyOrder": {
"allOf": [
{
"title": "ShopifyOrder",
"type": "object",
"properties": {
"orderNote": {
"type": "string",
"description": "The Shopify order note.",
"examples": [
"Customer has paid."
]
},
"customerNote": {
"type": "string",
"description": "The Shopify customer note for the order.",
"examples": [
"Leave at door."
]
}
},
"description": "Shopify-specific information for a RouteStop."
}
],
"description": "Information from the associated Shopify order, if applicable. Populated if\n stop source is `SHOPIFY_ORDER`"
},
"proofOfDeliveryBarcodes": {
"type": "array",
"items": {
"title": "ScannedBarcode",
"type": "object",
"properties": {
"value": {
"type": "string",
"description": "Barcode value (e.g. `\"123456789012\"`).",
"examples": [
"123456789012"
]
},
"createdAt": {
"type": "string",
"description": "Timestamp when the barcode was scanned.",
"format": "date-time",
"examples": [
"2026-03-30T13:10:00Z"
]
}
},
"description": "A proof of delivery barcode scanned at a stop."
},
"description": "Proof of delivery barcodes scanned at the stop."
},
"proofOfDeliveryBarcodeIssues": {
"type": "array",
"items": {
"title": "ScannedBarcodeIssue",
"type": "object",
"properties": {
"reason": {
"enum": [
"UNKNOWN",
"ITEM_MISSING",
"NOT_SCANNABLE",
"INCORRECT"
],
"type": "string",
"description": "The reported reason for the barcode issue.",
"format": "enum",
"examples": [
"ITEM_MISSING"
]
},
"note": {
"type": "string",
"description": "Optional note related to the reason for reporting a barcode issue.",
"examples": [
"Item was not packed."
]
},
"createdAt": {
"type": "string",
"description": "Timestamp when the issue was reported.",
"format": "date-time",
"examples": [
"2026-03-30T13:10:00Z"
]
}
},
"description": "A reported issue related to scanning barcodes at a stop."
},
"description": "Proof of delivery barcode issues reported at the stop."
},
"orderReferenceUrl": {
"type": "string",
"description": "A reference URL for the order associated with the stop (e.g. a link to the\n order in your order management system). Must be a valid HTTPS URL. This\n field can only be populated for imported stops.",
"examples": [
"https://orders.example.com/orders/148977776"
]
}
},
"description": "A stop on a route. A stop may correspond to a delivery or a driver break as\n determined by the type. A delivery stop will have location and contact\n information, items to deliver, optional order details, status, arrival time\n and stop duration, driver tasks and any proof of delivery information. A\n break stop will have start time and duration, and status."
},
"description": "Route stops. See RouteStop for stop fields."
},
"createdAt": {
"type": "string",
"description": "Timestamp when the route was created.",
"format": "date-time",
"examples": [
"2026-03-29T08:00:00Z"
]
},
"updatedAt": {
"type": "string",
"description": "Timestamp when the route was last updated (by the planner).",
"format": "date-time",
"examples": [
"2026-03-30T13:15:00Z"
]
},
"archivedAt": {
"type": "string",
"description": "Timestamp when the route was archived.",
"format": "date-time",
"examples": [
"2026-04-05T00:00:00Z"
]
},
"scheduledFor": {
"type": "string",
"description": "Timestamp when the route is scheduled for.",
"format": "date-time",
"examples": [
"2026-03-30T09:00:00Z"
]
},
"totalDistanceMeters": {
"type": "number",
"description": "The distance in meters for the entire route.",
"format": "double",
"examples": [
2387.2
]
},
"totalItemQuantity": {
"type": "integer",
"description": "The total quantity of items to deliver on the route.",
"format": "int32",
"examples": [
50
]
},
"totalItemGrams": {
"type": "string",
"description": "The total weight in grams for the items on the route.",
"examples": [
"6000"
]
},
"optimized": {
"type": "boolean",
"description": "Whether the route has been optimized. Adding or removing stops, reordering\n stops, or changing route options generally set this field to false until\n the route is reoptimized.",
"examples": [
true
]
},
"dispatchedUntil": {
"type": "string",
"description": "Timestamp until which the route is dispatched and accessible in the driver\n app.",
"format": "date-time",
"examples": [
"2026-03-30T20:00:00Z"
]
},
"note": {
"type": "string",
"description": "Top-level note for the route, as entered manually by route planners.",
"examples": [
"Fragile items."
]
},
"tags": {
"type": "array",
"items": {
"type": "string"
},
"description": "The tags for the route. Tags are used to categorize routes and can be\n used for filtering and grouping routes in the EasyRoutes web app.",
"examples": [
[
"foo",
"bar"
]
]
},
"defaultStopDuration": {
"pattern": "^-?(?:0|[1-9][0-9]{0,11})(?:\\.[0-9]{1,9})?s$",
"type": "string",
"description": "The default duration for stops on the route. Used to estimate arrival\n times for stops that do not have their own duration specified.\n Specified as a duration string in the format \"300s\" for 5 minutes, \"60s\"\n for 1 minute, etc.",
"examples": [
"300s"
]
},
"maxDuration": {
"pattern": "^-?(?:0|[1-9][0-9]{0,11})(?:\\.[0-9]{1,9})?s$",
"type": "string",
"description": "The maximum duration of the route. Specified as a duration string in the\n format \"3600s\" for 1 hour, \"7200s\" for 2 hours, etc.",
"examples": [
"28800s"
]
},
"maxStops": {
"type": "integer",
"description": "The maximum number of stops on the route.",
"format": "int32",
"examples": [
50
]
},
"maxItemCount": {
"type": "integer",
"description": "The maximum total item count across all stops on the route.",
"format": "int32",
"examples": [
200
]
},
"maxKilograms": {
"type": "number",
"description": "The maximum total weight in kilograms across all stops on the route.",
"format": "double",
"examples": [
500
]
},
"avoidTolls": {
"type": "boolean",
"description": "Whether to avoid toll roads during optimization.",
"examples": [
true
]
},
"avoidUTurns": {
"type": "boolean",
"description": "Whether to avoid U-turns during optimization.",
"examples": [
true
]
},
"speedFactor": {
"type": "number",
"description": "A speed factor for the route used during optimization to adjust estimated\n travel times. A value of 1.0 represents normal speed. Values less than 1.0\n indicate slower travel (e.g. 0.5 = half speed), and values greater than\n 1.0 indicate faster travel (e.g. 1.5 = 50% faster). Must be between 0.1\n and 1.9. A value of 0 (or unset) uses the default speed.",
"format": "double",
"examples": [
0.8
]
},
"vehicle": {
"allOf": [
{
"title": "Vehicle",
"required": [
"id"
],
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Vehicle ID.",
"examples": [
"veh-123e4567-e89b-12d3-a456-426614174000"
]
},
"name": {
"type": "string",
"description": "Vehicle name.",
"examples": [
"Delivery Van 1"
]
},
"make": {
"type": "string",
"description": "Vehicle make.",
"examples": [
"Ford"
]
},
"model": {
"type": "string",
"description": "Vehicle model.",
"examples": [
"Transit"
]
},
"year": {
"type": "integer",
"description": "Vehicle model year.",
"format": "int32",
"examples": [
2023
]
},
"type": {
"enum": [
"UNKNOWN",
"CAR",
"CARGO_VAN",
"PICKUP_TRUCK",
"BOX_TRUCK",
"MOTORCYCLE",
"BICYCLE",
"DRONE",
"OTHER"
],
"type": "string",
"description": "Vehicle type.",
"format": "enum",
"examples": [
"CARGO_VAN"
]
},
"vin": {
"type": "string",
"description": "Vehicle Identification Number.",
"examples": [
"1FTBW2CM5NKA12345"
]
},
"license": {
"type": "string",
"description": "Vehicle license plate.",
"examples": [
"ABC-1234"
]
},
"isArchived": {
"type": "boolean",
"description": "Whether the vehicle is archived.",
"examples": [
false
]
},
"createdTimestamp": {
"type": "string",
"description": "Timestamp when the vehicle was created.",
"format": "date-time",
"examples": [
"2026-07-30T12:00:00Z"
]
}
},
"description": "A vehicle that can be assigned to a route."
}
],
"description": "Assigned vehicle for the route."
}
},
"description": "A route of stops, optionally with an assigned driver."
}
}
}
},
"default": {
"description": "Default error response",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"code": {
"type": "integer",
"description": "The status code, which should be an enum value of [google.rpc.Code][google.rpc.Code].",
"format": "int32"
},
"message": {
"type": "string",
"description": "A developer-facing error message, which should be in English. Any user-facing error message should be localized and sent in the [google.rpc.Status.details][google.rpc.Status.details] field, or localized by the client."
},
"details": {
"type": "array",
"items": {
"type": "object",
"properties": {
"@type": {
"type": "string",
"description": "The type of the serialized message."
}
},
"additionalProperties": true,
"description": "Contains an arbitrary serialized message along with a @type that describes the type of the serialized message."
},
"description": "A list of messages that carry the error details. There is a common set of message types for APIs to use."
}
},
"description": "The `Status` type defines a logical error model that is suitable for different programming environments, including REST APIs and RPC APIs. It is used by [gRPC](https://github.com/grpc). Each `Status` message contains three pieces of data: error code, error message, and error details. You can find out more about this error model and how to work with it in the [API Design Guide](https://cloud.google.com/apis/design/errors)."
}
}
}
}
},
"security": [
{
"bearerAuth": []
}
],
"components": {
"securitySchemes": {
"bearerAuth": {
"type": "http",
"description": "Access token from `/authenticate`",
"scheme": "bearer",
"bearerFormat": "JWT"
}
}
}
}
```
# Update route start tasks (https://docs.roundtrip.ai/docs/api-reference/routes/put-routes-routeId-start-tasks)
PUT /routes/{routeId}/start/tasks
Updates the tasks required before starting a route by route ID. This is a
full replacement: the entire list of tasks on the route start is replaced
with the task templates provided in the request body, so existing tasks
not included in the request will be removed. Task and item IDs are always
regenerated by the server, and any existing completion state, input, or
timestamps are cleared, since only the driver (via the driver app) can
mark a task or item complete or provide input. The route must not be
archived. The response returns the full updated route.
## OpenAPI specification
```json
{
"servers": [
{
"url": "https://easyroutes.roundtrip.ai/api/2024-07"
}
],
"tags": [
"Routes"
],
"summary": "Update route start tasks",
"description": "Updates the tasks required before starting a route by route ID. This is a\n full replacement: the entire list of tasks on the route start is replaced\n with the task templates provided in the request body, so existing tasks\n not included in the request will be removed. Task and item IDs are always\n regenerated by the server, and any existing completion state, input, or\n timestamps are cleared, since only the driver (via the driver app) can\n mark a task or item complete or provide input. The route must not be\n archived. The response returns the full updated route.",
"operationId": "UpdateRouteStartTasks",
"parameters": [
{
"name": "routeId",
"in": "path",
"description": "The ID of the route to update start tasks.",
"required": true,
"schema": {
"type": "string",
"examples": [
"rte-123e4567-e89b-12d3-a456-426614174000"
]
}
},
{
"name": "Idempotency-Key",
"in": "header",
"description": "A unique key for safely retrying this operation. For more information read [our guide](https://docs.roundtrip.ai/docs/concepts/idempotency.md).",
"schema": {
"maxLength": 255,
"minLength": 1,
"type": "string"
},
"examples": {
"default": {
"value": "550e8400-e29b-41d4-a716-446655440000"
}
}
}
],
"requestBody": {
"content": {
"application/json": {
"schema": {
"type": "array",
"items": {
"title": "TaskTemplate",
"type": "object",
"properties": {
"title": {
"type": "string",
"description": "Task title (e.g. `\"Delivery checklist\"`).",
"examples": [
"Delivery checklist"
]
},
"type": {
"enum": [
"UNKNOWN",
"CHECKBOXES",
"RADIO_BUTTONS",
"TEXT_INPUT",
"DECIMAL_INPUT",
"SCANNER_INPUT"
],
"type": "string",
"description": "Task type.",
"format": "enum",
"examples": [
"CHECKBOXES"
]
},
"items": {
"type": "array",
"items": {
"title": "TaskItemTemplate",
"type": "object",
"properties": {
"title": {
"type": "string",
"description": "Item title (e.g. `\"Pick up package\"`).",
"examples": [
"Pick up package"
]
}
},
"description": "An item template for a task. For `CHECKBOXES`, each item on a task may be\n completed independently. For `RADIO_BUTTONS`, at most one item will be\n completed."
},
"description": "Task items, which are required for `CHECKBOXES` and `RADIO_BUTTONS`."
},
"requiredToMarkStopAsDelivered": {
"type": "boolean",
"description": "Whether the task is required to mark the stop as completed.",
"examples": [
true
]
},
"requiredToMarkStopAsAttempted": {
"type": "boolean",
"description": "Whether the task is required to mark the stop as attempted.",
"examples": [
true
]
}
},
"description": "A template for creating tasks at a stop. Task templates may have one or more\n items for `CHECKBOXES` or `RADIO_BUTTONS`. Imported stops may have task\n templates that are used to create tasks when the stop is added to a route."
}
}
}
},
"required": true
},
"responses": {
"200": {
"description": "OK",
"headers": {
"Idempotency-Key": {
"description": "The idempotency key associated with the response.",
"schema": {
"type": "string"
}
},
"Idempotency-Replayed": {
"description": "Whether the response was replayed from a previous request.",
"schema": {
"type": "boolean"
}
}
},
"content": {
"application/json": {
"schema": {
"title": "Route",
"required": [
"id",
"name",
"stops",
"createdAt",
"updatedAt",
"totalDistanceMeters",
"totalItemQuantity",
"totalItemGrams",
"optimized"
],
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Route ID (e.g. `\"rte-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"rte-123e4567-e89b-12d3-a456-426614174000"
]
},
"name": {
"type": "string",
"description": "Route name (e.g. `\"Morning route\"`).",
"examples": [
"Morning route"
]
},
"driver": {
"allOf": [
{
"title": "Driver",
"required": [
"id"
],
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Driver ID (e.g. `\"drv-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"drv-123e4567-e89b-12d3-a456-426614174000"
]
},
"firstName": {
"type": "string",
"description": "Driver first name (e.g. `\"John\"`).",
"examples": [
"John"
]
},
"lastName": {
"type": "string",
"description": "Driver last name (e.g. `\"Doe\"`).",
"examples": [
"Doe"
]
},
"phone": {
"type": "string",
"description": "Driver phone number in [E.164 format](https://en.wikipedia.org/wiki/E.164)\n (e.g. `\"+14265551000\"`).",
"examples": [
"+14265551000"
]
},
"status": {
"enum": [
"UNKNOWN",
"ACTIVE",
"INACTIVE",
"ARCHIVED"
],
"type": "string",
"description": "Shop driver status. (e.g. `ACTIVE`).",
"format": "enum",
"examples": [
"ACTIVE"
]
}
},
"description": "A driver who is assigned to a route."
}
],
"description": "Assigned driver for the route."
},
"start": {
"allOf": [
{
"title": "RouteStart",
"type": "object",
"properties": {
"address": {
"allOf": [
{
"title": "Address",
"type": "object",
"properties": {
"address1": {
"type": "string",
"description": "Street address line 1 (e.g. `\"123 Main St\"`).",
"examples": [
"123 Main St"
]
},
"address2": {
"type": "string",
"description": "Street address line 2 (e.g. `\"Apt 101\"`).",
"examples": [
"Apt 3B"
]
},
"city": {
"type": "string",
"description": "City name (e.g. `\"New York\"`).",
"examples": [
"New York"
]
},
"provinceCode": {
"type": "string",
"description": "Province or state as subdivision codes in\n [ISO 3166-2](https://en.wikipedia.org/wiki/ISO_3166-2) format without the\n country prefix (e.g. `\"NY\"` for New York).",
"examples": [
"NY"
]
},
"countryCode": {
"type": "string",
"description": "Country code (e.g. `\"US\"`).",
"examples": [
"US"
]
},
"zip": {
"type": "string",
"description": "Postal or ZIP code (e.g. `\"10001\"`).",
"examples": [
"10001"
]
}
},
"description": "A physical street address."
}
],
"description": "The start address of the route.",
"examples": [
{
"address1": "123 Main St",
"address2": "Apt 3B",
"city": "New York",
"provinceCode": "NY",
"countryCode": "US",
"zip": "10001"
}
]
},
"tasks": {
"type": "array",
"items": {
"title": "Task",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Task ID (e.g. `\"tsk-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"tsk-123e4567-e89b-12d3-a456-426614174000"
]
},
"title": {
"type": "string",
"description": "Task title (e.g. `\"Delivery checklist\"`).",
"examples": [
"Delivery checklist"
]
},
"type": {
"enum": [
"UNKNOWN",
"CHECKBOXES",
"RADIO_BUTTONS",
"TEXT_INPUT",
"DECIMAL_INPUT",
"SCANNER_INPUT"
],
"type": "string",
"description": "Task type.",
"format": "enum",
"examples": [
"TEXT_INPUT"
]
},
"items": {
"type": "array",
"items": {
"title": "TaskItem",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Item ID (e.g. `\"itm-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"itm-123e4567-e89b-12d3-a456-426614174000"
]
},
"title": {
"type": "string",
"description": "Item title (e.g. `\"Pick up package\"`).",
"examples": [
"Pick up package"
]
},
"complete": {
"type": "boolean",
"description": "Whether the item is completed.",
"examples": [
true
]
},
"updatedAt": {
"type": "string",
"description": "Timestamp when the item was last updated.",
"format": "date-time",
"examples": [
"2026-03-30T13:00:00Z"
]
}
},
"description": "An item within a task. For `CHECKBOXES`, each item on a task may be completed\n independently. For `RADIO_BUTTONS`, at most one item will be completed."
},
"description": "Task items (populated for `CHECKBOXES` and `RADIO_BUTTONS`).",
"examples": [
[]
]
},
"input": {
"allOf": [
{
"title": "TaskInput",
"type": "object",
"properties": {
"value": {
"type": "string",
"description": "Input value.",
"examples": [
"020123456789"
]
},
"updatedAt": {
"type": "string",
"description": "Timestamp when the input was last updated.",
"format": "date-time",
"examples": [
"2026-03-30T13:00:00Z"
]
},
"inputMethod": {
"enum": [
"UNKNOWN",
"SCANNED"
],
"type": "string",
"description": "Whether input was scanned (e.g. a scanned barcode)",
"format": "enum",
"examples": [
"SCANNED"
]
}
},
"description": "Captured driver input for a task. The value may be text for `TEXT_INPUT`\n tasks or a string decimal number for `DECIMAL_INPUT` tasks."
}
],
"description": "Task input (populated for `TEXT_INPUT` and `DECIMAL_INPUT`)."
},
"requiredToMarkStopAsDelivered": {
"type": "boolean",
"description": "Whether the task is required to mark the stop as completed. In the case of\n tasks on `RouteStart`, this represents tasks required for starting the\n route. In the case of tasks on `RouteEnd`, this represents tasks required\n for completing the route.",
"examples": [
true
]
},
"requiredToMarkStopAsAttempted": {
"type": "boolean",
"description": "Whether the task is required to mark the stop as attempted.",
"examples": [
true
]
}
},
"description": "A task to be completed at a stop, or at the start or end of a route. Tasks\n may have one or more items for `CHECKBOXES` or `RADIO_BUTTONS`, or may have\n an input for `TEXT_INPUT` or `DECIMAL_INPUT`."
},
"description": "Tasks to complete before starting the route."
},
"status": {
"enum": [
"UNKNOWN",
"STARTED"
],
"type": "string",
"description": "Status indicating whether the route has been started.",
"format": "enum",
"examples": [
"STARTED"
]
},
"updatedStart": {
"type": "string",
"description": "Updated start time for the route. If the route is started, this will be the\n actual start time.",
"format": "date-time",
"examples": [
"2026-03-30T09:05:00Z"
]
},
"scheduledStart": {
"type": "string",
"description": "Scheduled start time for the route (same as `scheduledFor` on the route).",
"format": "date-time",
"examples": [
"2026-03-30T09:00:00Z"
]
},
"photos": {
"type": "array",
"items": {
"title": "StopAttachment",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Attachment ID (e.g. `\"att-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"att-123e4567-e89b-12d3-a456-426614174000"
]
},
"createdAt": {
"type": "string",
"description": "Timestamp when the attachment was created.",
"format": "date-time",
"examples": [
"2026-03-30T09:05:00Z"
]
},
"url": {
"type": "string",
"description": "URL to fetch the attachment.",
"examples": [
"https://example.com/stop-attachment/attachment-2025-06-03-1"
]
}
},
"description": "An attachment to a stop, such as a proof of delivery photo or signature."
},
"description": "Photos for the route start. Photos may be fetched using the URLs on the\n attachments."
}
},
"description": "The start location of a route and any driver tasks to complete before\n beginning the route."
}
],
"description": "Route start address and tasks."
},
"end": {
"allOf": [
{
"title": "RouteEnd",
"type": "object",
"properties": {
"address": {
"allOf": [
{
"title": "Address",
"type": "object",
"properties": {
"address1": {
"type": "string",
"description": "Street address line 1 (e.g. `\"123 Main St\"`).",
"examples": [
"123 Main St"
]
},
"address2": {
"type": "string",
"description": "Street address line 2 (e.g. `\"Apt 101\"`).",
"examples": [
"Apt 3B"
]
},
"city": {
"type": "string",
"description": "City name (e.g. `\"New York\"`).",
"examples": [
"New York"
]
},
"provinceCode": {
"type": "string",
"description": "Province or state as subdivision codes in\n [ISO 3166-2](https://en.wikipedia.org/wiki/ISO_3166-2) format without the\n country prefix (e.g. `\"NY\"` for New York).",
"examples": [
"NY"
]
},
"countryCode": {
"type": "string",
"description": "Country code (e.g. `\"US\"`).",
"examples": [
"US"
]
},
"zip": {
"type": "string",
"description": "Postal or ZIP code (e.g. `\"10001\"`).",
"examples": [
"10001"
]
}
},
"description": "A physical street address."
}
],
"description": "The end address of the route.",
"examples": [
{
"address1": "123 Main St",
"address2": "Apt 3B",
"city": "New York",
"provinceCode": "NY",
"countryCode": "US",
"zip": "10001"
}
]
},
"tasks": {
"type": "array",
"items": {
"title": "Task",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Task ID (e.g. `\"tsk-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"tsk-123e4567-e89b-12d3-a456-426614174000"
]
},
"title": {
"type": "string",
"description": "Task title (e.g. `\"Delivery checklist\"`).",
"examples": [
"Delivery checklist"
]
},
"type": {
"enum": [
"UNKNOWN",
"CHECKBOXES",
"RADIO_BUTTONS",
"TEXT_INPUT",
"DECIMAL_INPUT",
"SCANNER_INPUT"
],
"type": "string",
"description": "Task type.",
"format": "enum",
"examples": [
"TEXT_INPUT"
]
},
"items": {
"type": "array",
"items": {
"title": "TaskItem",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Item ID (e.g. `\"itm-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"itm-123e4567-e89b-12d3-a456-426614174000"
]
},
"title": {
"type": "string",
"description": "Item title (e.g. `\"Pick up package\"`).",
"examples": [
"Pick up package"
]
},
"complete": {
"type": "boolean",
"description": "Whether the item is completed.",
"examples": [
true
]
},
"updatedAt": {
"type": "string",
"description": "Timestamp when the item was last updated.",
"format": "date-time",
"examples": [
"2026-03-30T13:00:00Z"
]
}
},
"description": "An item within a task. For `CHECKBOXES`, each item on a task may be completed\n independently. For `RADIO_BUTTONS`, at most one item will be completed."
},
"description": "Task items (populated for `CHECKBOXES` and `RADIO_BUTTONS`).",
"examples": [
[]
]
},
"input": {
"allOf": [
{
"title": "TaskInput",
"type": "object",
"properties": {
"value": {
"type": "string",
"description": "Input value.",
"examples": [
"020123456789"
]
},
"updatedAt": {
"type": "string",
"description": "Timestamp when the input was last updated.",
"format": "date-time",
"examples": [
"2026-03-30T13:00:00Z"
]
},
"inputMethod": {
"enum": [
"UNKNOWN",
"SCANNED"
],
"type": "string",
"description": "Whether input was scanned (e.g. a scanned barcode)",
"format": "enum",
"examples": [
"SCANNED"
]
}
},
"description": "Captured driver input for a task. The value may be text for `TEXT_INPUT`\n tasks or a string decimal number for `DECIMAL_INPUT` tasks."
}
],
"description": "Task input (populated for `TEXT_INPUT` and `DECIMAL_INPUT`)."
},
"requiredToMarkStopAsDelivered": {
"type": "boolean",
"description": "Whether the task is required to mark the stop as completed. In the case of\n tasks on `RouteStart`, this represents tasks required for starting the\n route. In the case of tasks on `RouteEnd`, this represents tasks required\n for completing the route.",
"examples": [
true
]
},
"requiredToMarkStopAsAttempted": {
"type": "boolean",
"description": "Whether the task is required to mark the stop as attempted.",
"examples": [
true
]
}
},
"description": "A task to be completed at a stop, or at the start or end of a route. Tasks\n may have one or more items for `CHECKBOXES` or `RADIO_BUTTONS`, or may have\n an input for `TEXT_INPUT` or `DECIMAL_INPUT`."
},
"description": "Tasks to complete before finishing the route."
},
"plannedArrival": {
"type": "string",
"description": "Planned arrival time at the end of the route.",
"format": "date-time",
"examples": [
"2026-03-30T17:00:00Z"
]
},
"distanceMeters": {
"type": "number",
"description": "The distance in meters from the previous stop.",
"format": "double",
"examples": [
1234.56
]
},
"updatedArrival": {
"type": "string",
"description": "Estimated arrival time at the end of the route. If the route is completed,\n this will be the actual arrival time.",
"format": "date-time",
"examples": [
"2026-03-30T17:05:00Z"
]
},
"status": {
"enum": [
"UNKNOWN",
"COMPLETED"
],
"type": "string",
"description": "Status indicating whether the route has been completed.",
"format": "enum",
"examples": [
"COMPLETED"
]
},
"photos": {
"type": "array",
"items": {
"title": "StopAttachment",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Attachment ID (e.g. `\"att-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"att-123e4567-e89b-12d3-a456-426614174000"
]
},
"createdAt": {
"type": "string",
"description": "Timestamp when the attachment was created.",
"format": "date-time",
"examples": [
"2026-03-30T09:05:00Z"
]
},
"url": {
"type": "string",
"description": "URL to fetch the attachment.",
"examples": [
"https://example.com/stop-attachment/attachment-2025-06-03-1"
]
}
},
"description": "An attachment to a stop, such as a proof of delivery photo or signature."
},
"description": "Photos for the route end. Photos may be fetched using the URLs on the\n attachments."
}
},
"description": "The end location of a route and any driver tasks to complete after completing\n the route."
}
],
"description": "Route end address and tasks."
},
"stops": {
"type": "array",
"items": {
"title": "RouteStop",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Stop ID (e.g. `\"rst-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"rst-123e4567-e89b-12d3-a456-426614174000"
]
},
"type": {
"enum": [
"UNKNOWN",
"DELIVERY",
"BREAK",
"PICKUP",
"TASK"
],
"type": "string",
"description": "The type of stop (DELIVERY, BREAK, PICKUP, or TASK).",
"format": "enum",
"examples": [
"DELIVERY"
]
},
"deliveryStatus": {
"enum": [
"UNKNOWN",
"DELIVERED",
"OUT_FOR_DELIVERY",
"ATTEMPTED_DELIVERY",
"READY_FOR_DELIVERY"
],
"type": "string",
"description": "The status for DELIVERY, PICKUP, or TASK stops.",
"format": "enum",
"examples": [
"ATTEMPTED_DELIVERY"
]
},
"breakStatus": {
"enum": [
"UNKNOWN",
"COMPLETED"
],
"type": "string",
"description": "The status for BREAK stops.",
"format": "enum",
"examples": [
"COMPLETED"
]
},
"updatedAt": {
"type": "string",
"description": "Timestamp when the stop status was last updated. Note that this timestamp\n corresponds only to major status updates (i.e. stop marked as DELIVERED).\n Minor updates like task completion or adding proof of delivery will not\n advance this timestamp. For those events, use the timestamps on the task or\n proof of delivery attachment.",
"format": "date-time",
"examples": [
"2026-03-30T13:15:00Z"
]
},
"duration": {
"pattern": "^-?(?:0|[1-9][0-9]{0,11})(?:\\.[0-9]{1,9})?s$",
"type": "string",
"description": "Planned duration of the stop in seconds.",
"examples": [
"300s"
]
},
"plannedArrival": {
"type": "string",
"description": "Planned arrival time at the stop.",
"format": "date-time",
"examples": [
"2026-03-30T13:00:00Z"
]
},
"note": {
"type": "string",
"description": "Top-level note for the stop, as entered manually by route planners,\n inherited from a saved or imported stop, or set by order import automation\n rules.",
"examples": [
"Leave at door."
]
},
"address": {
"allOf": [
{
"title": "Address",
"type": "object",
"properties": {
"address1": {
"type": "string",
"description": "Street address line 1 (e.g. `\"123 Main St\"`).",
"examples": [
"123 Main St"
]
},
"address2": {
"type": "string",
"description": "Street address line 2 (e.g. `\"Apt 101\"`).",
"examples": [
"Apt 3B"
]
},
"city": {
"type": "string",
"description": "City name (e.g. `\"New York\"`).",
"examples": [
"New York"
]
},
"provinceCode": {
"type": "string",
"description": "Province or state as subdivision codes in\n [ISO 3166-2](https://en.wikipedia.org/wiki/ISO_3166-2) format without the\n country prefix (e.g. `\"NY\"` for New York).",
"examples": [
"NY"
]
},
"countryCode": {
"type": "string",
"description": "Country code (e.g. `\"US\"`).",
"examples": [
"US"
]
},
"zip": {
"type": "string",
"description": "Postal or ZIP code (e.g. `\"10001\"`).",
"examples": [
"10001"
]
}
},
"description": "A physical street address."
}
],
"description": "Delivery address for the stop.",
"examples": [
{
"address1": "123 Main St",
"address2": "Apt 3B",
"city": "New York",
"provinceCode": "NY",
"countryCode": "US",
"zip": "10001"
}
]
},
"contact": {
"allOf": [
{
"title": "Contact",
"type": "object",
"properties": {
"firstName": {
"type": "string",
"description": "First name (e.g. `\"John\"`).",
"examples": [
"John"
]
},
"lastName": {
"type": "string",
"description": "Last name (e.g. `\"Doe\"`).",
"examples": [
"Doe"
]
},
"company": {
"type": "string",
"description": "Company name (e.g. `\"Roundtrip Systems Inc\"`).",
"examples": [
"Roundtrip Systems Inc"
]
},
"phone": {
"type": "string",
"description": "Phone number in [E.164 format](https://en.wikipedia.org/wiki/E.164) (e.g.\n `\"+14265551000\"`).",
"examples": [
"+14265551000"
]
},
"email": {
"type": "string",
"description": "Email address (e.g. `\"john.doe@roundtrip.ai\"`)",
"examples": [
"john.doe@roundtrip.ai"
]
}
},
"description": "Contact information for a person or company."
}
],
"description": "Contact information for the stop delivery recipient.",
"examples": [
{
"firstName": "John",
"lastName": "Doe",
"company": "Roundtrip Systems Inc",
"phone": "+14265551000",
"email": "john.doe@roundtrip.ai"
}
]
},
"plannedCoordinates": {
"allOf": [
{
"type": "object",
"properties": {
"latitude": {
"type": "number",
"description": "The latitude in degrees. It must be in the range [-90.0, +90.0].",
"format": "double"
},
"longitude": {
"type": "number",
"description": "The longitude in degrees. It must be in the range [-180.0, +180.0].",
"format": "double"
}
},
"description": "An object that represents a latitude/longitude pair. This is expressed as a\n pair of doubles to represent degrees latitude and degrees longitude. Unless\n specified otherwise, this must conform to the\n WGS84\n standard. Values must be within normalized ranges."
}
],
"description": "Planned coordinates for the stop.",
"examples": [
{
"latitude": 40.7128,
"longitude": -74.006
}
]
},
"items": {
"type": "array",
"items": {
"title": "StopItem",
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "Item name (e.g. `\"Bananas\"`).",
"examples": [
"Bananas"
]
},
"quantity": {
"type": "integer",
"description": "Quantity of the item (e.g. `5`).",
"format": "int32",
"examples": [
5
]
},
"grams": {
"type": "integer",
"description": "Weight of the item in grams (e.g. `500`).",
"format": "int32",
"examples": [
500
]
},
"sku": {
"type": "string",
"description": "Stock keeping unit (e.g. `\"BANANA-001\"`).",
"examples": [
"BANANA-001"
]
}
},
"description": "An item to be delivered at a stop."
},
"description": "Items to deliver at the stop."
},
"source": {
"enum": [
"UNKNOWN",
"SHOPIFY_ORDER",
"SAVED_STOP",
"IMPORTED_STOP"
],
"type": "string",
"description": "The source of the stop, which may be populated for `DELIVERY` stops. The\n source can be a `SHOPIFY_ORDER`, an EasyRoutes `SAVED_STOP`, or an\n `IMPORTED_STOP` from an external source (such as CSV file).",
"format": "enum",
"examples": [
"IMPORTED_STOP"
]
},
"shopifyOrderId": {
"type": "string",
"description": "The Shopify order ID, populated when the stop source is a `SHOPIFY_ORDER`.",
"examples": [
"6229749334323"
]
},
"savedStopId": {
"type": "string",
"description": "The saved stop ID, populated when the stop source is a `SAVED_STOP`.",
"examples": [
"sst-123e4567-e89b-12d3-a456-426614174000"
]
},
"deliveredCoordinates": {
"allOf": [
{
"type": "object",
"properties": {
"latitude": {
"type": "number",
"description": "The latitude in degrees. It must be in the range [-90.0, +90.0].",
"format": "double"
},
"longitude": {
"type": "number",
"description": "The longitude in degrees. It must be in the range [-180.0, +180.0].",
"format": "double"
}
},
"description": "An object that represents a latitude/longitude pair. This is expressed as a\n pair of doubles to represent degrees latitude and degrees longitude. Unless\n specified otherwise, this must conform to the\n WGS84\n standard. Values must be within normalized ranges."
}
],
"description": "Delivered coordinates for the stop."
},
"proofOfDeliveryNote": {
"type": "string",
"description": "Proof of delivery note for the stop.",
"examples": [
"Left at door."
]
},
"proofOfDeliveryPhotos": {
"type": "array",
"items": {
"title": "StopAttachment",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Attachment ID (e.g. `\"att-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"att-123e4567-e89b-12d3-a456-426614174000"
]
},
"createdAt": {
"type": "string",
"description": "Timestamp when the attachment was created.",
"format": "date-time",
"examples": [
"2026-03-30T09:05:00Z"
]
},
"url": {
"type": "string",
"description": "URL to fetch the attachment.",
"examples": [
"https://example.com/stop-attachment/attachment-2025-06-03-1"
]
}
},
"description": "An attachment to a stop, such as a proof of delivery photo or signature."
},
"description": "Proof of delivery photos for the stop. Photos may be fetched using the URLs\n on the attachments."
},
"proofOfDeliverySignatures": {
"type": "array",
"items": {
"title": "StopAttachment",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Attachment ID (e.g. `\"att-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"att-123e4567-e89b-12d3-a456-426614174000"
]
},
"createdAt": {
"type": "string",
"description": "Timestamp when the attachment was created.",
"format": "date-time",
"examples": [
"2026-03-30T09:05:00Z"
]
},
"url": {
"type": "string",
"description": "URL to fetch the attachment.",
"examples": [
"https://example.com/stop-attachment/attachment-2025-06-03-1"
]
}
},
"description": "An attachment to a stop, such as a proof of delivery photo or signature."
},
"description": "Proof of delivery signatures for the stop. Signatures may be fetched using\n the URLs on the attachments."
},
"tasks": {
"type": "array",
"items": {
"title": "Task",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Task ID (e.g. `\"tsk-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"tsk-123e4567-e89b-12d3-a456-426614174000"
]
},
"title": {
"type": "string",
"description": "Task title (e.g. `\"Delivery checklist\"`).",
"examples": [
"Delivery checklist"
]
},
"type": {
"enum": [
"UNKNOWN",
"CHECKBOXES",
"RADIO_BUTTONS",
"TEXT_INPUT",
"DECIMAL_INPUT",
"SCANNER_INPUT"
],
"type": "string",
"description": "Task type.",
"format": "enum",
"examples": [
"TEXT_INPUT"
]
},
"items": {
"type": "array",
"items": {
"title": "TaskItem",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Item ID (e.g. `\"itm-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"itm-123e4567-e89b-12d3-a456-426614174000"
]
},
"title": {
"type": "string",
"description": "Item title (e.g. `\"Pick up package\"`).",
"examples": [
"Pick up package"
]
},
"complete": {
"type": "boolean",
"description": "Whether the item is completed.",
"examples": [
true
]
},
"updatedAt": {
"type": "string",
"description": "Timestamp when the item was last updated.",
"format": "date-time",
"examples": [
"2026-03-30T13:00:00Z"
]
}
},
"description": "An item within a task. For `CHECKBOXES`, each item on a task may be completed\n independently. For `RADIO_BUTTONS`, at most one item will be completed."
},
"description": "Task items (populated for `CHECKBOXES` and `RADIO_BUTTONS`).",
"examples": [
[]
]
},
"input": {
"allOf": [
{
"title": "TaskInput",
"type": "object",
"properties": {
"value": {
"type": "string",
"description": "Input value.",
"examples": [
"020123456789"
]
},
"updatedAt": {
"type": "string",
"description": "Timestamp when the input was last updated.",
"format": "date-time",
"examples": [
"2026-03-30T13:00:00Z"
]
},
"inputMethod": {
"enum": [
"UNKNOWN",
"SCANNED"
],
"type": "string",
"description": "Whether input was scanned (e.g. a scanned barcode)",
"format": "enum",
"examples": [
"SCANNED"
]
}
},
"description": "Captured driver input for a task. The value may be text for `TEXT_INPUT`\n tasks or a string decimal number for `DECIMAL_INPUT` tasks."
}
],
"description": "Task input (populated for `TEXT_INPUT` and `DECIMAL_INPUT`)."
},
"requiredToMarkStopAsDelivered": {
"type": "boolean",
"description": "Whether the task is required to mark the stop as completed. In the case of\n tasks on `RouteStart`, this represents tasks required for starting the\n route. In the case of tasks on `RouteEnd`, this represents tasks required\n for completing the route.",
"examples": [
true
]
},
"requiredToMarkStopAsAttempted": {
"type": "boolean",
"description": "Whether the task is required to mark the stop as attempted.",
"examples": [
true
]
}
},
"description": "A task to be completed at a stop, or at the start or end of a route. Tasks\n may have one or more items for `CHECKBOXES` or `RADIO_BUTTONS`, or may have\n an input for `TEXT_INPUT` or `DECIMAL_INPUT`."
},
"description": "Driver tasks for the stop, including completed items and any input from the\n driver."
},
"priority": {
"maximum": 10,
"type": "integer",
"description": "Priority of the stop for route planning. The valid range for stop priority\n is between `1` (low) and `10` (high), with default priority corresponding\n to a value of `5`. A priority value of `0` is considered unset and is\n treated the same as \"default\" priority. Stops with higher priority will be\n preferred when generating routes with constraints.",
"format": "int32",
"examples": [
8
]
},
"importedStopId": {
"type": "string",
"description": "The imported stop ID, populated when the stop source is `IMPORTED_STOP`.",
"examples": [
"ist-123e4567-e89b-12d3-a456-426614174000"
]
},
"orderName": {
"type": "string",
"description": "The name of the order associated with the stop. For Shopify orders, the\n name is generated by combining the `orderNumber` property with the order\n prefix and suffix that are set in the merchant's general settings. For\n EasyRoutes imported orders, this field is populated with the order name\n provided on import.",
"examples": [
"#1234"
]
},
"distanceMeters": {
"type": "number",
"description": "The distance in meters from the previous stop.",
"format": "double",
"examples": [
123.45
]
},
"updatedArrival": {
"type": "string",
"description": "Estimated arrival time at the stop. If the stop is completed, this will be\n the actual arrival time.",
"format": "date-time",
"examples": [
"2026-03-30T13:05:00Z"
]
},
"timeWindows": {
"type": "array",
"items": {
"title": "TimeWindow",
"type": "object",
"properties": {
"start": {
"allOf": [
{
"title": "TimeOfDay",
"type": "object",
"properties": {
"hours": {
"maximum": 23,
"type": "integer",
"description": "Hours of day in 24 hour format. Must be from 0 to 23.",
"format": "int32",
"examples": [
13
]
},
"minutes": {
"maximum": 59,
"type": "integer",
"description": "Minutes of hour of day. Must be from 0 to 59.",
"format": "int32",
"examples": [
37
]
},
"seconds": {
"maximum": 59,
"type": "integer",
"description": "Seconds of minutes of the time. Must be from 0 to 59.",
"format": "int32",
"examples": [
16
]
}
},
"description": "A time of day, independent of a particular date or timezone."
}
],
"description": "The start time of the time window (optional)."
},
"end": {
"allOf": [
{
"title": "TimeOfDay",
"type": "object",
"properties": {
"hours": {
"maximum": 23,
"type": "integer",
"description": "Hours of day in 24 hour format. Must be from 0 to 23.",
"format": "int32",
"examples": [
13
]
},
"minutes": {
"maximum": 59,
"type": "integer",
"description": "Minutes of hour of day. Must be from 0 to 59.",
"format": "int32",
"examples": [
37
]
},
"seconds": {
"maximum": 59,
"type": "integer",
"description": "Seconds of minutes of the time. Must be from 0 to 59.",
"format": "int32",
"examples": [
16
]
}
},
"description": "A time of day, independent of a particular date or timezone."
}
],
"description": "The end time of the time window (optional)."
}
},
"description": "A time window for a stop. The time window may be open-ended, but one or both\n of the start and end times should be provided. The end time must be >= the\n start time."
},
"description": "The time window for the stop. Note that we currently support at most one\n time window but may support multiple time windows in the future.",
"examples": [
[
{
"start": {
"hours": 9
},
"end": {
"hours": 17
}
}
]
]
},
"deliveryDate": {
"allOf": [
{
"title": "Date",
"required": [
"year",
"month",
"day"
],
"type": "object",
"properties": {
"year": {
"maximum": 9999,
"minimum": 1,
"type": "integer",
"description": "Year of the date. Must be from 1 to 9999.",
"format": "int32",
"examples": [
2019
]
},
"month": {
"maximum": 12,
"minimum": 1,
"type": "integer",
"description": "Month of a year. Must be from 1 to 12.",
"format": "int32",
"examples": [
11
]
},
"day": {
"maximum": 31,
"minimum": 1,
"type": "integer",
"description": "Day of a month. Must be from 1 to 31.",
"format": "int32",
"examples": [
15
]
}
},
"description": "A date in year-month-day format."
}
],
"description": "The planned delivery date for the stop.",
"examples": [
{
"year": 2025,
"month": 12,
"day": 16
}
]
},
"attributes": {
"type": "array",
"items": {
"title": "Attribute",
"type": "object",
"properties": {
"key": {
"type": "string",
"description": "Attribute key. Must be non-empty.",
"examples": [
"delivery_date"
]
},
"value": {
"type": "string",
"description": "Attribute value.",
"examples": [
"2025-12-16"
]
}
},
"description": "A key-value pair for storing additional information on a stop, such as order\n details, delivery instructions, or custom fields."
},
"description": "Additional attributes for the stop. Attributes are key-value pairs for\n storing additional structured data on stops. These may be populated from\n the Shopify order or set on import.",
"examples": [
[
{
"key": "color",
"value": "blue"
}
]
]
},
"clientStopId": {
"type": "string",
"description": "The client-provided ID associated with the stop, if provided on import.",
"examples": [
"test-order-1234"
]
},
"tags": {
"type": "array",
"items": {
"type": "string"
},
"description": "The tags for the stop. Tags are used to categorize stops and can be used\n for filtering and grouping stops in the EasyRoutes web app. These may be\n populated from the Shopify order or set on import.",
"examples": [
[
"foo",
"bar"
]
]
},
"attemptedReason": {
"enum": [
"UNKNOWN",
"NOT_AVAILABLE",
"ACCESS_DENIED",
"INCORRECT_ADDRESS",
"SAFE_PLACE_UNAVAILABLE",
"REFUSED",
"EXTERNAL",
"INCORRECT_ITEMS",
"OTHER",
"CANCELED"
],
"type": "string",
"description": "The reason for marking the stop as attempted. This is only populated when\n `deliveryStatus = ATTEMPTED_DELIVERY`.",
"format": "enum",
"examples": [
"NOT_AVAILABLE"
]
},
"attemptedNote": {
"type": "string",
"description": "Optional note related to the reason for marking the stop as attempted. This\n is optionally populated when `deliveryStatus = ATTEMPTED_DELIVERY`.",
"examples": [
"Customer did not answer the door."
]
},
"customerRating": {
"allOf": [
{
"title": "CustomerRating",
"type": "object",
"properties": {
"rating": {
"maximum": 5,
"minimum": 1,
"type": "integer",
"description": "Rating from 1-5",
"format": "int32",
"examples": [
5
]
},
"comment": {
"type": "string",
"description": "Customer comment related to rating",
"examples": [
"Excellent delivery"
]
},
"createdAt": {
"type": "string",
"description": "Timestamp when rating was left by customer.",
"format": "date-time",
"examples": [
"2026-03-30T18:00:00Z"
]
}
},
"description": "Customer rating and feedback left on a stop."
}
],
"description": "Rating left by customer. This can only be populated once `deliveryStatus =\n DELIVERED`."
},
"customSignatureDisclosure": {
"type": "string",
"description": "Optional custom signature disclosure that is shown to customers in the\n driver app.",
"examples": [
"I acknowledge that I have received this delivery."
]
},
"shopifyOrder": {
"allOf": [
{
"title": "ShopifyOrder",
"type": "object",
"properties": {
"orderNote": {
"type": "string",
"description": "The Shopify order note.",
"examples": [
"Customer has paid."
]
},
"customerNote": {
"type": "string",
"description": "The Shopify customer note for the order.",
"examples": [
"Leave at door."
]
}
},
"description": "Shopify-specific information for a RouteStop."
}
],
"description": "Information from the associated Shopify order, if applicable. Populated if\n stop source is `SHOPIFY_ORDER`"
},
"proofOfDeliveryBarcodes": {
"type": "array",
"items": {
"title": "ScannedBarcode",
"type": "object",
"properties": {
"value": {
"type": "string",
"description": "Barcode value (e.g. `\"123456789012\"`).",
"examples": [
"123456789012"
]
},
"createdAt": {
"type": "string",
"description": "Timestamp when the barcode was scanned.",
"format": "date-time",
"examples": [
"2026-03-30T13:10:00Z"
]
}
},
"description": "A proof of delivery barcode scanned at a stop."
},
"description": "Proof of delivery barcodes scanned at the stop."
},
"proofOfDeliveryBarcodeIssues": {
"type": "array",
"items": {
"title": "ScannedBarcodeIssue",
"type": "object",
"properties": {
"reason": {
"enum": [
"UNKNOWN",
"ITEM_MISSING",
"NOT_SCANNABLE",
"INCORRECT"
],
"type": "string",
"description": "The reported reason for the barcode issue.",
"format": "enum",
"examples": [
"ITEM_MISSING"
]
},
"note": {
"type": "string",
"description": "Optional note related to the reason for reporting a barcode issue.",
"examples": [
"Item was not packed."
]
},
"createdAt": {
"type": "string",
"description": "Timestamp when the issue was reported.",
"format": "date-time",
"examples": [
"2026-03-30T13:10:00Z"
]
}
},
"description": "A reported issue related to scanning barcodes at a stop."
},
"description": "Proof of delivery barcode issues reported at the stop."
},
"orderReferenceUrl": {
"type": "string",
"description": "A reference URL for the order associated with the stop (e.g. a link to the\n order in your order management system). Must be a valid HTTPS URL. This\n field can only be populated for imported stops.",
"examples": [
"https://orders.example.com/orders/148977776"
]
}
},
"description": "A stop on a route. A stop may correspond to a delivery or a driver break as\n determined by the type. A delivery stop will have location and contact\n information, items to deliver, optional order details, status, arrival time\n and stop duration, driver tasks and any proof of delivery information. A\n break stop will have start time and duration, and status."
},
"description": "Route stops. See RouteStop for stop fields."
},
"createdAt": {
"type": "string",
"description": "Timestamp when the route was created.",
"format": "date-time",
"examples": [
"2026-03-29T08:00:00Z"
]
},
"updatedAt": {
"type": "string",
"description": "Timestamp when the route was last updated (by the planner).",
"format": "date-time",
"examples": [
"2026-03-30T13:15:00Z"
]
},
"archivedAt": {
"type": "string",
"description": "Timestamp when the route was archived.",
"format": "date-time",
"examples": [
"2026-04-05T00:00:00Z"
]
},
"scheduledFor": {
"type": "string",
"description": "Timestamp when the route is scheduled for.",
"format": "date-time",
"examples": [
"2026-03-30T09:00:00Z"
]
},
"totalDistanceMeters": {
"type": "number",
"description": "The distance in meters for the entire route.",
"format": "double",
"examples": [
2387.2
]
},
"totalItemQuantity": {
"type": "integer",
"description": "The total quantity of items to deliver on the route.",
"format": "int32",
"examples": [
50
]
},
"totalItemGrams": {
"type": "string",
"description": "The total weight in grams for the items on the route.",
"examples": [
"6000"
]
},
"optimized": {
"type": "boolean",
"description": "Whether the route has been optimized. Adding or removing stops, reordering\n stops, or changing route options generally set this field to false until\n the route is reoptimized.",
"examples": [
true
]
},
"dispatchedUntil": {
"type": "string",
"description": "Timestamp until which the route is dispatched and accessible in the driver\n app.",
"format": "date-time",
"examples": [
"2026-03-30T20:00:00Z"
]
},
"note": {
"type": "string",
"description": "Top-level note for the route, as entered manually by route planners.",
"examples": [
"Fragile items."
]
},
"tags": {
"type": "array",
"items": {
"type": "string"
},
"description": "The tags for the route. Tags are used to categorize routes and can be\n used for filtering and grouping routes in the EasyRoutes web app.",
"examples": [
[
"foo",
"bar"
]
]
},
"defaultStopDuration": {
"pattern": "^-?(?:0|[1-9][0-9]{0,11})(?:\\.[0-9]{1,9})?s$",
"type": "string",
"description": "The default duration for stops on the route. Used to estimate arrival\n times for stops that do not have their own duration specified.\n Specified as a duration string in the format \"300s\" for 5 minutes, \"60s\"\n for 1 minute, etc.",
"examples": [
"300s"
]
},
"maxDuration": {
"pattern": "^-?(?:0|[1-9][0-9]{0,11})(?:\\.[0-9]{1,9})?s$",
"type": "string",
"description": "The maximum duration of the route. Specified as a duration string in the\n format \"3600s\" for 1 hour, \"7200s\" for 2 hours, etc.",
"examples": [
"28800s"
]
},
"maxStops": {
"type": "integer",
"description": "The maximum number of stops on the route.",
"format": "int32",
"examples": [
50
]
},
"maxItemCount": {
"type": "integer",
"description": "The maximum total item count across all stops on the route.",
"format": "int32",
"examples": [
200
]
},
"maxKilograms": {
"type": "number",
"description": "The maximum total weight in kilograms across all stops on the route.",
"format": "double",
"examples": [
500
]
},
"avoidTolls": {
"type": "boolean",
"description": "Whether to avoid toll roads during optimization.",
"examples": [
true
]
},
"avoidUTurns": {
"type": "boolean",
"description": "Whether to avoid U-turns during optimization.",
"examples": [
true
]
},
"speedFactor": {
"type": "number",
"description": "A speed factor for the route used during optimization to adjust estimated\n travel times. A value of 1.0 represents normal speed. Values less than 1.0\n indicate slower travel (e.g. 0.5 = half speed), and values greater than\n 1.0 indicate faster travel (e.g. 1.5 = 50% faster). Must be between 0.1\n and 1.9. A value of 0 (or unset) uses the default speed.",
"format": "double",
"examples": [
0.8
]
},
"vehicle": {
"allOf": [
{
"title": "Vehicle",
"required": [
"id"
],
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Vehicle ID.",
"examples": [
"veh-123e4567-e89b-12d3-a456-426614174000"
]
},
"name": {
"type": "string",
"description": "Vehicle name.",
"examples": [
"Delivery Van 1"
]
},
"make": {
"type": "string",
"description": "Vehicle make.",
"examples": [
"Ford"
]
},
"model": {
"type": "string",
"description": "Vehicle model.",
"examples": [
"Transit"
]
},
"year": {
"type": "integer",
"description": "Vehicle model year.",
"format": "int32",
"examples": [
2023
]
},
"type": {
"enum": [
"UNKNOWN",
"CAR",
"CARGO_VAN",
"PICKUP_TRUCK",
"BOX_TRUCK",
"MOTORCYCLE",
"BICYCLE",
"DRONE",
"OTHER"
],
"type": "string",
"description": "Vehicle type.",
"format": "enum",
"examples": [
"CARGO_VAN"
]
},
"vin": {
"type": "string",
"description": "Vehicle Identification Number.",
"examples": [
"1FTBW2CM5NKA12345"
]
},
"license": {
"type": "string",
"description": "Vehicle license plate.",
"examples": [
"ABC-1234"
]
},
"isArchived": {
"type": "boolean",
"description": "Whether the vehicle is archived.",
"examples": [
false
]
},
"createdTimestamp": {
"type": "string",
"description": "Timestamp when the vehicle was created.",
"format": "date-time",
"examples": [
"2026-07-30T12:00:00Z"
]
}
},
"description": "A vehicle that can be assigned to a route."
}
],
"description": "Assigned vehicle for the route."
}
},
"description": "A route of stops, optionally with an assigned driver."
}
}
}
},
"default": {
"description": "Default error response",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"code": {
"type": "integer",
"description": "The status code, which should be an enum value of [google.rpc.Code][google.rpc.Code].",
"format": "int32"
},
"message": {
"type": "string",
"description": "A developer-facing error message, which should be in English. Any user-facing error message should be localized and sent in the [google.rpc.Status.details][google.rpc.Status.details] field, or localized by the client."
},
"details": {
"type": "array",
"items": {
"type": "object",
"properties": {
"@type": {
"type": "string",
"description": "The type of the serialized message."
}
},
"additionalProperties": true,
"description": "Contains an arbitrary serialized message along with a @type that describes the type of the serialized message."
},
"description": "A list of messages that carry the error details. There is a common set of message types for APIs to use."
}
},
"description": "The `Status` type defines a logical error model that is suitable for different programming environments, including REST APIs and RPC APIs. It is used by [gRPC](https://github.com/grpc). Each `Status` message contains three pieces of data: error code, error message, and error details. You can find out more about this error model and how to work with it in the [API Design Guide](https://cloud.google.com/apis/design/errors)."
}
}
}
}
},
"security": [
{
"bearerAuth": []
}
],
"components": {
"securitySchemes": {
"bearerAuth": {
"type": "http",
"description": "Access token from `/authenticate`",
"scheme": "bearer",
"bearerFormat": "JWT"
}
}
}
}
```
# Assign route vehicle (https://docs.roundtrip.ai/docs/api-reference/routes/put-routes-routeId-vehicle)
PUT /routes/{routeId}/vehicle
Assigns a vehicle to a route by route ID. The response will include the
updated route with the new vehicle assigned.
## OpenAPI specification
```json
{
"servers": [
{
"url": "https://easyroutes.roundtrip.ai/api/2024-07"
}
],
"tags": [
"Routes"
],
"summary": "Assign route vehicle",
"description": "Assigns a vehicle to a route by route ID. The response will include the\n updated route with the new vehicle assigned.",
"operationId": "AssignRouteVehicle",
"parameters": [
{
"name": "routeId",
"in": "path",
"description": "The route ID to assign the vehicle to.",
"required": true,
"schema": {
"type": "string",
"examples": [
"rte-123e4567-e89b-12d3-a456-426614174000"
]
}
},
{
"name": "Idempotency-Key",
"in": "header",
"description": "A unique key for safely retrying this operation. For more information read [our guide](https://docs.roundtrip.ai/docs/concepts/idempotency.md).",
"schema": {
"maxLength": 255,
"minLength": 1,
"type": "string"
},
"examples": {
"default": {
"value": "550e8400-e29b-41d4-a716-446655440000"
}
}
}
],
"requestBody": {
"content": {
"application/json": {
"schema": {
"title": "AssignRouteVehicleRequest",
"required": [
"vehicleId"
],
"type": "object",
"properties": {
"vehicleId": {
"type": "string",
"description": "The ID of the vehicle to assign to a route.",
"examples": [
"veh-123e4567-e89b-12d3-a456-426614174000"
]
}
}
}
}
},
"required": true
},
"responses": {
"200": {
"description": "OK",
"headers": {
"Idempotency-Key": {
"description": "The idempotency key associated with the response.",
"schema": {
"type": "string"
}
},
"Idempotency-Replayed": {
"description": "Whether the response was replayed from a previous request.",
"schema": {
"type": "boolean"
}
}
},
"content": {
"application/json": {
"schema": {
"title": "Route",
"required": [
"id",
"name",
"stops",
"createdAt",
"updatedAt",
"totalDistanceMeters",
"totalItemQuantity",
"totalItemGrams",
"optimized"
],
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Route ID (e.g. `\"rte-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"rte-123e4567-e89b-12d3-a456-426614174000"
]
},
"name": {
"type": "string",
"description": "Route name (e.g. `\"Morning route\"`).",
"examples": [
"Morning route"
]
},
"driver": {
"allOf": [
{
"title": "Driver",
"required": [
"id"
],
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Driver ID (e.g. `\"drv-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"drv-123e4567-e89b-12d3-a456-426614174000"
]
},
"firstName": {
"type": "string",
"description": "Driver first name (e.g. `\"John\"`).",
"examples": [
"John"
]
},
"lastName": {
"type": "string",
"description": "Driver last name (e.g. `\"Doe\"`).",
"examples": [
"Doe"
]
},
"phone": {
"type": "string",
"description": "Driver phone number in [E.164 format](https://en.wikipedia.org/wiki/E.164)\n (e.g. `\"+14265551000\"`).",
"examples": [
"+14265551000"
]
},
"status": {
"enum": [
"UNKNOWN",
"ACTIVE",
"INACTIVE",
"ARCHIVED"
],
"type": "string",
"description": "Shop driver status. (e.g. `ACTIVE`).",
"format": "enum",
"examples": [
"ACTIVE"
]
}
},
"description": "A driver who is assigned to a route."
}
],
"description": "Assigned driver for the route."
},
"start": {
"allOf": [
{
"title": "RouteStart",
"type": "object",
"properties": {
"address": {
"allOf": [
{
"title": "Address",
"type": "object",
"properties": {
"address1": {
"type": "string",
"description": "Street address line 1 (e.g. `\"123 Main St\"`).",
"examples": [
"123 Main St"
]
},
"address2": {
"type": "string",
"description": "Street address line 2 (e.g. `\"Apt 101\"`).",
"examples": [
"Apt 3B"
]
},
"city": {
"type": "string",
"description": "City name (e.g. `\"New York\"`).",
"examples": [
"New York"
]
},
"provinceCode": {
"type": "string",
"description": "Province or state as subdivision codes in\n [ISO 3166-2](https://en.wikipedia.org/wiki/ISO_3166-2) format without the\n country prefix (e.g. `\"NY\"` for New York).",
"examples": [
"NY"
]
},
"countryCode": {
"type": "string",
"description": "Country code (e.g. `\"US\"`).",
"examples": [
"US"
]
},
"zip": {
"type": "string",
"description": "Postal or ZIP code (e.g. `\"10001\"`).",
"examples": [
"10001"
]
}
},
"description": "A physical street address."
}
],
"description": "The start address of the route.",
"examples": [
{
"address1": "123 Main St",
"address2": "Apt 3B",
"city": "New York",
"provinceCode": "NY",
"countryCode": "US",
"zip": "10001"
}
]
},
"tasks": {
"type": "array",
"items": {
"title": "Task",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Task ID (e.g. `\"tsk-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"tsk-123e4567-e89b-12d3-a456-426614174000"
]
},
"title": {
"type": "string",
"description": "Task title (e.g. `\"Delivery checklist\"`).",
"examples": [
"Delivery checklist"
]
},
"type": {
"enum": [
"UNKNOWN",
"CHECKBOXES",
"RADIO_BUTTONS",
"TEXT_INPUT",
"DECIMAL_INPUT",
"SCANNER_INPUT"
],
"type": "string",
"description": "Task type.",
"format": "enum",
"examples": [
"TEXT_INPUT"
]
},
"items": {
"type": "array",
"items": {
"title": "TaskItem",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Item ID (e.g. `\"itm-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"itm-123e4567-e89b-12d3-a456-426614174000"
]
},
"title": {
"type": "string",
"description": "Item title (e.g. `\"Pick up package\"`).",
"examples": [
"Pick up package"
]
},
"complete": {
"type": "boolean",
"description": "Whether the item is completed.",
"examples": [
true
]
},
"updatedAt": {
"type": "string",
"description": "Timestamp when the item was last updated.",
"format": "date-time",
"examples": [
"2026-03-30T13:00:00Z"
]
}
},
"description": "An item within a task. For `CHECKBOXES`, each item on a task may be completed\n independently. For `RADIO_BUTTONS`, at most one item will be completed."
},
"description": "Task items (populated for `CHECKBOXES` and `RADIO_BUTTONS`).",
"examples": [
[]
]
},
"input": {
"allOf": [
{
"title": "TaskInput",
"type": "object",
"properties": {
"value": {
"type": "string",
"description": "Input value.",
"examples": [
"020123456789"
]
},
"updatedAt": {
"type": "string",
"description": "Timestamp when the input was last updated.",
"format": "date-time",
"examples": [
"2026-03-30T13:00:00Z"
]
},
"inputMethod": {
"enum": [
"UNKNOWN",
"SCANNED"
],
"type": "string",
"description": "Whether input was scanned (e.g. a scanned barcode)",
"format": "enum",
"examples": [
"SCANNED"
]
}
},
"description": "Captured driver input for a task. The value may be text for `TEXT_INPUT`\n tasks or a string decimal number for `DECIMAL_INPUT` tasks."
}
],
"description": "Task input (populated for `TEXT_INPUT` and `DECIMAL_INPUT`)."
},
"requiredToMarkStopAsDelivered": {
"type": "boolean",
"description": "Whether the task is required to mark the stop as completed. In the case of\n tasks on `RouteStart`, this represents tasks required for starting the\n route. In the case of tasks on `RouteEnd`, this represents tasks required\n for completing the route.",
"examples": [
true
]
},
"requiredToMarkStopAsAttempted": {
"type": "boolean",
"description": "Whether the task is required to mark the stop as attempted.",
"examples": [
true
]
}
},
"description": "A task to be completed at a stop, or at the start or end of a route. Tasks\n may have one or more items for `CHECKBOXES` or `RADIO_BUTTONS`, or may have\n an input for `TEXT_INPUT` or `DECIMAL_INPUT`."
},
"description": "Tasks to complete before starting the route."
},
"status": {
"enum": [
"UNKNOWN",
"STARTED"
],
"type": "string",
"description": "Status indicating whether the route has been started.",
"format": "enum",
"examples": [
"STARTED"
]
},
"updatedStart": {
"type": "string",
"description": "Updated start time for the route. If the route is started, this will be the\n actual start time.",
"format": "date-time",
"examples": [
"2026-03-30T09:05:00Z"
]
},
"scheduledStart": {
"type": "string",
"description": "Scheduled start time for the route (same as `scheduledFor` on the route).",
"format": "date-time",
"examples": [
"2026-03-30T09:00:00Z"
]
},
"photos": {
"type": "array",
"items": {
"title": "StopAttachment",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Attachment ID (e.g. `\"att-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"att-123e4567-e89b-12d3-a456-426614174000"
]
},
"createdAt": {
"type": "string",
"description": "Timestamp when the attachment was created.",
"format": "date-time",
"examples": [
"2026-03-30T09:05:00Z"
]
},
"url": {
"type": "string",
"description": "URL to fetch the attachment.",
"examples": [
"https://example.com/stop-attachment/attachment-2025-06-03-1"
]
}
},
"description": "An attachment to a stop, such as a proof of delivery photo or signature."
},
"description": "Photos for the route start. Photos may be fetched using the URLs on the\n attachments."
}
},
"description": "The start location of a route and any driver tasks to complete before\n beginning the route."
}
],
"description": "Route start address and tasks."
},
"end": {
"allOf": [
{
"title": "RouteEnd",
"type": "object",
"properties": {
"address": {
"allOf": [
{
"title": "Address",
"type": "object",
"properties": {
"address1": {
"type": "string",
"description": "Street address line 1 (e.g. `\"123 Main St\"`).",
"examples": [
"123 Main St"
]
},
"address2": {
"type": "string",
"description": "Street address line 2 (e.g. `\"Apt 101\"`).",
"examples": [
"Apt 3B"
]
},
"city": {
"type": "string",
"description": "City name (e.g. `\"New York\"`).",
"examples": [
"New York"
]
},
"provinceCode": {
"type": "string",
"description": "Province or state as subdivision codes in\n [ISO 3166-2](https://en.wikipedia.org/wiki/ISO_3166-2) format without the\n country prefix (e.g. `\"NY\"` for New York).",
"examples": [
"NY"
]
},
"countryCode": {
"type": "string",
"description": "Country code (e.g. `\"US\"`).",
"examples": [
"US"
]
},
"zip": {
"type": "string",
"description": "Postal or ZIP code (e.g. `\"10001\"`).",
"examples": [
"10001"
]
}
},
"description": "A physical street address."
}
],
"description": "The end address of the route.",
"examples": [
{
"address1": "123 Main St",
"address2": "Apt 3B",
"city": "New York",
"provinceCode": "NY",
"countryCode": "US",
"zip": "10001"
}
]
},
"tasks": {
"type": "array",
"items": {
"title": "Task",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Task ID (e.g. `\"tsk-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"tsk-123e4567-e89b-12d3-a456-426614174000"
]
},
"title": {
"type": "string",
"description": "Task title (e.g. `\"Delivery checklist\"`).",
"examples": [
"Delivery checklist"
]
},
"type": {
"enum": [
"UNKNOWN",
"CHECKBOXES",
"RADIO_BUTTONS",
"TEXT_INPUT",
"DECIMAL_INPUT",
"SCANNER_INPUT"
],
"type": "string",
"description": "Task type.",
"format": "enum",
"examples": [
"TEXT_INPUT"
]
},
"items": {
"type": "array",
"items": {
"title": "TaskItem",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Item ID (e.g. `\"itm-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"itm-123e4567-e89b-12d3-a456-426614174000"
]
},
"title": {
"type": "string",
"description": "Item title (e.g. `\"Pick up package\"`).",
"examples": [
"Pick up package"
]
},
"complete": {
"type": "boolean",
"description": "Whether the item is completed.",
"examples": [
true
]
},
"updatedAt": {
"type": "string",
"description": "Timestamp when the item was last updated.",
"format": "date-time",
"examples": [
"2026-03-30T13:00:00Z"
]
}
},
"description": "An item within a task. For `CHECKBOXES`, each item on a task may be completed\n independently. For `RADIO_BUTTONS`, at most one item will be completed."
},
"description": "Task items (populated for `CHECKBOXES` and `RADIO_BUTTONS`).",
"examples": [
[]
]
},
"input": {
"allOf": [
{
"title": "TaskInput",
"type": "object",
"properties": {
"value": {
"type": "string",
"description": "Input value.",
"examples": [
"020123456789"
]
},
"updatedAt": {
"type": "string",
"description": "Timestamp when the input was last updated.",
"format": "date-time",
"examples": [
"2026-03-30T13:00:00Z"
]
},
"inputMethod": {
"enum": [
"UNKNOWN",
"SCANNED"
],
"type": "string",
"description": "Whether input was scanned (e.g. a scanned barcode)",
"format": "enum",
"examples": [
"SCANNED"
]
}
},
"description": "Captured driver input for a task. The value may be text for `TEXT_INPUT`\n tasks or a string decimal number for `DECIMAL_INPUT` tasks."
}
],
"description": "Task input (populated for `TEXT_INPUT` and `DECIMAL_INPUT`)."
},
"requiredToMarkStopAsDelivered": {
"type": "boolean",
"description": "Whether the task is required to mark the stop as completed. In the case of\n tasks on `RouteStart`, this represents tasks required for starting the\n route. In the case of tasks on `RouteEnd`, this represents tasks required\n for completing the route.",
"examples": [
true
]
},
"requiredToMarkStopAsAttempted": {
"type": "boolean",
"description": "Whether the task is required to mark the stop as attempted.",
"examples": [
true
]
}
},
"description": "A task to be completed at a stop, or at the start or end of a route. Tasks\n may have one or more items for `CHECKBOXES` or `RADIO_BUTTONS`, or may have\n an input for `TEXT_INPUT` or `DECIMAL_INPUT`."
},
"description": "Tasks to complete before finishing the route."
},
"plannedArrival": {
"type": "string",
"description": "Planned arrival time at the end of the route.",
"format": "date-time",
"examples": [
"2026-03-30T17:00:00Z"
]
},
"distanceMeters": {
"type": "number",
"description": "The distance in meters from the previous stop.",
"format": "double",
"examples": [
1234.56
]
},
"updatedArrival": {
"type": "string",
"description": "Estimated arrival time at the end of the route. If the route is completed,\n this will be the actual arrival time.",
"format": "date-time",
"examples": [
"2026-03-30T17:05:00Z"
]
},
"status": {
"enum": [
"UNKNOWN",
"COMPLETED"
],
"type": "string",
"description": "Status indicating whether the route has been completed.",
"format": "enum",
"examples": [
"COMPLETED"
]
},
"photos": {
"type": "array",
"items": {
"title": "StopAttachment",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Attachment ID (e.g. `\"att-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"att-123e4567-e89b-12d3-a456-426614174000"
]
},
"createdAt": {
"type": "string",
"description": "Timestamp when the attachment was created.",
"format": "date-time",
"examples": [
"2026-03-30T09:05:00Z"
]
},
"url": {
"type": "string",
"description": "URL to fetch the attachment.",
"examples": [
"https://example.com/stop-attachment/attachment-2025-06-03-1"
]
}
},
"description": "An attachment to a stop, such as a proof of delivery photo or signature."
},
"description": "Photos for the route end. Photos may be fetched using the URLs on the\n attachments."
}
},
"description": "The end location of a route and any driver tasks to complete after completing\n the route."
}
],
"description": "Route end address and tasks."
},
"stops": {
"type": "array",
"items": {
"title": "RouteStop",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Stop ID (e.g. `\"rst-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"rst-123e4567-e89b-12d3-a456-426614174000"
]
},
"type": {
"enum": [
"UNKNOWN",
"DELIVERY",
"BREAK",
"PICKUP",
"TASK"
],
"type": "string",
"description": "The type of stop (DELIVERY, BREAK, PICKUP, or TASK).",
"format": "enum",
"examples": [
"DELIVERY"
]
},
"deliveryStatus": {
"enum": [
"UNKNOWN",
"DELIVERED",
"OUT_FOR_DELIVERY",
"ATTEMPTED_DELIVERY",
"READY_FOR_DELIVERY"
],
"type": "string",
"description": "The status for DELIVERY, PICKUP, or TASK stops.",
"format": "enum",
"examples": [
"ATTEMPTED_DELIVERY"
]
},
"breakStatus": {
"enum": [
"UNKNOWN",
"COMPLETED"
],
"type": "string",
"description": "The status for BREAK stops.",
"format": "enum",
"examples": [
"COMPLETED"
]
},
"updatedAt": {
"type": "string",
"description": "Timestamp when the stop status was last updated. Note that this timestamp\n corresponds only to major status updates (i.e. stop marked as DELIVERED).\n Minor updates like task completion or adding proof of delivery will not\n advance this timestamp. For those events, use the timestamps on the task or\n proof of delivery attachment.",
"format": "date-time",
"examples": [
"2026-03-30T13:15:00Z"
]
},
"duration": {
"pattern": "^-?(?:0|[1-9][0-9]{0,11})(?:\\.[0-9]{1,9})?s$",
"type": "string",
"description": "Planned duration of the stop in seconds.",
"examples": [
"300s"
]
},
"plannedArrival": {
"type": "string",
"description": "Planned arrival time at the stop.",
"format": "date-time",
"examples": [
"2026-03-30T13:00:00Z"
]
},
"note": {
"type": "string",
"description": "Top-level note for the stop, as entered manually by route planners,\n inherited from a saved or imported stop, or set by order import automation\n rules.",
"examples": [
"Leave at door."
]
},
"address": {
"allOf": [
{
"title": "Address",
"type": "object",
"properties": {
"address1": {
"type": "string",
"description": "Street address line 1 (e.g. `\"123 Main St\"`).",
"examples": [
"123 Main St"
]
},
"address2": {
"type": "string",
"description": "Street address line 2 (e.g. `\"Apt 101\"`).",
"examples": [
"Apt 3B"
]
},
"city": {
"type": "string",
"description": "City name (e.g. `\"New York\"`).",
"examples": [
"New York"
]
},
"provinceCode": {
"type": "string",
"description": "Province or state as subdivision codes in\n [ISO 3166-2](https://en.wikipedia.org/wiki/ISO_3166-2) format without the\n country prefix (e.g. `\"NY\"` for New York).",
"examples": [
"NY"
]
},
"countryCode": {
"type": "string",
"description": "Country code (e.g. `\"US\"`).",
"examples": [
"US"
]
},
"zip": {
"type": "string",
"description": "Postal or ZIP code (e.g. `\"10001\"`).",
"examples": [
"10001"
]
}
},
"description": "A physical street address."
}
],
"description": "Delivery address for the stop.",
"examples": [
{
"address1": "123 Main St",
"address2": "Apt 3B",
"city": "New York",
"provinceCode": "NY",
"countryCode": "US",
"zip": "10001"
}
]
},
"contact": {
"allOf": [
{
"title": "Contact",
"type": "object",
"properties": {
"firstName": {
"type": "string",
"description": "First name (e.g. `\"John\"`).",
"examples": [
"John"
]
},
"lastName": {
"type": "string",
"description": "Last name (e.g. `\"Doe\"`).",
"examples": [
"Doe"
]
},
"company": {
"type": "string",
"description": "Company name (e.g. `\"Roundtrip Systems Inc\"`).",
"examples": [
"Roundtrip Systems Inc"
]
},
"phone": {
"type": "string",
"description": "Phone number in [E.164 format](https://en.wikipedia.org/wiki/E.164) (e.g.\n `\"+14265551000\"`).",
"examples": [
"+14265551000"
]
},
"email": {
"type": "string",
"description": "Email address (e.g. `\"john.doe@roundtrip.ai\"`)",
"examples": [
"john.doe@roundtrip.ai"
]
}
},
"description": "Contact information for a person or company."
}
],
"description": "Contact information for the stop delivery recipient.",
"examples": [
{
"firstName": "John",
"lastName": "Doe",
"company": "Roundtrip Systems Inc",
"phone": "+14265551000",
"email": "john.doe@roundtrip.ai"
}
]
},
"plannedCoordinates": {
"allOf": [
{
"type": "object",
"properties": {
"latitude": {
"type": "number",
"description": "The latitude in degrees. It must be in the range [-90.0, +90.0].",
"format": "double"
},
"longitude": {
"type": "number",
"description": "The longitude in degrees. It must be in the range [-180.0, +180.0].",
"format": "double"
}
},
"description": "An object that represents a latitude/longitude pair. This is expressed as a\n pair of doubles to represent degrees latitude and degrees longitude. Unless\n specified otherwise, this must conform to the\n WGS84\n standard. Values must be within normalized ranges."
}
],
"description": "Planned coordinates for the stop.",
"examples": [
{
"latitude": 40.7128,
"longitude": -74.006
}
]
},
"items": {
"type": "array",
"items": {
"title": "StopItem",
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "Item name (e.g. `\"Bananas\"`).",
"examples": [
"Bananas"
]
},
"quantity": {
"type": "integer",
"description": "Quantity of the item (e.g. `5`).",
"format": "int32",
"examples": [
5
]
},
"grams": {
"type": "integer",
"description": "Weight of the item in grams (e.g. `500`).",
"format": "int32",
"examples": [
500
]
},
"sku": {
"type": "string",
"description": "Stock keeping unit (e.g. `\"BANANA-001\"`).",
"examples": [
"BANANA-001"
]
}
},
"description": "An item to be delivered at a stop."
},
"description": "Items to deliver at the stop."
},
"source": {
"enum": [
"UNKNOWN",
"SHOPIFY_ORDER",
"SAVED_STOP",
"IMPORTED_STOP"
],
"type": "string",
"description": "The source of the stop, which may be populated for `DELIVERY` stops. The\n source can be a `SHOPIFY_ORDER`, an EasyRoutes `SAVED_STOP`, or an\n `IMPORTED_STOP` from an external source (such as CSV file).",
"format": "enum",
"examples": [
"IMPORTED_STOP"
]
},
"shopifyOrderId": {
"type": "string",
"description": "The Shopify order ID, populated when the stop source is a `SHOPIFY_ORDER`.",
"examples": [
"6229749334323"
]
},
"savedStopId": {
"type": "string",
"description": "The saved stop ID, populated when the stop source is a `SAVED_STOP`.",
"examples": [
"sst-123e4567-e89b-12d3-a456-426614174000"
]
},
"deliveredCoordinates": {
"allOf": [
{
"type": "object",
"properties": {
"latitude": {
"type": "number",
"description": "The latitude in degrees. It must be in the range [-90.0, +90.0].",
"format": "double"
},
"longitude": {
"type": "number",
"description": "The longitude in degrees. It must be in the range [-180.0, +180.0].",
"format": "double"
}
},
"description": "An object that represents a latitude/longitude pair. This is expressed as a\n pair of doubles to represent degrees latitude and degrees longitude. Unless\n specified otherwise, this must conform to the\n WGS84\n standard. Values must be within normalized ranges."
}
],
"description": "Delivered coordinates for the stop."
},
"proofOfDeliveryNote": {
"type": "string",
"description": "Proof of delivery note for the stop.",
"examples": [
"Left at door."
]
},
"proofOfDeliveryPhotos": {
"type": "array",
"items": {
"title": "StopAttachment",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Attachment ID (e.g. `\"att-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"att-123e4567-e89b-12d3-a456-426614174000"
]
},
"createdAt": {
"type": "string",
"description": "Timestamp when the attachment was created.",
"format": "date-time",
"examples": [
"2026-03-30T09:05:00Z"
]
},
"url": {
"type": "string",
"description": "URL to fetch the attachment.",
"examples": [
"https://example.com/stop-attachment/attachment-2025-06-03-1"
]
}
},
"description": "An attachment to a stop, such as a proof of delivery photo or signature."
},
"description": "Proof of delivery photos for the stop. Photos may be fetched using the URLs\n on the attachments."
},
"proofOfDeliverySignatures": {
"type": "array",
"items": {
"title": "StopAttachment",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Attachment ID (e.g. `\"att-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"att-123e4567-e89b-12d3-a456-426614174000"
]
},
"createdAt": {
"type": "string",
"description": "Timestamp when the attachment was created.",
"format": "date-time",
"examples": [
"2026-03-30T09:05:00Z"
]
},
"url": {
"type": "string",
"description": "URL to fetch the attachment.",
"examples": [
"https://example.com/stop-attachment/attachment-2025-06-03-1"
]
}
},
"description": "An attachment to a stop, such as a proof of delivery photo or signature."
},
"description": "Proof of delivery signatures for the stop. Signatures may be fetched using\n the URLs on the attachments."
},
"tasks": {
"type": "array",
"items": {
"title": "Task",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Task ID (e.g. `\"tsk-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"tsk-123e4567-e89b-12d3-a456-426614174000"
]
},
"title": {
"type": "string",
"description": "Task title (e.g. `\"Delivery checklist\"`).",
"examples": [
"Delivery checklist"
]
},
"type": {
"enum": [
"UNKNOWN",
"CHECKBOXES",
"RADIO_BUTTONS",
"TEXT_INPUT",
"DECIMAL_INPUT",
"SCANNER_INPUT"
],
"type": "string",
"description": "Task type.",
"format": "enum",
"examples": [
"TEXT_INPUT"
]
},
"items": {
"type": "array",
"items": {
"title": "TaskItem",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Item ID (e.g. `\"itm-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"itm-123e4567-e89b-12d3-a456-426614174000"
]
},
"title": {
"type": "string",
"description": "Item title (e.g. `\"Pick up package\"`).",
"examples": [
"Pick up package"
]
},
"complete": {
"type": "boolean",
"description": "Whether the item is completed.",
"examples": [
true
]
},
"updatedAt": {
"type": "string",
"description": "Timestamp when the item was last updated.",
"format": "date-time",
"examples": [
"2026-03-30T13:00:00Z"
]
}
},
"description": "An item within a task. For `CHECKBOXES`, each item on a task may be completed\n independently. For `RADIO_BUTTONS`, at most one item will be completed."
},
"description": "Task items (populated for `CHECKBOXES` and `RADIO_BUTTONS`).",
"examples": [
[]
]
},
"input": {
"allOf": [
{
"title": "TaskInput",
"type": "object",
"properties": {
"value": {
"type": "string",
"description": "Input value.",
"examples": [
"020123456789"
]
},
"updatedAt": {
"type": "string",
"description": "Timestamp when the input was last updated.",
"format": "date-time",
"examples": [
"2026-03-30T13:00:00Z"
]
},
"inputMethod": {
"enum": [
"UNKNOWN",
"SCANNED"
],
"type": "string",
"description": "Whether input was scanned (e.g. a scanned barcode)",
"format": "enum",
"examples": [
"SCANNED"
]
}
},
"description": "Captured driver input for a task. The value may be text for `TEXT_INPUT`\n tasks or a string decimal number for `DECIMAL_INPUT` tasks."
}
],
"description": "Task input (populated for `TEXT_INPUT` and `DECIMAL_INPUT`)."
},
"requiredToMarkStopAsDelivered": {
"type": "boolean",
"description": "Whether the task is required to mark the stop as completed. In the case of\n tasks on `RouteStart`, this represents tasks required for starting the\n route. In the case of tasks on `RouteEnd`, this represents tasks required\n for completing the route.",
"examples": [
true
]
},
"requiredToMarkStopAsAttempted": {
"type": "boolean",
"description": "Whether the task is required to mark the stop as attempted.",
"examples": [
true
]
}
},
"description": "A task to be completed at a stop, or at the start or end of a route. Tasks\n may have one or more items for `CHECKBOXES` or `RADIO_BUTTONS`, or may have\n an input for `TEXT_INPUT` or `DECIMAL_INPUT`."
},
"description": "Driver tasks for the stop, including completed items and any input from the\n driver."
},
"priority": {
"maximum": 10,
"type": "integer",
"description": "Priority of the stop for route planning. The valid range for stop priority\n is between `1` (low) and `10` (high), with default priority corresponding\n to a value of `5`. A priority value of `0` is considered unset and is\n treated the same as \"default\" priority. Stops with higher priority will be\n preferred when generating routes with constraints.",
"format": "int32",
"examples": [
8
]
},
"importedStopId": {
"type": "string",
"description": "The imported stop ID, populated when the stop source is `IMPORTED_STOP`.",
"examples": [
"ist-123e4567-e89b-12d3-a456-426614174000"
]
},
"orderName": {
"type": "string",
"description": "The name of the order associated with the stop. For Shopify orders, the\n name is generated by combining the `orderNumber` property with the order\n prefix and suffix that are set in the merchant's general settings. For\n EasyRoutes imported orders, this field is populated with the order name\n provided on import.",
"examples": [
"#1234"
]
},
"distanceMeters": {
"type": "number",
"description": "The distance in meters from the previous stop.",
"format": "double",
"examples": [
123.45
]
},
"updatedArrival": {
"type": "string",
"description": "Estimated arrival time at the stop. If the stop is completed, this will be\n the actual arrival time.",
"format": "date-time",
"examples": [
"2026-03-30T13:05:00Z"
]
},
"timeWindows": {
"type": "array",
"items": {
"title": "TimeWindow",
"type": "object",
"properties": {
"start": {
"allOf": [
{
"title": "TimeOfDay",
"type": "object",
"properties": {
"hours": {
"maximum": 23,
"type": "integer",
"description": "Hours of day in 24 hour format. Must be from 0 to 23.",
"format": "int32",
"examples": [
13
]
},
"minutes": {
"maximum": 59,
"type": "integer",
"description": "Minutes of hour of day. Must be from 0 to 59.",
"format": "int32",
"examples": [
37
]
},
"seconds": {
"maximum": 59,
"type": "integer",
"description": "Seconds of minutes of the time. Must be from 0 to 59.",
"format": "int32",
"examples": [
16
]
}
},
"description": "A time of day, independent of a particular date or timezone."
}
],
"description": "The start time of the time window (optional)."
},
"end": {
"allOf": [
{
"title": "TimeOfDay",
"type": "object",
"properties": {
"hours": {
"maximum": 23,
"type": "integer",
"description": "Hours of day in 24 hour format. Must be from 0 to 23.",
"format": "int32",
"examples": [
13
]
},
"minutes": {
"maximum": 59,
"type": "integer",
"description": "Minutes of hour of day. Must be from 0 to 59.",
"format": "int32",
"examples": [
37
]
},
"seconds": {
"maximum": 59,
"type": "integer",
"description": "Seconds of minutes of the time. Must be from 0 to 59.",
"format": "int32",
"examples": [
16
]
}
},
"description": "A time of day, independent of a particular date or timezone."
}
],
"description": "The end time of the time window (optional)."
}
},
"description": "A time window for a stop. The time window may be open-ended, but one or both\n of the start and end times should be provided. The end time must be >= the\n start time."
},
"description": "The time window for the stop. Note that we currently support at most one\n time window but may support multiple time windows in the future.",
"examples": [
[
{
"start": {
"hours": 9
},
"end": {
"hours": 17
}
}
]
]
},
"deliveryDate": {
"allOf": [
{
"title": "Date",
"required": [
"year",
"month",
"day"
],
"type": "object",
"properties": {
"year": {
"maximum": 9999,
"minimum": 1,
"type": "integer",
"description": "Year of the date. Must be from 1 to 9999.",
"format": "int32",
"examples": [
2019
]
},
"month": {
"maximum": 12,
"minimum": 1,
"type": "integer",
"description": "Month of a year. Must be from 1 to 12.",
"format": "int32",
"examples": [
11
]
},
"day": {
"maximum": 31,
"minimum": 1,
"type": "integer",
"description": "Day of a month. Must be from 1 to 31.",
"format": "int32",
"examples": [
15
]
}
},
"description": "A date in year-month-day format."
}
],
"description": "The planned delivery date for the stop.",
"examples": [
{
"year": 2025,
"month": 12,
"day": 16
}
]
},
"attributes": {
"type": "array",
"items": {
"title": "Attribute",
"type": "object",
"properties": {
"key": {
"type": "string",
"description": "Attribute key. Must be non-empty.",
"examples": [
"delivery_date"
]
},
"value": {
"type": "string",
"description": "Attribute value.",
"examples": [
"2025-12-16"
]
}
},
"description": "A key-value pair for storing additional information on a stop, such as order\n details, delivery instructions, or custom fields."
},
"description": "Additional attributes for the stop. Attributes are key-value pairs for\n storing additional structured data on stops. These may be populated from\n the Shopify order or set on import.",
"examples": [
[
{
"key": "color",
"value": "blue"
}
]
]
},
"clientStopId": {
"type": "string",
"description": "The client-provided ID associated with the stop, if provided on import.",
"examples": [
"test-order-1234"
]
},
"tags": {
"type": "array",
"items": {
"type": "string"
},
"description": "The tags for the stop. Tags are used to categorize stops and can be used\n for filtering and grouping stops in the EasyRoutes web app. These may be\n populated from the Shopify order or set on import.",
"examples": [
[
"foo",
"bar"
]
]
},
"attemptedReason": {
"enum": [
"UNKNOWN",
"NOT_AVAILABLE",
"ACCESS_DENIED",
"INCORRECT_ADDRESS",
"SAFE_PLACE_UNAVAILABLE",
"REFUSED",
"EXTERNAL",
"INCORRECT_ITEMS",
"OTHER",
"CANCELED"
],
"type": "string",
"description": "The reason for marking the stop as attempted. This is only populated when\n `deliveryStatus = ATTEMPTED_DELIVERY`.",
"format": "enum",
"examples": [
"NOT_AVAILABLE"
]
},
"attemptedNote": {
"type": "string",
"description": "Optional note related to the reason for marking the stop as attempted. This\n is optionally populated when `deliveryStatus = ATTEMPTED_DELIVERY`.",
"examples": [
"Customer did not answer the door."
]
},
"customerRating": {
"allOf": [
{
"title": "CustomerRating",
"type": "object",
"properties": {
"rating": {
"maximum": 5,
"minimum": 1,
"type": "integer",
"description": "Rating from 1-5",
"format": "int32",
"examples": [
5
]
},
"comment": {
"type": "string",
"description": "Customer comment related to rating",
"examples": [
"Excellent delivery"
]
},
"createdAt": {
"type": "string",
"description": "Timestamp when rating was left by customer.",
"format": "date-time",
"examples": [
"2026-03-30T18:00:00Z"
]
}
},
"description": "Customer rating and feedback left on a stop."
}
],
"description": "Rating left by customer. This can only be populated once `deliveryStatus =\n DELIVERED`."
},
"customSignatureDisclosure": {
"type": "string",
"description": "Optional custom signature disclosure that is shown to customers in the\n driver app.",
"examples": [
"I acknowledge that I have received this delivery."
]
},
"shopifyOrder": {
"allOf": [
{
"title": "ShopifyOrder",
"type": "object",
"properties": {
"orderNote": {
"type": "string",
"description": "The Shopify order note.",
"examples": [
"Customer has paid."
]
},
"customerNote": {
"type": "string",
"description": "The Shopify customer note for the order.",
"examples": [
"Leave at door."
]
}
},
"description": "Shopify-specific information for a RouteStop."
}
],
"description": "Information from the associated Shopify order, if applicable. Populated if\n stop source is `SHOPIFY_ORDER`"
},
"proofOfDeliveryBarcodes": {
"type": "array",
"items": {
"title": "ScannedBarcode",
"type": "object",
"properties": {
"value": {
"type": "string",
"description": "Barcode value (e.g. `\"123456789012\"`).",
"examples": [
"123456789012"
]
},
"createdAt": {
"type": "string",
"description": "Timestamp when the barcode was scanned.",
"format": "date-time",
"examples": [
"2026-03-30T13:10:00Z"
]
}
},
"description": "A proof of delivery barcode scanned at a stop."
},
"description": "Proof of delivery barcodes scanned at the stop."
},
"proofOfDeliveryBarcodeIssues": {
"type": "array",
"items": {
"title": "ScannedBarcodeIssue",
"type": "object",
"properties": {
"reason": {
"enum": [
"UNKNOWN",
"ITEM_MISSING",
"NOT_SCANNABLE",
"INCORRECT"
],
"type": "string",
"description": "The reported reason for the barcode issue.",
"format": "enum",
"examples": [
"ITEM_MISSING"
]
},
"note": {
"type": "string",
"description": "Optional note related to the reason for reporting a barcode issue.",
"examples": [
"Item was not packed."
]
},
"createdAt": {
"type": "string",
"description": "Timestamp when the issue was reported.",
"format": "date-time",
"examples": [
"2026-03-30T13:10:00Z"
]
}
},
"description": "A reported issue related to scanning barcodes at a stop."
},
"description": "Proof of delivery barcode issues reported at the stop."
},
"orderReferenceUrl": {
"type": "string",
"description": "A reference URL for the order associated with the stop (e.g. a link to the\n order in your order management system). Must be a valid HTTPS URL. This\n field can only be populated for imported stops.",
"examples": [
"https://orders.example.com/orders/148977776"
]
}
},
"description": "A stop on a route. A stop may correspond to a delivery or a driver break as\n determined by the type. A delivery stop will have location and contact\n information, items to deliver, optional order details, status, arrival time\n and stop duration, driver tasks and any proof of delivery information. A\n break stop will have start time and duration, and status."
},
"description": "Route stops. See RouteStop for stop fields."
},
"createdAt": {
"type": "string",
"description": "Timestamp when the route was created.",
"format": "date-time",
"examples": [
"2026-03-29T08:00:00Z"
]
},
"updatedAt": {
"type": "string",
"description": "Timestamp when the route was last updated (by the planner).",
"format": "date-time",
"examples": [
"2026-03-30T13:15:00Z"
]
},
"archivedAt": {
"type": "string",
"description": "Timestamp when the route was archived.",
"format": "date-time",
"examples": [
"2026-04-05T00:00:00Z"
]
},
"scheduledFor": {
"type": "string",
"description": "Timestamp when the route is scheduled for.",
"format": "date-time",
"examples": [
"2026-03-30T09:00:00Z"
]
},
"totalDistanceMeters": {
"type": "number",
"description": "The distance in meters for the entire route.",
"format": "double",
"examples": [
2387.2
]
},
"totalItemQuantity": {
"type": "integer",
"description": "The total quantity of items to deliver on the route.",
"format": "int32",
"examples": [
50
]
},
"totalItemGrams": {
"type": "string",
"description": "The total weight in grams for the items on the route.",
"examples": [
"6000"
]
},
"optimized": {
"type": "boolean",
"description": "Whether the route has been optimized. Adding or removing stops, reordering\n stops, or changing route options generally set this field to false until\n the route is reoptimized.",
"examples": [
true
]
},
"dispatchedUntil": {
"type": "string",
"description": "Timestamp until which the route is dispatched and accessible in the driver\n app.",
"format": "date-time",
"examples": [
"2026-03-30T20:00:00Z"
]
},
"note": {
"type": "string",
"description": "Top-level note for the route, as entered manually by route planners.",
"examples": [
"Fragile items."
]
},
"tags": {
"type": "array",
"items": {
"type": "string"
},
"description": "The tags for the route. Tags are used to categorize routes and can be\n used for filtering and grouping routes in the EasyRoutes web app.",
"examples": [
[
"foo",
"bar"
]
]
},
"defaultStopDuration": {
"pattern": "^-?(?:0|[1-9][0-9]{0,11})(?:\\.[0-9]{1,9})?s$",
"type": "string",
"description": "The default duration for stops on the route. Used to estimate arrival\n times for stops that do not have their own duration specified.\n Specified as a duration string in the format \"300s\" for 5 minutes, \"60s\"\n for 1 minute, etc.",
"examples": [
"300s"
]
},
"maxDuration": {
"pattern": "^-?(?:0|[1-9][0-9]{0,11})(?:\\.[0-9]{1,9})?s$",
"type": "string",
"description": "The maximum duration of the route. Specified as a duration string in the\n format \"3600s\" for 1 hour, \"7200s\" for 2 hours, etc.",
"examples": [
"28800s"
]
},
"maxStops": {
"type": "integer",
"description": "The maximum number of stops on the route.",
"format": "int32",
"examples": [
50
]
},
"maxItemCount": {
"type": "integer",
"description": "The maximum total item count across all stops on the route.",
"format": "int32",
"examples": [
200
]
},
"maxKilograms": {
"type": "number",
"description": "The maximum total weight in kilograms across all stops on the route.",
"format": "double",
"examples": [
500
]
},
"avoidTolls": {
"type": "boolean",
"description": "Whether to avoid toll roads during optimization.",
"examples": [
true
]
},
"avoidUTurns": {
"type": "boolean",
"description": "Whether to avoid U-turns during optimization.",
"examples": [
true
]
},
"speedFactor": {
"type": "number",
"description": "A speed factor for the route used during optimization to adjust estimated\n travel times. A value of 1.0 represents normal speed. Values less than 1.0\n indicate slower travel (e.g. 0.5 = half speed), and values greater than\n 1.0 indicate faster travel (e.g. 1.5 = 50% faster). Must be between 0.1\n and 1.9. A value of 0 (or unset) uses the default speed.",
"format": "double",
"examples": [
0.8
]
},
"vehicle": {
"allOf": [
{
"title": "Vehicle",
"required": [
"id"
],
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Vehicle ID.",
"examples": [
"veh-123e4567-e89b-12d3-a456-426614174000"
]
},
"name": {
"type": "string",
"description": "Vehicle name.",
"examples": [
"Delivery Van 1"
]
},
"make": {
"type": "string",
"description": "Vehicle make.",
"examples": [
"Ford"
]
},
"model": {
"type": "string",
"description": "Vehicle model.",
"examples": [
"Transit"
]
},
"year": {
"type": "integer",
"description": "Vehicle model year.",
"format": "int32",
"examples": [
2023
]
},
"type": {
"enum": [
"UNKNOWN",
"CAR",
"CARGO_VAN",
"PICKUP_TRUCK",
"BOX_TRUCK",
"MOTORCYCLE",
"BICYCLE",
"DRONE",
"OTHER"
],
"type": "string",
"description": "Vehicle type.",
"format": "enum",
"examples": [
"CARGO_VAN"
]
},
"vin": {
"type": "string",
"description": "Vehicle Identification Number.",
"examples": [
"1FTBW2CM5NKA12345"
]
},
"license": {
"type": "string",
"description": "Vehicle license plate.",
"examples": [
"ABC-1234"
]
},
"isArchived": {
"type": "boolean",
"description": "Whether the vehicle is archived.",
"examples": [
false
]
},
"createdTimestamp": {
"type": "string",
"description": "Timestamp when the vehicle was created.",
"format": "date-time",
"examples": [
"2026-07-30T12:00:00Z"
]
}
},
"description": "A vehicle that can be assigned to a route."
}
],
"description": "Assigned vehicle for the route."
}
},
"description": "A route of stops, optionally with an assigned driver."
}
}
}
},
"default": {
"description": "Default error response",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"code": {
"type": "integer",
"description": "The status code, which should be an enum value of [google.rpc.Code][google.rpc.Code].",
"format": "int32"
},
"message": {
"type": "string",
"description": "A developer-facing error message, which should be in English. Any user-facing error message should be localized and sent in the [google.rpc.Status.details][google.rpc.Status.details] field, or localized by the client."
},
"details": {
"type": "array",
"items": {
"type": "object",
"properties": {
"@type": {
"type": "string",
"description": "The type of the serialized message."
}
},
"additionalProperties": true,
"description": "Contains an arbitrary serialized message along with a @type that describes the type of the serialized message."
},
"description": "A list of messages that carry the error details. There is a common set of message types for APIs to use."
}
},
"description": "The `Status` type defines a logical error model that is suitable for different programming environments, including REST APIs and RPC APIs. It is used by [gRPC](https://github.com/grpc). Each `Status` message contains three pieces of data: error code, error message, and error details. You can find out more about this error model and how to work with it in the [API Design Guide](https://cloud.google.com/apis/design/errors)."
}
}
}
}
},
"security": [
{
"bearerAuth": []
}
],
"components": {
"securitySchemes": {
"bearerAuth": {
"type": "http",
"description": "Access token from `/authenticate`",
"scheme": "bearer",
"bearerFormat": "JWT"
}
}
}
}
```
# Delete route stops (https://docs.roundtrip.ai/docs/api-reference/stops/delete-routes-routeId-stops-stopIds)
DELETE /routes/{routeId}/stops/{stopIds}
Deletes one or more stops from a route by route ID and stop IDs. Note that
the route may be in progress, completed, or archived and it is therefore up
to the caller to decide when it is appropriate to delete stops from a
route. The response will include the updated route with the stops removed.
If a stop is not found, it will be ignored and the route will be returned
without that stop. The route will not be optimized automatically after
deleting stops, so the caller should reoptimize the route if needed via
ReoptimizeRoute.
## OpenAPI specification
```json
{
"servers": [
{
"url": "https://easyroutes.roundtrip.ai/api/2024-07"
}
],
"tags": [
"Stops"
],
"summary": "Delete route stops",
"description": "Deletes one or more stops from a route by route ID and stop IDs. Note that\n the route may be in progress, completed, or archived and it is therefore up\n to the caller to decide when it is appropriate to delete stops from a\n route. The response will include the updated route with the stops removed.\n If a stop is not found, it will be ignored and the route will be returned\n without that stop. The route will not be optimized automatically after\n deleting stops, so the caller should reoptimize the route if needed via\n ReoptimizeRoute.",
"operationId": "DeleteRouteStops",
"parameters": [
{
"name": "routeId",
"in": "path",
"description": "The ID of the route to delete stops from.",
"required": true,
"schema": {
"type": "string",
"examples": [
"rte-123e4567-e89b-12d3-a456-426614174000"
]
}
},
{
"name": "stopIds",
"in": "path",
"description": "The IDs of the stops to delete from the route. Multiple stop IDs can be\n provided as a comma-separated list in the URL.",
"required": true,
"schema": {
"type": "array",
"items": {
"type": "string"
},
"examples": [
[
"rst-123e4567-e89b-12d3-a456-426614174000"
]
]
}
},
{
"name": "Idempotency-Key",
"in": "header",
"description": "A unique key for safely retrying this operation. For more information read [our guide](https://docs.roundtrip.ai/docs/concepts/idempotency.md).",
"schema": {
"maxLength": 255,
"minLength": 1,
"type": "string"
},
"examples": {
"default": {
"value": "550e8400-e29b-41d4-a716-446655440000"
}
}
}
],
"responses": {
"200": {
"description": "OK",
"headers": {
"Idempotency-Key": {
"description": "The idempotency key associated with the response.",
"schema": {
"type": "string"
}
},
"Idempotency-Replayed": {
"description": "Whether the response was replayed from a previous request.",
"schema": {
"type": "boolean"
}
}
},
"content": {
"application/json": {
"schema": {
"title": "Route",
"required": [
"id",
"name",
"stops",
"createdAt",
"updatedAt",
"totalDistanceMeters",
"totalItemQuantity",
"totalItemGrams",
"optimized"
],
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Route ID (e.g. `\"rte-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"rte-123e4567-e89b-12d3-a456-426614174000"
]
},
"name": {
"type": "string",
"description": "Route name (e.g. `\"Morning route\"`).",
"examples": [
"Morning route"
]
},
"driver": {
"allOf": [
{
"title": "Driver",
"required": [
"id"
],
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Driver ID (e.g. `\"drv-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"drv-123e4567-e89b-12d3-a456-426614174000"
]
},
"firstName": {
"type": "string",
"description": "Driver first name (e.g. `\"John\"`).",
"examples": [
"John"
]
},
"lastName": {
"type": "string",
"description": "Driver last name (e.g. `\"Doe\"`).",
"examples": [
"Doe"
]
},
"phone": {
"type": "string",
"description": "Driver phone number in [E.164 format](https://en.wikipedia.org/wiki/E.164)\n (e.g. `\"+14265551000\"`).",
"examples": [
"+14265551000"
]
},
"status": {
"enum": [
"UNKNOWN",
"ACTIVE",
"INACTIVE",
"ARCHIVED"
],
"type": "string",
"description": "Shop driver status. (e.g. `ACTIVE`).",
"format": "enum",
"examples": [
"ACTIVE"
]
}
},
"description": "A driver who is assigned to a route."
}
],
"description": "Assigned driver for the route."
},
"start": {
"allOf": [
{
"title": "RouteStart",
"type": "object",
"properties": {
"address": {
"allOf": [
{
"title": "Address",
"type": "object",
"properties": {
"address1": {
"type": "string",
"description": "Street address line 1 (e.g. `\"123 Main St\"`).",
"examples": [
"123 Main St"
]
},
"address2": {
"type": "string",
"description": "Street address line 2 (e.g. `\"Apt 101\"`).",
"examples": [
"Apt 3B"
]
},
"city": {
"type": "string",
"description": "City name (e.g. `\"New York\"`).",
"examples": [
"New York"
]
},
"provinceCode": {
"type": "string",
"description": "Province or state as subdivision codes in\n [ISO 3166-2](https://en.wikipedia.org/wiki/ISO_3166-2) format without the\n country prefix (e.g. `\"NY\"` for New York).",
"examples": [
"NY"
]
},
"countryCode": {
"type": "string",
"description": "Country code (e.g. `\"US\"`).",
"examples": [
"US"
]
},
"zip": {
"type": "string",
"description": "Postal or ZIP code (e.g. `\"10001\"`).",
"examples": [
"10001"
]
}
},
"description": "A physical street address."
}
],
"description": "The start address of the route.",
"examples": [
{
"address1": "123 Main St",
"address2": "Apt 3B",
"city": "New York",
"provinceCode": "NY",
"countryCode": "US",
"zip": "10001"
}
]
},
"tasks": {
"type": "array",
"items": {
"title": "Task",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Task ID (e.g. `\"tsk-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"tsk-123e4567-e89b-12d3-a456-426614174000"
]
},
"title": {
"type": "string",
"description": "Task title (e.g. `\"Delivery checklist\"`).",
"examples": [
"Delivery checklist"
]
},
"type": {
"enum": [
"UNKNOWN",
"CHECKBOXES",
"RADIO_BUTTONS",
"TEXT_INPUT",
"DECIMAL_INPUT",
"SCANNER_INPUT"
],
"type": "string",
"description": "Task type.",
"format": "enum",
"examples": [
"TEXT_INPUT"
]
},
"items": {
"type": "array",
"items": {
"title": "TaskItem",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Item ID (e.g. `\"itm-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"itm-123e4567-e89b-12d3-a456-426614174000"
]
},
"title": {
"type": "string",
"description": "Item title (e.g. `\"Pick up package\"`).",
"examples": [
"Pick up package"
]
},
"complete": {
"type": "boolean",
"description": "Whether the item is completed.",
"examples": [
true
]
},
"updatedAt": {
"type": "string",
"description": "Timestamp when the item was last updated.",
"format": "date-time",
"examples": [
"2026-03-30T13:00:00Z"
]
}
},
"description": "An item within a task. For `CHECKBOXES`, each item on a task may be completed\n independently. For `RADIO_BUTTONS`, at most one item will be completed."
},
"description": "Task items (populated for `CHECKBOXES` and `RADIO_BUTTONS`).",
"examples": [
[]
]
},
"input": {
"allOf": [
{
"title": "TaskInput",
"type": "object",
"properties": {
"value": {
"type": "string",
"description": "Input value.",
"examples": [
"020123456789"
]
},
"updatedAt": {
"type": "string",
"description": "Timestamp when the input was last updated.",
"format": "date-time",
"examples": [
"2026-03-30T13:00:00Z"
]
},
"inputMethod": {
"enum": [
"UNKNOWN",
"SCANNED"
],
"type": "string",
"description": "Whether input was scanned (e.g. a scanned barcode)",
"format": "enum",
"examples": [
"SCANNED"
]
}
},
"description": "Captured driver input for a task. The value may be text for `TEXT_INPUT`\n tasks or a string decimal number for `DECIMAL_INPUT` tasks."
}
],
"description": "Task input (populated for `TEXT_INPUT` and `DECIMAL_INPUT`)."
},
"requiredToMarkStopAsDelivered": {
"type": "boolean",
"description": "Whether the task is required to mark the stop as completed. In the case of\n tasks on `RouteStart`, this represents tasks required for starting the\n route. In the case of tasks on `RouteEnd`, this represents tasks required\n for completing the route.",
"examples": [
true
]
},
"requiredToMarkStopAsAttempted": {
"type": "boolean",
"description": "Whether the task is required to mark the stop as attempted.",
"examples": [
true
]
}
},
"description": "A task to be completed at a stop, or at the start or end of a route. Tasks\n may have one or more items for `CHECKBOXES` or `RADIO_BUTTONS`, or may have\n an input for `TEXT_INPUT` or `DECIMAL_INPUT`."
},
"description": "Tasks to complete before starting the route."
},
"status": {
"enum": [
"UNKNOWN",
"STARTED"
],
"type": "string",
"description": "Status indicating whether the route has been started.",
"format": "enum",
"examples": [
"STARTED"
]
},
"updatedStart": {
"type": "string",
"description": "Updated start time for the route. If the route is started, this will be the\n actual start time.",
"format": "date-time",
"examples": [
"2026-03-30T09:05:00Z"
]
},
"scheduledStart": {
"type": "string",
"description": "Scheduled start time for the route (same as `scheduledFor` on the route).",
"format": "date-time",
"examples": [
"2026-03-30T09:00:00Z"
]
},
"photos": {
"type": "array",
"items": {
"title": "StopAttachment",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Attachment ID (e.g. `\"att-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"att-123e4567-e89b-12d3-a456-426614174000"
]
},
"createdAt": {
"type": "string",
"description": "Timestamp when the attachment was created.",
"format": "date-time",
"examples": [
"2026-03-30T09:05:00Z"
]
},
"url": {
"type": "string",
"description": "URL to fetch the attachment.",
"examples": [
"https://example.com/stop-attachment/attachment-2025-06-03-1"
]
}
},
"description": "An attachment to a stop, such as a proof of delivery photo or signature."
},
"description": "Photos for the route start. Photos may be fetched using the URLs on the\n attachments."
}
},
"description": "The start location of a route and any driver tasks to complete before\n beginning the route."
}
],
"description": "Route start address and tasks."
},
"end": {
"allOf": [
{
"title": "RouteEnd",
"type": "object",
"properties": {
"address": {
"allOf": [
{
"title": "Address",
"type": "object",
"properties": {
"address1": {
"type": "string",
"description": "Street address line 1 (e.g. `\"123 Main St\"`).",
"examples": [
"123 Main St"
]
},
"address2": {
"type": "string",
"description": "Street address line 2 (e.g. `\"Apt 101\"`).",
"examples": [
"Apt 3B"
]
},
"city": {
"type": "string",
"description": "City name (e.g. `\"New York\"`).",
"examples": [
"New York"
]
},
"provinceCode": {
"type": "string",
"description": "Province or state as subdivision codes in\n [ISO 3166-2](https://en.wikipedia.org/wiki/ISO_3166-2) format without the\n country prefix (e.g. `\"NY\"` for New York).",
"examples": [
"NY"
]
},
"countryCode": {
"type": "string",
"description": "Country code (e.g. `\"US\"`).",
"examples": [
"US"
]
},
"zip": {
"type": "string",
"description": "Postal or ZIP code (e.g. `\"10001\"`).",
"examples": [
"10001"
]
}
},
"description": "A physical street address."
}
],
"description": "The end address of the route.",
"examples": [
{
"address1": "123 Main St",
"address2": "Apt 3B",
"city": "New York",
"provinceCode": "NY",
"countryCode": "US",
"zip": "10001"
}
]
},
"tasks": {
"type": "array",
"items": {
"title": "Task",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Task ID (e.g. `\"tsk-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"tsk-123e4567-e89b-12d3-a456-426614174000"
]
},
"title": {
"type": "string",
"description": "Task title (e.g. `\"Delivery checklist\"`).",
"examples": [
"Delivery checklist"
]
},
"type": {
"enum": [
"UNKNOWN",
"CHECKBOXES",
"RADIO_BUTTONS",
"TEXT_INPUT",
"DECIMAL_INPUT",
"SCANNER_INPUT"
],
"type": "string",
"description": "Task type.",
"format": "enum",
"examples": [
"TEXT_INPUT"
]
},
"items": {
"type": "array",
"items": {
"title": "TaskItem",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Item ID (e.g. `\"itm-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"itm-123e4567-e89b-12d3-a456-426614174000"
]
},
"title": {
"type": "string",
"description": "Item title (e.g. `\"Pick up package\"`).",
"examples": [
"Pick up package"
]
},
"complete": {
"type": "boolean",
"description": "Whether the item is completed.",
"examples": [
true
]
},
"updatedAt": {
"type": "string",
"description": "Timestamp when the item was last updated.",
"format": "date-time",
"examples": [
"2026-03-30T13:00:00Z"
]
}
},
"description": "An item within a task. For `CHECKBOXES`, each item on a task may be completed\n independently. For `RADIO_BUTTONS`, at most one item will be completed."
},
"description": "Task items (populated for `CHECKBOXES` and `RADIO_BUTTONS`).",
"examples": [
[]
]
},
"input": {
"allOf": [
{
"title": "TaskInput",
"type": "object",
"properties": {
"value": {
"type": "string",
"description": "Input value.",
"examples": [
"020123456789"
]
},
"updatedAt": {
"type": "string",
"description": "Timestamp when the input was last updated.",
"format": "date-time",
"examples": [
"2026-03-30T13:00:00Z"
]
},
"inputMethod": {
"enum": [
"UNKNOWN",
"SCANNED"
],
"type": "string",
"description": "Whether input was scanned (e.g. a scanned barcode)",
"format": "enum",
"examples": [
"SCANNED"
]
}
},
"description": "Captured driver input for a task. The value may be text for `TEXT_INPUT`\n tasks or a string decimal number for `DECIMAL_INPUT` tasks."
}
],
"description": "Task input (populated for `TEXT_INPUT` and `DECIMAL_INPUT`)."
},
"requiredToMarkStopAsDelivered": {
"type": "boolean",
"description": "Whether the task is required to mark the stop as completed. In the case of\n tasks on `RouteStart`, this represents tasks required for starting the\n route. In the case of tasks on `RouteEnd`, this represents tasks required\n for completing the route.",
"examples": [
true
]
},
"requiredToMarkStopAsAttempted": {
"type": "boolean",
"description": "Whether the task is required to mark the stop as attempted.",
"examples": [
true
]
}
},
"description": "A task to be completed at a stop, or at the start or end of a route. Tasks\n may have one or more items for `CHECKBOXES` or `RADIO_BUTTONS`, or may have\n an input for `TEXT_INPUT` or `DECIMAL_INPUT`."
},
"description": "Tasks to complete before finishing the route."
},
"plannedArrival": {
"type": "string",
"description": "Planned arrival time at the end of the route.",
"format": "date-time",
"examples": [
"2026-03-30T17:00:00Z"
]
},
"distanceMeters": {
"type": "number",
"description": "The distance in meters from the previous stop.",
"format": "double",
"examples": [
1234.56
]
},
"updatedArrival": {
"type": "string",
"description": "Estimated arrival time at the end of the route. If the route is completed,\n this will be the actual arrival time.",
"format": "date-time",
"examples": [
"2026-03-30T17:05:00Z"
]
},
"status": {
"enum": [
"UNKNOWN",
"COMPLETED"
],
"type": "string",
"description": "Status indicating whether the route has been completed.",
"format": "enum",
"examples": [
"COMPLETED"
]
},
"photos": {
"type": "array",
"items": {
"title": "StopAttachment",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Attachment ID (e.g. `\"att-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"att-123e4567-e89b-12d3-a456-426614174000"
]
},
"createdAt": {
"type": "string",
"description": "Timestamp when the attachment was created.",
"format": "date-time",
"examples": [
"2026-03-30T09:05:00Z"
]
},
"url": {
"type": "string",
"description": "URL to fetch the attachment.",
"examples": [
"https://example.com/stop-attachment/attachment-2025-06-03-1"
]
}
},
"description": "An attachment to a stop, such as a proof of delivery photo or signature."
},
"description": "Photos for the route end. Photos may be fetched using the URLs on the\n attachments."
}
},
"description": "The end location of a route and any driver tasks to complete after completing\n the route."
}
],
"description": "Route end address and tasks."
},
"stops": {
"type": "array",
"items": {
"title": "RouteStop",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Stop ID (e.g. `\"rst-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"rst-123e4567-e89b-12d3-a456-426614174000"
]
},
"type": {
"enum": [
"UNKNOWN",
"DELIVERY",
"BREAK",
"PICKUP",
"TASK"
],
"type": "string",
"description": "The type of stop (DELIVERY, BREAK, PICKUP, or TASK).",
"format": "enum",
"examples": [
"DELIVERY"
]
},
"deliveryStatus": {
"enum": [
"UNKNOWN",
"DELIVERED",
"OUT_FOR_DELIVERY",
"ATTEMPTED_DELIVERY",
"READY_FOR_DELIVERY"
],
"type": "string",
"description": "The status for DELIVERY, PICKUP, or TASK stops.",
"format": "enum",
"examples": [
"ATTEMPTED_DELIVERY"
]
},
"breakStatus": {
"enum": [
"UNKNOWN",
"COMPLETED"
],
"type": "string",
"description": "The status for BREAK stops.",
"format": "enum",
"examples": [
"COMPLETED"
]
},
"updatedAt": {
"type": "string",
"description": "Timestamp when the stop status was last updated. Note that this timestamp\n corresponds only to major status updates (i.e. stop marked as DELIVERED).\n Minor updates like task completion or adding proof of delivery will not\n advance this timestamp. For those events, use the timestamps on the task or\n proof of delivery attachment.",
"format": "date-time",
"examples": [
"2026-03-30T13:15:00Z"
]
},
"duration": {
"pattern": "^-?(?:0|[1-9][0-9]{0,11})(?:\\.[0-9]{1,9})?s$",
"type": "string",
"description": "Planned duration of the stop in seconds.",
"examples": [
"300s"
]
},
"plannedArrival": {
"type": "string",
"description": "Planned arrival time at the stop.",
"format": "date-time",
"examples": [
"2026-03-30T13:00:00Z"
]
},
"note": {
"type": "string",
"description": "Top-level note for the stop, as entered manually by route planners,\n inherited from a saved or imported stop, or set by order import automation\n rules.",
"examples": [
"Leave at door."
]
},
"address": {
"allOf": [
{
"title": "Address",
"type": "object",
"properties": {
"address1": {
"type": "string",
"description": "Street address line 1 (e.g. `\"123 Main St\"`).",
"examples": [
"123 Main St"
]
},
"address2": {
"type": "string",
"description": "Street address line 2 (e.g. `\"Apt 101\"`).",
"examples": [
"Apt 3B"
]
},
"city": {
"type": "string",
"description": "City name (e.g. `\"New York\"`).",
"examples": [
"New York"
]
},
"provinceCode": {
"type": "string",
"description": "Province or state as subdivision codes in\n [ISO 3166-2](https://en.wikipedia.org/wiki/ISO_3166-2) format without the\n country prefix (e.g. `\"NY\"` for New York).",
"examples": [
"NY"
]
},
"countryCode": {
"type": "string",
"description": "Country code (e.g. `\"US\"`).",
"examples": [
"US"
]
},
"zip": {
"type": "string",
"description": "Postal or ZIP code (e.g. `\"10001\"`).",
"examples": [
"10001"
]
}
},
"description": "A physical street address."
}
],
"description": "Delivery address for the stop.",
"examples": [
{
"address1": "123 Main St",
"address2": "Apt 3B",
"city": "New York",
"provinceCode": "NY",
"countryCode": "US",
"zip": "10001"
}
]
},
"contact": {
"allOf": [
{
"title": "Contact",
"type": "object",
"properties": {
"firstName": {
"type": "string",
"description": "First name (e.g. `\"John\"`).",
"examples": [
"John"
]
},
"lastName": {
"type": "string",
"description": "Last name (e.g. `\"Doe\"`).",
"examples": [
"Doe"
]
},
"company": {
"type": "string",
"description": "Company name (e.g. `\"Roundtrip Systems Inc\"`).",
"examples": [
"Roundtrip Systems Inc"
]
},
"phone": {
"type": "string",
"description": "Phone number in [E.164 format](https://en.wikipedia.org/wiki/E.164) (e.g.\n `\"+14265551000\"`).",
"examples": [
"+14265551000"
]
},
"email": {
"type": "string",
"description": "Email address (e.g. `\"john.doe@roundtrip.ai\"`)",
"examples": [
"john.doe@roundtrip.ai"
]
}
},
"description": "Contact information for a person or company."
}
],
"description": "Contact information for the stop delivery recipient.",
"examples": [
{
"firstName": "John",
"lastName": "Doe",
"company": "Roundtrip Systems Inc",
"phone": "+14265551000",
"email": "john.doe@roundtrip.ai"
}
]
},
"plannedCoordinates": {
"allOf": [
{
"type": "object",
"properties": {
"latitude": {
"type": "number",
"description": "The latitude in degrees. It must be in the range [-90.0, +90.0].",
"format": "double"
},
"longitude": {
"type": "number",
"description": "The longitude in degrees. It must be in the range [-180.0, +180.0].",
"format": "double"
}
},
"description": "An object that represents a latitude/longitude pair. This is expressed as a\n pair of doubles to represent degrees latitude and degrees longitude. Unless\n specified otherwise, this must conform to the\n WGS84\n standard. Values must be within normalized ranges."
}
],
"description": "Planned coordinates for the stop.",
"examples": [
{
"latitude": 40.7128,
"longitude": -74.006
}
]
},
"items": {
"type": "array",
"items": {
"title": "StopItem",
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "Item name (e.g. `\"Bananas\"`).",
"examples": [
"Bananas"
]
},
"quantity": {
"type": "integer",
"description": "Quantity of the item (e.g. `5`).",
"format": "int32",
"examples": [
5
]
},
"grams": {
"type": "integer",
"description": "Weight of the item in grams (e.g. `500`).",
"format": "int32",
"examples": [
500
]
},
"sku": {
"type": "string",
"description": "Stock keeping unit (e.g. `\"BANANA-001\"`).",
"examples": [
"BANANA-001"
]
}
},
"description": "An item to be delivered at a stop."
},
"description": "Items to deliver at the stop."
},
"source": {
"enum": [
"UNKNOWN",
"SHOPIFY_ORDER",
"SAVED_STOP",
"IMPORTED_STOP"
],
"type": "string",
"description": "The source of the stop, which may be populated for `DELIVERY` stops. The\n source can be a `SHOPIFY_ORDER`, an EasyRoutes `SAVED_STOP`, or an\n `IMPORTED_STOP` from an external source (such as CSV file).",
"format": "enum",
"examples": [
"IMPORTED_STOP"
]
},
"shopifyOrderId": {
"type": "string",
"description": "The Shopify order ID, populated when the stop source is a `SHOPIFY_ORDER`.",
"examples": [
"6229749334323"
]
},
"savedStopId": {
"type": "string",
"description": "The saved stop ID, populated when the stop source is a `SAVED_STOP`.",
"examples": [
"sst-123e4567-e89b-12d3-a456-426614174000"
]
},
"deliveredCoordinates": {
"allOf": [
{
"type": "object",
"properties": {
"latitude": {
"type": "number",
"description": "The latitude in degrees. It must be in the range [-90.0, +90.0].",
"format": "double"
},
"longitude": {
"type": "number",
"description": "The longitude in degrees. It must be in the range [-180.0, +180.0].",
"format": "double"
}
},
"description": "An object that represents a latitude/longitude pair. This is expressed as a\n pair of doubles to represent degrees latitude and degrees longitude. Unless\n specified otherwise, this must conform to the\n WGS84\n standard. Values must be within normalized ranges."
}
],
"description": "Delivered coordinates for the stop."
},
"proofOfDeliveryNote": {
"type": "string",
"description": "Proof of delivery note for the stop.",
"examples": [
"Left at door."
]
},
"proofOfDeliveryPhotos": {
"type": "array",
"items": {
"title": "StopAttachment",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Attachment ID (e.g. `\"att-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"att-123e4567-e89b-12d3-a456-426614174000"
]
},
"createdAt": {
"type": "string",
"description": "Timestamp when the attachment was created.",
"format": "date-time",
"examples": [
"2026-03-30T09:05:00Z"
]
},
"url": {
"type": "string",
"description": "URL to fetch the attachment.",
"examples": [
"https://example.com/stop-attachment/attachment-2025-06-03-1"
]
}
},
"description": "An attachment to a stop, such as a proof of delivery photo or signature."
},
"description": "Proof of delivery photos for the stop. Photos may be fetched using the URLs\n on the attachments."
},
"proofOfDeliverySignatures": {
"type": "array",
"items": {
"title": "StopAttachment",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Attachment ID (e.g. `\"att-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"att-123e4567-e89b-12d3-a456-426614174000"
]
},
"createdAt": {
"type": "string",
"description": "Timestamp when the attachment was created.",
"format": "date-time",
"examples": [
"2026-03-30T09:05:00Z"
]
},
"url": {
"type": "string",
"description": "URL to fetch the attachment.",
"examples": [
"https://example.com/stop-attachment/attachment-2025-06-03-1"
]
}
},
"description": "An attachment to a stop, such as a proof of delivery photo or signature."
},
"description": "Proof of delivery signatures for the stop. Signatures may be fetched using\n the URLs on the attachments."
},
"tasks": {
"type": "array",
"items": {
"title": "Task",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Task ID (e.g. `\"tsk-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"tsk-123e4567-e89b-12d3-a456-426614174000"
]
},
"title": {
"type": "string",
"description": "Task title (e.g. `\"Delivery checklist\"`).",
"examples": [
"Delivery checklist"
]
},
"type": {
"enum": [
"UNKNOWN",
"CHECKBOXES",
"RADIO_BUTTONS",
"TEXT_INPUT",
"DECIMAL_INPUT",
"SCANNER_INPUT"
],
"type": "string",
"description": "Task type.",
"format": "enum",
"examples": [
"TEXT_INPUT"
]
},
"items": {
"type": "array",
"items": {
"title": "TaskItem",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Item ID (e.g. `\"itm-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"itm-123e4567-e89b-12d3-a456-426614174000"
]
},
"title": {
"type": "string",
"description": "Item title (e.g. `\"Pick up package\"`).",
"examples": [
"Pick up package"
]
},
"complete": {
"type": "boolean",
"description": "Whether the item is completed.",
"examples": [
true
]
},
"updatedAt": {
"type": "string",
"description": "Timestamp when the item was last updated.",
"format": "date-time",
"examples": [
"2026-03-30T13:00:00Z"
]
}
},
"description": "An item within a task. For `CHECKBOXES`, each item on a task may be completed\n independently. For `RADIO_BUTTONS`, at most one item will be completed."
},
"description": "Task items (populated for `CHECKBOXES` and `RADIO_BUTTONS`).",
"examples": [
[]
]
},
"input": {
"allOf": [
{
"title": "TaskInput",
"type": "object",
"properties": {
"value": {
"type": "string",
"description": "Input value.",
"examples": [
"020123456789"
]
},
"updatedAt": {
"type": "string",
"description": "Timestamp when the input was last updated.",
"format": "date-time",
"examples": [
"2026-03-30T13:00:00Z"
]
},
"inputMethod": {
"enum": [
"UNKNOWN",
"SCANNED"
],
"type": "string",
"description": "Whether input was scanned (e.g. a scanned barcode)",
"format": "enum",
"examples": [
"SCANNED"
]
}
},
"description": "Captured driver input for a task. The value may be text for `TEXT_INPUT`\n tasks or a string decimal number for `DECIMAL_INPUT` tasks."
}
],
"description": "Task input (populated for `TEXT_INPUT` and `DECIMAL_INPUT`)."
},
"requiredToMarkStopAsDelivered": {
"type": "boolean",
"description": "Whether the task is required to mark the stop as completed. In the case of\n tasks on `RouteStart`, this represents tasks required for starting the\n route. In the case of tasks on `RouteEnd`, this represents tasks required\n for completing the route.",
"examples": [
true
]
},
"requiredToMarkStopAsAttempted": {
"type": "boolean",
"description": "Whether the task is required to mark the stop as attempted.",
"examples": [
true
]
}
},
"description": "A task to be completed at a stop, or at the start or end of a route. Tasks\n may have one or more items for `CHECKBOXES` or `RADIO_BUTTONS`, or may have\n an input for `TEXT_INPUT` or `DECIMAL_INPUT`."
},
"description": "Driver tasks for the stop, including completed items and any input from the\n driver."
},
"priority": {
"maximum": 10,
"type": "integer",
"description": "Priority of the stop for route planning. The valid range for stop priority\n is between `1` (low) and `10` (high), with default priority corresponding\n to a value of `5`. A priority value of `0` is considered unset and is\n treated the same as \"default\" priority. Stops with higher priority will be\n preferred when generating routes with constraints.",
"format": "int32",
"examples": [
8
]
},
"importedStopId": {
"type": "string",
"description": "The imported stop ID, populated when the stop source is `IMPORTED_STOP`.",
"examples": [
"ist-123e4567-e89b-12d3-a456-426614174000"
]
},
"orderName": {
"type": "string",
"description": "The name of the order associated with the stop. For Shopify orders, the\n name is generated by combining the `orderNumber` property with the order\n prefix and suffix that are set in the merchant's general settings. For\n EasyRoutes imported orders, this field is populated with the order name\n provided on import.",
"examples": [
"#1234"
]
},
"distanceMeters": {
"type": "number",
"description": "The distance in meters from the previous stop.",
"format": "double",
"examples": [
123.45
]
},
"updatedArrival": {
"type": "string",
"description": "Estimated arrival time at the stop. If the stop is completed, this will be\n the actual arrival time.",
"format": "date-time",
"examples": [
"2026-03-30T13:05:00Z"
]
},
"timeWindows": {
"type": "array",
"items": {
"title": "TimeWindow",
"type": "object",
"properties": {
"start": {
"allOf": [
{
"title": "TimeOfDay",
"type": "object",
"properties": {
"hours": {
"maximum": 23,
"type": "integer",
"description": "Hours of day in 24 hour format. Must be from 0 to 23.",
"format": "int32",
"examples": [
13
]
},
"minutes": {
"maximum": 59,
"type": "integer",
"description": "Minutes of hour of day. Must be from 0 to 59.",
"format": "int32",
"examples": [
37
]
},
"seconds": {
"maximum": 59,
"type": "integer",
"description": "Seconds of minutes of the time. Must be from 0 to 59.",
"format": "int32",
"examples": [
16
]
}
},
"description": "A time of day, independent of a particular date or timezone."
}
],
"description": "The start time of the time window (optional)."
},
"end": {
"allOf": [
{
"title": "TimeOfDay",
"type": "object",
"properties": {
"hours": {
"maximum": 23,
"type": "integer",
"description": "Hours of day in 24 hour format. Must be from 0 to 23.",
"format": "int32",
"examples": [
13
]
},
"minutes": {
"maximum": 59,
"type": "integer",
"description": "Minutes of hour of day. Must be from 0 to 59.",
"format": "int32",
"examples": [
37
]
},
"seconds": {
"maximum": 59,
"type": "integer",
"description": "Seconds of minutes of the time. Must be from 0 to 59.",
"format": "int32",
"examples": [
16
]
}
},
"description": "A time of day, independent of a particular date or timezone."
}
],
"description": "The end time of the time window (optional)."
}
},
"description": "A time window for a stop. The time window may be open-ended, but one or both\n of the start and end times should be provided. The end time must be >= the\n start time."
},
"description": "The time window for the stop. Note that we currently support at most one\n time window but may support multiple time windows in the future.",
"examples": [
[
{
"start": {
"hours": 9
},
"end": {
"hours": 17
}
}
]
]
},
"deliveryDate": {
"allOf": [
{
"title": "Date",
"required": [
"year",
"month",
"day"
],
"type": "object",
"properties": {
"year": {
"maximum": 9999,
"minimum": 1,
"type": "integer",
"description": "Year of the date. Must be from 1 to 9999.",
"format": "int32",
"examples": [
2019
]
},
"month": {
"maximum": 12,
"minimum": 1,
"type": "integer",
"description": "Month of a year. Must be from 1 to 12.",
"format": "int32",
"examples": [
11
]
},
"day": {
"maximum": 31,
"minimum": 1,
"type": "integer",
"description": "Day of a month. Must be from 1 to 31.",
"format": "int32",
"examples": [
15
]
}
},
"description": "A date in year-month-day format."
}
],
"description": "The planned delivery date for the stop.",
"examples": [
{
"year": 2025,
"month": 12,
"day": 16
}
]
},
"attributes": {
"type": "array",
"items": {
"title": "Attribute",
"type": "object",
"properties": {
"key": {
"type": "string",
"description": "Attribute key. Must be non-empty.",
"examples": [
"delivery_date"
]
},
"value": {
"type": "string",
"description": "Attribute value.",
"examples": [
"2025-12-16"
]
}
},
"description": "A key-value pair for storing additional information on a stop, such as order\n details, delivery instructions, or custom fields."
},
"description": "Additional attributes for the stop. Attributes are key-value pairs for\n storing additional structured data on stops. These may be populated from\n the Shopify order or set on import.",
"examples": [
[
{
"key": "color",
"value": "blue"
}
]
]
},
"clientStopId": {
"type": "string",
"description": "The client-provided ID associated with the stop, if provided on import.",
"examples": [
"test-order-1234"
]
},
"tags": {
"type": "array",
"items": {
"type": "string"
},
"description": "The tags for the stop. Tags are used to categorize stops and can be used\n for filtering and grouping stops in the EasyRoutes web app. These may be\n populated from the Shopify order or set on import.",
"examples": [
[
"foo",
"bar"
]
]
},
"attemptedReason": {
"enum": [
"UNKNOWN",
"NOT_AVAILABLE",
"ACCESS_DENIED",
"INCORRECT_ADDRESS",
"SAFE_PLACE_UNAVAILABLE",
"REFUSED",
"EXTERNAL",
"INCORRECT_ITEMS",
"OTHER",
"CANCELED"
],
"type": "string",
"description": "The reason for marking the stop as attempted. This is only populated when\n `deliveryStatus = ATTEMPTED_DELIVERY`.",
"format": "enum",
"examples": [
"NOT_AVAILABLE"
]
},
"attemptedNote": {
"type": "string",
"description": "Optional note related to the reason for marking the stop as attempted. This\n is optionally populated when `deliveryStatus = ATTEMPTED_DELIVERY`.",
"examples": [
"Customer did not answer the door."
]
},
"customerRating": {
"allOf": [
{
"title": "CustomerRating",
"type": "object",
"properties": {
"rating": {
"maximum": 5,
"minimum": 1,
"type": "integer",
"description": "Rating from 1-5",
"format": "int32",
"examples": [
5
]
},
"comment": {
"type": "string",
"description": "Customer comment related to rating",
"examples": [
"Excellent delivery"
]
},
"createdAt": {
"type": "string",
"description": "Timestamp when rating was left by customer.",
"format": "date-time",
"examples": [
"2026-03-30T18:00:00Z"
]
}
},
"description": "Customer rating and feedback left on a stop."
}
],
"description": "Rating left by customer. This can only be populated once `deliveryStatus =\n DELIVERED`."
},
"customSignatureDisclosure": {
"type": "string",
"description": "Optional custom signature disclosure that is shown to customers in the\n driver app.",
"examples": [
"I acknowledge that I have received this delivery."
]
},
"shopifyOrder": {
"allOf": [
{
"title": "ShopifyOrder",
"type": "object",
"properties": {
"orderNote": {
"type": "string",
"description": "The Shopify order note.",
"examples": [
"Customer has paid."
]
},
"customerNote": {
"type": "string",
"description": "The Shopify customer note for the order.",
"examples": [
"Leave at door."
]
}
},
"description": "Shopify-specific information for a RouteStop."
}
],
"description": "Information from the associated Shopify order, if applicable. Populated if\n stop source is `SHOPIFY_ORDER`"
},
"proofOfDeliveryBarcodes": {
"type": "array",
"items": {
"title": "ScannedBarcode",
"type": "object",
"properties": {
"value": {
"type": "string",
"description": "Barcode value (e.g. `\"123456789012\"`).",
"examples": [
"123456789012"
]
},
"createdAt": {
"type": "string",
"description": "Timestamp when the barcode was scanned.",
"format": "date-time",
"examples": [
"2026-03-30T13:10:00Z"
]
}
},
"description": "A proof of delivery barcode scanned at a stop."
},
"description": "Proof of delivery barcodes scanned at the stop."
},
"proofOfDeliveryBarcodeIssues": {
"type": "array",
"items": {
"title": "ScannedBarcodeIssue",
"type": "object",
"properties": {
"reason": {
"enum": [
"UNKNOWN",
"ITEM_MISSING",
"NOT_SCANNABLE",
"INCORRECT"
],
"type": "string",
"description": "The reported reason for the barcode issue.",
"format": "enum",
"examples": [
"ITEM_MISSING"
]
},
"note": {
"type": "string",
"description": "Optional note related to the reason for reporting a barcode issue.",
"examples": [
"Item was not packed."
]
},
"createdAt": {
"type": "string",
"description": "Timestamp when the issue was reported.",
"format": "date-time",
"examples": [
"2026-03-30T13:10:00Z"
]
}
},
"description": "A reported issue related to scanning barcodes at a stop."
},
"description": "Proof of delivery barcode issues reported at the stop."
},
"orderReferenceUrl": {
"type": "string",
"description": "A reference URL for the order associated with the stop (e.g. a link to the\n order in your order management system). Must be a valid HTTPS URL. This\n field can only be populated for imported stops.",
"examples": [
"https://orders.example.com/orders/148977776"
]
}
},
"description": "A stop on a route. A stop may correspond to a delivery or a driver break as\n determined by the type. A delivery stop will have location and contact\n information, items to deliver, optional order details, status, arrival time\n and stop duration, driver tasks and any proof of delivery information. A\n break stop will have start time and duration, and status."
},
"description": "Route stops. See RouteStop for stop fields."
},
"createdAt": {
"type": "string",
"description": "Timestamp when the route was created.",
"format": "date-time",
"examples": [
"2026-03-29T08:00:00Z"
]
},
"updatedAt": {
"type": "string",
"description": "Timestamp when the route was last updated (by the planner).",
"format": "date-time",
"examples": [
"2026-03-30T13:15:00Z"
]
},
"archivedAt": {
"type": "string",
"description": "Timestamp when the route was archived.",
"format": "date-time",
"examples": [
"2026-04-05T00:00:00Z"
]
},
"scheduledFor": {
"type": "string",
"description": "Timestamp when the route is scheduled for.",
"format": "date-time",
"examples": [
"2026-03-30T09:00:00Z"
]
},
"totalDistanceMeters": {
"type": "number",
"description": "The distance in meters for the entire route.",
"format": "double",
"examples": [
2387.2
]
},
"totalItemQuantity": {
"type": "integer",
"description": "The total quantity of items to deliver on the route.",
"format": "int32",
"examples": [
50
]
},
"totalItemGrams": {
"type": "string",
"description": "The total weight in grams for the items on the route.",
"examples": [
"6000"
]
},
"optimized": {
"type": "boolean",
"description": "Whether the route has been optimized. Adding or removing stops, reordering\n stops, or changing route options generally set this field to false until\n the route is reoptimized.",
"examples": [
true
]
},
"dispatchedUntil": {
"type": "string",
"description": "Timestamp until which the route is dispatched and accessible in the driver\n app.",
"format": "date-time",
"examples": [
"2026-03-30T20:00:00Z"
]
},
"note": {
"type": "string",
"description": "Top-level note for the route, as entered manually by route planners.",
"examples": [
"Fragile items."
]
},
"tags": {
"type": "array",
"items": {
"type": "string"
},
"description": "The tags for the route. Tags are used to categorize routes and can be\n used for filtering and grouping routes in the EasyRoutes web app.",
"examples": [
[
"foo",
"bar"
]
]
},
"defaultStopDuration": {
"pattern": "^-?(?:0|[1-9][0-9]{0,11})(?:\\.[0-9]{1,9})?s$",
"type": "string",
"description": "The default duration for stops on the route. Used to estimate arrival\n times for stops that do not have their own duration specified.\n Specified as a duration string in the format \"300s\" for 5 minutes, \"60s\"\n for 1 minute, etc.",
"examples": [
"300s"
]
},
"maxDuration": {
"pattern": "^-?(?:0|[1-9][0-9]{0,11})(?:\\.[0-9]{1,9})?s$",
"type": "string",
"description": "The maximum duration of the route. Specified as a duration string in the\n format \"3600s\" for 1 hour, \"7200s\" for 2 hours, etc.",
"examples": [
"28800s"
]
},
"maxStops": {
"type": "integer",
"description": "The maximum number of stops on the route.",
"format": "int32",
"examples": [
50
]
},
"maxItemCount": {
"type": "integer",
"description": "The maximum total item count across all stops on the route.",
"format": "int32",
"examples": [
200
]
},
"maxKilograms": {
"type": "number",
"description": "The maximum total weight in kilograms across all stops on the route.",
"format": "double",
"examples": [
500
]
},
"avoidTolls": {
"type": "boolean",
"description": "Whether to avoid toll roads during optimization.",
"examples": [
true
]
},
"avoidUTurns": {
"type": "boolean",
"description": "Whether to avoid U-turns during optimization.",
"examples": [
true
]
},
"speedFactor": {
"type": "number",
"description": "A speed factor for the route used during optimization to adjust estimated\n travel times. A value of 1.0 represents normal speed. Values less than 1.0\n indicate slower travel (e.g. 0.5 = half speed), and values greater than\n 1.0 indicate faster travel (e.g. 1.5 = 50% faster). Must be between 0.1\n and 1.9. A value of 0 (or unset) uses the default speed.",
"format": "double",
"examples": [
0.8
]
},
"vehicle": {
"allOf": [
{
"title": "Vehicle",
"required": [
"id"
],
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Vehicle ID.",
"examples": [
"veh-123e4567-e89b-12d3-a456-426614174000"
]
},
"name": {
"type": "string",
"description": "Vehicle name.",
"examples": [
"Delivery Van 1"
]
},
"make": {
"type": "string",
"description": "Vehicle make.",
"examples": [
"Ford"
]
},
"model": {
"type": "string",
"description": "Vehicle model.",
"examples": [
"Transit"
]
},
"year": {
"type": "integer",
"description": "Vehicle model year.",
"format": "int32",
"examples": [
2023
]
},
"type": {
"enum": [
"UNKNOWN",
"CAR",
"CARGO_VAN",
"PICKUP_TRUCK",
"BOX_TRUCK",
"MOTORCYCLE",
"BICYCLE",
"DRONE",
"OTHER"
],
"type": "string",
"description": "Vehicle type.",
"format": "enum",
"examples": [
"CARGO_VAN"
]
},
"vin": {
"type": "string",
"description": "Vehicle Identification Number.",
"examples": [
"1FTBW2CM5NKA12345"
]
},
"license": {
"type": "string",
"description": "Vehicle license plate.",
"examples": [
"ABC-1234"
]
},
"isArchived": {
"type": "boolean",
"description": "Whether the vehicle is archived.",
"examples": [
false
]
},
"createdTimestamp": {
"type": "string",
"description": "Timestamp when the vehicle was created.",
"format": "date-time",
"examples": [
"2026-07-30T12:00:00Z"
]
}
},
"description": "A vehicle that can be assigned to a route."
}
],
"description": "Assigned vehicle for the route."
}
},
"description": "A route of stops, optionally with an assigned driver."
}
}
}
},
"default": {
"description": "Default error response",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"code": {
"type": "integer",
"description": "The status code, which should be an enum value of [google.rpc.Code][google.rpc.Code].",
"format": "int32"
},
"message": {
"type": "string",
"description": "A developer-facing error message, which should be in English. Any user-facing error message should be localized and sent in the [google.rpc.Status.details][google.rpc.Status.details] field, or localized by the client."
},
"details": {
"type": "array",
"items": {
"type": "object",
"properties": {
"@type": {
"type": "string",
"description": "The type of the serialized message."
}
},
"additionalProperties": true,
"description": "Contains an arbitrary serialized message along with a @type that describes the type of the serialized message."
},
"description": "A list of messages that carry the error details. There is a common set of message types for APIs to use."
}
},
"description": "The `Status` type defines a logical error model that is suitable for different programming environments, including REST APIs and RPC APIs. It is used by [gRPC](https://github.com/grpc). Each `Status` message contains three pieces of data: error code, error message, and error details. You can find out more about this error model and how to work with it in the [API Design Guide](https://cloud.google.com/apis/design/errors)."
}
}
}
}
},
"security": [
{
"bearerAuth": []
}
],
"components": {
"securitySchemes": {
"bearerAuth": {
"type": "http",
"description": "Access token from `/authenticate`",
"scheme": "bearer",
"bearerFormat": "JWT"
}
}
}
}
```
# Delete imported stop (https://docs.roundtrip.ai/docs/api-reference/stops/delete-stops-imports-id)
DELETE /stops/imports/{id}
Delete an imported stop by ID. The ID can be the EasyRoutes `id` returned
on import or the client-provided `clientStopId`.
## OpenAPI specification
```json
{
"servers": [
{
"url": "https://easyroutes.roundtrip.ai/api/2024-07"
}
],
"tags": [
"Stops"
],
"summary": "Delete imported stop",
"description": "Delete an imported stop by ID. The ID can be the EasyRoutes `id` returned\n on import or the client-provided `clientStopId`.",
"operationId": "DeleteImportedStop",
"parameters": [
{
"name": "id",
"in": "path",
"description": "The ID of the imported stop to delete. You provide the EasyRoutes `id`\n returned on import or the client-provided `clientStopId`.",
"required": true,
"schema": {
"type": "string",
"examples": [
"ist-123e4567-e89b-12d3-a456-426614174000"
]
}
},
{
"name": "Idempotency-Key",
"in": "header",
"description": "A unique key for safely retrying this operation. For more information read [our guide](https://docs.roundtrip.ai/docs/concepts/idempotency.md).",
"schema": {
"maxLength": 255,
"minLength": 1,
"type": "string"
},
"examples": {
"default": {
"value": "550e8400-e29b-41d4-a716-446655440000"
}
}
}
],
"responses": {
"200": {
"description": "OK",
"headers": {
"Idempotency-Key": {
"description": "The idempotency key associated with the response.",
"schema": {
"type": "string"
}
},
"Idempotency-Replayed": {
"description": "Whether the response was replayed from a previous request.",
"schema": {
"type": "boolean"
}
}
},
"content": {}
},
"default": {
"description": "Default error response",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"code": {
"type": "integer",
"description": "The status code, which should be an enum value of [google.rpc.Code][google.rpc.Code].",
"format": "int32"
},
"message": {
"type": "string",
"description": "A developer-facing error message, which should be in English. Any user-facing error message should be localized and sent in the [google.rpc.Status.details][google.rpc.Status.details] field, or localized by the client."
},
"details": {
"type": "array",
"items": {
"type": "object",
"properties": {
"@type": {
"type": "string",
"description": "The type of the serialized message."
}
},
"additionalProperties": true,
"description": "Contains an arbitrary serialized message along with a @type that describes the type of the serialized message."
},
"description": "A list of messages that carry the error details. There is a common set of message types for APIs to use."
}
},
"description": "The `Status` type defines a logical error model that is suitable for different programming environments, including REST APIs and RPC APIs. It is used by [gRPC](https://github.com/grpc). Each `Status` message contains three pieces of data: error code, error message, and error details. You can find out more about this error model and how to work with it in the [API Design Guide](https://cloud.google.com/apis/design/errors)."
}
}
}
}
},
"security": [
{
"bearerAuth": []
}
],
"components": {
"securitySchemes": {
"bearerAuth": {
"type": "http",
"description": "Access token from `/authenticate`",
"scheme": "bearer",
"bearerFormat": "JWT"
}
}
}
}
```
# Get route stop (https://docs.roundtrip.ai/docs/api-reference/stops/get-routes-routeId-stops-stopId)
GET /routes/{routeId}/stops/{stopId}
Fetch a single stop on a route by route ID and stop ID. A route stop can be
created from a Shopify order or a copy of an imported stop that has been
added to a route and may have additional route-specific information, such
as status. It can also be a break or a custom stop that is not associated
with an imported stop.
## OpenAPI specification
```json
{
"servers": [
{
"url": "https://easyroutes.roundtrip.ai/api/2024-07"
}
],
"tags": [
"Stops"
],
"summary": "Get route stop",
"description": "Fetch a single stop on a route by route ID and stop ID. A route stop can be\n created from a Shopify order or a copy of an imported stop that has been\n added to a route and may have additional route-specific information, such\n as status. It can also be a break or a custom stop that is not associated\n with an imported stop.",
"operationId": "GetRouteStop",
"parameters": [
{
"name": "routeId",
"in": "path",
"description": "The route ID containing the stop.",
"required": true,
"schema": {
"type": "string",
"examples": [
"rte-123e4567-e89b-12d3-a456-426614174000"
]
}
},
{
"name": "stopId",
"in": "path",
"description": "The stop ID to fetch.",
"required": true,
"schema": {
"type": "string",
"examples": [
"rst-123e4567-e89b-12d3-a456-426614174000"
]
}
}
],
"responses": {
"200": {
"description": "OK",
"content": {
"application/json": {
"schema": {
"title": "RouteStop",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Stop ID (e.g. `\"rst-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"rst-123e4567-e89b-12d3-a456-426614174000"
]
},
"type": {
"enum": [
"UNKNOWN",
"DELIVERY",
"BREAK",
"PICKUP",
"TASK"
],
"type": "string",
"description": "The type of stop (DELIVERY, BREAK, PICKUP, or TASK).",
"format": "enum",
"examples": [
"DELIVERY"
]
},
"deliveryStatus": {
"enum": [
"UNKNOWN",
"DELIVERED",
"OUT_FOR_DELIVERY",
"ATTEMPTED_DELIVERY",
"READY_FOR_DELIVERY"
],
"type": "string",
"description": "The status for DELIVERY, PICKUP, or TASK stops.",
"format": "enum",
"examples": [
"ATTEMPTED_DELIVERY"
]
},
"breakStatus": {
"enum": [
"UNKNOWN",
"COMPLETED"
],
"type": "string",
"description": "The status for BREAK stops.",
"format": "enum",
"examples": [
"COMPLETED"
]
},
"updatedAt": {
"type": "string",
"description": "Timestamp when the stop status was last updated. Note that this timestamp\n corresponds only to major status updates (i.e. stop marked as DELIVERED).\n Minor updates like task completion or adding proof of delivery will not\n advance this timestamp. For those events, use the timestamps on the task or\n proof of delivery attachment.",
"format": "date-time",
"examples": [
"2026-03-30T13:15:00Z"
]
},
"duration": {
"pattern": "^-?(?:0|[1-9][0-9]{0,11})(?:\\.[0-9]{1,9})?s$",
"type": "string",
"description": "Planned duration of the stop in seconds.",
"examples": [
"300s"
]
},
"plannedArrival": {
"type": "string",
"description": "Planned arrival time at the stop.",
"format": "date-time",
"examples": [
"2026-03-30T13:00:00Z"
]
},
"note": {
"type": "string",
"description": "Top-level note for the stop, as entered manually by route planners,\n inherited from a saved or imported stop, or set by order import automation\n rules.",
"examples": [
"Leave at door."
]
},
"address": {
"allOf": [
{
"title": "Address",
"type": "object",
"properties": {
"address1": {
"type": "string",
"description": "Street address line 1 (e.g. `\"123 Main St\"`).",
"examples": [
"123 Main St"
]
},
"address2": {
"type": "string",
"description": "Street address line 2 (e.g. `\"Apt 101\"`).",
"examples": [
"Apt 3B"
]
},
"city": {
"type": "string",
"description": "City name (e.g. `\"New York\"`).",
"examples": [
"New York"
]
},
"provinceCode": {
"type": "string",
"description": "Province or state as subdivision codes in\n [ISO 3166-2](https://en.wikipedia.org/wiki/ISO_3166-2) format without the\n country prefix (e.g. `\"NY\"` for New York).",
"examples": [
"NY"
]
},
"countryCode": {
"type": "string",
"description": "Country code (e.g. `\"US\"`).",
"examples": [
"US"
]
},
"zip": {
"type": "string",
"description": "Postal or ZIP code (e.g. `\"10001\"`).",
"examples": [
"10001"
]
}
},
"description": "A physical street address."
}
],
"description": "Delivery address for the stop.",
"examples": [
{
"address1": "123 Main St",
"address2": "Apt 3B",
"city": "New York",
"provinceCode": "NY",
"countryCode": "US",
"zip": "10001"
}
]
},
"contact": {
"allOf": [
{
"title": "Contact",
"type": "object",
"properties": {
"firstName": {
"type": "string",
"description": "First name (e.g. `\"John\"`).",
"examples": [
"John"
]
},
"lastName": {
"type": "string",
"description": "Last name (e.g. `\"Doe\"`).",
"examples": [
"Doe"
]
},
"company": {
"type": "string",
"description": "Company name (e.g. `\"Roundtrip Systems Inc\"`).",
"examples": [
"Roundtrip Systems Inc"
]
},
"phone": {
"type": "string",
"description": "Phone number in [E.164 format](https://en.wikipedia.org/wiki/E.164) (e.g.\n `\"+14265551000\"`).",
"examples": [
"+14265551000"
]
},
"email": {
"type": "string",
"description": "Email address (e.g. `\"john.doe@roundtrip.ai\"`)",
"examples": [
"john.doe@roundtrip.ai"
]
}
},
"description": "Contact information for a person or company."
}
],
"description": "Contact information for the stop delivery recipient.",
"examples": [
{
"firstName": "John",
"lastName": "Doe",
"company": "Roundtrip Systems Inc",
"phone": "+14265551000",
"email": "john.doe@roundtrip.ai"
}
]
},
"plannedCoordinates": {
"allOf": [
{
"type": "object",
"properties": {
"latitude": {
"type": "number",
"description": "The latitude in degrees. It must be in the range [-90.0, +90.0].",
"format": "double"
},
"longitude": {
"type": "number",
"description": "The longitude in degrees. It must be in the range [-180.0, +180.0].",
"format": "double"
}
},
"description": "An object that represents a latitude/longitude pair. This is expressed as a\n pair of doubles to represent degrees latitude and degrees longitude. Unless\n specified otherwise, this must conform to the\n WGS84\n standard. Values must be within normalized ranges."
}
],
"description": "Planned coordinates for the stop.",
"examples": [
{
"latitude": 40.7128,
"longitude": -74.006
}
]
},
"items": {
"type": "array",
"items": {
"title": "StopItem",
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "Item name (e.g. `\"Bananas\"`).",
"examples": [
"Bananas"
]
},
"quantity": {
"type": "integer",
"description": "Quantity of the item (e.g. `5`).",
"format": "int32",
"examples": [
5
]
},
"grams": {
"type": "integer",
"description": "Weight of the item in grams (e.g. `500`).",
"format": "int32",
"examples": [
500
]
},
"sku": {
"type": "string",
"description": "Stock keeping unit (e.g. `\"BANANA-001\"`).",
"examples": [
"BANANA-001"
]
}
},
"description": "An item to be delivered at a stop."
},
"description": "Items to deliver at the stop."
},
"source": {
"enum": [
"UNKNOWN",
"SHOPIFY_ORDER",
"SAVED_STOP",
"IMPORTED_STOP"
],
"type": "string",
"description": "The source of the stop, which may be populated for `DELIVERY` stops. The\n source can be a `SHOPIFY_ORDER`, an EasyRoutes `SAVED_STOP`, or an\n `IMPORTED_STOP` from an external source (such as CSV file).",
"format": "enum",
"examples": [
"IMPORTED_STOP"
]
},
"shopifyOrderId": {
"type": "string",
"description": "The Shopify order ID, populated when the stop source is a `SHOPIFY_ORDER`.",
"examples": [
"6229749334323"
]
},
"savedStopId": {
"type": "string",
"description": "The saved stop ID, populated when the stop source is a `SAVED_STOP`.",
"examples": [
"sst-123e4567-e89b-12d3-a456-426614174000"
]
},
"deliveredCoordinates": {
"allOf": [
{
"type": "object",
"properties": {
"latitude": {
"type": "number",
"description": "The latitude in degrees. It must be in the range [-90.0, +90.0].",
"format": "double"
},
"longitude": {
"type": "number",
"description": "The longitude in degrees. It must be in the range [-180.0, +180.0].",
"format": "double"
}
},
"description": "An object that represents a latitude/longitude pair. This is expressed as a\n pair of doubles to represent degrees latitude and degrees longitude. Unless\n specified otherwise, this must conform to the\n WGS84\n standard. Values must be within normalized ranges."
}
],
"description": "Delivered coordinates for the stop."
},
"proofOfDeliveryNote": {
"type": "string",
"description": "Proof of delivery note for the stop.",
"examples": [
"Left at door."
]
},
"proofOfDeliveryPhotos": {
"type": "array",
"items": {
"title": "StopAttachment",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Attachment ID (e.g. `\"att-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"att-123e4567-e89b-12d3-a456-426614174000"
]
},
"createdAt": {
"type": "string",
"description": "Timestamp when the attachment was created.",
"format": "date-time",
"examples": [
"2026-03-30T09:05:00Z"
]
},
"url": {
"type": "string",
"description": "URL to fetch the attachment.",
"examples": [
"https://example.com/stop-attachment/attachment-2025-06-03-1"
]
}
},
"description": "An attachment to a stop, such as a proof of delivery photo or signature."
},
"description": "Proof of delivery photos for the stop. Photos may be fetched using the URLs\n on the attachments."
},
"proofOfDeliverySignatures": {
"type": "array",
"items": {
"title": "StopAttachment",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Attachment ID (e.g. `\"att-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"att-123e4567-e89b-12d3-a456-426614174000"
]
},
"createdAt": {
"type": "string",
"description": "Timestamp when the attachment was created.",
"format": "date-time",
"examples": [
"2026-03-30T09:05:00Z"
]
},
"url": {
"type": "string",
"description": "URL to fetch the attachment.",
"examples": [
"https://example.com/stop-attachment/attachment-2025-06-03-1"
]
}
},
"description": "An attachment to a stop, such as a proof of delivery photo or signature."
},
"description": "Proof of delivery signatures for the stop. Signatures may be fetched using\n the URLs on the attachments."
},
"tasks": {
"type": "array",
"items": {
"title": "Task",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Task ID (e.g. `\"tsk-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"tsk-123e4567-e89b-12d3-a456-426614174000"
]
},
"title": {
"type": "string",
"description": "Task title (e.g. `\"Delivery checklist\"`).",
"examples": [
"Delivery checklist"
]
},
"type": {
"enum": [
"UNKNOWN",
"CHECKBOXES",
"RADIO_BUTTONS",
"TEXT_INPUT",
"DECIMAL_INPUT",
"SCANNER_INPUT"
],
"type": "string",
"description": "Task type.",
"format": "enum",
"examples": [
"TEXT_INPUT"
]
},
"items": {
"type": "array",
"items": {
"title": "TaskItem",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Item ID (e.g. `\"itm-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"itm-123e4567-e89b-12d3-a456-426614174000"
]
},
"title": {
"type": "string",
"description": "Item title (e.g. `\"Pick up package\"`).",
"examples": [
"Pick up package"
]
},
"complete": {
"type": "boolean",
"description": "Whether the item is completed.",
"examples": [
true
]
},
"updatedAt": {
"type": "string",
"description": "Timestamp when the item was last updated.",
"format": "date-time",
"examples": [
"2026-03-30T13:00:00Z"
]
}
},
"description": "An item within a task. For `CHECKBOXES`, each item on a task may be completed\n independently. For `RADIO_BUTTONS`, at most one item will be completed."
},
"description": "Task items (populated for `CHECKBOXES` and `RADIO_BUTTONS`).",
"examples": [
[]
]
},
"input": {
"allOf": [
{
"title": "TaskInput",
"type": "object",
"properties": {
"value": {
"type": "string",
"description": "Input value.",
"examples": [
"020123456789"
]
},
"updatedAt": {
"type": "string",
"description": "Timestamp when the input was last updated.",
"format": "date-time",
"examples": [
"2026-03-30T13:00:00Z"
]
},
"inputMethod": {
"enum": [
"UNKNOWN",
"SCANNED"
],
"type": "string",
"description": "Whether input was scanned (e.g. a scanned barcode)",
"format": "enum",
"examples": [
"SCANNED"
]
}
},
"description": "Captured driver input for a task. The value may be text for `TEXT_INPUT`\n tasks or a string decimal number for `DECIMAL_INPUT` tasks."
}
],
"description": "Task input (populated for `TEXT_INPUT` and `DECIMAL_INPUT`)."
},
"requiredToMarkStopAsDelivered": {
"type": "boolean",
"description": "Whether the task is required to mark the stop as completed. In the case of\n tasks on `RouteStart`, this represents tasks required for starting the\n route. In the case of tasks on `RouteEnd`, this represents tasks required\n for completing the route.",
"examples": [
true
]
},
"requiredToMarkStopAsAttempted": {
"type": "boolean",
"description": "Whether the task is required to mark the stop as attempted.",
"examples": [
true
]
}
},
"description": "A task to be completed at a stop, or at the start or end of a route. Tasks\n may have one or more items for `CHECKBOXES` or `RADIO_BUTTONS`, or may have\n an input for `TEXT_INPUT` or `DECIMAL_INPUT`."
},
"description": "Driver tasks for the stop, including completed items and any input from the\n driver."
},
"priority": {
"maximum": 10,
"type": "integer",
"description": "Priority of the stop for route planning. The valid range for stop priority\n is between `1` (low) and `10` (high), with default priority corresponding\n to a value of `5`. A priority value of `0` is considered unset and is\n treated the same as \"default\" priority. Stops with higher priority will be\n preferred when generating routes with constraints.",
"format": "int32",
"examples": [
8
]
},
"importedStopId": {
"type": "string",
"description": "The imported stop ID, populated when the stop source is `IMPORTED_STOP`.",
"examples": [
"ist-123e4567-e89b-12d3-a456-426614174000"
]
},
"orderName": {
"type": "string",
"description": "The name of the order associated with the stop. For Shopify orders, the\n name is generated by combining the `orderNumber` property with the order\n prefix and suffix that are set in the merchant's general settings. For\n EasyRoutes imported orders, this field is populated with the order name\n provided on import.",
"examples": [
"#1234"
]
},
"distanceMeters": {
"type": "number",
"description": "The distance in meters from the previous stop.",
"format": "double",
"examples": [
123.45
]
},
"updatedArrival": {
"type": "string",
"description": "Estimated arrival time at the stop. If the stop is completed, this will be\n the actual arrival time.",
"format": "date-time",
"examples": [
"2026-03-30T13:05:00Z"
]
},
"timeWindows": {
"type": "array",
"items": {
"title": "TimeWindow",
"type": "object",
"properties": {
"start": {
"allOf": [
{
"title": "TimeOfDay",
"type": "object",
"properties": {
"hours": {
"maximum": 23,
"type": "integer",
"description": "Hours of day in 24 hour format. Must be from 0 to 23.",
"format": "int32",
"examples": [
13
]
},
"minutes": {
"maximum": 59,
"type": "integer",
"description": "Minutes of hour of day. Must be from 0 to 59.",
"format": "int32",
"examples": [
37
]
},
"seconds": {
"maximum": 59,
"type": "integer",
"description": "Seconds of minutes of the time. Must be from 0 to 59.",
"format": "int32",
"examples": [
16
]
}
},
"description": "A time of day, independent of a particular date or timezone."
}
],
"description": "The start time of the time window (optional)."
},
"end": {
"allOf": [
{
"title": "TimeOfDay",
"type": "object",
"properties": {
"hours": {
"maximum": 23,
"type": "integer",
"description": "Hours of day in 24 hour format. Must be from 0 to 23.",
"format": "int32",
"examples": [
13
]
},
"minutes": {
"maximum": 59,
"type": "integer",
"description": "Minutes of hour of day. Must be from 0 to 59.",
"format": "int32",
"examples": [
37
]
},
"seconds": {
"maximum": 59,
"type": "integer",
"description": "Seconds of minutes of the time. Must be from 0 to 59.",
"format": "int32",
"examples": [
16
]
}
},
"description": "A time of day, independent of a particular date or timezone."
}
],
"description": "The end time of the time window (optional)."
}
},
"description": "A time window for a stop. The time window may be open-ended, but one or both\n of the start and end times should be provided. The end time must be >= the\n start time."
},
"description": "The time window for the stop. Note that we currently support at most one\n time window but may support multiple time windows in the future.",
"examples": [
[
{
"start": {
"hours": 9
},
"end": {
"hours": 17
}
}
]
]
},
"deliveryDate": {
"allOf": [
{
"title": "Date",
"required": [
"year",
"month",
"day"
],
"type": "object",
"properties": {
"year": {
"maximum": 9999,
"minimum": 1,
"type": "integer",
"description": "Year of the date. Must be from 1 to 9999.",
"format": "int32",
"examples": [
2019
]
},
"month": {
"maximum": 12,
"minimum": 1,
"type": "integer",
"description": "Month of a year. Must be from 1 to 12.",
"format": "int32",
"examples": [
11
]
},
"day": {
"maximum": 31,
"minimum": 1,
"type": "integer",
"description": "Day of a month. Must be from 1 to 31.",
"format": "int32",
"examples": [
15
]
}
},
"description": "A date in year-month-day format."
}
],
"description": "The planned delivery date for the stop.",
"examples": [
{
"year": 2025,
"month": 12,
"day": 16
}
]
},
"attributes": {
"type": "array",
"items": {
"title": "Attribute",
"type": "object",
"properties": {
"key": {
"type": "string",
"description": "Attribute key. Must be non-empty.",
"examples": [
"delivery_date"
]
},
"value": {
"type": "string",
"description": "Attribute value.",
"examples": [
"2025-12-16"
]
}
},
"description": "A key-value pair for storing additional information on a stop, such as order\n details, delivery instructions, or custom fields."
},
"description": "Additional attributes for the stop. Attributes are key-value pairs for\n storing additional structured data on stops. These may be populated from\n the Shopify order or set on import.",
"examples": [
[
{
"key": "color",
"value": "blue"
}
]
]
},
"clientStopId": {
"type": "string",
"description": "The client-provided ID associated with the stop, if provided on import.",
"examples": [
"test-order-1234"
]
},
"tags": {
"type": "array",
"items": {
"type": "string"
},
"description": "The tags for the stop. Tags are used to categorize stops and can be used\n for filtering and grouping stops in the EasyRoutes web app. These may be\n populated from the Shopify order or set on import.",
"examples": [
[
"foo",
"bar"
]
]
},
"attemptedReason": {
"enum": [
"UNKNOWN",
"NOT_AVAILABLE",
"ACCESS_DENIED",
"INCORRECT_ADDRESS",
"SAFE_PLACE_UNAVAILABLE",
"REFUSED",
"EXTERNAL",
"INCORRECT_ITEMS",
"OTHER",
"CANCELED"
],
"type": "string",
"description": "The reason for marking the stop as attempted. This is only populated when\n `deliveryStatus = ATTEMPTED_DELIVERY`.",
"format": "enum",
"examples": [
"NOT_AVAILABLE"
]
},
"attemptedNote": {
"type": "string",
"description": "Optional note related to the reason for marking the stop as attempted. This\n is optionally populated when `deliveryStatus = ATTEMPTED_DELIVERY`.",
"examples": [
"Customer did not answer the door."
]
},
"customerRating": {
"allOf": [
{
"title": "CustomerRating",
"type": "object",
"properties": {
"rating": {
"maximum": 5,
"minimum": 1,
"type": "integer",
"description": "Rating from 1-5",
"format": "int32",
"examples": [
5
]
},
"comment": {
"type": "string",
"description": "Customer comment related to rating",
"examples": [
"Excellent delivery"
]
},
"createdAt": {
"type": "string",
"description": "Timestamp when rating was left by customer.",
"format": "date-time",
"examples": [
"2026-03-30T18:00:00Z"
]
}
},
"description": "Customer rating and feedback left on a stop."
}
],
"description": "Rating left by customer. This can only be populated once `deliveryStatus =\n DELIVERED`."
},
"customSignatureDisclosure": {
"type": "string",
"description": "Optional custom signature disclosure that is shown to customers in the\n driver app.",
"examples": [
"I acknowledge that I have received this delivery."
]
},
"shopifyOrder": {
"allOf": [
{
"title": "ShopifyOrder",
"type": "object",
"properties": {
"orderNote": {
"type": "string",
"description": "The Shopify order note.",
"examples": [
"Customer has paid."
]
},
"customerNote": {
"type": "string",
"description": "The Shopify customer note for the order.",
"examples": [
"Leave at door."
]
}
},
"description": "Shopify-specific information for a RouteStop."
}
],
"description": "Information from the associated Shopify order, if applicable. Populated if\n stop source is `SHOPIFY_ORDER`"
},
"proofOfDeliveryBarcodes": {
"type": "array",
"items": {
"title": "ScannedBarcode",
"type": "object",
"properties": {
"value": {
"type": "string",
"description": "Barcode value (e.g. `\"123456789012\"`).",
"examples": [
"123456789012"
]
},
"createdAt": {
"type": "string",
"description": "Timestamp when the barcode was scanned.",
"format": "date-time",
"examples": [
"2026-03-30T13:10:00Z"
]
}
},
"description": "A proof of delivery barcode scanned at a stop."
},
"description": "Proof of delivery barcodes scanned at the stop."
},
"proofOfDeliveryBarcodeIssues": {
"type": "array",
"items": {
"title": "ScannedBarcodeIssue",
"type": "object",
"properties": {
"reason": {
"enum": [
"UNKNOWN",
"ITEM_MISSING",
"NOT_SCANNABLE",
"INCORRECT"
],
"type": "string",
"description": "The reported reason for the barcode issue.",
"format": "enum",
"examples": [
"ITEM_MISSING"
]
},
"note": {
"type": "string",
"description": "Optional note related to the reason for reporting a barcode issue.",
"examples": [
"Item was not packed."
]
},
"createdAt": {
"type": "string",
"description": "Timestamp when the issue was reported.",
"format": "date-time",
"examples": [
"2026-03-30T13:10:00Z"
]
}
},
"description": "A reported issue related to scanning barcodes at a stop."
},
"description": "Proof of delivery barcode issues reported at the stop."
},
"orderReferenceUrl": {
"type": "string",
"description": "A reference URL for the order associated with the stop (e.g. a link to the\n order in your order management system). Must be a valid HTTPS URL. This\n field can only be populated for imported stops.",
"examples": [
"https://orders.example.com/orders/148977776"
]
}
},
"description": "A stop on a route. A stop may correspond to a delivery or a driver break as\n determined by the type. A delivery stop will have location and contact\n information, items to deliver, optional order details, status, arrival time\n and stop duration, driver tasks and any proof of delivery information. A\n break stop will have start time and duration, and status."
}
}
}
},
"default": {
"description": "Default error response",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"code": {
"type": "integer",
"description": "The status code, which should be an enum value of [google.rpc.Code][google.rpc.Code].",
"format": "int32"
},
"message": {
"type": "string",
"description": "A developer-facing error message, which should be in English. Any user-facing error message should be localized and sent in the [google.rpc.Status.details][google.rpc.Status.details] field, or localized by the client."
},
"details": {
"type": "array",
"items": {
"type": "object",
"properties": {
"@type": {
"type": "string",
"description": "The type of the serialized message."
}
},
"additionalProperties": true,
"description": "Contains an arbitrary serialized message along with a @type that describes the type of the serialized message."
},
"description": "A list of messages that carry the error details. There is a common set of message types for APIs to use."
}
},
"description": "The `Status` type defines a logical error model that is suitable for different programming environments, including REST APIs and RPC APIs. It is used by [gRPC](https://github.com/grpc). Each `Status` message contains three pieces of data: error code, error message, and error details. You can find out more about this error model and how to work with it in the [API Design Guide](https://cloud.google.com/apis/design/errors)."
}
}
}
}
},
"security": [
{
"bearerAuth": []
}
],
"components": {
"securitySchemes": {
"bearerAuth": {
"type": "http",
"description": "Access token from `/authenticate`",
"scheme": "bearer",
"bearerFormat": "JWT"
}
}
}
}
```
# Get imported stop route info (https://docs.roundtrip.ai/docs/api-reference/stops/get-stops-imports-id-routes)
GET /stops/imports/{id}/routes
Fetch the route and stop IDs for an imported stop that has been added to
one or more routes. The ID can be the EasyRoutes `id` returned on import or
the client-provided `clientStopId`. Note that only non-deleted routes are
returned.
## OpenAPI specification
```json
{
"servers": [
{
"url": "https://easyroutes.roundtrip.ai/api/2024-07"
}
],
"tags": [
"Stops"
],
"summary": "Get imported stop route info",
"description": "Fetch the route and stop IDs for an imported stop that has been added to\n one or more routes. The ID can be the EasyRoutes `id` returned on import or\n the client-provided `clientStopId`. Note that only non-deleted routes are\n returned.",
"operationId": "GetImportedStopRouteInfo",
"parameters": [
{
"name": "id",
"in": "path",
"description": "The ID of the imported stop to fetch route info. You provide the EasyRoutes\n `id` returned on import or the client-provided `clientStopId`.",
"required": true,
"schema": {
"type": "string",
"examples": [
"ist-123e4567-e89b-12d3-a456-426614174000"
]
}
}
],
"responses": {
"200": {
"description": "OK",
"content": {
"application/json": {
"schema": {
"title": "GetImportedStopRouteInfoResponse",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "The ID of the imported stop.",
"examples": [
"ist-123e4567-e89b-12d3-a456-426614174000"
]
},
"routeInfo": {
"type": "array",
"items": {
"title": "ImportedStopRouteInfo",
"type": "object",
"properties": {
"routeId": {
"type": "string",
"description": "The ID of the route the stop is associated with (e.g.\n `\"rte-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"rte-123e4567-e89b-12d3-a456-426614174000"
]
},
"stopId": {
"type": "string",
"description": "The ID of the stop on the route (e.g.\n `\"rst-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"rst-123e4567-e89b-12d3-a456-426614174000"
]
},
"deliveryStatus": {
"enum": [
"UNKNOWN",
"DELIVERED",
"OUT_FOR_DELIVERY",
"ATTEMPTED_DELIVERY",
"READY_FOR_DELIVERY"
],
"type": "string",
"description": "The status for the stop on the route.",
"format": "enum",
"examples": [
"DELIVERED"
]
}
},
"description": "Route and stop IDs for an imported stop that has been added to a route."
},
"description": "The route and stop IDs for the imported stop that has been added to a\n route."
}
}
}
}
}
},
"default": {
"description": "Default error response",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"code": {
"type": "integer",
"description": "The status code, which should be an enum value of [google.rpc.Code][google.rpc.Code].",
"format": "int32"
},
"message": {
"type": "string",
"description": "A developer-facing error message, which should be in English. Any user-facing error message should be localized and sent in the [google.rpc.Status.details][google.rpc.Status.details] field, or localized by the client."
},
"details": {
"type": "array",
"items": {
"type": "object",
"properties": {
"@type": {
"type": "string",
"description": "The type of the serialized message."
}
},
"additionalProperties": true,
"description": "Contains an arbitrary serialized message along with a @type that describes the type of the serialized message."
},
"description": "A list of messages that carry the error details. There is a common set of message types for APIs to use."
}
},
"description": "The `Status` type defines a logical error model that is suitable for different programming environments, including REST APIs and RPC APIs. It is used by [gRPC](https://github.com/grpc). Each `Status` message contains three pieces of data: error code, error message, and error details. You can find out more about this error model and how to work with it in the [API Design Guide](https://cloud.google.com/apis/design/errors)."
}
}
}
}
},
"security": [
{
"bearerAuth": []
}
],
"components": {
"securitySchemes": {
"bearerAuth": {
"type": "http",
"description": "Access token from `/authenticate`",
"scheme": "bearer",
"bearerFormat": "JWT"
}
}
}
}
```
# Get imported stop (https://docs.roundtrip.ai/docs/api-reference/stops/get-stops-imports-id)
GET /stops/imports/{id}
Fetch a single imported stop by ID. The ID can be the EasyRoutes `id`
returned on import or the client-provided `clientStopId`.
## OpenAPI specification
```json
{
"servers": [
{
"url": "https://easyroutes.roundtrip.ai/api/2024-07"
}
],
"tags": [
"Stops"
],
"summary": "Get imported stop",
"description": "Fetch a single imported stop by ID. The ID can be the EasyRoutes `id`\n returned on import or the client-provided `clientStopId`.",
"operationId": "GetImportedStop",
"parameters": [
{
"name": "id",
"in": "path",
"description": "The ID of the imported stop to fetch. You provide the EasyRoutes `id`\n returned on import or the client-provided `clientStopId`.",
"required": true,
"schema": {
"type": "string",
"examples": [
"ist-123e4567-e89b-12d3-a456-426614174000"
]
}
}
],
"responses": {
"200": {
"description": "OK",
"content": {
"application/json": {
"schema": {
"title": "ImportedStop",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "The ID of the imported stop, generated by EasyRoutes (e.g.\n `\"ist-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"ist-123e4567-e89b-12d3-a456-426614174000"
]
},
"clientStopId": {
"type": "string",
"description": "The client-provided ID associated with the imported stop, if provided.",
"examples": [
"test-order-1234"
]
},
"address": {
"allOf": [
{
"title": "Address",
"type": "object",
"properties": {
"address1": {
"type": "string",
"description": "Street address line 1 (e.g. `\"123 Main St\"`).",
"examples": [
"123 Main St"
]
},
"address2": {
"type": "string",
"description": "Street address line 2 (e.g. `\"Apt 101\"`).",
"examples": [
"Apt 3B"
]
},
"city": {
"type": "string",
"description": "City name (e.g. `\"New York\"`).",
"examples": [
"New York"
]
},
"provinceCode": {
"type": "string",
"description": "Province or state as subdivision codes in\n [ISO 3166-2](https://en.wikipedia.org/wiki/ISO_3166-2) format without the\n country prefix (e.g. `\"NY\"` for New York).",
"examples": [
"NY"
]
},
"countryCode": {
"type": "string",
"description": "Country code (e.g. `\"US\"`).",
"examples": [
"US"
]
},
"zip": {
"type": "string",
"description": "Postal or ZIP code (e.g. `\"10001\"`).",
"examples": [
"10001"
]
}
},
"description": "A physical street address."
}
],
"description": "The address for the stop.",
"examples": [
{
"address1": "123 Main St",
"address2": "Apt 3B",
"city": "New York",
"provinceCode": "NY",
"countryCode": "US",
"zip": "10001"
}
]
},
"contact": {
"allOf": [
{
"title": "Contact",
"type": "object",
"properties": {
"firstName": {
"type": "string",
"description": "First name (e.g. `\"John\"`).",
"examples": [
"John"
]
},
"lastName": {
"type": "string",
"description": "Last name (e.g. `\"Doe\"`).",
"examples": [
"Doe"
]
},
"company": {
"type": "string",
"description": "Company name (e.g. `\"Roundtrip Systems Inc\"`).",
"examples": [
"Roundtrip Systems Inc"
]
},
"phone": {
"type": "string",
"description": "Phone number in [E.164 format](https://en.wikipedia.org/wiki/E.164) (e.g.\n `\"+14265551000\"`).",
"examples": [
"+14265551000"
]
},
"email": {
"type": "string",
"description": "Email address (e.g. `\"john.doe@roundtrip.ai\"`)",
"examples": [
"john.doe@roundtrip.ai"
]
}
},
"description": "Contact information for a person or company."
}
],
"description": "The contact information for the stop.",
"examples": [
{
"firstName": "John",
"lastName": "Doe",
"company": "Roundtrip Systems Inc",
"phone": "+14265551000",
"email": "john.doe@roundtrip.ai"
}
]
},
"coordinates": {
"allOf": [
{
"type": "object",
"properties": {
"latitude": {
"type": "number",
"description": "The latitude in degrees. It must be in the range [-90.0, +90.0].",
"format": "double"
},
"longitude": {
"type": "number",
"description": "The longitude in degrees. It must be in the range [-180.0, +180.0].",
"format": "double"
}
},
"description": "An object that represents a latitude/longitude pair. This is expressed as a\n pair of doubles to represent degrees latitude and degrees longitude. Unless\n specified otherwise, this must conform to the\n WGS84\n standard. Values must be within normalized ranges."
}
],
"description": "The coordinates to use for the stop, if provided on import.",
"examples": [
{
"latitude": 40.7128,
"longitude": -74.006
}
]
},
"items": {
"type": "array",
"items": {
"title": "StopItem",
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "Item name (e.g. `\"Bananas\"`).",
"examples": [
"Bananas"
]
},
"quantity": {
"type": "integer",
"description": "Quantity of the item (e.g. `5`).",
"format": "int32",
"examples": [
5
]
},
"grams": {
"type": "integer",
"description": "Weight of the item in grams (e.g. `500`).",
"format": "int32",
"examples": [
500
]
},
"sku": {
"type": "string",
"description": "Stock keeping unit (e.g. `\"BANANA-001\"`).",
"examples": [
"BANANA-001"
]
}
},
"description": "An item to be delivered at a stop."
},
"description": "The items to deliver at the stop."
},
"note": {
"type": "string",
"description": "A note for the stop.",
"examples": [
"Leave at door."
]
},
"duration": {
"pattern": "^-?(?:0|[1-9][0-9]{0,11})(?:\\.[0-9]{1,9})?s$",
"type": "string",
"description": "The planned duration for the driver to spend at this stop. This duration is\n used in route optimization to estimate arrival times. If specified, it\n takes precedence over the route's default stop duration. Specified as a\n duration string in the format \"300s\" for 5 minutes, \"60s\" for 1 minute,\n etc.",
"examples": [
"300s"
]
},
"priority": {
"maximum": 10,
"type": "integer",
"description": "Priority of the stop for route planning.",
"format": "int32",
"examples": [
5
]
},
"orderName": {
"type": "string",
"description": "The name of the order associated with the stop.",
"examples": [
"#1234"
]
},
"importedAt": {
"type": "string",
"description": "The timestamp at which the stop was imported.",
"format": "date-time",
"examples": [
"2026-03-28T10:00:00Z"
]
},
"timeWindows": {
"type": "array",
"items": {
"title": "TimeWindow",
"type": "object",
"properties": {
"start": {
"allOf": [
{
"title": "TimeOfDay",
"type": "object",
"properties": {
"hours": {
"maximum": 23,
"type": "integer",
"description": "Hours of day in 24 hour format. Must be from 0 to 23.",
"format": "int32",
"examples": [
13
]
},
"minutes": {
"maximum": 59,
"type": "integer",
"description": "Minutes of hour of day. Must be from 0 to 59.",
"format": "int32",
"examples": [
37
]
},
"seconds": {
"maximum": 59,
"type": "integer",
"description": "Seconds of minutes of the time. Must be from 0 to 59.",
"format": "int32",
"examples": [
16
]
}
},
"description": "A time of day, independent of a particular date or timezone."
}
],
"description": "The start time of the time window (optional)."
},
"end": {
"allOf": [
{
"title": "TimeOfDay",
"type": "object",
"properties": {
"hours": {
"maximum": 23,
"type": "integer",
"description": "Hours of day in 24 hour format. Must be from 0 to 23.",
"format": "int32",
"examples": [
13
]
},
"minutes": {
"maximum": 59,
"type": "integer",
"description": "Minutes of hour of day. Must be from 0 to 59.",
"format": "int32",
"examples": [
37
]
},
"seconds": {
"maximum": 59,
"type": "integer",
"description": "Seconds of minutes of the time. Must be from 0 to 59.",
"format": "int32",
"examples": [
16
]
}
},
"description": "A time of day, independent of a particular date or timezone."
}
],
"description": "The end time of the time window (optional)."
}
},
"description": "A time window for a stop. The time window may be open-ended, but one or both\n of the start and end times should be provided. The end time must be >= the\n start time."
},
"description": "The time window for the stop. Note that we currently support at most one\n time window but may support multiple time windows in the future.",
"examples": [
[
{
"start": {
"hours": 9
},
"end": {
"hours": 17
}
}
]
]
},
"deliveryDate": {
"allOf": [
{
"title": "Date",
"required": [
"year",
"month",
"day"
],
"type": "object",
"properties": {
"year": {
"maximum": 9999,
"minimum": 1,
"type": "integer",
"description": "Year of the date. Must be from 1 to 9999.",
"format": "int32",
"examples": [
2019
]
},
"month": {
"maximum": 12,
"minimum": 1,
"type": "integer",
"description": "Month of a year. Must be from 1 to 12.",
"format": "int32",
"examples": [
11
]
},
"day": {
"maximum": 31,
"minimum": 1,
"type": "integer",
"description": "Day of a month. Must be from 1 to 31.",
"format": "int32",
"examples": [
15
]
}
},
"description": "A date in year-month-day format."
}
],
"description": "The delivery date for the stop.",
"examples": [
{
"year": 2025,
"month": 12,
"day": 16
}
]
},
"attributes": {
"type": "array",
"items": {
"title": "Attribute",
"type": "object",
"properties": {
"key": {
"type": "string",
"description": "Attribute key. Must be non-empty.",
"examples": [
"delivery_date"
]
},
"value": {
"type": "string",
"description": "Attribute value.",
"examples": [
"2025-12-16"
]
}
},
"description": "A key-value pair for storing additional information on a stop, such as order\n details, delivery instructions, or custom fields."
},
"description": "The additional key-value attributes set on the imported stop.",
"examples": [
[
{
"key": "color",
"value": "blue"
}
]
]
},
"tags": {
"type": "array",
"items": {
"type": "string"
},
"description": "The tags for the stop.",
"examples": [
[
"foo",
"bar"
]
]
},
"tasks": {
"type": "array",
"items": {
"title": "TaskTemplate",
"type": "object",
"properties": {
"title": {
"type": "string",
"description": "Task title (e.g. `\"Delivery checklist\"`).",
"examples": [
"Delivery checklist"
]
},
"type": {
"enum": [
"UNKNOWN",
"CHECKBOXES",
"RADIO_BUTTONS",
"TEXT_INPUT",
"DECIMAL_INPUT",
"SCANNER_INPUT"
],
"type": "string",
"description": "Task type.",
"format": "enum",
"examples": [
"CHECKBOXES"
]
},
"items": {
"type": "array",
"items": {
"title": "TaskItemTemplate",
"type": "object",
"properties": {
"title": {
"type": "string",
"description": "Item title (e.g. `\"Pick up package\"`).",
"examples": [
"Pick up package"
]
}
},
"description": "An item template for a task. For `CHECKBOXES`, each item on a task may be\n completed independently. For `RADIO_BUTTONS`, at most one item will be\n completed."
},
"description": "Task items, which are required for `CHECKBOXES` and `RADIO_BUTTONS`."
},
"requiredToMarkStopAsDelivered": {
"type": "boolean",
"description": "Whether the task is required to mark the stop as completed.",
"examples": [
true
]
},
"requiredToMarkStopAsAttempted": {
"type": "boolean",
"description": "Whether the task is required to mark the stop as attempted.",
"examples": [
true
]
}
},
"description": "A template for creating tasks at a stop. Task templates may have one or more\n items for `CHECKBOXES` or `RADIO_BUTTONS`. Imported stops may have task\n templates that are used to create tasks when the stop is added to a route."
},
"description": "The tasks for the stop."
},
"type": {
"enum": [
"UNKNOWN",
"DELIVERY",
"BREAK",
"PICKUP",
"TASK"
],
"type": "string",
"description": "The type of stop (DELIVERY, PICKUP, or TASK). Defaults to DELIVERY if not\n provided.",
"format": "enum",
"examples": [
"DELIVERY"
]
},
"customSignatureDisclosure": {
"type": "string",
"description": "Custom signature disclosure for the stop. Only populated if stop type is\n DELIVERY, PICKUP, or TASK.",
"examples": [
"I acknowledge that I have received this delivery."
]
},
"orderReferenceUrl": {
"type": "string",
"description": "A reference URL for the order associated with the stop (e.g. a link to the\n order in your order management system). Must be a valid HTTPS URL.",
"examples": [
"https://orders.example.com/orders/148977776"
]
}
},
"description": "A stop imported into EasyRoutes."
}
}
}
},
"default": {
"description": "Default error response",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"code": {
"type": "integer",
"description": "The status code, which should be an enum value of [google.rpc.Code][google.rpc.Code].",
"format": "int32"
},
"message": {
"type": "string",
"description": "A developer-facing error message, which should be in English. Any user-facing error message should be localized and sent in the [google.rpc.Status.details][google.rpc.Status.details] field, or localized by the client."
},
"details": {
"type": "array",
"items": {
"type": "object",
"properties": {
"@type": {
"type": "string",
"description": "The type of the serialized message."
}
},
"additionalProperties": true,
"description": "Contains an arbitrary serialized message along with a @type that describes the type of the serialized message."
},
"description": "A list of messages that carry the error details. There is a common set of message types for APIs to use."
}
},
"description": "The `Status` type defines a logical error model that is suitable for different programming environments, including REST APIs and RPC APIs. It is used by [gRPC](https://github.com/grpc). Each `Status` message contains three pieces of data: error code, error message, and error details. You can find out more about this error model and how to work with it in the [API Design Guide](https://cloud.google.com/apis/design/errors)."
}
}
}
}
},
"security": [
{
"bearerAuth": []
}
],
"components": {
"securitySchemes": {
"bearerAuth": {
"type": "http",
"description": "Access token from `/authenticate`",
"scheme": "bearer",
"bearerFormat": "JWT"
}
}
}
}
```
# List imported stops (https://docs.roundtrip.ai/docs/api-reference/stops/get-stops-imports)
GET /stops/imports
Fetch a list of imported stops. The response will include a list of
imported stops and a cursor to fetch the next page of results. Subsequent
requests should include the cursor only and no list query arguments (which
are encoded in the cursor).
## OpenAPI specification
```json
{
"servers": [
{
"url": "https://easyroutes.roundtrip.ai/api/2024-07"
}
],
"tags": [
"Stops"
],
"summary": "List imported stops",
"description": "Fetch a list of imported stops. The response will include a list of\n imported stops and a cursor to fetch the next page of results. Subsequent\n requests should include the cursor only and no list query arguments (which\n are encoded in the cursor).",
"operationId": "ListImportedStops",
"parameters": [
{
"name": "query.limit",
"in": "query",
"description": "Maximum number of imported stops to return. Must be less than or equal to\n `200`. Defaults to `20`.",
"schema": {
"maximum": 200,
"minimum": 1,
"type": "integer",
"format": "int32",
"examples": [
50
]
}
},
{
"name": "cursor",
"in": "query",
"description": "Cursor to fetch the next page of results (if available). Should only be set\n on subsequent requests.",
"schema": {
"type": "string",
"examples": [
"eyJpZCI6IjEyMyJ9"
]
}
}
],
"responses": {
"200": {
"description": "OK",
"content": {
"application/json": {
"schema": {
"title": "ListImportedStopsResponse",
"type": "object",
"properties": {
"stops": {
"type": "array",
"items": {
"title": "ImportedStop",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "The ID of the imported stop, generated by EasyRoutes (e.g.\n `\"ist-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"ist-123e4567-e89b-12d3-a456-426614174000"
]
},
"clientStopId": {
"type": "string",
"description": "The client-provided ID associated with the imported stop, if provided.",
"examples": [
"test-order-1234"
]
},
"address": {
"allOf": [
{
"title": "Address",
"type": "object",
"properties": {
"address1": {
"type": "string",
"description": "Street address line 1 (e.g. `\"123 Main St\"`).",
"examples": [
"123 Main St"
]
},
"address2": {
"type": "string",
"description": "Street address line 2 (e.g. `\"Apt 101\"`).",
"examples": [
"Apt 3B"
]
},
"city": {
"type": "string",
"description": "City name (e.g. `\"New York\"`).",
"examples": [
"New York"
]
},
"provinceCode": {
"type": "string",
"description": "Province or state as subdivision codes in\n [ISO 3166-2](https://en.wikipedia.org/wiki/ISO_3166-2) format without the\n country prefix (e.g. `\"NY\"` for New York).",
"examples": [
"NY"
]
},
"countryCode": {
"type": "string",
"description": "Country code (e.g. `\"US\"`).",
"examples": [
"US"
]
},
"zip": {
"type": "string",
"description": "Postal or ZIP code (e.g. `\"10001\"`).",
"examples": [
"10001"
]
}
},
"description": "A physical street address."
}
],
"description": "The address for the stop.",
"examples": [
{
"address1": "123 Main St",
"address2": "Apt 3B",
"city": "New York",
"provinceCode": "NY",
"countryCode": "US",
"zip": "10001"
}
]
},
"contact": {
"allOf": [
{
"title": "Contact",
"type": "object",
"properties": {
"firstName": {
"type": "string",
"description": "First name (e.g. `\"John\"`).",
"examples": [
"John"
]
},
"lastName": {
"type": "string",
"description": "Last name (e.g. `\"Doe\"`).",
"examples": [
"Doe"
]
},
"company": {
"type": "string",
"description": "Company name (e.g. `\"Roundtrip Systems Inc\"`).",
"examples": [
"Roundtrip Systems Inc"
]
},
"phone": {
"type": "string",
"description": "Phone number in [E.164 format](https://en.wikipedia.org/wiki/E.164) (e.g.\n `\"+14265551000\"`).",
"examples": [
"+14265551000"
]
},
"email": {
"type": "string",
"description": "Email address (e.g. `\"john.doe@roundtrip.ai\"`)",
"examples": [
"john.doe@roundtrip.ai"
]
}
},
"description": "Contact information for a person or company."
}
],
"description": "The contact information for the stop.",
"examples": [
{
"firstName": "John",
"lastName": "Doe",
"company": "Roundtrip Systems Inc",
"phone": "+14265551000",
"email": "john.doe@roundtrip.ai"
}
]
},
"coordinates": {
"allOf": [
{
"type": "object",
"properties": {
"latitude": {
"type": "number",
"description": "The latitude in degrees. It must be in the range [-90.0, +90.0].",
"format": "double"
},
"longitude": {
"type": "number",
"description": "The longitude in degrees. It must be in the range [-180.0, +180.0].",
"format": "double"
}
},
"description": "An object that represents a latitude/longitude pair. This is expressed as a\n pair of doubles to represent degrees latitude and degrees longitude. Unless\n specified otherwise, this must conform to the\n WGS84\n standard. Values must be within normalized ranges."
}
],
"description": "The coordinates to use for the stop, if provided on import.",
"examples": [
{
"latitude": 40.7128,
"longitude": -74.006
}
]
},
"items": {
"type": "array",
"items": {
"title": "StopItem",
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "Item name (e.g. `\"Bananas\"`).",
"examples": [
"Bananas"
]
},
"quantity": {
"type": "integer",
"description": "Quantity of the item (e.g. `5`).",
"format": "int32",
"examples": [
5
]
},
"grams": {
"type": "integer",
"description": "Weight of the item in grams (e.g. `500`).",
"format": "int32",
"examples": [
500
]
},
"sku": {
"type": "string",
"description": "Stock keeping unit (e.g. `\"BANANA-001\"`).",
"examples": [
"BANANA-001"
]
}
},
"description": "An item to be delivered at a stop."
},
"description": "The items to deliver at the stop."
},
"note": {
"type": "string",
"description": "A note for the stop.",
"examples": [
"Leave at door."
]
},
"duration": {
"pattern": "^-?(?:0|[1-9][0-9]{0,11})(?:\\.[0-9]{1,9})?s$",
"type": "string",
"description": "The planned duration for the driver to spend at this stop. This duration is\n used in route optimization to estimate arrival times. If specified, it\n takes precedence over the route's default stop duration. Specified as a\n duration string in the format \"300s\" for 5 minutes, \"60s\" for 1 minute,\n etc.",
"examples": [
"300s"
]
},
"priority": {
"maximum": 10,
"type": "integer",
"description": "Priority of the stop for route planning.",
"format": "int32",
"examples": [
5
]
},
"orderName": {
"type": "string",
"description": "The name of the order associated with the stop.",
"examples": [
"#1234"
]
},
"importedAt": {
"type": "string",
"description": "The timestamp at which the stop was imported.",
"format": "date-time",
"examples": [
"2026-03-28T10:00:00Z"
]
},
"timeWindows": {
"type": "array",
"items": {
"title": "TimeWindow",
"type": "object",
"properties": {
"start": {
"allOf": [
{
"title": "TimeOfDay",
"type": "object",
"properties": {
"hours": {
"maximum": 23,
"type": "integer",
"description": "Hours of day in 24 hour format. Must be from 0 to 23.",
"format": "int32",
"examples": [
13
]
},
"minutes": {
"maximum": 59,
"type": "integer",
"description": "Minutes of hour of day. Must be from 0 to 59.",
"format": "int32",
"examples": [
37
]
},
"seconds": {
"maximum": 59,
"type": "integer",
"description": "Seconds of minutes of the time. Must be from 0 to 59.",
"format": "int32",
"examples": [
16
]
}
},
"description": "A time of day, independent of a particular date or timezone."
}
],
"description": "The start time of the time window (optional)."
},
"end": {
"allOf": [
{
"title": "TimeOfDay",
"type": "object",
"properties": {
"hours": {
"maximum": 23,
"type": "integer",
"description": "Hours of day in 24 hour format. Must be from 0 to 23.",
"format": "int32",
"examples": [
13
]
},
"minutes": {
"maximum": 59,
"type": "integer",
"description": "Minutes of hour of day. Must be from 0 to 59.",
"format": "int32",
"examples": [
37
]
},
"seconds": {
"maximum": 59,
"type": "integer",
"description": "Seconds of minutes of the time. Must be from 0 to 59.",
"format": "int32",
"examples": [
16
]
}
},
"description": "A time of day, independent of a particular date or timezone."
}
],
"description": "The end time of the time window (optional)."
}
},
"description": "A time window for a stop. The time window may be open-ended, but one or both\n of the start and end times should be provided. The end time must be >= the\n start time."
},
"description": "The time window for the stop. Note that we currently support at most one\n time window but may support multiple time windows in the future.",
"examples": [
[
{
"start": {
"hours": 9
},
"end": {
"hours": 17
}
}
]
]
},
"deliveryDate": {
"allOf": [
{
"title": "Date",
"required": [
"year",
"month",
"day"
],
"type": "object",
"properties": {
"year": {
"maximum": 9999,
"minimum": 1,
"type": "integer",
"description": "Year of the date. Must be from 1 to 9999.",
"format": "int32",
"examples": [
2019
]
},
"month": {
"maximum": 12,
"minimum": 1,
"type": "integer",
"description": "Month of a year. Must be from 1 to 12.",
"format": "int32",
"examples": [
11
]
},
"day": {
"maximum": 31,
"minimum": 1,
"type": "integer",
"description": "Day of a month. Must be from 1 to 31.",
"format": "int32",
"examples": [
15
]
}
},
"description": "A date in year-month-day format."
}
],
"description": "The delivery date for the stop.",
"examples": [
{
"year": 2025,
"month": 12,
"day": 16
}
]
},
"attributes": {
"type": "array",
"items": {
"title": "Attribute",
"type": "object",
"properties": {
"key": {
"type": "string",
"description": "Attribute key. Must be non-empty.",
"examples": [
"delivery_date"
]
},
"value": {
"type": "string",
"description": "Attribute value.",
"examples": [
"2025-12-16"
]
}
},
"description": "A key-value pair for storing additional information on a stop, such as order\n details, delivery instructions, or custom fields."
},
"description": "The additional key-value attributes set on the imported stop.",
"examples": [
[
{
"key": "color",
"value": "blue"
}
]
]
},
"tags": {
"type": "array",
"items": {
"type": "string"
},
"description": "The tags for the stop.",
"examples": [
[
"foo",
"bar"
]
]
},
"tasks": {
"type": "array",
"items": {
"title": "TaskTemplate",
"type": "object",
"properties": {
"title": {
"type": "string",
"description": "Task title (e.g. `\"Delivery checklist\"`).",
"examples": [
"Delivery checklist"
]
},
"type": {
"enum": [
"UNKNOWN",
"CHECKBOXES",
"RADIO_BUTTONS",
"TEXT_INPUT",
"DECIMAL_INPUT",
"SCANNER_INPUT"
],
"type": "string",
"description": "Task type.",
"format": "enum",
"examples": [
"CHECKBOXES"
]
},
"items": {
"type": "array",
"items": {
"title": "TaskItemTemplate",
"type": "object",
"properties": {
"title": {
"type": "string",
"description": "Item title (e.g. `\"Pick up package\"`).",
"examples": [
"Pick up package"
]
}
},
"description": "An item template for a task. For `CHECKBOXES`, each item on a task may be\n completed independently. For `RADIO_BUTTONS`, at most one item will be\n completed."
},
"description": "Task items, which are required for `CHECKBOXES` and `RADIO_BUTTONS`."
},
"requiredToMarkStopAsDelivered": {
"type": "boolean",
"description": "Whether the task is required to mark the stop as completed.",
"examples": [
true
]
},
"requiredToMarkStopAsAttempted": {
"type": "boolean",
"description": "Whether the task is required to mark the stop as attempted.",
"examples": [
true
]
}
},
"description": "A template for creating tasks at a stop. Task templates may have one or more\n items for `CHECKBOXES` or `RADIO_BUTTONS`. Imported stops may have task\n templates that are used to create tasks when the stop is added to a route."
},
"description": "The tasks for the stop."
},
"type": {
"enum": [
"UNKNOWN",
"DELIVERY",
"BREAK",
"PICKUP",
"TASK"
],
"type": "string",
"description": "The type of stop (DELIVERY, PICKUP, or TASK). Defaults to DELIVERY if not\n provided.",
"format": "enum",
"examples": [
"DELIVERY"
]
},
"customSignatureDisclosure": {
"type": "string",
"description": "Custom signature disclosure for the stop. Only populated if stop type is\n DELIVERY, PICKUP, or TASK.",
"examples": [
"I acknowledge that I have received this delivery."
]
},
"orderReferenceUrl": {
"type": "string",
"description": "A reference URL for the order associated with the stop (e.g. a link to the\n order in your order management system). Must be a valid HTTPS URL.",
"examples": [
"https://orders.example.com/orders/148977776"
]
}
},
"description": "A stop imported into EasyRoutes."
},
"description": "List of imported stops."
},
"nextCursor": {
"type": "string",
"description": "Cursor to fetch the next page of results (if available).",
"examples": [
"eyJpZCI6IjEyMyJ9"
]
}
}
}
}
}
},
"default": {
"description": "Default error response",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"code": {
"type": "integer",
"description": "The status code, which should be an enum value of [google.rpc.Code][google.rpc.Code].",
"format": "int32"
},
"message": {
"type": "string",
"description": "A developer-facing error message, which should be in English. Any user-facing error message should be localized and sent in the [google.rpc.Status.details][google.rpc.Status.details] field, or localized by the client."
},
"details": {
"type": "array",
"items": {
"type": "object",
"properties": {
"@type": {
"type": "string",
"description": "The type of the serialized message."
}
},
"additionalProperties": true,
"description": "Contains an arbitrary serialized message along with a @type that describes the type of the serialized message."
},
"description": "A list of messages that carry the error details. There is a common set of message types for APIs to use."
}
},
"description": "The `Status` type defines a logical error model that is suitable for different programming environments, including REST APIs and RPC APIs. It is used by [gRPC](https://github.com/grpc). Each `Status` message contains three pieces of data: error code, error message, and error details. You can find out more about this error model and how to work with it in the [API Design Guide](https://cloud.google.com/apis/design/errors)."
}
}
}
}
},
"security": [
{
"bearerAuth": []
}
],
"components": {
"securitySchemes": {
"bearerAuth": {
"type": "http",
"description": "Access token from `/authenticate`",
"scheme": "bearer",
"bearerFormat": "JWT"
}
}
}
}
```
# Get Shopify stop route info (https://docs.roundtrip.ai/docs/api-reference/stops/get-stops-shopify-id-routes)
GET /stops/shopify/{id}/routes
Fetch the route and stop IDs for a Shopify order that has been added to one
or more routes. The ID should be the Shopify order ID (int64). Note that
only non-deleted routes are returned.
## OpenAPI specification
```json
{
"servers": [
{
"url": "https://easyroutes.roundtrip.ai/api/2024-07"
}
],
"tags": [
"Stops"
],
"summary": "Get Shopify stop route info",
"description": "Fetch the route and stop IDs for a Shopify order that has been added to one\n or more routes. The ID should be the Shopify order ID (int64). Note that\n only non-deleted routes are returned.",
"operationId": "GetShopifyStopRouteInfo",
"parameters": [
{
"name": "id",
"in": "path",
"description": "The Shopify order ID to fetch route info for.",
"required": true,
"schema": {
"type": "string",
"examples": [
"450789469"
]
}
}
],
"responses": {
"200": {
"description": "OK",
"content": {
"application/json": {
"schema": {
"title": "GetShopifyStopRouteInfoResponse",
"type": "object",
"properties": {
"routeInfo": {
"type": "array",
"items": {
"title": "ImportedStopRouteInfo",
"type": "object",
"properties": {
"routeId": {
"type": "string",
"description": "The ID of the route the stop is associated with (e.g.\n `\"rte-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"rte-123e4567-e89b-12d3-a456-426614174000"
]
},
"stopId": {
"type": "string",
"description": "The ID of the stop on the route (e.g.\n `\"rst-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"rst-123e4567-e89b-12d3-a456-426614174000"
]
},
"deliveryStatus": {
"enum": [
"UNKNOWN",
"DELIVERED",
"OUT_FOR_DELIVERY",
"ATTEMPTED_DELIVERY",
"READY_FOR_DELIVERY"
],
"type": "string",
"description": "The status for the stop on the route.",
"format": "enum",
"examples": [
"DELIVERED"
]
}
},
"description": "Route and stop IDs for an imported stop that has been added to a route."
},
"description": "The route and stop IDs for the Shopify order that has been added to a\n route."
}
}
}
}
}
},
"default": {
"description": "Default error response",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"code": {
"type": "integer",
"description": "The status code, which should be an enum value of [google.rpc.Code][google.rpc.Code].",
"format": "int32"
},
"message": {
"type": "string",
"description": "A developer-facing error message, which should be in English. Any user-facing error message should be localized and sent in the [google.rpc.Status.details][google.rpc.Status.details] field, or localized by the client."
},
"details": {
"type": "array",
"items": {
"type": "object",
"properties": {
"@type": {
"type": "string",
"description": "The type of the serialized message."
}
},
"additionalProperties": true,
"description": "Contains an arbitrary serialized message along with a @type that describes the type of the serialized message."
},
"description": "A list of messages that carry the error details. There is a common set of message types for APIs to use."
}
},
"description": "The `Status` type defines a logical error model that is suitable for different programming environments, including REST APIs and RPC APIs. It is used by [gRPC](https://github.com/grpc). Each `Status` message contains three pieces of data: error code, error message, and error details. You can find out more about this error model and how to work with it in the [API Design Guide](https://cloud.google.com/apis/design/errors)."
}
}
}
}
},
"security": [
{
"bearerAuth": []
}
],
"components": {
"securitySchemes": {
"bearerAuth": {
"type": "http",
"description": "Access token from `/authenticate`",
"scheme": "bearer",
"bearerFormat": "JWT"
}
}
}
}
```
# Update route stop location (https://docs.roundtrip.ai/docs/api-reference/stops/patch-routes-routeId-stops-stopId-location)
PATCH /routes/{routeId}/stops/{stopId}/location
Updates the address and/or planned coordinates for a stop on a route by
route ID and stop ID. This updates only the stop as it exists on this
route; the imported stop it originated from is not modified. Only stops
that were previously imported via ImportStops (i.e. stops with an
`importedStopId`) can be updated through this endpoint. This is a partial
update: provide the fields to change in `location` and list their paths in
`updateMask`, which must contain at least one of `address` or
`plannedCoordinates`. Changing a stop's location affects its distances and
ETAs and marks the route as not optimized; fetch the route to see the
updated directions, and call ReoptimizeRoute if the stop order should be
adjusted. The route must not be archived. The response returns the single
updated RouteStop.
## OpenAPI specification
```json
{
"servers": [
{
"url": "https://easyroutes.roundtrip.ai/api/2024-07"
}
],
"tags": [
"Stops"
],
"summary": "Update route stop location",
"description": "Updates the address and/or planned coordinates for a stop on a route by\n route ID and stop ID. This updates only the stop as it exists on this\n route; the imported stop it originated from is not modified. Only stops\n that were previously imported via ImportStops (i.e. stops with an\n `importedStopId`) can be updated through this endpoint. This is a partial\n update: provide the fields to change in `location` and list their paths in\n `updateMask`, which must contain at least one of `address` or\n `plannedCoordinates`. Changing a stop's location affects its distances and\n ETAs and marks the route as not optimized; fetch the route to see the\n updated directions, and call ReoptimizeRoute if the stop order should be\n adjusted. The route must not be archived. The response returns the single\n updated RouteStop.",
"operationId": "UpdateRouteStopLocation",
"parameters": [
{
"name": "routeId",
"in": "path",
"description": "The ID of the route containing the stop to update.",
"required": true,
"schema": {
"type": "string",
"examples": [
"rte-123e4567-e89b-12d3-a456-426614174000"
]
}
},
{
"name": "stopId",
"in": "path",
"description": "The ID of the stop to update.",
"required": true,
"schema": {
"type": "string",
"examples": [
"rst-123e4567-e89b-12d3-a456-426614174000"
]
}
},
{
"name": "Idempotency-Key",
"in": "header",
"description": "A unique key for safely retrying this operation. For more information read [our guide](https://docs.roundtrip.ai/docs/concepts/idempotency.md).",
"schema": {
"maxLength": 255,
"minLength": 1,
"type": "string"
},
"examples": {
"default": {
"value": "550e8400-e29b-41d4-a716-446655440000"
}
}
}
],
"requestBody": {
"content": {
"application/json": {
"schema": {
"title": "UpdateRouteStopLocationRequest",
"required": [
"location",
"updateMask"
],
"type": "object",
"properties": {
"location": {
"allOf": [
{
"title": "RouteStopLocationUpdate",
"type": "object",
"properties": {
"address": {
"allOf": [
{
"title": "Address",
"type": "object",
"properties": {
"address1": {
"type": "string",
"description": "Street address line 1 (e.g. `\"123 Main St\"`).",
"examples": [
"123 Main St"
]
},
"address2": {
"type": "string",
"description": "Street address line 2 (e.g. `\"Apt 101\"`).",
"examples": [
"Apt 3B"
]
},
"city": {
"type": "string",
"description": "City name (e.g. `\"New York\"`).",
"examples": [
"New York"
]
},
"provinceCode": {
"type": "string",
"description": "Province or state as subdivision codes in\n [ISO 3166-2](https://en.wikipedia.org/wiki/ISO_3166-2) format without the\n country prefix (e.g. `\"NY\"` for New York).",
"examples": [
"NY"
]
},
"countryCode": {
"type": "string",
"description": "Country code (e.g. `\"US\"`).",
"examples": [
"US"
]
},
"zip": {
"type": "string",
"description": "Postal or ZIP code (e.g. `\"10001\"`).",
"examples": [
"10001"
]
}
},
"description": "A physical street address."
}
],
"description": "The new address for the stop. If `plannedCoordinates` is not included in\n `updateMask`, this address is geocoded to determine the stop's new\n coordinates, and the request fails if the address cannot be geocoded.\n Exception: if the stop's coordinates are currently set manually (e.g. via a\n prior call with `plannedCoordinates`, or manually in the EasyRoutes UI), an\n address-only update leaves the existing manual coordinates untouched rather\n than re-geocoding; include `plannedCoordinates` in `updateMask` to change\n them.",
"examples": [
{
"address1": "123 Main St",
"address2": "Apt 3B",
"city": "New York",
"provinceCode": "NY",
"countryCode": "US",
"zip": "10001"
}
]
},
"plannedCoordinates": {
"allOf": [
{
"type": "object",
"properties": {
"latitude": {
"type": "number",
"description": "The latitude in degrees. It must be in the range [-90.0, +90.0].",
"format": "double"
},
"longitude": {
"type": "number",
"description": "The longitude in degrees. It must be in the range [-180.0, +180.0].",
"format": "double"
}
},
"description": "An object that represents a latitude/longitude pair. This is expressed as a\n pair of doubles to represent degrees latitude and degrees longitude. Unless\n specified otherwise, this must conform to the\n WGS84\n standard. Values must be within normalized ranges."
}
],
"description": "The new planned coordinates for the stop. If included in `updateMask`,\n these coordinates are used directly instead of geocoding the address, and\n are treated as a manual override of the stop's location.",
"examples": [
{
"latitude": 40.7128,
"longitude": -74.006
}
]
}
}
}
],
"description": "Update for the stop's location."
},
"updateMask": {
"type": "string",
"description": "Comma-separated list of [field mask](https://docs.roundtrip.ai/docs/concepts/field-masks.md) paths in `location` to apply. Only listed paths are updated; omitted fields are left unchanged. Must contain at least one of `address` or `plannedCoordinates`.",
"format": "field-mask"
}
}
}
}
},
"required": true
},
"responses": {
"200": {
"description": "OK",
"headers": {
"Idempotency-Key": {
"description": "The idempotency key associated with the response.",
"schema": {
"type": "string"
}
},
"Idempotency-Replayed": {
"description": "Whether the response was replayed from a previous request.",
"schema": {
"type": "boolean"
}
}
},
"content": {
"application/json": {
"schema": {
"title": "RouteStop",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Stop ID (e.g. `\"rst-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"rst-123e4567-e89b-12d3-a456-426614174000"
]
},
"type": {
"enum": [
"UNKNOWN",
"DELIVERY",
"BREAK",
"PICKUP",
"TASK"
],
"type": "string",
"description": "The type of stop (DELIVERY, BREAK, PICKUP, or TASK).",
"format": "enum",
"examples": [
"DELIVERY"
]
},
"deliveryStatus": {
"enum": [
"UNKNOWN",
"DELIVERED",
"OUT_FOR_DELIVERY",
"ATTEMPTED_DELIVERY",
"READY_FOR_DELIVERY"
],
"type": "string",
"description": "The status for DELIVERY, PICKUP, or TASK stops.",
"format": "enum",
"examples": [
"ATTEMPTED_DELIVERY"
]
},
"breakStatus": {
"enum": [
"UNKNOWN",
"COMPLETED"
],
"type": "string",
"description": "The status for BREAK stops.",
"format": "enum",
"examples": [
"COMPLETED"
]
},
"updatedAt": {
"type": "string",
"description": "Timestamp when the stop status was last updated. Note that this timestamp\n corresponds only to major status updates (i.e. stop marked as DELIVERED).\n Minor updates like task completion or adding proof of delivery will not\n advance this timestamp. For those events, use the timestamps on the task or\n proof of delivery attachment.",
"format": "date-time",
"examples": [
"2026-03-30T13:15:00Z"
]
},
"duration": {
"pattern": "^-?(?:0|[1-9][0-9]{0,11})(?:\\.[0-9]{1,9})?s$",
"type": "string",
"description": "Planned duration of the stop in seconds.",
"examples": [
"300s"
]
},
"plannedArrival": {
"type": "string",
"description": "Planned arrival time at the stop.",
"format": "date-time",
"examples": [
"2026-03-30T13:00:00Z"
]
},
"note": {
"type": "string",
"description": "Top-level note for the stop, as entered manually by route planners,\n inherited from a saved or imported stop, or set by order import automation\n rules.",
"examples": [
"Leave at door."
]
},
"address": {
"allOf": [
{
"title": "Address",
"type": "object",
"properties": {
"address1": {
"type": "string",
"description": "Street address line 1 (e.g. `\"123 Main St\"`).",
"examples": [
"123 Main St"
]
},
"address2": {
"type": "string",
"description": "Street address line 2 (e.g. `\"Apt 101\"`).",
"examples": [
"Apt 3B"
]
},
"city": {
"type": "string",
"description": "City name (e.g. `\"New York\"`).",
"examples": [
"New York"
]
},
"provinceCode": {
"type": "string",
"description": "Province or state as subdivision codes in\n [ISO 3166-2](https://en.wikipedia.org/wiki/ISO_3166-2) format without the\n country prefix (e.g. `\"NY\"` for New York).",
"examples": [
"NY"
]
},
"countryCode": {
"type": "string",
"description": "Country code (e.g. `\"US\"`).",
"examples": [
"US"
]
},
"zip": {
"type": "string",
"description": "Postal or ZIP code (e.g. `\"10001\"`).",
"examples": [
"10001"
]
}
},
"description": "A physical street address."
}
],
"description": "Delivery address for the stop.",
"examples": [
{
"address1": "123 Main St",
"address2": "Apt 3B",
"city": "New York",
"provinceCode": "NY",
"countryCode": "US",
"zip": "10001"
}
]
},
"contact": {
"allOf": [
{
"title": "Contact",
"type": "object",
"properties": {
"firstName": {
"type": "string",
"description": "First name (e.g. `\"John\"`).",
"examples": [
"John"
]
},
"lastName": {
"type": "string",
"description": "Last name (e.g. `\"Doe\"`).",
"examples": [
"Doe"
]
},
"company": {
"type": "string",
"description": "Company name (e.g. `\"Roundtrip Systems Inc\"`).",
"examples": [
"Roundtrip Systems Inc"
]
},
"phone": {
"type": "string",
"description": "Phone number in [E.164 format](https://en.wikipedia.org/wiki/E.164) (e.g.\n `\"+14265551000\"`).",
"examples": [
"+14265551000"
]
},
"email": {
"type": "string",
"description": "Email address (e.g. `\"john.doe@roundtrip.ai\"`)",
"examples": [
"john.doe@roundtrip.ai"
]
}
},
"description": "Contact information for a person or company."
}
],
"description": "Contact information for the stop delivery recipient.",
"examples": [
{
"firstName": "John",
"lastName": "Doe",
"company": "Roundtrip Systems Inc",
"phone": "+14265551000",
"email": "john.doe@roundtrip.ai"
}
]
},
"plannedCoordinates": {
"allOf": [
{
"type": "object",
"properties": {
"latitude": {
"type": "number",
"description": "The latitude in degrees. It must be in the range [-90.0, +90.0].",
"format": "double"
},
"longitude": {
"type": "number",
"description": "The longitude in degrees. It must be in the range [-180.0, +180.0].",
"format": "double"
}
},
"description": "An object that represents a latitude/longitude pair. This is expressed as a\n pair of doubles to represent degrees latitude and degrees longitude. Unless\n specified otherwise, this must conform to the\n WGS84\n standard. Values must be within normalized ranges."
}
],
"description": "Planned coordinates for the stop.",
"examples": [
{
"latitude": 40.7128,
"longitude": -74.006
}
]
},
"items": {
"type": "array",
"items": {
"title": "StopItem",
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "Item name (e.g. `\"Bananas\"`).",
"examples": [
"Bananas"
]
},
"quantity": {
"type": "integer",
"description": "Quantity of the item (e.g. `5`).",
"format": "int32",
"examples": [
5
]
},
"grams": {
"type": "integer",
"description": "Weight of the item in grams (e.g. `500`).",
"format": "int32",
"examples": [
500
]
},
"sku": {
"type": "string",
"description": "Stock keeping unit (e.g. `\"BANANA-001\"`).",
"examples": [
"BANANA-001"
]
}
},
"description": "An item to be delivered at a stop."
},
"description": "Items to deliver at the stop."
},
"source": {
"enum": [
"UNKNOWN",
"SHOPIFY_ORDER",
"SAVED_STOP",
"IMPORTED_STOP"
],
"type": "string",
"description": "The source of the stop, which may be populated for `DELIVERY` stops. The\n source can be a `SHOPIFY_ORDER`, an EasyRoutes `SAVED_STOP`, or an\n `IMPORTED_STOP` from an external source (such as CSV file).",
"format": "enum",
"examples": [
"IMPORTED_STOP"
]
},
"shopifyOrderId": {
"type": "string",
"description": "The Shopify order ID, populated when the stop source is a `SHOPIFY_ORDER`.",
"examples": [
"6229749334323"
]
},
"savedStopId": {
"type": "string",
"description": "The saved stop ID, populated when the stop source is a `SAVED_STOP`.",
"examples": [
"sst-123e4567-e89b-12d3-a456-426614174000"
]
},
"deliveredCoordinates": {
"allOf": [
{
"type": "object",
"properties": {
"latitude": {
"type": "number",
"description": "The latitude in degrees. It must be in the range [-90.0, +90.0].",
"format": "double"
},
"longitude": {
"type": "number",
"description": "The longitude in degrees. It must be in the range [-180.0, +180.0].",
"format": "double"
}
},
"description": "An object that represents a latitude/longitude pair. This is expressed as a\n pair of doubles to represent degrees latitude and degrees longitude. Unless\n specified otherwise, this must conform to the\n WGS84\n standard. Values must be within normalized ranges."
}
],
"description": "Delivered coordinates for the stop."
},
"proofOfDeliveryNote": {
"type": "string",
"description": "Proof of delivery note for the stop.",
"examples": [
"Left at door."
]
},
"proofOfDeliveryPhotos": {
"type": "array",
"items": {
"title": "StopAttachment",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Attachment ID (e.g. `\"att-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"att-123e4567-e89b-12d3-a456-426614174000"
]
},
"createdAt": {
"type": "string",
"description": "Timestamp when the attachment was created.",
"format": "date-time",
"examples": [
"2026-03-30T09:05:00Z"
]
},
"url": {
"type": "string",
"description": "URL to fetch the attachment.",
"examples": [
"https://example.com/stop-attachment/attachment-2025-06-03-1"
]
}
},
"description": "An attachment to a stop, such as a proof of delivery photo or signature."
},
"description": "Proof of delivery photos for the stop. Photos may be fetched using the URLs\n on the attachments."
},
"proofOfDeliverySignatures": {
"type": "array",
"items": {
"title": "StopAttachment",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Attachment ID (e.g. `\"att-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"att-123e4567-e89b-12d3-a456-426614174000"
]
},
"createdAt": {
"type": "string",
"description": "Timestamp when the attachment was created.",
"format": "date-time",
"examples": [
"2026-03-30T09:05:00Z"
]
},
"url": {
"type": "string",
"description": "URL to fetch the attachment.",
"examples": [
"https://example.com/stop-attachment/attachment-2025-06-03-1"
]
}
},
"description": "An attachment to a stop, such as a proof of delivery photo or signature."
},
"description": "Proof of delivery signatures for the stop. Signatures may be fetched using\n the URLs on the attachments."
},
"tasks": {
"type": "array",
"items": {
"title": "Task",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Task ID (e.g. `\"tsk-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"tsk-123e4567-e89b-12d3-a456-426614174000"
]
},
"title": {
"type": "string",
"description": "Task title (e.g. `\"Delivery checklist\"`).",
"examples": [
"Delivery checklist"
]
},
"type": {
"enum": [
"UNKNOWN",
"CHECKBOXES",
"RADIO_BUTTONS",
"TEXT_INPUT",
"DECIMAL_INPUT",
"SCANNER_INPUT"
],
"type": "string",
"description": "Task type.",
"format": "enum",
"examples": [
"TEXT_INPUT"
]
},
"items": {
"type": "array",
"items": {
"title": "TaskItem",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Item ID (e.g. `\"itm-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"itm-123e4567-e89b-12d3-a456-426614174000"
]
},
"title": {
"type": "string",
"description": "Item title (e.g. `\"Pick up package\"`).",
"examples": [
"Pick up package"
]
},
"complete": {
"type": "boolean",
"description": "Whether the item is completed.",
"examples": [
true
]
},
"updatedAt": {
"type": "string",
"description": "Timestamp when the item was last updated.",
"format": "date-time",
"examples": [
"2026-03-30T13:00:00Z"
]
}
},
"description": "An item within a task. For `CHECKBOXES`, each item on a task may be completed\n independently. For `RADIO_BUTTONS`, at most one item will be completed."
},
"description": "Task items (populated for `CHECKBOXES` and `RADIO_BUTTONS`).",
"examples": [
[]
]
},
"input": {
"allOf": [
{
"title": "TaskInput",
"type": "object",
"properties": {
"value": {
"type": "string",
"description": "Input value.",
"examples": [
"020123456789"
]
},
"updatedAt": {
"type": "string",
"description": "Timestamp when the input was last updated.",
"format": "date-time",
"examples": [
"2026-03-30T13:00:00Z"
]
},
"inputMethod": {
"enum": [
"UNKNOWN",
"SCANNED"
],
"type": "string",
"description": "Whether input was scanned (e.g. a scanned barcode)",
"format": "enum",
"examples": [
"SCANNED"
]
}
},
"description": "Captured driver input for a task. The value may be text for `TEXT_INPUT`\n tasks or a string decimal number for `DECIMAL_INPUT` tasks."
}
],
"description": "Task input (populated for `TEXT_INPUT` and `DECIMAL_INPUT`)."
},
"requiredToMarkStopAsDelivered": {
"type": "boolean",
"description": "Whether the task is required to mark the stop as completed. In the case of\n tasks on `RouteStart`, this represents tasks required for starting the\n route. In the case of tasks on `RouteEnd`, this represents tasks required\n for completing the route.",
"examples": [
true
]
},
"requiredToMarkStopAsAttempted": {
"type": "boolean",
"description": "Whether the task is required to mark the stop as attempted.",
"examples": [
true
]
}
},
"description": "A task to be completed at a stop, or at the start or end of a route. Tasks\n may have one or more items for `CHECKBOXES` or `RADIO_BUTTONS`, or may have\n an input for `TEXT_INPUT` or `DECIMAL_INPUT`."
},
"description": "Driver tasks for the stop, including completed items and any input from the\n driver."
},
"priority": {
"maximum": 10,
"type": "integer",
"description": "Priority of the stop for route planning. The valid range for stop priority\n is between `1` (low) and `10` (high), with default priority corresponding\n to a value of `5`. A priority value of `0` is considered unset and is\n treated the same as \"default\" priority. Stops with higher priority will be\n preferred when generating routes with constraints.",
"format": "int32",
"examples": [
8
]
},
"importedStopId": {
"type": "string",
"description": "The imported stop ID, populated when the stop source is `IMPORTED_STOP`.",
"examples": [
"ist-123e4567-e89b-12d3-a456-426614174000"
]
},
"orderName": {
"type": "string",
"description": "The name of the order associated with the stop. For Shopify orders, the\n name is generated by combining the `orderNumber` property with the order\n prefix and suffix that are set in the merchant's general settings. For\n EasyRoutes imported orders, this field is populated with the order name\n provided on import.",
"examples": [
"#1234"
]
},
"distanceMeters": {
"type": "number",
"description": "The distance in meters from the previous stop.",
"format": "double",
"examples": [
123.45
]
},
"updatedArrival": {
"type": "string",
"description": "Estimated arrival time at the stop. If the stop is completed, this will be\n the actual arrival time.",
"format": "date-time",
"examples": [
"2026-03-30T13:05:00Z"
]
},
"timeWindows": {
"type": "array",
"items": {
"title": "TimeWindow",
"type": "object",
"properties": {
"start": {
"allOf": [
{
"title": "TimeOfDay",
"type": "object",
"properties": {
"hours": {
"maximum": 23,
"type": "integer",
"description": "Hours of day in 24 hour format. Must be from 0 to 23.",
"format": "int32",
"examples": [
13
]
},
"minutes": {
"maximum": 59,
"type": "integer",
"description": "Minutes of hour of day. Must be from 0 to 59.",
"format": "int32",
"examples": [
37
]
},
"seconds": {
"maximum": 59,
"type": "integer",
"description": "Seconds of minutes of the time. Must be from 0 to 59.",
"format": "int32",
"examples": [
16
]
}
},
"description": "A time of day, independent of a particular date or timezone."
}
],
"description": "The start time of the time window (optional)."
},
"end": {
"allOf": [
{
"title": "TimeOfDay",
"type": "object",
"properties": {
"hours": {
"maximum": 23,
"type": "integer",
"description": "Hours of day in 24 hour format. Must be from 0 to 23.",
"format": "int32",
"examples": [
13
]
},
"minutes": {
"maximum": 59,
"type": "integer",
"description": "Minutes of hour of day. Must be from 0 to 59.",
"format": "int32",
"examples": [
37
]
},
"seconds": {
"maximum": 59,
"type": "integer",
"description": "Seconds of minutes of the time. Must be from 0 to 59.",
"format": "int32",
"examples": [
16
]
}
},
"description": "A time of day, independent of a particular date or timezone."
}
],
"description": "The end time of the time window (optional)."
}
},
"description": "A time window for a stop. The time window may be open-ended, but one or both\n of the start and end times should be provided. The end time must be >= the\n start time."
},
"description": "The time window for the stop. Note that we currently support at most one\n time window but may support multiple time windows in the future.",
"examples": [
[
{
"start": {
"hours": 9
},
"end": {
"hours": 17
}
}
]
]
},
"deliveryDate": {
"allOf": [
{
"title": "Date",
"required": [
"year",
"month",
"day"
],
"type": "object",
"properties": {
"year": {
"maximum": 9999,
"minimum": 1,
"type": "integer",
"description": "Year of the date. Must be from 1 to 9999.",
"format": "int32",
"examples": [
2019
]
},
"month": {
"maximum": 12,
"minimum": 1,
"type": "integer",
"description": "Month of a year. Must be from 1 to 12.",
"format": "int32",
"examples": [
11
]
},
"day": {
"maximum": 31,
"minimum": 1,
"type": "integer",
"description": "Day of a month. Must be from 1 to 31.",
"format": "int32",
"examples": [
15
]
}
},
"description": "A date in year-month-day format."
}
],
"description": "The planned delivery date for the stop.",
"examples": [
{
"year": 2025,
"month": 12,
"day": 16
}
]
},
"attributes": {
"type": "array",
"items": {
"title": "Attribute",
"type": "object",
"properties": {
"key": {
"type": "string",
"description": "Attribute key. Must be non-empty.",
"examples": [
"delivery_date"
]
},
"value": {
"type": "string",
"description": "Attribute value.",
"examples": [
"2025-12-16"
]
}
},
"description": "A key-value pair for storing additional information on a stop, such as order\n details, delivery instructions, or custom fields."
},
"description": "Additional attributes for the stop. Attributes are key-value pairs for\n storing additional structured data on stops. These may be populated from\n the Shopify order or set on import.",
"examples": [
[
{
"key": "color",
"value": "blue"
}
]
]
},
"clientStopId": {
"type": "string",
"description": "The client-provided ID associated with the stop, if provided on import.",
"examples": [
"test-order-1234"
]
},
"tags": {
"type": "array",
"items": {
"type": "string"
},
"description": "The tags for the stop. Tags are used to categorize stops and can be used\n for filtering and grouping stops in the EasyRoutes web app. These may be\n populated from the Shopify order or set on import.",
"examples": [
[
"foo",
"bar"
]
]
},
"attemptedReason": {
"enum": [
"UNKNOWN",
"NOT_AVAILABLE",
"ACCESS_DENIED",
"INCORRECT_ADDRESS",
"SAFE_PLACE_UNAVAILABLE",
"REFUSED",
"EXTERNAL",
"INCORRECT_ITEMS",
"OTHER",
"CANCELED"
],
"type": "string",
"description": "The reason for marking the stop as attempted. This is only populated when\n `deliveryStatus = ATTEMPTED_DELIVERY`.",
"format": "enum",
"examples": [
"NOT_AVAILABLE"
]
},
"attemptedNote": {
"type": "string",
"description": "Optional note related to the reason for marking the stop as attempted. This\n is optionally populated when `deliveryStatus = ATTEMPTED_DELIVERY`.",
"examples": [
"Customer did not answer the door."
]
},
"customerRating": {
"allOf": [
{
"title": "CustomerRating",
"type": "object",
"properties": {
"rating": {
"maximum": 5,
"minimum": 1,
"type": "integer",
"description": "Rating from 1-5",
"format": "int32",
"examples": [
5
]
},
"comment": {
"type": "string",
"description": "Customer comment related to rating",
"examples": [
"Excellent delivery"
]
},
"createdAt": {
"type": "string",
"description": "Timestamp when rating was left by customer.",
"format": "date-time",
"examples": [
"2026-03-30T18:00:00Z"
]
}
},
"description": "Customer rating and feedback left on a stop."
}
],
"description": "Rating left by customer. This can only be populated once `deliveryStatus =\n DELIVERED`."
},
"customSignatureDisclosure": {
"type": "string",
"description": "Optional custom signature disclosure that is shown to customers in the\n driver app.",
"examples": [
"I acknowledge that I have received this delivery."
]
},
"shopifyOrder": {
"allOf": [
{
"title": "ShopifyOrder",
"type": "object",
"properties": {
"orderNote": {
"type": "string",
"description": "The Shopify order note.",
"examples": [
"Customer has paid."
]
},
"customerNote": {
"type": "string",
"description": "The Shopify customer note for the order.",
"examples": [
"Leave at door."
]
}
},
"description": "Shopify-specific information for a RouteStop."
}
],
"description": "Information from the associated Shopify order, if applicable. Populated if\n stop source is `SHOPIFY_ORDER`"
},
"proofOfDeliveryBarcodes": {
"type": "array",
"items": {
"title": "ScannedBarcode",
"type": "object",
"properties": {
"value": {
"type": "string",
"description": "Barcode value (e.g. `\"123456789012\"`).",
"examples": [
"123456789012"
]
},
"createdAt": {
"type": "string",
"description": "Timestamp when the barcode was scanned.",
"format": "date-time",
"examples": [
"2026-03-30T13:10:00Z"
]
}
},
"description": "A proof of delivery barcode scanned at a stop."
},
"description": "Proof of delivery barcodes scanned at the stop."
},
"proofOfDeliveryBarcodeIssues": {
"type": "array",
"items": {
"title": "ScannedBarcodeIssue",
"type": "object",
"properties": {
"reason": {
"enum": [
"UNKNOWN",
"ITEM_MISSING",
"NOT_SCANNABLE",
"INCORRECT"
],
"type": "string",
"description": "The reported reason for the barcode issue.",
"format": "enum",
"examples": [
"ITEM_MISSING"
]
},
"note": {
"type": "string",
"description": "Optional note related to the reason for reporting a barcode issue.",
"examples": [
"Item was not packed."
]
},
"createdAt": {
"type": "string",
"description": "Timestamp when the issue was reported.",
"format": "date-time",
"examples": [
"2026-03-30T13:10:00Z"
]
}
},
"description": "A reported issue related to scanning barcodes at a stop."
},
"description": "Proof of delivery barcode issues reported at the stop."
},
"orderReferenceUrl": {
"type": "string",
"description": "A reference URL for the order associated with the stop (e.g. a link to the\n order in your order management system). Must be a valid HTTPS URL. This\n field can only be populated for imported stops.",
"examples": [
"https://orders.example.com/orders/148977776"
]
}
},
"description": "A stop on a route. A stop may correspond to a delivery or a driver break as\n determined by the type. A delivery stop will have location and contact\n information, items to deliver, optional order details, status, arrival time\n and stop duration, driver tasks and any proof of delivery information. A\n break stop will have start time and duration, and status."
}
}
}
},
"default": {
"description": "Default error response",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"code": {
"type": "integer",
"description": "The status code, which should be an enum value of [google.rpc.Code][google.rpc.Code].",
"format": "int32"
},
"message": {
"type": "string",
"description": "A developer-facing error message, which should be in English. Any user-facing error message should be localized and sent in the [google.rpc.Status.details][google.rpc.Status.details] field, or localized by the client."
},
"details": {
"type": "array",
"items": {
"type": "object",
"properties": {
"@type": {
"type": "string",
"description": "The type of the serialized message."
}
},
"additionalProperties": true,
"description": "Contains an arbitrary serialized message along with a @type that describes the type of the serialized message."
},
"description": "A list of messages that carry the error details. There is a common set of message types for APIs to use."
}
},
"description": "The `Status` type defines a logical error model that is suitable for different programming environments, including REST APIs and RPC APIs. It is used by [gRPC](https://github.com/grpc). Each `Status` message contains three pieces of data: error code, error message, and error details. You can find out more about this error model and how to work with it in the [API Design Guide](https://cloud.google.com/apis/design/errors)."
}
}
}
}
},
"security": [
{
"bearerAuth": []
}
],
"components": {
"securitySchemes": {
"bearerAuth": {
"type": "http",
"description": "Access token from `/authenticate`",
"scheme": "bearer",
"bearerFormat": "JWT"
}
}
}
}
```
# Update route stop (https://docs.roundtrip.ai/docs/api-reference/stops/patch-routes-routeId-stops-stopId)
PATCH /routes/{routeId}/stops/{stopId}
Updates an imported stop on a route by route ID and stop ID. Only stops
that were previously imported via ImportStops (i.e. stops with an
`importedStopId`) can be updated through this endpoint; stops created from
Shopify orders, saved stops, or manually created stops cannot. This is a
partial update: provide the fields to change in `routeStop` and list their
paths in `updateMask`. Only the paths listed in `updateMask` are applied;
omitted fields are left unchanged. The route must not be archived, though
it may be in progress or completed, so it is up to the caller to decide
when it is appropriate to update a stop.
## OpenAPI specification
```json
{
"servers": [
{
"url": "https://easyroutes.roundtrip.ai/api/2024-07"
}
],
"tags": [
"Stops"
],
"summary": "Update route stop",
"description": "Updates an imported stop on a route by route ID and stop ID. Only stops\n that were previously imported via ImportStops (i.e. stops with an\n `importedStopId`) can be updated through this endpoint; stops created from\n Shopify orders, saved stops, or manually created stops cannot. This is a\n partial update: provide the fields to change in `routeStop` and list their\n paths in `updateMask`. Only the paths listed in `updateMask` are applied;\n omitted fields are left unchanged. The route must not be archived, though\n it may be in progress or completed, so it is up to the caller to decide\n when it is appropriate to update a stop.",
"operationId": "UpdateRouteStop",
"parameters": [
{
"name": "routeId",
"in": "path",
"description": "The ID of the route to update the stop on.",
"required": true,
"schema": {
"type": "string",
"examples": [
"rte-123e4567-e89b-12d3-a456-426614174000"
]
}
},
{
"name": "stopId",
"in": "path",
"description": "The ID of the stop to update.",
"required": true,
"schema": {
"type": "string",
"examples": [
"rst-123e4567-e89b-12d3-a456-426614174000"
]
}
},
{
"name": "Idempotency-Key",
"in": "header",
"description": "A unique key for safely retrying this operation. For more information read [our guide](https://docs.roundtrip.ai/docs/concepts/idempotency.md).",
"schema": {
"maxLength": 255,
"minLength": 1,
"type": "string"
},
"examples": {
"default": {
"value": "550e8400-e29b-41d4-a716-446655440000"
}
}
}
],
"requestBody": {
"content": {
"application/json": {
"schema": {
"title": "UpdateRouteStopRequest",
"required": [
"routeStop",
"updateMask"
],
"type": "object",
"properties": {
"routeStop": {
"allOf": [
{
"title": "RouteStopUpdate",
"type": "object",
"properties": {
"note": {
"type": "string",
"description": "Top-level note for the stop to update.",
"examples": [
"Leave at door."
]
},
"tags": {
"type": "array",
"items": {
"type": "string"
},
"description": "The tags for the stop to update.",
"examples": [
[
"foo",
"bar"
]
]
},
"contact": {
"allOf": [
{
"title": "Contact",
"type": "object",
"properties": {
"firstName": {
"type": "string",
"description": "First name (e.g. `\"John\"`).",
"examples": [
"John"
]
},
"lastName": {
"type": "string",
"description": "Last name (e.g. `\"Doe\"`).",
"examples": [
"Doe"
]
},
"company": {
"type": "string",
"description": "Company name (e.g. `\"Roundtrip Systems Inc\"`).",
"examples": [
"Roundtrip Systems Inc"
]
},
"phone": {
"type": "string",
"description": "Phone number in [E.164 format](https://en.wikipedia.org/wiki/E.164) (e.g.\n `\"+14265551000\"`).",
"examples": [
"+14265551000"
]
},
"email": {
"type": "string",
"description": "Email address (e.g. `\"john.doe@roundtrip.ai\"`)",
"examples": [
"john.doe@roundtrip.ai"
]
}
},
"description": "Contact information for a person or company."
}
],
"description": "Contact information for the stop delivery recipient.",
"examples": [
{
"firstName": "John",
"lastName": "Doe",
"company": "Roundtrip Systems Inc",
"phone": "+14265551000",
"email": "john.doe@roundtrip.ai"
}
]
},
"timeWindows": {
"type": "array",
"items": {
"title": "TimeWindow",
"type": "object",
"properties": {
"start": {
"allOf": [
{
"title": "TimeOfDay",
"type": "object",
"properties": {
"hours": {
"maximum": 23,
"type": "integer",
"description": "Hours of day in 24 hour format. Must be from 0 to 23.",
"format": "int32",
"examples": [
13
]
},
"minutes": {
"maximum": 59,
"type": "integer",
"description": "Minutes of hour of day. Must be from 0 to 59.",
"format": "int32",
"examples": [
37
]
},
"seconds": {
"maximum": 59,
"type": "integer",
"description": "Seconds of minutes of the time. Must be from 0 to 59.",
"format": "int32",
"examples": [
16
]
}
},
"description": "A time of day, independent of a particular date or timezone."
}
],
"description": "The start time of the time window (optional)."
},
"end": {
"allOf": [
{
"title": "TimeOfDay",
"type": "object",
"properties": {
"hours": {
"maximum": 23,
"type": "integer",
"description": "Hours of day in 24 hour format. Must be from 0 to 23.",
"format": "int32",
"examples": [
13
]
},
"minutes": {
"maximum": 59,
"type": "integer",
"description": "Minutes of hour of day. Must be from 0 to 59.",
"format": "int32",
"examples": [
37
]
},
"seconds": {
"maximum": 59,
"type": "integer",
"description": "Seconds of minutes of the time. Must be from 0 to 59.",
"format": "int32",
"examples": [
16
]
}
},
"description": "A time of day, independent of a particular date or timezone."
}
],
"description": "The end time of the time window (optional)."
}
},
"description": "A time window for a stop. The time window may be open-ended, but one or both\n of the start and end times should be provided. The end time must be >= the\n start time."
},
"description": "The time windows for the stop to update. Replaces all existing time\n windows. At most one time window is currently supported.",
"examples": [
[
{
"start": {
"hours": 9
},
"end": {
"hours": 17
}
}
]
]
},
"attributes": {
"type": "array",
"items": {
"title": "Attribute",
"type": "object",
"properties": {
"key": {
"type": "string",
"description": "Attribute key. Must be non-empty.",
"examples": [
"delivery_date"
]
},
"value": {
"type": "string",
"description": "Attribute value.",
"examples": [
"2025-12-16"
]
}
},
"description": "A key-value pair for storing additional information on a stop, such as order\n details, delivery instructions, or custom fields."
},
"description": "The attributes for the stop to update. Replaces all existing attributes.",
"examples": [
[
{
"key": "color",
"value": "blue"
}
]
]
},
"priority": {
"type": "integer",
"description": "Priority of the stop for route planning.",
"format": "int32",
"examples": [
5
]
},
"deliveryDate": {
"allOf": [
{
"title": "Date",
"required": [
"year",
"month",
"day"
],
"type": "object",
"properties": {
"year": {
"maximum": 9999,
"minimum": 1,
"type": "integer",
"description": "Year of the date. Must be from 1 to 9999.",
"format": "int32",
"examples": [
2019
]
},
"month": {
"maximum": 12,
"minimum": 1,
"type": "integer",
"description": "Month of a year. Must be from 1 to 12.",
"format": "int32",
"examples": [
11
]
},
"day": {
"maximum": 31,
"minimum": 1,
"type": "integer",
"description": "Day of a month. Must be from 1 to 31.",
"format": "int32",
"examples": [
15
]
}
},
"description": "A date in year-month-day format."
}
],
"description": "The delivery date for the stop.",
"examples": [
{
"year": 2025,
"month": 12,
"day": 16
}
]
},
"duration": {
"pattern": "^-?(?:0|[1-9][0-9]{0,11})(?:\\.[0-9]{1,9})?s$",
"type": "string",
"description": "The planned duration for the driver to spend at this stop. This duration is\n used in route optimization to estimate arrival times. If specified, it\n takes precedence over the route's default stop duration. Specified as a\n duration string in the format \"300s\" for 5 minutes, \"60s\" for 1 minute,\n etc.",
"examples": [
"300s"
]
},
"type": {
"enum": [
"UNKNOWN",
"DELIVERY",
"BREAK",
"PICKUP",
"TASK"
],
"type": "string",
"description": "The type of stop (DELIVERY, PICKUP, or TASK). BREAK and UNKNOWN are not\n allowed and will be rejected.",
"format": "enum",
"examples": [
"DELIVERY"
]
},
"orderName": {
"type": "string",
"description": "The name of the order associated with the stop. For Shopify orders, the\n name is generated by combining the order_number property with the order\n prefix and suffix that are set in the merchant's general settings. For\n EasyRoutes imported orders, this field is populated with the order name\n provided on import.",
"examples": [
"#1234"
]
},
"orderReferenceUrl": {
"type": "string",
"description": "A reference URL for the order associated with the stop (e.g. a link to the\n order in your order management system). Must be a valid HTTPS URL.",
"examples": [
"https://orders.example.com/orders/148977776"
]
}
}
}
],
"description": "Update for RouteStop fields to apply to the specified stop."
},
"updateMask": {
"type": "string",
"description": "Comma-separated list of [field mask](https://docs.roundtrip.ai/docs/concepts/field-masks.md) paths in `routeStop` to apply. Only listed paths are updated; omitted fields are left unchanged.",
"format": "field-mask"
}
}
}
}
},
"required": true
},
"responses": {
"200": {
"description": "OK",
"headers": {
"Idempotency-Key": {
"description": "The idempotency key associated with the response.",
"schema": {
"type": "string"
}
},
"Idempotency-Replayed": {
"description": "Whether the response was replayed from a previous request.",
"schema": {
"type": "boolean"
}
}
},
"content": {
"application/json": {
"schema": {
"title": "RouteStop",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Stop ID (e.g. `\"rst-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"rst-123e4567-e89b-12d3-a456-426614174000"
]
},
"type": {
"enum": [
"UNKNOWN",
"DELIVERY",
"BREAK",
"PICKUP",
"TASK"
],
"type": "string",
"description": "The type of stop (DELIVERY, BREAK, PICKUP, or TASK).",
"format": "enum",
"examples": [
"DELIVERY"
]
},
"deliveryStatus": {
"enum": [
"UNKNOWN",
"DELIVERED",
"OUT_FOR_DELIVERY",
"ATTEMPTED_DELIVERY",
"READY_FOR_DELIVERY"
],
"type": "string",
"description": "The status for DELIVERY, PICKUP, or TASK stops.",
"format": "enum",
"examples": [
"ATTEMPTED_DELIVERY"
]
},
"breakStatus": {
"enum": [
"UNKNOWN",
"COMPLETED"
],
"type": "string",
"description": "The status for BREAK stops.",
"format": "enum",
"examples": [
"COMPLETED"
]
},
"updatedAt": {
"type": "string",
"description": "Timestamp when the stop status was last updated. Note that this timestamp\n corresponds only to major status updates (i.e. stop marked as DELIVERED).\n Minor updates like task completion or adding proof of delivery will not\n advance this timestamp. For those events, use the timestamps on the task or\n proof of delivery attachment.",
"format": "date-time",
"examples": [
"2026-03-30T13:15:00Z"
]
},
"duration": {
"pattern": "^-?(?:0|[1-9][0-9]{0,11})(?:\\.[0-9]{1,9})?s$",
"type": "string",
"description": "Planned duration of the stop in seconds.",
"examples": [
"300s"
]
},
"plannedArrival": {
"type": "string",
"description": "Planned arrival time at the stop.",
"format": "date-time",
"examples": [
"2026-03-30T13:00:00Z"
]
},
"note": {
"type": "string",
"description": "Top-level note for the stop, as entered manually by route planners,\n inherited from a saved or imported stop, or set by order import automation\n rules.",
"examples": [
"Leave at door."
]
},
"address": {
"allOf": [
{
"title": "Address",
"type": "object",
"properties": {
"address1": {
"type": "string",
"description": "Street address line 1 (e.g. `\"123 Main St\"`).",
"examples": [
"123 Main St"
]
},
"address2": {
"type": "string",
"description": "Street address line 2 (e.g. `\"Apt 101\"`).",
"examples": [
"Apt 3B"
]
},
"city": {
"type": "string",
"description": "City name (e.g. `\"New York\"`).",
"examples": [
"New York"
]
},
"provinceCode": {
"type": "string",
"description": "Province or state as subdivision codes in\n [ISO 3166-2](https://en.wikipedia.org/wiki/ISO_3166-2) format without the\n country prefix (e.g. `\"NY\"` for New York).",
"examples": [
"NY"
]
},
"countryCode": {
"type": "string",
"description": "Country code (e.g. `\"US\"`).",
"examples": [
"US"
]
},
"zip": {
"type": "string",
"description": "Postal or ZIP code (e.g. `\"10001\"`).",
"examples": [
"10001"
]
}
},
"description": "A physical street address."
}
],
"description": "Delivery address for the stop.",
"examples": [
{
"address1": "123 Main St",
"address2": "Apt 3B",
"city": "New York",
"provinceCode": "NY",
"countryCode": "US",
"zip": "10001"
}
]
},
"contact": {
"allOf": [
{
"title": "Contact",
"type": "object",
"properties": {
"firstName": {
"type": "string",
"description": "First name (e.g. `\"John\"`).",
"examples": [
"John"
]
},
"lastName": {
"type": "string",
"description": "Last name (e.g. `\"Doe\"`).",
"examples": [
"Doe"
]
},
"company": {
"type": "string",
"description": "Company name (e.g. `\"Roundtrip Systems Inc\"`).",
"examples": [
"Roundtrip Systems Inc"
]
},
"phone": {
"type": "string",
"description": "Phone number in [E.164 format](https://en.wikipedia.org/wiki/E.164) (e.g.\n `\"+14265551000\"`).",
"examples": [
"+14265551000"
]
},
"email": {
"type": "string",
"description": "Email address (e.g. `\"john.doe@roundtrip.ai\"`)",
"examples": [
"john.doe@roundtrip.ai"
]
}
},
"description": "Contact information for a person or company."
}
],
"description": "Contact information for the stop delivery recipient.",
"examples": [
{
"firstName": "John",
"lastName": "Doe",
"company": "Roundtrip Systems Inc",
"phone": "+14265551000",
"email": "john.doe@roundtrip.ai"
}
]
},
"plannedCoordinates": {
"allOf": [
{
"type": "object",
"properties": {
"latitude": {
"type": "number",
"description": "The latitude in degrees. It must be in the range [-90.0, +90.0].",
"format": "double"
},
"longitude": {
"type": "number",
"description": "The longitude in degrees. It must be in the range [-180.0, +180.0].",
"format": "double"
}
},
"description": "An object that represents a latitude/longitude pair. This is expressed as a\n pair of doubles to represent degrees latitude and degrees longitude. Unless\n specified otherwise, this must conform to the\n WGS84\n standard. Values must be within normalized ranges."
}
],
"description": "Planned coordinates for the stop.",
"examples": [
{
"latitude": 40.7128,
"longitude": -74.006
}
]
},
"items": {
"type": "array",
"items": {
"title": "StopItem",
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "Item name (e.g. `\"Bananas\"`).",
"examples": [
"Bananas"
]
},
"quantity": {
"type": "integer",
"description": "Quantity of the item (e.g. `5`).",
"format": "int32",
"examples": [
5
]
},
"grams": {
"type": "integer",
"description": "Weight of the item in grams (e.g. `500`).",
"format": "int32",
"examples": [
500
]
},
"sku": {
"type": "string",
"description": "Stock keeping unit (e.g. `\"BANANA-001\"`).",
"examples": [
"BANANA-001"
]
}
},
"description": "An item to be delivered at a stop."
},
"description": "Items to deliver at the stop."
},
"source": {
"enum": [
"UNKNOWN",
"SHOPIFY_ORDER",
"SAVED_STOP",
"IMPORTED_STOP"
],
"type": "string",
"description": "The source of the stop, which may be populated for `DELIVERY` stops. The\n source can be a `SHOPIFY_ORDER`, an EasyRoutes `SAVED_STOP`, or an\n `IMPORTED_STOP` from an external source (such as CSV file).",
"format": "enum",
"examples": [
"IMPORTED_STOP"
]
},
"shopifyOrderId": {
"type": "string",
"description": "The Shopify order ID, populated when the stop source is a `SHOPIFY_ORDER`.",
"examples": [
"6229749334323"
]
},
"savedStopId": {
"type": "string",
"description": "The saved stop ID, populated when the stop source is a `SAVED_STOP`.",
"examples": [
"sst-123e4567-e89b-12d3-a456-426614174000"
]
},
"deliveredCoordinates": {
"allOf": [
{
"type": "object",
"properties": {
"latitude": {
"type": "number",
"description": "The latitude in degrees. It must be in the range [-90.0, +90.0].",
"format": "double"
},
"longitude": {
"type": "number",
"description": "The longitude in degrees. It must be in the range [-180.0, +180.0].",
"format": "double"
}
},
"description": "An object that represents a latitude/longitude pair. This is expressed as a\n pair of doubles to represent degrees latitude and degrees longitude. Unless\n specified otherwise, this must conform to the\n WGS84\n standard. Values must be within normalized ranges."
}
],
"description": "Delivered coordinates for the stop."
},
"proofOfDeliveryNote": {
"type": "string",
"description": "Proof of delivery note for the stop.",
"examples": [
"Left at door."
]
},
"proofOfDeliveryPhotos": {
"type": "array",
"items": {
"title": "StopAttachment",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Attachment ID (e.g. `\"att-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"att-123e4567-e89b-12d3-a456-426614174000"
]
},
"createdAt": {
"type": "string",
"description": "Timestamp when the attachment was created.",
"format": "date-time",
"examples": [
"2026-03-30T09:05:00Z"
]
},
"url": {
"type": "string",
"description": "URL to fetch the attachment.",
"examples": [
"https://example.com/stop-attachment/attachment-2025-06-03-1"
]
}
},
"description": "An attachment to a stop, such as a proof of delivery photo or signature."
},
"description": "Proof of delivery photos for the stop. Photos may be fetched using the URLs\n on the attachments."
},
"proofOfDeliverySignatures": {
"type": "array",
"items": {
"title": "StopAttachment",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Attachment ID (e.g. `\"att-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"att-123e4567-e89b-12d3-a456-426614174000"
]
},
"createdAt": {
"type": "string",
"description": "Timestamp when the attachment was created.",
"format": "date-time",
"examples": [
"2026-03-30T09:05:00Z"
]
},
"url": {
"type": "string",
"description": "URL to fetch the attachment.",
"examples": [
"https://example.com/stop-attachment/attachment-2025-06-03-1"
]
}
},
"description": "An attachment to a stop, such as a proof of delivery photo or signature."
},
"description": "Proof of delivery signatures for the stop. Signatures may be fetched using\n the URLs on the attachments."
},
"tasks": {
"type": "array",
"items": {
"title": "Task",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Task ID (e.g. `\"tsk-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"tsk-123e4567-e89b-12d3-a456-426614174000"
]
},
"title": {
"type": "string",
"description": "Task title (e.g. `\"Delivery checklist\"`).",
"examples": [
"Delivery checklist"
]
},
"type": {
"enum": [
"UNKNOWN",
"CHECKBOXES",
"RADIO_BUTTONS",
"TEXT_INPUT",
"DECIMAL_INPUT",
"SCANNER_INPUT"
],
"type": "string",
"description": "Task type.",
"format": "enum",
"examples": [
"TEXT_INPUT"
]
},
"items": {
"type": "array",
"items": {
"title": "TaskItem",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Item ID (e.g. `\"itm-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"itm-123e4567-e89b-12d3-a456-426614174000"
]
},
"title": {
"type": "string",
"description": "Item title (e.g. `\"Pick up package\"`).",
"examples": [
"Pick up package"
]
},
"complete": {
"type": "boolean",
"description": "Whether the item is completed.",
"examples": [
true
]
},
"updatedAt": {
"type": "string",
"description": "Timestamp when the item was last updated.",
"format": "date-time",
"examples": [
"2026-03-30T13:00:00Z"
]
}
},
"description": "An item within a task. For `CHECKBOXES`, each item on a task may be completed\n independently. For `RADIO_BUTTONS`, at most one item will be completed."
},
"description": "Task items (populated for `CHECKBOXES` and `RADIO_BUTTONS`).",
"examples": [
[]
]
},
"input": {
"allOf": [
{
"title": "TaskInput",
"type": "object",
"properties": {
"value": {
"type": "string",
"description": "Input value.",
"examples": [
"020123456789"
]
},
"updatedAt": {
"type": "string",
"description": "Timestamp when the input was last updated.",
"format": "date-time",
"examples": [
"2026-03-30T13:00:00Z"
]
},
"inputMethod": {
"enum": [
"UNKNOWN",
"SCANNED"
],
"type": "string",
"description": "Whether input was scanned (e.g. a scanned barcode)",
"format": "enum",
"examples": [
"SCANNED"
]
}
},
"description": "Captured driver input for a task. The value may be text for `TEXT_INPUT`\n tasks or a string decimal number for `DECIMAL_INPUT` tasks."
}
],
"description": "Task input (populated for `TEXT_INPUT` and `DECIMAL_INPUT`)."
},
"requiredToMarkStopAsDelivered": {
"type": "boolean",
"description": "Whether the task is required to mark the stop as completed. In the case of\n tasks on `RouteStart`, this represents tasks required for starting the\n route. In the case of tasks on `RouteEnd`, this represents tasks required\n for completing the route.",
"examples": [
true
]
},
"requiredToMarkStopAsAttempted": {
"type": "boolean",
"description": "Whether the task is required to mark the stop as attempted.",
"examples": [
true
]
}
},
"description": "A task to be completed at a stop, or at the start or end of a route. Tasks\n may have one or more items for `CHECKBOXES` or `RADIO_BUTTONS`, or may have\n an input for `TEXT_INPUT` or `DECIMAL_INPUT`."
},
"description": "Driver tasks for the stop, including completed items and any input from the\n driver."
},
"priority": {
"maximum": 10,
"type": "integer",
"description": "Priority of the stop for route planning. The valid range for stop priority\n is between `1` (low) and `10` (high), with default priority corresponding\n to a value of `5`. A priority value of `0` is considered unset and is\n treated the same as \"default\" priority. Stops with higher priority will be\n preferred when generating routes with constraints.",
"format": "int32",
"examples": [
8
]
},
"importedStopId": {
"type": "string",
"description": "The imported stop ID, populated when the stop source is `IMPORTED_STOP`.",
"examples": [
"ist-123e4567-e89b-12d3-a456-426614174000"
]
},
"orderName": {
"type": "string",
"description": "The name of the order associated with the stop. For Shopify orders, the\n name is generated by combining the `orderNumber` property with the order\n prefix and suffix that are set in the merchant's general settings. For\n EasyRoutes imported orders, this field is populated with the order name\n provided on import.",
"examples": [
"#1234"
]
},
"distanceMeters": {
"type": "number",
"description": "The distance in meters from the previous stop.",
"format": "double",
"examples": [
123.45
]
},
"updatedArrival": {
"type": "string",
"description": "Estimated arrival time at the stop. If the stop is completed, this will be\n the actual arrival time.",
"format": "date-time",
"examples": [
"2026-03-30T13:05:00Z"
]
},
"timeWindows": {
"type": "array",
"items": {
"title": "TimeWindow",
"type": "object",
"properties": {
"start": {
"allOf": [
{
"title": "TimeOfDay",
"type": "object",
"properties": {
"hours": {
"maximum": 23,
"type": "integer",
"description": "Hours of day in 24 hour format. Must be from 0 to 23.",
"format": "int32",
"examples": [
13
]
},
"minutes": {
"maximum": 59,
"type": "integer",
"description": "Minutes of hour of day. Must be from 0 to 59.",
"format": "int32",
"examples": [
37
]
},
"seconds": {
"maximum": 59,
"type": "integer",
"description": "Seconds of minutes of the time. Must be from 0 to 59.",
"format": "int32",
"examples": [
16
]
}
},
"description": "A time of day, independent of a particular date or timezone."
}
],
"description": "The start time of the time window (optional)."
},
"end": {
"allOf": [
{
"title": "TimeOfDay",
"type": "object",
"properties": {
"hours": {
"maximum": 23,
"type": "integer",
"description": "Hours of day in 24 hour format. Must be from 0 to 23.",
"format": "int32",
"examples": [
13
]
},
"minutes": {
"maximum": 59,
"type": "integer",
"description": "Minutes of hour of day. Must be from 0 to 59.",
"format": "int32",
"examples": [
37
]
},
"seconds": {
"maximum": 59,
"type": "integer",
"description": "Seconds of minutes of the time. Must be from 0 to 59.",
"format": "int32",
"examples": [
16
]
}
},
"description": "A time of day, independent of a particular date or timezone."
}
],
"description": "The end time of the time window (optional)."
}
},
"description": "A time window for a stop. The time window may be open-ended, but one or both\n of the start and end times should be provided. The end time must be >= the\n start time."
},
"description": "The time window for the stop. Note that we currently support at most one\n time window but may support multiple time windows in the future.",
"examples": [
[
{
"start": {
"hours": 9
},
"end": {
"hours": 17
}
}
]
]
},
"deliveryDate": {
"allOf": [
{
"title": "Date",
"required": [
"year",
"month",
"day"
],
"type": "object",
"properties": {
"year": {
"maximum": 9999,
"minimum": 1,
"type": "integer",
"description": "Year of the date. Must be from 1 to 9999.",
"format": "int32",
"examples": [
2019
]
},
"month": {
"maximum": 12,
"minimum": 1,
"type": "integer",
"description": "Month of a year. Must be from 1 to 12.",
"format": "int32",
"examples": [
11
]
},
"day": {
"maximum": 31,
"minimum": 1,
"type": "integer",
"description": "Day of a month. Must be from 1 to 31.",
"format": "int32",
"examples": [
15
]
}
},
"description": "A date in year-month-day format."
}
],
"description": "The planned delivery date for the stop.",
"examples": [
{
"year": 2025,
"month": 12,
"day": 16
}
]
},
"attributes": {
"type": "array",
"items": {
"title": "Attribute",
"type": "object",
"properties": {
"key": {
"type": "string",
"description": "Attribute key. Must be non-empty.",
"examples": [
"delivery_date"
]
},
"value": {
"type": "string",
"description": "Attribute value.",
"examples": [
"2025-12-16"
]
}
},
"description": "A key-value pair for storing additional information on a stop, such as order\n details, delivery instructions, or custom fields."
},
"description": "Additional attributes for the stop. Attributes are key-value pairs for\n storing additional structured data on stops. These may be populated from\n the Shopify order or set on import.",
"examples": [
[
{
"key": "color",
"value": "blue"
}
]
]
},
"clientStopId": {
"type": "string",
"description": "The client-provided ID associated with the stop, if provided on import.",
"examples": [
"test-order-1234"
]
},
"tags": {
"type": "array",
"items": {
"type": "string"
},
"description": "The tags for the stop. Tags are used to categorize stops and can be used\n for filtering and grouping stops in the EasyRoutes web app. These may be\n populated from the Shopify order or set on import.",
"examples": [
[
"foo",
"bar"
]
]
},
"attemptedReason": {
"enum": [
"UNKNOWN",
"NOT_AVAILABLE",
"ACCESS_DENIED",
"INCORRECT_ADDRESS",
"SAFE_PLACE_UNAVAILABLE",
"REFUSED",
"EXTERNAL",
"INCORRECT_ITEMS",
"OTHER",
"CANCELED"
],
"type": "string",
"description": "The reason for marking the stop as attempted. This is only populated when\n `deliveryStatus = ATTEMPTED_DELIVERY`.",
"format": "enum",
"examples": [
"NOT_AVAILABLE"
]
},
"attemptedNote": {
"type": "string",
"description": "Optional note related to the reason for marking the stop as attempted. This\n is optionally populated when `deliveryStatus = ATTEMPTED_DELIVERY`.",
"examples": [
"Customer did not answer the door."
]
},
"customerRating": {
"allOf": [
{
"title": "CustomerRating",
"type": "object",
"properties": {
"rating": {
"maximum": 5,
"minimum": 1,
"type": "integer",
"description": "Rating from 1-5",
"format": "int32",
"examples": [
5
]
},
"comment": {
"type": "string",
"description": "Customer comment related to rating",
"examples": [
"Excellent delivery"
]
},
"createdAt": {
"type": "string",
"description": "Timestamp when rating was left by customer.",
"format": "date-time",
"examples": [
"2026-03-30T18:00:00Z"
]
}
},
"description": "Customer rating and feedback left on a stop."
}
],
"description": "Rating left by customer. This can only be populated once `deliveryStatus =\n DELIVERED`."
},
"customSignatureDisclosure": {
"type": "string",
"description": "Optional custom signature disclosure that is shown to customers in the\n driver app.",
"examples": [
"I acknowledge that I have received this delivery."
]
},
"shopifyOrder": {
"allOf": [
{
"title": "ShopifyOrder",
"type": "object",
"properties": {
"orderNote": {
"type": "string",
"description": "The Shopify order note.",
"examples": [
"Customer has paid."
]
},
"customerNote": {
"type": "string",
"description": "The Shopify customer note for the order.",
"examples": [
"Leave at door."
]
}
},
"description": "Shopify-specific information for a RouteStop."
}
],
"description": "Information from the associated Shopify order, if applicable. Populated if\n stop source is `SHOPIFY_ORDER`"
},
"proofOfDeliveryBarcodes": {
"type": "array",
"items": {
"title": "ScannedBarcode",
"type": "object",
"properties": {
"value": {
"type": "string",
"description": "Barcode value (e.g. `\"123456789012\"`).",
"examples": [
"123456789012"
]
},
"createdAt": {
"type": "string",
"description": "Timestamp when the barcode was scanned.",
"format": "date-time",
"examples": [
"2026-03-30T13:10:00Z"
]
}
},
"description": "A proof of delivery barcode scanned at a stop."
},
"description": "Proof of delivery barcodes scanned at the stop."
},
"proofOfDeliveryBarcodeIssues": {
"type": "array",
"items": {
"title": "ScannedBarcodeIssue",
"type": "object",
"properties": {
"reason": {
"enum": [
"UNKNOWN",
"ITEM_MISSING",
"NOT_SCANNABLE",
"INCORRECT"
],
"type": "string",
"description": "The reported reason for the barcode issue.",
"format": "enum",
"examples": [
"ITEM_MISSING"
]
},
"note": {
"type": "string",
"description": "Optional note related to the reason for reporting a barcode issue.",
"examples": [
"Item was not packed."
]
},
"createdAt": {
"type": "string",
"description": "Timestamp when the issue was reported.",
"format": "date-time",
"examples": [
"2026-03-30T13:10:00Z"
]
}
},
"description": "A reported issue related to scanning barcodes at a stop."
},
"description": "Proof of delivery barcode issues reported at the stop."
},
"orderReferenceUrl": {
"type": "string",
"description": "A reference URL for the order associated with the stop (e.g. a link to the\n order in your order management system). Must be a valid HTTPS URL. This\n field can only be populated for imported stops.",
"examples": [
"https://orders.example.com/orders/148977776"
]
}
},
"description": "A stop on a route. A stop may correspond to a delivery or a driver break as\n determined by the type. A delivery stop will have location and contact\n information, items to deliver, optional order details, status, arrival time\n and stop duration, driver tasks and any proof of delivery information. A\n break stop will have start time and duration, and status."
}
}
}
},
"default": {
"description": "Default error response",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"code": {
"type": "integer",
"description": "The status code, which should be an enum value of [google.rpc.Code][google.rpc.Code].",
"format": "int32"
},
"message": {
"type": "string",
"description": "A developer-facing error message, which should be in English. Any user-facing error message should be localized and sent in the [google.rpc.Status.details][google.rpc.Status.details] field, or localized by the client."
},
"details": {
"type": "array",
"items": {
"type": "object",
"properties": {
"@type": {
"type": "string",
"description": "The type of the serialized message."
}
},
"additionalProperties": true,
"description": "Contains an arbitrary serialized message along with a @type that describes the type of the serialized message."
},
"description": "A list of messages that carry the error details. There is a common set of message types for APIs to use."
}
},
"description": "The `Status` type defines a logical error model that is suitable for different programming environments, including REST APIs and RPC APIs. It is used by [gRPC](https://github.com/grpc). Each `Status` message contains three pieces of data: error code, error message, and error details. You can find out more about this error model and how to work with it in the [API Design Guide](https://cloud.google.com/apis/design/errors)."
}
}
}
}
},
"security": [
{
"bearerAuth": []
}
],
"components": {
"securitySchemes": {
"bearerAuth": {
"type": "http",
"description": "Access token from `/authenticate`",
"scheme": "bearer",
"bearerFormat": "JWT"
}
}
}
}
```
# Update imported stop location (https://docs.roundtrip.ai/docs/api-reference/stops/patch-stops-imports-id-location)
PATCH /stops/imports/{id}/location
Updates the address and/or coordinates for an imported stop by ID. The ID
can be the EasyRoutes `id` returned on import or the client-provided
`clientStopId`. This is a partial update: provide the fields to change in
`location` and list their paths in `updateMask`, which must contain at
least one of `address` or `coordinates`. This only updates the imported
stop record itself; if the stop has already been added to one or more
routes, use UpdateRouteStopLocation to update those route-stop copies. The
response returns the updated ImportedStop.
## OpenAPI specification
```json
{
"servers": [
{
"url": "https://easyroutes.roundtrip.ai/api/2024-07"
}
],
"tags": [
"Stops"
],
"summary": "Update imported stop location",
"description": "Updates the address and/or coordinates for an imported stop by ID. The ID\n can be the EasyRoutes `id` returned on import or the client-provided\n `clientStopId`. This is a partial update: provide the fields to change in\n `location` and list their paths in `updateMask`, which must contain at\n least one of `address` or `coordinates`. This only updates the imported\n stop record itself; if the stop has already been added to one or more\n routes, use UpdateRouteStopLocation to update those route-stop copies. The\n response returns the updated ImportedStop.",
"operationId": "UpdateImportedStopLocation",
"parameters": [
{
"name": "id",
"in": "path",
"description": "The ID of the imported stop to update. You provide the EasyRoutes `id`\n returned on import or the client-provided `clientStopId`.",
"required": true,
"schema": {
"type": "string",
"examples": [
"ist-123e4567-e89b-12d3-a456-426614174000"
]
}
},
{
"name": "Idempotency-Key",
"in": "header",
"description": "A unique key for safely retrying this operation. For more information read [our guide](https://docs.roundtrip.ai/docs/concepts/idempotency.md).",
"schema": {
"maxLength": 255,
"minLength": 1,
"type": "string"
},
"examples": {
"default": {
"value": "550e8400-e29b-41d4-a716-446655440000"
}
}
}
],
"requestBody": {
"content": {
"application/json": {
"schema": {
"title": "UpdateImportedStopLocationRequest",
"required": [
"location",
"updateMask"
],
"type": "object",
"properties": {
"location": {
"allOf": [
{
"title": "ImportedStopLocationUpdate",
"type": "object",
"properties": {
"address": {
"allOf": [
{
"title": "Address",
"type": "object",
"properties": {
"address1": {
"type": "string",
"description": "Street address line 1 (e.g. `\"123 Main St\"`).",
"examples": [
"123 Main St"
]
},
"address2": {
"type": "string",
"description": "Street address line 2 (e.g. `\"Apt 101\"`).",
"examples": [
"Apt 3B"
]
},
"city": {
"type": "string",
"description": "City name (e.g. `\"New York\"`).",
"examples": [
"New York"
]
},
"provinceCode": {
"type": "string",
"description": "Province or state as subdivision codes in\n [ISO 3166-2](https://en.wikipedia.org/wiki/ISO_3166-2) format without the\n country prefix (e.g. `\"NY\"` for New York).",
"examples": [
"NY"
]
},
"countryCode": {
"type": "string",
"description": "Country code (e.g. `\"US\"`).",
"examples": [
"US"
]
},
"zip": {
"type": "string",
"description": "Postal or ZIP code (e.g. `\"10001\"`).",
"examples": [
"10001"
]
}
},
"description": "A physical street address."
}
],
"description": "The new address for the stop. If `coordinates` is not included in\n `updateMask`, this address is geocoded to determine the stop's new\n coordinates, and the request fails if the address cannot be geocoded.\n Exception: if the stop's coordinates were previously provided explicitly\n (e.g. via `coordinates` on import, or via a prior call with `coordinates`),\n an address-only update leaves the existing coordinates untouched rather\n than re-geocoding; include `coordinates` in `updateMask` to change them.",
"examples": [
{
"address1": "123 Main St",
"address2": "Apt 3B",
"city": "New York",
"provinceCode": "NY",
"countryCode": "US",
"zip": "10001"
}
]
},
"coordinates": {
"allOf": [
{
"type": "object",
"properties": {
"latitude": {
"type": "number",
"description": "The latitude in degrees. It must be in the range [-90.0, +90.0].",
"format": "double"
},
"longitude": {
"type": "number",
"description": "The longitude in degrees. It must be in the range [-180.0, +180.0].",
"format": "double"
}
},
"description": "An object that represents a latitude/longitude pair. This is expressed as a\n pair of doubles to represent degrees latitude and degrees longitude. Unless\n specified otherwise, this must conform to the\n WGS84\n standard. Values must be within normalized ranges."
}
],
"description": "The new coordinates for the stop. If included in `updateMask`, these\n coordinates are used directly instead of geocoding the address, and are\n treated as an explicit override of the stop's location.",
"examples": [
{
"latitude": 40.7128,
"longitude": -74.006
}
]
}
}
}
],
"description": "Update for the stop's location."
},
"updateMask": {
"type": "string",
"description": "Comma-separated list of [field mask](https://docs.roundtrip.ai/docs/concepts/field-masks.md) paths in `location` to apply. Only listed paths are updated; omitted fields are left unchanged. Must contain at least one of `address` or `coordinates`.",
"format": "field-mask"
}
}
}
}
},
"required": true
},
"responses": {
"200": {
"description": "OK",
"headers": {
"Idempotency-Key": {
"description": "The idempotency key associated with the response.",
"schema": {
"type": "string"
}
},
"Idempotency-Replayed": {
"description": "Whether the response was replayed from a previous request.",
"schema": {
"type": "boolean"
}
}
},
"content": {
"application/json": {
"schema": {
"title": "ImportedStop",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "The ID of the imported stop, generated by EasyRoutes (e.g.\n `\"ist-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"ist-123e4567-e89b-12d3-a456-426614174000"
]
},
"clientStopId": {
"type": "string",
"description": "The client-provided ID associated with the imported stop, if provided.",
"examples": [
"test-order-1234"
]
},
"address": {
"allOf": [
{
"title": "Address",
"type": "object",
"properties": {
"address1": {
"type": "string",
"description": "Street address line 1 (e.g. `\"123 Main St\"`).",
"examples": [
"123 Main St"
]
},
"address2": {
"type": "string",
"description": "Street address line 2 (e.g. `\"Apt 101\"`).",
"examples": [
"Apt 3B"
]
},
"city": {
"type": "string",
"description": "City name (e.g. `\"New York\"`).",
"examples": [
"New York"
]
},
"provinceCode": {
"type": "string",
"description": "Province or state as subdivision codes in\n [ISO 3166-2](https://en.wikipedia.org/wiki/ISO_3166-2) format without the\n country prefix (e.g. `\"NY\"` for New York).",
"examples": [
"NY"
]
},
"countryCode": {
"type": "string",
"description": "Country code (e.g. `\"US\"`).",
"examples": [
"US"
]
},
"zip": {
"type": "string",
"description": "Postal or ZIP code (e.g. `\"10001\"`).",
"examples": [
"10001"
]
}
},
"description": "A physical street address."
}
],
"description": "The address for the stop.",
"examples": [
{
"address1": "123 Main St",
"address2": "Apt 3B",
"city": "New York",
"provinceCode": "NY",
"countryCode": "US",
"zip": "10001"
}
]
},
"contact": {
"allOf": [
{
"title": "Contact",
"type": "object",
"properties": {
"firstName": {
"type": "string",
"description": "First name (e.g. `\"John\"`).",
"examples": [
"John"
]
},
"lastName": {
"type": "string",
"description": "Last name (e.g. `\"Doe\"`).",
"examples": [
"Doe"
]
},
"company": {
"type": "string",
"description": "Company name (e.g. `\"Roundtrip Systems Inc\"`).",
"examples": [
"Roundtrip Systems Inc"
]
},
"phone": {
"type": "string",
"description": "Phone number in [E.164 format](https://en.wikipedia.org/wiki/E.164) (e.g.\n `\"+14265551000\"`).",
"examples": [
"+14265551000"
]
},
"email": {
"type": "string",
"description": "Email address (e.g. `\"john.doe@roundtrip.ai\"`)",
"examples": [
"john.doe@roundtrip.ai"
]
}
},
"description": "Contact information for a person or company."
}
],
"description": "The contact information for the stop.",
"examples": [
{
"firstName": "John",
"lastName": "Doe",
"company": "Roundtrip Systems Inc",
"phone": "+14265551000",
"email": "john.doe@roundtrip.ai"
}
]
},
"coordinates": {
"allOf": [
{
"type": "object",
"properties": {
"latitude": {
"type": "number",
"description": "The latitude in degrees. It must be in the range [-90.0, +90.0].",
"format": "double"
},
"longitude": {
"type": "number",
"description": "The longitude in degrees. It must be in the range [-180.0, +180.0].",
"format": "double"
}
},
"description": "An object that represents a latitude/longitude pair. This is expressed as a\n pair of doubles to represent degrees latitude and degrees longitude. Unless\n specified otherwise, this must conform to the\n WGS84\n standard. Values must be within normalized ranges."
}
],
"description": "The coordinates to use for the stop, if provided on import.",
"examples": [
{
"latitude": 40.7128,
"longitude": -74.006
}
]
},
"items": {
"type": "array",
"items": {
"title": "StopItem",
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "Item name (e.g. `\"Bananas\"`).",
"examples": [
"Bananas"
]
},
"quantity": {
"type": "integer",
"description": "Quantity of the item (e.g. `5`).",
"format": "int32",
"examples": [
5
]
},
"grams": {
"type": "integer",
"description": "Weight of the item in grams (e.g. `500`).",
"format": "int32",
"examples": [
500
]
},
"sku": {
"type": "string",
"description": "Stock keeping unit (e.g. `\"BANANA-001\"`).",
"examples": [
"BANANA-001"
]
}
},
"description": "An item to be delivered at a stop."
},
"description": "The items to deliver at the stop."
},
"note": {
"type": "string",
"description": "A note for the stop.",
"examples": [
"Leave at door."
]
},
"duration": {
"pattern": "^-?(?:0|[1-9][0-9]{0,11})(?:\\.[0-9]{1,9})?s$",
"type": "string",
"description": "The planned duration for the driver to spend at this stop. This duration is\n used in route optimization to estimate arrival times. If specified, it\n takes precedence over the route's default stop duration. Specified as a\n duration string in the format \"300s\" for 5 minutes, \"60s\" for 1 minute,\n etc.",
"examples": [
"300s"
]
},
"priority": {
"maximum": 10,
"type": "integer",
"description": "Priority of the stop for route planning.",
"format": "int32",
"examples": [
5
]
},
"orderName": {
"type": "string",
"description": "The name of the order associated with the stop.",
"examples": [
"#1234"
]
},
"importedAt": {
"type": "string",
"description": "The timestamp at which the stop was imported.",
"format": "date-time",
"examples": [
"2026-03-28T10:00:00Z"
]
},
"timeWindows": {
"type": "array",
"items": {
"title": "TimeWindow",
"type": "object",
"properties": {
"start": {
"allOf": [
{
"title": "TimeOfDay",
"type": "object",
"properties": {
"hours": {
"maximum": 23,
"type": "integer",
"description": "Hours of day in 24 hour format. Must be from 0 to 23.",
"format": "int32",
"examples": [
13
]
},
"minutes": {
"maximum": 59,
"type": "integer",
"description": "Minutes of hour of day. Must be from 0 to 59.",
"format": "int32",
"examples": [
37
]
},
"seconds": {
"maximum": 59,
"type": "integer",
"description": "Seconds of minutes of the time. Must be from 0 to 59.",
"format": "int32",
"examples": [
16
]
}
},
"description": "A time of day, independent of a particular date or timezone."
}
],
"description": "The start time of the time window (optional)."
},
"end": {
"allOf": [
{
"title": "TimeOfDay",
"type": "object",
"properties": {
"hours": {
"maximum": 23,
"type": "integer",
"description": "Hours of day in 24 hour format. Must be from 0 to 23.",
"format": "int32",
"examples": [
13
]
},
"minutes": {
"maximum": 59,
"type": "integer",
"description": "Minutes of hour of day. Must be from 0 to 59.",
"format": "int32",
"examples": [
37
]
},
"seconds": {
"maximum": 59,
"type": "integer",
"description": "Seconds of minutes of the time. Must be from 0 to 59.",
"format": "int32",
"examples": [
16
]
}
},
"description": "A time of day, independent of a particular date or timezone."
}
],
"description": "The end time of the time window (optional)."
}
},
"description": "A time window for a stop. The time window may be open-ended, but one or both\n of the start and end times should be provided. The end time must be >= the\n start time."
},
"description": "The time window for the stop. Note that we currently support at most one\n time window but may support multiple time windows in the future.",
"examples": [
[
{
"start": {
"hours": 9
},
"end": {
"hours": 17
}
}
]
]
},
"deliveryDate": {
"allOf": [
{
"title": "Date",
"required": [
"year",
"month",
"day"
],
"type": "object",
"properties": {
"year": {
"maximum": 9999,
"minimum": 1,
"type": "integer",
"description": "Year of the date. Must be from 1 to 9999.",
"format": "int32",
"examples": [
2019
]
},
"month": {
"maximum": 12,
"minimum": 1,
"type": "integer",
"description": "Month of a year. Must be from 1 to 12.",
"format": "int32",
"examples": [
11
]
},
"day": {
"maximum": 31,
"minimum": 1,
"type": "integer",
"description": "Day of a month. Must be from 1 to 31.",
"format": "int32",
"examples": [
15
]
}
},
"description": "A date in year-month-day format."
}
],
"description": "The delivery date for the stop.",
"examples": [
{
"year": 2025,
"month": 12,
"day": 16
}
]
},
"attributes": {
"type": "array",
"items": {
"title": "Attribute",
"type": "object",
"properties": {
"key": {
"type": "string",
"description": "Attribute key. Must be non-empty.",
"examples": [
"delivery_date"
]
},
"value": {
"type": "string",
"description": "Attribute value.",
"examples": [
"2025-12-16"
]
}
},
"description": "A key-value pair for storing additional information on a stop, such as order\n details, delivery instructions, or custom fields."
},
"description": "The additional key-value attributes set on the imported stop.",
"examples": [
[
{
"key": "color",
"value": "blue"
}
]
]
},
"tags": {
"type": "array",
"items": {
"type": "string"
},
"description": "The tags for the stop.",
"examples": [
[
"foo",
"bar"
]
]
},
"tasks": {
"type": "array",
"items": {
"title": "TaskTemplate",
"type": "object",
"properties": {
"title": {
"type": "string",
"description": "Task title (e.g. `\"Delivery checklist\"`).",
"examples": [
"Delivery checklist"
]
},
"type": {
"enum": [
"UNKNOWN",
"CHECKBOXES",
"RADIO_BUTTONS",
"TEXT_INPUT",
"DECIMAL_INPUT",
"SCANNER_INPUT"
],
"type": "string",
"description": "Task type.",
"format": "enum",
"examples": [
"CHECKBOXES"
]
},
"items": {
"type": "array",
"items": {
"title": "TaskItemTemplate",
"type": "object",
"properties": {
"title": {
"type": "string",
"description": "Item title (e.g. `\"Pick up package\"`).",
"examples": [
"Pick up package"
]
}
},
"description": "An item template for a task. For `CHECKBOXES`, each item on a task may be\n completed independently. For `RADIO_BUTTONS`, at most one item will be\n completed."
},
"description": "Task items, which are required for `CHECKBOXES` and `RADIO_BUTTONS`."
},
"requiredToMarkStopAsDelivered": {
"type": "boolean",
"description": "Whether the task is required to mark the stop as completed.",
"examples": [
true
]
},
"requiredToMarkStopAsAttempted": {
"type": "boolean",
"description": "Whether the task is required to mark the stop as attempted.",
"examples": [
true
]
}
},
"description": "A template for creating tasks at a stop. Task templates may have one or more\n items for `CHECKBOXES` or `RADIO_BUTTONS`. Imported stops may have task\n templates that are used to create tasks when the stop is added to a route."
},
"description": "The tasks for the stop."
},
"type": {
"enum": [
"UNKNOWN",
"DELIVERY",
"BREAK",
"PICKUP",
"TASK"
],
"type": "string",
"description": "The type of stop (DELIVERY, PICKUP, or TASK). Defaults to DELIVERY if not\n provided.",
"format": "enum",
"examples": [
"DELIVERY"
]
},
"customSignatureDisclosure": {
"type": "string",
"description": "Custom signature disclosure for the stop. Only populated if stop type is\n DELIVERY, PICKUP, or TASK.",
"examples": [
"I acknowledge that I have received this delivery."
]
},
"orderReferenceUrl": {
"type": "string",
"description": "A reference URL for the order associated with the stop (e.g. a link to the\n order in your order management system). Must be a valid HTTPS URL.",
"examples": [
"https://orders.example.com/orders/148977776"
]
}
},
"description": "A stop imported into EasyRoutes."
}
}
}
},
"default": {
"description": "Default error response",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"code": {
"type": "integer",
"description": "The status code, which should be an enum value of [google.rpc.Code][google.rpc.Code].",
"format": "int32"
},
"message": {
"type": "string",
"description": "A developer-facing error message, which should be in English. Any user-facing error message should be localized and sent in the [google.rpc.Status.details][google.rpc.Status.details] field, or localized by the client."
},
"details": {
"type": "array",
"items": {
"type": "object",
"properties": {
"@type": {
"type": "string",
"description": "The type of the serialized message."
}
},
"additionalProperties": true,
"description": "Contains an arbitrary serialized message along with a @type that describes the type of the serialized message."
},
"description": "A list of messages that carry the error details. There is a common set of message types for APIs to use."
}
},
"description": "The `Status` type defines a logical error model that is suitable for different programming environments, including REST APIs and RPC APIs. It is used by [gRPC](https://github.com/grpc). Each `Status` message contains three pieces of data: error code, error message, and error details. You can find out more about this error model and how to work with it in the [API Design Guide](https://cloud.google.com/apis/design/errors)."
}
}
}
}
},
"security": [
{
"bearerAuth": []
}
],
"components": {
"securitySchemes": {
"bearerAuth": {
"type": "http",
"description": "Access token from `/authenticate`",
"scheme": "bearer",
"bearerFormat": "JWT"
}
}
}
}
```
# Update imported stop (https://docs.roundtrip.ai/docs/api-reference/stops/patch-stops-imports-id)
PATCH /stops/imports/{id}
Updates top-level fields on an existing imported stop by ID, without
needing to re-send the full stop payload via ImportStops. This is a
partial update: provide the fields to change in `importedStop` and list
their paths in `updateMask`. Only the paths listed in `updateMask` are
applied; omitted fields are left unchanged. The ID can be the EasyRoutes
`id` returned on import or the client-provided `clientStopId`.
## OpenAPI specification
```json
{
"servers": [
{
"url": "https://easyroutes.roundtrip.ai/api/2024-07"
}
],
"tags": [
"Stops"
],
"summary": "Update imported stop",
"description": "Updates top-level fields on an existing imported stop by ID, without\n needing to re-send the full stop payload via ImportStops. This is a\n partial update: provide the fields to change in `importedStop` and list\n their paths in `updateMask`. Only the paths listed in `updateMask` are\n applied; omitted fields are left unchanged. The ID can be the EasyRoutes\n `id` returned on import or the client-provided `clientStopId`.",
"operationId": "UpdateImportedStop",
"parameters": [
{
"name": "id",
"in": "path",
"description": "The ID of the imported stop to update. You provide the EasyRoutes `id`\n returned on import or the client-provided `clientStopId`.",
"required": true,
"schema": {
"type": "string",
"examples": [
"ist-123e4567-e89b-12d3-a456-426614174000"
]
}
},
{
"name": "Idempotency-Key",
"in": "header",
"description": "A unique key for safely retrying this operation. For more information read [our guide](https://docs.roundtrip.ai/docs/concepts/idempotency.md).",
"schema": {
"maxLength": 255,
"minLength": 1,
"type": "string"
},
"examples": {
"default": {
"value": "550e8400-e29b-41d4-a716-446655440000"
}
}
}
],
"requestBody": {
"content": {
"application/json": {
"schema": {
"title": "UpdateImportedStopRequest",
"required": [
"importedStop",
"updateMask"
],
"type": "object",
"properties": {
"importedStop": {
"allOf": [
{
"title": "ImportedStopUpdate",
"type": "object",
"properties": {
"note": {
"type": "string",
"description": "Top-level note for the stop to update.",
"examples": [
"Leave at door."
]
},
"tags": {
"type": "array",
"items": {
"type": "string"
},
"description": "The tags for the stop to update.",
"examples": [
[
"foo",
"bar"
]
]
},
"contact": {
"allOf": [
{
"title": "Contact",
"type": "object",
"properties": {
"firstName": {
"type": "string",
"description": "First name (e.g. `\"John\"`).",
"examples": [
"John"
]
},
"lastName": {
"type": "string",
"description": "Last name (e.g. `\"Doe\"`).",
"examples": [
"Doe"
]
},
"company": {
"type": "string",
"description": "Company name (e.g. `\"Roundtrip Systems Inc\"`).",
"examples": [
"Roundtrip Systems Inc"
]
},
"phone": {
"type": "string",
"description": "Phone number in [E.164 format](https://en.wikipedia.org/wiki/E.164) (e.g.\n `\"+14265551000\"`).",
"examples": [
"+14265551000"
]
},
"email": {
"type": "string",
"description": "Email address (e.g. `\"john.doe@roundtrip.ai\"`)",
"examples": [
"john.doe@roundtrip.ai"
]
}
},
"description": "Contact information for a person or company."
}
],
"description": "Contact information for the stop delivery recipient.",
"examples": [
{
"firstName": "John",
"lastName": "Doe",
"company": "Roundtrip Systems Inc",
"phone": "+14265551000",
"email": "john.doe@roundtrip.ai"
}
]
},
"timeWindows": {
"type": "array",
"items": {
"title": "TimeWindow",
"type": "object",
"properties": {
"start": {
"allOf": [
{
"title": "TimeOfDay",
"type": "object",
"properties": {
"hours": {
"maximum": 23,
"type": "integer",
"description": "Hours of day in 24 hour format. Must be from 0 to 23.",
"format": "int32",
"examples": [
13
]
},
"minutes": {
"maximum": 59,
"type": "integer",
"description": "Minutes of hour of day. Must be from 0 to 59.",
"format": "int32",
"examples": [
37
]
},
"seconds": {
"maximum": 59,
"type": "integer",
"description": "Seconds of minutes of the time. Must be from 0 to 59.",
"format": "int32",
"examples": [
16
]
}
},
"description": "A time of day, independent of a particular date or timezone."
}
],
"description": "The start time of the time window (optional)."
},
"end": {
"allOf": [
{
"title": "TimeOfDay",
"type": "object",
"properties": {
"hours": {
"maximum": 23,
"type": "integer",
"description": "Hours of day in 24 hour format. Must be from 0 to 23.",
"format": "int32",
"examples": [
13
]
},
"minutes": {
"maximum": 59,
"type": "integer",
"description": "Minutes of hour of day. Must be from 0 to 59.",
"format": "int32",
"examples": [
37
]
},
"seconds": {
"maximum": 59,
"type": "integer",
"description": "Seconds of minutes of the time. Must be from 0 to 59.",
"format": "int32",
"examples": [
16
]
}
},
"description": "A time of day, independent of a particular date or timezone."
}
],
"description": "The end time of the time window (optional)."
}
},
"description": "A time window for a stop. The time window may be open-ended, but one or both\n of the start and end times should be provided. The end time must be >= the\n start time."
},
"description": "The time windows for the stop to update. Replaces all existing time\n windows. At most one time window is currently supported.",
"examples": [
[
{
"start": {
"hours": 9
},
"end": {
"hours": 17
}
}
]
]
},
"attributes": {
"type": "array",
"items": {
"title": "Attribute",
"type": "object",
"properties": {
"key": {
"type": "string",
"description": "Attribute key. Must be non-empty.",
"examples": [
"delivery_date"
]
},
"value": {
"type": "string",
"description": "Attribute value.",
"examples": [
"2025-12-16"
]
}
},
"description": "A key-value pair for storing additional information on a stop, such as order\n details, delivery instructions, or custom fields."
},
"description": "The attributes for the stop to update. Replaces all existing attributes.",
"examples": [
[
{
"key": "color",
"value": "blue"
}
]
]
},
"priority": {
"maximum": 10,
"type": "integer",
"description": "Priority of the stop for route planning.",
"format": "int32",
"examples": [
5
]
},
"duration": {
"pattern": "^-?(?:0|[1-9][0-9]{0,11})(?:\\.[0-9]{1,9})?s$",
"type": "string",
"description": "The planned duration for the driver to spend at this stop. This duration is\n used in route optimization to estimate arrival times. If specified, it\n takes precedence over the route's default stop duration. Specified as a\n duration string in the format \"300s\" for 5 minutes, \"60s\" for 1 minute,\n etc.",
"examples": [
"300s"
]
},
"orderName": {
"type": "string",
"description": "The name of the order associated with the stop to update.",
"examples": [
"#1234"
]
},
"deliveryDate": {
"allOf": [
{
"title": "Date",
"required": [
"year",
"month",
"day"
],
"type": "object",
"properties": {
"year": {
"maximum": 9999,
"minimum": 1,
"type": "integer",
"description": "Year of the date. Must be from 1 to 9999.",
"format": "int32",
"examples": [
2019
]
},
"month": {
"maximum": 12,
"minimum": 1,
"type": "integer",
"description": "Month of a year. Must be from 1 to 12.",
"format": "int32",
"examples": [
11
]
},
"day": {
"maximum": 31,
"minimum": 1,
"type": "integer",
"description": "Day of a month. Must be from 1 to 31.",
"format": "int32",
"examples": [
15
]
}
},
"description": "A date in year-month-day format."
}
],
"description": "The delivery date for the stop to update.",
"examples": [
{
"year": 2025,
"month": 12,
"day": 16
}
]
},
"type": {
"enum": [
"UNKNOWN",
"DELIVERY",
"BREAK",
"PICKUP",
"TASK"
],
"type": "string",
"description": "The type of stop (DELIVERY, PICKUP, or TASK). BREAK and UNKNOWN are not\n allowed and will be rejected.",
"format": "enum",
"examples": [
"DELIVERY"
]
},
"customSignatureDisclosure": {
"type": "string",
"description": "Custom signature disclosure for the stop to update. Only applicable for\n stops of type DELIVERY, PICKUP, or TASK.",
"examples": [
"I acknowledge that I have received this delivery."
]
},
"orderReferenceUrl": {
"type": "string",
"description": "A reference URL for the order associated with the stop (e.g. a link to the\n order in your order management system). Must be a valid HTTPS URL.",
"examples": [
"https://orders.example.com/orders/148977776"
]
}
}
}
],
"description": "Update for ImportedStop fields to apply to the specified stop."
},
"updateMask": {
"type": "string",
"description": "Comma-separated list of [field mask](https://docs.roundtrip.ai/docs/concepts/field-masks.md) paths in `importedStop` to apply. Only listed paths are updated; omitted fields are left unchanged.",
"format": "field-mask"
}
}
}
}
},
"required": true
},
"responses": {
"200": {
"description": "OK",
"headers": {
"Idempotency-Key": {
"description": "The idempotency key associated with the response.",
"schema": {
"type": "string"
}
},
"Idempotency-Replayed": {
"description": "Whether the response was replayed from a previous request.",
"schema": {
"type": "boolean"
}
}
},
"content": {
"application/json": {
"schema": {
"title": "ImportedStop",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "The ID of the imported stop, generated by EasyRoutes (e.g.\n `\"ist-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"ist-123e4567-e89b-12d3-a456-426614174000"
]
},
"clientStopId": {
"type": "string",
"description": "The client-provided ID associated with the imported stop, if provided.",
"examples": [
"test-order-1234"
]
},
"address": {
"allOf": [
{
"title": "Address",
"type": "object",
"properties": {
"address1": {
"type": "string",
"description": "Street address line 1 (e.g. `\"123 Main St\"`).",
"examples": [
"123 Main St"
]
},
"address2": {
"type": "string",
"description": "Street address line 2 (e.g. `\"Apt 101\"`).",
"examples": [
"Apt 3B"
]
},
"city": {
"type": "string",
"description": "City name (e.g. `\"New York\"`).",
"examples": [
"New York"
]
},
"provinceCode": {
"type": "string",
"description": "Province or state as subdivision codes in\n [ISO 3166-2](https://en.wikipedia.org/wiki/ISO_3166-2) format without the\n country prefix (e.g. `\"NY\"` for New York).",
"examples": [
"NY"
]
},
"countryCode": {
"type": "string",
"description": "Country code (e.g. `\"US\"`).",
"examples": [
"US"
]
},
"zip": {
"type": "string",
"description": "Postal or ZIP code (e.g. `\"10001\"`).",
"examples": [
"10001"
]
}
},
"description": "A physical street address."
}
],
"description": "The address for the stop.",
"examples": [
{
"address1": "123 Main St",
"address2": "Apt 3B",
"city": "New York",
"provinceCode": "NY",
"countryCode": "US",
"zip": "10001"
}
]
},
"contact": {
"allOf": [
{
"title": "Contact",
"type": "object",
"properties": {
"firstName": {
"type": "string",
"description": "First name (e.g. `\"John\"`).",
"examples": [
"John"
]
},
"lastName": {
"type": "string",
"description": "Last name (e.g. `\"Doe\"`).",
"examples": [
"Doe"
]
},
"company": {
"type": "string",
"description": "Company name (e.g. `\"Roundtrip Systems Inc\"`).",
"examples": [
"Roundtrip Systems Inc"
]
},
"phone": {
"type": "string",
"description": "Phone number in [E.164 format](https://en.wikipedia.org/wiki/E.164) (e.g.\n `\"+14265551000\"`).",
"examples": [
"+14265551000"
]
},
"email": {
"type": "string",
"description": "Email address (e.g. `\"john.doe@roundtrip.ai\"`)",
"examples": [
"john.doe@roundtrip.ai"
]
}
},
"description": "Contact information for a person or company."
}
],
"description": "The contact information for the stop.",
"examples": [
{
"firstName": "John",
"lastName": "Doe",
"company": "Roundtrip Systems Inc",
"phone": "+14265551000",
"email": "john.doe@roundtrip.ai"
}
]
},
"coordinates": {
"allOf": [
{
"type": "object",
"properties": {
"latitude": {
"type": "number",
"description": "The latitude in degrees. It must be in the range [-90.0, +90.0].",
"format": "double"
},
"longitude": {
"type": "number",
"description": "The longitude in degrees. It must be in the range [-180.0, +180.0].",
"format": "double"
}
},
"description": "An object that represents a latitude/longitude pair. This is expressed as a\n pair of doubles to represent degrees latitude and degrees longitude. Unless\n specified otherwise, this must conform to the\n WGS84\n standard. Values must be within normalized ranges."
}
],
"description": "The coordinates to use for the stop, if provided on import.",
"examples": [
{
"latitude": 40.7128,
"longitude": -74.006
}
]
},
"items": {
"type": "array",
"items": {
"title": "StopItem",
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "Item name (e.g. `\"Bananas\"`).",
"examples": [
"Bananas"
]
},
"quantity": {
"type": "integer",
"description": "Quantity of the item (e.g. `5`).",
"format": "int32",
"examples": [
5
]
},
"grams": {
"type": "integer",
"description": "Weight of the item in grams (e.g. `500`).",
"format": "int32",
"examples": [
500
]
},
"sku": {
"type": "string",
"description": "Stock keeping unit (e.g. `\"BANANA-001\"`).",
"examples": [
"BANANA-001"
]
}
},
"description": "An item to be delivered at a stop."
},
"description": "The items to deliver at the stop."
},
"note": {
"type": "string",
"description": "A note for the stop.",
"examples": [
"Leave at door."
]
},
"duration": {
"pattern": "^-?(?:0|[1-9][0-9]{0,11})(?:\\.[0-9]{1,9})?s$",
"type": "string",
"description": "The planned duration for the driver to spend at this stop. This duration is\n used in route optimization to estimate arrival times. If specified, it\n takes precedence over the route's default stop duration. Specified as a\n duration string in the format \"300s\" for 5 minutes, \"60s\" for 1 minute,\n etc.",
"examples": [
"300s"
]
},
"priority": {
"maximum": 10,
"type": "integer",
"description": "Priority of the stop for route planning.",
"format": "int32",
"examples": [
5
]
},
"orderName": {
"type": "string",
"description": "The name of the order associated with the stop.",
"examples": [
"#1234"
]
},
"importedAt": {
"type": "string",
"description": "The timestamp at which the stop was imported.",
"format": "date-time",
"examples": [
"2026-03-28T10:00:00Z"
]
},
"timeWindows": {
"type": "array",
"items": {
"title": "TimeWindow",
"type": "object",
"properties": {
"start": {
"allOf": [
{
"title": "TimeOfDay",
"type": "object",
"properties": {
"hours": {
"maximum": 23,
"type": "integer",
"description": "Hours of day in 24 hour format. Must be from 0 to 23.",
"format": "int32",
"examples": [
13
]
},
"minutes": {
"maximum": 59,
"type": "integer",
"description": "Minutes of hour of day. Must be from 0 to 59.",
"format": "int32",
"examples": [
37
]
},
"seconds": {
"maximum": 59,
"type": "integer",
"description": "Seconds of minutes of the time. Must be from 0 to 59.",
"format": "int32",
"examples": [
16
]
}
},
"description": "A time of day, independent of a particular date or timezone."
}
],
"description": "The start time of the time window (optional)."
},
"end": {
"allOf": [
{
"title": "TimeOfDay",
"type": "object",
"properties": {
"hours": {
"maximum": 23,
"type": "integer",
"description": "Hours of day in 24 hour format. Must be from 0 to 23.",
"format": "int32",
"examples": [
13
]
},
"minutes": {
"maximum": 59,
"type": "integer",
"description": "Minutes of hour of day. Must be from 0 to 59.",
"format": "int32",
"examples": [
37
]
},
"seconds": {
"maximum": 59,
"type": "integer",
"description": "Seconds of minutes of the time. Must be from 0 to 59.",
"format": "int32",
"examples": [
16
]
}
},
"description": "A time of day, independent of a particular date or timezone."
}
],
"description": "The end time of the time window (optional)."
}
},
"description": "A time window for a stop. The time window may be open-ended, but one or both\n of the start and end times should be provided. The end time must be >= the\n start time."
},
"description": "The time window for the stop. Note that we currently support at most one\n time window but may support multiple time windows in the future.",
"examples": [
[
{
"start": {
"hours": 9
},
"end": {
"hours": 17
}
}
]
]
},
"deliveryDate": {
"allOf": [
{
"title": "Date",
"required": [
"year",
"month",
"day"
],
"type": "object",
"properties": {
"year": {
"maximum": 9999,
"minimum": 1,
"type": "integer",
"description": "Year of the date. Must be from 1 to 9999.",
"format": "int32",
"examples": [
2019
]
},
"month": {
"maximum": 12,
"minimum": 1,
"type": "integer",
"description": "Month of a year. Must be from 1 to 12.",
"format": "int32",
"examples": [
11
]
},
"day": {
"maximum": 31,
"minimum": 1,
"type": "integer",
"description": "Day of a month. Must be from 1 to 31.",
"format": "int32",
"examples": [
15
]
}
},
"description": "A date in year-month-day format."
}
],
"description": "The delivery date for the stop.",
"examples": [
{
"year": 2025,
"month": 12,
"day": 16
}
]
},
"attributes": {
"type": "array",
"items": {
"title": "Attribute",
"type": "object",
"properties": {
"key": {
"type": "string",
"description": "Attribute key. Must be non-empty.",
"examples": [
"delivery_date"
]
},
"value": {
"type": "string",
"description": "Attribute value.",
"examples": [
"2025-12-16"
]
}
},
"description": "A key-value pair for storing additional information on a stop, such as order\n details, delivery instructions, or custom fields."
},
"description": "The additional key-value attributes set on the imported stop.",
"examples": [
[
{
"key": "color",
"value": "blue"
}
]
]
},
"tags": {
"type": "array",
"items": {
"type": "string"
},
"description": "The tags for the stop.",
"examples": [
[
"foo",
"bar"
]
]
},
"tasks": {
"type": "array",
"items": {
"title": "TaskTemplate",
"type": "object",
"properties": {
"title": {
"type": "string",
"description": "Task title (e.g. `\"Delivery checklist\"`).",
"examples": [
"Delivery checklist"
]
},
"type": {
"enum": [
"UNKNOWN",
"CHECKBOXES",
"RADIO_BUTTONS",
"TEXT_INPUT",
"DECIMAL_INPUT",
"SCANNER_INPUT"
],
"type": "string",
"description": "Task type.",
"format": "enum",
"examples": [
"CHECKBOXES"
]
},
"items": {
"type": "array",
"items": {
"title": "TaskItemTemplate",
"type": "object",
"properties": {
"title": {
"type": "string",
"description": "Item title (e.g. `\"Pick up package\"`).",
"examples": [
"Pick up package"
]
}
},
"description": "An item template for a task. For `CHECKBOXES`, each item on a task may be\n completed independently. For `RADIO_BUTTONS`, at most one item will be\n completed."
},
"description": "Task items, which are required for `CHECKBOXES` and `RADIO_BUTTONS`."
},
"requiredToMarkStopAsDelivered": {
"type": "boolean",
"description": "Whether the task is required to mark the stop as completed.",
"examples": [
true
]
},
"requiredToMarkStopAsAttempted": {
"type": "boolean",
"description": "Whether the task is required to mark the stop as attempted.",
"examples": [
true
]
}
},
"description": "A template for creating tasks at a stop. Task templates may have one or more\n items for `CHECKBOXES` or `RADIO_BUTTONS`. Imported stops may have task\n templates that are used to create tasks when the stop is added to a route."
},
"description": "The tasks for the stop."
},
"type": {
"enum": [
"UNKNOWN",
"DELIVERY",
"BREAK",
"PICKUP",
"TASK"
],
"type": "string",
"description": "The type of stop (DELIVERY, PICKUP, or TASK). Defaults to DELIVERY if not\n provided.",
"format": "enum",
"examples": [
"DELIVERY"
]
},
"customSignatureDisclosure": {
"type": "string",
"description": "Custom signature disclosure for the stop. Only populated if stop type is\n DELIVERY, PICKUP, or TASK.",
"examples": [
"I acknowledge that I have received this delivery."
]
},
"orderReferenceUrl": {
"type": "string",
"description": "A reference URL for the order associated with the stop (e.g. a link to the\n order in your order management system). Must be a valid HTTPS URL.",
"examples": [
"https://orders.example.com/orders/148977776"
]
}
},
"description": "A stop imported into EasyRoutes."
}
}
}
},
"default": {
"description": "Default error response",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"code": {
"type": "integer",
"description": "The status code, which should be an enum value of [google.rpc.Code][google.rpc.Code].",
"format": "int32"
},
"message": {
"type": "string",
"description": "A developer-facing error message, which should be in English. Any user-facing error message should be localized and sent in the [google.rpc.Status.details][google.rpc.Status.details] field, or localized by the client."
},
"details": {
"type": "array",
"items": {
"type": "object",
"properties": {
"@type": {
"type": "string",
"description": "The type of the serialized message."
}
},
"additionalProperties": true,
"description": "Contains an arbitrary serialized message along with a @type that describes the type of the serialized message."
},
"description": "A list of messages that carry the error details. There is a common set of message types for APIs to use."
}
},
"description": "The `Status` type defines a logical error model that is suitable for different programming environments, including REST APIs and RPC APIs. It is used by [gRPC](https://github.com/grpc). Each `Status` message contains three pieces of data: error code, error message, and error details. You can find out more about this error model and how to work with it in the [API Design Guide](https://cloud.google.com/apis/design/errors)."
}
}
}
}
},
"security": [
{
"bearerAuth": []
}
],
"components": {
"securitySchemes": {
"bearerAuth": {
"type": "http",
"description": "Access token from `/authenticate`",
"scheme": "bearer",
"bearerFormat": "JWT"
}
}
}
}
```
# Reoptimize route (https://docs.roundtrip.ai/docs/api-reference/stops/post-routes-id-reoptimize)
POST /routes/{id}/reoptimize
Reoptimizes a route according to the currently configured route options. If
a route is already optimized, this is a no-op. The returned response is the
reoptimized route.
## OpenAPI specification
```json
{
"servers": [
{
"url": "https://easyroutes.roundtrip.ai/api/2024-07"
}
],
"tags": [
"Stops"
],
"summary": "Reoptimize route",
"description": "Reoptimizes a route according to the currently configured route options. If\n a route is already optimized, this is a no-op. The returned response is the\n reoptimized route.",
"operationId": "ReoptimizeRoute",
"parameters": [
{
"name": "id",
"in": "path",
"description": "The ID of the route to reoptimize.",
"required": true,
"schema": {
"type": "string",
"examples": [
"rte-123e4567-e89b-12d3-a456-426614174000"
]
}
},
{
"name": "Idempotency-Key",
"in": "header",
"description": "A unique key for safely retrying this operation. For more information read [our guide](https://docs.roundtrip.ai/docs/concepts/idempotency.md).",
"schema": {
"maxLength": 255,
"minLength": 1,
"type": "string"
},
"examples": {
"default": {
"value": "550e8400-e29b-41d4-a716-446655440000"
}
}
}
],
"requestBody": {
"content": {
"application/json": {
"schema": {
"title": "ReoptimizeRouteRequest",
"type": "object",
"properties": {
"ignoreCompletedStops": {
"type": "boolean",
"description": "(Optional) The optimization will only be run on stops that are not\n completed (e.g. delivered or attempted) when this is set to true.",
"examples": [
true
]
},
"ignoreRoutingConstraints": {
"type": "boolean",
"description": "(Optional) The optimization will ignore all routing constraints (e.g. max\n route duration, max weight) when this is set to true.",
"examples": [
true
]
}
},
"description": "Request to reoptimize a route by ID."
}
}
},
"required": true
},
"responses": {
"200": {
"description": "OK",
"headers": {
"Idempotency-Key": {
"description": "The idempotency key associated with the response.",
"schema": {
"type": "string"
}
},
"Idempotency-Replayed": {
"description": "Whether the response was replayed from a previous request.",
"schema": {
"type": "boolean"
}
}
},
"content": {
"application/json": {
"schema": {
"title": "Route",
"required": [
"id",
"name",
"stops",
"createdAt",
"updatedAt",
"totalDistanceMeters",
"totalItemQuantity",
"totalItemGrams",
"optimized"
],
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Route ID (e.g. `\"rte-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"rte-123e4567-e89b-12d3-a456-426614174000"
]
},
"name": {
"type": "string",
"description": "Route name (e.g. `\"Morning route\"`).",
"examples": [
"Morning route"
]
},
"driver": {
"allOf": [
{
"title": "Driver",
"required": [
"id"
],
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Driver ID (e.g. `\"drv-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"drv-123e4567-e89b-12d3-a456-426614174000"
]
},
"firstName": {
"type": "string",
"description": "Driver first name (e.g. `\"John\"`).",
"examples": [
"John"
]
},
"lastName": {
"type": "string",
"description": "Driver last name (e.g. `\"Doe\"`).",
"examples": [
"Doe"
]
},
"phone": {
"type": "string",
"description": "Driver phone number in [E.164 format](https://en.wikipedia.org/wiki/E.164)\n (e.g. `\"+14265551000\"`).",
"examples": [
"+14265551000"
]
},
"status": {
"enum": [
"UNKNOWN",
"ACTIVE",
"INACTIVE",
"ARCHIVED"
],
"type": "string",
"description": "Shop driver status. (e.g. `ACTIVE`).",
"format": "enum",
"examples": [
"ACTIVE"
]
}
},
"description": "A driver who is assigned to a route."
}
],
"description": "Assigned driver for the route."
},
"start": {
"allOf": [
{
"title": "RouteStart",
"type": "object",
"properties": {
"address": {
"allOf": [
{
"title": "Address",
"type": "object",
"properties": {
"address1": {
"type": "string",
"description": "Street address line 1 (e.g. `\"123 Main St\"`).",
"examples": [
"123 Main St"
]
},
"address2": {
"type": "string",
"description": "Street address line 2 (e.g. `\"Apt 101\"`).",
"examples": [
"Apt 3B"
]
},
"city": {
"type": "string",
"description": "City name (e.g. `\"New York\"`).",
"examples": [
"New York"
]
},
"provinceCode": {
"type": "string",
"description": "Province or state as subdivision codes in\n [ISO 3166-2](https://en.wikipedia.org/wiki/ISO_3166-2) format without the\n country prefix (e.g. `\"NY\"` for New York).",
"examples": [
"NY"
]
},
"countryCode": {
"type": "string",
"description": "Country code (e.g. `\"US\"`).",
"examples": [
"US"
]
},
"zip": {
"type": "string",
"description": "Postal or ZIP code (e.g. `\"10001\"`).",
"examples": [
"10001"
]
}
},
"description": "A physical street address."
}
],
"description": "The start address of the route.",
"examples": [
{
"address1": "123 Main St",
"address2": "Apt 3B",
"city": "New York",
"provinceCode": "NY",
"countryCode": "US",
"zip": "10001"
}
]
},
"tasks": {
"type": "array",
"items": {
"title": "Task",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Task ID (e.g. `\"tsk-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"tsk-123e4567-e89b-12d3-a456-426614174000"
]
},
"title": {
"type": "string",
"description": "Task title (e.g. `\"Delivery checklist\"`).",
"examples": [
"Delivery checklist"
]
},
"type": {
"enum": [
"UNKNOWN",
"CHECKBOXES",
"RADIO_BUTTONS",
"TEXT_INPUT",
"DECIMAL_INPUT",
"SCANNER_INPUT"
],
"type": "string",
"description": "Task type.",
"format": "enum",
"examples": [
"TEXT_INPUT"
]
},
"items": {
"type": "array",
"items": {
"title": "TaskItem",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Item ID (e.g. `\"itm-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"itm-123e4567-e89b-12d3-a456-426614174000"
]
},
"title": {
"type": "string",
"description": "Item title (e.g. `\"Pick up package\"`).",
"examples": [
"Pick up package"
]
},
"complete": {
"type": "boolean",
"description": "Whether the item is completed.",
"examples": [
true
]
},
"updatedAt": {
"type": "string",
"description": "Timestamp when the item was last updated.",
"format": "date-time",
"examples": [
"2026-03-30T13:00:00Z"
]
}
},
"description": "An item within a task. For `CHECKBOXES`, each item on a task may be completed\n independently. For `RADIO_BUTTONS`, at most one item will be completed."
},
"description": "Task items (populated for `CHECKBOXES` and `RADIO_BUTTONS`).",
"examples": [
[]
]
},
"input": {
"allOf": [
{
"title": "TaskInput",
"type": "object",
"properties": {
"value": {
"type": "string",
"description": "Input value.",
"examples": [
"020123456789"
]
},
"updatedAt": {
"type": "string",
"description": "Timestamp when the input was last updated.",
"format": "date-time",
"examples": [
"2026-03-30T13:00:00Z"
]
},
"inputMethod": {
"enum": [
"UNKNOWN",
"SCANNED"
],
"type": "string",
"description": "Whether input was scanned (e.g. a scanned barcode)",
"format": "enum",
"examples": [
"SCANNED"
]
}
},
"description": "Captured driver input for a task. The value may be text for `TEXT_INPUT`\n tasks or a string decimal number for `DECIMAL_INPUT` tasks."
}
],
"description": "Task input (populated for `TEXT_INPUT` and `DECIMAL_INPUT`)."
},
"requiredToMarkStopAsDelivered": {
"type": "boolean",
"description": "Whether the task is required to mark the stop as completed. In the case of\n tasks on `RouteStart`, this represents tasks required for starting the\n route. In the case of tasks on `RouteEnd`, this represents tasks required\n for completing the route.",
"examples": [
true
]
},
"requiredToMarkStopAsAttempted": {
"type": "boolean",
"description": "Whether the task is required to mark the stop as attempted.",
"examples": [
true
]
}
},
"description": "A task to be completed at a stop, or at the start or end of a route. Tasks\n may have one or more items for `CHECKBOXES` or `RADIO_BUTTONS`, or may have\n an input for `TEXT_INPUT` or `DECIMAL_INPUT`."
},
"description": "Tasks to complete before starting the route."
},
"status": {
"enum": [
"UNKNOWN",
"STARTED"
],
"type": "string",
"description": "Status indicating whether the route has been started.",
"format": "enum",
"examples": [
"STARTED"
]
},
"updatedStart": {
"type": "string",
"description": "Updated start time for the route. If the route is started, this will be the\n actual start time.",
"format": "date-time",
"examples": [
"2026-03-30T09:05:00Z"
]
},
"scheduledStart": {
"type": "string",
"description": "Scheduled start time for the route (same as `scheduledFor` on the route).",
"format": "date-time",
"examples": [
"2026-03-30T09:00:00Z"
]
},
"photos": {
"type": "array",
"items": {
"title": "StopAttachment",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Attachment ID (e.g. `\"att-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"att-123e4567-e89b-12d3-a456-426614174000"
]
},
"createdAt": {
"type": "string",
"description": "Timestamp when the attachment was created.",
"format": "date-time",
"examples": [
"2026-03-30T09:05:00Z"
]
},
"url": {
"type": "string",
"description": "URL to fetch the attachment.",
"examples": [
"https://example.com/stop-attachment/attachment-2025-06-03-1"
]
}
},
"description": "An attachment to a stop, such as a proof of delivery photo or signature."
},
"description": "Photos for the route start. Photos may be fetched using the URLs on the\n attachments."
}
},
"description": "The start location of a route and any driver tasks to complete before\n beginning the route."
}
],
"description": "Route start address and tasks."
},
"end": {
"allOf": [
{
"title": "RouteEnd",
"type": "object",
"properties": {
"address": {
"allOf": [
{
"title": "Address",
"type": "object",
"properties": {
"address1": {
"type": "string",
"description": "Street address line 1 (e.g. `\"123 Main St\"`).",
"examples": [
"123 Main St"
]
},
"address2": {
"type": "string",
"description": "Street address line 2 (e.g. `\"Apt 101\"`).",
"examples": [
"Apt 3B"
]
},
"city": {
"type": "string",
"description": "City name (e.g. `\"New York\"`).",
"examples": [
"New York"
]
},
"provinceCode": {
"type": "string",
"description": "Province or state as subdivision codes in\n [ISO 3166-2](https://en.wikipedia.org/wiki/ISO_3166-2) format without the\n country prefix (e.g. `\"NY\"` for New York).",
"examples": [
"NY"
]
},
"countryCode": {
"type": "string",
"description": "Country code (e.g. `\"US\"`).",
"examples": [
"US"
]
},
"zip": {
"type": "string",
"description": "Postal or ZIP code (e.g. `\"10001\"`).",
"examples": [
"10001"
]
}
},
"description": "A physical street address."
}
],
"description": "The end address of the route.",
"examples": [
{
"address1": "123 Main St",
"address2": "Apt 3B",
"city": "New York",
"provinceCode": "NY",
"countryCode": "US",
"zip": "10001"
}
]
},
"tasks": {
"type": "array",
"items": {
"title": "Task",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Task ID (e.g. `\"tsk-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"tsk-123e4567-e89b-12d3-a456-426614174000"
]
},
"title": {
"type": "string",
"description": "Task title (e.g. `\"Delivery checklist\"`).",
"examples": [
"Delivery checklist"
]
},
"type": {
"enum": [
"UNKNOWN",
"CHECKBOXES",
"RADIO_BUTTONS",
"TEXT_INPUT",
"DECIMAL_INPUT",
"SCANNER_INPUT"
],
"type": "string",
"description": "Task type.",
"format": "enum",
"examples": [
"TEXT_INPUT"
]
},
"items": {
"type": "array",
"items": {
"title": "TaskItem",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Item ID (e.g. `\"itm-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"itm-123e4567-e89b-12d3-a456-426614174000"
]
},
"title": {
"type": "string",
"description": "Item title (e.g. `\"Pick up package\"`).",
"examples": [
"Pick up package"
]
},
"complete": {
"type": "boolean",
"description": "Whether the item is completed.",
"examples": [
true
]
},
"updatedAt": {
"type": "string",
"description": "Timestamp when the item was last updated.",
"format": "date-time",
"examples": [
"2026-03-30T13:00:00Z"
]
}
},
"description": "An item within a task. For `CHECKBOXES`, each item on a task may be completed\n independently. For `RADIO_BUTTONS`, at most one item will be completed."
},
"description": "Task items (populated for `CHECKBOXES` and `RADIO_BUTTONS`).",
"examples": [
[]
]
},
"input": {
"allOf": [
{
"title": "TaskInput",
"type": "object",
"properties": {
"value": {
"type": "string",
"description": "Input value.",
"examples": [
"020123456789"
]
},
"updatedAt": {
"type": "string",
"description": "Timestamp when the input was last updated.",
"format": "date-time",
"examples": [
"2026-03-30T13:00:00Z"
]
},
"inputMethod": {
"enum": [
"UNKNOWN",
"SCANNED"
],
"type": "string",
"description": "Whether input was scanned (e.g. a scanned barcode)",
"format": "enum",
"examples": [
"SCANNED"
]
}
},
"description": "Captured driver input for a task. The value may be text for `TEXT_INPUT`\n tasks or a string decimal number for `DECIMAL_INPUT` tasks."
}
],
"description": "Task input (populated for `TEXT_INPUT` and `DECIMAL_INPUT`)."
},
"requiredToMarkStopAsDelivered": {
"type": "boolean",
"description": "Whether the task is required to mark the stop as completed. In the case of\n tasks on `RouteStart`, this represents tasks required for starting the\n route. In the case of tasks on `RouteEnd`, this represents tasks required\n for completing the route.",
"examples": [
true
]
},
"requiredToMarkStopAsAttempted": {
"type": "boolean",
"description": "Whether the task is required to mark the stop as attempted.",
"examples": [
true
]
}
},
"description": "A task to be completed at a stop, or at the start or end of a route. Tasks\n may have one or more items for `CHECKBOXES` or `RADIO_BUTTONS`, or may have\n an input for `TEXT_INPUT` or `DECIMAL_INPUT`."
},
"description": "Tasks to complete before finishing the route."
},
"plannedArrival": {
"type": "string",
"description": "Planned arrival time at the end of the route.",
"format": "date-time",
"examples": [
"2026-03-30T17:00:00Z"
]
},
"distanceMeters": {
"type": "number",
"description": "The distance in meters from the previous stop.",
"format": "double",
"examples": [
1234.56
]
},
"updatedArrival": {
"type": "string",
"description": "Estimated arrival time at the end of the route. If the route is completed,\n this will be the actual arrival time.",
"format": "date-time",
"examples": [
"2026-03-30T17:05:00Z"
]
},
"status": {
"enum": [
"UNKNOWN",
"COMPLETED"
],
"type": "string",
"description": "Status indicating whether the route has been completed.",
"format": "enum",
"examples": [
"COMPLETED"
]
},
"photos": {
"type": "array",
"items": {
"title": "StopAttachment",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Attachment ID (e.g. `\"att-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"att-123e4567-e89b-12d3-a456-426614174000"
]
},
"createdAt": {
"type": "string",
"description": "Timestamp when the attachment was created.",
"format": "date-time",
"examples": [
"2026-03-30T09:05:00Z"
]
},
"url": {
"type": "string",
"description": "URL to fetch the attachment.",
"examples": [
"https://example.com/stop-attachment/attachment-2025-06-03-1"
]
}
},
"description": "An attachment to a stop, such as a proof of delivery photo or signature."
},
"description": "Photos for the route end. Photos may be fetched using the URLs on the\n attachments."
}
},
"description": "The end location of a route and any driver tasks to complete after completing\n the route."
}
],
"description": "Route end address and tasks."
},
"stops": {
"type": "array",
"items": {
"title": "RouteStop",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Stop ID (e.g. `\"rst-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"rst-123e4567-e89b-12d3-a456-426614174000"
]
},
"type": {
"enum": [
"UNKNOWN",
"DELIVERY",
"BREAK",
"PICKUP",
"TASK"
],
"type": "string",
"description": "The type of stop (DELIVERY, BREAK, PICKUP, or TASK).",
"format": "enum",
"examples": [
"DELIVERY"
]
},
"deliveryStatus": {
"enum": [
"UNKNOWN",
"DELIVERED",
"OUT_FOR_DELIVERY",
"ATTEMPTED_DELIVERY",
"READY_FOR_DELIVERY"
],
"type": "string",
"description": "The status for DELIVERY, PICKUP, or TASK stops.",
"format": "enum",
"examples": [
"ATTEMPTED_DELIVERY"
]
},
"breakStatus": {
"enum": [
"UNKNOWN",
"COMPLETED"
],
"type": "string",
"description": "The status for BREAK stops.",
"format": "enum",
"examples": [
"COMPLETED"
]
},
"updatedAt": {
"type": "string",
"description": "Timestamp when the stop status was last updated. Note that this timestamp\n corresponds only to major status updates (i.e. stop marked as DELIVERED).\n Minor updates like task completion or adding proof of delivery will not\n advance this timestamp. For those events, use the timestamps on the task or\n proof of delivery attachment.",
"format": "date-time",
"examples": [
"2026-03-30T13:15:00Z"
]
},
"duration": {
"pattern": "^-?(?:0|[1-9][0-9]{0,11})(?:\\.[0-9]{1,9})?s$",
"type": "string",
"description": "Planned duration of the stop in seconds.",
"examples": [
"300s"
]
},
"plannedArrival": {
"type": "string",
"description": "Planned arrival time at the stop.",
"format": "date-time",
"examples": [
"2026-03-30T13:00:00Z"
]
},
"note": {
"type": "string",
"description": "Top-level note for the stop, as entered manually by route planners,\n inherited from a saved or imported stop, or set by order import automation\n rules.",
"examples": [
"Leave at door."
]
},
"address": {
"allOf": [
{
"title": "Address",
"type": "object",
"properties": {
"address1": {
"type": "string",
"description": "Street address line 1 (e.g. `\"123 Main St\"`).",
"examples": [
"123 Main St"
]
},
"address2": {
"type": "string",
"description": "Street address line 2 (e.g. `\"Apt 101\"`).",
"examples": [
"Apt 3B"
]
},
"city": {
"type": "string",
"description": "City name (e.g. `\"New York\"`).",
"examples": [
"New York"
]
},
"provinceCode": {
"type": "string",
"description": "Province or state as subdivision codes in\n [ISO 3166-2](https://en.wikipedia.org/wiki/ISO_3166-2) format without the\n country prefix (e.g. `\"NY\"` for New York).",
"examples": [
"NY"
]
},
"countryCode": {
"type": "string",
"description": "Country code (e.g. `\"US\"`).",
"examples": [
"US"
]
},
"zip": {
"type": "string",
"description": "Postal or ZIP code (e.g. `\"10001\"`).",
"examples": [
"10001"
]
}
},
"description": "A physical street address."
}
],
"description": "Delivery address for the stop.",
"examples": [
{
"address1": "123 Main St",
"address2": "Apt 3B",
"city": "New York",
"provinceCode": "NY",
"countryCode": "US",
"zip": "10001"
}
]
},
"contact": {
"allOf": [
{
"title": "Contact",
"type": "object",
"properties": {
"firstName": {
"type": "string",
"description": "First name (e.g. `\"John\"`).",
"examples": [
"John"
]
},
"lastName": {
"type": "string",
"description": "Last name (e.g. `\"Doe\"`).",
"examples": [
"Doe"
]
},
"company": {
"type": "string",
"description": "Company name (e.g. `\"Roundtrip Systems Inc\"`).",
"examples": [
"Roundtrip Systems Inc"
]
},
"phone": {
"type": "string",
"description": "Phone number in [E.164 format](https://en.wikipedia.org/wiki/E.164) (e.g.\n `\"+14265551000\"`).",
"examples": [
"+14265551000"
]
},
"email": {
"type": "string",
"description": "Email address (e.g. `\"john.doe@roundtrip.ai\"`)",
"examples": [
"john.doe@roundtrip.ai"
]
}
},
"description": "Contact information for a person or company."
}
],
"description": "Contact information for the stop delivery recipient.",
"examples": [
{
"firstName": "John",
"lastName": "Doe",
"company": "Roundtrip Systems Inc",
"phone": "+14265551000",
"email": "john.doe@roundtrip.ai"
}
]
},
"plannedCoordinates": {
"allOf": [
{
"type": "object",
"properties": {
"latitude": {
"type": "number",
"description": "The latitude in degrees. It must be in the range [-90.0, +90.0].",
"format": "double"
},
"longitude": {
"type": "number",
"description": "The longitude in degrees. It must be in the range [-180.0, +180.0].",
"format": "double"
}
},
"description": "An object that represents a latitude/longitude pair. This is expressed as a\n pair of doubles to represent degrees latitude and degrees longitude. Unless\n specified otherwise, this must conform to the\n WGS84\n standard. Values must be within normalized ranges."
}
],
"description": "Planned coordinates for the stop.",
"examples": [
{
"latitude": 40.7128,
"longitude": -74.006
}
]
},
"items": {
"type": "array",
"items": {
"title": "StopItem",
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "Item name (e.g. `\"Bananas\"`).",
"examples": [
"Bananas"
]
},
"quantity": {
"type": "integer",
"description": "Quantity of the item (e.g. `5`).",
"format": "int32",
"examples": [
5
]
},
"grams": {
"type": "integer",
"description": "Weight of the item in grams (e.g. `500`).",
"format": "int32",
"examples": [
500
]
},
"sku": {
"type": "string",
"description": "Stock keeping unit (e.g. `\"BANANA-001\"`).",
"examples": [
"BANANA-001"
]
}
},
"description": "An item to be delivered at a stop."
},
"description": "Items to deliver at the stop."
},
"source": {
"enum": [
"UNKNOWN",
"SHOPIFY_ORDER",
"SAVED_STOP",
"IMPORTED_STOP"
],
"type": "string",
"description": "The source of the stop, which may be populated for `DELIVERY` stops. The\n source can be a `SHOPIFY_ORDER`, an EasyRoutes `SAVED_STOP`, or an\n `IMPORTED_STOP` from an external source (such as CSV file).",
"format": "enum",
"examples": [
"IMPORTED_STOP"
]
},
"shopifyOrderId": {
"type": "string",
"description": "The Shopify order ID, populated when the stop source is a `SHOPIFY_ORDER`.",
"examples": [
"6229749334323"
]
},
"savedStopId": {
"type": "string",
"description": "The saved stop ID, populated when the stop source is a `SAVED_STOP`.",
"examples": [
"sst-123e4567-e89b-12d3-a456-426614174000"
]
},
"deliveredCoordinates": {
"allOf": [
{
"type": "object",
"properties": {
"latitude": {
"type": "number",
"description": "The latitude in degrees. It must be in the range [-90.0, +90.0].",
"format": "double"
},
"longitude": {
"type": "number",
"description": "The longitude in degrees. It must be in the range [-180.0, +180.0].",
"format": "double"
}
},
"description": "An object that represents a latitude/longitude pair. This is expressed as a\n pair of doubles to represent degrees latitude and degrees longitude. Unless\n specified otherwise, this must conform to the\n WGS84\n standard. Values must be within normalized ranges."
}
],
"description": "Delivered coordinates for the stop."
},
"proofOfDeliveryNote": {
"type": "string",
"description": "Proof of delivery note for the stop.",
"examples": [
"Left at door."
]
},
"proofOfDeliveryPhotos": {
"type": "array",
"items": {
"title": "StopAttachment",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Attachment ID (e.g. `\"att-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"att-123e4567-e89b-12d3-a456-426614174000"
]
},
"createdAt": {
"type": "string",
"description": "Timestamp when the attachment was created.",
"format": "date-time",
"examples": [
"2026-03-30T09:05:00Z"
]
},
"url": {
"type": "string",
"description": "URL to fetch the attachment.",
"examples": [
"https://example.com/stop-attachment/attachment-2025-06-03-1"
]
}
},
"description": "An attachment to a stop, such as a proof of delivery photo or signature."
},
"description": "Proof of delivery photos for the stop. Photos may be fetched using the URLs\n on the attachments."
},
"proofOfDeliverySignatures": {
"type": "array",
"items": {
"title": "StopAttachment",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Attachment ID (e.g. `\"att-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"att-123e4567-e89b-12d3-a456-426614174000"
]
},
"createdAt": {
"type": "string",
"description": "Timestamp when the attachment was created.",
"format": "date-time",
"examples": [
"2026-03-30T09:05:00Z"
]
},
"url": {
"type": "string",
"description": "URL to fetch the attachment.",
"examples": [
"https://example.com/stop-attachment/attachment-2025-06-03-1"
]
}
},
"description": "An attachment to a stop, such as a proof of delivery photo or signature."
},
"description": "Proof of delivery signatures for the stop. Signatures may be fetched using\n the URLs on the attachments."
},
"tasks": {
"type": "array",
"items": {
"title": "Task",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Task ID (e.g. `\"tsk-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"tsk-123e4567-e89b-12d3-a456-426614174000"
]
},
"title": {
"type": "string",
"description": "Task title (e.g. `\"Delivery checklist\"`).",
"examples": [
"Delivery checklist"
]
},
"type": {
"enum": [
"UNKNOWN",
"CHECKBOXES",
"RADIO_BUTTONS",
"TEXT_INPUT",
"DECIMAL_INPUT",
"SCANNER_INPUT"
],
"type": "string",
"description": "Task type.",
"format": "enum",
"examples": [
"TEXT_INPUT"
]
},
"items": {
"type": "array",
"items": {
"title": "TaskItem",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Item ID (e.g. `\"itm-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"itm-123e4567-e89b-12d3-a456-426614174000"
]
},
"title": {
"type": "string",
"description": "Item title (e.g. `\"Pick up package\"`).",
"examples": [
"Pick up package"
]
},
"complete": {
"type": "boolean",
"description": "Whether the item is completed.",
"examples": [
true
]
},
"updatedAt": {
"type": "string",
"description": "Timestamp when the item was last updated.",
"format": "date-time",
"examples": [
"2026-03-30T13:00:00Z"
]
}
},
"description": "An item within a task. For `CHECKBOXES`, each item on a task may be completed\n independently. For `RADIO_BUTTONS`, at most one item will be completed."
},
"description": "Task items (populated for `CHECKBOXES` and `RADIO_BUTTONS`).",
"examples": [
[]
]
},
"input": {
"allOf": [
{
"title": "TaskInput",
"type": "object",
"properties": {
"value": {
"type": "string",
"description": "Input value.",
"examples": [
"020123456789"
]
},
"updatedAt": {
"type": "string",
"description": "Timestamp when the input was last updated.",
"format": "date-time",
"examples": [
"2026-03-30T13:00:00Z"
]
},
"inputMethod": {
"enum": [
"UNKNOWN",
"SCANNED"
],
"type": "string",
"description": "Whether input was scanned (e.g. a scanned barcode)",
"format": "enum",
"examples": [
"SCANNED"
]
}
},
"description": "Captured driver input for a task. The value may be text for `TEXT_INPUT`\n tasks or a string decimal number for `DECIMAL_INPUT` tasks."
}
],
"description": "Task input (populated for `TEXT_INPUT` and `DECIMAL_INPUT`)."
},
"requiredToMarkStopAsDelivered": {
"type": "boolean",
"description": "Whether the task is required to mark the stop as completed. In the case of\n tasks on `RouteStart`, this represents tasks required for starting the\n route. In the case of tasks on `RouteEnd`, this represents tasks required\n for completing the route.",
"examples": [
true
]
},
"requiredToMarkStopAsAttempted": {
"type": "boolean",
"description": "Whether the task is required to mark the stop as attempted.",
"examples": [
true
]
}
},
"description": "A task to be completed at a stop, or at the start or end of a route. Tasks\n may have one or more items for `CHECKBOXES` or `RADIO_BUTTONS`, or may have\n an input for `TEXT_INPUT` or `DECIMAL_INPUT`."
},
"description": "Driver tasks for the stop, including completed items and any input from the\n driver."
},
"priority": {
"maximum": 10,
"type": "integer",
"description": "Priority of the stop for route planning. The valid range for stop priority\n is between `1` (low) and `10` (high), with default priority corresponding\n to a value of `5`. A priority value of `0` is considered unset and is\n treated the same as \"default\" priority. Stops with higher priority will be\n preferred when generating routes with constraints.",
"format": "int32",
"examples": [
8
]
},
"importedStopId": {
"type": "string",
"description": "The imported stop ID, populated when the stop source is `IMPORTED_STOP`.",
"examples": [
"ist-123e4567-e89b-12d3-a456-426614174000"
]
},
"orderName": {
"type": "string",
"description": "The name of the order associated with the stop. For Shopify orders, the\n name is generated by combining the `orderNumber` property with the order\n prefix and suffix that are set in the merchant's general settings. For\n EasyRoutes imported orders, this field is populated with the order name\n provided on import.",
"examples": [
"#1234"
]
},
"distanceMeters": {
"type": "number",
"description": "The distance in meters from the previous stop.",
"format": "double",
"examples": [
123.45
]
},
"updatedArrival": {
"type": "string",
"description": "Estimated arrival time at the stop. If the stop is completed, this will be\n the actual arrival time.",
"format": "date-time",
"examples": [
"2026-03-30T13:05:00Z"
]
},
"timeWindows": {
"type": "array",
"items": {
"title": "TimeWindow",
"type": "object",
"properties": {
"start": {
"allOf": [
{
"title": "TimeOfDay",
"type": "object",
"properties": {
"hours": {
"maximum": 23,
"type": "integer",
"description": "Hours of day in 24 hour format. Must be from 0 to 23.",
"format": "int32",
"examples": [
13
]
},
"minutes": {
"maximum": 59,
"type": "integer",
"description": "Minutes of hour of day. Must be from 0 to 59.",
"format": "int32",
"examples": [
37
]
},
"seconds": {
"maximum": 59,
"type": "integer",
"description": "Seconds of minutes of the time. Must be from 0 to 59.",
"format": "int32",
"examples": [
16
]
}
},
"description": "A time of day, independent of a particular date or timezone."
}
],
"description": "The start time of the time window (optional)."
},
"end": {
"allOf": [
{
"title": "TimeOfDay",
"type": "object",
"properties": {
"hours": {
"maximum": 23,
"type": "integer",
"description": "Hours of day in 24 hour format. Must be from 0 to 23.",
"format": "int32",
"examples": [
13
]
},
"minutes": {
"maximum": 59,
"type": "integer",
"description": "Minutes of hour of day. Must be from 0 to 59.",
"format": "int32",
"examples": [
37
]
},
"seconds": {
"maximum": 59,
"type": "integer",
"description": "Seconds of minutes of the time. Must be from 0 to 59.",
"format": "int32",
"examples": [
16
]
}
},
"description": "A time of day, independent of a particular date or timezone."
}
],
"description": "The end time of the time window (optional)."
}
},
"description": "A time window for a stop. The time window may be open-ended, but one or both\n of the start and end times should be provided. The end time must be >= the\n start time."
},
"description": "The time window for the stop. Note that we currently support at most one\n time window but may support multiple time windows in the future.",
"examples": [
[
{
"start": {
"hours": 9
},
"end": {
"hours": 17
}
}
]
]
},
"deliveryDate": {
"allOf": [
{
"title": "Date",
"required": [
"year",
"month",
"day"
],
"type": "object",
"properties": {
"year": {
"maximum": 9999,
"minimum": 1,
"type": "integer",
"description": "Year of the date. Must be from 1 to 9999.",
"format": "int32",
"examples": [
2019
]
},
"month": {
"maximum": 12,
"minimum": 1,
"type": "integer",
"description": "Month of a year. Must be from 1 to 12.",
"format": "int32",
"examples": [
11
]
},
"day": {
"maximum": 31,
"minimum": 1,
"type": "integer",
"description": "Day of a month. Must be from 1 to 31.",
"format": "int32",
"examples": [
15
]
}
},
"description": "A date in year-month-day format."
}
],
"description": "The planned delivery date for the stop.",
"examples": [
{
"year": 2025,
"month": 12,
"day": 16
}
]
},
"attributes": {
"type": "array",
"items": {
"title": "Attribute",
"type": "object",
"properties": {
"key": {
"type": "string",
"description": "Attribute key. Must be non-empty.",
"examples": [
"delivery_date"
]
},
"value": {
"type": "string",
"description": "Attribute value.",
"examples": [
"2025-12-16"
]
}
},
"description": "A key-value pair for storing additional information on a stop, such as order\n details, delivery instructions, or custom fields."
},
"description": "Additional attributes for the stop. Attributes are key-value pairs for\n storing additional structured data on stops. These may be populated from\n the Shopify order or set on import.",
"examples": [
[
{
"key": "color",
"value": "blue"
}
]
]
},
"clientStopId": {
"type": "string",
"description": "The client-provided ID associated with the stop, if provided on import.",
"examples": [
"test-order-1234"
]
},
"tags": {
"type": "array",
"items": {
"type": "string"
},
"description": "The tags for the stop. Tags are used to categorize stops and can be used\n for filtering and grouping stops in the EasyRoutes web app. These may be\n populated from the Shopify order or set on import.",
"examples": [
[
"foo",
"bar"
]
]
},
"attemptedReason": {
"enum": [
"UNKNOWN",
"NOT_AVAILABLE",
"ACCESS_DENIED",
"INCORRECT_ADDRESS",
"SAFE_PLACE_UNAVAILABLE",
"REFUSED",
"EXTERNAL",
"INCORRECT_ITEMS",
"OTHER",
"CANCELED"
],
"type": "string",
"description": "The reason for marking the stop as attempted. This is only populated when\n `deliveryStatus = ATTEMPTED_DELIVERY`.",
"format": "enum",
"examples": [
"NOT_AVAILABLE"
]
},
"attemptedNote": {
"type": "string",
"description": "Optional note related to the reason for marking the stop as attempted. This\n is optionally populated when `deliveryStatus = ATTEMPTED_DELIVERY`.",
"examples": [
"Customer did not answer the door."
]
},
"customerRating": {
"allOf": [
{
"title": "CustomerRating",
"type": "object",
"properties": {
"rating": {
"maximum": 5,
"minimum": 1,
"type": "integer",
"description": "Rating from 1-5",
"format": "int32",
"examples": [
5
]
},
"comment": {
"type": "string",
"description": "Customer comment related to rating",
"examples": [
"Excellent delivery"
]
},
"createdAt": {
"type": "string",
"description": "Timestamp when rating was left by customer.",
"format": "date-time",
"examples": [
"2026-03-30T18:00:00Z"
]
}
},
"description": "Customer rating and feedback left on a stop."
}
],
"description": "Rating left by customer. This can only be populated once `deliveryStatus =\n DELIVERED`."
},
"customSignatureDisclosure": {
"type": "string",
"description": "Optional custom signature disclosure that is shown to customers in the\n driver app.",
"examples": [
"I acknowledge that I have received this delivery."
]
},
"shopifyOrder": {
"allOf": [
{
"title": "ShopifyOrder",
"type": "object",
"properties": {
"orderNote": {
"type": "string",
"description": "The Shopify order note.",
"examples": [
"Customer has paid."
]
},
"customerNote": {
"type": "string",
"description": "The Shopify customer note for the order.",
"examples": [
"Leave at door."
]
}
},
"description": "Shopify-specific information for a RouteStop."
}
],
"description": "Information from the associated Shopify order, if applicable. Populated if\n stop source is `SHOPIFY_ORDER`"
},
"proofOfDeliveryBarcodes": {
"type": "array",
"items": {
"title": "ScannedBarcode",
"type": "object",
"properties": {
"value": {
"type": "string",
"description": "Barcode value (e.g. `\"123456789012\"`).",
"examples": [
"123456789012"
]
},
"createdAt": {
"type": "string",
"description": "Timestamp when the barcode was scanned.",
"format": "date-time",
"examples": [
"2026-03-30T13:10:00Z"
]
}
},
"description": "A proof of delivery barcode scanned at a stop."
},
"description": "Proof of delivery barcodes scanned at the stop."
},
"proofOfDeliveryBarcodeIssues": {
"type": "array",
"items": {
"title": "ScannedBarcodeIssue",
"type": "object",
"properties": {
"reason": {
"enum": [
"UNKNOWN",
"ITEM_MISSING",
"NOT_SCANNABLE",
"INCORRECT"
],
"type": "string",
"description": "The reported reason for the barcode issue.",
"format": "enum",
"examples": [
"ITEM_MISSING"
]
},
"note": {
"type": "string",
"description": "Optional note related to the reason for reporting a barcode issue.",
"examples": [
"Item was not packed."
]
},
"createdAt": {
"type": "string",
"description": "Timestamp when the issue was reported.",
"format": "date-time",
"examples": [
"2026-03-30T13:10:00Z"
]
}
},
"description": "A reported issue related to scanning barcodes at a stop."
},
"description": "Proof of delivery barcode issues reported at the stop."
},
"orderReferenceUrl": {
"type": "string",
"description": "A reference URL for the order associated with the stop (e.g. a link to the\n order in your order management system). Must be a valid HTTPS URL. This\n field can only be populated for imported stops.",
"examples": [
"https://orders.example.com/orders/148977776"
]
}
},
"description": "A stop on a route. A stop may correspond to a delivery or a driver break as\n determined by the type. A delivery stop will have location and contact\n information, items to deliver, optional order details, status, arrival time\n and stop duration, driver tasks and any proof of delivery information. A\n break stop will have start time and duration, and status."
},
"description": "Route stops. See RouteStop for stop fields."
},
"createdAt": {
"type": "string",
"description": "Timestamp when the route was created.",
"format": "date-time",
"examples": [
"2026-03-29T08:00:00Z"
]
},
"updatedAt": {
"type": "string",
"description": "Timestamp when the route was last updated (by the planner).",
"format": "date-time",
"examples": [
"2026-03-30T13:15:00Z"
]
},
"archivedAt": {
"type": "string",
"description": "Timestamp when the route was archived.",
"format": "date-time",
"examples": [
"2026-04-05T00:00:00Z"
]
},
"scheduledFor": {
"type": "string",
"description": "Timestamp when the route is scheduled for.",
"format": "date-time",
"examples": [
"2026-03-30T09:00:00Z"
]
},
"totalDistanceMeters": {
"type": "number",
"description": "The distance in meters for the entire route.",
"format": "double",
"examples": [
2387.2
]
},
"totalItemQuantity": {
"type": "integer",
"description": "The total quantity of items to deliver on the route.",
"format": "int32",
"examples": [
50
]
},
"totalItemGrams": {
"type": "string",
"description": "The total weight in grams for the items on the route.",
"examples": [
"6000"
]
},
"optimized": {
"type": "boolean",
"description": "Whether the route has been optimized. Adding or removing stops, reordering\n stops, or changing route options generally set this field to false until\n the route is reoptimized.",
"examples": [
true
]
},
"dispatchedUntil": {
"type": "string",
"description": "Timestamp until which the route is dispatched and accessible in the driver\n app.",
"format": "date-time",
"examples": [
"2026-03-30T20:00:00Z"
]
},
"note": {
"type": "string",
"description": "Top-level note for the route, as entered manually by route planners.",
"examples": [
"Fragile items."
]
},
"tags": {
"type": "array",
"items": {
"type": "string"
},
"description": "The tags for the route. Tags are used to categorize routes and can be\n used for filtering and grouping routes in the EasyRoutes web app.",
"examples": [
[
"foo",
"bar"
]
]
},
"defaultStopDuration": {
"pattern": "^-?(?:0|[1-9][0-9]{0,11})(?:\\.[0-9]{1,9})?s$",
"type": "string",
"description": "The default duration for stops on the route. Used to estimate arrival\n times for stops that do not have their own duration specified.\n Specified as a duration string in the format \"300s\" for 5 minutes, \"60s\"\n for 1 minute, etc.",
"examples": [
"300s"
]
},
"maxDuration": {
"pattern": "^-?(?:0|[1-9][0-9]{0,11})(?:\\.[0-9]{1,9})?s$",
"type": "string",
"description": "The maximum duration of the route. Specified as a duration string in the\n format \"3600s\" for 1 hour, \"7200s\" for 2 hours, etc.",
"examples": [
"28800s"
]
},
"maxStops": {
"type": "integer",
"description": "The maximum number of stops on the route.",
"format": "int32",
"examples": [
50
]
},
"maxItemCount": {
"type": "integer",
"description": "The maximum total item count across all stops on the route.",
"format": "int32",
"examples": [
200
]
},
"maxKilograms": {
"type": "number",
"description": "The maximum total weight in kilograms across all stops on the route.",
"format": "double",
"examples": [
500
]
},
"avoidTolls": {
"type": "boolean",
"description": "Whether to avoid toll roads during optimization.",
"examples": [
true
]
},
"avoidUTurns": {
"type": "boolean",
"description": "Whether to avoid U-turns during optimization.",
"examples": [
true
]
},
"speedFactor": {
"type": "number",
"description": "A speed factor for the route used during optimization to adjust estimated\n travel times. A value of 1.0 represents normal speed. Values less than 1.0\n indicate slower travel (e.g. 0.5 = half speed), and values greater than\n 1.0 indicate faster travel (e.g. 1.5 = 50% faster). Must be between 0.1\n and 1.9. A value of 0 (or unset) uses the default speed.",
"format": "double",
"examples": [
0.8
]
},
"vehicle": {
"allOf": [
{
"title": "Vehicle",
"required": [
"id"
],
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Vehicle ID.",
"examples": [
"veh-123e4567-e89b-12d3-a456-426614174000"
]
},
"name": {
"type": "string",
"description": "Vehicle name.",
"examples": [
"Delivery Van 1"
]
},
"make": {
"type": "string",
"description": "Vehicle make.",
"examples": [
"Ford"
]
},
"model": {
"type": "string",
"description": "Vehicle model.",
"examples": [
"Transit"
]
},
"year": {
"type": "integer",
"description": "Vehicle model year.",
"format": "int32",
"examples": [
2023
]
},
"type": {
"enum": [
"UNKNOWN",
"CAR",
"CARGO_VAN",
"PICKUP_TRUCK",
"BOX_TRUCK",
"MOTORCYCLE",
"BICYCLE",
"DRONE",
"OTHER"
],
"type": "string",
"description": "Vehicle type.",
"format": "enum",
"examples": [
"CARGO_VAN"
]
},
"vin": {
"type": "string",
"description": "Vehicle Identification Number.",
"examples": [
"1FTBW2CM5NKA12345"
]
},
"license": {
"type": "string",
"description": "Vehicle license plate.",
"examples": [
"ABC-1234"
]
},
"isArchived": {
"type": "boolean",
"description": "Whether the vehicle is archived.",
"examples": [
false
]
},
"createdTimestamp": {
"type": "string",
"description": "Timestamp when the vehicle was created.",
"format": "date-time",
"examples": [
"2026-07-30T12:00:00Z"
]
}
},
"description": "A vehicle that can be assigned to a route."
}
],
"description": "Assigned vehicle for the route."
}
},
"description": "A route of stops, optionally with an assigned driver."
}
}
}
},
"default": {
"description": "Default error response",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"code": {
"type": "integer",
"description": "The status code, which should be an enum value of [google.rpc.Code][google.rpc.Code].",
"format": "int32"
},
"message": {
"type": "string",
"description": "A developer-facing error message, which should be in English. Any user-facing error message should be localized and sent in the [google.rpc.Status.details][google.rpc.Status.details] field, or localized by the client."
},
"details": {
"type": "array",
"items": {
"type": "object",
"properties": {
"@type": {
"type": "string",
"description": "The type of the serialized message."
}
},
"additionalProperties": true,
"description": "Contains an arbitrary serialized message along with a @type that describes the type of the serialized message."
},
"description": "A list of messages that carry the error details. There is a common set of message types for APIs to use."
}
},
"description": "The `Status` type defines a logical error model that is suitable for different programming environments, including REST APIs and RPC APIs. It is used by [gRPC](https://github.com/grpc). Each `Status` message contains three pieces of data: error code, error message, and error details. You can find out more about this error model and how to work with it in the [API Design Guide](https://cloud.google.com/apis/design/errors)."
}
}
}
}
},
"security": [
{
"bearerAuth": []
}
],
"components": {
"securitySchemes": {
"bearerAuth": {
"type": "http",
"description": "Access token from `/authenticate`",
"scheme": "bearer",
"bearerFormat": "JWT"
}
}
}
}
```
# Add route stops (https://docs.roundtrip.ai/docs/api-reference/stops/post-routes-routeId-stops)
POST /routes/{routeId}/stops
Adds stops to a route by route ID. The added stops are references to
previously imported stops by ID (or client-provided ID). The resulting
RouteStops inherit most attributes from the imported stop, while optionally
inheriting some defaults from the route. Specifically, if the stop does not
have a duration set, it will inherit the default duration from the route
options. Additionally, tasks configured on the imported stops will be
merged with the configured stop tasks on the route. The request body should
include a list of stop IDs to add to the route. The response will include
the updated route with the added stops. All new stops are appended to the
end of the existing route. The route will not be optimized automatically
after adding stops, so the caller should reoptimize the route if needed via
ReoptimizeRoute.
## OpenAPI specification
```json
{
"servers": [
{
"url": "https://easyroutes.roundtrip.ai/api/2024-07"
}
],
"tags": [
"Stops"
],
"summary": "Add route stops",
"description": "Adds stops to a route by route ID. The added stops are references to\n previously imported stops by ID (or client-provided ID). The resulting\n RouteStops inherit most attributes from the imported stop, while optionally\n inheriting some defaults from the route. Specifically, if the stop does not\n have a duration set, it will inherit the default duration from the route\n options. Additionally, tasks configured on the imported stops will be\n merged with the configured stop tasks on the route. The request body should\n include a list of stop IDs to add to the route. The response will include\n the updated route with the added stops. All new stops are appended to the\n end of the existing route. The route will not be optimized automatically\n after adding stops, so the caller should reoptimize the route if needed via\n ReoptimizeRoute.",
"operationId": "AddRouteStops",
"parameters": [
{
"name": "routeId",
"in": "path",
"description": "The ID of the route to add stops to.",
"required": true,
"schema": {
"type": "string",
"examples": [
"rte-123e4567-e89b-12d3-a456-426614174000"
]
}
},
{
"name": "Idempotency-Key",
"in": "header",
"description": "A unique key for safely retrying this operation. For more information read [our guide](https://docs.roundtrip.ai/docs/concepts/idempotency.md).",
"schema": {
"maxLength": 255,
"minLength": 1,
"type": "string"
},
"examples": {
"default": {
"value": "550e8400-e29b-41d4-a716-446655440000"
}
}
}
],
"requestBody": {
"content": {
"application/json": {
"schema": {
"type": "array",
"items": {
"title": "ImportedStopToAdd",
"required": [
"importedStopId"
],
"type": "object",
"properties": {
"importedStopId": {
"type": "string",
"description": "The ID of the existing imported stop to add to the route (required). The\n imported stop is fetched and converted into a route stop.",
"examples": [
"ist-123e4567-e89b-12d3-a456-426614174000"
]
},
"deliveryStatus": {
"enum": [
"UNKNOWN",
"DELIVERED",
"OUT_FOR_DELIVERY",
"ATTEMPTED_DELIVERY",
"READY_FOR_DELIVERY"
],
"type": "string",
"description": "The delivery status to set on the stop (optional).",
"format": "enum",
"examples": [
"DELIVERED"
]
}
}
}
}
}
},
"required": true
},
"responses": {
"200": {
"description": "OK",
"headers": {
"Idempotency-Key": {
"description": "The idempotency key associated with the response.",
"schema": {
"type": "string"
}
},
"Idempotency-Replayed": {
"description": "Whether the response was replayed from a previous request.",
"schema": {
"type": "boolean"
}
}
},
"content": {
"application/json": {
"schema": {
"title": "Route",
"required": [
"id",
"name",
"stops",
"createdAt",
"updatedAt",
"totalDistanceMeters",
"totalItemQuantity",
"totalItemGrams",
"optimized"
],
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Route ID (e.g. `\"rte-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"rte-123e4567-e89b-12d3-a456-426614174000"
]
},
"name": {
"type": "string",
"description": "Route name (e.g. `\"Morning route\"`).",
"examples": [
"Morning route"
]
},
"driver": {
"allOf": [
{
"title": "Driver",
"required": [
"id"
],
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Driver ID (e.g. `\"drv-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"drv-123e4567-e89b-12d3-a456-426614174000"
]
},
"firstName": {
"type": "string",
"description": "Driver first name (e.g. `\"John\"`).",
"examples": [
"John"
]
},
"lastName": {
"type": "string",
"description": "Driver last name (e.g. `\"Doe\"`).",
"examples": [
"Doe"
]
},
"phone": {
"type": "string",
"description": "Driver phone number in [E.164 format](https://en.wikipedia.org/wiki/E.164)\n (e.g. `\"+14265551000\"`).",
"examples": [
"+14265551000"
]
},
"status": {
"enum": [
"UNKNOWN",
"ACTIVE",
"INACTIVE",
"ARCHIVED"
],
"type": "string",
"description": "Shop driver status. (e.g. `ACTIVE`).",
"format": "enum",
"examples": [
"ACTIVE"
]
}
},
"description": "A driver who is assigned to a route."
}
],
"description": "Assigned driver for the route."
},
"start": {
"allOf": [
{
"title": "RouteStart",
"type": "object",
"properties": {
"address": {
"allOf": [
{
"title": "Address",
"type": "object",
"properties": {
"address1": {
"type": "string",
"description": "Street address line 1 (e.g. `\"123 Main St\"`).",
"examples": [
"123 Main St"
]
},
"address2": {
"type": "string",
"description": "Street address line 2 (e.g. `\"Apt 101\"`).",
"examples": [
"Apt 3B"
]
},
"city": {
"type": "string",
"description": "City name (e.g. `\"New York\"`).",
"examples": [
"New York"
]
},
"provinceCode": {
"type": "string",
"description": "Province or state as subdivision codes in\n [ISO 3166-2](https://en.wikipedia.org/wiki/ISO_3166-2) format without the\n country prefix (e.g. `\"NY\"` for New York).",
"examples": [
"NY"
]
},
"countryCode": {
"type": "string",
"description": "Country code (e.g. `\"US\"`).",
"examples": [
"US"
]
},
"zip": {
"type": "string",
"description": "Postal or ZIP code (e.g. `\"10001\"`).",
"examples": [
"10001"
]
}
},
"description": "A physical street address."
}
],
"description": "The start address of the route.",
"examples": [
{
"address1": "123 Main St",
"address2": "Apt 3B",
"city": "New York",
"provinceCode": "NY",
"countryCode": "US",
"zip": "10001"
}
]
},
"tasks": {
"type": "array",
"items": {
"title": "Task",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Task ID (e.g. `\"tsk-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"tsk-123e4567-e89b-12d3-a456-426614174000"
]
},
"title": {
"type": "string",
"description": "Task title (e.g. `\"Delivery checklist\"`).",
"examples": [
"Delivery checklist"
]
},
"type": {
"enum": [
"UNKNOWN",
"CHECKBOXES",
"RADIO_BUTTONS",
"TEXT_INPUT",
"DECIMAL_INPUT",
"SCANNER_INPUT"
],
"type": "string",
"description": "Task type.",
"format": "enum",
"examples": [
"TEXT_INPUT"
]
},
"items": {
"type": "array",
"items": {
"title": "TaskItem",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Item ID (e.g. `\"itm-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"itm-123e4567-e89b-12d3-a456-426614174000"
]
},
"title": {
"type": "string",
"description": "Item title (e.g. `\"Pick up package\"`).",
"examples": [
"Pick up package"
]
},
"complete": {
"type": "boolean",
"description": "Whether the item is completed.",
"examples": [
true
]
},
"updatedAt": {
"type": "string",
"description": "Timestamp when the item was last updated.",
"format": "date-time",
"examples": [
"2026-03-30T13:00:00Z"
]
}
},
"description": "An item within a task. For `CHECKBOXES`, each item on a task may be completed\n independently. For `RADIO_BUTTONS`, at most one item will be completed."
},
"description": "Task items (populated for `CHECKBOXES` and `RADIO_BUTTONS`).",
"examples": [
[]
]
},
"input": {
"allOf": [
{
"title": "TaskInput",
"type": "object",
"properties": {
"value": {
"type": "string",
"description": "Input value.",
"examples": [
"020123456789"
]
},
"updatedAt": {
"type": "string",
"description": "Timestamp when the input was last updated.",
"format": "date-time",
"examples": [
"2026-03-30T13:00:00Z"
]
},
"inputMethod": {
"enum": [
"UNKNOWN",
"SCANNED"
],
"type": "string",
"description": "Whether input was scanned (e.g. a scanned barcode)",
"format": "enum",
"examples": [
"SCANNED"
]
}
},
"description": "Captured driver input for a task. The value may be text for `TEXT_INPUT`\n tasks or a string decimal number for `DECIMAL_INPUT` tasks."
}
],
"description": "Task input (populated for `TEXT_INPUT` and `DECIMAL_INPUT`)."
},
"requiredToMarkStopAsDelivered": {
"type": "boolean",
"description": "Whether the task is required to mark the stop as completed. In the case of\n tasks on `RouteStart`, this represents tasks required for starting the\n route. In the case of tasks on `RouteEnd`, this represents tasks required\n for completing the route.",
"examples": [
true
]
},
"requiredToMarkStopAsAttempted": {
"type": "boolean",
"description": "Whether the task is required to mark the stop as attempted.",
"examples": [
true
]
}
},
"description": "A task to be completed at a stop, or at the start or end of a route. Tasks\n may have one or more items for `CHECKBOXES` or `RADIO_BUTTONS`, or may have\n an input for `TEXT_INPUT` or `DECIMAL_INPUT`."
},
"description": "Tasks to complete before starting the route."
},
"status": {
"enum": [
"UNKNOWN",
"STARTED"
],
"type": "string",
"description": "Status indicating whether the route has been started.",
"format": "enum",
"examples": [
"STARTED"
]
},
"updatedStart": {
"type": "string",
"description": "Updated start time for the route. If the route is started, this will be the\n actual start time.",
"format": "date-time",
"examples": [
"2026-03-30T09:05:00Z"
]
},
"scheduledStart": {
"type": "string",
"description": "Scheduled start time for the route (same as `scheduledFor` on the route).",
"format": "date-time",
"examples": [
"2026-03-30T09:00:00Z"
]
},
"photos": {
"type": "array",
"items": {
"title": "StopAttachment",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Attachment ID (e.g. `\"att-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"att-123e4567-e89b-12d3-a456-426614174000"
]
},
"createdAt": {
"type": "string",
"description": "Timestamp when the attachment was created.",
"format": "date-time",
"examples": [
"2026-03-30T09:05:00Z"
]
},
"url": {
"type": "string",
"description": "URL to fetch the attachment.",
"examples": [
"https://example.com/stop-attachment/attachment-2025-06-03-1"
]
}
},
"description": "An attachment to a stop, such as a proof of delivery photo or signature."
},
"description": "Photos for the route start. Photos may be fetched using the URLs on the\n attachments."
}
},
"description": "The start location of a route and any driver tasks to complete before\n beginning the route."
}
],
"description": "Route start address and tasks."
},
"end": {
"allOf": [
{
"title": "RouteEnd",
"type": "object",
"properties": {
"address": {
"allOf": [
{
"title": "Address",
"type": "object",
"properties": {
"address1": {
"type": "string",
"description": "Street address line 1 (e.g. `\"123 Main St\"`).",
"examples": [
"123 Main St"
]
},
"address2": {
"type": "string",
"description": "Street address line 2 (e.g. `\"Apt 101\"`).",
"examples": [
"Apt 3B"
]
},
"city": {
"type": "string",
"description": "City name (e.g. `\"New York\"`).",
"examples": [
"New York"
]
},
"provinceCode": {
"type": "string",
"description": "Province or state as subdivision codes in\n [ISO 3166-2](https://en.wikipedia.org/wiki/ISO_3166-2) format without the\n country prefix (e.g. `\"NY\"` for New York).",
"examples": [
"NY"
]
},
"countryCode": {
"type": "string",
"description": "Country code (e.g. `\"US\"`).",
"examples": [
"US"
]
},
"zip": {
"type": "string",
"description": "Postal or ZIP code (e.g. `\"10001\"`).",
"examples": [
"10001"
]
}
},
"description": "A physical street address."
}
],
"description": "The end address of the route.",
"examples": [
{
"address1": "123 Main St",
"address2": "Apt 3B",
"city": "New York",
"provinceCode": "NY",
"countryCode": "US",
"zip": "10001"
}
]
},
"tasks": {
"type": "array",
"items": {
"title": "Task",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Task ID (e.g. `\"tsk-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"tsk-123e4567-e89b-12d3-a456-426614174000"
]
},
"title": {
"type": "string",
"description": "Task title (e.g. `\"Delivery checklist\"`).",
"examples": [
"Delivery checklist"
]
},
"type": {
"enum": [
"UNKNOWN",
"CHECKBOXES",
"RADIO_BUTTONS",
"TEXT_INPUT",
"DECIMAL_INPUT",
"SCANNER_INPUT"
],
"type": "string",
"description": "Task type.",
"format": "enum",
"examples": [
"TEXT_INPUT"
]
},
"items": {
"type": "array",
"items": {
"title": "TaskItem",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Item ID (e.g. `\"itm-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"itm-123e4567-e89b-12d3-a456-426614174000"
]
},
"title": {
"type": "string",
"description": "Item title (e.g. `\"Pick up package\"`).",
"examples": [
"Pick up package"
]
},
"complete": {
"type": "boolean",
"description": "Whether the item is completed.",
"examples": [
true
]
},
"updatedAt": {
"type": "string",
"description": "Timestamp when the item was last updated.",
"format": "date-time",
"examples": [
"2026-03-30T13:00:00Z"
]
}
},
"description": "An item within a task. For `CHECKBOXES`, each item on a task may be completed\n independently. For `RADIO_BUTTONS`, at most one item will be completed."
},
"description": "Task items (populated for `CHECKBOXES` and `RADIO_BUTTONS`).",
"examples": [
[]
]
},
"input": {
"allOf": [
{
"title": "TaskInput",
"type": "object",
"properties": {
"value": {
"type": "string",
"description": "Input value.",
"examples": [
"020123456789"
]
},
"updatedAt": {
"type": "string",
"description": "Timestamp when the input was last updated.",
"format": "date-time",
"examples": [
"2026-03-30T13:00:00Z"
]
},
"inputMethod": {
"enum": [
"UNKNOWN",
"SCANNED"
],
"type": "string",
"description": "Whether input was scanned (e.g. a scanned barcode)",
"format": "enum",
"examples": [
"SCANNED"
]
}
},
"description": "Captured driver input for a task. The value may be text for `TEXT_INPUT`\n tasks or a string decimal number for `DECIMAL_INPUT` tasks."
}
],
"description": "Task input (populated for `TEXT_INPUT` and `DECIMAL_INPUT`)."
},
"requiredToMarkStopAsDelivered": {
"type": "boolean",
"description": "Whether the task is required to mark the stop as completed. In the case of\n tasks on `RouteStart`, this represents tasks required for starting the\n route. In the case of tasks on `RouteEnd`, this represents tasks required\n for completing the route.",
"examples": [
true
]
},
"requiredToMarkStopAsAttempted": {
"type": "boolean",
"description": "Whether the task is required to mark the stop as attempted.",
"examples": [
true
]
}
},
"description": "A task to be completed at a stop, or at the start or end of a route. Tasks\n may have one or more items for `CHECKBOXES` or `RADIO_BUTTONS`, or may have\n an input for `TEXT_INPUT` or `DECIMAL_INPUT`."
},
"description": "Tasks to complete before finishing the route."
},
"plannedArrival": {
"type": "string",
"description": "Planned arrival time at the end of the route.",
"format": "date-time",
"examples": [
"2026-03-30T17:00:00Z"
]
},
"distanceMeters": {
"type": "number",
"description": "The distance in meters from the previous stop.",
"format": "double",
"examples": [
1234.56
]
},
"updatedArrival": {
"type": "string",
"description": "Estimated arrival time at the end of the route. If the route is completed,\n this will be the actual arrival time.",
"format": "date-time",
"examples": [
"2026-03-30T17:05:00Z"
]
},
"status": {
"enum": [
"UNKNOWN",
"COMPLETED"
],
"type": "string",
"description": "Status indicating whether the route has been completed.",
"format": "enum",
"examples": [
"COMPLETED"
]
},
"photos": {
"type": "array",
"items": {
"title": "StopAttachment",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Attachment ID (e.g. `\"att-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"att-123e4567-e89b-12d3-a456-426614174000"
]
},
"createdAt": {
"type": "string",
"description": "Timestamp when the attachment was created.",
"format": "date-time",
"examples": [
"2026-03-30T09:05:00Z"
]
},
"url": {
"type": "string",
"description": "URL to fetch the attachment.",
"examples": [
"https://example.com/stop-attachment/attachment-2025-06-03-1"
]
}
},
"description": "An attachment to a stop, such as a proof of delivery photo or signature."
},
"description": "Photos for the route end. Photos may be fetched using the URLs on the\n attachments."
}
},
"description": "The end location of a route and any driver tasks to complete after completing\n the route."
}
],
"description": "Route end address and tasks."
},
"stops": {
"type": "array",
"items": {
"title": "RouteStop",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Stop ID (e.g. `\"rst-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"rst-123e4567-e89b-12d3-a456-426614174000"
]
},
"type": {
"enum": [
"UNKNOWN",
"DELIVERY",
"BREAK",
"PICKUP",
"TASK"
],
"type": "string",
"description": "The type of stop (DELIVERY, BREAK, PICKUP, or TASK).",
"format": "enum",
"examples": [
"DELIVERY"
]
},
"deliveryStatus": {
"enum": [
"UNKNOWN",
"DELIVERED",
"OUT_FOR_DELIVERY",
"ATTEMPTED_DELIVERY",
"READY_FOR_DELIVERY"
],
"type": "string",
"description": "The status for DELIVERY, PICKUP, or TASK stops.",
"format": "enum",
"examples": [
"ATTEMPTED_DELIVERY"
]
},
"breakStatus": {
"enum": [
"UNKNOWN",
"COMPLETED"
],
"type": "string",
"description": "The status for BREAK stops.",
"format": "enum",
"examples": [
"COMPLETED"
]
},
"updatedAt": {
"type": "string",
"description": "Timestamp when the stop status was last updated. Note that this timestamp\n corresponds only to major status updates (i.e. stop marked as DELIVERED).\n Minor updates like task completion or adding proof of delivery will not\n advance this timestamp. For those events, use the timestamps on the task or\n proof of delivery attachment.",
"format": "date-time",
"examples": [
"2026-03-30T13:15:00Z"
]
},
"duration": {
"pattern": "^-?(?:0|[1-9][0-9]{0,11})(?:\\.[0-9]{1,9})?s$",
"type": "string",
"description": "Planned duration of the stop in seconds.",
"examples": [
"300s"
]
},
"plannedArrival": {
"type": "string",
"description": "Planned arrival time at the stop.",
"format": "date-time",
"examples": [
"2026-03-30T13:00:00Z"
]
},
"note": {
"type": "string",
"description": "Top-level note for the stop, as entered manually by route planners,\n inherited from a saved or imported stop, or set by order import automation\n rules.",
"examples": [
"Leave at door."
]
},
"address": {
"allOf": [
{
"title": "Address",
"type": "object",
"properties": {
"address1": {
"type": "string",
"description": "Street address line 1 (e.g. `\"123 Main St\"`).",
"examples": [
"123 Main St"
]
},
"address2": {
"type": "string",
"description": "Street address line 2 (e.g. `\"Apt 101\"`).",
"examples": [
"Apt 3B"
]
},
"city": {
"type": "string",
"description": "City name (e.g. `\"New York\"`).",
"examples": [
"New York"
]
},
"provinceCode": {
"type": "string",
"description": "Province or state as subdivision codes in\n [ISO 3166-2](https://en.wikipedia.org/wiki/ISO_3166-2) format without the\n country prefix (e.g. `\"NY\"` for New York).",
"examples": [
"NY"
]
},
"countryCode": {
"type": "string",
"description": "Country code (e.g. `\"US\"`).",
"examples": [
"US"
]
},
"zip": {
"type": "string",
"description": "Postal or ZIP code (e.g. `\"10001\"`).",
"examples": [
"10001"
]
}
},
"description": "A physical street address."
}
],
"description": "Delivery address for the stop.",
"examples": [
{
"address1": "123 Main St",
"address2": "Apt 3B",
"city": "New York",
"provinceCode": "NY",
"countryCode": "US",
"zip": "10001"
}
]
},
"contact": {
"allOf": [
{
"title": "Contact",
"type": "object",
"properties": {
"firstName": {
"type": "string",
"description": "First name (e.g. `\"John\"`).",
"examples": [
"John"
]
},
"lastName": {
"type": "string",
"description": "Last name (e.g. `\"Doe\"`).",
"examples": [
"Doe"
]
},
"company": {
"type": "string",
"description": "Company name (e.g. `\"Roundtrip Systems Inc\"`).",
"examples": [
"Roundtrip Systems Inc"
]
},
"phone": {
"type": "string",
"description": "Phone number in [E.164 format](https://en.wikipedia.org/wiki/E.164) (e.g.\n `\"+14265551000\"`).",
"examples": [
"+14265551000"
]
},
"email": {
"type": "string",
"description": "Email address (e.g. `\"john.doe@roundtrip.ai\"`)",
"examples": [
"john.doe@roundtrip.ai"
]
}
},
"description": "Contact information for a person or company."
}
],
"description": "Contact information for the stop delivery recipient.",
"examples": [
{
"firstName": "John",
"lastName": "Doe",
"company": "Roundtrip Systems Inc",
"phone": "+14265551000",
"email": "john.doe@roundtrip.ai"
}
]
},
"plannedCoordinates": {
"allOf": [
{
"type": "object",
"properties": {
"latitude": {
"type": "number",
"description": "The latitude in degrees. It must be in the range [-90.0, +90.0].",
"format": "double"
},
"longitude": {
"type": "number",
"description": "The longitude in degrees. It must be in the range [-180.0, +180.0].",
"format": "double"
}
},
"description": "An object that represents a latitude/longitude pair. This is expressed as a\n pair of doubles to represent degrees latitude and degrees longitude. Unless\n specified otherwise, this must conform to the\n WGS84\n standard. Values must be within normalized ranges."
}
],
"description": "Planned coordinates for the stop.",
"examples": [
{
"latitude": 40.7128,
"longitude": -74.006
}
]
},
"items": {
"type": "array",
"items": {
"title": "StopItem",
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "Item name (e.g. `\"Bananas\"`).",
"examples": [
"Bananas"
]
},
"quantity": {
"type": "integer",
"description": "Quantity of the item (e.g. `5`).",
"format": "int32",
"examples": [
5
]
},
"grams": {
"type": "integer",
"description": "Weight of the item in grams (e.g. `500`).",
"format": "int32",
"examples": [
500
]
},
"sku": {
"type": "string",
"description": "Stock keeping unit (e.g. `\"BANANA-001\"`).",
"examples": [
"BANANA-001"
]
}
},
"description": "An item to be delivered at a stop."
},
"description": "Items to deliver at the stop."
},
"source": {
"enum": [
"UNKNOWN",
"SHOPIFY_ORDER",
"SAVED_STOP",
"IMPORTED_STOP"
],
"type": "string",
"description": "The source of the stop, which may be populated for `DELIVERY` stops. The\n source can be a `SHOPIFY_ORDER`, an EasyRoutes `SAVED_STOP`, or an\n `IMPORTED_STOP` from an external source (such as CSV file).",
"format": "enum",
"examples": [
"IMPORTED_STOP"
]
},
"shopifyOrderId": {
"type": "string",
"description": "The Shopify order ID, populated when the stop source is a `SHOPIFY_ORDER`.",
"examples": [
"6229749334323"
]
},
"savedStopId": {
"type": "string",
"description": "The saved stop ID, populated when the stop source is a `SAVED_STOP`.",
"examples": [
"sst-123e4567-e89b-12d3-a456-426614174000"
]
},
"deliveredCoordinates": {
"allOf": [
{
"type": "object",
"properties": {
"latitude": {
"type": "number",
"description": "The latitude in degrees. It must be in the range [-90.0, +90.0].",
"format": "double"
},
"longitude": {
"type": "number",
"description": "The longitude in degrees. It must be in the range [-180.0, +180.0].",
"format": "double"
}
},
"description": "An object that represents a latitude/longitude pair. This is expressed as a\n pair of doubles to represent degrees latitude and degrees longitude. Unless\n specified otherwise, this must conform to the\n WGS84\n standard. Values must be within normalized ranges."
}
],
"description": "Delivered coordinates for the stop."
},
"proofOfDeliveryNote": {
"type": "string",
"description": "Proof of delivery note for the stop.",
"examples": [
"Left at door."
]
},
"proofOfDeliveryPhotos": {
"type": "array",
"items": {
"title": "StopAttachment",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Attachment ID (e.g. `\"att-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"att-123e4567-e89b-12d3-a456-426614174000"
]
},
"createdAt": {
"type": "string",
"description": "Timestamp when the attachment was created.",
"format": "date-time",
"examples": [
"2026-03-30T09:05:00Z"
]
},
"url": {
"type": "string",
"description": "URL to fetch the attachment.",
"examples": [
"https://example.com/stop-attachment/attachment-2025-06-03-1"
]
}
},
"description": "An attachment to a stop, such as a proof of delivery photo or signature."
},
"description": "Proof of delivery photos for the stop. Photos may be fetched using the URLs\n on the attachments."
},
"proofOfDeliverySignatures": {
"type": "array",
"items": {
"title": "StopAttachment",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Attachment ID (e.g. `\"att-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"att-123e4567-e89b-12d3-a456-426614174000"
]
},
"createdAt": {
"type": "string",
"description": "Timestamp when the attachment was created.",
"format": "date-time",
"examples": [
"2026-03-30T09:05:00Z"
]
},
"url": {
"type": "string",
"description": "URL to fetch the attachment.",
"examples": [
"https://example.com/stop-attachment/attachment-2025-06-03-1"
]
}
},
"description": "An attachment to a stop, such as a proof of delivery photo or signature."
},
"description": "Proof of delivery signatures for the stop. Signatures may be fetched using\n the URLs on the attachments."
},
"tasks": {
"type": "array",
"items": {
"title": "Task",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Task ID (e.g. `\"tsk-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"tsk-123e4567-e89b-12d3-a456-426614174000"
]
},
"title": {
"type": "string",
"description": "Task title (e.g. `\"Delivery checklist\"`).",
"examples": [
"Delivery checklist"
]
},
"type": {
"enum": [
"UNKNOWN",
"CHECKBOXES",
"RADIO_BUTTONS",
"TEXT_INPUT",
"DECIMAL_INPUT",
"SCANNER_INPUT"
],
"type": "string",
"description": "Task type.",
"format": "enum",
"examples": [
"TEXT_INPUT"
]
},
"items": {
"type": "array",
"items": {
"title": "TaskItem",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Item ID (e.g. `\"itm-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"itm-123e4567-e89b-12d3-a456-426614174000"
]
},
"title": {
"type": "string",
"description": "Item title (e.g. `\"Pick up package\"`).",
"examples": [
"Pick up package"
]
},
"complete": {
"type": "boolean",
"description": "Whether the item is completed.",
"examples": [
true
]
},
"updatedAt": {
"type": "string",
"description": "Timestamp when the item was last updated.",
"format": "date-time",
"examples": [
"2026-03-30T13:00:00Z"
]
}
},
"description": "An item within a task. For `CHECKBOXES`, each item on a task may be completed\n independently. For `RADIO_BUTTONS`, at most one item will be completed."
},
"description": "Task items (populated for `CHECKBOXES` and `RADIO_BUTTONS`).",
"examples": [
[]
]
},
"input": {
"allOf": [
{
"title": "TaskInput",
"type": "object",
"properties": {
"value": {
"type": "string",
"description": "Input value.",
"examples": [
"020123456789"
]
},
"updatedAt": {
"type": "string",
"description": "Timestamp when the input was last updated.",
"format": "date-time",
"examples": [
"2026-03-30T13:00:00Z"
]
},
"inputMethod": {
"enum": [
"UNKNOWN",
"SCANNED"
],
"type": "string",
"description": "Whether input was scanned (e.g. a scanned barcode)",
"format": "enum",
"examples": [
"SCANNED"
]
}
},
"description": "Captured driver input for a task. The value may be text for `TEXT_INPUT`\n tasks or a string decimal number for `DECIMAL_INPUT` tasks."
}
],
"description": "Task input (populated for `TEXT_INPUT` and `DECIMAL_INPUT`)."
},
"requiredToMarkStopAsDelivered": {
"type": "boolean",
"description": "Whether the task is required to mark the stop as completed. In the case of\n tasks on `RouteStart`, this represents tasks required for starting the\n route. In the case of tasks on `RouteEnd`, this represents tasks required\n for completing the route.",
"examples": [
true
]
},
"requiredToMarkStopAsAttempted": {
"type": "boolean",
"description": "Whether the task is required to mark the stop as attempted.",
"examples": [
true
]
}
},
"description": "A task to be completed at a stop, or at the start or end of a route. Tasks\n may have one or more items for `CHECKBOXES` or `RADIO_BUTTONS`, or may have\n an input for `TEXT_INPUT` or `DECIMAL_INPUT`."
},
"description": "Driver tasks for the stop, including completed items and any input from the\n driver."
},
"priority": {
"maximum": 10,
"type": "integer",
"description": "Priority of the stop for route planning. The valid range for stop priority\n is between `1` (low) and `10` (high), with default priority corresponding\n to a value of `5`. A priority value of `0` is considered unset and is\n treated the same as \"default\" priority. Stops with higher priority will be\n preferred when generating routes with constraints.",
"format": "int32",
"examples": [
8
]
},
"importedStopId": {
"type": "string",
"description": "The imported stop ID, populated when the stop source is `IMPORTED_STOP`.",
"examples": [
"ist-123e4567-e89b-12d3-a456-426614174000"
]
},
"orderName": {
"type": "string",
"description": "The name of the order associated with the stop. For Shopify orders, the\n name is generated by combining the `orderNumber` property with the order\n prefix and suffix that are set in the merchant's general settings. For\n EasyRoutes imported orders, this field is populated with the order name\n provided on import.",
"examples": [
"#1234"
]
},
"distanceMeters": {
"type": "number",
"description": "The distance in meters from the previous stop.",
"format": "double",
"examples": [
123.45
]
},
"updatedArrival": {
"type": "string",
"description": "Estimated arrival time at the stop. If the stop is completed, this will be\n the actual arrival time.",
"format": "date-time",
"examples": [
"2026-03-30T13:05:00Z"
]
},
"timeWindows": {
"type": "array",
"items": {
"title": "TimeWindow",
"type": "object",
"properties": {
"start": {
"allOf": [
{
"title": "TimeOfDay",
"type": "object",
"properties": {
"hours": {
"maximum": 23,
"type": "integer",
"description": "Hours of day in 24 hour format. Must be from 0 to 23.",
"format": "int32",
"examples": [
13
]
},
"minutes": {
"maximum": 59,
"type": "integer",
"description": "Minutes of hour of day. Must be from 0 to 59.",
"format": "int32",
"examples": [
37
]
},
"seconds": {
"maximum": 59,
"type": "integer",
"description": "Seconds of minutes of the time. Must be from 0 to 59.",
"format": "int32",
"examples": [
16
]
}
},
"description": "A time of day, independent of a particular date or timezone."
}
],
"description": "The start time of the time window (optional)."
},
"end": {
"allOf": [
{
"title": "TimeOfDay",
"type": "object",
"properties": {
"hours": {
"maximum": 23,
"type": "integer",
"description": "Hours of day in 24 hour format. Must be from 0 to 23.",
"format": "int32",
"examples": [
13
]
},
"minutes": {
"maximum": 59,
"type": "integer",
"description": "Minutes of hour of day. Must be from 0 to 59.",
"format": "int32",
"examples": [
37
]
},
"seconds": {
"maximum": 59,
"type": "integer",
"description": "Seconds of minutes of the time. Must be from 0 to 59.",
"format": "int32",
"examples": [
16
]
}
},
"description": "A time of day, independent of a particular date or timezone."
}
],
"description": "The end time of the time window (optional)."
}
},
"description": "A time window for a stop. The time window may be open-ended, but one or both\n of the start and end times should be provided. The end time must be >= the\n start time."
},
"description": "The time window for the stop. Note that we currently support at most one\n time window but may support multiple time windows in the future.",
"examples": [
[
{
"start": {
"hours": 9
},
"end": {
"hours": 17
}
}
]
]
},
"deliveryDate": {
"allOf": [
{
"title": "Date",
"required": [
"year",
"month",
"day"
],
"type": "object",
"properties": {
"year": {
"maximum": 9999,
"minimum": 1,
"type": "integer",
"description": "Year of the date. Must be from 1 to 9999.",
"format": "int32",
"examples": [
2019
]
},
"month": {
"maximum": 12,
"minimum": 1,
"type": "integer",
"description": "Month of a year. Must be from 1 to 12.",
"format": "int32",
"examples": [
11
]
},
"day": {
"maximum": 31,
"minimum": 1,
"type": "integer",
"description": "Day of a month. Must be from 1 to 31.",
"format": "int32",
"examples": [
15
]
}
},
"description": "A date in year-month-day format."
}
],
"description": "The planned delivery date for the stop.",
"examples": [
{
"year": 2025,
"month": 12,
"day": 16
}
]
},
"attributes": {
"type": "array",
"items": {
"title": "Attribute",
"type": "object",
"properties": {
"key": {
"type": "string",
"description": "Attribute key. Must be non-empty.",
"examples": [
"delivery_date"
]
},
"value": {
"type": "string",
"description": "Attribute value.",
"examples": [
"2025-12-16"
]
}
},
"description": "A key-value pair for storing additional information on a stop, such as order\n details, delivery instructions, or custom fields."
},
"description": "Additional attributes for the stop. Attributes are key-value pairs for\n storing additional structured data on stops. These may be populated from\n the Shopify order or set on import.",
"examples": [
[
{
"key": "color",
"value": "blue"
}
]
]
},
"clientStopId": {
"type": "string",
"description": "The client-provided ID associated with the stop, if provided on import.",
"examples": [
"test-order-1234"
]
},
"tags": {
"type": "array",
"items": {
"type": "string"
},
"description": "The tags for the stop. Tags are used to categorize stops and can be used\n for filtering and grouping stops in the EasyRoutes web app. These may be\n populated from the Shopify order or set on import.",
"examples": [
[
"foo",
"bar"
]
]
},
"attemptedReason": {
"enum": [
"UNKNOWN",
"NOT_AVAILABLE",
"ACCESS_DENIED",
"INCORRECT_ADDRESS",
"SAFE_PLACE_UNAVAILABLE",
"REFUSED",
"EXTERNAL",
"INCORRECT_ITEMS",
"OTHER",
"CANCELED"
],
"type": "string",
"description": "The reason for marking the stop as attempted. This is only populated when\n `deliveryStatus = ATTEMPTED_DELIVERY`.",
"format": "enum",
"examples": [
"NOT_AVAILABLE"
]
},
"attemptedNote": {
"type": "string",
"description": "Optional note related to the reason for marking the stop as attempted. This\n is optionally populated when `deliveryStatus = ATTEMPTED_DELIVERY`.",
"examples": [
"Customer did not answer the door."
]
},
"customerRating": {
"allOf": [
{
"title": "CustomerRating",
"type": "object",
"properties": {
"rating": {
"maximum": 5,
"minimum": 1,
"type": "integer",
"description": "Rating from 1-5",
"format": "int32",
"examples": [
5
]
},
"comment": {
"type": "string",
"description": "Customer comment related to rating",
"examples": [
"Excellent delivery"
]
},
"createdAt": {
"type": "string",
"description": "Timestamp when rating was left by customer.",
"format": "date-time",
"examples": [
"2026-03-30T18:00:00Z"
]
}
},
"description": "Customer rating and feedback left on a stop."
}
],
"description": "Rating left by customer. This can only be populated once `deliveryStatus =\n DELIVERED`."
},
"customSignatureDisclosure": {
"type": "string",
"description": "Optional custom signature disclosure that is shown to customers in the\n driver app.",
"examples": [
"I acknowledge that I have received this delivery."
]
},
"shopifyOrder": {
"allOf": [
{
"title": "ShopifyOrder",
"type": "object",
"properties": {
"orderNote": {
"type": "string",
"description": "The Shopify order note.",
"examples": [
"Customer has paid."
]
},
"customerNote": {
"type": "string",
"description": "The Shopify customer note for the order.",
"examples": [
"Leave at door."
]
}
},
"description": "Shopify-specific information for a RouteStop."
}
],
"description": "Information from the associated Shopify order, if applicable. Populated if\n stop source is `SHOPIFY_ORDER`"
},
"proofOfDeliveryBarcodes": {
"type": "array",
"items": {
"title": "ScannedBarcode",
"type": "object",
"properties": {
"value": {
"type": "string",
"description": "Barcode value (e.g. `\"123456789012\"`).",
"examples": [
"123456789012"
]
},
"createdAt": {
"type": "string",
"description": "Timestamp when the barcode was scanned.",
"format": "date-time",
"examples": [
"2026-03-30T13:10:00Z"
]
}
},
"description": "A proof of delivery barcode scanned at a stop."
},
"description": "Proof of delivery barcodes scanned at the stop."
},
"proofOfDeliveryBarcodeIssues": {
"type": "array",
"items": {
"title": "ScannedBarcodeIssue",
"type": "object",
"properties": {
"reason": {
"enum": [
"UNKNOWN",
"ITEM_MISSING",
"NOT_SCANNABLE",
"INCORRECT"
],
"type": "string",
"description": "The reported reason for the barcode issue.",
"format": "enum",
"examples": [
"ITEM_MISSING"
]
},
"note": {
"type": "string",
"description": "Optional note related to the reason for reporting a barcode issue.",
"examples": [
"Item was not packed."
]
},
"createdAt": {
"type": "string",
"description": "Timestamp when the issue was reported.",
"format": "date-time",
"examples": [
"2026-03-30T13:10:00Z"
]
}
},
"description": "A reported issue related to scanning barcodes at a stop."
},
"description": "Proof of delivery barcode issues reported at the stop."
},
"orderReferenceUrl": {
"type": "string",
"description": "A reference URL for the order associated with the stop (e.g. a link to the\n order in your order management system). Must be a valid HTTPS URL. This\n field can only be populated for imported stops.",
"examples": [
"https://orders.example.com/orders/148977776"
]
}
},
"description": "A stop on a route. A stop may correspond to a delivery or a driver break as\n determined by the type. A delivery stop will have location and contact\n information, items to deliver, optional order details, status, arrival time\n and stop duration, driver tasks and any proof of delivery information. A\n break stop will have start time and duration, and status."
},
"description": "Route stops. See RouteStop for stop fields."
},
"createdAt": {
"type": "string",
"description": "Timestamp when the route was created.",
"format": "date-time",
"examples": [
"2026-03-29T08:00:00Z"
]
},
"updatedAt": {
"type": "string",
"description": "Timestamp when the route was last updated (by the planner).",
"format": "date-time",
"examples": [
"2026-03-30T13:15:00Z"
]
},
"archivedAt": {
"type": "string",
"description": "Timestamp when the route was archived.",
"format": "date-time",
"examples": [
"2026-04-05T00:00:00Z"
]
},
"scheduledFor": {
"type": "string",
"description": "Timestamp when the route is scheduled for.",
"format": "date-time",
"examples": [
"2026-03-30T09:00:00Z"
]
},
"totalDistanceMeters": {
"type": "number",
"description": "The distance in meters for the entire route.",
"format": "double",
"examples": [
2387.2
]
},
"totalItemQuantity": {
"type": "integer",
"description": "The total quantity of items to deliver on the route.",
"format": "int32",
"examples": [
50
]
},
"totalItemGrams": {
"type": "string",
"description": "The total weight in grams for the items on the route.",
"examples": [
"6000"
]
},
"optimized": {
"type": "boolean",
"description": "Whether the route has been optimized. Adding or removing stops, reordering\n stops, or changing route options generally set this field to false until\n the route is reoptimized.",
"examples": [
true
]
},
"dispatchedUntil": {
"type": "string",
"description": "Timestamp until which the route is dispatched and accessible in the driver\n app.",
"format": "date-time",
"examples": [
"2026-03-30T20:00:00Z"
]
},
"note": {
"type": "string",
"description": "Top-level note for the route, as entered manually by route planners.",
"examples": [
"Fragile items."
]
},
"tags": {
"type": "array",
"items": {
"type": "string"
},
"description": "The tags for the route. Tags are used to categorize routes and can be\n used for filtering and grouping routes in the EasyRoutes web app.",
"examples": [
[
"foo",
"bar"
]
]
},
"defaultStopDuration": {
"pattern": "^-?(?:0|[1-9][0-9]{0,11})(?:\\.[0-9]{1,9})?s$",
"type": "string",
"description": "The default duration for stops on the route. Used to estimate arrival\n times for stops that do not have their own duration specified.\n Specified as a duration string in the format \"300s\" for 5 minutes, \"60s\"\n for 1 minute, etc.",
"examples": [
"300s"
]
},
"maxDuration": {
"pattern": "^-?(?:0|[1-9][0-9]{0,11})(?:\\.[0-9]{1,9})?s$",
"type": "string",
"description": "The maximum duration of the route. Specified as a duration string in the\n format \"3600s\" for 1 hour, \"7200s\" for 2 hours, etc.",
"examples": [
"28800s"
]
},
"maxStops": {
"type": "integer",
"description": "The maximum number of stops on the route.",
"format": "int32",
"examples": [
50
]
},
"maxItemCount": {
"type": "integer",
"description": "The maximum total item count across all stops on the route.",
"format": "int32",
"examples": [
200
]
},
"maxKilograms": {
"type": "number",
"description": "The maximum total weight in kilograms across all stops on the route.",
"format": "double",
"examples": [
500
]
},
"avoidTolls": {
"type": "boolean",
"description": "Whether to avoid toll roads during optimization.",
"examples": [
true
]
},
"avoidUTurns": {
"type": "boolean",
"description": "Whether to avoid U-turns during optimization.",
"examples": [
true
]
},
"speedFactor": {
"type": "number",
"description": "A speed factor for the route used during optimization to adjust estimated\n travel times. A value of 1.0 represents normal speed. Values less than 1.0\n indicate slower travel (e.g. 0.5 = half speed), and values greater than\n 1.0 indicate faster travel (e.g. 1.5 = 50% faster). Must be between 0.1\n and 1.9. A value of 0 (or unset) uses the default speed.",
"format": "double",
"examples": [
0.8
]
},
"vehicle": {
"allOf": [
{
"title": "Vehicle",
"required": [
"id"
],
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Vehicle ID.",
"examples": [
"veh-123e4567-e89b-12d3-a456-426614174000"
]
},
"name": {
"type": "string",
"description": "Vehicle name.",
"examples": [
"Delivery Van 1"
]
},
"make": {
"type": "string",
"description": "Vehicle make.",
"examples": [
"Ford"
]
},
"model": {
"type": "string",
"description": "Vehicle model.",
"examples": [
"Transit"
]
},
"year": {
"type": "integer",
"description": "Vehicle model year.",
"format": "int32",
"examples": [
2023
]
},
"type": {
"enum": [
"UNKNOWN",
"CAR",
"CARGO_VAN",
"PICKUP_TRUCK",
"BOX_TRUCK",
"MOTORCYCLE",
"BICYCLE",
"DRONE",
"OTHER"
],
"type": "string",
"description": "Vehicle type.",
"format": "enum",
"examples": [
"CARGO_VAN"
]
},
"vin": {
"type": "string",
"description": "Vehicle Identification Number.",
"examples": [
"1FTBW2CM5NKA12345"
]
},
"license": {
"type": "string",
"description": "Vehicle license plate.",
"examples": [
"ABC-1234"
]
},
"isArchived": {
"type": "boolean",
"description": "Whether the vehicle is archived.",
"examples": [
false
]
},
"createdTimestamp": {
"type": "string",
"description": "Timestamp when the vehicle was created.",
"format": "date-time",
"examples": [
"2026-07-30T12:00:00Z"
]
}
},
"description": "A vehicle that can be assigned to a route."
}
],
"description": "Assigned vehicle for the route."
}
},
"description": "A route of stops, optionally with an assigned driver."
}
}
}
},
"default": {
"description": "Default error response",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"code": {
"type": "integer",
"description": "The status code, which should be an enum value of [google.rpc.Code][google.rpc.Code].",
"format": "int32"
},
"message": {
"type": "string",
"description": "A developer-facing error message, which should be in English. Any user-facing error message should be localized and sent in the [google.rpc.Status.details][google.rpc.Status.details] field, or localized by the client."
},
"details": {
"type": "array",
"items": {
"type": "object",
"properties": {
"@type": {
"type": "string",
"description": "The type of the serialized message."
}
},
"additionalProperties": true,
"description": "Contains an arbitrary serialized message along with a @type that describes the type of the serialized message."
},
"description": "A list of messages that carry the error details. There is a common set of message types for APIs to use."
}
},
"description": "The `Status` type defines a logical error model that is suitable for different programming environments, including REST APIs and RPC APIs. It is used by [gRPC](https://github.com/grpc). Each `Status` message contains three pieces of data: error code, error message, and error details. You can find out more about this error model and how to work with it in the [API Design Guide](https://cloud.google.com/apis/design/errors)."
}
}
}
}
},
"security": [
{
"bearerAuth": []
}
],
"components": {
"securitySchemes": {
"bearerAuth": {
"type": "http",
"description": "Access token from `/authenticate`",
"scheme": "bearer",
"bearerFormat": "JWT"
}
}
}
}
```
# Import stops (https://docs.roundtrip.ai/docs/api-reference/stops/post-stops-imports)
POST /stops/imports
Import stops into EasyRoutes from an external source. The request body
should include a list of stops to import. The response will include a list
of imported stops with generated IDs. The maximum number of stops to import
in a single request is `200`. Imported stops will show up in EasyRoutes as
orders that can be used to create routes.
## OpenAPI specification
```json
{
"servers": [
{
"url": "https://easyroutes.roundtrip.ai/api/2024-07"
}
],
"tags": [
"Stops"
],
"summary": "Import stops",
"description": "Import stops into EasyRoutes from an external source. The request body\n should include a list of stops to import. The response will include a list\n of imported stops with generated IDs. The maximum number of stops to import\n in a single request is `200`. Imported stops will show up in EasyRoutes as\n orders that can be used to create routes.",
"operationId": "ImportStops",
"parameters": [
{
"name": "Idempotency-Key",
"in": "header",
"description": "A unique key for safely retrying this operation. For more information read [our guide](https://docs.roundtrip.ai/docs/concepts/idempotency.md).",
"schema": {
"maxLength": 255,
"minLength": 1,
"type": "string"
},
"examples": {
"default": {
"value": "550e8400-e29b-41d4-a716-446655440000"
}
}
}
],
"requestBody": {
"content": {
"application/json": {
"schema": {
"type": "array",
"items": {
"title": "StopToImport",
"type": "object",
"properties": {
"clientStopId": {
"type": "string",
"description": "Optional unique ID to associate with the imported stop. If provided, and a\n stop with the same `clientStopId` already exists, the existing stop will be\n replaced with the new data. Otherwise, a new stop will be created. Note\n this ID is distinct from the EasyRoutes-generated stop `id`. Must be 1-128\n characters when provided and cannot contain spaces or control characters\n (e.g., newlines, tabs).",
"examples": [
"test-order-1234"
]
},
"address": {
"allOf": [
{
"title": "Address",
"type": "object",
"properties": {
"address1": {
"type": "string",
"description": "Street address line 1 (e.g. `\"123 Main St\"`).",
"examples": [
"123 Main St"
]
},
"address2": {
"type": "string",
"description": "Street address line 2 (e.g. `\"Apt 101\"`).",
"examples": [
"Apt 3B"
]
},
"city": {
"type": "string",
"description": "City name (e.g. `\"New York\"`).",
"examples": [
"New York"
]
},
"provinceCode": {
"type": "string",
"description": "Province or state as subdivision codes in\n [ISO 3166-2](https://en.wikipedia.org/wiki/ISO_3166-2) format without the\n country prefix (e.g. `\"NY\"` for New York).",
"examples": [
"NY"
]
},
"countryCode": {
"type": "string",
"description": "Country code (e.g. `\"US\"`).",
"examples": [
"US"
]
},
"zip": {
"type": "string",
"description": "Postal or ZIP code (e.g. `\"10001\"`).",
"examples": [
"10001"
]
}
},
"description": "A physical street address."
}
],
"description": "The address for the stop.",
"examples": [
{
"address1": "123 Main St",
"address2": "Apt 3B",
"city": "New York",
"provinceCode": "NY",
"countryCode": "US",
"zip": "10001"
}
]
},
"contact": {
"allOf": [
{
"title": "Contact",
"type": "object",
"properties": {
"firstName": {
"type": "string",
"description": "First name (e.g. `\"John\"`).",
"examples": [
"John"
]
},
"lastName": {
"type": "string",
"description": "Last name (e.g. `\"Doe\"`).",
"examples": [
"Doe"
]
},
"company": {
"type": "string",
"description": "Company name (e.g. `\"Roundtrip Systems Inc\"`).",
"examples": [
"Roundtrip Systems Inc"
]
},
"phone": {
"type": "string",
"description": "Phone number in [E.164 format](https://en.wikipedia.org/wiki/E.164) (e.g.\n `\"+14265551000\"`).",
"examples": [
"+14265551000"
]
},
"email": {
"type": "string",
"description": "Email address (e.g. `\"john.doe@roundtrip.ai\"`)",
"examples": [
"john.doe@roundtrip.ai"
]
}
},
"description": "Contact information for a person or company."
}
],
"description": "The contact information for the stop.",
"examples": [
{
"firstName": "John",
"lastName": "Doe",
"company": "Roundtrip Systems Inc",
"phone": "+14265551000",
"email": "john.doe@roundtrip.ai"
}
]
},
"coordinates": {
"allOf": [
{
"type": "object",
"properties": {
"latitude": {
"type": "number",
"description": "The latitude in degrees. It must be in the range [-90.0, +90.0].",
"format": "double"
},
"longitude": {
"type": "number",
"description": "The longitude in degrees. It must be in the range [-180.0, +180.0].",
"format": "double"
}
},
"description": "An object that represents a latitude/longitude pair. This is expressed as a\n pair of doubles to represent degrees latitude and degrees longitude. Unless\n specified otherwise, this must conform to the\n WGS84\n standard. Values must be within normalized ranges."
}
],
"description": "(Optional) The coordinates for the stop. If not provided, the coordinates\n will be geocoded from the address when the stop is added to a route.",
"examples": [
{
"latitude": 40.7128,
"longitude": -74.006
}
]
},
"items": {
"type": "array",
"items": {
"title": "StopItem",
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "Item name (e.g. `\"Bananas\"`).",
"examples": [
"Bananas"
]
},
"quantity": {
"type": "integer",
"description": "Quantity of the item (e.g. `5`).",
"format": "int32",
"examples": [
5
]
},
"grams": {
"type": "integer",
"description": "Weight of the item in grams (e.g. `500`).",
"format": "int32",
"examples": [
500
]
},
"sku": {
"type": "string",
"description": "Stock keeping unit (e.g. `\"BANANA-001\"`).",
"examples": [
"BANANA-001"
]
}
},
"description": "An item to be delivered at a stop."
},
"description": "The items to deliver at the stop."
},
"note": {
"type": "string",
"description": "A note for the stop.",
"examples": [
"Leave at door."
]
},
"duration": {
"pattern": "^-?(?:0|[1-9][0-9]{0,11})(?:\\.[0-9]{1,9})?s$",
"type": "string",
"description": "The planned duration for the driver to spend at this stop. This duration is\n used in route optimization to estimate arrival times. If specified, it\n takes precedence over the route's default stop duration. Specified as a\n duration string in the format \"300s\" for 5 minutes, \"60s\" for 1 minute,\n etc.",
"examples": [
"300s"
]
},
"priority": {
"maximum": 10,
"type": "integer",
"description": "Priority of the stop for route planning. The valid range for stop priority\n is between `1` (low) and `10` (high), with default priority corresponding\n to a value of `5`. A priority value of `0` is considered unset and is\n treated the same as \"default\" priority. Stops with higher priority will be\n preferred when generating routes with constraints.",
"format": "int32",
"examples": [
5
]
},
"orderName": {
"type": "string",
"description": "The name of the order associated with the stop, which can serve as an\n external reference to the order name / ID outside of EasyRoutes. This field\n is optional and EasyRoutes does not enforce uniqueness of order names.",
"examples": [
"#1234"
]
},
"timeWindows": {
"type": "array",
"items": {
"title": "TimeWindow",
"type": "object",
"properties": {
"start": {
"allOf": [
{
"title": "TimeOfDay",
"type": "object",
"properties": {
"hours": {
"maximum": 23,
"type": "integer",
"description": "Hours of day in 24 hour format. Must be from 0 to 23.",
"format": "int32",
"examples": [
13
]
},
"minutes": {
"maximum": 59,
"type": "integer",
"description": "Minutes of hour of day. Must be from 0 to 59.",
"format": "int32",
"examples": [
37
]
},
"seconds": {
"maximum": 59,
"type": "integer",
"description": "Seconds of minutes of the time. Must be from 0 to 59.",
"format": "int32",
"examples": [
16
]
}
},
"description": "A time of day, independent of a particular date or timezone."
}
],
"description": "The start time of the time window (optional)."
},
"end": {
"allOf": [
{
"title": "TimeOfDay",
"type": "object",
"properties": {
"hours": {
"maximum": 23,
"type": "integer",
"description": "Hours of day in 24 hour format. Must be from 0 to 23.",
"format": "int32",
"examples": [
13
]
},
"minutes": {
"maximum": 59,
"type": "integer",
"description": "Minutes of hour of day. Must be from 0 to 59.",
"format": "int32",
"examples": [
37
]
},
"seconds": {
"maximum": 59,
"type": "integer",
"description": "Seconds of minutes of the time. Must be from 0 to 59.",
"format": "int32",
"examples": [
16
]
}
},
"description": "A time of day, independent of a particular date or timezone."
}
],
"description": "The end time of the time window (optional)."
}
},
"description": "A time window for a stop. The time window may be open-ended, but one or both\n of the start and end times should be provided. The end time must be >= the\n start time."
},
"description": "The time windows for the stop. Note that we currently support at most one\n time window but accept an array for future compatibility.",
"examples": [
[
{
"start": {
"hours": 9
},
"end": {
"hours": 17
}
}
]
]
},
"deliveryDate": {
"allOf": [
{
"title": "Date",
"required": [
"year",
"month",
"day"
],
"type": "object",
"properties": {
"year": {
"maximum": 9999,
"minimum": 1,
"type": "integer",
"description": "Year of the date. Must be from 1 to 9999.",
"format": "int32",
"examples": [
2019
]
},
"month": {
"maximum": 12,
"minimum": 1,
"type": "integer",
"description": "Month of a year. Must be from 1 to 12.",
"format": "int32",
"examples": [
11
]
},
"day": {
"maximum": 31,
"minimum": 1,
"type": "integer",
"description": "Day of a month. Must be from 1 to 31.",
"format": "int32",
"examples": [
15
]
}
},
"description": "A date in year-month-day format."
}
],
"description": "The delivery date for the stop.",
"examples": [
{
"year": 2025,
"month": 12,
"day": 16
}
]
},
"attributes": {
"type": "array",
"items": {
"title": "Attribute",
"type": "object",
"properties": {
"key": {
"type": "string",
"description": "Attribute key. Must be non-empty.",
"examples": [
"delivery_date"
]
},
"value": {
"type": "string",
"description": "Attribute value.",
"examples": [
"2025-12-16"
]
}
},
"description": "A key-value pair for storing additional information on a stop, such as order\n details, delivery instructions, or custom fields."
},
"description": "Additional attributes for the stop. Attributes are key-value pairs for\n storing additional structured data on stops. You may specify up to `50`\n attributes per stop.",
"examples": [
[
{
"key": "color",
"value": "blue"
}
]
]
},
"tags": {
"type": "array",
"items": {
"type": "string"
},
"description": "The tags for the stop. Tags are used to categorize stops and can be used\n for filtering and grouping stops in the EasyRoutes web app. You may specify\n up to `250` tags per stop.",
"examples": [
[
"foo",
"bar"
]
]
},
"tasks": {
"type": "array",
"items": {
"title": "TaskTemplate",
"type": "object",
"properties": {
"title": {
"type": "string",
"description": "Task title (e.g. `\"Delivery checklist\"`).",
"examples": [
"Delivery checklist"
]
},
"type": {
"enum": [
"UNKNOWN",
"CHECKBOXES",
"RADIO_BUTTONS",
"TEXT_INPUT",
"DECIMAL_INPUT",
"SCANNER_INPUT"
],
"type": "string",
"description": "Task type.",
"format": "enum",
"examples": [
"CHECKBOXES"
]
},
"items": {
"type": "array",
"items": {
"title": "TaskItemTemplate",
"type": "object",
"properties": {
"title": {
"type": "string",
"description": "Item title (e.g. `\"Pick up package\"`).",
"examples": [
"Pick up package"
]
}
},
"description": "An item template for a task. For `CHECKBOXES`, each item on a task may be\n completed independently. For `RADIO_BUTTONS`, at most one item will be\n completed."
},
"description": "Task items, which are required for `CHECKBOXES` and `RADIO_BUTTONS`."
},
"requiredToMarkStopAsDelivered": {
"type": "boolean",
"description": "Whether the task is required to mark the stop as completed.",
"examples": [
true
]
},
"requiredToMarkStopAsAttempted": {
"type": "boolean",
"description": "Whether the task is required to mark the stop as attempted.",
"examples": [
true
]
}
},
"description": "A template for creating tasks at a stop. Task templates may have one or more\n items for `CHECKBOXES` or `RADIO_BUTTONS`. Imported stops may have task\n templates that are used to create tasks when the stop is added to a route."
},
"description": "The tasks for the stop. Tasks are used to define the work that needs to be\n completed at the stop by the driver, when the stop is added to a route."
},
"type": {
"enum": [
"UNKNOWN",
"DELIVERY",
"BREAK",
"PICKUP",
"TASK"
],
"type": "string",
"description": "The type of stop (DELIVERY, PICKUP, or TASK). Defaults to DELIVERY if not\n provided.",
"format": "enum",
"examples": [
"DELIVERY"
]
},
"customSignatureDisclosure": {
"type": "string",
"description": "Custom signature disclosure for the stop. Only applicable for stops of type\n DELIVERY, PICKUP, or TASK.",
"examples": [
"I acknowledge that I have received this delivery."
]
},
"orderReferenceUrl": {
"type": "string",
"description": "A reference URL for the order associated with the stop (e.g. a link to the\n order in your order management system). Must be a valid HTTPS URL.",
"examples": [
"https://orders.example.com/orders/148977776"
]
}
},
"description": "A stop to import into EasyRoutes."
}
}
}
},
"required": true
},
"responses": {
"200": {
"description": "OK",
"headers": {
"Idempotency-Key": {
"description": "The idempotency key associated with the response.",
"schema": {
"type": "string"
}
},
"Idempotency-Replayed": {
"description": "Whether the response was replayed from a previous request.",
"schema": {
"type": "boolean"
}
}
},
"content": {
"application/json": {
"schema": {
"title": "ImportStopsResponse",
"type": "object",
"properties": {
"stops": {
"type": "array",
"items": {
"title": "ImportedStop",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "The ID of the imported stop, generated by EasyRoutes (e.g.\n `\"ist-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"ist-123e4567-e89b-12d3-a456-426614174000"
]
},
"clientStopId": {
"type": "string",
"description": "The client-provided ID associated with the imported stop, if provided.",
"examples": [
"test-order-1234"
]
},
"address": {
"allOf": [
{
"title": "Address",
"type": "object",
"properties": {
"address1": {
"type": "string",
"description": "Street address line 1 (e.g. `\"123 Main St\"`).",
"examples": [
"123 Main St"
]
},
"address2": {
"type": "string",
"description": "Street address line 2 (e.g. `\"Apt 101\"`).",
"examples": [
"Apt 3B"
]
},
"city": {
"type": "string",
"description": "City name (e.g. `\"New York\"`).",
"examples": [
"New York"
]
},
"provinceCode": {
"type": "string",
"description": "Province or state as subdivision codes in\n [ISO 3166-2](https://en.wikipedia.org/wiki/ISO_3166-2) format without the\n country prefix (e.g. `\"NY\"` for New York).",
"examples": [
"NY"
]
},
"countryCode": {
"type": "string",
"description": "Country code (e.g. `\"US\"`).",
"examples": [
"US"
]
},
"zip": {
"type": "string",
"description": "Postal or ZIP code (e.g. `\"10001\"`).",
"examples": [
"10001"
]
}
},
"description": "A physical street address."
}
],
"description": "The address for the stop.",
"examples": [
{
"address1": "123 Main St",
"address2": "Apt 3B",
"city": "New York",
"provinceCode": "NY",
"countryCode": "US",
"zip": "10001"
}
]
},
"contact": {
"allOf": [
{
"title": "Contact",
"type": "object",
"properties": {
"firstName": {
"type": "string",
"description": "First name (e.g. `\"John\"`).",
"examples": [
"John"
]
},
"lastName": {
"type": "string",
"description": "Last name (e.g. `\"Doe\"`).",
"examples": [
"Doe"
]
},
"company": {
"type": "string",
"description": "Company name (e.g. `\"Roundtrip Systems Inc\"`).",
"examples": [
"Roundtrip Systems Inc"
]
},
"phone": {
"type": "string",
"description": "Phone number in [E.164 format](https://en.wikipedia.org/wiki/E.164) (e.g.\n `\"+14265551000\"`).",
"examples": [
"+14265551000"
]
},
"email": {
"type": "string",
"description": "Email address (e.g. `\"john.doe@roundtrip.ai\"`)",
"examples": [
"john.doe@roundtrip.ai"
]
}
},
"description": "Contact information for a person or company."
}
],
"description": "The contact information for the stop.",
"examples": [
{
"firstName": "John",
"lastName": "Doe",
"company": "Roundtrip Systems Inc",
"phone": "+14265551000",
"email": "john.doe@roundtrip.ai"
}
]
},
"coordinates": {
"allOf": [
{
"type": "object",
"properties": {
"latitude": {
"type": "number",
"description": "The latitude in degrees. It must be in the range [-90.0, +90.0].",
"format": "double"
},
"longitude": {
"type": "number",
"description": "The longitude in degrees. It must be in the range [-180.0, +180.0].",
"format": "double"
}
},
"description": "An object that represents a latitude/longitude pair. This is expressed as a\n pair of doubles to represent degrees latitude and degrees longitude. Unless\n specified otherwise, this must conform to the\n WGS84\n standard. Values must be within normalized ranges."
}
],
"description": "The coordinates to use for the stop, if provided on import.",
"examples": [
{
"latitude": 40.7128,
"longitude": -74.006
}
]
},
"items": {
"type": "array",
"items": {
"title": "StopItem",
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "Item name (e.g. `\"Bananas\"`).",
"examples": [
"Bananas"
]
},
"quantity": {
"type": "integer",
"description": "Quantity of the item (e.g. `5`).",
"format": "int32",
"examples": [
5
]
},
"grams": {
"type": "integer",
"description": "Weight of the item in grams (e.g. `500`).",
"format": "int32",
"examples": [
500
]
},
"sku": {
"type": "string",
"description": "Stock keeping unit (e.g. `\"BANANA-001\"`).",
"examples": [
"BANANA-001"
]
}
},
"description": "An item to be delivered at a stop."
},
"description": "The items to deliver at the stop."
},
"note": {
"type": "string",
"description": "A note for the stop.",
"examples": [
"Leave at door."
]
},
"duration": {
"pattern": "^-?(?:0|[1-9][0-9]{0,11})(?:\\.[0-9]{1,9})?s$",
"type": "string",
"description": "The planned duration for the driver to spend at this stop. This duration is\n used in route optimization to estimate arrival times. If specified, it\n takes precedence over the route's default stop duration. Specified as a\n duration string in the format \"300s\" for 5 minutes, \"60s\" for 1 minute,\n etc.",
"examples": [
"300s"
]
},
"priority": {
"maximum": 10,
"type": "integer",
"description": "Priority of the stop for route planning.",
"format": "int32",
"examples": [
5
]
},
"orderName": {
"type": "string",
"description": "The name of the order associated with the stop.",
"examples": [
"#1234"
]
},
"importedAt": {
"type": "string",
"description": "The timestamp at which the stop was imported.",
"format": "date-time",
"examples": [
"2026-03-28T10:00:00Z"
]
},
"timeWindows": {
"type": "array",
"items": {
"title": "TimeWindow",
"type": "object",
"properties": {
"start": {
"allOf": [
{
"title": "TimeOfDay",
"type": "object",
"properties": {
"hours": {
"maximum": 23,
"type": "integer",
"description": "Hours of day in 24 hour format. Must be from 0 to 23.",
"format": "int32",
"examples": [
13
]
},
"minutes": {
"maximum": 59,
"type": "integer",
"description": "Minutes of hour of day. Must be from 0 to 59.",
"format": "int32",
"examples": [
37
]
},
"seconds": {
"maximum": 59,
"type": "integer",
"description": "Seconds of minutes of the time. Must be from 0 to 59.",
"format": "int32",
"examples": [
16
]
}
},
"description": "A time of day, independent of a particular date or timezone."
}
],
"description": "The start time of the time window (optional)."
},
"end": {
"allOf": [
{
"title": "TimeOfDay",
"type": "object",
"properties": {
"hours": {
"maximum": 23,
"type": "integer",
"description": "Hours of day in 24 hour format. Must be from 0 to 23.",
"format": "int32",
"examples": [
13
]
},
"minutes": {
"maximum": 59,
"type": "integer",
"description": "Minutes of hour of day. Must be from 0 to 59.",
"format": "int32",
"examples": [
37
]
},
"seconds": {
"maximum": 59,
"type": "integer",
"description": "Seconds of minutes of the time. Must be from 0 to 59.",
"format": "int32",
"examples": [
16
]
}
},
"description": "A time of day, independent of a particular date or timezone."
}
],
"description": "The end time of the time window (optional)."
}
},
"description": "A time window for a stop. The time window may be open-ended, but one or both\n of the start and end times should be provided. The end time must be >= the\n start time."
},
"description": "The time window for the stop. Note that we currently support at most one\n time window but may support multiple time windows in the future.",
"examples": [
[
{
"start": {
"hours": 9
},
"end": {
"hours": 17
}
}
]
]
},
"deliveryDate": {
"allOf": [
{
"title": "Date",
"required": [
"year",
"month",
"day"
],
"type": "object",
"properties": {
"year": {
"maximum": 9999,
"minimum": 1,
"type": "integer",
"description": "Year of the date. Must be from 1 to 9999.",
"format": "int32",
"examples": [
2019
]
},
"month": {
"maximum": 12,
"minimum": 1,
"type": "integer",
"description": "Month of a year. Must be from 1 to 12.",
"format": "int32",
"examples": [
11
]
},
"day": {
"maximum": 31,
"minimum": 1,
"type": "integer",
"description": "Day of a month. Must be from 1 to 31.",
"format": "int32",
"examples": [
15
]
}
},
"description": "A date in year-month-day format."
}
],
"description": "The delivery date for the stop.",
"examples": [
{
"year": 2025,
"month": 12,
"day": 16
}
]
},
"attributes": {
"type": "array",
"items": {
"title": "Attribute",
"type": "object",
"properties": {
"key": {
"type": "string",
"description": "Attribute key. Must be non-empty.",
"examples": [
"delivery_date"
]
},
"value": {
"type": "string",
"description": "Attribute value.",
"examples": [
"2025-12-16"
]
}
},
"description": "A key-value pair for storing additional information on a stop, such as order\n details, delivery instructions, or custom fields."
},
"description": "The additional key-value attributes set on the imported stop.",
"examples": [
[
{
"key": "color",
"value": "blue"
}
]
]
},
"tags": {
"type": "array",
"items": {
"type": "string"
},
"description": "The tags for the stop.",
"examples": [
[
"foo",
"bar"
]
]
},
"tasks": {
"type": "array",
"items": {
"title": "TaskTemplate",
"type": "object",
"properties": {
"title": {
"type": "string",
"description": "Task title (e.g. `\"Delivery checklist\"`).",
"examples": [
"Delivery checklist"
]
},
"type": {
"enum": [
"UNKNOWN",
"CHECKBOXES",
"RADIO_BUTTONS",
"TEXT_INPUT",
"DECIMAL_INPUT",
"SCANNER_INPUT"
],
"type": "string",
"description": "Task type.",
"format": "enum",
"examples": [
"CHECKBOXES"
]
},
"items": {
"type": "array",
"items": {
"title": "TaskItemTemplate",
"type": "object",
"properties": {
"title": {
"type": "string",
"description": "Item title (e.g. `\"Pick up package\"`).",
"examples": [
"Pick up package"
]
}
},
"description": "An item template for a task. For `CHECKBOXES`, each item on a task may be\n completed independently. For `RADIO_BUTTONS`, at most one item will be\n completed."
},
"description": "Task items, which are required for `CHECKBOXES` and `RADIO_BUTTONS`."
},
"requiredToMarkStopAsDelivered": {
"type": "boolean",
"description": "Whether the task is required to mark the stop as completed.",
"examples": [
true
]
},
"requiredToMarkStopAsAttempted": {
"type": "boolean",
"description": "Whether the task is required to mark the stop as attempted.",
"examples": [
true
]
}
},
"description": "A template for creating tasks at a stop. Task templates may have one or more\n items for `CHECKBOXES` or `RADIO_BUTTONS`. Imported stops may have task\n templates that are used to create tasks when the stop is added to a route."
},
"description": "The tasks for the stop."
},
"type": {
"enum": [
"UNKNOWN",
"DELIVERY",
"BREAK",
"PICKUP",
"TASK"
],
"type": "string",
"description": "The type of stop (DELIVERY, PICKUP, or TASK). Defaults to DELIVERY if not\n provided.",
"format": "enum",
"examples": [
"DELIVERY"
]
},
"customSignatureDisclosure": {
"type": "string",
"description": "Custom signature disclosure for the stop. Only populated if stop type is\n DELIVERY, PICKUP, or TASK.",
"examples": [
"I acknowledge that I have received this delivery."
]
},
"orderReferenceUrl": {
"type": "string",
"description": "A reference URL for the order associated with the stop (e.g. a link to the\n order in your order management system). Must be a valid HTTPS URL.",
"examples": [
"https://orders.example.com/orders/148977776"
]
}
},
"description": "A stop imported into EasyRoutes."
},
"description": "The list of imported stops with generated IDs."
}
}
}
}
}
},
"default": {
"description": "Default error response",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"code": {
"type": "integer",
"description": "The status code, which should be an enum value of [google.rpc.Code][google.rpc.Code].",
"format": "int32"
},
"message": {
"type": "string",
"description": "A developer-facing error message, which should be in English. Any user-facing error message should be localized and sent in the [google.rpc.Status.details][google.rpc.Status.details] field, or localized by the client."
},
"details": {
"type": "array",
"items": {
"type": "object",
"properties": {
"@type": {
"type": "string",
"description": "The type of the serialized message."
}
},
"additionalProperties": true,
"description": "Contains an arbitrary serialized message along with a @type that describes the type of the serialized message."
},
"description": "A list of messages that carry the error details. There is a common set of message types for APIs to use."
}
},
"description": "The `Status` type defines a logical error model that is suitable for different programming environments, including REST APIs and RPC APIs. It is used by [gRPC](https://github.com/grpc). Each `Status` message contains three pieces of data: error code, error message, and error details. You can find out more about this error model and how to work with it in the [API Design Guide](https://cloud.google.com/apis/design/errors)."
}
}
}
}
},
"security": [
{
"bearerAuth": []
}
],
"components": {
"securitySchemes": {
"bearerAuth": {
"type": "http",
"description": "Access token from `/authenticate`",
"scheme": "bearer",
"bearerFormat": "JWT"
}
}
}
}
```
# Update route stop items (https://docs.roundtrip.ai/docs/api-reference/stops/put-routes-routeId-stops-stopId-items)
PUT /routes/{routeId}/stops/{stopId}/items
Updates the items for an imported stop on a route. Allows you to set or
replace the list of items for a stop that was previously imported via
ImportStops. Only stops with an `importedStopId` can have their items
updated through this endpoint. Stops created from Shopify orders, saved
stops, or manually created stops cannot be updated via this RPC. The
response will include the updated stop with the new items. The route will
be marked as not optimized after updating items, so the caller should
reoptimize the route if needed via ReoptimizeRoute. Items are validated to
ensure they meet the following constraints: maximum 250 items per stop,
item names up to 1500 characters, quantities up to 100,000, and weight up
to 1,000,000,000 grams.
## OpenAPI specification
```json
{
"servers": [
{
"url": "https://easyroutes.roundtrip.ai/api/2024-07"
}
],
"tags": [
"Stops"
],
"summary": "Update route stop items",
"description": "Updates the items for an imported stop on a route. Allows you to set or\n replace the list of items for a stop that was previously imported via\n ImportStops. Only stops with an `importedStopId` can have their items\n updated through this endpoint. Stops created from Shopify orders, saved\n stops, or manually created stops cannot be updated via this RPC. The\n response will include the updated stop with the new items. The route will\n be marked as not optimized after updating items, so the caller should\n reoptimize the route if needed via ReoptimizeRoute. Items are validated to\n ensure they meet the following constraints: maximum 250 items per stop,\n item names up to 1500 characters, quantities up to 100,000, and weight up\n to 1,000,000,000 grams.",
"operationId": "UpdateRouteStopItems",
"parameters": [
{
"name": "routeId",
"in": "path",
"description": "The ID of the route to update stop items.",
"required": true,
"schema": {
"type": "string",
"examples": [
"rte-123e4567-e89b-12d3-a456-426614174000"
]
}
},
{
"name": "stopId",
"in": "path",
"description": "The ID of the stop to update items for.",
"required": true,
"schema": {
"type": "string",
"examples": [
"rst-123e4567-e89b-12d3-a456-426614174000"
]
}
},
{
"name": "Idempotency-Key",
"in": "header",
"description": "A unique key for safely retrying this operation. For more information read [our guide](https://docs.roundtrip.ai/docs/concepts/idempotency.md).",
"schema": {
"maxLength": 255,
"minLength": 1,
"type": "string"
},
"examples": {
"default": {
"value": "550e8400-e29b-41d4-a716-446655440000"
}
}
}
],
"requestBody": {
"content": {
"application/json": {
"schema": {
"type": "array",
"items": {
"title": "StopItem",
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "Item name (e.g. `\"Bananas\"`).",
"examples": [
"Bananas"
]
},
"quantity": {
"type": "integer",
"description": "Quantity of the item (e.g. `5`).",
"format": "int32",
"examples": [
5
]
},
"grams": {
"type": "integer",
"description": "Weight of the item in grams (e.g. `500`).",
"format": "int32",
"examples": [
500
]
},
"sku": {
"type": "string",
"description": "Stock keeping unit (e.g. `\"BANANA-001\"`).",
"examples": [
"BANANA-001"
]
}
},
"description": "An item to be delivered at a stop."
}
}
}
},
"required": true
},
"responses": {
"200": {
"description": "OK",
"headers": {
"Idempotency-Key": {
"description": "The idempotency key associated with the response.",
"schema": {
"type": "string"
}
},
"Idempotency-Replayed": {
"description": "Whether the response was replayed from a previous request.",
"schema": {
"type": "boolean"
}
}
},
"content": {
"application/json": {
"schema": {
"title": "RouteStop",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Stop ID (e.g. `\"rst-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"rst-123e4567-e89b-12d3-a456-426614174000"
]
},
"type": {
"enum": [
"UNKNOWN",
"DELIVERY",
"BREAK",
"PICKUP",
"TASK"
],
"type": "string",
"description": "The type of stop (DELIVERY, BREAK, PICKUP, or TASK).",
"format": "enum",
"examples": [
"DELIVERY"
]
},
"deliveryStatus": {
"enum": [
"UNKNOWN",
"DELIVERED",
"OUT_FOR_DELIVERY",
"ATTEMPTED_DELIVERY",
"READY_FOR_DELIVERY"
],
"type": "string",
"description": "The status for DELIVERY, PICKUP, or TASK stops.",
"format": "enum",
"examples": [
"ATTEMPTED_DELIVERY"
]
},
"breakStatus": {
"enum": [
"UNKNOWN",
"COMPLETED"
],
"type": "string",
"description": "The status for BREAK stops.",
"format": "enum",
"examples": [
"COMPLETED"
]
},
"updatedAt": {
"type": "string",
"description": "Timestamp when the stop status was last updated. Note that this timestamp\n corresponds only to major status updates (i.e. stop marked as DELIVERED).\n Minor updates like task completion or adding proof of delivery will not\n advance this timestamp. For those events, use the timestamps on the task or\n proof of delivery attachment.",
"format": "date-time",
"examples": [
"2026-03-30T13:15:00Z"
]
},
"duration": {
"pattern": "^-?(?:0|[1-9][0-9]{0,11})(?:\\.[0-9]{1,9})?s$",
"type": "string",
"description": "Planned duration of the stop in seconds.",
"examples": [
"300s"
]
},
"plannedArrival": {
"type": "string",
"description": "Planned arrival time at the stop.",
"format": "date-time",
"examples": [
"2026-03-30T13:00:00Z"
]
},
"note": {
"type": "string",
"description": "Top-level note for the stop, as entered manually by route planners,\n inherited from a saved or imported stop, or set by order import automation\n rules.",
"examples": [
"Leave at door."
]
},
"address": {
"allOf": [
{
"title": "Address",
"type": "object",
"properties": {
"address1": {
"type": "string",
"description": "Street address line 1 (e.g. `\"123 Main St\"`).",
"examples": [
"123 Main St"
]
},
"address2": {
"type": "string",
"description": "Street address line 2 (e.g. `\"Apt 101\"`).",
"examples": [
"Apt 3B"
]
},
"city": {
"type": "string",
"description": "City name (e.g. `\"New York\"`).",
"examples": [
"New York"
]
},
"provinceCode": {
"type": "string",
"description": "Province or state as subdivision codes in\n [ISO 3166-2](https://en.wikipedia.org/wiki/ISO_3166-2) format without the\n country prefix (e.g. `\"NY\"` for New York).",
"examples": [
"NY"
]
},
"countryCode": {
"type": "string",
"description": "Country code (e.g. `\"US\"`).",
"examples": [
"US"
]
},
"zip": {
"type": "string",
"description": "Postal or ZIP code (e.g. `\"10001\"`).",
"examples": [
"10001"
]
}
},
"description": "A physical street address."
}
],
"description": "Delivery address for the stop.",
"examples": [
{
"address1": "123 Main St",
"address2": "Apt 3B",
"city": "New York",
"provinceCode": "NY",
"countryCode": "US",
"zip": "10001"
}
]
},
"contact": {
"allOf": [
{
"title": "Contact",
"type": "object",
"properties": {
"firstName": {
"type": "string",
"description": "First name (e.g. `\"John\"`).",
"examples": [
"John"
]
},
"lastName": {
"type": "string",
"description": "Last name (e.g. `\"Doe\"`).",
"examples": [
"Doe"
]
},
"company": {
"type": "string",
"description": "Company name (e.g. `\"Roundtrip Systems Inc\"`).",
"examples": [
"Roundtrip Systems Inc"
]
},
"phone": {
"type": "string",
"description": "Phone number in [E.164 format](https://en.wikipedia.org/wiki/E.164) (e.g.\n `\"+14265551000\"`).",
"examples": [
"+14265551000"
]
},
"email": {
"type": "string",
"description": "Email address (e.g. `\"john.doe@roundtrip.ai\"`)",
"examples": [
"john.doe@roundtrip.ai"
]
}
},
"description": "Contact information for a person or company."
}
],
"description": "Contact information for the stop delivery recipient.",
"examples": [
{
"firstName": "John",
"lastName": "Doe",
"company": "Roundtrip Systems Inc",
"phone": "+14265551000",
"email": "john.doe@roundtrip.ai"
}
]
},
"plannedCoordinates": {
"allOf": [
{
"type": "object",
"properties": {
"latitude": {
"type": "number",
"description": "The latitude in degrees. It must be in the range [-90.0, +90.0].",
"format": "double"
},
"longitude": {
"type": "number",
"description": "The longitude in degrees. It must be in the range [-180.0, +180.0].",
"format": "double"
}
},
"description": "An object that represents a latitude/longitude pair. This is expressed as a\n pair of doubles to represent degrees latitude and degrees longitude. Unless\n specified otherwise, this must conform to the\n WGS84\n standard. Values must be within normalized ranges."
}
],
"description": "Planned coordinates for the stop.",
"examples": [
{
"latitude": 40.7128,
"longitude": -74.006
}
]
},
"items": {
"type": "array",
"items": {
"title": "StopItem",
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "Item name (e.g. `\"Bananas\"`).",
"examples": [
"Bananas"
]
},
"quantity": {
"type": "integer",
"description": "Quantity of the item (e.g. `5`).",
"format": "int32",
"examples": [
5
]
},
"grams": {
"type": "integer",
"description": "Weight of the item in grams (e.g. `500`).",
"format": "int32",
"examples": [
500
]
},
"sku": {
"type": "string",
"description": "Stock keeping unit (e.g. `\"BANANA-001\"`).",
"examples": [
"BANANA-001"
]
}
},
"description": "An item to be delivered at a stop."
},
"description": "Items to deliver at the stop."
},
"source": {
"enum": [
"UNKNOWN",
"SHOPIFY_ORDER",
"SAVED_STOP",
"IMPORTED_STOP"
],
"type": "string",
"description": "The source of the stop, which may be populated for `DELIVERY` stops. The\n source can be a `SHOPIFY_ORDER`, an EasyRoutes `SAVED_STOP`, or an\n `IMPORTED_STOP` from an external source (such as CSV file).",
"format": "enum",
"examples": [
"IMPORTED_STOP"
]
},
"shopifyOrderId": {
"type": "string",
"description": "The Shopify order ID, populated when the stop source is a `SHOPIFY_ORDER`.",
"examples": [
"6229749334323"
]
},
"savedStopId": {
"type": "string",
"description": "The saved stop ID, populated when the stop source is a `SAVED_STOP`.",
"examples": [
"sst-123e4567-e89b-12d3-a456-426614174000"
]
},
"deliveredCoordinates": {
"allOf": [
{
"type": "object",
"properties": {
"latitude": {
"type": "number",
"description": "The latitude in degrees. It must be in the range [-90.0, +90.0].",
"format": "double"
},
"longitude": {
"type": "number",
"description": "The longitude in degrees. It must be in the range [-180.0, +180.0].",
"format": "double"
}
},
"description": "An object that represents a latitude/longitude pair. This is expressed as a\n pair of doubles to represent degrees latitude and degrees longitude. Unless\n specified otherwise, this must conform to the\n WGS84\n standard. Values must be within normalized ranges."
}
],
"description": "Delivered coordinates for the stop."
},
"proofOfDeliveryNote": {
"type": "string",
"description": "Proof of delivery note for the stop.",
"examples": [
"Left at door."
]
},
"proofOfDeliveryPhotos": {
"type": "array",
"items": {
"title": "StopAttachment",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Attachment ID (e.g. `\"att-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"att-123e4567-e89b-12d3-a456-426614174000"
]
},
"createdAt": {
"type": "string",
"description": "Timestamp when the attachment was created.",
"format": "date-time",
"examples": [
"2026-03-30T09:05:00Z"
]
},
"url": {
"type": "string",
"description": "URL to fetch the attachment.",
"examples": [
"https://example.com/stop-attachment/attachment-2025-06-03-1"
]
}
},
"description": "An attachment to a stop, such as a proof of delivery photo or signature."
},
"description": "Proof of delivery photos for the stop. Photos may be fetched using the URLs\n on the attachments."
},
"proofOfDeliverySignatures": {
"type": "array",
"items": {
"title": "StopAttachment",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Attachment ID (e.g. `\"att-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"att-123e4567-e89b-12d3-a456-426614174000"
]
},
"createdAt": {
"type": "string",
"description": "Timestamp when the attachment was created.",
"format": "date-time",
"examples": [
"2026-03-30T09:05:00Z"
]
},
"url": {
"type": "string",
"description": "URL to fetch the attachment.",
"examples": [
"https://example.com/stop-attachment/attachment-2025-06-03-1"
]
}
},
"description": "An attachment to a stop, such as a proof of delivery photo or signature."
},
"description": "Proof of delivery signatures for the stop. Signatures may be fetched using\n the URLs on the attachments."
},
"tasks": {
"type": "array",
"items": {
"title": "Task",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Task ID (e.g. `\"tsk-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"tsk-123e4567-e89b-12d3-a456-426614174000"
]
},
"title": {
"type": "string",
"description": "Task title (e.g. `\"Delivery checklist\"`).",
"examples": [
"Delivery checklist"
]
},
"type": {
"enum": [
"UNKNOWN",
"CHECKBOXES",
"RADIO_BUTTONS",
"TEXT_INPUT",
"DECIMAL_INPUT",
"SCANNER_INPUT"
],
"type": "string",
"description": "Task type.",
"format": "enum",
"examples": [
"TEXT_INPUT"
]
},
"items": {
"type": "array",
"items": {
"title": "TaskItem",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Item ID (e.g. `\"itm-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"itm-123e4567-e89b-12d3-a456-426614174000"
]
},
"title": {
"type": "string",
"description": "Item title (e.g. `\"Pick up package\"`).",
"examples": [
"Pick up package"
]
},
"complete": {
"type": "boolean",
"description": "Whether the item is completed.",
"examples": [
true
]
},
"updatedAt": {
"type": "string",
"description": "Timestamp when the item was last updated.",
"format": "date-time",
"examples": [
"2026-03-30T13:00:00Z"
]
}
},
"description": "An item within a task. For `CHECKBOXES`, each item on a task may be completed\n independently. For `RADIO_BUTTONS`, at most one item will be completed."
},
"description": "Task items (populated for `CHECKBOXES` and `RADIO_BUTTONS`).",
"examples": [
[]
]
},
"input": {
"allOf": [
{
"title": "TaskInput",
"type": "object",
"properties": {
"value": {
"type": "string",
"description": "Input value.",
"examples": [
"020123456789"
]
},
"updatedAt": {
"type": "string",
"description": "Timestamp when the input was last updated.",
"format": "date-time",
"examples": [
"2026-03-30T13:00:00Z"
]
},
"inputMethod": {
"enum": [
"UNKNOWN",
"SCANNED"
],
"type": "string",
"description": "Whether input was scanned (e.g. a scanned barcode)",
"format": "enum",
"examples": [
"SCANNED"
]
}
},
"description": "Captured driver input for a task. The value may be text for `TEXT_INPUT`\n tasks or a string decimal number for `DECIMAL_INPUT` tasks."
}
],
"description": "Task input (populated for `TEXT_INPUT` and `DECIMAL_INPUT`)."
},
"requiredToMarkStopAsDelivered": {
"type": "boolean",
"description": "Whether the task is required to mark the stop as completed. In the case of\n tasks on `RouteStart`, this represents tasks required for starting the\n route. In the case of tasks on `RouteEnd`, this represents tasks required\n for completing the route.",
"examples": [
true
]
},
"requiredToMarkStopAsAttempted": {
"type": "boolean",
"description": "Whether the task is required to mark the stop as attempted.",
"examples": [
true
]
}
},
"description": "A task to be completed at a stop, or at the start or end of a route. Tasks\n may have one or more items for `CHECKBOXES` or `RADIO_BUTTONS`, or may have\n an input for `TEXT_INPUT` or `DECIMAL_INPUT`."
},
"description": "Driver tasks for the stop, including completed items and any input from the\n driver."
},
"priority": {
"maximum": 10,
"type": "integer",
"description": "Priority of the stop for route planning. The valid range for stop priority\n is between `1` (low) and `10` (high), with default priority corresponding\n to a value of `5`. A priority value of `0` is considered unset and is\n treated the same as \"default\" priority. Stops with higher priority will be\n preferred when generating routes with constraints.",
"format": "int32",
"examples": [
8
]
},
"importedStopId": {
"type": "string",
"description": "The imported stop ID, populated when the stop source is `IMPORTED_STOP`.",
"examples": [
"ist-123e4567-e89b-12d3-a456-426614174000"
]
},
"orderName": {
"type": "string",
"description": "The name of the order associated with the stop. For Shopify orders, the\n name is generated by combining the `orderNumber` property with the order\n prefix and suffix that are set in the merchant's general settings. For\n EasyRoutes imported orders, this field is populated with the order name\n provided on import.",
"examples": [
"#1234"
]
},
"distanceMeters": {
"type": "number",
"description": "The distance in meters from the previous stop.",
"format": "double",
"examples": [
123.45
]
},
"updatedArrival": {
"type": "string",
"description": "Estimated arrival time at the stop. If the stop is completed, this will be\n the actual arrival time.",
"format": "date-time",
"examples": [
"2026-03-30T13:05:00Z"
]
},
"timeWindows": {
"type": "array",
"items": {
"title": "TimeWindow",
"type": "object",
"properties": {
"start": {
"allOf": [
{
"title": "TimeOfDay",
"type": "object",
"properties": {
"hours": {
"maximum": 23,
"type": "integer",
"description": "Hours of day in 24 hour format. Must be from 0 to 23.",
"format": "int32",
"examples": [
13
]
},
"minutes": {
"maximum": 59,
"type": "integer",
"description": "Minutes of hour of day. Must be from 0 to 59.",
"format": "int32",
"examples": [
37
]
},
"seconds": {
"maximum": 59,
"type": "integer",
"description": "Seconds of minutes of the time. Must be from 0 to 59.",
"format": "int32",
"examples": [
16
]
}
},
"description": "A time of day, independent of a particular date or timezone."
}
],
"description": "The start time of the time window (optional)."
},
"end": {
"allOf": [
{
"title": "TimeOfDay",
"type": "object",
"properties": {
"hours": {
"maximum": 23,
"type": "integer",
"description": "Hours of day in 24 hour format. Must be from 0 to 23.",
"format": "int32",
"examples": [
13
]
},
"minutes": {
"maximum": 59,
"type": "integer",
"description": "Minutes of hour of day. Must be from 0 to 59.",
"format": "int32",
"examples": [
37
]
},
"seconds": {
"maximum": 59,
"type": "integer",
"description": "Seconds of minutes of the time. Must be from 0 to 59.",
"format": "int32",
"examples": [
16
]
}
},
"description": "A time of day, independent of a particular date or timezone."
}
],
"description": "The end time of the time window (optional)."
}
},
"description": "A time window for a stop. The time window may be open-ended, but one or both\n of the start and end times should be provided. The end time must be >= the\n start time."
},
"description": "The time window for the stop. Note that we currently support at most one\n time window but may support multiple time windows in the future.",
"examples": [
[
{
"start": {
"hours": 9
},
"end": {
"hours": 17
}
}
]
]
},
"deliveryDate": {
"allOf": [
{
"title": "Date",
"required": [
"year",
"month",
"day"
],
"type": "object",
"properties": {
"year": {
"maximum": 9999,
"minimum": 1,
"type": "integer",
"description": "Year of the date. Must be from 1 to 9999.",
"format": "int32",
"examples": [
2019
]
},
"month": {
"maximum": 12,
"minimum": 1,
"type": "integer",
"description": "Month of a year. Must be from 1 to 12.",
"format": "int32",
"examples": [
11
]
},
"day": {
"maximum": 31,
"minimum": 1,
"type": "integer",
"description": "Day of a month. Must be from 1 to 31.",
"format": "int32",
"examples": [
15
]
}
},
"description": "A date in year-month-day format."
}
],
"description": "The planned delivery date for the stop.",
"examples": [
{
"year": 2025,
"month": 12,
"day": 16
}
]
},
"attributes": {
"type": "array",
"items": {
"title": "Attribute",
"type": "object",
"properties": {
"key": {
"type": "string",
"description": "Attribute key. Must be non-empty.",
"examples": [
"delivery_date"
]
},
"value": {
"type": "string",
"description": "Attribute value.",
"examples": [
"2025-12-16"
]
}
},
"description": "A key-value pair for storing additional information on a stop, such as order\n details, delivery instructions, or custom fields."
},
"description": "Additional attributes for the stop. Attributes are key-value pairs for\n storing additional structured data on stops. These may be populated from\n the Shopify order or set on import.",
"examples": [
[
{
"key": "color",
"value": "blue"
}
]
]
},
"clientStopId": {
"type": "string",
"description": "The client-provided ID associated with the stop, if provided on import.",
"examples": [
"test-order-1234"
]
},
"tags": {
"type": "array",
"items": {
"type": "string"
},
"description": "The tags for the stop. Tags are used to categorize stops and can be used\n for filtering and grouping stops in the EasyRoutes web app. These may be\n populated from the Shopify order or set on import.",
"examples": [
[
"foo",
"bar"
]
]
},
"attemptedReason": {
"enum": [
"UNKNOWN",
"NOT_AVAILABLE",
"ACCESS_DENIED",
"INCORRECT_ADDRESS",
"SAFE_PLACE_UNAVAILABLE",
"REFUSED",
"EXTERNAL",
"INCORRECT_ITEMS",
"OTHER",
"CANCELED"
],
"type": "string",
"description": "The reason for marking the stop as attempted. This is only populated when\n `deliveryStatus = ATTEMPTED_DELIVERY`.",
"format": "enum",
"examples": [
"NOT_AVAILABLE"
]
},
"attemptedNote": {
"type": "string",
"description": "Optional note related to the reason for marking the stop as attempted. This\n is optionally populated when `deliveryStatus = ATTEMPTED_DELIVERY`.",
"examples": [
"Customer did not answer the door."
]
},
"customerRating": {
"allOf": [
{
"title": "CustomerRating",
"type": "object",
"properties": {
"rating": {
"maximum": 5,
"minimum": 1,
"type": "integer",
"description": "Rating from 1-5",
"format": "int32",
"examples": [
5
]
},
"comment": {
"type": "string",
"description": "Customer comment related to rating",
"examples": [
"Excellent delivery"
]
},
"createdAt": {
"type": "string",
"description": "Timestamp when rating was left by customer.",
"format": "date-time",
"examples": [
"2026-03-30T18:00:00Z"
]
}
},
"description": "Customer rating and feedback left on a stop."
}
],
"description": "Rating left by customer. This can only be populated once `deliveryStatus =\n DELIVERED`."
},
"customSignatureDisclosure": {
"type": "string",
"description": "Optional custom signature disclosure that is shown to customers in the\n driver app.",
"examples": [
"I acknowledge that I have received this delivery."
]
},
"shopifyOrder": {
"allOf": [
{
"title": "ShopifyOrder",
"type": "object",
"properties": {
"orderNote": {
"type": "string",
"description": "The Shopify order note.",
"examples": [
"Customer has paid."
]
},
"customerNote": {
"type": "string",
"description": "The Shopify customer note for the order.",
"examples": [
"Leave at door."
]
}
},
"description": "Shopify-specific information for a RouteStop."
}
],
"description": "Information from the associated Shopify order, if applicable. Populated if\n stop source is `SHOPIFY_ORDER`"
},
"proofOfDeliveryBarcodes": {
"type": "array",
"items": {
"title": "ScannedBarcode",
"type": "object",
"properties": {
"value": {
"type": "string",
"description": "Barcode value (e.g. `\"123456789012\"`).",
"examples": [
"123456789012"
]
},
"createdAt": {
"type": "string",
"description": "Timestamp when the barcode was scanned.",
"format": "date-time",
"examples": [
"2026-03-30T13:10:00Z"
]
}
},
"description": "A proof of delivery barcode scanned at a stop."
},
"description": "Proof of delivery barcodes scanned at the stop."
},
"proofOfDeliveryBarcodeIssues": {
"type": "array",
"items": {
"title": "ScannedBarcodeIssue",
"type": "object",
"properties": {
"reason": {
"enum": [
"UNKNOWN",
"ITEM_MISSING",
"NOT_SCANNABLE",
"INCORRECT"
],
"type": "string",
"description": "The reported reason for the barcode issue.",
"format": "enum",
"examples": [
"ITEM_MISSING"
]
},
"note": {
"type": "string",
"description": "Optional note related to the reason for reporting a barcode issue.",
"examples": [
"Item was not packed."
]
},
"createdAt": {
"type": "string",
"description": "Timestamp when the issue was reported.",
"format": "date-time",
"examples": [
"2026-03-30T13:10:00Z"
]
}
},
"description": "A reported issue related to scanning barcodes at a stop."
},
"description": "Proof of delivery barcode issues reported at the stop."
},
"orderReferenceUrl": {
"type": "string",
"description": "A reference URL for the order associated with the stop (e.g. a link to the\n order in your order management system). Must be a valid HTTPS URL. This\n field can only be populated for imported stops.",
"examples": [
"https://orders.example.com/orders/148977776"
]
}
},
"description": "A stop on a route. A stop may correspond to a delivery or a driver break as\n determined by the type. A delivery stop will have location and contact\n information, items to deliver, optional order details, status, arrival time\n and stop duration, driver tasks and any proof of delivery information. A\n break stop will have start time and duration, and status."
}
}
}
},
"default": {
"description": "Default error response",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"code": {
"type": "integer",
"description": "The status code, which should be an enum value of [google.rpc.Code][google.rpc.Code].",
"format": "int32"
},
"message": {
"type": "string",
"description": "A developer-facing error message, which should be in English. Any user-facing error message should be localized and sent in the [google.rpc.Status.details][google.rpc.Status.details] field, or localized by the client."
},
"details": {
"type": "array",
"items": {
"type": "object",
"properties": {
"@type": {
"type": "string",
"description": "The type of the serialized message."
}
},
"additionalProperties": true,
"description": "Contains an arbitrary serialized message along with a @type that describes the type of the serialized message."
},
"description": "A list of messages that carry the error details. There is a common set of message types for APIs to use."
}
},
"description": "The `Status` type defines a logical error model that is suitable for different programming environments, including REST APIs and RPC APIs. It is used by [gRPC](https://github.com/grpc). Each `Status` message contains three pieces of data: error code, error message, and error details. You can find out more about this error model and how to work with it in the [API Design Guide](https://cloud.google.com/apis/design/errors)."
}
}
}
}
},
"security": [
{
"bearerAuth": []
}
],
"components": {
"securitySchemes": {
"bearerAuth": {
"type": "http",
"description": "Access token from `/authenticate`",
"scheme": "bearer",
"bearerFormat": "JWT"
}
}
}
}
```
# Reorder route stop (https://docs.roundtrip.ai/docs/api-reference/stops/put-routes-routeId-stops-stopId-position)
PUT /routes/{routeId}/stops/{stopId}/position
Moves a stop on a route to a specific 0-based final index in the `stops`
list. Index `0` is the first route stop and index `len(stops) - 1` is the
last route stop. Note that `start` and `end` are not included in this
indexing. The response returns the full updated route because reordering a
stop may change stop order, ETAs, distances, and the `optimized` flag. The
route will be marked as not optimized after moving a stop, so the caller
should reoptimize the route if needed via
[`ReoptimizeRoute`](https://docs.roundtrip.ai/docs/api-reference/stops/post-routes-id-reoptimize.md).
## OpenAPI specification
```json
{
"servers": [
{
"url": "https://easyroutes.roundtrip.ai/api/2024-07"
}
],
"tags": [
"Stops"
],
"summary": "Reorder route stop",
"description": "Moves a stop on a route to a specific 0-based final index in the `stops`\n list. Index `0` is the first route stop and index `len(stops) - 1` is the\n last route stop. Note that `start` and `end` are not included in this\n indexing. The response returns the full updated route because reordering a\n stop may change stop order, ETAs, distances, and the `optimized` flag. The\n route will be marked as not optimized after moving a stop, so the caller\n should reoptimize the route if needed via\n [`ReoptimizeRoute`](https://docs.roundtrip.ai/docs/api-reference/stops/post-routes-id-reoptimize.md).",
"operationId": "ReorderRouteStop",
"parameters": [
{
"name": "routeId",
"in": "path",
"description": "The ID of the route containing the stop to move.",
"required": true,
"schema": {
"type": "string",
"examples": [
"rte-123e4567-e89b-12d3-a456-426614174000"
]
}
},
{
"name": "stopId",
"in": "path",
"description": "The ID of the stop to move.",
"required": true,
"schema": {
"type": "string",
"examples": [
"rst-123e4567-e89b-12d3-a456-426614174000"
]
}
},
{
"name": "Idempotency-Key",
"in": "header",
"description": "A unique key for safely retrying this operation. For more information read [our guide](https://docs.roundtrip.ai/docs/concepts/idempotency.md).",
"schema": {
"maxLength": 255,
"minLength": 1,
"type": "string"
},
"examples": {
"default": {
"value": "550e8400-e29b-41d4-a716-446655440000"
}
}
}
],
"requestBody": {
"content": {
"application/json": {
"schema": {
"title": "ReorderRouteStopRequest",
"required": [
"index"
],
"type": "object",
"properties": {
"index": {
"type": "integer",
"description": "The 0-based final index for the stop in route.stops. Valid range is\n `0..numStops-1`.",
"format": "int32",
"examples": [
2
]
}
}
}
}
},
"required": true
},
"responses": {
"200": {
"description": "OK",
"headers": {
"Idempotency-Key": {
"description": "The idempotency key associated with the response.",
"schema": {
"type": "string"
}
},
"Idempotency-Replayed": {
"description": "Whether the response was replayed from a previous request.",
"schema": {
"type": "boolean"
}
}
},
"content": {
"application/json": {
"schema": {
"title": "Route",
"required": [
"id",
"name",
"stops",
"createdAt",
"updatedAt",
"totalDistanceMeters",
"totalItemQuantity",
"totalItemGrams",
"optimized"
],
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Route ID (e.g. `\"rte-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"rte-123e4567-e89b-12d3-a456-426614174000"
]
},
"name": {
"type": "string",
"description": "Route name (e.g. `\"Morning route\"`).",
"examples": [
"Morning route"
]
},
"driver": {
"allOf": [
{
"title": "Driver",
"required": [
"id"
],
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Driver ID (e.g. `\"drv-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"drv-123e4567-e89b-12d3-a456-426614174000"
]
},
"firstName": {
"type": "string",
"description": "Driver first name (e.g. `\"John\"`).",
"examples": [
"John"
]
},
"lastName": {
"type": "string",
"description": "Driver last name (e.g. `\"Doe\"`).",
"examples": [
"Doe"
]
},
"phone": {
"type": "string",
"description": "Driver phone number in [E.164 format](https://en.wikipedia.org/wiki/E.164)\n (e.g. `\"+14265551000\"`).",
"examples": [
"+14265551000"
]
},
"status": {
"enum": [
"UNKNOWN",
"ACTIVE",
"INACTIVE",
"ARCHIVED"
],
"type": "string",
"description": "Shop driver status. (e.g. `ACTIVE`).",
"format": "enum",
"examples": [
"ACTIVE"
]
}
},
"description": "A driver who is assigned to a route."
}
],
"description": "Assigned driver for the route."
},
"start": {
"allOf": [
{
"title": "RouteStart",
"type": "object",
"properties": {
"address": {
"allOf": [
{
"title": "Address",
"type": "object",
"properties": {
"address1": {
"type": "string",
"description": "Street address line 1 (e.g. `\"123 Main St\"`).",
"examples": [
"123 Main St"
]
},
"address2": {
"type": "string",
"description": "Street address line 2 (e.g. `\"Apt 101\"`).",
"examples": [
"Apt 3B"
]
},
"city": {
"type": "string",
"description": "City name (e.g. `\"New York\"`).",
"examples": [
"New York"
]
},
"provinceCode": {
"type": "string",
"description": "Province or state as subdivision codes in\n [ISO 3166-2](https://en.wikipedia.org/wiki/ISO_3166-2) format without the\n country prefix (e.g. `\"NY\"` for New York).",
"examples": [
"NY"
]
},
"countryCode": {
"type": "string",
"description": "Country code (e.g. `\"US\"`).",
"examples": [
"US"
]
},
"zip": {
"type": "string",
"description": "Postal or ZIP code (e.g. `\"10001\"`).",
"examples": [
"10001"
]
}
},
"description": "A physical street address."
}
],
"description": "The start address of the route.",
"examples": [
{
"address1": "123 Main St",
"address2": "Apt 3B",
"city": "New York",
"provinceCode": "NY",
"countryCode": "US",
"zip": "10001"
}
]
},
"tasks": {
"type": "array",
"items": {
"title": "Task",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Task ID (e.g. `\"tsk-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"tsk-123e4567-e89b-12d3-a456-426614174000"
]
},
"title": {
"type": "string",
"description": "Task title (e.g. `\"Delivery checklist\"`).",
"examples": [
"Delivery checklist"
]
},
"type": {
"enum": [
"UNKNOWN",
"CHECKBOXES",
"RADIO_BUTTONS",
"TEXT_INPUT",
"DECIMAL_INPUT",
"SCANNER_INPUT"
],
"type": "string",
"description": "Task type.",
"format": "enum",
"examples": [
"TEXT_INPUT"
]
},
"items": {
"type": "array",
"items": {
"title": "TaskItem",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Item ID (e.g. `\"itm-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"itm-123e4567-e89b-12d3-a456-426614174000"
]
},
"title": {
"type": "string",
"description": "Item title (e.g. `\"Pick up package\"`).",
"examples": [
"Pick up package"
]
},
"complete": {
"type": "boolean",
"description": "Whether the item is completed.",
"examples": [
true
]
},
"updatedAt": {
"type": "string",
"description": "Timestamp when the item was last updated.",
"format": "date-time",
"examples": [
"2026-03-30T13:00:00Z"
]
}
},
"description": "An item within a task. For `CHECKBOXES`, each item on a task may be completed\n independently. For `RADIO_BUTTONS`, at most one item will be completed."
},
"description": "Task items (populated for `CHECKBOXES` and `RADIO_BUTTONS`).",
"examples": [
[]
]
},
"input": {
"allOf": [
{
"title": "TaskInput",
"type": "object",
"properties": {
"value": {
"type": "string",
"description": "Input value.",
"examples": [
"020123456789"
]
},
"updatedAt": {
"type": "string",
"description": "Timestamp when the input was last updated.",
"format": "date-time",
"examples": [
"2026-03-30T13:00:00Z"
]
},
"inputMethod": {
"enum": [
"UNKNOWN",
"SCANNED"
],
"type": "string",
"description": "Whether input was scanned (e.g. a scanned barcode)",
"format": "enum",
"examples": [
"SCANNED"
]
}
},
"description": "Captured driver input for a task. The value may be text for `TEXT_INPUT`\n tasks or a string decimal number for `DECIMAL_INPUT` tasks."
}
],
"description": "Task input (populated for `TEXT_INPUT` and `DECIMAL_INPUT`)."
},
"requiredToMarkStopAsDelivered": {
"type": "boolean",
"description": "Whether the task is required to mark the stop as completed. In the case of\n tasks on `RouteStart`, this represents tasks required for starting the\n route. In the case of tasks on `RouteEnd`, this represents tasks required\n for completing the route.",
"examples": [
true
]
},
"requiredToMarkStopAsAttempted": {
"type": "boolean",
"description": "Whether the task is required to mark the stop as attempted.",
"examples": [
true
]
}
},
"description": "A task to be completed at a stop, or at the start or end of a route. Tasks\n may have one or more items for `CHECKBOXES` or `RADIO_BUTTONS`, or may have\n an input for `TEXT_INPUT` or `DECIMAL_INPUT`."
},
"description": "Tasks to complete before starting the route."
},
"status": {
"enum": [
"UNKNOWN",
"STARTED"
],
"type": "string",
"description": "Status indicating whether the route has been started.",
"format": "enum",
"examples": [
"STARTED"
]
},
"updatedStart": {
"type": "string",
"description": "Updated start time for the route. If the route is started, this will be the\n actual start time.",
"format": "date-time",
"examples": [
"2026-03-30T09:05:00Z"
]
},
"scheduledStart": {
"type": "string",
"description": "Scheduled start time for the route (same as `scheduledFor` on the route).",
"format": "date-time",
"examples": [
"2026-03-30T09:00:00Z"
]
},
"photos": {
"type": "array",
"items": {
"title": "StopAttachment",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Attachment ID (e.g. `\"att-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"att-123e4567-e89b-12d3-a456-426614174000"
]
},
"createdAt": {
"type": "string",
"description": "Timestamp when the attachment was created.",
"format": "date-time",
"examples": [
"2026-03-30T09:05:00Z"
]
},
"url": {
"type": "string",
"description": "URL to fetch the attachment.",
"examples": [
"https://example.com/stop-attachment/attachment-2025-06-03-1"
]
}
},
"description": "An attachment to a stop, such as a proof of delivery photo or signature."
},
"description": "Photos for the route start. Photos may be fetched using the URLs on the\n attachments."
}
},
"description": "The start location of a route and any driver tasks to complete before\n beginning the route."
}
],
"description": "Route start address and tasks."
},
"end": {
"allOf": [
{
"title": "RouteEnd",
"type": "object",
"properties": {
"address": {
"allOf": [
{
"title": "Address",
"type": "object",
"properties": {
"address1": {
"type": "string",
"description": "Street address line 1 (e.g. `\"123 Main St\"`).",
"examples": [
"123 Main St"
]
},
"address2": {
"type": "string",
"description": "Street address line 2 (e.g. `\"Apt 101\"`).",
"examples": [
"Apt 3B"
]
},
"city": {
"type": "string",
"description": "City name (e.g. `\"New York\"`).",
"examples": [
"New York"
]
},
"provinceCode": {
"type": "string",
"description": "Province or state as subdivision codes in\n [ISO 3166-2](https://en.wikipedia.org/wiki/ISO_3166-2) format without the\n country prefix (e.g. `\"NY\"` for New York).",
"examples": [
"NY"
]
},
"countryCode": {
"type": "string",
"description": "Country code (e.g. `\"US\"`).",
"examples": [
"US"
]
},
"zip": {
"type": "string",
"description": "Postal or ZIP code (e.g. `\"10001\"`).",
"examples": [
"10001"
]
}
},
"description": "A physical street address."
}
],
"description": "The end address of the route.",
"examples": [
{
"address1": "123 Main St",
"address2": "Apt 3B",
"city": "New York",
"provinceCode": "NY",
"countryCode": "US",
"zip": "10001"
}
]
},
"tasks": {
"type": "array",
"items": {
"title": "Task",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Task ID (e.g. `\"tsk-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"tsk-123e4567-e89b-12d3-a456-426614174000"
]
},
"title": {
"type": "string",
"description": "Task title (e.g. `\"Delivery checklist\"`).",
"examples": [
"Delivery checklist"
]
},
"type": {
"enum": [
"UNKNOWN",
"CHECKBOXES",
"RADIO_BUTTONS",
"TEXT_INPUT",
"DECIMAL_INPUT",
"SCANNER_INPUT"
],
"type": "string",
"description": "Task type.",
"format": "enum",
"examples": [
"TEXT_INPUT"
]
},
"items": {
"type": "array",
"items": {
"title": "TaskItem",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Item ID (e.g. `\"itm-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"itm-123e4567-e89b-12d3-a456-426614174000"
]
},
"title": {
"type": "string",
"description": "Item title (e.g. `\"Pick up package\"`).",
"examples": [
"Pick up package"
]
},
"complete": {
"type": "boolean",
"description": "Whether the item is completed.",
"examples": [
true
]
},
"updatedAt": {
"type": "string",
"description": "Timestamp when the item was last updated.",
"format": "date-time",
"examples": [
"2026-03-30T13:00:00Z"
]
}
},
"description": "An item within a task. For `CHECKBOXES`, each item on a task may be completed\n independently. For `RADIO_BUTTONS`, at most one item will be completed."
},
"description": "Task items (populated for `CHECKBOXES` and `RADIO_BUTTONS`).",
"examples": [
[]
]
},
"input": {
"allOf": [
{
"title": "TaskInput",
"type": "object",
"properties": {
"value": {
"type": "string",
"description": "Input value.",
"examples": [
"020123456789"
]
},
"updatedAt": {
"type": "string",
"description": "Timestamp when the input was last updated.",
"format": "date-time",
"examples": [
"2026-03-30T13:00:00Z"
]
},
"inputMethod": {
"enum": [
"UNKNOWN",
"SCANNED"
],
"type": "string",
"description": "Whether input was scanned (e.g. a scanned barcode)",
"format": "enum",
"examples": [
"SCANNED"
]
}
},
"description": "Captured driver input for a task. The value may be text for `TEXT_INPUT`\n tasks or a string decimal number for `DECIMAL_INPUT` tasks."
}
],
"description": "Task input (populated for `TEXT_INPUT` and `DECIMAL_INPUT`)."
},
"requiredToMarkStopAsDelivered": {
"type": "boolean",
"description": "Whether the task is required to mark the stop as completed. In the case of\n tasks on `RouteStart`, this represents tasks required for starting the\n route. In the case of tasks on `RouteEnd`, this represents tasks required\n for completing the route.",
"examples": [
true
]
},
"requiredToMarkStopAsAttempted": {
"type": "boolean",
"description": "Whether the task is required to mark the stop as attempted.",
"examples": [
true
]
}
},
"description": "A task to be completed at a stop, or at the start or end of a route. Tasks\n may have one or more items for `CHECKBOXES` or `RADIO_BUTTONS`, or may have\n an input for `TEXT_INPUT` or `DECIMAL_INPUT`."
},
"description": "Tasks to complete before finishing the route."
},
"plannedArrival": {
"type": "string",
"description": "Planned arrival time at the end of the route.",
"format": "date-time",
"examples": [
"2026-03-30T17:00:00Z"
]
},
"distanceMeters": {
"type": "number",
"description": "The distance in meters from the previous stop.",
"format": "double",
"examples": [
1234.56
]
},
"updatedArrival": {
"type": "string",
"description": "Estimated arrival time at the end of the route. If the route is completed,\n this will be the actual arrival time.",
"format": "date-time",
"examples": [
"2026-03-30T17:05:00Z"
]
},
"status": {
"enum": [
"UNKNOWN",
"COMPLETED"
],
"type": "string",
"description": "Status indicating whether the route has been completed.",
"format": "enum",
"examples": [
"COMPLETED"
]
},
"photos": {
"type": "array",
"items": {
"title": "StopAttachment",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Attachment ID (e.g. `\"att-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"att-123e4567-e89b-12d3-a456-426614174000"
]
},
"createdAt": {
"type": "string",
"description": "Timestamp when the attachment was created.",
"format": "date-time",
"examples": [
"2026-03-30T09:05:00Z"
]
},
"url": {
"type": "string",
"description": "URL to fetch the attachment.",
"examples": [
"https://example.com/stop-attachment/attachment-2025-06-03-1"
]
}
},
"description": "An attachment to a stop, such as a proof of delivery photo or signature."
},
"description": "Photos for the route end. Photos may be fetched using the URLs on the\n attachments."
}
},
"description": "The end location of a route and any driver tasks to complete after completing\n the route."
}
],
"description": "Route end address and tasks."
},
"stops": {
"type": "array",
"items": {
"title": "RouteStop",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Stop ID (e.g. `\"rst-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"rst-123e4567-e89b-12d3-a456-426614174000"
]
},
"type": {
"enum": [
"UNKNOWN",
"DELIVERY",
"BREAK",
"PICKUP",
"TASK"
],
"type": "string",
"description": "The type of stop (DELIVERY, BREAK, PICKUP, or TASK).",
"format": "enum",
"examples": [
"DELIVERY"
]
},
"deliveryStatus": {
"enum": [
"UNKNOWN",
"DELIVERED",
"OUT_FOR_DELIVERY",
"ATTEMPTED_DELIVERY",
"READY_FOR_DELIVERY"
],
"type": "string",
"description": "The status for DELIVERY, PICKUP, or TASK stops.",
"format": "enum",
"examples": [
"ATTEMPTED_DELIVERY"
]
},
"breakStatus": {
"enum": [
"UNKNOWN",
"COMPLETED"
],
"type": "string",
"description": "The status for BREAK stops.",
"format": "enum",
"examples": [
"COMPLETED"
]
},
"updatedAt": {
"type": "string",
"description": "Timestamp when the stop status was last updated. Note that this timestamp\n corresponds only to major status updates (i.e. stop marked as DELIVERED).\n Minor updates like task completion or adding proof of delivery will not\n advance this timestamp. For those events, use the timestamps on the task or\n proof of delivery attachment.",
"format": "date-time",
"examples": [
"2026-03-30T13:15:00Z"
]
},
"duration": {
"pattern": "^-?(?:0|[1-9][0-9]{0,11})(?:\\.[0-9]{1,9})?s$",
"type": "string",
"description": "Planned duration of the stop in seconds.",
"examples": [
"300s"
]
},
"plannedArrival": {
"type": "string",
"description": "Planned arrival time at the stop.",
"format": "date-time",
"examples": [
"2026-03-30T13:00:00Z"
]
},
"note": {
"type": "string",
"description": "Top-level note for the stop, as entered manually by route planners,\n inherited from a saved or imported stop, or set by order import automation\n rules.",
"examples": [
"Leave at door."
]
},
"address": {
"allOf": [
{
"title": "Address",
"type": "object",
"properties": {
"address1": {
"type": "string",
"description": "Street address line 1 (e.g. `\"123 Main St\"`).",
"examples": [
"123 Main St"
]
},
"address2": {
"type": "string",
"description": "Street address line 2 (e.g. `\"Apt 101\"`).",
"examples": [
"Apt 3B"
]
},
"city": {
"type": "string",
"description": "City name (e.g. `\"New York\"`).",
"examples": [
"New York"
]
},
"provinceCode": {
"type": "string",
"description": "Province or state as subdivision codes in\n [ISO 3166-2](https://en.wikipedia.org/wiki/ISO_3166-2) format without the\n country prefix (e.g. `\"NY\"` for New York).",
"examples": [
"NY"
]
},
"countryCode": {
"type": "string",
"description": "Country code (e.g. `\"US\"`).",
"examples": [
"US"
]
},
"zip": {
"type": "string",
"description": "Postal or ZIP code (e.g. `\"10001\"`).",
"examples": [
"10001"
]
}
},
"description": "A physical street address."
}
],
"description": "Delivery address for the stop.",
"examples": [
{
"address1": "123 Main St",
"address2": "Apt 3B",
"city": "New York",
"provinceCode": "NY",
"countryCode": "US",
"zip": "10001"
}
]
},
"contact": {
"allOf": [
{
"title": "Contact",
"type": "object",
"properties": {
"firstName": {
"type": "string",
"description": "First name (e.g. `\"John\"`).",
"examples": [
"John"
]
},
"lastName": {
"type": "string",
"description": "Last name (e.g. `\"Doe\"`).",
"examples": [
"Doe"
]
},
"company": {
"type": "string",
"description": "Company name (e.g. `\"Roundtrip Systems Inc\"`).",
"examples": [
"Roundtrip Systems Inc"
]
},
"phone": {
"type": "string",
"description": "Phone number in [E.164 format](https://en.wikipedia.org/wiki/E.164) (e.g.\n `\"+14265551000\"`).",
"examples": [
"+14265551000"
]
},
"email": {
"type": "string",
"description": "Email address (e.g. `\"john.doe@roundtrip.ai\"`)",
"examples": [
"john.doe@roundtrip.ai"
]
}
},
"description": "Contact information for a person or company."
}
],
"description": "Contact information for the stop delivery recipient.",
"examples": [
{
"firstName": "John",
"lastName": "Doe",
"company": "Roundtrip Systems Inc",
"phone": "+14265551000",
"email": "john.doe@roundtrip.ai"
}
]
},
"plannedCoordinates": {
"allOf": [
{
"type": "object",
"properties": {
"latitude": {
"type": "number",
"description": "The latitude in degrees. It must be in the range [-90.0, +90.0].",
"format": "double"
},
"longitude": {
"type": "number",
"description": "The longitude in degrees. It must be in the range [-180.0, +180.0].",
"format": "double"
}
},
"description": "An object that represents a latitude/longitude pair. This is expressed as a\n pair of doubles to represent degrees latitude and degrees longitude. Unless\n specified otherwise, this must conform to the\n WGS84\n standard. Values must be within normalized ranges."
}
],
"description": "Planned coordinates for the stop.",
"examples": [
{
"latitude": 40.7128,
"longitude": -74.006
}
]
},
"items": {
"type": "array",
"items": {
"title": "StopItem",
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "Item name (e.g. `\"Bananas\"`).",
"examples": [
"Bananas"
]
},
"quantity": {
"type": "integer",
"description": "Quantity of the item (e.g. `5`).",
"format": "int32",
"examples": [
5
]
},
"grams": {
"type": "integer",
"description": "Weight of the item in grams (e.g. `500`).",
"format": "int32",
"examples": [
500
]
},
"sku": {
"type": "string",
"description": "Stock keeping unit (e.g. `\"BANANA-001\"`).",
"examples": [
"BANANA-001"
]
}
},
"description": "An item to be delivered at a stop."
},
"description": "Items to deliver at the stop."
},
"source": {
"enum": [
"UNKNOWN",
"SHOPIFY_ORDER",
"SAVED_STOP",
"IMPORTED_STOP"
],
"type": "string",
"description": "The source of the stop, which may be populated for `DELIVERY` stops. The\n source can be a `SHOPIFY_ORDER`, an EasyRoutes `SAVED_STOP`, or an\n `IMPORTED_STOP` from an external source (such as CSV file).",
"format": "enum",
"examples": [
"IMPORTED_STOP"
]
},
"shopifyOrderId": {
"type": "string",
"description": "The Shopify order ID, populated when the stop source is a `SHOPIFY_ORDER`.",
"examples": [
"6229749334323"
]
},
"savedStopId": {
"type": "string",
"description": "The saved stop ID, populated when the stop source is a `SAVED_STOP`.",
"examples": [
"sst-123e4567-e89b-12d3-a456-426614174000"
]
},
"deliveredCoordinates": {
"allOf": [
{
"type": "object",
"properties": {
"latitude": {
"type": "number",
"description": "The latitude in degrees. It must be in the range [-90.0, +90.0].",
"format": "double"
},
"longitude": {
"type": "number",
"description": "The longitude in degrees. It must be in the range [-180.0, +180.0].",
"format": "double"
}
},
"description": "An object that represents a latitude/longitude pair. This is expressed as a\n pair of doubles to represent degrees latitude and degrees longitude. Unless\n specified otherwise, this must conform to the\n WGS84\n standard. Values must be within normalized ranges."
}
],
"description": "Delivered coordinates for the stop."
},
"proofOfDeliveryNote": {
"type": "string",
"description": "Proof of delivery note for the stop.",
"examples": [
"Left at door."
]
},
"proofOfDeliveryPhotos": {
"type": "array",
"items": {
"title": "StopAttachment",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Attachment ID (e.g. `\"att-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"att-123e4567-e89b-12d3-a456-426614174000"
]
},
"createdAt": {
"type": "string",
"description": "Timestamp when the attachment was created.",
"format": "date-time",
"examples": [
"2026-03-30T09:05:00Z"
]
},
"url": {
"type": "string",
"description": "URL to fetch the attachment.",
"examples": [
"https://example.com/stop-attachment/attachment-2025-06-03-1"
]
}
},
"description": "An attachment to a stop, such as a proof of delivery photo or signature."
},
"description": "Proof of delivery photos for the stop. Photos may be fetched using the URLs\n on the attachments."
},
"proofOfDeliverySignatures": {
"type": "array",
"items": {
"title": "StopAttachment",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Attachment ID (e.g. `\"att-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"att-123e4567-e89b-12d3-a456-426614174000"
]
},
"createdAt": {
"type": "string",
"description": "Timestamp when the attachment was created.",
"format": "date-time",
"examples": [
"2026-03-30T09:05:00Z"
]
},
"url": {
"type": "string",
"description": "URL to fetch the attachment.",
"examples": [
"https://example.com/stop-attachment/attachment-2025-06-03-1"
]
}
},
"description": "An attachment to a stop, such as a proof of delivery photo or signature."
},
"description": "Proof of delivery signatures for the stop. Signatures may be fetched using\n the URLs on the attachments."
},
"tasks": {
"type": "array",
"items": {
"title": "Task",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Task ID (e.g. `\"tsk-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"tsk-123e4567-e89b-12d3-a456-426614174000"
]
},
"title": {
"type": "string",
"description": "Task title (e.g. `\"Delivery checklist\"`).",
"examples": [
"Delivery checklist"
]
},
"type": {
"enum": [
"UNKNOWN",
"CHECKBOXES",
"RADIO_BUTTONS",
"TEXT_INPUT",
"DECIMAL_INPUT",
"SCANNER_INPUT"
],
"type": "string",
"description": "Task type.",
"format": "enum",
"examples": [
"TEXT_INPUT"
]
},
"items": {
"type": "array",
"items": {
"title": "TaskItem",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Item ID (e.g. `\"itm-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"itm-123e4567-e89b-12d3-a456-426614174000"
]
},
"title": {
"type": "string",
"description": "Item title (e.g. `\"Pick up package\"`).",
"examples": [
"Pick up package"
]
},
"complete": {
"type": "boolean",
"description": "Whether the item is completed.",
"examples": [
true
]
},
"updatedAt": {
"type": "string",
"description": "Timestamp when the item was last updated.",
"format": "date-time",
"examples": [
"2026-03-30T13:00:00Z"
]
}
},
"description": "An item within a task. For `CHECKBOXES`, each item on a task may be completed\n independently. For `RADIO_BUTTONS`, at most one item will be completed."
},
"description": "Task items (populated for `CHECKBOXES` and `RADIO_BUTTONS`).",
"examples": [
[]
]
},
"input": {
"allOf": [
{
"title": "TaskInput",
"type": "object",
"properties": {
"value": {
"type": "string",
"description": "Input value.",
"examples": [
"020123456789"
]
},
"updatedAt": {
"type": "string",
"description": "Timestamp when the input was last updated.",
"format": "date-time",
"examples": [
"2026-03-30T13:00:00Z"
]
},
"inputMethod": {
"enum": [
"UNKNOWN",
"SCANNED"
],
"type": "string",
"description": "Whether input was scanned (e.g. a scanned barcode)",
"format": "enum",
"examples": [
"SCANNED"
]
}
},
"description": "Captured driver input for a task. The value may be text for `TEXT_INPUT`\n tasks or a string decimal number for `DECIMAL_INPUT` tasks."
}
],
"description": "Task input (populated for `TEXT_INPUT` and `DECIMAL_INPUT`)."
},
"requiredToMarkStopAsDelivered": {
"type": "boolean",
"description": "Whether the task is required to mark the stop as completed. In the case of\n tasks on `RouteStart`, this represents tasks required for starting the\n route. In the case of tasks on `RouteEnd`, this represents tasks required\n for completing the route.",
"examples": [
true
]
},
"requiredToMarkStopAsAttempted": {
"type": "boolean",
"description": "Whether the task is required to mark the stop as attempted.",
"examples": [
true
]
}
},
"description": "A task to be completed at a stop, or at the start or end of a route. Tasks\n may have one or more items for `CHECKBOXES` or `RADIO_BUTTONS`, or may have\n an input for `TEXT_INPUT` or `DECIMAL_INPUT`."
},
"description": "Driver tasks for the stop, including completed items and any input from the\n driver."
},
"priority": {
"maximum": 10,
"type": "integer",
"description": "Priority of the stop for route planning. The valid range for stop priority\n is between `1` (low) and `10` (high), with default priority corresponding\n to a value of `5`. A priority value of `0` is considered unset and is\n treated the same as \"default\" priority. Stops with higher priority will be\n preferred when generating routes with constraints.",
"format": "int32",
"examples": [
8
]
},
"importedStopId": {
"type": "string",
"description": "The imported stop ID, populated when the stop source is `IMPORTED_STOP`.",
"examples": [
"ist-123e4567-e89b-12d3-a456-426614174000"
]
},
"orderName": {
"type": "string",
"description": "The name of the order associated with the stop. For Shopify orders, the\n name is generated by combining the `orderNumber` property with the order\n prefix and suffix that are set in the merchant's general settings. For\n EasyRoutes imported orders, this field is populated with the order name\n provided on import.",
"examples": [
"#1234"
]
},
"distanceMeters": {
"type": "number",
"description": "The distance in meters from the previous stop.",
"format": "double",
"examples": [
123.45
]
},
"updatedArrival": {
"type": "string",
"description": "Estimated arrival time at the stop. If the stop is completed, this will be\n the actual arrival time.",
"format": "date-time",
"examples": [
"2026-03-30T13:05:00Z"
]
},
"timeWindows": {
"type": "array",
"items": {
"title": "TimeWindow",
"type": "object",
"properties": {
"start": {
"allOf": [
{
"title": "TimeOfDay",
"type": "object",
"properties": {
"hours": {
"maximum": 23,
"type": "integer",
"description": "Hours of day in 24 hour format. Must be from 0 to 23.",
"format": "int32",
"examples": [
13
]
},
"minutes": {
"maximum": 59,
"type": "integer",
"description": "Minutes of hour of day. Must be from 0 to 59.",
"format": "int32",
"examples": [
37
]
},
"seconds": {
"maximum": 59,
"type": "integer",
"description": "Seconds of minutes of the time. Must be from 0 to 59.",
"format": "int32",
"examples": [
16
]
}
},
"description": "A time of day, independent of a particular date or timezone."
}
],
"description": "The start time of the time window (optional)."
},
"end": {
"allOf": [
{
"title": "TimeOfDay",
"type": "object",
"properties": {
"hours": {
"maximum": 23,
"type": "integer",
"description": "Hours of day in 24 hour format. Must be from 0 to 23.",
"format": "int32",
"examples": [
13
]
},
"minutes": {
"maximum": 59,
"type": "integer",
"description": "Minutes of hour of day. Must be from 0 to 59.",
"format": "int32",
"examples": [
37
]
},
"seconds": {
"maximum": 59,
"type": "integer",
"description": "Seconds of minutes of the time. Must be from 0 to 59.",
"format": "int32",
"examples": [
16
]
}
},
"description": "A time of day, independent of a particular date or timezone."
}
],
"description": "The end time of the time window (optional)."
}
},
"description": "A time window for a stop. The time window may be open-ended, but one or both\n of the start and end times should be provided. The end time must be >= the\n start time."
},
"description": "The time window for the stop. Note that we currently support at most one\n time window but may support multiple time windows in the future.",
"examples": [
[
{
"start": {
"hours": 9
},
"end": {
"hours": 17
}
}
]
]
},
"deliveryDate": {
"allOf": [
{
"title": "Date",
"required": [
"year",
"month",
"day"
],
"type": "object",
"properties": {
"year": {
"maximum": 9999,
"minimum": 1,
"type": "integer",
"description": "Year of the date. Must be from 1 to 9999.",
"format": "int32",
"examples": [
2019
]
},
"month": {
"maximum": 12,
"minimum": 1,
"type": "integer",
"description": "Month of a year. Must be from 1 to 12.",
"format": "int32",
"examples": [
11
]
},
"day": {
"maximum": 31,
"minimum": 1,
"type": "integer",
"description": "Day of a month. Must be from 1 to 31.",
"format": "int32",
"examples": [
15
]
}
},
"description": "A date in year-month-day format."
}
],
"description": "The planned delivery date for the stop.",
"examples": [
{
"year": 2025,
"month": 12,
"day": 16
}
]
},
"attributes": {
"type": "array",
"items": {
"title": "Attribute",
"type": "object",
"properties": {
"key": {
"type": "string",
"description": "Attribute key. Must be non-empty.",
"examples": [
"delivery_date"
]
},
"value": {
"type": "string",
"description": "Attribute value.",
"examples": [
"2025-12-16"
]
}
},
"description": "A key-value pair for storing additional information on a stop, such as order\n details, delivery instructions, or custom fields."
},
"description": "Additional attributes for the stop. Attributes are key-value pairs for\n storing additional structured data on stops. These may be populated from\n the Shopify order or set on import.",
"examples": [
[
{
"key": "color",
"value": "blue"
}
]
]
},
"clientStopId": {
"type": "string",
"description": "The client-provided ID associated with the stop, if provided on import.",
"examples": [
"test-order-1234"
]
},
"tags": {
"type": "array",
"items": {
"type": "string"
},
"description": "The tags for the stop. Tags are used to categorize stops and can be used\n for filtering and grouping stops in the EasyRoutes web app. These may be\n populated from the Shopify order or set on import.",
"examples": [
[
"foo",
"bar"
]
]
},
"attemptedReason": {
"enum": [
"UNKNOWN",
"NOT_AVAILABLE",
"ACCESS_DENIED",
"INCORRECT_ADDRESS",
"SAFE_PLACE_UNAVAILABLE",
"REFUSED",
"EXTERNAL",
"INCORRECT_ITEMS",
"OTHER",
"CANCELED"
],
"type": "string",
"description": "The reason for marking the stop as attempted. This is only populated when\n `deliveryStatus = ATTEMPTED_DELIVERY`.",
"format": "enum",
"examples": [
"NOT_AVAILABLE"
]
},
"attemptedNote": {
"type": "string",
"description": "Optional note related to the reason for marking the stop as attempted. This\n is optionally populated when `deliveryStatus = ATTEMPTED_DELIVERY`.",
"examples": [
"Customer did not answer the door."
]
},
"customerRating": {
"allOf": [
{
"title": "CustomerRating",
"type": "object",
"properties": {
"rating": {
"maximum": 5,
"minimum": 1,
"type": "integer",
"description": "Rating from 1-5",
"format": "int32",
"examples": [
5
]
},
"comment": {
"type": "string",
"description": "Customer comment related to rating",
"examples": [
"Excellent delivery"
]
},
"createdAt": {
"type": "string",
"description": "Timestamp when rating was left by customer.",
"format": "date-time",
"examples": [
"2026-03-30T18:00:00Z"
]
}
},
"description": "Customer rating and feedback left on a stop."
}
],
"description": "Rating left by customer. This can only be populated once `deliveryStatus =\n DELIVERED`."
},
"customSignatureDisclosure": {
"type": "string",
"description": "Optional custom signature disclosure that is shown to customers in the\n driver app.",
"examples": [
"I acknowledge that I have received this delivery."
]
},
"shopifyOrder": {
"allOf": [
{
"title": "ShopifyOrder",
"type": "object",
"properties": {
"orderNote": {
"type": "string",
"description": "The Shopify order note.",
"examples": [
"Customer has paid."
]
},
"customerNote": {
"type": "string",
"description": "The Shopify customer note for the order.",
"examples": [
"Leave at door."
]
}
},
"description": "Shopify-specific information for a RouteStop."
}
],
"description": "Information from the associated Shopify order, if applicable. Populated if\n stop source is `SHOPIFY_ORDER`"
},
"proofOfDeliveryBarcodes": {
"type": "array",
"items": {
"title": "ScannedBarcode",
"type": "object",
"properties": {
"value": {
"type": "string",
"description": "Barcode value (e.g. `\"123456789012\"`).",
"examples": [
"123456789012"
]
},
"createdAt": {
"type": "string",
"description": "Timestamp when the barcode was scanned.",
"format": "date-time",
"examples": [
"2026-03-30T13:10:00Z"
]
}
},
"description": "A proof of delivery barcode scanned at a stop."
},
"description": "Proof of delivery barcodes scanned at the stop."
},
"proofOfDeliveryBarcodeIssues": {
"type": "array",
"items": {
"title": "ScannedBarcodeIssue",
"type": "object",
"properties": {
"reason": {
"enum": [
"UNKNOWN",
"ITEM_MISSING",
"NOT_SCANNABLE",
"INCORRECT"
],
"type": "string",
"description": "The reported reason for the barcode issue.",
"format": "enum",
"examples": [
"ITEM_MISSING"
]
},
"note": {
"type": "string",
"description": "Optional note related to the reason for reporting a barcode issue.",
"examples": [
"Item was not packed."
]
},
"createdAt": {
"type": "string",
"description": "Timestamp when the issue was reported.",
"format": "date-time",
"examples": [
"2026-03-30T13:10:00Z"
]
}
},
"description": "A reported issue related to scanning barcodes at a stop."
},
"description": "Proof of delivery barcode issues reported at the stop."
},
"orderReferenceUrl": {
"type": "string",
"description": "A reference URL for the order associated with the stop (e.g. a link to the\n order in your order management system). Must be a valid HTTPS URL. This\n field can only be populated for imported stops.",
"examples": [
"https://orders.example.com/orders/148977776"
]
}
},
"description": "A stop on a route. A stop may correspond to a delivery or a driver break as\n determined by the type. A delivery stop will have location and contact\n information, items to deliver, optional order details, status, arrival time\n and stop duration, driver tasks and any proof of delivery information. A\n break stop will have start time and duration, and status."
},
"description": "Route stops. See RouteStop for stop fields."
},
"createdAt": {
"type": "string",
"description": "Timestamp when the route was created.",
"format": "date-time",
"examples": [
"2026-03-29T08:00:00Z"
]
},
"updatedAt": {
"type": "string",
"description": "Timestamp when the route was last updated (by the planner).",
"format": "date-time",
"examples": [
"2026-03-30T13:15:00Z"
]
},
"archivedAt": {
"type": "string",
"description": "Timestamp when the route was archived.",
"format": "date-time",
"examples": [
"2026-04-05T00:00:00Z"
]
},
"scheduledFor": {
"type": "string",
"description": "Timestamp when the route is scheduled for.",
"format": "date-time",
"examples": [
"2026-03-30T09:00:00Z"
]
},
"totalDistanceMeters": {
"type": "number",
"description": "The distance in meters for the entire route.",
"format": "double",
"examples": [
2387.2
]
},
"totalItemQuantity": {
"type": "integer",
"description": "The total quantity of items to deliver on the route.",
"format": "int32",
"examples": [
50
]
},
"totalItemGrams": {
"type": "string",
"description": "The total weight in grams for the items on the route.",
"examples": [
"6000"
]
},
"optimized": {
"type": "boolean",
"description": "Whether the route has been optimized. Adding or removing stops, reordering\n stops, or changing route options generally set this field to false until\n the route is reoptimized.",
"examples": [
true
]
},
"dispatchedUntil": {
"type": "string",
"description": "Timestamp until which the route is dispatched and accessible in the driver\n app.",
"format": "date-time",
"examples": [
"2026-03-30T20:00:00Z"
]
},
"note": {
"type": "string",
"description": "Top-level note for the route, as entered manually by route planners.",
"examples": [
"Fragile items."
]
},
"tags": {
"type": "array",
"items": {
"type": "string"
},
"description": "The tags for the route. Tags are used to categorize routes and can be\n used for filtering and grouping routes in the EasyRoutes web app.",
"examples": [
[
"foo",
"bar"
]
]
},
"defaultStopDuration": {
"pattern": "^-?(?:0|[1-9][0-9]{0,11})(?:\\.[0-9]{1,9})?s$",
"type": "string",
"description": "The default duration for stops on the route. Used to estimate arrival\n times for stops that do not have their own duration specified.\n Specified as a duration string in the format \"300s\" for 5 minutes, \"60s\"\n for 1 minute, etc.",
"examples": [
"300s"
]
},
"maxDuration": {
"pattern": "^-?(?:0|[1-9][0-9]{0,11})(?:\\.[0-9]{1,9})?s$",
"type": "string",
"description": "The maximum duration of the route. Specified as a duration string in the\n format \"3600s\" for 1 hour, \"7200s\" for 2 hours, etc.",
"examples": [
"28800s"
]
},
"maxStops": {
"type": "integer",
"description": "The maximum number of stops on the route.",
"format": "int32",
"examples": [
50
]
},
"maxItemCount": {
"type": "integer",
"description": "The maximum total item count across all stops on the route.",
"format": "int32",
"examples": [
200
]
},
"maxKilograms": {
"type": "number",
"description": "The maximum total weight in kilograms across all stops on the route.",
"format": "double",
"examples": [
500
]
},
"avoidTolls": {
"type": "boolean",
"description": "Whether to avoid toll roads during optimization.",
"examples": [
true
]
},
"avoidUTurns": {
"type": "boolean",
"description": "Whether to avoid U-turns during optimization.",
"examples": [
true
]
},
"speedFactor": {
"type": "number",
"description": "A speed factor for the route used during optimization to adjust estimated\n travel times. A value of 1.0 represents normal speed. Values less than 1.0\n indicate slower travel (e.g. 0.5 = half speed), and values greater than\n 1.0 indicate faster travel (e.g. 1.5 = 50% faster). Must be between 0.1\n and 1.9. A value of 0 (or unset) uses the default speed.",
"format": "double",
"examples": [
0.8
]
},
"vehicle": {
"allOf": [
{
"title": "Vehicle",
"required": [
"id"
],
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Vehicle ID.",
"examples": [
"veh-123e4567-e89b-12d3-a456-426614174000"
]
},
"name": {
"type": "string",
"description": "Vehicle name.",
"examples": [
"Delivery Van 1"
]
},
"make": {
"type": "string",
"description": "Vehicle make.",
"examples": [
"Ford"
]
},
"model": {
"type": "string",
"description": "Vehicle model.",
"examples": [
"Transit"
]
},
"year": {
"type": "integer",
"description": "Vehicle model year.",
"format": "int32",
"examples": [
2023
]
},
"type": {
"enum": [
"UNKNOWN",
"CAR",
"CARGO_VAN",
"PICKUP_TRUCK",
"BOX_TRUCK",
"MOTORCYCLE",
"BICYCLE",
"DRONE",
"OTHER"
],
"type": "string",
"description": "Vehicle type.",
"format": "enum",
"examples": [
"CARGO_VAN"
]
},
"vin": {
"type": "string",
"description": "Vehicle Identification Number.",
"examples": [
"1FTBW2CM5NKA12345"
]
},
"license": {
"type": "string",
"description": "Vehicle license plate.",
"examples": [
"ABC-1234"
]
},
"isArchived": {
"type": "boolean",
"description": "Whether the vehicle is archived.",
"examples": [
false
]
},
"createdTimestamp": {
"type": "string",
"description": "Timestamp when the vehicle was created.",
"format": "date-time",
"examples": [
"2026-07-30T12:00:00Z"
]
}
},
"description": "A vehicle that can be assigned to a route."
}
],
"description": "Assigned vehicle for the route."
}
},
"description": "A route of stops, optionally with an assigned driver."
}
}
}
},
"default": {
"description": "Default error response",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"code": {
"type": "integer",
"description": "The status code, which should be an enum value of [google.rpc.Code][google.rpc.Code].",
"format": "int32"
},
"message": {
"type": "string",
"description": "A developer-facing error message, which should be in English. Any user-facing error message should be localized and sent in the [google.rpc.Status.details][google.rpc.Status.details] field, or localized by the client."
},
"details": {
"type": "array",
"items": {
"type": "object",
"properties": {
"@type": {
"type": "string",
"description": "The type of the serialized message."
}
},
"additionalProperties": true,
"description": "Contains an arbitrary serialized message along with a @type that describes the type of the serialized message."
},
"description": "A list of messages that carry the error details. There is a common set of message types for APIs to use."
}
},
"description": "The `Status` type defines a logical error model that is suitable for different programming environments, including REST APIs and RPC APIs. It is used by [gRPC](https://github.com/grpc). Each `Status` message contains three pieces of data: error code, error message, and error details. You can find out more about this error model and how to work with it in the [API Design Guide](https://cloud.google.com/apis/design/errors)."
}
}
}
}
},
"security": [
{
"bearerAuth": []
}
],
"components": {
"securitySchemes": {
"bearerAuth": {
"type": "http",
"description": "Access token from `/authenticate`",
"scheme": "bearer",
"bearerFormat": "JWT"
}
}
}
}
```
# Update route stop tasks (https://docs.roundtrip.ai/docs/api-reference/stops/put-routes-routeId-stops-stopId-tasks)
PUT /routes/{routeId}/stops/{stopId}/tasks
Updates the tasks for an imported stop on a route. Allows you to set or
replace the list of driver tasks for a stop that was previously imported
via ImportStops. Only stops with an `importedStopId` can have
their tasks updated through this endpoint. Stops created from Shopify
orders, saved stops, or manually created stops cannot be updated via this
RPC. This is a full replacement: the entire list of tasks on the stop is
replaced with the task templates provided in the request body, so
existing tasks not included in the request will be removed. Task and item
IDs are always regenerated by the server, and any existing completion
state, input, or timestamps are cleared, since only the driver (via the
driver app) can mark a task or item complete or provide input. The response
will include the updated stop with the new tasks.
## OpenAPI specification
```json
{
"servers": [
{
"url": "https://easyroutes.roundtrip.ai/api/2024-07"
}
],
"tags": [
"Stops"
],
"summary": "Update route stop tasks",
"description": "Updates the tasks for an imported stop on a route. Allows you to set or\n replace the list of driver tasks for a stop that was previously imported\n via ImportStops. Only stops with an `importedStopId` can have\n their tasks updated through this endpoint. Stops created from Shopify\n orders, saved stops, or manually created stops cannot be updated via this\n RPC. This is a full replacement: the entire list of tasks on the stop is\n replaced with the task templates provided in the request body, so\n existing tasks not included in the request will be removed. Task and item\n IDs are always regenerated by the server, and any existing completion\n state, input, or timestamps are cleared, since only the driver (via the\n driver app) can mark a task or item complete or provide input. The response\n will include the updated stop with the new tasks.",
"operationId": "UpdateRouteStopTasks",
"parameters": [
{
"name": "routeId",
"in": "path",
"description": "The ID of the route to update stop tasks.",
"required": true,
"schema": {
"type": "string",
"examples": [
"rte-123e4567-e89b-12d3-a456-426614174000"
]
}
},
{
"name": "stopId",
"in": "path",
"description": "The ID of the stop to update tasks for.",
"required": true,
"schema": {
"type": "string",
"examples": [
"rst-123e4567-e89b-12d3-a456-426614174000"
]
}
},
{
"name": "Idempotency-Key",
"in": "header",
"description": "A unique key for safely retrying this operation. For more information read [our guide](https://docs.roundtrip.ai/docs/concepts/idempotency.md).",
"schema": {
"maxLength": 255,
"minLength": 1,
"type": "string"
},
"examples": {
"default": {
"value": "550e8400-e29b-41d4-a716-446655440000"
}
}
}
],
"requestBody": {
"content": {
"application/json": {
"schema": {
"type": "array",
"items": {
"title": "TaskTemplate",
"type": "object",
"properties": {
"title": {
"type": "string",
"description": "Task title (e.g. `\"Delivery checklist\"`).",
"examples": [
"Delivery checklist"
]
},
"type": {
"enum": [
"UNKNOWN",
"CHECKBOXES",
"RADIO_BUTTONS",
"TEXT_INPUT",
"DECIMAL_INPUT",
"SCANNER_INPUT"
],
"type": "string",
"description": "Task type.",
"format": "enum",
"examples": [
"CHECKBOXES"
]
},
"items": {
"type": "array",
"items": {
"title": "TaskItemTemplate",
"type": "object",
"properties": {
"title": {
"type": "string",
"description": "Item title (e.g. `\"Pick up package\"`).",
"examples": [
"Pick up package"
]
}
},
"description": "An item template for a task. For `CHECKBOXES`, each item on a task may be\n completed independently. For `RADIO_BUTTONS`, at most one item will be\n completed."
},
"description": "Task items, which are required for `CHECKBOXES` and `RADIO_BUTTONS`."
},
"requiredToMarkStopAsDelivered": {
"type": "boolean",
"description": "Whether the task is required to mark the stop as completed.",
"examples": [
true
]
},
"requiredToMarkStopAsAttempted": {
"type": "boolean",
"description": "Whether the task is required to mark the stop as attempted.",
"examples": [
true
]
}
},
"description": "A template for creating tasks at a stop. Task templates may have one or more\n items for `CHECKBOXES` or `RADIO_BUTTONS`. Imported stops may have task\n templates that are used to create tasks when the stop is added to a route."
}
}
}
},
"required": true
},
"responses": {
"200": {
"description": "OK",
"headers": {
"Idempotency-Key": {
"description": "The idempotency key associated with the response.",
"schema": {
"type": "string"
}
},
"Idempotency-Replayed": {
"description": "Whether the response was replayed from a previous request.",
"schema": {
"type": "boolean"
}
}
},
"content": {
"application/json": {
"schema": {
"title": "RouteStop",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Stop ID (e.g. `\"rst-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"rst-123e4567-e89b-12d3-a456-426614174000"
]
},
"type": {
"enum": [
"UNKNOWN",
"DELIVERY",
"BREAK",
"PICKUP",
"TASK"
],
"type": "string",
"description": "The type of stop (DELIVERY, BREAK, PICKUP, or TASK).",
"format": "enum",
"examples": [
"DELIVERY"
]
},
"deliveryStatus": {
"enum": [
"UNKNOWN",
"DELIVERED",
"OUT_FOR_DELIVERY",
"ATTEMPTED_DELIVERY",
"READY_FOR_DELIVERY"
],
"type": "string",
"description": "The status for DELIVERY, PICKUP, or TASK stops.",
"format": "enum",
"examples": [
"ATTEMPTED_DELIVERY"
]
},
"breakStatus": {
"enum": [
"UNKNOWN",
"COMPLETED"
],
"type": "string",
"description": "The status for BREAK stops.",
"format": "enum",
"examples": [
"COMPLETED"
]
},
"updatedAt": {
"type": "string",
"description": "Timestamp when the stop status was last updated. Note that this timestamp\n corresponds only to major status updates (i.e. stop marked as DELIVERED).\n Minor updates like task completion or adding proof of delivery will not\n advance this timestamp. For those events, use the timestamps on the task or\n proof of delivery attachment.",
"format": "date-time",
"examples": [
"2026-03-30T13:15:00Z"
]
},
"duration": {
"pattern": "^-?(?:0|[1-9][0-9]{0,11})(?:\\.[0-9]{1,9})?s$",
"type": "string",
"description": "Planned duration of the stop in seconds.",
"examples": [
"300s"
]
},
"plannedArrival": {
"type": "string",
"description": "Planned arrival time at the stop.",
"format": "date-time",
"examples": [
"2026-03-30T13:00:00Z"
]
},
"note": {
"type": "string",
"description": "Top-level note for the stop, as entered manually by route planners,\n inherited from a saved or imported stop, or set by order import automation\n rules.",
"examples": [
"Leave at door."
]
},
"address": {
"allOf": [
{
"title": "Address",
"type": "object",
"properties": {
"address1": {
"type": "string",
"description": "Street address line 1 (e.g. `\"123 Main St\"`).",
"examples": [
"123 Main St"
]
},
"address2": {
"type": "string",
"description": "Street address line 2 (e.g. `\"Apt 101\"`).",
"examples": [
"Apt 3B"
]
},
"city": {
"type": "string",
"description": "City name (e.g. `\"New York\"`).",
"examples": [
"New York"
]
},
"provinceCode": {
"type": "string",
"description": "Province or state as subdivision codes in\n [ISO 3166-2](https://en.wikipedia.org/wiki/ISO_3166-2) format without the\n country prefix (e.g. `\"NY\"` for New York).",
"examples": [
"NY"
]
},
"countryCode": {
"type": "string",
"description": "Country code (e.g. `\"US\"`).",
"examples": [
"US"
]
},
"zip": {
"type": "string",
"description": "Postal or ZIP code (e.g. `\"10001\"`).",
"examples": [
"10001"
]
}
},
"description": "A physical street address."
}
],
"description": "Delivery address for the stop.",
"examples": [
{
"address1": "123 Main St",
"address2": "Apt 3B",
"city": "New York",
"provinceCode": "NY",
"countryCode": "US",
"zip": "10001"
}
]
},
"contact": {
"allOf": [
{
"title": "Contact",
"type": "object",
"properties": {
"firstName": {
"type": "string",
"description": "First name (e.g. `\"John\"`).",
"examples": [
"John"
]
},
"lastName": {
"type": "string",
"description": "Last name (e.g. `\"Doe\"`).",
"examples": [
"Doe"
]
},
"company": {
"type": "string",
"description": "Company name (e.g. `\"Roundtrip Systems Inc\"`).",
"examples": [
"Roundtrip Systems Inc"
]
},
"phone": {
"type": "string",
"description": "Phone number in [E.164 format](https://en.wikipedia.org/wiki/E.164) (e.g.\n `\"+14265551000\"`).",
"examples": [
"+14265551000"
]
},
"email": {
"type": "string",
"description": "Email address (e.g. `\"john.doe@roundtrip.ai\"`)",
"examples": [
"john.doe@roundtrip.ai"
]
}
},
"description": "Contact information for a person or company."
}
],
"description": "Contact information for the stop delivery recipient.",
"examples": [
{
"firstName": "John",
"lastName": "Doe",
"company": "Roundtrip Systems Inc",
"phone": "+14265551000",
"email": "john.doe@roundtrip.ai"
}
]
},
"plannedCoordinates": {
"allOf": [
{
"type": "object",
"properties": {
"latitude": {
"type": "number",
"description": "The latitude in degrees. It must be in the range [-90.0, +90.0].",
"format": "double"
},
"longitude": {
"type": "number",
"description": "The longitude in degrees. It must be in the range [-180.0, +180.0].",
"format": "double"
}
},
"description": "An object that represents a latitude/longitude pair. This is expressed as a\n pair of doubles to represent degrees latitude and degrees longitude. Unless\n specified otherwise, this must conform to the\n WGS84\n standard. Values must be within normalized ranges."
}
],
"description": "Planned coordinates for the stop.",
"examples": [
{
"latitude": 40.7128,
"longitude": -74.006
}
]
},
"items": {
"type": "array",
"items": {
"title": "StopItem",
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "Item name (e.g. `\"Bananas\"`).",
"examples": [
"Bananas"
]
},
"quantity": {
"type": "integer",
"description": "Quantity of the item (e.g. `5`).",
"format": "int32",
"examples": [
5
]
},
"grams": {
"type": "integer",
"description": "Weight of the item in grams (e.g. `500`).",
"format": "int32",
"examples": [
500
]
},
"sku": {
"type": "string",
"description": "Stock keeping unit (e.g. `\"BANANA-001\"`).",
"examples": [
"BANANA-001"
]
}
},
"description": "An item to be delivered at a stop."
},
"description": "Items to deliver at the stop."
},
"source": {
"enum": [
"UNKNOWN",
"SHOPIFY_ORDER",
"SAVED_STOP",
"IMPORTED_STOP"
],
"type": "string",
"description": "The source of the stop, which may be populated for `DELIVERY` stops. The\n source can be a `SHOPIFY_ORDER`, an EasyRoutes `SAVED_STOP`, or an\n `IMPORTED_STOP` from an external source (such as CSV file).",
"format": "enum",
"examples": [
"IMPORTED_STOP"
]
},
"shopifyOrderId": {
"type": "string",
"description": "The Shopify order ID, populated when the stop source is a `SHOPIFY_ORDER`.",
"examples": [
"6229749334323"
]
},
"savedStopId": {
"type": "string",
"description": "The saved stop ID, populated when the stop source is a `SAVED_STOP`.",
"examples": [
"sst-123e4567-e89b-12d3-a456-426614174000"
]
},
"deliveredCoordinates": {
"allOf": [
{
"type": "object",
"properties": {
"latitude": {
"type": "number",
"description": "The latitude in degrees. It must be in the range [-90.0, +90.0].",
"format": "double"
},
"longitude": {
"type": "number",
"description": "The longitude in degrees. It must be in the range [-180.0, +180.0].",
"format": "double"
}
},
"description": "An object that represents a latitude/longitude pair. This is expressed as a\n pair of doubles to represent degrees latitude and degrees longitude. Unless\n specified otherwise, this must conform to the\n WGS84\n standard. Values must be within normalized ranges."
}
],
"description": "Delivered coordinates for the stop."
},
"proofOfDeliveryNote": {
"type": "string",
"description": "Proof of delivery note for the stop.",
"examples": [
"Left at door."
]
},
"proofOfDeliveryPhotos": {
"type": "array",
"items": {
"title": "StopAttachment",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Attachment ID (e.g. `\"att-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"att-123e4567-e89b-12d3-a456-426614174000"
]
},
"createdAt": {
"type": "string",
"description": "Timestamp when the attachment was created.",
"format": "date-time",
"examples": [
"2026-03-30T09:05:00Z"
]
},
"url": {
"type": "string",
"description": "URL to fetch the attachment.",
"examples": [
"https://example.com/stop-attachment/attachment-2025-06-03-1"
]
}
},
"description": "An attachment to a stop, such as a proof of delivery photo or signature."
},
"description": "Proof of delivery photos for the stop. Photos may be fetched using the URLs\n on the attachments."
},
"proofOfDeliverySignatures": {
"type": "array",
"items": {
"title": "StopAttachment",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Attachment ID (e.g. `\"att-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"att-123e4567-e89b-12d3-a456-426614174000"
]
},
"createdAt": {
"type": "string",
"description": "Timestamp when the attachment was created.",
"format": "date-time",
"examples": [
"2026-03-30T09:05:00Z"
]
},
"url": {
"type": "string",
"description": "URL to fetch the attachment.",
"examples": [
"https://example.com/stop-attachment/attachment-2025-06-03-1"
]
}
},
"description": "An attachment to a stop, such as a proof of delivery photo or signature."
},
"description": "Proof of delivery signatures for the stop. Signatures may be fetched using\n the URLs on the attachments."
},
"tasks": {
"type": "array",
"items": {
"title": "Task",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Task ID (e.g. `\"tsk-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"tsk-123e4567-e89b-12d3-a456-426614174000"
]
},
"title": {
"type": "string",
"description": "Task title (e.g. `\"Delivery checklist\"`).",
"examples": [
"Delivery checklist"
]
},
"type": {
"enum": [
"UNKNOWN",
"CHECKBOXES",
"RADIO_BUTTONS",
"TEXT_INPUT",
"DECIMAL_INPUT",
"SCANNER_INPUT"
],
"type": "string",
"description": "Task type.",
"format": "enum",
"examples": [
"TEXT_INPUT"
]
},
"items": {
"type": "array",
"items": {
"title": "TaskItem",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Item ID (e.g. `\"itm-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"itm-123e4567-e89b-12d3-a456-426614174000"
]
},
"title": {
"type": "string",
"description": "Item title (e.g. `\"Pick up package\"`).",
"examples": [
"Pick up package"
]
},
"complete": {
"type": "boolean",
"description": "Whether the item is completed.",
"examples": [
true
]
},
"updatedAt": {
"type": "string",
"description": "Timestamp when the item was last updated.",
"format": "date-time",
"examples": [
"2026-03-30T13:00:00Z"
]
}
},
"description": "An item within a task. For `CHECKBOXES`, each item on a task may be completed\n independently. For `RADIO_BUTTONS`, at most one item will be completed."
},
"description": "Task items (populated for `CHECKBOXES` and `RADIO_BUTTONS`).",
"examples": [
[]
]
},
"input": {
"allOf": [
{
"title": "TaskInput",
"type": "object",
"properties": {
"value": {
"type": "string",
"description": "Input value.",
"examples": [
"020123456789"
]
},
"updatedAt": {
"type": "string",
"description": "Timestamp when the input was last updated.",
"format": "date-time",
"examples": [
"2026-03-30T13:00:00Z"
]
},
"inputMethod": {
"enum": [
"UNKNOWN",
"SCANNED"
],
"type": "string",
"description": "Whether input was scanned (e.g. a scanned barcode)",
"format": "enum",
"examples": [
"SCANNED"
]
}
},
"description": "Captured driver input for a task. The value may be text for `TEXT_INPUT`\n tasks or a string decimal number for `DECIMAL_INPUT` tasks."
}
],
"description": "Task input (populated for `TEXT_INPUT` and `DECIMAL_INPUT`)."
},
"requiredToMarkStopAsDelivered": {
"type": "boolean",
"description": "Whether the task is required to mark the stop as completed. In the case of\n tasks on `RouteStart`, this represents tasks required for starting the\n route. In the case of tasks on `RouteEnd`, this represents tasks required\n for completing the route.",
"examples": [
true
]
},
"requiredToMarkStopAsAttempted": {
"type": "boolean",
"description": "Whether the task is required to mark the stop as attempted.",
"examples": [
true
]
}
},
"description": "A task to be completed at a stop, or at the start or end of a route. Tasks\n may have one or more items for `CHECKBOXES` or `RADIO_BUTTONS`, or may have\n an input for `TEXT_INPUT` or `DECIMAL_INPUT`."
},
"description": "Driver tasks for the stop, including completed items and any input from the\n driver."
},
"priority": {
"maximum": 10,
"type": "integer",
"description": "Priority of the stop for route planning. The valid range for stop priority\n is between `1` (low) and `10` (high), with default priority corresponding\n to a value of `5`. A priority value of `0` is considered unset and is\n treated the same as \"default\" priority. Stops with higher priority will be\n preferred when generating routes with constraints.",
"format": "int32",
"examples": [
8
]
},
"importedStopId": {
"type": "string",
"description": "The imported stop ID, populated when the stop source is `IMPORTED_STOP`.",
"examples": [
"ist-123e4567-e89b-12d3-a456-426614174000"
]
},
"orderName": {
"type": "string",
"description": "The name of the order associated with the stop. For Shopify orders, the\n name is generated by combining the `orderNumber` property with the order\n prefix and suffix that are set in the merchant's general settings. For\n EasyRoutes imported orders, this field is populated with the order name\n provided on import.",
"examples": [
"#1234"
]
},
"distanceMeters": {
"type": "number",
"description": "The distance in meters from the previous stop.",
"format": "double",
"examples": [
123.45
]
},
"updatedArrival": {
"type": "string",
"description": "Estimated arrival time at the stop. If the stop is completed, this will be\n the actual arrival time.",
"format": "date-time",
"examples": [
"2026-03-30T13:05:00Z"
]
},
"timeWindows": {
"type": "array",
"items": {
"title": "TimeWindow",
"type": "object",
"properties": {
"start": {
"allOf": [
{
"title": "TimeOfDay",
"type": "object",
"properties": {
"hours": {
"maximum": 23,
"type": "integer",
"description": "Hours of day in 24 hour format. Must be from 0 to 23.",
"format": "int32",
"examples": [
13
]
},
"minutes": {
"maximum": 59,
"type": "integer",
"description": "Minutes of hour of day. Must be from 0 to 59.",
"format": "int32",
"examples": [
37
]
},
"seconds": {
"maximum": 59,
"type": "integer",
"description": "Seconds of minutes of the time. Must be from 0 to 59.",
"format": "int32",
"examples": [
16
]
}
},
"description": "A time of day, independent of a particular date or timezone."
}
],
"description": "The start time of the time window (optional)."
},
"end": {
"allOf": [
{
"title": "TimeOfDay",
"type": "object",
"properties": {
"hours": {
"maximum": 23,
"type": "integer",
"description": "Hours of day in 24 hour format. Must be from 0 to 23.",
"format": "int32",
"examples": [
13
]
},
"minutes": {
"maximum": 59,
"type": "integer",
"description": "Minutes of hour of day. Must be from 0 to 59.",
"format": "int32",
"examples": [
37
]
},
"seconds": {
"maximum": 59,
"type": "integer",
"description": "Seconds of minutes of the time. Must be from 0 to 59.",
"format": "int32",
"examples": [
16
]
}
},
"description": "A time of day, independent of a particular date or timezone."
}
],
"description": "The end time of the time window (optional)."
}
},
"description": "A time window for a stop. The time window may be open-ended, but one or both\n of the start and end times should be provided. The end time must be >= the\n start time."
},
"description": "The time window for the stop. Note that we currently support at most one\n time window but may support multiple time windows in the future.",
"examples": [
[
{
"start": {
"hours": 9
},
"end": {
"hours": 17
}
}
]
]
},
"deliveryDate": {
"allOf": [
{
"title": "Date",
"required": [
"year",
"month",
"day"
],
"type": "object",
"properties": {
"year": {
"maximum": 9999,
"minimum": 1,
"type": "integer",
"description": "Year of the date. Must be from 1 to 9999.",
"format": "int32",
"examples": [
2019
]
},
"month": {
"maximum": 12,
"minimum": 1,
"type": "integer",
"description": "Month of a year. Must be from 1 to 12.",
"format": "int32",
"examples": [
11
]
},
"day": {
"maximum": 31,
"minimum": 1,
"type": "integer",
"description": "Day of a month. Must be from 1 to 31.",
"format": "int32",
"examples": [
15
]
}
},
"description": "A date in year-month-day format."
}
],
"description": "The planned delivery date for the stop.",
"examples": [
{
"year": 2025,
"month": 12,
"day": 16
}
]
},
"attributes": {
"type": "array",
"items": {
"title": "Attribute",
"type": "object",
"properties": {
"key": {
"type": "string",
"description": "Attribute key. Must be non-empty.",
"examples": [
"delivery_date"
]
},
"value": {
"type": "string",
"description": "Attribute value.",
"examples": [
"2025-12-16"
]
}
},
"description": "A key-value pair for storing additional information on a stop, such as order\n details, delivery instructions, or custom fields."
},
"description": "Additional attributes for the stop. Attributes are key-value pairs for\n storing additional structured data on stops. These may be populated from\n the Shopify order or set on import.",
"examples": [
[
{
"key": "color",
"value": "blue"
}
]
]
},
"clientStopId": {
"type": "string",
"description": "The client-provided ID associated with the stop, if provided on import.",
"examples": [
"test-order-1234"
]
},
"tags": {
"type": "array",
"items": {
"type": "string"
},
"description": "The tags for the stop. Tags are used to categorize stops and can be used\n for filtering and grouping stops in the EasyRoutes web app. These may be\n populated from the Shopify order or set on import.",
"examples": [
[
"foo",
"bar"
]
]
},
"attemptedReason": {
"enum": [
"UNKNOWN",
"NOT_AVAILABLE",
"ACCESS_DENIED",
"INCORRECT_ADDRESS",
"SAFE_PLACE_UNAVAILABLE",
"REFUSED",
"EXTERNAL",
"INCORRECT_ITEMS",
"OTHER",
"CANCELED"
],
"type": "string",
"description": "The reason for marking the stop as attempted. This is only populated when\n `deliveryStatus = ATTEMPTED_DELIVERY`.",
"format": "enum",
"examples": [
"NOT_AVAILABLE"
]
},
"attemptedNote": {
"type": "string",
"description": "Optional note related to the reason for marking the stop as attempted. This\n is optionally populated when `deliveryStatus = ATTEMPTED_DELIVERY`.",
"examples": [
"Customer did not answer the door."
]
},
"customerRating": {
"allOf": [
{
"title": "CustomerRating",
"type": "object",
"properties": {
"rating": {
"maximum": 5,
"minimum": 1,
"type": "integer",
"description": "Rating from 1-5",
"format": "int32",
"examples": [
5
]
},
"comment": {
"type": "string",
"description": "Customer comment related to rating",
"examples": [
"Excellent delivery"
]
},
"createdAt": {
"type": "string",
"description": "Timestamp when rating was left by customer.",
"format": "date-time",
"examples": [
"2026-03-30T18:00:00Z"
]
}
},
"description": "Customer rating and feedback left on a stop."
}
],
"description": "Rating left by customer. This can only be populated once `deliveryStatus =\n DELIVERED`."
},
"customSignatureDisclosure": {
"type": "string",
"description": "Optional custom signature disclosure that is shown to customers in the\n driver app.",
"examples": [
"I acknowledge that I have received this delivery."
]
},
"shopifyOrder": {
"allOf": [
{
"title": "ShopifyOrder",
"type": "object",
"properties": {
"orderNote": {
"type": "string",
"description": "The Shopify order note.",
"examples": [
"Customer has paid."
]
},
"customerNote": {
"type": "string",
"description": "The Shopify customer note for the order.",
"examples": [
"Leave at door."
]
}
},
"description": "Shopify-specific information for a RouteStop."
}
],
"description": "Information from the associated Shopify order, if applicable. Populated if\n stop source is `SHOPIFY_ORDER`"
},
"proofOfDeliveryBarcodes": {
"type": "array",
"items": {
"title": "ScannedBarcode",
"type": "object",
"properties": {
"value": {
"type": "string",
"description": "Barcode value (e.g. `\"123456789012\"`).",
"examples": [
"123456789012"
]
},
"createdAt": {
"type": "string",
"description": "Timestamp when the barcode was scanned.",
"format": "date-time",
"examples": [
"2026-03-30T13:10:00Z"
]
}
},
"description": "A proof of delivery barcode scanned at a stop."
},
"description": "Proof of delivery barcodes scanned at the stop."
},
"proofOfDeliveryBarcodeIssues": {
"type": "array",
"items": {
"title": "ScannedBarcodeIssue",
"type": "object",
"properties": {
"reason": {
"enum": [
"UNKNOWN",
"ITEM_MISSING",
"NOT_SCANNABLE",
"INCORRECT"
],
"type": "string",
"description": "The reported reason for the barcode issue.",
"format": "enum",
"examples": [
"ITEM_MISSING"
]
},
"note": {
"type": "string",
"description": "Optional note related to the reason for reporting a barcode issue.",
"examples": [
"Item was not packed."
]
},
"createdAt": {
"type": "string",
"description": "Timestamp when the issue was reported.",
"format": "date-time",
"examples": [
"2026-03-30T13:10:00Z"
]
}
},
"description": "A reported issue related to scanning barcodes at a stop."
},
"description": "Proof of delivery barcode issues reported at the stop."
},
"orderReferenceUrl": {
"type": "string",
"description": "A reference URL for the order associated with the stop (e.g. a link to the\n order in your order management system). Must be a valid HTTPS URL. This\n field can only be populated for imported stops.",
"examples": [
"https://orders.example.com/orders/148977776"
]
}
},
"description": "A stop on a route. A stop may correspond to a delivery or a driver break as\n determined by the type. A delivery stop will have location and contact\n information, items to deliver, optional order details, status, arrival time\n and stop duration, driver tasks and any proof of delivery information. A\n break stop will have start time and duration, and status."
}
}
}
},
"default": {
"description": "Default error response",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"code": {
"type": "integer",
"description": "The status code, which should be an enum value of [google.rpc.Code][google.rpc.Code].",
"format": "int32"
},
"message": {
"type": "string",
"description": "A developer-facing error message, which should be in English. Any user-facing error message should be localized and sent in the [google.rpc.Status.details][google.rpc.Status.details] field, or localized by the client."
},
"details": {
"type": "array",
"items": {
"type": "object",
"properties": {
"@type": {
"type": "string",
"description": "The type of the serialized message."
}
},
"additionalProperties": true,
"description": "Contains an arbitrary serialized message along with a @type that describes the type of the serialized message."
},
"description": "A list of messages that carry the error details. There is a common set of message types for APIs to use."
}
},
"description": "The `Status` type defines a logical error model that is suitable for different programming environments, including REST APIs and RPC APIs. It is used by [gRPC](https://github.com/grpc). Each `Status` message contains three pieces of data: error code, error message, and error details. You can find out more about this error model and how to work with it in the [API Design Guide](https://cloud.google.com/apis/design/errors)."
}
}
}
}
},
"security": [
{
"bearerAuth": []
}
],
"components": {
"securitySchemes": {
"bearerAuth": {
"type": "http",
"description": "Access token from `/authenticate`",
"scheme": "bearer",
"bearerFormat": "JWT"
}
}
}
}
```
# Update imported stop items (https://docs.roundtrip.ai/docs/api-reference/stops/put-stops-imports-id-items)
PUT /stops/imports/{id}/items
Updates the items on an existing imported stop by ID, without needing to
re-send the full stop payload via ImportStops. This is a full replacement:
the entire list of items on the stop is replaced with the items provided
in the request body. The ID can be the EasyRoutes `id` returned on import
or the client-provided `clientStopId`. Items are validated to ensure they
meet the following constraints: maximum 499 items per stop, item names up
to 1500 characters, quantities up to 100,000, and weight up to
1,000,000,000 grams. Note that this only updates the imported stop
record; if the stop has already been added to a route, use
UpdateRouteStopItems to update its items on that route.
## OpenAPI specification
```json
{
"servers": [
{
"url": "https://easyroutes.roundtrip.ai/api/2024-07"
}
],
"tags": [
"Stops"
],
"summary": "Update imported stop items",
"description": "Updates the items on an existing imported stop by ID, without needing to\n re-send the full stop payload via ImportStops. This is a full replacement:\n the entire list of items on the stop is replaced with the items provided\n in the request body. The ID can be the EasyRoutes `id` returned on import\n or the client-provided `clientStopId`. Items are validated to ensure they\n meet the following constraints: maximum 499 items per stop, item names up\n to 1500 characters, quantities up to 100,000, and weight up to\n 1,000,000,000 grams. Note that this only updates the imported stop\n record; if the stop has already been added to a route, use\n UpdateRouteStopItems to update its items on that route.",
"operationId": "UpdateImportedStopItems",
"parameters": [
{
"name": "id",
"in": "path",
"description": "The ID of the imported stop to update items for. You provide the\n EasyRoutes `id` returned on import or the client-provided `clientStopId`.",
"required": true,
"schema": {
"type": "string",
"examples": [
"ist-123e4567-e89b-12d3-a456-426614174000"
]
}
},
{
"name": "Idempotency-Key",
"in": "header",
"description": "A unique key for safely retrying this operation. For more information read [our guide](https://docs.roundtrip.ai/docs/concepts/idempotency.md).",
"schema": {
"maxLength": 255,
"minLength": 1,
"type": "string"
},
"examples": {
"default": {
"value": "550e8400-e29b-41d4-a716-446655440000"
}
}
}
],
"requestBody": {
"content": {
"application/json": {
"schema": {
"type": "array",
"items": {
"title": "StopItem",
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "Item name (e.g. `\"Bananas\"`).",
"examples": [
"Bananas"
]
},
"quantity": {
"type": "integer",
"description": "Quantity of the item (e.g. `5`).",
"format": "int32",
"examples": [
5
]
},
"grams": {
"type": "integer",
"description": "Weight of the item in grams (e.g. `500`).",
"format": "int32",
"examples": [
500
]
},
"sku": {
"type": "string",
"description": "Stock keeping unit (e.g. `\"BANANA-001\"`).",
"examples": [
"BANANA-001"
]
}
},
"description": "An item to be delivered at a stop."
}
}
}
},
"required": true
},
"responses": {
"200": {
"description": "OK",
"headers": {
"Idempotency-Key": {
"description": "The idempotency key associated with the response.",
"schema": {
"type": "string"
}
},
"Idempotency-Replayed": {
"description": "Whether the response was replayed from a previous request.",
"schema": {
"type": "boolean"
}
}
},
"content": {
"application/json": {
"schema": {
"title": "ImportedStop",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "The ID of the imported stop, generated by EasyRoutes (e.g.\n `\"ist-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"ist-123e4567-e89b-12d3-a456-426614174000"
]
},
"clientStopId": {
"type": "string",
"description": "The client-provided ID associated with the imported stop, if provided.",
"examples": [
"test-order-1234"
]
},
"address": {
"allOf": [
{
"title": "Address",
"type": "object",
"properties": {
"address1": {
"type": "string",
"description": "Street address line 1 (e.g. `\"123 Main St\"`).",
"examples": [
"123 Main St"
]
},
"address2": {
"type": "string",
"description": "Street address line 2 (e.g. `\"Apt 101\"`).",
"examples": [
"Apt 3B"
]
},
"city": {
"type": "string",
"description": "City name (e.g. `\"New York\"`).",
"examples": [
"New York"
]
},
"provinceCode": {
"type": "string",
"description": "Province or state as subdivision codes in\n [ISO 3166-2](https://en.wikipedia.org/wiki/ISO_3166-2) format without the\n country prefix (e.g. `\"NY\"` for New York).",
"examples": [
"NY"
]
},
"countryCode": {
"type": "string",
"description": "Country code (e.g. `\"US\"`).",
"examples": [
"US"
]
},
"zip": {
"type": "string",
"description": "Postal or ZIP code (e.g. `\"10001\"`).",
"examples": [
"10001"
]
}
},
"description": "A physical street address."
}
],
"description": "The address for the stop.",
"examples": [
{
"address1": "123 Main St",
"address2": "Apt 3B",
"city": "New York",
"provinceCode": "NY",
"countryCode": "US",
"zip": "10001"
}
]
},
"contact": {
"allOf": [
{
"title": "Contact",
"type": "object",
"properties": {
"firstName": {
"type": "string",
"description": "First name (e.g. `\"John\"`).",
"examples": [
"John"
]
},
"lastName": {
"type": "string",
"description": "Last name (e.g. `\"Doe\"`).",
"examples": [
"Doe"
]
},
"company": {
"type": "string",
"description": "Company name (e.g. `\"Roundtrip Systems Inc\"`).",
"examples": [
"Roundtrip Systems Inc"
]
},
"phone": {
"type": "string",
"description": "Phone number in [E.164 format](https://en.wikipedia.org/wiki/E.164) (e.g.\n `\"+14265551000\"`).",
"examples": [
"+14265551000"
]
},
"email": {
"type": "string",
"description": "Email address (e.g. `\"john.doe@roundtrip.ai\"`)",
"examples": [
"john.doe@roundtrip.ai"
]
}
},
"description": "Contact information for a person or company."
}
],
"description": "The contact information for the stop.",
"examples": [
{
"firstName": "John",
"lastName": "Doe",
"company": "Roundtrip Systems Inc",
"phone": "+14265551000",
"email": "john.doe@roundtrip.ai"
}
]
},
"coordinates": {
"allOf": [
{
"type": "object",
"properties": {
"latitude": {
"type": "number",
"description": "The latitude in degrees. It must be in the range [-90.0, +90.0].",
"format": "double"
},
"longitude": {
"type": "number",
"description": "The longitude in degrees. It must be in the range [-180.0, +180.0].",
"format": "double"
}
},
"description": "An object that represents a latitude/longitude pair. This is expressed as a\n pair of doubles to represent degrees latitude and degrees longitude. Unless\n specified otherwise, this must conform to the\n WGS84\n standard. Values must be within normalized ranges."
}
],
"description": "The coordinates to use for the stop, if provided on import.",
"examples": [
{
"latitude": 40.7128,
"longitude": -74.006
}
]
},
"items": {
"type": "array",
"items": {
"title": "StopItem",
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "Item name (e.g. `\"Bananas\"`).",
"examples": [
"Bananas"
]
},
"quantity": {
"type": "integer",
"description": "Quantity of the item (e.g. `5`).",
"format": "int32",
"examples": [
5
]
},
"grams": {
"type": "integer",
"description": "Weight of the item in grams (e.g. `500`).",
"format": "int32",
"examples": [
500
]
},
"sku": {
"type": "string",
"description": "Stock keeping unit (e.g. `\"BANANA-001\"`).",
"examples": [
"BANANA-001"
]
}
},
"description": "An item to be delivered at a stop."
},
"description": "The items to deliver at the stop."
},
"note": {
"type": "string",
"description": "A note for the stop.",
"examples": [
"Leave at door."
]
},
"duration": {
"pattern": "^-?(?:0|[1-9][0-9]{0,11})(?:\\.[0-9]{1,9})?s$",
"type": "string",
"description": "The planned duration for the driver to spend at this stop. This duration is\n used in route optimization to estimate arrival times. If specified, it\n takes precedence over the route's default stop duration. Specified as a\n duration string in the format \"300s\" for 5 minutes, \"60s\" for 1 minute,\n etc.",
"examples": [
"300s"
]
},
"priority": {
"maximum": 10,
"type": "integer",
"description": "Priority of the stop for route planning.",
"format": "int32",
"examples": [
5
]
},
"orderName": {
"type": "string",
"description": "The name of the order associated with the stop.",
"examples": [
"#1234"
]
},
"importedAt": {
"type": "string",
"description": "The timestamp at which the stop was imported.",
"format": "date-time",
"examples": [
"2026-03-28T10:00:00Z"
]
},
"timeWindows": {
"type": "array",
"items": {
"title": "TimeWindow",
"type": "object",
"properties": {
"start": {
"allOf": [
{
"title": "TimeOfDay",
"type": "object",
"properties": {
"hours": {
"maximum": 23,
"type": "integer",
"description": "Hours of day in 24 hour format. Must be from 0 to 23.",
"format": "int32",
"examples": [
13
]
},
"minutes": {
"maximum": 59,
"type": "integer",
"description": "Minutes of hour of day. Must be from 0 to 59.",
"format": "int32",
"examples": [
37
]
},
"seconds": {
"maximum": 59,
"type": "integer",
"description": "Seconds of minutes of the time. Must be from 0 to 59.",
"format": "int32",
"examples": [
16
]
}
},
"description": "A time of day, independent of a particular date or timezone."
}
],
"description": "The start time of the time window (optional)."
},
"end": {
"allOf": [
{
"title": "TimeOfDay",
"type": "object",
"properties": {
"hours": {
"maximum": 23,
"type": "integer",
"description": "Hours of day in 24 hour format. Must be from 0 to 23.",
"format": "int32",
"examples": [
13
]
},
"minutes": {
"maximum": 59,
"type": "integer",
"description": "Minutes of hour of day. Must be from 0 to 59.",
"format": "int32",
"examples": [
37
]
},
"seconds": {
"maximum": 59,
"type": "integer",
"description": "Seconds of minutes of the time. Must be from 0 to 59.",
"format": "int32",
"examples": [
16
]
}
},
"description": "A time of day, independent of a particular date or timezone."
}
],
"description": "The end time of the time window (optional)."
}
},
"description": "A time window for a stop. The time window may be open-ended, but one or both\n of the start and end times should be provided. The end time must be >= the\n start time."
},
"description": "The time window for the stop. Note that we currently support at most one\n time window but may support multiple time windows in the future.",
"examples": [
[
{
"start": {
"hours": 9
},
"end": {
"hours": 17
}
}
]
]
},
"deliveryDate": {
"allOf": [
{
"title": "Date",
"required": [
"year",
"month",
"day"
],
"type": "object",
"properties": {
"year": {
"maximum": 9999,
"minimum": 1,
"type": "integer",
"description": "Year of the date. Must be from 1 to 9999.",
"format": "int32",
"examples": [
2019
]
},
"month": {
"maximum": 12,
"minimum": 1,
"type": "integer",
"description": "Month of a year. Must be from 1 to 12.",
"format": "int32",
"examples": [
11
]
},
"day": {
"maximum": 31,
"minimum": 1,
"type": "integer",
"description": "Day of a month. Must be from 1 to 31.",
"format": "int32",
"examples": [
15
]
}
},
"description": "A date in year-month-day format."
}
],
"description": "The delivery date for the stop.",
"examples": [
{
"year": 2025,
"month": 12,
"day": 16
}
]
},
"attributes": {
"type": "array",
"items": {
"title": "Attribute",
"type": "object",
"properties": {
"key": {
"type": "string",
"description": "Attribute key. Must be non-empty.",
"examples": [
"delivery_date"
]
},
"value": {
"type": "string",
"description": "Attribute value.",
"examples": [
"2025-12-16"
]
}
},
"description": "A key-value pair for storing additional information on a stop, such as order\n details, delivery instructions, or custom fields."
},
"description": "The additional key-value attributes set on the imported stop.",
"examples": [
[
{
"key": "color",
"value": "blue"
}
]
]
},
"tags": {
"type": "array",
"items": {
"type": "string"
},
"description": "The tags for the stop.",
"examples": [
[
"foo",
"bar"
]
]
},
"tasks": {
"type": "array",
"items": {
"title": "TaskTemplate",
"type": "object",
"properties": {
"title": {
"type": "string",
"description": "Task title (e.g. `\"Delivery checklist\"`).",
"examples": [
"Delivery checklist"
]
},
"type": {
"enum": [
"UNKNOWN",
"CHECKBOXES",
"RADIO_BUTTONS",
"TEXT_INPUT",
"DECIMAL_INPUT",
"SCANNER_INPUT"
],
"type": "string",
"description": "Task type.",
"format": "enum",
"examples": [
"CHECKBOXES"
]
},
"items": {
"type": "array",
"items": {
"title": "TaskItemTemplate",
"type": "object",
"properties": {
"title": {
"type": "string",
"description": "Item title (e.g. `\"Pick up package\"`).",
"examples": [
"Pick up package"
]
}
},
"description": "An item template for a task. For `CHECKBOXES`, each item on a task may be\n completed independently. For `RADIO_BUTTONS`, at most one item will be\n completed."
},
"description": "Task items, which are required for `CHECKBOXES` and `RADIO_BUTTONS`."
},
"requiredToMarkStopAsDelivered": {
"type": "boolean",
"description": "Whether the task is required to mark the stop as completed.",
"examples": [
true
]
},
"requiredToMarkStopAsAttempted": {
"type": "boolean",
"description": "Whether the task is required to mark the stop as attempted.",
"examples": [
true
]
}
},
"description": "A template for creating tasks at a stop. Task templates may have one or more\n items for `CHECKBOXES` or `RADIO_BUTTONS`. Imported stops may have task\n templates that are used to create tasks when the stop is added to a route."
},
"description": "The tasks for the stop."
},
"type": {
"enum": [
"UNKNOWN",
"DELIVERY",
"BREAK",
"PICKUP",
"TASK"
],
"type": "string",
"description": "The type of stop (DELIVERY, PICKUP, or TASK). Defaults to DELIVERY if not\n provided.",
"format": "enum",
"examples": [
"DELIVERY"
]
},
"customSignatureDisclosure": {
"type": "string",
"description": "Custom signature disclosure for the stop. Only populated if stop type is\n DELIVERY, PICKUP, or TASK.",
"examples": [
"I acknowledge that I have received this delivery."
]
},
"orderReferenceUrl": {
"type": "string",
"description": "A reference URL for the order associated with the stop (e.g. a link to the\n order in your order management system). Must be a valid HTTPS URL.",
"examples": [
"https://orders.example.com/orders/148977776"
]
}
},
"description": "A stop imported into EasyRoutes."
}
}
}
},
"default": {
"description": "Default error response",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"code": {
"type": "integer",
"description": "The status code, which should be an enum value of [google.rpc.Code][google.rpc.Code].",
"format": "int32"
},
"message": {
"type": "string",
"description": "A developer-facing error message, which should be in English. Any user-facing error message should be localized and sent in the [google.rpc.Status.details][google.rpc.Status.details] field, or localized by the client."
},
"details": {
"type": "array",
"items": {
"type": "object",
"properties": {
"@type": {
"type": "string",
"description": "The type of the serialized message."
}
},
"additionalProperties": true,
"description": "Contains an arbitrary serialized message along with a @type that describes the type of the serialized message."
},
"description": "A list of messages that carry the error details. There is a common set of message types for APIs to use."
}
},
"description": "The `Status` type defines a logical error model that is suitable for different programming environments, including REST APIs and RPC APIs. It is used by [gRPC](https://github.com/grpc). Each `Status` message contains three pieces of data: error code, error message, and error details. You can find out more about this error model and how to work with it in the [API Design Guide](https://cloud.google.com/apis/design/errors)."
}
}
}
}
},
"security": [
{
"bearerAuth": []
}
],
"components": {
"securitySchemes": {
"bearerAuth": {
"type": "http",
"description": "Access token from `/authenticate`",
"scheme": "bearer",
"bearerFormat": "JWT"
}
}
}
}
```
# Update imported stop tasks (https://docs.roundtrip.ai/docs/api-reference/stops/put-stops-imports-id-tasks)
PUT /stops/imports/{id}/tasks
Updates the tasks on an existing imported stop by ID, without needing to
re-send the full stop payload via ImportStops. This is a full
replacement: the entire list of tasks on the stop is replaced with the
task templates provided in the request body. Task and item IDs are
always regenerated by the server, and any existing completion state,
input, or timestamps are cleared, since only the driver (via the driver
app) can mark a task or item complete or provide input. The ID can be
the EasyRoutes `id` returned on import or the client-provided
`clientStopId`. Note that this only updates the imported stop record;
if the stop has already been added to a route, use UpdateRouteStopTasks
to update its tasks on that route.
## OpenAPI specification
```json
{
"servers": [
{
"url": "https://easyroutes.roundtrip.ai/api/2024-07"
}
],
"tags": [
"Stops"
],
"summary": "Update imported stop tasks",
"description": "Updates the tasks on an existing imported stop by ID, without needing to\n re-send the full stop payload via ImportStops. This is a full\n replacement: the entire list of tasks on the stop is replaced with the\n task templates provided in the request body. Task and item IDs are\n always regenerated by the server, and any existing completion state,\n input, or timestamps are cleared, since only the driver (via the driver\n app) can mark a task or item complete or provide input. The ID can be\n the EasyRoutes `id` returned on import or the client-provided\n `clientStopId`. Note that this only updates the imported stop record;\n if the stop has already been added to a route, use UpdateRouteStopTasks\n to update its tasks on that route.",
"operationId": "UpdateImportedStopTasks",
"parameters": [
{
"name": "id",
"in": "path",
"description": "The ID of the imported stop to update tasks for. You provide the\n EasyRoutes `id` returned on import or the client-provided\n `clientStopId`.",
"required": true,
"schema": {
"type": "string",
"examples": [
"ist-123e4567-e89b-12d3-a456-426614174000"
]
}
},
{
"name": "Idempotency-Key",
"in": "header",
"description": "A unique key for safely retrying this operation. For more information read [our guide](https://docs.roundtrip.ai/docs/concepts/idempotency.md).",
"schema": {
"maxLength": 255,
"minLength": 1,
"type": "string"
},
"examples": {
"default": {
"value": "550e8400-e29b-41d4-a716-446655440000"
}
}
}
],
"requestBody": {
"content": {
"application/json": {
"schema": {
"type": "array",
"items": {
"title": "TaskTemplate",
"type": "object",
"properties": {
"title": {
"type": "string",
"description": "Task title (e.g. `\"Delivery checklist\"`).",
"examples": [
"Delivery checklist"
]
},
"type": {
"enum": [
"UNKNOWN",
"CHECKBOXES",
"RADIO_BUTTONS",
"TEXT_INPUT",
"DECIMAL_INPUT",
"SCANNER_INPUT"
],
"type": "string",
"description": "Task type.",
"format": "enum",
"examples": [
"CHECKBOXES"
]
},
"items": {
"type": "array",
"items": {
"title": "TaskItemTemplate",
"type": "object",
"properties": {
"title": {
"type": "string",
"description": "Item title (e.g. `\"Pick up package\"`).",
"examples": [
"Pick up package"
]
}
},
"description": "An item template for a task. For `CHECKBOXES`, each item on a task may be\n completed independently. For `RADIO_BUTTONS`, at most one item will be\n completed."
},
"description": "Task items, which are required for `CHECKBOXES` and `RADIO_BUTTONS`."
},
"requiredToMarkStopAsDelivered": {
"type": "boolean",
"description": "Whether the task is required to mark the stop as completed.",
"examples": [
true
]
},
"requiredToMarkStopAsAttempted": {
"type": "boolean",
"description": "Whether the task is required to mark the stop as attempted.",
"examples": [
true
]
}
},
"description": "A template for creating tasks at a stop. Task templates may have one or more\n items for `CHECKBOXES` or `RADIO_BUTTONS`. Imported stops may have task\n templates that are used to create tasks when the stop is added to a route."
}
}
}
},
"required": true
},
"responses": {
"200": {
"description": "OK",
"headers": {
"Idempotency-Key": {
"description": "The idempotency key associated with the response.",
"schema": {
"type": "string"
}
},
"Idempotency-Replayed": {
"description": "Whether the response was replayed from a previous request.",
"schema": {
"type": "boolean"
}
}
},
"content": {
"application/json": {
"schema": {
"title": "ImportedStop",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "The ID of the imported stop, generated by EasyRoutes (e.g.\n `\"ist-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"ist-123e4567-e89b-12d3-a456-426614174000"
]
},
"clientStopId": {
"type": "string",
"description": "The client-provided ID associated with the imported stop, if provided.",
"examples": [
"test-order-1234"
]
},
"address": {
"allOf": [
{
"title": "Address",
"type": "object",
"properties": {
"address1": {
"type": "string",
"description": "Street address line 1 (e.g. `\"123 Main St\"`).",
"examples": [
"123 Main St"
]
},
"address2": {
"type": "string",
"description": "Street address line 2 (e.g. `\"Apt 101\"`).",
"examples": [
"Apt 3B"
]
},
"city": {
"type": "string",
"description": "City name (e.g. `\"New York\"`).",
"examples": [
"New York"
]
},
"provinceCode": {
"type": "string",
"description": "Province or state as subdivision codes in\n [ISO 3166-2](https://en.wikipedia.org/wiki/ISO_3166-2) format without the\n country prefix (e.g. `\"NY\"` for New York).",
"examples": [
"NY"
]
},
"countryCode": {
"type": "string",
"description": "Country code (e.g. `\"US\"`).",
"examples": [
"US"
]
},
"zip": {
"type": "string",
"description": "Postal or ZIP code (e.g. `\"10001\"`).",
"examples": [
"10001"
]
}
},
"description": "A physical street address."
}
],
"description": "The address for the stop.",
"examples": [
{
"address1": "123 Main St",
"address2": "Apt 3B",
"city": "New York",
"provinceCode": "NY",
"countryCode": "US",
"zip": "10001"
}
]
},
"contact": {
"allOf": [
{
"title": "Contact",
"type": "object",
"properties": {
"firstName": {
"type": "string",
"description": "First name (e.g. `\"John\"`).",
"examples": [
"John"
]
},
"lastName": {
"type": "string",
"description": "Last name (e.g. `\"Doe\"`).",
"examples": [
"Doe"
]
},
"company": {
"type": "string",
"description": "Company name (e.g. `\"Roundtrip Systems Inc\"`).",
"examples": [
"Roundtrip Systems Inc"
]
},
"phone": {
"type": "string",
"description": "Phone number in [E.164 format](https://en.wikipedia.org/wiki/E.164) (e.g.\n `\"+14265551000\"`).",
"examples": [
"+14265551000"
]
},
"email": {
"type": "string",
"description": "Email address (e.g. `\"john.doe@roundtrip.ai\"`)",
"examples": [
"john.doe@roundtrip.ai"
]
}
},
"description": "Contact information for a person or company."
}
],
"description": "The contact information for the stop.",
"examples": [
{
"firstName": "John",
"lastName": "Doe",
"company": "Roundtrip Systems Inc",
"phone": "+14265551000",
"email": "john.doe@roundtrip.ai"
}
]
},
"coordinates": {
"allOf": [
{
"type": "object",
"properties": {
"latitude": {
"type": "number",
"description": "The latitude in degrees. It must be in the range [-90.0, +90.0].",
"format": "double"
},
"longitude": {
"type": "number",
"description": "The longitude in degrees. It must be in the range [-180.0, +180.0].",
"format": "double"
}
},
"description": "An object that represents a latitude/longitude pair. This is expressed as a\n pair of doubles to represent degrees latitude and degrees longitude. Unless\n specified otherwise, this must conform to the\n WGS84\n standard. Values must be within normalized ranges."
}
],
"description": "The coordinates to use for the stop, if provided on import.",
"examples": [
{
"latitude": 40.7128,
"longitude": -74.006
}
]
},
"items": {
"type": "array",
"items": {
"title": "StopItem",
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "Item name (e.g. `\"Bananas\"`).",
"examples": [
"Bananas"
]
},
"quantity": {
"type": "integer",
"description": "Quantity of the item (e.g. `5`).",
"format": "int32",
"examples": [
5
]
},
"grams": {
"type": "integer",
"description": "Weight of the item in grams (e.g. `500`).",
"format": "int32",
"examples": [
500
]
},
"sku": {
"type": "string",
"description": "Stock keeping unit (e.g. `\"BANANA-001\"`).",
"examples": [
"BANANA-001"
]
}
},
"description": "An item to be delivered at a stop."
},
"description": "The items to deliver at the stop."
},
"note": {
"type": "string",
"description": "A note for the stop.",
"examples": [
"Leave at door."
]
},
"duration": {
"pattern": "^-?(?:0|[1-9][0-9]{0,11})(?:\\.[0-9]{1,9})?s$",
"type": "string",
"description": "The planned duration for the driver to spend at this stop. This duration is\n used in route optimization to estimate arrival times. If specified, it\n takes precedence over the route's default stop duration. Specified as a\n duration string in the format \"300s\" for 5 minutes, \"60s\" for 1 minute,\n etc.",
"examples": [
"300s"
]
},
"priority": {
"maximum": 10,
"type": "integer",
"description": "Priority of the stop for route planning.",
"format": "int32",
"examples": [
5
]
},
"orderName": {
"type": "string",
"description": "The name of the order associated with the stop.",
"examples": [
"#1234"
]
},
"importedAt": {
"type": "string",
"description": "The timestamp at which the stop was imported.",
"format": "date-time",
"examples": [
"2026-03-28T10:00:00Z"
]
},
"timeWindows": {
"type": "array",
"items": {
"title": "TimeWindow",
"type": "object",
"properties": {
"start": {
"allOf": [
{
"title": "TimeOfDay",
"type": "object",
"properties": {
"hours": {
"maximum": 23,
"type": "integer",
"description": "Hours of day in 24 hour format. Must be from 0 to 23.",
"format": "int32",
"examples": [
13
]
},
"minutes": {
"maximum": 59,
"type": "integer",
"description": "Minutes of hour of day. Must be from 0 to 59.",
"format": "int32",
"examples": [
37
]
},
"seconds": {
"maximum": 59,
"type": "integer",
"description": "Seconds of minutes of the time. Must be from 0 to 59.",
"format": "int32",
"examples": [
16
]
}
},
"description": "A time of day, independent of a particular date or timezone."
}
],
"description": "The start time of the time window (optional)."
},
"end": {
"allOf": [
{
"title": "TimeOfDay",
"type": "object",
"properties": {
"hours": {
"maximum": 23,
"type": "integer",
"description": "Hours of day in 24 hour format. Must be from 0 to 23.",
"format": "int32",
"examples": [
13
]
},
"minutes": {
"maximum": 59,
"type": "integer",
"description": "Minutes of hour of day. Must be from 0 to 59.",
"format": "int32",
"examples": [
37
]
},
"seconds": {
"maximum": 59,
"type": "integer",
"description": "Seconds of minutes of the time. Must be from 0 to 59.",
"format": "int32",
"examples": [
16
]
}
},
"description": "A time of day, independent of a particular date or timezone."
}
],
"description": "The end time of the time window (optional)."
}
},
"description": "A time window for a stop. The time window may be open-ended, but one or both\n of the start and end times should be provided. The end time must be >= the\n start time."
},
"description": "The time window for the stop. Note that we currently support at most one\n time window but may support multiple time windows in the future.",
"examples": [
[
{
"start": {
"hours": 9
},
"end": {
"hours": 17
}
}
]
]
},
"deliveryDate": {
"allOf": [
{
"title": "Date",
"required": [
"year",
"month",
"day"
],
"type": "object",
"properties": {
"year": {
"maximum": 9999,
"minimum": 1,
"type": "integer",
"description": "Year of the date. Must be from 1 to 9999.",
"format": "int32",
"examples": [
2019
]
},
"month": {
"maximum": 12,
"minimum": 1,
"type": "integer",
"description": "Month of a year. Must be from 1 to 12.",
"format": "int32",
"examples": [
11
]
},
"day": {
"maximum": 31,
"minimum": 1,
"type": "integer",
"description": "Day of a month. Must be from 1 to 31.",
"format": "int32",
"examples": [
15
]
}
},
"description": "A date in year-month-day format."
}
],
"description": "The delivery date for the stop.",
"examples": [
{
"year": 2025,
"month": 12,
"day": 16
}
]
},
"attributes": {
"type": "array",
"items": {
"title": "Attribute",
"type": "object",
"properties": {
"key": {
"type": "string",
"description": "Attribute key. Must be non-empty.",
"examples": [
"delivery_date"
]
},
"value": {
"type": "string",
"description": "Attribute value.",
"examples": [
"2025-12-16"
]
}
},
"description": "A key-value pair for storing additional information on a stop, such as order\n details, delivery instructions, or custom fields."
},
"description": "The additional key-value attributes set on the imported stop.",
"examples": [
[
{
"key": "color",
"value": "blue"
}
]
]
},
"tags": {
"type": "array",
"items": {
"type": "string"
},
"description": "The tags for the stop.",
"examples": [
[
"foo",
"bar"
]
]
},
"tasks": {
"type": "array",
"items": {
"title": "TaskTemplate",
"type": "object",
"properties": {
"title": {
"type": "string",
"description": "Task title (e.g. `\"Delivery checklist\"`).",
"examples": [
"Delivery checklist"
]
},
"type": {
"enum": [
"UNKNOWN",
"CHECKBOXES",
"RADIO_BUTTONS",
"TEXT_INPUT",
"DECIMAL_INPUT",
"SCANNER_INPUT"
],
"type": "string",
"description": "Task type.",
"format": "enum",
"examples": [
"CHECKBOXES"
]
},
"items": {
"type": "array",
"items": {
"title": "TaskItemTemplate",
"type": "object",
"properties": {
"title": {
"type": "string",
"description": "Item title (e.g. `\"Pick up package\"`).",
"examples": [
"Pick up package"
]
}
},
"description": "An item template for a task. For `CHECKBOXES`, each item on a task may be\n completed independently. For `RADIO_BUTTONS`, at most one item will be\n completed."
},
"description": "Task items, which are required for `CHECKBOXES` and `RADIO_BUTTONS`."
},
"requiredToMarkStopAsDelivered": {
"type": "boolean",
"description": "Whether the task is required to mark the stop as completed.",
"examples": [
true
]
},
"requiredToMarkStopAsAttempted": {
"type": "boolean",
"description": "Whether the task is required to mark the stop as attempted.",
"examples": [
true
]
}
},
"description": "A template for creating tasks at a stop. Task templates may have one or more\n items for `CHECKBOXES` or `RADIO_BUTTONS`. Imported stops may have task\n templates that are used to create tasks when the stop is added to a route."
},
"description": "The tasks for the stop."
},
"type": {
"enum": [
"UNKNOWN",
"DELIVERY",
"BREAK",
"PICKUP",
"TASK"
],
"type": "string",
"description": "The type of stop (DELIVERY, PICKUP, or TASK). Defaults to DELIVERY if not\n provided.",
"format": "enum",
"examples": [
"DELIVERY"
]
},
"customSignatureDisclosure": {
"type": "string",
"description": "Custom signature disclosure for the stop. Only populated if stop type is\n DELIVERY, PICKUP, or TASK.",
"examples": [
"I acknowledge that I have received this delivery."
]
},
"orderReferenceUrl": {
"type": "string",
"description": "A reference URL for the order associated with the stop (e.g. a link to the\n order in your order management system). Must be a valid HTTPS URL.",
"examples": [
"https://orders.example.com/orders/148977776"
]
}
},
"description": "A stop imported into EasyRoutes."
}
}
}
},
"default": {
"description": "Default error response",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"code": {
"type": "integer",
"description": "The status code, which should be an enum value of [google.rpc.Code][google.rpc.Code].",
"format": "int32"
},
"message": {
"type": "string",
"description": "A developer-facing error message, which should be in English. Any user-facing error message should be localized and sent in the [google.rpc.Status.details][google.rpc.Status.details] field, or localized by the client."
},
"details": {
"type": "array",
"items": {
"type": "object",
"properties": {
"@type": {
"type": "string",
"description": "The type of the serialized message."
}
},
"additionalProperties": true,
"description": "Contains an arbitrary serialized message along with a @type that describes the type of the serialized message."
},
"description": "A list of messages that carry the error details. There is a common set of message types for APIs to use."
}
},
"description": "The `Status` type defines a logical error model that is suitable for different programming environments, including REST APIs and RPC APIs. It is used by [gRPC](https://github.com/grpc). Each `Status` message contains three pieces of data: error code, error message, and error details. You can find out more about this error model and how to work with it in the [API Design Guide](https://cloud.google.com/apis/design/errors)."
}
}
}
}
},
"security": [
{
"bearerAuth": []
}
],
"components": {
"securitySchemes": {
"bearerAuth": {
"type": "http",
"description": "Access token from `/authenticate`",
"scheme": "bearer",
"bearerFormat": "JWT"
}
}
}
}
```
# Get vehicle (https://docs.roundtrip.ai/docs/api-reference/vehicles/get-vehicles-id)
GET /vehicles/{id}
Fetch a single vehicle by ID.
## OpenAPI specification
```json
{
"servers": [
{
"url": "https://easyroutes.roundtrip.ai/api/2024-07"
}
],
"tags": [
"Vehicles"
],
"summary": "Get vehicle",
"description": "Fetch a single vehicle by ID.",
"operationId": "GetVehicle",
"parameters": [
{
"name": "id",
"in": "path",
"description": "The ID of the vehicle to fetch.",
"required": true,
"schema": {
"type": "string",
"examples": [
"veh-123e4567-e89b-12d3-a456-426614174000"
]
}
}
],
"responses": {
"200": {
"description": "OK",
"content": {
"application/json": {
"schema": {
"title": "Vehicle",
"required": [
"id"
],
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Vehicle ID.",
"examples": [
"veh-123e4567-e89b-12d3-a456-426614174000"
]
},
"name": {
"type": "string",
"description": "Vehicle name.",
"examples": [
"Delivery Van 1"
]
},
"make": {
"type": "string",
"description": "Vehicle make.",
"examples": [
"Ford"
]
},
"model": {
"type": "string",
"description": "Vehicle model.",
"examples": [
"Transit"
]
},
"year": {
"type": "integer",
"description": "Vehicle model year.",
"format": "int32",
"examples": [
2023
]
},
"type": {
"enum": [
"UNKNOWN",
"CAR",
"CARGO_VAN",
"PICKUP_TRUCK",
"BOX_TRUCK",
"MOTORCYCLE",
"BICYCLE",
"DRONE",
"OTHER"
],
"type": "string",
"description": "Vehicle type.",
"format": "enum",
"examples": [
"CARGO_VAN"
]
},
"vin": {
"type": "string",
"description": "Vehicle Identification Number.",
"examples": [
"1FTBW2CM5NKA12345"
]
},
"license": {
"type": "string",
"description": "Vehicle license plate.",
"examples": [
"ABC-1234"
]
},
"isArchived": {
"type": "boolean",
"description": "Whether the vehicle is archived.",
"examples": [
false
]
},
"createdTimestamp": {
"type": "string",
"description": "Timestamp when the vehicle was created.",
"format": "date-time",
"examples": [
"2026-07-30T12:00:00Z"
]
}
},
"description": "A vehicle that can be assigned to a route."
}
}
}
},
"default": {
"description": "Default error response",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"code": {
"type": "integer",
"description": "The status code, which should be an enum value of [google.rpc.Code][google.rpc.Code].",
"format": "int32"
},
"message": {
"type": "string",
"description": "A developer-facing error message, which should be in English. Any user-facing error message should be localized and sent in the [google.rpc.Status.details][google.rpc.Status.details] field, or localized by the client."
},
"details": {
"type": "array",
"items": {
"type": "object",
"properties": {
"@type": {
"type": "string",
"description": "The type of the serialized message."
}
},
"additionalProperties": true,
"description": "Contains an arbitrary serialized message along with a @type that describes the type of the serialized message."
},
"description": "A list of messages that carry the error details. There is a common set of message types for APIs to use."
}
},
"description": "The `Status` type defines a logical error model that is suitable for different programming environments, including REST APIs and RPC APIs. It is used by [gRPC](https://github.com/grpc). Each `Status` message contains three pieces of data: error code, error message, and error details. You can find out more about this error model and how to work with it in the [API Design Guide](https://cloud.google.com/apis/design/errors)."
}
}
}
}
},
"security": [
{
"bearerAuth": []
}
],
"components": {
"securitySchemes": {
"bearerAuth": {
"type": "http",
"description": "Access token from `/authenticate`",
"scheme": "bearer",
"bearerFormat": "JWT"
}
}
}
}
```
# List vehicles (https://docs.roundtrip.ai/docs/api-reference/vehicles/get-vehicles)
GET /vehicles
Fetch a paginated list of vehicles associated with the shop.
## OpenAPI specification
```json
{
"servers": [
{
"url": "https://easyroutes.roundtrip.ai/api/2024-07"
}
],
"tags": [
"Vehicles"
],
"summary": "List vehicles",
"description": "Fetch a paginated list of vehicles associated with the shop.",
"operationId": "ListVehicles",
"parameters": [
{
"name": "query.limit",
"in": "query",
"description": "Maximum number of vehicles to return. Must be less than or equal to\n `200`. Defaults to `20`.",
"schema": {
"maximum": 200,
"type": "integer",
"format": "int32",
"examples": [
50
]
}
},
{
"name": "cursor",
"in": "query",
"description": "Cursor to fetch the next page of results (if available). Should only be\n set on subsequent requests.",
"schema": {
"type": "string",
"examples": [
"eyJpZCI6IjEyMyJ9"
]
}
}
],
"responses": {
"200": {
"description": "OK",
"content": {
"application/json": {
"schema": {
"title": "ListVehiclesResponse",
"type": "object",
"properties": {
"vehicles": {
"type": "array",
"items": {
"title": "Vehicle",
"required": [
"id"
],
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Vehicle ID.",
"examples": [
"veh-123e4567-e89b-12d3-a456-426614174000"
]
},
"name": {
"type": "string",
"description": "Vehicle name.",
"examples": [
"Delivery Van 1"
]
},
"make": {
"type": "string",
"description": "Vehicle make.",
"examples": [
"Ford"
]
},
"model": {
"type": "string",
"description": "Vehicle model.",
"examples": [
"Transit"
]
},
"year": {
"type": "integer",
"description": "Vehicle model year.",
"format": "int32",
"examples": [
2023
]
},
"type": {
"enum": [
"UNKNOWN",
"CAR",
"CARGO_VAN",
"PICKUP_TRUCK",
"BOX_TRUCK",
"MOTORCYCLE",
"BICYCLE",
"DRONE",
"OTHER"
],
"type": "string",
"description": "Vehicle type.",
"format": "enum",
"examples": [
"CARGO_VAN"
]
},
"vin": {
"type": "string",
"description": "Vehicle Identification Number.",
"examples": [
"1FTBW2CM5NKA12345"
]
},
"license": {
"type": "string",
"description": "Vehicle license plate.",
"examples": [
"ABC-1234"
]
},
"isArchived": {
"type": "boolean",
"description": "Whether the vehicle is archived.",
"examples": [
false
]
},
"createdTimestamp": {
"type": "string",
"description": "Timestamp when the vehicle was created.",
"format": "date-time",
"examples": [
"2026-07-30T12:00:00Z"
]
}
},
"description": "A vehicle that can be assigned to a route."
},
"description": "List of vehicles."
},
"nextCursor": {
"type": "string",
"description": "Cursor to fetch the next page of results (if available).",
"examples": [
"eyJsaW1pdCI6MjB9"
]
}
}
}
}
}
},
"default": {
"description": "Default error response",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"code": {
"type": "integer",
"description": "The status code, which should be an enum value of [google.rpc.Code][google.rpc.Code].",
"format": "int32"
},
"message": {
"type": "string",
"description": "A developer-facing error message, which should be in English. Any user-facing error message should be localized and sent in the [google.rpc.Status.details][google.rpc.Status.details] field, or localized by the client."
},
"details": {
"type": "array",
"items": {
"type": "object",
"properties": {
"@type": {
"type": "string",
"description": "The type of the serialized message."
}
},
"additionalProperties": true,
"description": "Contains an arbitrary serialized message along with a @type that describes the type of the serialized message."
},
"description": "A list of messages that carry the error details. There is a common set of message types for APIs to use."
}
},
"description": "The `Status` type defines a logical error model that is suitable for different programming environments, including REST APIs and RPC APIs. It is used by [gRPC](https://github.com/grpc). Each `Status` message contains three pieces of data: error code, error message, and error details. You can find out more about this error model and how to work with it in the [API Design Guide](https://cloud.google.com/apis/design/errors)."
}
}
}
}
},
"security": [
{
"bearerAuth": []
}
],
"components": {
"securitySchemes": {
"bearerAuth": {
"type": "http",
"description": "Access token from `/authenticate`",
"scheme": "bearer",
"bearerFormat": "JWT"
}
}
}
}
```
# Unsubscribe webhook (https://docs.roundtrip.ai/docs/api-reference/webhooks/delete-webhooks-id)
DELETE /webhooks/{id}
Unsubscribe from a webhook by ID. The ID should be the webhook subscription
ID returned when the webhook was created. The response will be empty on
success.
## OpenAPI specification
```json
{
"servers": [
{
"url": "https://easyroutes.roundtrip.ai/api/2024-07"
}
],
"tags": [
"Webhooks"
],
"summary": "Unsubscribe webhook",
"description": "Unsubscribe from a webhook by ID. The ID should be the webhook subscription\n ID returned when the webhook was created. The response will be empty on\n success.",
"operationId": "UnsubscribeWebhook",
"parameters": [
{
"name": "id",
"in": "path",
"description": "The ID of the webhook to unsubscribe.",
"required": true,
"schema": {
"type": "string",
"examples": [
"sub-123e4567-e89b-12d3-a456-426614174000"
]
}
},
{
"name": "Idempotency-Key",
"in": "header",
"description": "A unique key for safely retrying this operation. For more information read [our guide](https://docs.roundtrip.ai/docs/concepts/idempotency.md).",
"schema": {
"maxLength": 255,
"minLength": 1,
"type": "string"
},
"examples": {
"default": {
"value": "550e8400-e29b-41d4-a716-446655440000"
}
}
}
],
"responses": {
"200": {
"description": "OK",
"headers": {
"Idempotency-Key": {
"description": "The idempotency key associated with the response.",
"schema": {
"type": "string"
}
},
"Idempotency-Replayed": {
"description": "Whether the response was replayed from a previous request.",
"schema": {
"type": "boolean"
}
}
},
"content": {}
},
"default": {
"description": "Default error response",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"code": {
"type": "integer",
"description": "The status code, which should be an enum value of [google.rpc.Code][google.rpc.Code].",
"format": "int32"
},
"message": {
"type": "string",
"description": "A developer-facing error message, which should be in English. Any user-facing error message should be localized and sent in the [google.rpc.Status.details][google.rpc.Status.details] field, or localized by the client."
},
"details": {
"type": "array",
"items": {
"type": "object",
"properties": {
"@type": {
"type": "string",
"description": "The type of the serialized message."
}
},
"additionalProperties": true,
"description": "Contains an arbitrary serialized message along with a @type that describes the type of the serialized message."
},
"description": "A list of messages that carry the error details. There is a common set of message types for APIs to use."
}
},
"description": "The `Status` type defines a logical error model that is suitable for different programming environments, including REST APIs and RPC APIs. It is used by [gRPC](https://github.com/grpc). Each `Status` message contains three pieces of data: error code, error message, and error details. You can find out more about this error model and how to work with it in the [API Design Guide](https://cloud.google.com/apis/design/errors)."
}
}
}
}
},
"security": [
{
"bearerAuth": []
}
],
"components": {
"securitySchemes": {
"bearerAuth": {
"type": "http",
"description": "Access token from `/authenticate`",
"scheme": "bearer",
"bearerFormat": "JWT"
}
}
}
}
```
# List webhook subscriptions (https://docs.roundtrip.ai/docs/api-reference/webhooks/get-webhooks)
GET /webhooks
Fetch a list of all webhook subscriptions. The response will include a list
of webhook subscriptions with their IDs, URLs, subscribed topics, and
active status.
## OpenAPI specification
```json
{
"servers": [
{
"url": "https://easyroutes.roundtrip.ai/api/2024-07"
}
],
"tags": [
"Webhooks"
],
"summary": "List webhook subscriptions",
"description": "Fetch a list of all webhook subscriptions. The response will include a list\n of webhook subscriptions with their IDs, URLs, subscribed topics, and\n active status.",
"operationId": "ListWebhookSubscriptions",
"responses": {
"200": {
"description": "OK",
"content": {
"application/json": {
"schema": {
"title": "ListWebhookSubscriptionsResponse",
"required": [
"webhooks"
],
"type": "object",
"properties": {
"webhooks": {
"type": "array",
"items": {
"title": "WebhookSubscription",
"required": [
"id",
"url",
"topics",
"active"
],
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Webhook subscription ID (e.g.\n `\"sub-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"sub-123e4567-e89b-12d3-a456-426614174000"
]
},
"url": {
"type": "string",
"description": "The URL to send webhook events to.",
"examples": [
"https://example.com/webhook"
]
},
"topics": {
"type": "array",
"items": {
"enum": [
"UNKNOWN",
"TEST",
"ROUTE_CREATED",
"ROUTE_UPDATED",
"ROUTE_DELETED",
"ROUTE_COMPLETED",
"STOP_STATUS_UPDATED",
"STOP_UPDATED",
"ROUTE_STARTED",
"ROUTE_DISPATCHED",
"ROUTE_START_STOP_UPDATED",
"ROUTE_END_STOP_UPDATED",
"DRIVER_ADDED",
"DRIVER_UPDATED",
"DRIVER_ACTIVATED",
"DRIVER_DEACTIVATED",
"DRIVER_ARCHIVED",
"IMPORTED_STOP_DELETED",
"IMPORTED_STOP_CREATED",
"IMPORTED_STOP_UPDATED"
],
"type": "string",
"format": "enum"
},
"description": "The list of subscribed topics for webhook events.",
"examples": [
[
"ROUTE_CREATED",
"ROUTE_UPDATED"
]
]
},
"active": {
"type": "boolean",
"description": "Boolean indicating whether the subscription is active.",
"examples": [
true
]
}
},
"description": "A subscription for receiving webhook events from EasyRoutes."
},
"description": "The list of webhooks that are currently subscribed."
}
}
}
}
}
},
"default": {
"description": "Default error response",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"code": {
"type": "integer",
"description": "The status code, which should be an enum value of [google.rpc.Code][google.rpc.Code].",
"format": "int32"
},
"message": {
"type": "string",
"description": "A developer-facing error message, which should be in English. Any user-facing error message should be localized and sent in the [google.rpc.Status.details][google.rpc.Status.details] field, or localized by the client."
},
"details": {
"type": "array",
"items": {
"type": "object",
"properties": {
"@type": {
"type": "string",
"description": "The type of the serialized message."
}
},
"additionalProperties": true,
"description": "Contains an arbitrary serialized message along with a @type that describes the type of the serialized message."
},
"description": "A list of messages that carry the error details. There is a common set of message types for APIs to use."
}
},
"description": "The `Status` type defines a logical error model that is suitable for different programming environments, including REST APIs and RPC APIs. It is used by [gRPC](https://github.com/grpc). Each `Status` message contains three pieces of data: error code, error message, and error details. You can find out more about this error model and how to work with it in the [API Design Guide](https://cloud.google.com/apis/design/errors)."
}
}
}
}
},
"security": [
{
"bearerAuth": []
}
],
"components": {
"securitySchemes": {
"bearerAuth": {
"type": "http",
"description": "Access token from `/authenticate`",
"scheme": "bearer",
"bearerFormat": "JWT"
}
}
}
}
```
# Subscribe webhook (https://docs.roundtrip.ai/docs/api-reference/webhooks/post-webhooks)
POST /webhooks
Creates a new webhook subscription to receive events from EasyRoutes. The
request body should include the URL to send webhook events to and the
topics to subscribe to. The response will include the created webhook
subscription with its ID and the list of subscribed topics. You may have a
maximum of 5 webhook subscriptions per organization. The webhook URL must
be publicly accessible and able to handle POST requests with JSON payloads.
The response will include the created webhook subscription with a unique
ID.
## OpenAPI specification
```json
{
"servers": [
{
"url": "https://easyroutes.roundtrip.ai/api/2024-07"
}
],
"tags": [
"Webhooks"
],
"summary": "Subscribe webhook",
"description": "Creates a new webhook subscription to receive events from EasyRoutes. The\n request body should include the URL to send webhook events to and the\n topics to subscribe to. The response will include the created webhook\n subscription with its ID and the list of subscribed topics. You may have a\n maximum of 5 webhook subscriptions per organization. The webhook URL must\n be publicly accessible and able to handle POST requests with JSON payloads.\n The response will include the created webhook subscription with a unique\n ID.",
"operationId": "SubscribeWebhook",
"parameters": [
{
"name": "Idempotency-Key",
"in": "header",
"description": "A unique key for safely retrying this operation. For more information read [our guide](https://docs.roundtrip.ai/docs/concepts/idempotency.md).",
"schema": {
"maxLength": 255,
"minLength": 1,
"type": "string"
},
"examples": {
"default": {
"value": "550e8400-e29b-41d4-a716-446655440000"
}
}
}
],
"requestBody": {
"content": {
"application/json": {
"schema": {
"title": "SubscribeWebhookRequest",
"required": [
"url",
"topics"
],
"type": "object",
"properties": {
"url": {
"type": "string",
"description": "The URL to send webhook events to. This must be a publicly accessible URL\n that can handle POST requests with JSON payloads. See\n [our guide on webhooks](https://docs.roundtrip.ai/docs/webhooks.md) for more details.",
"examples": [
"https://example.com/webhook"
]
},
"topics": {
"type": "array",
"items": {
"enum": [
"UNKNOWN",
"TEST",
"ROUTE_CREATED",
"ROUTE_UPDATED",
"ROUTE_DELETED",
"ROUTE_COMPLETED",
"STOP_STATUS_UPDATED",
"STOP_UPDATED",
"ROUTE_STARTED",
"ROUTE_DISPATCHED",
"ROUTE_START_STOP_UPDATED",
"ROUTE_END_STOP_UPDATED",
"DRIVER_ADDED",
"DRIVER_UPDATED",
"DRIVER_ACTIVATED",
"DRIVER_DEACTIVATED",
"DRIVER_ARCHIVED",
"IMPORTED_STOP_DELETED",
"IMPORTED_STOP_CREATED",
"IMPORTED_STOP_UPDATED"
],
"type": "string",
"format": "enum"
},
"description": "The topics to subscribe to.",
"examples": [
[
"ROUTE_CREATED",
"ROUTE_UPDATED"
]
]
}
}
}
}
},
"required": true
},
"responses": {
"200": {
"description": "OK",
"headers": {
"Idempotency-Key": {
"description": "The idempotency key associated with the response.",
"schema": {
"type": "string"
}
},
"Idempotency-Replayed": {
"description": "Whether the response was replayed from a previous request.",
"schema": {
"type": "boolean"
}
}
},
"content": {
"application/json": {
"schema": {
"title": "WebhookSubscription",
"required": [
"id",
"url",
"topics",
"active"
],
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Webhook subscription ID (e.g.\n `\"sub-123e4567-e89b-12d3-a456-426614174000\"`).",
"examples": [
"sub-123e4567-e89b-12d3-a456-426614174000"
]
},
"url": {
"type": "string",
"description": "The URL to send webhook events to.",
"examples": [
"https://example.com/webhook"
]
},
"topics": {
"type": "array",
"items": {
"enum": [
"UNKNOWN",
"TEST",
"ROUTE_CREATED",
"ROUTE_UPDATED",
"ROUTE_DELETED",
"ROUTE_COMPLETED",
"STOP_STATUS_UPDATED",
"STOP_UPDATED",
"ROUTE_STARTED",
"ROUTE_DISPATCHED",
"ROUTE_START_STOP_UPDATED",
"ROUTE_END_STOP_UPDATED",
"DRIVER_ADDED",
"DRIVER_UPDATED",
"DRIVER_ACTIVATED",
"DRIVER_DEACTIVATED",
"DRIVER_ARCHIVED",
"IMPORTED_STOP_DELETED",
"IMPORTED_STOP_CREATED",
"IMPORTED_STOP_UPDATED"
],
"type": "string",
"format": "enum"
},
"description": "The list of subscribed topics for webhook events.",
"examples": [
[
"ROUTE_CREATED",
"ROUTE_UPDATED"
]
]
},
"active": {
"type": "boolean",
"description": "Boolean indicating whether the subscription is active.",
"examples": [
true
]
}
},
"description": "A subscription for receiving webhook events from EasyRoutes."
}
}
}
},
"default": {
"description": "Default error response",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"code": {
"type": "integer",
"description": "The status code, which should be an enum value of [google.rpc.Code][google.rpc.Code].",
"format": "int32"
},
"message": {
"type": "string",
"description": "A developer-facing error message, which should be in English. Any user-facing error message should be localized and sent in the [google.rpc.Status.details][google.rpc.Status.details] field, or localized by the client."
},
"details": {
"type": "array",
"items": {
"type": "object",
"properties": {
"@type": {
"type": "string",
"description": "The type of the serialized message."
}
},
"additionalProperties": true,
"description": "Contains an arbitrary serialized message along with a @type that describes the type of the serialized message."
},
"description": "A list of messages that carry the error details. There is a common set of message types for APIs to use."
}
},
"description": "The `Status` type defines a logical error model that is suitable for different programming environments, including REST APIs and RPC APIs. It is used by [gRPC](https://github.com/grpc). Each `Status` message contains three pieces of data: error code, error message, and error details. You can find out more about this error model and how to work with it in the [API Design Guide](https://cloud.google.com/apis/design/errors)."
}
}
}
}
},
"security": [
{
"bearerAuth": []
}
],
"components": {
"securitySchemes": {
"bearerAuth": {
"type": "http",
"description": "Access token from `/authenticate`",
"scheme": "bearer",
"bearerFormat": "JWT"
}
}
}
}
```
# API Changelog (https://docs.roundtrip.ai/docs/changelog)
## September 9, 2026 - rev bb5086d
### Endpoint changes
#### Added endpoint to resync route orders
Added the `POST /routes/{routeId}/resync-orders` endpoint to refresh order-backed stops from Shopify with the latest fulfillment statuses, item updates, notes, and tags.
**Endpoints:** `POST /routes/{routeId}/resync-orders`
- **Added:** Added the `POST /routes/{routeId}/resync-orders` endpoint to resync Shopify order data across a route's stops and return the updated route.
**Tags:** Routes
---
## September 1, 2026 - rev 559604c
### Endpoint changes
#### Added idempotency support to mutating endpoints
You can now safely retry route, stop, and webhook requests using idempotency headers. See [our guide](https://docs.roundtrip.ai/docs/concepts/idempotency.md) for more details.
**Endpoints:** `POST /routes`, `POST /routes/{id}/reoptimize`, `PATCH /routes/{routeId}`, `DELETE /routes/{routeId}/dispatch`, `POST /routes/{routeId}/dispatch`, `DELETE /routes/{routeId}/driver`, `PUT /routes/{routeId}/driver`, `PATCH /routes/{routeId}/end/location`, `PUT /routes/{routeId}/end/tasks`, `PATCH /routes/{routeId}/start/location`, `PUT /routes/{routeId}/start/tasks`, `POST /routes/{routeId}/stops`, `DELETE /routes/{routeId}/stops/{stopIds}`, `PATCH /routes/{routeId}/stops/{stopId}`, `PUT /routes/{routeId}/stops/{stopId}/items`, `PATCH /routes/{routeId}/stops/{stopId}/location`, `PUT /routes/{routeId}/stops/{stopId}/position`, `PUT /routes/{routeId}/stops/{stopId}/tasks`, `DELETE /routes/{routeId}/vehicle`, `PUT /routes/{routeId}/vehicle`, `POST /stops/imports`, `DELETE /stops/imports/{id}`, `PATCH /stops/imports/{id}`, `PUT /stops/imports/{id}/items`, `PATCH /stops/imports/{id}/location`, `PUT /stops/imports/{id}/tasks`, `POST /webhooks`, `DELETE /webhooks/{id}`
- **Changed:** Added the optional `Idempotency-Key` request header.
- **Changed:** Added the `Idempotency-Key` response header on `200` responses.
- **Changed:** Added the `Idempotency-Replayed` response header on `200` responses.
**Tags:** Routes, Stops, Webhooks
---
## August 31, 2026 - rev cc6f98e
### Schema changes
#### Added order reference URL to imported stops
You can now view an external order reference URL on imported stops.
- **Changed:** Added `orderReferenceUrl` to provide a reference HTTPS URL for the order associated with the stop, such as a link to an order management system.
**Affected endpoints:** `GET /stops/imports`, `POST /stops/imports`, `GET /stops/imports/{id}`, `PATCH /stops/imports/{id}`, `PUT /stops/imports/{id}/items`, `PATCH /stops/imports/{id}/location`, `PUT /stops/imports/{id}/tasks`
**Tags:** Stops
#### Imported stop update support for order reference URLs
You can now update the order reference URL for an imported stop.
- **Changed:** Added the optional `orderReferenceUrl` request field to update the HTTPS reference link to the order in your external order management system.
**Affected endpoints:** `PATCH /stops/imports/{id}`
**Tags:** Stops
#### Added order reference URL to RouteStop
You can now view an external order reference link directly on imported route stops.
- **Changed:** Added optional `orderReferenceUrl` field providing a link to the order associated with the stop in an external system for imported stops.
**Affected endpoints:** `GET /routes`, `POST /routes`, `GET /routes/{id}`, `POST /routes/{id}/reoptimize`, `PATCH /routes/{routeId}`, `DELETE /routes/{routeId}/dispatch`, `POST /routes/{routeId}/dispatch`, `DELETE /routes/{routeId}/driver`, `PUT /routes/{routeId}/driver`, `PATCH /routes/{routeId}/end/location`, `PUT /routes/{routeId}/end/tasks`, `PATCH /routes/{routeId}/start/location`, `PUT /routes/{routeId}/start/tasks`, `POST /routes/{routeId}/stops`, `DELETE /routes/{routeId}/stops/{stopIds}`, `GET /routes/{routeId}/stops/{stopId}`, `PATCH /routes/{routeId}/stops/{stopId}`, `PUT /routes/{routeId}/stops/{stopId}/items`, `PATCH /routes/{routeId}/stops/{stopId}/location`, `PUT /routes/{routeId}/stops/{stopId}/position`, `PUT /routes/{routeId}/stops/{stopId}/tasks`, `DELETE /routes/{routeId}/vehicle`, `PUT /routes/{routeId}/vehicle`
**Tags:** Routes, Stops
#### Added order reference URL when updating route stops
You can now update the external order reference URL for an existing stop on a route.
- **Changed:** Added the optional `orderReferenceUrl` request field to update the stop's external order reference URL, such as a link to the order in your order management system (must be a valid HTTPS URL).
**Affected endpoints:** `PATCH /routes/{routeId}/stops/{stopId}`
**Tags:** Stops
#### Added order reference URL to imported stops
You can now include an external order reference link when importing stops.
- **Changed:** Added the optional `orderReferenceUrl` field to link an imported stop to an external order management system via an HTTPS URL.
**Affected endpoints:** `POST /stops/imports`
**Tags:** Stops
### Endpoint changes
#### Route sorting updates
You can now sort routes by their scheduled date and time.
**Endpoints:** `GET /routes`
- **Changed:** Added the `SCHEDULED_AT` option to the `sortKey` query parameter.
**Tags:** Routes
---
## August 10, 2026 - rev 90e013a
### Schema changes
#### Imported Stop Update
You can now update additional stop details including timing, sequencing, and custom disclosures.
- **Changed:** Add a duration to the stop.
- **Changed:** Specify an order name.
- **Changed:** Set a delivery date.
- **Changed:** Define the stop type.
- **Changed:** Include a custom signature disclosure.
**Affected endpoints:** `PATCH /stops/imports/{id}`
**Tags:** Stops
#### Route
You can now access vehicle information directly within route details.
- **Changed:** Includes the assigned vehicle.
**Affected endpoints:** `GET /routes`, `POST /routes`, `GET /routes/{id}`, `POST /routes/{id}/reoptimize`, `PATCH /routes/{routeId}`, `DELETE /routes/{routeId}/dispatch`, `POST /routes/{routeId}/dispatch`, `DELETE /routes/{routeId}/driver`, `PUT /routes/{routeId}/driver`, `PATCH /routes/{routeId}/end/location`, `PUT /routes/{routeId}/end/tasks`, `PATCH /routes/{routeId}/start/location`, `PUT /routes/{routeId}/start/tasks`, `POST /routes/{routeId}/stops`, `DELETE /routes/{routeId}/stops/{stopIds}`, `PUT /routes/{routeId}/stops/{stopId}/position`, `DELETE /routes/{routeId}/vehicle`, `PUT /routes/{routeId}/vehicle`
**Tags:** Routes, Stops
### Endpoint changes
#### Unassign route vehicle
A new endpoint has been added to unassign a vehicle from a route by its ID. The response returns the updated route without an assigned vehicle.
**Endpoints:** `DELETE /routes/{routeId}/vehicle`
- **Added:** The endpoint DELETE /routes/{routeId}/vehicle has been added.
**Tags:** Routes
#### List vehicles
Fetch a paginated list of vehicles associated with the shop.
**Endpoints:** `GET /vehicles`
- **Added:** Added the GET /vehicles endpoint to retrieve a paginated list of vehicles.
**Tags:** Vehicles
#### Get vehicle
Fetch a single vehicle by ID.
**Endpoints:** `GET /vehicles/{id}`
- **Added:** Added the GET /vehicles/{id} endpoint to fetch a single vehicle by ID.
**Tags:** Vehicles
#### Assign route vehicle
Assigns a vehicle to a route by route ID. The response will include the updated route with the new vehicle assigned.
**Endpoints:** `PUT /routes/{routeId}/vehicle`
- **Added:** Added the PUT /routes/{routeId}/vehicle endpoint to assign a vehicle to a specific route.
**Tags:** Routes
#### Update imported stop tasks
Updates the tasks on an existing imported stop by ID, without needing to re-send the full stop payload via ImportStops. This is a full replacement: the entire list of tasks on the stop is replaced with the task templates provided in the request body.
**Endpoints:** `PUT /stops/imports/{id}/tasks`
- **Added:** Added the PUT /stops/imports/{id}/tasks endpoint to allow full replacement of tasks on an imported stop record.
**Tags:** Stops
---
## July 29, 2026 - rev dae72f5
### Schema changes
#### Imported stop updates
You can now update time windows, attributes, and priority levels for imported stops.
- **Changed:** Add optional time windows to the update request.
- **Changed:** Include custom attributes when updating a stop.
- **Changed:** Set or modify the priority level for the stop.
**Affected endpoints:** `PATCH /stops/imports/{id}`
**Tags:** Stops
### Endpoint changes
#### Update imported stop location
Updates the address and/or coordinates for an imported stop by ID. This partial update modifies the imported stop record itself using a provided update mask.
**Endpoints:** `PATCH /stops/imports/{id}/location`
- **Added:** Added the UpdateImportedStopLocation endpoint to allow partial updates to an imported stop's address or coordinates.
**Tags:** Stops
#### Update route end tasks
Updates the tasks required to complete a route by route ID. This is a full replacement: the entire list of tasks on the route end is replaced with the task templates provided in the request body, so existing tasks not included in the request will be removed. Task and item IDs are always regenerated by the server, and any existing completion state, input, or timestamps are cleared, since only the driver (via the driver app) can mark a task or item complete or provide input. The route must have an end location and must not be archived. The response returns the full updated route.
**Endpoints:** `PUT /routes/{routeId}/end/tasks`
- **Added:** Added the UpdateRouteEndTasks endpoint to replace tasks on a route's end location.
**Tags:** Routes
#### Update route start tasks
Updates the tasks required before starting a route by route ID. This is a full replacement: the entire list of tasks on the route start is replaced with the task templates provided in the request body, so existing tasks not included in the request will be removed. Task and item IDs are always regenerated by the server, and any existing completion state, input, or timestamps are cleared, since only the driver (via the driver app) can mark a task or item complete or provide input. The route must not be archived. The response returns the full updated route.
**Endpoints:** `PUT /routes/{routeId}/start/tasks`
- **Added:** Added the PUT /routes/{routeId}/start/tasks endpoint.
**Tags:** Routes
#### Update imported stop items
Updates the items on an existing imported stop by ID. This is a full replacement of the item list and supports both the EasyRoutes ID or a client-provided ID.
**Endpoints:** `PUT /stops/imports/{id}/items`
- **Added:** Added the PUT /stops/imports/{id}/items endpoint to allow full replacement of items on an imported stop record.
**Tags:** Stops
---
## July 24, 2026 - rev 3a7e902
### Endpoint changes
#### Update imported stop
Updates top-level fields on an existing imported stop by ID without requiring a full payload. This partial update applies only the fields specified in the update mask.
**Endpoints:** `PATCH /stops/imports/{id}`
- **Added:** Added the PATCH /stops/imports/{id} endpoint to allow partial updates to imported stops using an update mask.
**Tags:** Stops
#### Update route end location
A new endpoint has been added to update the address or coordinates for a route's end location. This partial update affects distances, ETAs, and optimization status.
**Endpoints:** `PATCH /routes/{routeId}/end/location`
- **Added:** Added the PATCH /routes/{routeId}/end/location endpoint to update or set a route's end location.
**Tags:** Routes
#### Update route start location
Updates the address and/or coordinates for a route's start location by route ID. This partial update requires an updateMask for address or coordinates and results in recalculated distances and ETAs.
**Endpoints:** `PATCH /routes/{routeId}/start/location`
- **Added:** Added the PATCH /routes/{routeId}/start/location endpoint to update a route's start location address or coordinates.
**Tags:** Routes
---
## July 20, 2026 - rev 39a5531
### Schema changes
#### RouteUpdate
You can now configure additional constraints and preferences when updating a route.
- **Changed:** Added optional maxDuration property.
- **Changed:** Added optional maxStops property.
- **Changed:** Added optional maxItemCount property.
- **Changed:** Added optional maxKilograms property.
- **Changed:** Added optional avoidTolls property.
- **Changed:** Added optional avoidUTurns property.
- **Changed:** Added optional speedFactor property.
**Affected endpoints:** `PATCH /routes/{routeId}`
**Tags:** Routes
---
## July 20, 2026 - rev a2a8e35
### Endpoint changes
#### Update route
Updates top-level fields on a route by route ID. This is a partial update: provide the fields to change in `route` and list their paths in `updateMask`. Only the paths listed in `updateMask` are applied; omitted fields are left unchanged. The route must not be archived. The response returns the full updated route.
**Endpoints:** `PATCH /routes/{routeId}`
- **Added:** Added the UpdateRoute endpoint to allow partial updates to route fields using a PATCH request.
**Tags:** Routes
---
## July 17, 2026 - rev e45bc94
### Schema changes
#### Route
Access new route constraints and routing preferences.
- **Changed:** Added maxDuration to specify the maximum allowed time for a route.
- **Changed:** Added maxStops to limit the number of stops on a route.
- **Changed:** Added maxItemCount to define the maximum number of items allowed.
- **Changed:** Added maxKilograms to set the maximum weight capacity.
- **Changed:** Added avoidTolls to indicate if toll roads should be bypassed.
- **Changed:** Added avoidUTurns to indicate if U-turns should be restricted.
- **Changed:** Added speedFactor to adjust travel time calculations.
**Affected endpoints:** `GET /routes`, `POST /routes`, `GET /routes/{id}`, `POST /routes/{id}/reoptimize`, `DELETE /routes/{routeId}/dispatch`, `POST /routes/{routeId}/dispatch`, `DELETE /routes/{routeId}/driver`, `PUT /routes/{routeId}/driver`, `POST /routes/{routeId}/stops`, `DELETE /routes/{routeId}/stops/{stopIds}`, `PUT /routes/{routeId}/stops/{stopId}/position`
**Tags:** Routes, Stops
---
## July 16, 2026 - rev 702a824
### Endpoint changes
#### Update route stop tasks
Updates the tasks for an imported stop on a route. Allows you to set or replace the list of driver tasks for a stop that was previously imported via ImportStops.
**Endpoints:** `PUT /routes/{routeId}/stops/{stopId}/tasks`
- **Added:** Added the PUT /routes/{routeId}/stops/{stopId}/tasks endpoint to allow full replacement of driver tasks for imported stops.
**Tags:** Stops
#### Imported stops
Retrieve a list of imported stop locations.
**Endpoints:** `GET /stops/imports`
- **Breaking:** The limit parameter now requires a minimum value of 1.
**Tags:** Stops
---
## July 14, 2026 - rev ef74bb4
### Schema changes
#### Route
Access route-level tags and default stop durations.
- **Changed:** Added optional tags to the Route.
- **Changed:** Added an optional default stop duration.
**Affected endpoints:** `GET /routes`, `POST /routes`, `GET /routes/{id}`, `POST /routes/{id}/reoptimize`, `DELETE /routes/{routeId}/dispatch`, `POST /routes/{routeId}/dispatch`, `DELETE /routes/{routeId}/driver`, `PUT /routes/{routeId}/driver`, `POST /routes/{routeId}/stops`, `DELETE /routes/{routeId}/stops/{stopIds}`, `PUT /routes/{routeId}/stops/{stopId}/position`
**Tags:** Routes, Stops
---
## July 14, 2026 - rev 7d39caf
### Schema changes
#### Route
You can now view additional notes associated with your routes.
- **Changed:** Includes an optional note.
**Affected endpoints:** `GET /routes`, `POST /routes`, `GET /routes/{id}`, `POST /routes/{id}/reoptimize`, `DELETE /routes/{routeId}/dispatch`, `POST /routes/{routeId}/dispatch`, `DELETE /routes/{routeId}/driver`, `PUT /routes/{routeId}/driver`, `POST /routes/{routeId}/stops`, `DELETE /routes/{routeId}/stops/{stopIds}`, `PUT /routes/{routeId}/stops/{stopId}/position`
**Tags:** Routes, Stops
# Field Masks (https://docs.roundtrip.ai/docs/concepts/field-masks)
A **field mask** tells the EasyRoutes API which fields of a resource you want to update on a partial update (`PATCH`) request. Only the fields listed in the mask are written; all other fields on the resource are left unchanged.
Under the hood, EasyRoutes field masks are [`google.protobuf.FieldMask`](https://protobuf.dev/reference/protobuf/google.protobuf/#field-mask) values exchanged as JSON.
## Wire format [#wire-format]
In JSON requests, a field mask is sent as a **single string** containing a comma-separated list of field paths.
```json
{
"updateMask": "note,tags"
}
```
Each path is a `lowerCamelCase` field name on the **update payload** for the request (for example, on the `routeStop` object for `PATCH /routes/{routeId}/stops/{stopId}`), **not** on the request envelope.
EasyRoutes' field masks are intentionally minimal — only the literal field names listed in the endpoint's update payload are accepted. The `*` wildcard, nested path prefixes, and dotted sub-field paths are **not supported at this time**.
## Semantics [#semantics]
| Mask contents | Result |
| ------------------------------ | ---------------------------------------------------------------------------------- |
| Path is listed | The corresponding field on the payload replaces the current value on the resource. |
| Path is omitted | The current value on the resource is left unchanged, even if the payload sets it. |
| Path is unknown on the payload | The request fails with HTTP `400` — Bad Request |
| Mask is missing | The request fails with HTTP `400` — Bad Request |
| Mask is present but empty | The request fails with HTTP `400` — Bad Request |
Tips:
* To clear a field, list its path in the mask and send the empty/default value (e.g. `""` for a string, `[]` for a list) in the payload.
* For repeated fields, the supplied list **replaces** the existing list rather than appending to it.
* Each endpoint enforces its own per-field validation (length limits, count limits, etc.) on the values you send for paths listed in the mask. See the endpoint reference for specifics.
## Example: updating a stop [#example-updating-a-stop]
`PATCH /routes/{routeId}/stops/{stopId}` accepts a [`RouteStopUpdate`](https://docs.roundtrip.ai/docs/api-reference/stops/patch-routes-routeId-stops-stopId.md) payload plus an `updateMask`. To update only the note on a stop and leave its tags unchanged:
```bash
curl -X PATCH \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"routeStop": {
"note": "Leave at the side door"
},
"updateMask": "note"
}' \
https://easyroutes.roundtrip.ai/api/2024-07/routes/rte-.../stops/rst-...
```
To replace the tags on the stop and clear its note in a single call:
```bash
curl -X PATCH \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"routeStop": {
"note": "",
"tags": ["fragile", "signature-required"]
},
"updateMask": "note,tags"
}' \
https://easyroutes.roundtrip.ai/api/2024-07/routes/rte-.../stops/rst-...
```
# Idempotent Requests (https://docs.roundtrip.ai/docs/concepts/idempotency)
[Idempotency](https://en.wikipedia.org/wiki/Idempotence) lets you safely retry a mutating request when a network error, timeout, or lost response leaves its result uncertain. Add an `Idempotency-Key` header, then reuse the same key and request for every retry.
EasyRoutes stores the response once the mutation succeeds. A matching retry returns that stored response instead of running the operation again, preventing duplicate resources, updates, and side effects such as webhooks.
## Send an idempotency key [#send-an-idempotency-key]
Idempotency keys are optional on supported authenticated `POST`, `PUT`, `PATCH`, and `DELETE` requests; each supported endpoint lists the `Idempotency-Key` header on its API reference page. Keys are ignored on `GET` and `HEAD` and by `POST /authenticate`.
Generate a new key for each operation — a UUID v4 or another random value with enough entropy to avoid collisions.
```http
Idempotency-Key: 550e8400-e29b-41d4-a716-446655440000
```
An idempotency key:
* Must be between 1 and 255 characters.
* Must not contain sensitive information, such as customer details, email addresses, or API credentials.
* Must only be reused with the same API operation and request parameters.
Keys are scoped to your organization and API client, but treat each key as unique within your integration.
## How EasyRoutes matches your key [#how-easyroutes-matches-your-key]
EasyRoutes matches the key against the API operation and its parsed request — path, query, and body. Because the parsed request is compared, differences in JSON whitespace or object key order don't matter.
| Your request | What you get back |
| -------------------------------------- | --------------------------------------------------------------------------------------------------------- |
| First request | Reserves the key and runs the operation. The response and mutation are saved together only on success. |
| Retry after success | Doesn't run again. Returns HTTP `200` with the stored response and `Idempotency-Replayed: true`. |
| Retry while the first is still running | Returns HTTP `409` `idempotent request already in progress`. Wait, then retry the same request and key. |
| Same key, different request | Returns HTTP `400` `cannot reuse key for different request`. Send the original request, or use a new key. |
Only successful responses are stored. Validation failures, server errors, and rolled-back mutations aren't replayed, and the key is freed so you can retry.
## Example: safely retrying a route creation [#example-safely-retrying-a-route-creation]
The following request creates a route with an idempotency key. Replace `YOUR_ACCESS_TOKEN` with the token returned by `POST /authenticate`. Generate the key once, persist it alongside your operation, and reuse that exact value on every retry.
**cURL**
```sh
# Generate once (e.g. `uuidgen`), persist it, and reuse it on every retry.
curl -X POST \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: 550e8400-e29b-41d4-a716-446655440000" \
-d '{
"start": {
"address": {
"address1": "123 Queen St W",
"city": "Toronto",
"provinceCode": "ON",
"countryCode": "CA",
"zip": "M5H 2M9"
}
}
}' \
https://easyroutes.roundtrip.ai/api/2024-07/routes
```
**JavaScript**
```js
// Generate once (e.g. `crypto.randomUUID()`), persist it, and reuse it on every retry.
const idempotencyKey = "550e8400-e29b-41d4-a716-446655440000";
const response = await fetch(
"https://easyroutes.roundtrip.ai/api/2024-07/routes",
{
method: "POST",
headers: {
Authorization: "Bearer YOUR_ACCESS_TOKEN",
"Content-Type": "application/json",
"Idempotency-Key": idempotencyKey,
},
body: JSON.stringify({
start: {
address: {
address1: "123 Queen St W",
city: "Toronto",
provinceCode: "ON",
countryCode: "CA",
zip: "M5H 2M9",
},
},
}),
},
);
```
**Go**
```go
package main
import (
"bytes"
"net/http"
)
func main() {
// Generate once (e.g. `uuid.NewString()`), persist it, and reuse it on every retry.
const idempotencyKey = "550e8400-e29b-41d4-a716-446655440000"
body := []byte(`{
"start": {
"address": {
"address1": "123 Queen St W",
"city": "Toronto",
"provinceCode": "ON",
"countryCode": "CA",
"zip": "M5H 2M9"
}
}
}`)
req, err := http.NewRequest(
http.MethodPost,
"https://easyroutes.roundtrip.ai/api/2024-07/routes",
bytes.NewReader(body),
)
if err != nil {
panic(err)
}
req.Header.Set("Authorization", "Bearer YOUR_ACCESS_TOKEN")
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Idempotency-Key", idempotencyKey)
resp, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
}
```
**Python**
```python
import requests
# Generate once (e.g. `uuid.uuid4()`), persist it, and reuse it on every retry.
idempotency_key = "550e8400-e29b-41d4-a716-446655440000"
response = requests.post(
"https://easyroutes.roundtrip.ai/api/2024-07/routes",
headers={
"Authorization": "Bearer YOUR_ACCESS_TOKEN",
"Content-Type": "application/json",
"Idempotency-Key": idempotency_key,
},
json={
"start": {
"address": {
"address1": "123 Queen St W",
"city": "Toronto",
"provinceCode": "ON",
"countryCode": "CA",
"zip": "M5H 2M9",
},
},
},
)
```
If the response is lost, repeat the request with the same key — don't generate a new one, since the original might already have committed. If it did, EasyRoutes returns the stored response without creating another route:
```http
HTTP/1.1 200 OK
Idempotency-Key: 550e8400-e29b-41d4-a716-446655440000
Idempotency-Replayed: true
Content-Type: application/json
```
Successful responses echo the `Idempotency-Key`. `Idempotency-Replayed: true` appears only on a stored response, never the first.
## Failure cases [#failure-cases]
How you respond depends on whether the operation might have committed:
| Failure | What happened | What to do |
| -------------------------------------------------------- | ---------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------ |
| Connection failure, timeout, or lost response | Outcome unknown — the operation might have committed without returning a response. | Retry unchanged with the same key. It replays if committed, otherwise runs safely. |
| HTTP `409` with `idempotent request already in progress` | An earlier request with the same key is still being processed. | Wait, then retry unchanged with the same key. |
| Transient HTTP `5xx` | No successful response, so nothing was stored and the key is freed. | Retry unchanged with the same key using exponential backoff and jitter. |
| Validation or other correctable `4xx` error | The operation didn't run and nothing is stored for replay. | Correct the request and retry. Reuse the key, or use a new one. |
| HTTP `400` with `cannot reuse key for different request` | The key is already tied to different parameters or another operation. | Send the original request with that key, or use a new key for the different request. |
| HTTP `400` for an invalid key | The key is empty, over 255 characters, or otherwise invalid. Nothing is stored. | Fix the key and retry. |
Never change a request while its outcome is unknown. If the first attempt committed, changing parameters but keeping the key returns a key-reuse error; changing both can run a second mutation.
## Retry safely [#retry-safely]
A retry strategy for mutating requests:
1. Generate and persist a key before the first attempt.
2. Send the request with that key.
3. On a connection failure, timeout, `409`, or transient `5xx`, retry with the **same key and unchanged request** using exponential backoff with jitter.
4. On `cannot reuse key for different request`, resend the original request or use a new key for the new operation.
5. Stop after a reasonable limit, keeping the key with your operation record for troubleshooting.
Never replace the key just because a response was lost or a transient error occurred — it breaks the link to the first attempt and can run the operation twice.
## Retention [#retention]
EasyRoutes retains completed idempotency records for at least 24 hours. After that, reusing a key is treated as a new request and can run the operation again, so always generate new keys for new operations.
# Getting Started (https://docs.roundtrip.ai/docs/getting-started)
This guide walks you through getting API access, authenticating, and making your first API call. By the end, you'll have retrieved your routes via the API.
**What you'll need:**
* An active EasyRoutes paid plan (Shopify or Web)
* Admin access to EasyRoutes settings
* A way to make HTTP requests (terminal, Postman, etc.)
## Set up API client ID and secret key [#set-up-api-client-id-and-secret-key]
API access is included with every EasyRoutes paid plan. To generate your credentials:
1. Go to **Settings > API** and add a developer contact email.
2. Click **Generate API Key**.
You'll receive two values:
| Credential | Description |
| ------------ | ---------------------------------------------------- |
| `Client ID` | Always visible in settings. Identifies your account. |
| `Secret key` | **Shown only once.** Copy and store it securely. |
Note: the `Secret key` is **only available immediately after it is generated.** The secret key should be copied and stored in a secure location. If you lose your secret key, you'll need to rotate it (see [Rotating secrets](#rotating-secrets) below).
## Authenticating and making requests [#authenticating-and-making-requests]
See our [EasyRoutes API Reference](https://docs.roundtrip.ai/docs/api-reference.md) for full API documentation.
To get started, exchange your client ID and secret key for a short-lived access token using the `/authenticate` endpoint. Replace the placeholder values with the credentials you generated in **Settings > API**.
```sh
curl -X POST \
-H "Content-Type: application/json" \
-d '{
"clientId": "your-client-id",
"clientSecret": "your-secret-key"
}' \
https://easyroutes.roundtrip.ai/api/2024-07/authenticate
```
The response includes an access token and its lifetime:
```json
{
"accessToken": "eyJ...",
"expiresInSeconds": "3600",
"organization": "your-organization"
}
```
Copy the `accessToken` value into an environment variable before making authenticated requests:
```sh
export EASYROUTES_ACCESS_TOKEN="paste-access-token-here"
```
`expiresInSeconds` tells you how long the access token remains valid. Cache the token and authenticate again before it expires.
Refer to [Authenticate API](https://docs.roundtrip.ai/docs/api-reference/authentication/post-authenticate.md) for details.
## Rotating secrets [#rotating-secrets]
Forgot your secret key? If you have forgotten your secret key, you can initiate a key rotation to generate a new one. During the rotation, **both** the old key and the newly generated one will be valid for API authentication.
Once again, the new secret key is **only viewable immediately after you generate it**. Please copy and store it in a secure location before completing the rotation! Once you have migrated clients to the new key, click the **Finish rotation** button to disable the old key. You can also cancel the rotation at any time to disable the new key instead.
## Make your first API call [#make-your-first-api-call]
Use the access token to retrieve a list of [recent routes:](https://docs.roundtrip.ai/docs/api-reference/routes/get-routes.md)
```sh
curl -sS -H "Authorization: Bearer $EASYROUTES_ACCESS_TOKEN" \
'https://easyroutes.roundtrip.ai/api/2024-07/routes?query.sortKey=UPDATED_AT&query.limit=10'
```
## What's next? [#whats-next]
Now that you're authenticated, here's what you can do:
| Goal | API |
| ------------------------------------------ | ------------------------------------------------------------------------- |
| Import orders from external systems | [ImportStops endpoint](https://docs.roundtrip.ai/docs/api-reference/stops/post-stops-imports.md) |
| Get notified when deliveries complete | [Webhooks API](https://docs.roundtrip.ai/docs/webhooks.md) |
| Access stop-level data (POD, status, etc.) | [ListRoutes or GetRoute endpoints](https://docs.roundtrip.ai/docs/api-reference/routes/get-routes.md) |
| Connect to Zapier without code | [Zapier integration](https://zapier.com/apps/easyroutes/integrations) |
## Documentation [#documentation]
Now that you have set up your initial API access, learn more about our API below and view our docs:
* [Developer Overview](https://docs.roundtrip.ai/docs.md) - this guide provides a high-level overview to help you get started building integrations with EasyRoutes as a developer.
* [API Reference Guide](https://docs.roundtrip.ai/docs/api-reference.md) - learn how to add stops into EasyRoutes for route planning and access route and stop data
* [Webhooks Guide](https://docs.roundtrip.ai/docs/webhooks.md) - learn how to use our webhooks to react to real-time changes in routes and stops for integrations or connect with Zapier to integrate with no-code workflows
## Zapier Integrations [#zapier-integrations]
You can use our API with Zapier to unlock seamless no-code workflows with your favorite apps and services, triggered by route updates in EasyRoutes or by stops imported from your own data sources.
* [Import Stops Action](https://zapier.com/apps/easyroutes/integrations) - You can [Import stops](https://docs.roundtrip.ai/docs/api-reference/stops/post-stops-imports.md) into EasyRoutes for planning with our [Import Stop action on Zapier](https://zapier.com/apps/easyroutes/integrations).
* Integrate with route- and stop-level updates with our [Route Updated & Stop Status Updated Zapier triggers](https://zapier.com/apps/easyroutes/integrations).
* Design custom workflows to suit your specific needs - see our [Common Zapier Integrations](https://support.roundtrip.ai/article/671-common-zapier-integrations) support article for examples and workflows.
# Overview (https://docs.roundtrip.ai/docs)
EasyRoutes is a route optimization and delivery management platform for last-mile delivery, built for e-commerce businesses. The API lets you integrate EasyRoutes with your existing systems — import orders, create and manage routes, assign and dispatch drivers, and react to delivery events in real time.
***
## What you can do [#what-you-can-do]
| Task | How |
| ----------------------------------------- | ----------------------------------------------------------------------------------------------- |
| Import and list external orders | `POST /stops/imports`, `GET /stops/imports` |
| Retrieve or delete an import | `GET /stops/imports/{stopId}`, `DELETE /stops/imports/{stopId}` |
| See routes containing an imported stop | `GET /stops/imports/{stopId}/routes` |
| Create, list, or retrieve routes | `POST /routes`, `GET /routes`, `GET /routes/{routeId}` |
| Add or remove stops on a route | `POST /routes/{routeId}/stops`, `DELETE /routes/{routeId}/stops/{stopIds}` |
| Retrieve or update a route stop | `GET /routes/{routeId}/stops/{stopId}`, `PATCH /routes/{routeId}/stops/{stopId}` |
| Update a route stop's items or location | `PUT /routes/{routeId}/stops/{stopId}/items`, `PATCH /routes/{routeId}/stops/{stopId}/location` |
| Reorder a route stop | `PUT /routes/{routeId}/stops/{stopId}/position` |
| Reoptimize a route | `POST /routes/{routeId}/reoptimize` |
| Assign or unassign a driver | `PUT /routes/{routeId}/driver`, `DELETE /routes/{routeId}/driver` |
| Dispatch or undispatch a route | `POST /routes/{routeId}/dispatch`, `DELETE /routes/{routeId}/dispatch` |
| Look up routes by Shopify order | `GET /stops/shopify/{orderId}/routes` |
| List or retrieve driver information | `GET /drivers`, `GET /drivers/{driverId}` |
| Create, list, or delete webhook endpoints | `POST /webhooks`, `GET /webhooks`, `DELETE /webhooks/{webhookId}` |
| React to delivery events | [Webhooks](https://docs.roundtrip.ai/docs/webhooks.md) |
| Connect to Zapier (no code) | [Zapier integration](https://zapier.com/apps/easyroutes/integrations) |
***
## Core concepts [#core-concepts]
### Routes [#routes]
A planned sequence of stops for a driver on a given day. Includes start/end locations, assigned driver, optimization status, and dispatch status (`dispatchedUntil` indicates when the current dispatch expires).
ID format: `rte-xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx`
### Route Stops [#route-stops]
Individual deliveries on a route. Contains address, customer info, delivery status, and proof of delivery (photos, signature, notes).
ID format: `rst-xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx`
### Imported Stops [#imported-stops]
Orders you've sent to EasyRoutes via API that haven't been added to a route yet. They appear in your Orders page, ready for route planning.
ID format: `ist-xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx`
### Drivers [#drivers]
Team members who deliver routes. Includes contact info and current status.
ID format: `drv-xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx`
### Webhooks [#webhooks]
Real-time notifications when things happen — routes dispatched, stops delivered, drivers updated. Register webhooks in **Settings > API**.
***
## Authentication [#authentication]
1. Get your **Client ID** and **Secret** from Settings > API
2. Exchange them for an access token via `POST /authenticate`
3. Include the token in all requests: `Authorization: Bearer {token}`
Tokens expire after 1 hour. See the [Getting Started guide](https://docs.roundtrip.ai/docs/getting-started.md) for details.
***
## Base URL [#base-url]
The API uses date-based major versioning. New endpoints and improvements ship as backwards-compatible additions to the current major version. If a future change would break existing integrations, it will ship under a new major version.
```
https://easyroutes.roundtrip.ai/api/2024-07/
```
***
## Common workflows [#common-workflows]
### Build and dispatch a route end-to-end [#build-and-dispatch-a-route-end-to-end]
1. Authenticate
2. `POST /stops/imports` with your order data
3. `POST /routes` to create a route with start/end locations and optional constraints (max duration, max stops, max weight, toll/U-turn avoidance)
4. `POST /routes/{id}/stops` to add imported stops to the route
5. `POST /routes/{id}/reoptimize` to optimize stop ordering
6. `PUT /routes/{id}/driver` to assign a driver
7. `POST /routes/{id}/dispatch` to dispatch the route to the driver
### Working with Shopify orders [#working-with-shopify-orders]
The workflow above applies to orders imported via the API. If you're using EasyRoutes' native Shopify integration, orders sync automatically — add them to routes in the app or use Workflows to assign them automatically. Once on a route, you can manage that route entirely via the API (assign drivers, dispatch, reoptimize, read delivery status, etc.).
If you need full programmatic control over Shopify orders, you can also import them as imported stops using `POST /stops/imports` with a `clientStopId` (e.g. the Shopify order ID or order number) to maintain the link between systems, and use webhooks to sync delivery status back. This gives you more flexibility but means you own the integration.
### Import orders and let Workflows handle the rest [#import-orders-and-let-workflows-handle-the-rest]
1. Authenticate
2. `POST /stops/imports` with your order data
3. Stops appear in EasyRoutes Orders page
4. Workflows automatically assign them to routes on creation
### Sync delivery status to your system [#sync-delivery-status-to-your-system]
1. Register a webhook for `STOP_STATUS_UPDATED`
2. When a stop is delivered, you receive the event
3. Update your order management system
### Track proof of delivery [#track-proof-of-delivery]
1. Subscribe to `STOP_UPDATED` webhook
2. Access photos, signatures, and notes from the payload
3. Store or display in your system
### Reoptimize an in-progress route [#reoptimize-an-in-progress-route]
1. `POST /routes/{id}/reoptimize` with `ignoreCompletedStops: true` to skip delivered/attempted stops
2. Optionally set `ignoreRoutingConstraints: true` to override max duration, weight, and other constraints during reoptimization
***
## Best Practices [#best-practices]
Consider the following when building solutions or integrations with the EasyRoutes API.
### Security [#security]
* **Store credentials securely**: Never commit API keys to version control
* **Use HTTPS**: All API requests must use HTTPS
* **Rotate tokens**: Implement token refresh logic before expiration (tokens expire after 1 hour)
* **Validate webhooks**: Verify webhook signatures using HMAC-SHA256 (sent in `X-EasyRoutes-Hmac-Sha256` header)
### Performance [#performance]
* **Cache access tokens**: Reuse tokens until they expire (1 hour)
* **Batch operations**: Import or add multiple stops in a single request when possible
* **Use webhooks**: Prefer event-driven updates over polling
* **Implement pagination**: Don't request all records at once
### Reliability [#reliability]
* **Idempotent imports**: Use `clientStopId` when importing stops — existing stops with the same ID will be replaced instead of duplicated
* **Reoptimize after changes**: After adding or removing stops, call `ReoptimizeRoute` — the route is not automatically reoptimized
* **Retry logic**: Use [idempotency keys](https://docs.roundtrip.ai/docs/concepts/idempotency.md) and exponential backoff when retrying mutations
* **Monitor webhooks**: Track webhook delivery success and implement retry logic for failed deliveries
* **Validate inputs**: Check data constraints before sending requests
* **Log requests**: Maintain request/response logs for debugging
### Data Quality [#data-quality]
* **Geocode addresses**: Ensure stops have valid addresses that can be matched to a geolocation
* **Structured phone numbers**: When inputting phone numbers, ensure they are in the expected E.164 format
* **Use custom IDs**: Include your order IDs in the `clientStopId` field for reference and idempotent updates
* **Add metadata**: Use tags and attributes for filtering and reporting, and add a delivery date or time window if those constraints are required for route planning.
***
## Data formats [#data-formats]
**Timestamps:** RFC3339 with timezone — `"2024-12-15T14:30:00Z"`
**Durations:** Seconds as string — `"300s"` (5 minutes)
**Coordinates:**
```
{ "latitude": 43.6532, "longitude": -79.3832 }
```
**Addresses:**
```
{
"address1": "123 Queen St W",
"city": "Toronto",
"provinceCode": "ON",
"countryCode": "CA",
"zip": "M5H 2M9"
}
```
***
## Error handling [#error-handling]
| Status | Meaning |
| ------ | --------------------------------------- |
| `200` | Success |
| `400` | Bad request — check your input |
| `401` | Unauthorized — invalid or expired token |
| `404` | Resource not found |
| `429` | Rate limited — slow down |
| `500` | Server error — contact support |
Error responses include a `message` field explaining what went wrong.
***
## Pagination [#pagination]
List endpoints return up to 20 items by default. Use cursor-based pagination for more:
```
GET /routes?query.limit=20&cursor=eyJsYXN0X2lkIjoiMTIzIn0=
```
Response includes `nextCursor` — pass it in subsequent requests.
***
## Next steps [#next-steps]
| Goal | Resource |
| ------------------------------------------- | ----------------------------------------------------------------------------------------- |
| Set up credentials and make your first call | [Getting Started Guide](https://docs.roundtrip.ai/docs/getting-started.md) |
| See all endpoints | [API Reference Guide](https://docs.roundtrip.ai/docs/api-reference.md) |
| Set up real-time events | [Webhooks Guide](https://docs.roundtrip.ai/docs/webhooks.md) |
| Build no-code workflows | [Zapier Integration](https://support.roundtrip.ai/article/705-building-an-easyroutes-zap) |
# Webhooks Guide (https://docs.roundtrip.ai/docs/webhooks)
EasyRoutes webhooks allow you to receive events programmatically in response to changes in your routes, stops, drivers, and imported stops. In combination with using the [EasyRoutes API](https://docs.roundtrip.ai/docs/getting-started.md), webhook events allow you to build powerful automation triggered by deliveries, route updates, or other events.
**What you'll need:**
* An active EasyRoutes paid plan and API credentials ([see Getting Started Guide](https://docs.roundtrip.ai/docs/getting-started.md))
* A server with an HTTPS endpoint that can receive POST requests
* Familiarity with HMAC signature verification (optional but recommended)
## Common use cases [#common-use-cases]
| Goal | Subscribe to |
| ---------------------------------------------- | ------------------------------------------------ |
| Update your system when a delivery completes | `STOP_STATUS_UPDATED` |
| Sync proof of delivery photos to your system | `STOP_UPDATED` |
| Know when a driver starts their route | `ROUTE_STARTED` |
| Track when routes are dispatched | `ROUTE_DISPATCHED` |
| Sync imported stops back to your source system | `IMPORTED_STOP_CREATED`, `IMPORTED_STOP_UPDATED` |
**Prefer no-code?** Set up Zaps based on route- and stop-level updates using our [Route Updated & Stop Status Updated Zapier triggers](https://zapier.com/apps/easyroutes/integrations), which interface directly with our Webhooks API. Check out some [common Zapier Integrations](https://support.roundtrip.ai/article/671-common-zapier-integrations).
## Register a webhook endpoint [#register-a-webhook-endpoint]You can register webhook endpoints in EasyRoutes Settings or through the API.### Register in Settings [#register-in-settings]Go to **EasyRoutes Settings > API** and click **Register webhook**.
Configure:
- **URL**: Your HTTPS endpoint (e.g., `https://yourserver.com/webhooks/easyroutes`)
- **API version**: Determines the payload format
- **Topics**: Which events to receive (see [Webhook topics](#webhook-topics) below)Creating your first webhook generates a **Webhook secret** — you'll use this to verify requests are from EasyRoutes. See [Verifying webhook requests](#verifying-webhook-requests) for details on how to secure your endpoint.### Register with the API [#register-with-the-api]After [authenticating](https://docs.roundtrip.ai/docs/getting-started.md), send a `POST` request to `/webhooks` with your public HTTPS URL and the topics to receive:```sh
curl -X POST \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"url": "https://yourserver.com/webhooks/easyroutes",
"topics": ["STOP_STATUS_UPDATED", "ROUTE_DISPATCHED"]
}' \
https://easyroutes.roundtrip.ai/api/2024-07/webhooks
```The response contains the subscription ID, URL, selected topics, and whether the subscription is active. Use `GET /webhooks` to list subscriptions and `DELETE /webhooks/{id}` to remove one. Your webhook secret remains available in **EasyRoutes Settings > API** and is distinct from your API secret key.## Build a webhook handler [#build-a-webhook-handler]To receive webhooks, you need to:- Accept `POST` webhook requests on an HTTPS endpoint or server
* Relevant webhook metadata like the topic and affected object ID are sent via headers as well as in the JSON body of the request.
* The affected object is sent in the `payload` field of the body. Its type depends on the topic: `Route` for route and route-stop events, `Driver` for driver events, and `ImportedStop` for imported-stop events. The `TEST` topic has no payload.
* See [Webhook event overview](#webhook-event-overview) below for details on the request format.
- Return a successful status code (`2xx`) to acknowledge the webhook **quickly** (within 10 seconds).
* Avoid doing any complex logic that could cause a timeout synchronously in your endpoint handler.
- (Recommended) Verify the HMAC signature — see below.### Webhook event overview [#webhook-event-overview]All EasyRoutes webhook requests share a set of common fields, regardless of API version. These fields are serialized in a JSON payload in the body of the `POST` request.| Field | Description | Example |
| ------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `eventId` | The unique ID of the webhook event. In rare cases of duplicate webhook delivery, this can be used to deduplicate work. | `"evt-fa75b82d-2411-4cf8-b15f-cf3d8c91e919"` |
| `topic` | Topic of the webhook. See [Webhook topics](#webhook-topics) for a list of supported topics. | `"ROUTE_UPDATED"` |
| `eventTimestamp` | The timestamp of the event that triggered the webhook. | `"2024-08-23T16:12:26-04:00"` |
| `apiVersion` | The API version of the payload object. | `"V2024_07"` |
| `shopifyShop` (optional) | The Shopify shop connected to EasyRoutes (Shopify only) | `"easyroutes.myshopify.com"` |
| `organization` (optional) | The unique organization identifier for EasyRoutes for Web | `"roundabout-supply-co-a5c2"` |
| `objectId` (optional) | The ID of the affected object. For route-stop events, this is the route-stop ID even though `payload` is the containing `Route`. | `"rst-6ffc8a79-e556-4ca4-9246-33850da3cedc"` |
| `user` | User that triggered the event. The field is structured and different fields are populated for different update scenarios. For EasyRoutes in Shopify, this corresponds to the `shopifyUserId` of the [Shopify admin user](https://help.shopify.com/en/manual/your-account/users/invite-users) for your store that took the action. For EasyRoutes for Web users, this corresponds to the `email` of the authenticated member who made the update. For driver-initiated actions, the `driverId` is populated with the driver's ID (matching the API format). All kinds of webhooks may also include an `ipAddress` and `userAgent` of the initiating user (if available). | EasyRoutes for Shopify update: `{"shopifyUserId": "96343753011"}` EasyRoutes for Web update: `{"email":"john.doe@roundtrip.ai"}` Driver update: `{"driverId":"drv-cb93e344-fb1d-4d34-b8a8-8df5cdd9e939"}` Example with IP address and user agent: `{"ipAddress": "37.19.211.58", "userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/135.0.0.0 Safari/537.36"}` |
| `payload` (optional) | The affected object. It is a `Route` for route and route-stop topics, a `Driver` for driver topics, and an `ImportedStop` for imported-stop topics. The `TEST` topic has no payload. | `{"id":"rte-...", "name":"#878", "start":{...}, ...}` |Sample:```
{
"eventId": "evt-fa75b82d-2411-4cf8-b15f-cf3d8c91e919",
"topic": "STOP_STATUS_UPDATED",
"eventTimestamp": "2024-08-23T16:12:26-04:00",
"apiVersion": "V2024_07",
"objectId": "rst-abc123",
"payload": {
"id": "rte-6ffc8a79-e556-4ca4-9246-33850da3cedc",
"name": "Monday AM Route",
"stops": [...]
}
}
```Additionally, some of the metadata fields are mirrored in HTTP headers for convenience.- `X-EasyRoutes-Event-Id`
- `X-EasyRoutes-Topic`
- `X-EasyRoutes-Event-Timestamp`
- `X-EasyRoutes-Version`
- `X-EasyRoutes-Shopify-Shop`
- `X-EasyRoutes-Organization`
- `X-EasyRoutes-Object-Id`### Verifying webhook requests [#verifying-webhook-requests]EasyRoutes webhooks are signed using your unique `Webhook secret` from Settings. The HMAC SHA256 hash is sent in the webhook request via the `X-EasyRoutes-Hmac-Sha256` header. To verify that requests are sent by EasyRoutes, compute your own signature from the request body and verify it against the header signature.**Note**: your webhook secret is distinct from your API secret key and is always available on the Settings page.### Example webhook endpoint [#example-webhook-endpoint]Here is an example endpoint implemented in Go:```go
package main
import (
"crypto/hmac"
"crypto/sha256"
"encoding/base64"
"encoding/json"
"io"
"log"
"net/http"
)
// Webhook secret key example.
// Not recommended to hardcode!
const easyroutesSecret = "PjV...w=="
type Event struct {
EventId string `json:"eventId"`
Topic string `json:"topic"`
EventTimestamp string `json:"eventTimestamp"`
ApiVersion string `json:"apiVersion"`
ObjectId string `json:"objectId,omitempty"`
Payload []byte `json:"payload,omitempty"`
}
func main() {
http.HandleFunc("/webhook", func(w http.ResponseWriter, r *http.Request) {
b, err := io.ReadAll(r.Body)
if err != nil {
log.Printf("error reading webhook body: %v", err)
w.WriteHeader(http.StatusServiceUnavailable)
return
}
sig := r.Header.Get("X-EasyRoutes-Hmac-Sha256")
if len(sig) == 0 {
log.Printf("missing signature header")
w.WriteHeader(http.StatusBadRequest)
return
}
d, err := base64.StdEncoding.DecodeString(easyroutesSecret)
if err != nil {
log.Fatalf("error decoding secret: %v", err)
}
enc := hmac.New(sha256.New, d)
enc.Write(b)
expected := enc.Sum(nil)
actual, err := base64.StdEncoding.DecodeString(sig)
if err != nil {
log.Printf("error decoding signature: %v", err)
w.WriteHeader(http.StatusBadRequest)
return
}
if !hmac.Equal(expected, actual) {
log.Printf(
"signature mismatch, expected=%s, actual=%s",
base64.StdEncoding.EncodeToString(expected),
base64.StdEncoding.EncodeToString(actual),
)
w.WriteHeader(http.StatusBadRequest)
return
}
parsed := &Event{}
err = json.Unmarshal(b, parsed)
if err != nil {
log.Printf("error parsing webhook body: %v", err)
w.WriteHeader(http.StatusBadRequest)
return
}
switch parsed.Topic {
case "ROUTE_CREATED":
// process event here
}
w.WriteHeader(http.StatusOK)
})
http.ListenAndServe(":8080", nil)
}
```## Testing your webhook [#testing-your-webhook]Once you've built your webhook endpoint and registered it in EasyRoutes, you can send a test event (`topic` = `TEST`) to verify everything is working as expected.
If your endpoint returns `2xx`, you're ready.
***
## Webhook topics [#webhook-topics]
| Topic | Description | Payload type |
| -------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------ |
| `TEST` | Test topic generated when testing webhooks from settings. | none |
| `ROUTE_CREATED` | New route created. | `Route` |
| `ROUTE_UPDATED` | Route updated by planner (i.e. stop order changed, start time, etc) | `Route` |
| `ROUTE_DELETED` | Route deleted. | `Route` (deleted) |
| `ROUTE_DISPATCHED` | Route dispatched to a specific driver or available to claim. | `Route` |
| `ROUTE_STARTED` | Route started by driver. | `Route` |
| `ROUTE_COMPLETED` | Route completed by driver. For a route that ends at the last stop, this is triggered when all stops are complete (attempted or delivered). For a route with an explicit end stop, this is triggered when the route is marked complete. | `Route` |
| `ROUTE_START_STOP_UPDATED` | The start stop on the route was updated. This may correspond to the driver completing tasks or entering input on the start task. | `Route` |
| `ROUTE_END_STOP_UPDATED` | The end stop on the route was updated. This may correspond to the driver completing tasks or entering input on the end task. | `Route` |
| `STOP_UPDATED` | An individual route stop was updated. This includes: