> For the complete documentation index, see [llms.txt](https://docs.shortcutco.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.shortcutco.com/developers/api-reference/reference/visits.md).

# Visits

One stop on the schedule: a job's work on one date.

A visit is a job's work for one customer on one date, done by a crew. Visits are assigned, rescheduled, skipped, canceled, and completed here.

Fields: [The visit object](https://docs.shortcutco.com/developers/reference/objects/visit) · [The visit completion object](https://docs.shortcutco.com/developers/reference/objects/visit-completion).

## List visits

> Visits newest first, or by last change when \`updatedSince\` is set. \`from\` and \`to\` are dates in the workspace's timezone and are inclusive.\
> \
> Returns a list of \[visit objects]\(<https://docs.shortcutco.com/developers/reference/objects/visit>).

```json
{"openapi":"3.1.0","info":{"title":"Shortcut API","version":"v1"},"tags":[{"name":"Visits","description":"A visit is a job's work for one customer on one date, done by a crew. Visits are assigned, rescheduled, skipped, canceled, and completed here.\n\nFields: [The visit object](https://docs.shortcutco.com/developers/reference/objects/visit) · [The visit completion object](https://docs.shortcutco.com/developers/reference/objects/visit-completion)."}],"servers":[{"url":"https://api.shortcutco.com","description":"Production"}],"security":[{"bearerAuth":["visits:read"]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"scut_<env>_<id>_<secret>","description":"A workspace API token. Each operation lists the scopes it needs; `write` implies `read`, and `send`/`complete` are never implied."}},"headers":{"RateLimitLimit":{"schema":{"type":"integer"},"description":"Requests allowed in the tightest window."},"RateLimitRemaining":{"schema":{"type":"integer"},"description":"Requests left in that window."},"RateLimitReset":{"schema":{"type":"integer"},"description":"Seconds until that window resets."}},"schemas":{"Visit":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"The visit's id."},"object":{"type":"string","const":"visit","description":"Always `visit`."},"date":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"The scheduled date, `YYYY-MM-DD` in the workspace's timezone."},"status":{"type":"string","enum":["pending","scheduled","completed","canceled","rescheduled","needs_reschedule","skipped"],"description":"`scheduled` visits are on the schedule, and `rescheduled` visits were moved to this date and are on the schedule too. `pending` visits are planned but not on the schedule yet. `completed` visits are done. `needs_reschedule` visits are waiting for a new date. `skipped` and `canceled` visits are closed."},"closeReason":{"anyOf":[{"type":"string","enum":["already_handled"]},{"type":"null"}],"description":"`already_handled` when a canceled visit was closed because the work was handled outside Shortcut (the app shows it as Handled); otherwise null."},"jobId":{"type":"string","format":"uuid","description":"The job this visit belongs to."},"jobName":{"type":"string","description":"The job's name, such as `Weekly mowing`."},"customerId":{"type":"string","format":"uuid","description":"The customer the visit is for."},"propertyId":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"The property (service address), when the job has one."},"address":{"type":["string","null"],"description":"The property's street address, when the job has a property."},"assignedTeamId":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"The crew pinned to this visit. Null means the visit inherits its job's crew; read `effectiveTeamId` for the crew doing the work."},"effectiveTeamId":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"The crew doing the visit: `assignedTeamId` when set, otherwise the job's crew. Null when neither has a crew (unassigned)."},"routePosition":{"anyOf":[{"type":"integer","minimum":1},{"type":"null"}],"description":"The visit's stop number on its crew's route for the day, starting at 1. Null when the visit is not routed or has no crew."},"plannedStartAt":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"Planned start, ISO 8601 in UTC, or null."},"plannedEndAt":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"Planned end, ISO 8601 in UTC, or null."},"estimatedDurationMinutes":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Estimated time on site in minutes, when known."},"arrivedAt":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"When the crew arrived on site (read-only), ISO 8601 in UTC, or null."},"completedAt":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"When the visit was completed, ISO 8601 in UTC, or null."},"invoiceId":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"The invoice that bills this visit, once a completed visit has been billed; otherwise null."},"createdAt":{"type":"string","format":"date-time","description":"When the visit was created, ISO 8601 in UTC."},"updatedAt":{"type":"string","format":"date-time","description":"When the visit last changed, ISO 8601 in UTC."}},"required":["id","object","date","status","closeReason","jobId","jobName","customerId","propertyId","address","assignedTeamId","effectiveTeamId","routePosition","plannedStartAt","plannedEndAt","estimatedDurationMinutes","arrivedAt","completedAt","invoiceId","createdAt","updatedAt"],"additionalProperties":false,"description":"A visit: one scheduled service for a customer on one date."},"Error":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string","description":"Error family, such as `invalid_request` or `permission`."},"code":{"type":"string","description":"Specific error code; see the errors page."},"message":{"type":"string","description":"A human-readable explanation."},"param":{"type":"string","description":"The input the error is about, such as `query.limit`."},"requiredScope":{"type":"string","description":"The scope the token is missing."},"requestId":{"type":"string","description":"Quote this id to support."},"docs":{"type":"string","description":"Link to the error's documentation."}},"required":["type","code","message","requestId","docs"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}},"responses":{"BadRequest":{"description":"The request is invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Unauthenticated":{"description":"The token is missing, invalid, expired, or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"SubscriptionRequired":{"description":"The workspace's subscription needs attention.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Forbidden":{"description":"The token is missing a required scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"NotFound":{"description":"No such object in this workspace.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"RateLimited":{"description":"Rate limited; see Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"InternalError":{"description":"Internal error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Unavailable":{"description":"Temporarily unavailable; retry later.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"paths":{"/v1/visits":{"get":{"operationId":"visits.list","tags":["Visits"],"summary":"List visits","description":"Visits newest first, or by last change when `updatedSince` is set. `from` and `to` are dates in the workspace's timezone and are inclusive.\n\nReturns a list of [visit objects](https://docs.shortcutco.com/developers/reference/objects/visit).","parameters":[{"name":"limit","in":"query","required":false,"description":"How many items to return, 1-200. Defaults to 50.","schema":{"type":"integer","minimum":1,"maximum":200,"default":50}},{"name":"cursor","in":"query","required":false,"description":"The `meta.nextCursor` from the previous page. Omit it for the first page.","schema":{"type":"string","minLength":1,"maxLength":4096}},{"name":"from","in":"query","required":false,"description":"Only visits on or after this date, `YYYY-MM-DD` in the workspace's timezone.","schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"}},{"name":"to","in":"query","required":false,"description":"Only visits on or before this date, `YYYY-MM-DD` in the workspace's timezone.","schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"}},{"name":"teamId","in":"query","required":false,"description":"Only visits this crew is doing (the visit's own crew, or its job's crew when the visit has none).","schema":{"type":"string","format":"uuid"}},{"name":"status","in":"query","required":false,"description":"Only visits with this status.","schema":{"type":"string","enum":["pending","scheduled","completed","canceled","rescheduled","needs_reschedule","skipped"]}},{"name":"customerId","in":"query","required":false,"description":"Only this customer's visits.","schema":{"type":"string","format":"uuid"}},{"name":"jobId","in":"query","required":false,"description":"Only this job's visits.","schema":{"type":"string","format":"uuid"}},{"name":"updatedSince","in":"query","required":false,"description":"ISO 8601 timestamp. Returns visits changed at or after it, oldest change first. Keep the largest `updatedAt` you have seen, subtract five minutes, and pass it on the next sync; deduplicate by `id`. A visit's `updatedAt` changes only when the visit itself changes: `jobName`, `address`, `customerId`, and an inherited `effectiveTeamId` come from its job and property and do not change it, so sync jobs and properties from their own lists.","schema":{"type":"string","format":"date-time"}}],"responses":{"200":{"description":"Success.","headers":{"RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Visit"}},"meta":{"type":"object","properties":{"nextCursor":{"type":["string","null"],"description":"Pass as `cursor` to get the next page; null on the last page."},"hasMore":{"type":"boolean","description":"Whether another page exists."}},"required":["nextCursor","hasMore"],"additionalProperties":false}},"required":["data","meta"],"additionalProperties":false}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthenticated"},"402":{"$ref":"#/components/responses/SubscriptionRequired"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/Unavailable"}}}}}}
```

## Get a visit

> One visit with its date, status, crew, and times. \`effectiveTeamId\` is the crew doing the work; \`arrivedAt\` is read-only.\
> \
> Returns \[the visit object]\(<https://docs.shortcutco.com/developers/reference/objects/visit>).

```json
{"openapi":"3.1.0","info":{"title":"Shortcut API","version":"v1"},"tags":[{"name":"Visits","description":"A visit is a job's work for one customer on one date, done by a crew. Visits are assigned, rescheduled, skipped, canceled, and completed here.\n\nFields: [The visit object](https://docs.shortcutco.com/developers/reference/objects/visit) · [The visit completion object](https://docs.shortcutco.com/developers/reference/objects/visit-completion)."}],"servers":[{"url":"https://api.shortcutco.com","description":"Production"}],"security":[{"bearerAuth":["visits:read"]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"scut_<env>_<id>_<secret>","description":"A workspace API token. Each operation lists the scopes it needs; `write` implies `read`, and `send`/`complete` are never implied."}},"headers":{"RateLimitLimit":{"schema":{"type":"integer"},"description":"Requests allowed in the tightest window."},"RateLimitRemaining":{"schema":{"type":"integer"},"description":"Requests left in that window."},"RateLimitReset":{"schema":{"type":"integer"},"description":"Seconds until that window resets."}},"schemas":{"Visit":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"The visit's id."},"object":{"type":"string","const":"visit","description":"Always `visit`."},"date":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"The scheduled date, `YYYY-MM-DD` in the workspace's timezone."},"status":{"type":"string","enum":["pending","scheduled","completed","canceled","rescheduled","needs_reschedule","skipped"],"description":"`scheduled` visits are on the schedule, and `rescheduled` visits were moved to this date and are on the schedule too. `pending` visits are planned but not on the schedule yet. `completed` visits are done. `needs_reschedule` visits are waiting for a new date. `skipped` and `canceled` visits are closed."},"closeReason":{"anyOf":[{"type":"string","enum":["already_handled"]},{"type":"null"}],"description":"`already_handled` when a canceled visit was closed because the work was handled outside Shortcut (the app shows it as Handled); otherwise null."},"jobId":{"type":"string","format":"uuid","description":"The job this visit belongs to."},"jobName":{"type":"string","description":"The job's name, such as `Weekly mowing`."},"customerId":{"type":"string","format":"uuid","description":"The customer the visit is for."},"propertyId":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"The property (service address), when the job has one."},"address":{"type":["string","null"],"description":"The property's street address, when the job has a property."},"assignedTeamId":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"The crew pinned to this visit. Null means the visit inherits its job's crew; read `effectiveTeamId` for the crew doing the work."},"effectiveTeamId":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"The crew doing the visit: `assignedTeamId` when set, otherwise the job's crew. Null when neither has a crew (unassigned)."},"routePosition":{"anyOf":[{"type":"integer","minimum":1},{"type":"null"}],"description":"The visit's stop number on its crew's route for the day, starting at 1. Null when the visit is not routed or has no crew."},"plannedStartAt":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"Planned start, ISO 8601 in UTC, or null."},"plannedEndAt":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"Planned end, ISO 8601 in UTC, or null."},"estimatedDurationMinutes":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Estimated time on site in minutes, when known."},"arrivedAt":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"When the crew arrived on site (read-only), ISO 8601 in UTC, or null."},"completedAt":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"When the visit was completed, ISO 8601 in UTC, or null."},"invoiceId":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"The invoice that bills this visit, once a completed visit has been billed; otherwise null."},"createdAt":{"type":"string","format":"date-time","description":"When the visit was created, ISO 8601 in UTC."},"updatedAt":{"type":"string","format":"date-time","description":"When the visit last changed, ISO 8601 in UTC."}},"required":["id","object","date","status","closeReason","jobId","jobName","customerId","propertyId","address","assignedTeamId","effectiveTeamId","routePosition","plannedStartAt","plannedEndAt","estimatedDurationMinutes","arrivedAt","completedAt","invoiceId","createdAt","updatedAt"],"additionalProperties":false,"description":"A visit: one scheduled service for a customer on one date."},"Error":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string","description":"Error family, such as `invalid_request` or `permission`."},"code":{"type":"string","description":"Specific error code; see the errors page."},"message":{"type":"string","description":"A human-readable explanation."},"param":{"type":"string","description":"The input the error is about, such as `query.limit`."},"requiredScope":{"type":"string","description":"The scope the token is missing."},"requestId":{"type":"string","description":"Quote this id to support."},"docs":{"type":"string","description":"Link to the error's documentation."}},"required":["type","code","message","requestId","docs"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}},"responses":{"BadRequest":{"description":"The request is invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Unauthenticated":{"description":"The token is missing, invalid, expired, or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"SubscriptionRequired":{"description":"The workspace's subscription needs attention.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Forbidden":{"description":"The token is missing a required scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"NotFound":{"description":"No such object in this workspace.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"RateLimited":{"description":"Rate limited; see Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"InternalError":{"description":"Internal error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Unavailable":{"description":"Temporarily unavailable; retry later.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"paths":{"/v1/visits/{id}":{"get":{"operationId":"visits.get","tags":["Visits"],"summary":"Get a visit","description":"One visit with its date, status, crew, and times. `effectiveTeamId` is the crew doing the work; `arrivedAt` is read-only.\n\nReturns [the visit object](https://docs.shortcutco.com/developers/reference/objects/visit).","parameters":[{"name":"id","in":"path","required":true,"description":"The object's id.","schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Success.","headers":{"RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Visit"},"meta":{"type":"object","properties":{},"additionalProperties":true,"description":"Facts about this request beside the object, such as `alreadyReminded` on a repeated reminder. Present only when there is something to report."}},"required":["data"],"additionalProperties":false}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthenticated"},"402":{"$ref":"#/components/responses/SubscriptionRequired"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/Unavailable"}}}}}}
```

## Assign a visit to a crew

> Gives one scheduled visit to a crew, exactly as moving its stop to another crew in Dispatch does: the visit leaves its current crew's route, joins the end of the new crew's route for that day, and both crews are notified of the route change. Assigning the job's own crew stores no crew on the visit (it inherits the job's), so \`assignedTeamId\` reads null and \`effectiveTeamId\` the job's crew; a portion of a split visit is the exception and always stores its crew id. Another crew can't take a portion of a split visit that it already works.\
> \
> Returns \[the visit object]\(<https://docs.shortcutco.com/developers/reference/objects/visit).\\>
> \
> \*\*Errors specific to this endpoint:\*\* \[\`rule\_violation\`]\(<https://docs.shortcutco.com/developers/concepts/errors#rule\\_violation>), \[\`state\_conflict\`]\(<https://docs.shortcutco.com/developers/concepts/errors#state\\_conflict>). Every endpoint can also return the \[common errors]\(<https://docs.shortcutco.com/developers/concepts/errors>).

```json
{"openapi":"3.1.0","info":{"title":"Shortcut API","version":"v1"},"tags":[{"name":"Visits","description":"A visit is a job's work for one customer on one date, done by a crew. Visits are assigned, rescheduled, skipped, canceled, and completed here.\n\nFields: [The visit object](https://docs.shortcutco.com/developers/reference/objects/visit) · [The visit completion object](https://docs.shortcutco.com/developers/reference/objects/visit-completion)."}],"servers":[{"url":"https://api.shortcutco.com","description":"Production"}],"security":[{"bearerAuth":["visits:write"]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"scut_<env>_<id>_<secret>","description":"A workspace API token. Each operation lists the scopes it needs; `write` implies `read`, and `send`/`complete` are never implied."}},"parameters":{"IdempotencyKey":{"name":"Idempotency-Key","in":"header","required":false,"description":"Any string up to 255 characters. Retrying with the same key returns the first response instead of repeating the write, for 24 hours.","schema":{"type":"string","maxLength":255}}},"headers":{"RateLimitLimit":{"schema":{"type":"integer"},"description":"Requests allowed in the tightest window."},"RateLimitRemaining":{"schema":{"type":"integer"},"description":"Requests left in that window."},"RateLimitReset":{"schema":{"type":"integer"},"description":"Seconds until that window resets."}},"schemas":{"Visit":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"The visit's id."},"object":{"type":"string","const":"visit","description":"Always `visit`."},"date":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"The scheduled date, `YYYY-MM-DD` in the workspace's timezone."},"status":{"type":"string","enum":["pending","scheduled","completed","canceled","rescheduled","needs_reschedule","skipped"],"description":"`scheduled` visits are on the schedule, and `rescheduled` visits were moved to this date and are on the schedule too. `pending` visits are planned but not on the schedule yet. `completed` visits are done. `needs_reschedule` visits are waiting for a new date. `skipped` and `canceled` visits are closed."},"closeReason":{"anyOf":[{"type":"string","enum":["already_handled"]},{"type":"null"}],"description":"`already_handled` when a canceled visit was closed because the work was handled outside Shortcut (the app shows it as Handled); otherwise null."},"jobId":{"type":"string","format":"uuid","description":"The job this visit belongs to."},"jobName":{"type":"string","description":"The job's name, such as `Weekly mowing`."},"customerId":{"type":"string","format":"uuid","description":"The customer the visit is for."},"propertyId":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"The property (service address), when the job has one."},"address":{"type":["string","null"],"description":"The property's street address, when the job has a property."},"assignedTeamId":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"The crew pinned to this visit. Null means the visit inherits its job's crew; read `effectiveTeamId` for the crew doing the work."},"effectiveTeamId":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"The crew doing the visit: `assignedTeamId` when set, otherwise the job's crew. Null when neither has a crew (unassigned)."},"routePosition":{"anyOf":[{"type":"integer","minimum":1},{"type":"null"}],"description":"The visit's stop number on its crew's route for the day, starting at 1. Null when the visit is not routed or has no crew."},"plannedStartAt":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"Planned start, ISO 8601 in UTC, or null."},"plannedEndAt":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"Planned end, ISO 8601 in UTC, or null."},"estimatedDurationMinutes":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Estimated time on site in minutes, when known."},"arrivedAt":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"When the crew arrived on site (read-only), ISO 8601 in UTC, or null."},"completedAt":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"When the visit was completed, ISO 8601 in UTC, or null."},"invoiceId":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"The invoice that bills this visit, once a completed visit has been billed; otherwise null."},"createdAt":{"type":"string","format":"date-time","description":"When the visit was created, ISO 8601 in UTC."},"updatedAt":{"type":"string","format":"date-time","description":"When the visit last changed, ISO 8601 in UTC."}},"required":["id","object","date","status","closeReason","jobId","jobName","customerId","propertyId","address","assignedTeamId","effectiveTeamId","routePosition","plannedStartAt","plannedEndAt","estimatedDurationMinutes","arrivedAt","completedAt","invoiceId","createdAt","updatedAt"],"additionalProperties":false,"description":"A visit: one scheduled service for a customer on one date."},"Error":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string","description":"Error family, such as `invalid_request` or `permission`."},"code":{"type":"string","description":"Specific error code; see the errors page."},"message":{"type":"string","description":"A human-readable explanation."},"param":{"type":"string","description":"The input the error is about, such as `query.limit`."},"requiredScope":{"type":"string","description":"The scope the token is missing."},"requestId":{"type":"string","description":"Quote this id to support."},"docs":{"type":"string","description":"Link to the error's documentation."}},"required":["type","code","message","requestId","docs"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}},"responses":{"BadRequest":{"description":"The request is invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Unauthenticated":{"description":"The token is missing, invalid, expired, or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"SubscriptionRequired":{"description":"The workspace's subscription needs attention.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Forbidden":{"description":"The token is missing a required scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"NotFound":{"description":"No such object in this workspace.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Conflict":{"description":"Conflict with the current state or an in-flight request with the same idempotency key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Unprocessable":{"description":"The request cannot be applied, or its idempotency key was used for a different request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"RateLimited":{"description":"Rate limited; see Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"InternalError":{"description":"Internal error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Unavailable":{"description":"Temporarily unavailable; retry later.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"paths":{"/v1/visits/{id}/assign":{"post":{"operationId":"visits.assign","tags":["Visits"],"summary":"Assign a visit to a crew","description":"Gives one scheduled visit to a crew, exactly as moving its stop to another crew in Dispatch does: the visit leaves its current crew's route, joins the end of the new crew's route for that day, and both crews are notified of the route change. Assigning the job's own crew stores no crew on the visit (it inherits the job's), so `assignedTeamId` reads null and `effectiveTeamId` the job's crew; a portion of a split visit is the exception and always stores its crew id. Another crew can't take a portion of a split visit that it already works.\n\nReturns [the visit object](https://docs.shortcutco.com/developers/reference/objects/visit).\n\n**Errors specific to this endpoint:** [`rule_violation`](https://docs.shortcutco.com/developers/concepts/errors#rule_violation), [`state_conflict`](https://docs.shortcutco.com/developers/concepts/errors#state_conflict). Every endpoint can also return the [common errors](https://docs.shortcutco.com/developers/concepts/errors).","parameters":[{"name":"id","in":"path","required":true,"description":"The object's id.","schema":{"type":"string","format":"uuid"}},{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"teamId":{"type":"string","format":"uuid","description":"The crew to do the visit. The visit joins the end of that crew's route for its day. Assigning the job's own crew clears the visit's own crew, so it follows the job's crew again, except on a portion of a split visit, which always stores its crew."}},"required":["teamId"],"additionalProperties":false}}}},"responses":{"200":{"description":"Success.","headers":{"RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Visit"},"meta":{"type":"object","properties":{},"additionalProperties":true,"description":"Facts about this request beside the object, such as `alreadyReminded` on a repeated reminder. Present only when there is something to report."}},"required":["data"],"additionalProperties":false}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthenticated"},"402":{"$ref":"#/components/responses/SubscriptionRequired"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"},"422":{"$ref":"#/components/responses/Unprocessable"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/Unavailable"}}}}}}
```

## Cancel a visit

> Cancels one open visit, exactly as canceling its stop in Dispatch does: it leaves its crew's route, every crew's portion of a split visit is canceled with it, and the crews are notified of the route change. The job and its other visits stay as they are. Visits dated before today, and visits with man-hour work still open, are refused. Your job-canceled automations, which can email or text the customer, and automations your workspace built on visit changes, run only if the token has \`automations:trigger\`. To close a visit without the job-canceled notice, use skip. This cannot be undone.\
> \
> Returns \[the visit object]\(<https://docs.shortcutco.com/developers/reference/objects/visit).\\>
> \
> \*\*Errors specific to this endpoint:\*\* \[\`rule\_violation\`]\(<https://docs.shortcutco.com/developers/concepts/errors#rule\\_violation>), \[\`state\_conflict\`]\(<https://docs.shortcutco.com/developers/concepts/errors#state\\_conflict>). Every endpoint can also return the \[common errors]\(<https://docs.shortcutco.com/developers/concepts/errors>).

```json
{"openapi":"3.1.0","info":{"title":"Shortcut API","version":"v1"},"tags":[{"name":"Visits","description":"A visit is a job's work for one customer on one date, done by a crew. Visits are assigned, rescheduled, skipped, canceled, and completed here.\n\nFields: [The visit object](https://docs.shortcutco.com/developers/reference/objects/visit) · [The visit completion object](https://docs.shortcutco.com/developers/reference/objects/visit-completion)."}],"servers":[{"url":"https://api.shortcutco.com","description":"Production"}],"security":[{"bearerAuth":["visits:write"]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"scut_<env>_<id>_<secret>","description":"A workspace API token. Each operation lists the scopes it needs; `write` implies `read`, and `send`/`complete` are never implied."}},"parameters":{"IdempotencyKey":{"name":"Idempotency-Key","in":"header","required":false,"description":"Any string up to 255 characters. Retrying with the same key returns the first response instead of repeating the write, for 24 hours.","schema":{"type":"string","maxLength":255}}},"headers":{"RateLimitLimit":{"schema":{"type":"integer"},"description":"Requests allowed in the tightest window."},"RateLimitRemaining":{"schema":{"type":"integer"},"description":"Requests left in that window."},"RateLimitReset":{"schema":{"type":"integer"},"description":"Seconds until that window resets."}},"schemas":{"Visit":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"The visit's id."},"object":{"type":"string","const":"visit","description":"Always `visit`."},"date":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"The scheduled date, `YYYY-MM-DD` in the workspace's timezone."},"status":{"type":"string","enum":["pending","scheduled","completed","canceled","rescheduled","needs_reschedule","skipped"],"description":"`scheduled` visits are on the schedule, and `rescheduled` visits were moved to this date and are on the schedule too. `pending` visits are planned but not on the schedule yet. `completed` visits are done. `needs_reschedule` visits are waiting for a new date. `skipped` and `canceled` visits are closed."},"closeReason":{"anyOf":[{"type":"string","enum":["already_handled"]},{"type":"null"}],"description":"`already_handled` when a canceled visit was closed because the work was handled outside Shortcut (the app shows it as Handled); otherwise null."},"jobId":{"type":"string","format":"uuid","description":"The job this visit belongs to."},"jobName":{"type":"string","description":"The job's name, such as `Weekly mowing`."},"customerId":{"type":"string","format":"uuid","description":"The customer the visit is for."},"propertyId":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"The property (service address), when the job has one."},"address":{"type":["string","null"],"description":"The property's street address, when the job has a property."},"assignedTeamId":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"The crew pinned to this visit. Null means the visit inherits its job's crew; read `effectiveTeamId` for the crew doing the work."},"effectiveTeamId":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"The crew doing the visit: `assignedTeamId` when set, otherwise the job's crew. Null when neither has a crew (unassigned)."},"routePosition":{"anyOf":[{"type":"integer","minimum":1},{"type":"null"}],"description":"The visit's stop number on its crew's route for the day, starting at 1. Null when the visit is not routed or has no crew."},"plannedStartAt":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"Planned start, ISO 8601 in UTC, or null."},"plannedEndAt":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"Planned end, ISO 8601 in UTC, or null."},"estimatedDurationMinutes":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Estimated time on site in minutes, when known."},"arrivedAt":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"When the crew arrived on site (read-only), ISO 8601 in UTC, or null."},"completedAt":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"When the visit was completed, ISO 8601 in UTC, or null."},"invoiceId":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"The invoice that bills this visit, once a completed visit has been billed; otherwise null."},"createdAt":{"type":"string","format":"date-time","description":"When the visit was created, ISO 8601 in UTC."},"updatedAt":{"type":"string","format":"date-time","description":"When the visit last changed, ISO 8601 in UTC."}},"required":["id","object","date","status","closeReason","jobId","jobName","customerId","propertyId","address","assignedTeamId","effectiveTeamId","routePosition","plannedStartAt","plannedEndAt","estimatedDurationMinutes","arrivedAt","completedAt","invoiceId","createdAt","updatedAt"],"additionalProperties":false,"description":"A visit: one scheduled service for a customer on one date."},"Error":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string","description":"Error family, such as `invalid_request` or `permission`."},"code":{"type":"string","description":"Specific error code; see the errors page."},"message":{"type":"string","description":"A human-readable explanation."},"param":{"type":"string","description":"The input the error is about, such as `query.limit`."},"requiredScope":{"type":"string","description":"The scope the token is missing."},"requestId":{"type":"string","description":"Quote this id to support."},"docs":{"type":"string","description":"Link to the error's documentation."}},"required":["type","code","message","requestId","docs"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}},"responses":{"BadRequest":{"description":"The request is invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Unauthenticated":{"description":"The token is missing, invalid, expired, or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"SubscriptionRequired":{"description":"The workspace's subscription needs attention.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Forbidden":{"description":"The token is missing a required scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"NotFound":{"description":"No such object in this workspace.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Conflict":{"description":"Conflict with the current state or an in-flight request with the same idempotency key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Unprocessable":{"description":"The request cannot be applied, or its idempotency key was used for a different request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"RateLimited":{"description":"Rate limited; see Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"InternalError":{"description":"Internal error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Unavailable":{"description":"Temporarily unavailable; retry later.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"paths":{"/v1/visits/{id}/cancel":{"post":{"operationId":"visits.cancel","tags":["Visits"],"summary":"Cancel a visit","description":"Cancels one open visit, exactly as canceling its stop in Dispatch does: it leaves its crew's route, every crew's portion of a split visit is canceled with it, and the crews are notified of the route change. The job and its other visits stay as they are. Visits dated before today, and visits with man-hour work still open, are refused. Your job-canceled automations, which can email or text the customer, and automations your workspace built on visit changes, run only if the token has `automations:trigger`. To close a visit without the job-canceled notice, use skip. This cannot be undone.\n\nReturns [the visit object](https://docs.shortcutco.com/developers/reference/objects/visit).\n\n**Errors specific to this endpoint:** [`rule_violation`](https://docs.shortcutco.com/developers/concepts/errors#rule_violation), [`state_conflict`](https://docs.shortcutco.com/developers/concepts/errors#state_conflict). Every endpoint can also return the [common errors](https://docs.shortcutco.com/developers/concepts/errors).","parameters":[{"name":"id","in":"path","required":true,"description":"The object's id.","schema":{"type":"string","format":"uuid"}},{"$ref":"#/components/parameters/IdempotencyKey"}],"responses":{"200":{"description":"Success.","headers":{"RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Visit"},"meta":{"type":"object","properties":{},"additionalProperties":true,"description":"Facts about this request beside the object, such as `alreadyReminded` on a repeated reminder. Present only when there is something to report."}},"required":["data"],"additionalProperties":false}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthenticated"},"402":{"$ref":"#/components/responses/SubscriptionRequired"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"},"422":{"$ref":"#/components/responses/Unprocessable"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/Unavailable"}}}}}}
```

## Complete a visit

> Completes a visit exactly as completing it in the app does. Billing then runs after the same five-minute undo window, through the same worker as every completion: it creates the visit's invoice (once per visit, whatever the retries), queues its delivery to the customer, and charges the customer's saved card when they have autopay on. The response has the completion's \`finalizeAt\` and the \`effects\` billing will have; once billing has run it reports what happened. An hourly visit is priced by your office from the crew's time, so billing holds it for review instead. Read the invoice later from the visit's \`invoiceId\`, \`GET /v1/invoices\`, or the \`invoice.created\` webhook event. Only this visit is completed unless \`completeStop=true\`; a second \`completeStop\` call for a stop already being completed gets \`503 stop\_completion\_in\_progress\`. A pending chemical record is completed with its planned amounts; an hourly job the crew has not started, or with work still open, is refused. Needs \`visits:complete\` (not included in \`visits:write\`) and \`visits:read\`. Without \`automations:trigger\` the completion and its billing start none of your automations (Automations rules, invoice-created and job-completed) and no review request; later changes to the invoice, such as its delivery being recorded or a payment, including an autopay charge, start your rules like any invoice's. Send an \`Idempotency-Key\` to retry safely.\
> \
> Returns \[the visit completion object]\(<https://docs.shortcutco.com/developers/reference/objects/visit-completion).\\>
> \
> \*\*Errors specific to this endpoint:\*\* \[\`rule\_violation\`]\(<https://docs.shortcutco.com/developers/concepts/errors#rule\\_violation>), \[\`state\_conflict\`]\(<https://docs.shortcutco.com/developers/concepts/errors#state\\_conflict>), \[\`stop\_completion\_in\_progress\`]\(<https://docs.shortcutco.com/developers/concepts/errors#stop\\_completion\\_in\\_progress>). Every endpoint can also return the \[common errors]\(<https://docs.shortcutco.com/developers/concepts/errors>).

```json
{"openapi":"3.1.0","info":{"title":"Shortcut API","version":"v1"},"tags":[{"name":"Visits","description":"A visit is a job's work for one customer on one date, done by a crew. Visits are assigned, rescheduled, skipped, canceled, and completed here.\n\nFields: [The visit object](https://docs.shortcutco.com/developers/reference/objects/visit) · [The visit completion object](https://docs.shortcutco.com/developers/reference/objects/visit-completion)."}],"servers":[{"url":"https://api.shortcutco.com","description":"Production"}],"security":[{"bearerAuth":["visits:complete","visits:read"]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"scut_<env>_<id>_<secret>","description":"A workspace API token. Each operation lists the scopes it needs; `write` implies `read`, and `send`/`complete` are never implied."}},"parameters":{"IdempotencyKey":{"name":"Idempotency-Key","in":"header","required":false,"description":"Any string up to 255 characters. Retrying with the same key returns the first response instead of repeating the write, for 24 hours.","schema":{"type":"string","maxLength":255}}},"headers":{"RateLimitLimit":{"schema":{"type":"integer"},"description":"Requests allowed in the tightest window."},"RateLimitRemaining":{"schema":{"type":"integer"},"description":"Requests left in that window."},"RateLimitReset":{"schema":{"type":"integer"},"description":"Seconds until that window resets."}},"schemas":{"VisitCompletion":{"type":"object","properties":{"object":{"type":"string","const":"visit_completion","description":"Always `visit_completion`."},"visit":{"$ref":"#/components/schemas/Visit","description":"The visit, now completed."},"completedVisitIds":{"type":"array","items":{"type":"string","format":"uuid"},"description":"The visits this request completed: the visit itself, plus its stop's other open services with `completeStop`. Empty when nothing was left to complete."},"alreadyCompletedVisitIds":{"type":"array","items":{"type":"string","format":"uuid"},"description":"Visits this request found already completed (in the app, by a crew, or by an earlier attempt): the visit itself, and with `completeStop` the stop's other completed services. Nothing was written for them."},"holdId":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"The visit's completion record, which billing runs from. Null for a visit completed before completion records existed."},"finalizeAt":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"When billing runs (ISO 8601 in UTC): the end of the same undo window completing in the app has. Null once billed."},"billing":{"type":"string","enum":["pending","invoiced","covered_by_prepay","invoice_manual","invoice_scheduled","invoice_review","not_billed"],"description":"`pending` until billing runs. Then `invoiced` (the visit is on an invoice), `covered_by_prepay` (a prepayment covers it), or `invoice_manual` / `invoice_scheduled` / `invoice_review` (the visit's work waits to be invoiced by hand, on a schedule, or after review). `not_billed`: completed without a completion record and on no invoice."},"invoiceId":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"The invoice the visit is on, once billed. Until billing runs it is null; read it later from the visit's `invoiceId`, from `GET /v1/invoices`, or from the `invoice.created` webhook event."},"addOnInvoiceId":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"When the visit's work waits to be invoiced by hand or on a schedule, its field add-ons are billed at once on their own invoice; that invoice. The visit's `invoiceId` stays null. Otherwise null."},"effects":{"type":"array","items":{"type":"string","enum":["invoice_on_finalize","autopay_on_finalize","invoice_created","add_on_invoice_created","notification_queued","notification_sent","autopay_attempted","covered_by_prepay"]},"description":"Before billing runs: `invoice_on_finalize` (billing will invoice the visit, unless a prepayment covers it) and `autopay_on_finalize` when the customer has autopay on with a usable saved card; neither when billing will hold the visit (an hourly visit waits for the office's review; a workspace or customer that invoices by hand or on a schedule). After: `invoice_created` or `add_on_invoice_created`, `notification_queued` or `notification_sent` (that invoice's delivery to the customer), `autopay_attempted` (a charge to the saved card was made or tried), or `covered_by_prepay`."}},"required":["object","visit","completedVisitIds","alreadyCompletedVisitIds","holdId","finalizeAt","billing","invoiceId","addOnInvoiceId","effects"],"additionalProperties":false,"description":"The result of completing a visit."},"Visit":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"The visit's id."},"object":{"type":"string","const":"visit","description":"Always `visit`."},"date":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"The scheduled date, `YYYY-MM-DD` in the workspace's timezone."},"status":{"type":"string","enum":["pending","scheduled","completed","canceled","rescheduled","needs_reschedule","skipped"],"description":"`scheduled` visits are on the schedule, and `rescheduled` visits were moved to this date and are on the schedule too. `pending` visits are planned but not on the schedule yet. `completed` visits are done. `needs_reschedule` visits are waiting for a new date. `skipped` and `canceled` visits are closed."},"closeReason":{"anyOf":[{"type":"string","enum":["already_handled"]},{"type":"null"}],"description":"`already_handled` when a canceled visit was closed because the work was handled outside Shortcut (the app shows it as Handled); otherwise null."},"jobId":{"type":"string","format":"uuid","description":"The job this visit belongs to."},"jobName":{"type":"string","description":"The job's name, such as `Weekly mowing`."},"customerId":{"type":"string","format":"uuid","description":"The customer the visit is for."},"propertyId":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"The property (service address), when the job has one."},"address":{"type":["string","null"],"description":"The property's street address, when the job has a property."},"assignedTeamId":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"The crew pinned to this visit. Null means the visit inherits its job's crew; read `effectiveTeamId` for the crew doing the work."},"effectiveTeamId":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"The crew doing the visit: `assignedTeamId` when set, otherwise the job's crew. Null when neither has a crew (unassigned)."},"routePosition":{"anyOf":[{"type":"integer","minimum":1},{"type":"null"}],"description":"The visit's stop number on its crew's route for the day, starting at 1. Null when the visit is not routed or has no crew."},"plannedStartAt":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"Planned start, ISO 8601 in UTC, or null."},"plannedEndAt":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"Planned end, ISO 8601 in UTC, or null."},"estimatedDurationMinutes":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Estimated time on site in minutes, when known."},"arrivedAt":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"When the crew arrived on site (read-only), ISO 8601 in UTC, or null."},"completedAt":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"When the visit was completed, ISO 8601 in UTC, or null."},"invoiceId":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"The invoice that bills this visit, once a completed visit has been billed; otherwise null."},"createdAt":{"type":"string","format":"date-time","description":"When the visit was created, ISO 8601 in UTC."},"updatedAt":{"type":"string","format":"date-time","description":"When the visit last changed, ISO 8601 in UTC."}},"required":["id","object","date","status","closeReason","jobId","jobName","customerId","propertyId","address","assignedTeamId","effectiveTeamId","routePosition","plannedStartAt","plannedEndAt","estimatedDurationMinutes","arrivedAt","completedAt","invoiceId","createdAt","updatedAt"],"additionalProperties":false,"description":"A visit: one scheduled service for a customer on one date."},"Error":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string","description":"Error family, such as `invalid_request` or `permission`."},"code":{"type":"string","description":"Specific error code; see the errors page."},"message":{"type":"string","description":"A human-readable explanation."},"param":{"type":"string","description":"The input the error is about, such as `query.limit`."},"requiredScope":{"type":"string","description":"The scope the token is missing."},"requestId":{"type":"string","description":"Quote this id to support."},"docs":{"type":"string","description":"Link to the error's documentation."}},"required":["type","code","message","requestId","docs"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}},"responses":{"BadRequest":{"description":"The request is invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Unauthenticated":{"description":"The token is missing, invalid, expired, or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"SubscriptionRequired":{"description":"The workspace's subscription needs attention.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Forbidden":{"description":"The token is missing a required scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"NotFound":{"description":"No such object in this workspace.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Conflict":{"description":"Conflict with the current state or an in-flight request with the same idempotency key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Unprocessable":{"description":"The request cannot be applied, or its idempotency key was used for a different request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"RateLimited":{"description":"Rate limited; see Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"InternalError":{"description":"Internal error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Unavailable":{"description":"Temporarily unavailable; retry later.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"paths":{"/v1/visits/{id}/complete":{"post":{"operationId":"visits.complete","tags":["Visits"],"summary":"Complete a visit","description":"Completes a visit exactly as completing it in the app does. Billing then runs after the same five-minute undo window, through the same worker as every completion: it creates the visit's invoice (once per visit, whatever the retries), queues its delivery to the customer, and charges the customer's saved card when they have autopay on. The response has the completion's `finalizeAt` and the `effects` billing will have; once billing has run it reports what happened. An hourly visit is priced by your office from the crew's time, so billing holds it for review instead. Read the invoice later from the visit's `invoiceId`, `GET /v1/invoices`, or the `invoice.created` webhook event. Only this visit is completed unless `completeStop=true`; a second `completeStop` call for a stop already being completed gets `503 stop_completion_in_progress`. A pending chemical record is completed with its planned amounts; an hourly job the crew has not started, or with work still open, is refused. Needs `visits:complete` (not included in `visits:write`) and `visits:read`. Without `automations:trigger` the completion and its billing start none of your automations (Automations rules, invoice-created and job-completed) and no review request; later changes to the invoice, such as its delivery being recorded or a payment, including an autopay charge, start your rules like any invoice's. Send an `Idempotency-Key` to retry safely.\n\nReturns [the visit completion object](https://docs.shortcutco.com/developers/reference/objects/visit-completion).\n\n**Errors specific to this endpoint:** [`rule_violation`](https://docs.shortcutco.com/developers/concepts/errors#rule_violation), [`state_conflict`](https://docs.shortcutco.com/developers/concepts/errors#state_conflict), [`stop_completion_in_progress`](https://docs.shortcutco.com/developers/concepts/errors#stop_completion_in_progress). Every endpoint can also return the [common errors](https://docs.shortcutco.com/developers/concepts/errors).","parameters":[{"name":"id","in":"path","required":true,"description":"The object's id.","schema":{"type":"string","format":"uuid"}},{"name":"completeStop","in":"query","required":false,"description":"`true` also completes the stop's other open services (same customer, date, crew, and address) as one batch, billed on one invoice, the way the crew app finishes a visit. Omitted or `false` completes only this visit.","schema":{"anyOf":[{"type":"boolean"},{"type":"string","enum":["true","false"]}]}},{"$ref":"#/components/parameters/IdempotencyKey"}],"responses":{"200":{"description":"Success.","headers":{"RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/VisitCompletion"},"meta":{"type":"object","properties":{},"additionalProperties":true,"description":"Facts about this request beside the object, such as `alreadyReminded` on a repeated reminder. Present only when there is something to report."}},"required":["data"],"additionalProperties":false}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthenticated"},"402":{"$ref":"#/components/responses/SubscriptionRequired"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"},"422":{"$ref":"#/components/responses/Unprocessable"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/Unavailable"}}}}}}
```

## Reschedule a visit

> Moves a scheduled or pending visit to another date, exactly as rescheduling it in the app does: a split visit moves together, the visit keeps its crew (or keeps following its job's crew), and crews are notified of route changes. \`scope: this\_and\_future\` replaces this and every later untouched visit with a new series and sets the job to scheduled, clearing any pause. A visit the crew has started cannot be moved. Your job-rescheduled automations, which can email or text the customer, run only if the token has \`automations:trigger\`. Returns the visit now on the new date (a new visit for \`this\_and\_future\`). Send an \`Idempotency-Key\` to retry safely.\
> \
> Returns \[the visit object]\(<https://docs.shortcutco.com/developers/reference/objects/visit).\\>
> \
> \*\*Errors specific to this endpoint:\*\* \[\`rule\_violation\`]\(<https://docs.shortcutco.com/developers/concepts/errors#rule\\_violation>), \[\`state\_conflict\`]\(<https://docs.shortcutco.com/developers/concepts/errors#state\\_conflict>). Every endpoint can also return the \[common errors]\(<https://docs.shortcutco.com/developers/concepts/errors>).

```json
{"openapi":"3.1.0","info":{"title":"Shortcut API","version":"v1"},"tags":[{"name":"Visits","description":"A visit is a job's work for one customer on one date, done by a crew. Visits are assigned, rescheduled, skipped, canceled, and completed here.\n\nFields: [The visit object](https://docs.shortcutco.com/developers/reference/objects/visit) · [The visit completion object](https://docs.shortcutco.com/developers/reference/objects/visit-completion)."}],"servers":[{"url":"https://api.shortcutco.com","description":"Production"}],"security":[{"bearerAuth":["visits:write"]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"scut_<env>_<id>_<secret>","description":"A workspace API token. Each operation lists the scopes it needs; `write` implies `read`, and `send`/`complete` are never implied."}},"parameters":{"IdempotencyKey":{"name":"Idempotency-Key","in":"header","required":false,"description":"Any string up to 255 characters. Retrying with the same key returns the first response instead of repeating the write, for 24 hours.","schema":{"type":"string","maxLength":255}}},"headers":{"RateLimitLimit":{"schema":{"type":"integer"},"description":"Requests allowed in the tightest window."},"RateLimitRemaining":{"schema":{"type":"integer"},"description":"Requests left in that window."},"RateLimitReset":{"schema":{"type":"integer"},"description":"Seconds until that window resets."}},"schemas":{"Visit":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"The visit's id."},"object":{"type":"string","const":"visit","description":"Always `visit`."},"date":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"The scheduled date, `YYYY-MM-DD` in the workspace's timezone."},"status":{"type":"string","enum":["pending","scheduled","completed","canceled","rescheduled","needs_reschedule","skipped"],"description":"`scheduled` visits are on the schedule, and `rescheduled` visits were moved to this date and are on the schedule too. `pending` visits are planned but not on the schedule yet. `completed` visits are done. `needs_reschedule` visits are waiting for a new date. `skipped` and `canceled` visits are closed."},"closeReason":{"anyOf":[{"type":"string","enum":["already_handled"]},{"type":"null"}],"description":"`already_handled` when a canceled visit was closed because the work was handled outside Shortcut (the app shows it as Handled); otherwise null."},"jobId":{"type":"string","format":"uuid","description":"The job this visit belongs to."},"jobName":{"type":"string","description":"The job's name, such as `Weekly mowing`."},"customerId":{"type":"string","format":"uuid","description":"The customer the visit is for."},"propertyId":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"The property (service address), when the job has one."},"address":{"type":["string","null"],"description":"The property's street address, when the job has a property."},"assignedTeamId":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"The crew pinned to this visit. Null means the visit inherits its job's crew; read `effectiveTeamId` for the crew doing the work."},"effectiveTeamId":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"The crew doing the visit: `assignedTeamId` when set, otherwise the job's crew. Null when neither has a crew (unassigned)."},"routePosition":{"anyOf":[{"type":"integer","minimum":1},{"type":"null"}],"description":"The visit's stop number on its crew's route for the day, starting at 1. Null when the visit is not routed or has no crew."},"plannedStartAt":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"Planned start, ISO 8601 in UTC, or null."},"plannedEndAt":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"Planned end, ISO 8601 in UTC, or null."},"estimatedDurationMinutes":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Estimated time on site in minutes, when known."},"arrivedAt":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"When the crew arrived on site (read-only), ISO 8601 in UTC, or null."},"completedAt":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"When the visit was completed, ISO 8601 in UTC, or null."},"invoiceId":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"The invoice that bills this visit, once a completed visit has been billed; otherwise null."},"createdAt":{"type":"string","format":"date-time","description":"When the visit was created, ISO 8601 in UTC."},"updatedAt":{"type":"string","format":"date-time","description":"When the visit last changed, ISO 8601 in UTC."}},"required":["id","object","date","status","closeReason","jobId","jobName","customerId","propertyId","address","assignedTeamId","effectiveTeamId","routePosition","plannedStartAt","plannedEndAt","estimatedDurationMinutes","arrivedAt","completedAt","invoiceId","createdAt","updatedAt"],"additionalProperties":false,"description":"A visit: one scheduled service for a customer on one date."},"Error":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string","description":"Error family, such as `invalid_request` or `permission`."},"code":{"type":"string","description":"Specific error code; see the errors page."},"message":{"type":"string","description":"A human-readable explanation."},"param":{"type":"string","description":"The input the error is about, such as `query.limit`."},"requiredScope":{"type":"string","description":"The scope the token is missing."},"requestId":{"type":"string","description":"Quote this id to support."},"docs":{"type":"string","description":"Link to the error's documentation."}},"required":["type","code","message","requestId","docs"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}},"responses":{"BadRequest":{"description":"The request is invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Unauthenticated":{"description":"The token is missing, invalid, expired, or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"SubscriptionRequired":{"description":"The workspace's subscription needs attention.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Forbidden":{"description":"The token is missing a required scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"NotFound":{"description":"No such object in this workspace.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Conflict":{"description":"Conflict with the current state or an in-flight request with the same idempotency key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Unprocessable":{"description":"The request cannot be applied, or its idempotency key was used for a different request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"RateLimited":{"description":"Rate limited; see Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"InternalError":{"description":"Internal error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Unavailable":{"description":"Temporarily unavailable; retry later.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"paths":{"/v1/visits/{id}/reschedule":{"post":{"operationId":"visits.reschedule","tags":["Visits"],"summary":"Reschedule a visit","description":"Moves a scheduled or pending visit to another date, exactly as rescheduling it in the app does: a split visit moves together, the visit keeps its crew (or keeps following its job's crew), and crews are notified of route changes. `scope: this_and_future` replaces this and every later untouched visit with a new series and sets the job to scheduled, clearing any pause. A visit the crew has started cannot be moved. Your job-rescheduled automations, which can email or text the customer, run only if the token has `automations:trigger`. Returns the visit now on the new date (a new visit for `this_and_future`). Send an `Idempotency-Key` to retry safely.\n\nReturns [the visit object](https://docs.shortcutco.com/developers/reference/objects/visit).\n\n**Errors specific to this endpoint:** [`rule_violation`](https://docs.shortcutco.com/developers/concepts/errors#rule_violation), [`state_conflict`](https://docs.shortcutco.com/developers/concepts/errors#state_conflict). Every endpoint can also return the [common errors](https://docs.shortcutco.com/developers/concepts/errors).","parameters":[{"name":"id","in":"path","required":true,"description":"The object's id.","schema":{"type":"string","format":"uuid"}},{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"date":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"The new date, `YYYY-MM-DD` in the workspace's timezone; today or later."},"scope":{"type":"string","enum":["this_only","this_and_future"],"default":"this_only","description":"`this_only` (the default) moves this visit. `this_and_future` replaces this visit and every later visit of its job that has no history with a new series starting on `date`, as the app's \"This and following\" does, and sets the job to scheduled, clearing any pause; it fails if any of those visits already has history."},"placement":{"type":"string","enum":["start","end"],"description":"`this_only` only: put the visit at the start or end of its crew's route that day. Omitted, the workspace setting decides (a visit carried over from an earlier day goes first, anything else last)."}},"required":["date"],"additionalProperties":false}}}},"responses":{"200":{"description":"Success.","headers":{"RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Visit"},"meta":{"type":"object","properties":{},"additionalProperties":true,"description":"Facts about this request beside the object, such as `alreadyReminded` on a repeated reminder. Present only when there is something to report."}},"required":["data"],"additionalProperties":false}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthenticated"},"402":{"$ref":"#/components/responses/SubscriptionRequired"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"},"422":{"$ref":"#/components/responses/Unprocessable"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/Unavailable"}}}}}}
```

## Skip a visit

> Skips one open visit: it is closed exactly as cancel closes it (through Dispatch's close path, every crew's portion of a split visit together, crews notified of the route change), and the job's later visits stay scheduled. Unlike cancel, it never sends the job-canceled notice. This action sends no message itself; automations your workspace built on visit changes run only if the token has \`automations:trigger\`. Visits dated before today, and visits with man-hour work still open, are refused. This cannot be undone.\
> \
> Returns \[the visit object]\(<https://docs.shortcutco.com/developers/reference/objects/visit).\\>
> \
> \*\*Errors specific to this endpoint:\*\* \[\`rule\_violation\`]\(<https://docs.shortcutco.com/developers/concepts/errors#rule\\_violation>), \[\`state\_conflict\`]\(<https://docs.shortcutco.com/developers/concepts/errors#state\\_conflict>). Every endpoint can also return the \[common errors]\(<https://docs.shortcutco.com/developers/concepts/errors>).

```json
{"openapi":"3.1.0","info":{"title":"Shortcut API","version":"v1"},"tags":[{"name":"Visits","description":"A visit is a job's work for one customer on one date, done by a crew. Visits are assigned, rescheduled, skipped, canceled, and completed here.\n\nFields: [The visit object](https://docs.shortcutco.com/developers/reference/objects/visit) · [The visit completion object](https://docs.shortcutco.com/developers/reference/objects/visit-completion)."}],"servers":[{"url":"https://api.shortcutco.com","description":"Production"}],"security":[{"bearerAuth":["visits:write"]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"scut_<env>_<id>_<secret>","description":"A workspace API token. Each operation lists the scopes it needs; `write` implies `read`, and `send`/`complete` are never implied."}},"parameters":{"IdempotencyKey":{"name":"Idempotency-Key","in":"header","required":false,"description":"Any string up to 255 characters. Retrying with the same key returns the first response instead of repeating the write, for 24 hours.","schema":{"type":"string","maxLength":255}}},"headers":{"RateLimitLimit":{"schema":{"type":"integer"},"description":"Requests allowed in the tightest window."},"RateLimitRemaining":{"schema":{"type":"integer"},"description":"Requests left in that window."},"RateLimitReset":{"schema":{"type":"integer"},"description":"Seconds until that window resets."}},"schemas":{"Visit":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"The visit's id."},"object":{"type":"string","const":"visit","description":"Always `visit`."},"date":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"The scheduled date, `YYYY-MM-DD` in the workspace's timezone."},"status":{"type":"string","enum":["pending","scheduled","completed","canceled","rescheduled","needs_reschedule","skipped"],"description":"`scheduled` visits are on the schedule, and `rescheduled` visits were moved to this date and are on the schedule too. `pending` visits are planned but not on the schedule yet. `completed` visits are done. `needs_reschedule` visits are waiting for a new date. `skipped` and `canceled` visits are closed."},"closeReason":{"anyOf":[{"type":"string","enum":["already_handled"]},{"type":"null"}],"description":"`already_handled` when a canceled visit was closed because the work was handled outside Shortcut (the app shows it as Handled); otherwise null."},"jobId":{"type":"string","format":"uuid","description":"The job this visit belongs to."},"jobName":{"type":"string","description":"The job's name, such as `Weekly mowing`."},"customerId":{"type":"string","format":"uuid","description":"The customer the visit is for."},"propertyId":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"The property (service address), when the job has one."},"address":{"type":["string","null"],"description":"The property's street address, when the job has a property."},"assignedTeamId":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"The crew pinned to this visit. Null means the visit inherits its job's crew; read `effectiveTeamId` for the crew doing the work."},"effectiveTeamId":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"The crew doing the visit: `assignedTeamId` when set, otherwise the job's crew. Null when neither has a crew (unassigned)."},"routePosition":{"anyOf":[{"type":"integer","minimum":1},{"type":"null"}],"description":"The visit's stop number on its crew's route for the day, starting at 1. Null when the visit is not routed or has no crew."},"plannedStartAt":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"Planned start, ISO 8601 in UTC, or null."},"plannedEndAt":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"Planned end, ISO 8601 in UTC, or null."},"estimatedDurationMinutes":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Estimated time on site in minutes, when known."},"arrivedAt":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"When the crew arrived on site (read-only), ISO 8601 in UTC, or null."},"completedAt":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"When the visit was completed, ISO 8601 in UTC, or null."},"invoiceId":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"The invoice that bills this visit, once a completed visit has been billed; otherwise null."},"createdAt":{"type":"string","format":"date-time","description":"When the visit was created, ISO 8601 in UTC."},"updatedAt":{"type":"string","format":"date-time","description":"When the visit last changed, ISO 8601 in UTC."}},"required":["id","object","date","status","closeReason","jobId","jobName","customerId","propertyId","address","assignedTeamId","effectiveTeamId","routePosition","plannedStartAt","plannedEndAt","estimatedDurationMinutes","arrivedAt","completedAt","invoiceId","createdAt","updatedAt"],"additionalProperties":false,"description":"A visit: one scheduled service for a customer on one date."},"Error":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string","description":"Error family, such as `invalid_request` or `permission`."},"code":{"type":"string","description":"Specific error code; see the errors page."},"message":{"type":"string","description":"A human-readable explanation."},"param":{"type":"string","description":"The input the error is about, such as `query.limit`."},"requiredScope":{"type":"string","description":"The scope the token is missing."},"requestId":{"type":"string","description":"Quote this id to support."},"docs":{"type":"string","description":"Link to the error's documentation."}},"required":["type","code","message","requestId","docs"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}},"responses":{"BadRequest":{"description":"The request is invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Unauthenticated":{"description":"The token is missing, invalid, expired, or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"SubscriptionRequired":{"description":"The workspace's subscription needs attention.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Forbidden":{"description":"The token is missing a required scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"NotFound":{"description":"No such object in this workspace.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Conflict":{"description":"Conflict with the current state or an in-flight request with the same idempotency key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Unprocessable":{"description":"The request cannot be applied, or its idempotency key was used for a different request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"RateLimited":{"description":"Rate limited; see Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"InternalError":{"description":"Internal error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Unavailable":{"description":"Temporarily unavailable; retry later.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"paths":{"/v1/visits/{id}/skip":{"post":{"operationId":"visits.skip","tags":["Visits"],"summary":"Skip a visit","description":"Skips one open visit: it is closed exactly as cancel closes it (through Dispatch's close path, every crew's portion of a split visit together, crews notified of the route change), and the job's later visits stay scheduled. Unlike cancel, it never sends the job-canceled notice. This action sends no message itself; automations your workspace built on visit changes run only if the token has `automations:trigger`. Visits dated before today, and visits with man-hour work still open, are refused. This cannot be undone.\n\nReturns [the visit object](https://docs.shortcutco.com/developers/reference/objects/visit).\n\n**Errors specific to this endpoint:** [`rule_violation`](https://docs.shortcutco.com/developers/concepts/errors#rule_violation), [`state_conflict`](https://docs.shortcutco.com/developers/concepts/errors#state_conflict). Every endpoint can also return the [common errors](https://docs.shortcutco.com/developers/concepts/errors).","parameters":[{"name":"id","in":"path","required":true,"description":"The object's id.","schema":{"type":"string","format":"uuid"}},{"$ref":"#/components/parameters/IdempotencyKey"}],"responses":{"200":{"description":"Success.","headers":{"RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Visit"},"meta":{"type":"object","properties":{},"additionalProperties":true,"description":"Facts about this request beside the object, such as `alreadyReminded` on a repeated reminder. Present only when there is something to report."}},"required":["data"],"additionalProperties":false}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthenticated"},"402":{"$ref":"#/components/responses/SubscriptionRequired"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"},"422":{"$ref":"#/components/responses/Unprocessable"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/Unavailable"}}}}}}
```
