> 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/services.md).

# Services

The service catalog jobs and estimates are made from.

A service is something the workspace sells, with its price structure and rate. Jobs and estimate lines are made from services.

Fields: [The service object](https://docs.shortcutco.com/developers/reference/objects/service).

## List services

> The service catalog, newest first, or by last change when \`updatedSince\` is set: standard, snow, and chemical services, active and deactivated, as the app's Services settings show them.\
> \
> Returns a list of \[service objects]\(<https://docs.shortcutco.com/developers/reference/objects/service>).

```json
{"openapi":"3.1.0","info":{"title":"Shortcut API","version":"v1"},"tags":[{"name":"Services","description":"A service is something the workspace sells, with its price structure and rate. Jobs and estimate lines are made from services.\n\nFields: [The service object](https://docs.shortcutco.com/developers/reference/objects/service)."}],"servers":[{"url":"https://api.shortcutco.com","description":"Production"}],"security":[{"bearerAuth":["services: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":{"Service":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"The service's id."},"object":{"type":"string","const":"service","description":"Always `service`."},"name":{"type":"string","description":"The service's name, unique in the workspace regardless of case."},"description":{"type":["string","null"],"description":"Description shown on estimates and invoices."},"serviceType":{"type":"string","enum":["standard","snow","chemical"],"description":"`standard`, `snow`, or `chemical`. Chemical services are read-only through the API."},"status":{"type":"string","enum":["active","deactivated"],"description":"Deactivated services stay on existing jobs but are no longer offered for new work."},"priceStructure":{"type":"string","enum":["per_hour","per_sqft","flat","per_man_hour"],"description":"How the price is computed: `flat` per visit, `per_sqft` by lawn area, `per_hour` per crew hour, or `per_man_hour` per person-hour on site."},"rate":{"type":["number","null"],"description":"The price in US dollars for the price structure; null when `pricingTiers` sets the price."},"pricingTiers":{"anyOf":[{"type":"array","items":{"type":"object","properties":{"upTo":{"anyOf":[{"type":"integer","minimum":0},{"type":"null"}],"description":"The top of this bracket in square feet (inclusive); null on the last, open-ended bracket."},"rate":{"type":"number","minimum":0,"description":"The per-square-foot rate in this bracket, in US dollars."}},"required":["upTo","rate"],"additionalProperties":false}},{"type":"null"}],"description":"Square-footage brackets, or null."},"completionMessage":{"type":["string","null"],"description":"The message customers get when a visit of this service is completed; null uses the default message."},"availableForWorkerAddOns":{"type":"boolean","description":"Whether crew members can add this service to a visit in the field."},"snow":{"anyOf":[{"type":"object","properties":{"triggerKind":{"type":"string","enum":["depth","any","manual","on_call"],"description":"When the service is due: `depth` at `triggerInches` of snow, `any` accumulation, `manual` (never auto-selected), or `on_call` (offered to the customer each time)."},"triggerInches":{"type":["number","null"],"description":"Inches of snow that make a `depth` service due; null for other kinds."},"offerWindowHours":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Hours an `on_call` offer stays open; null for other kinds."},"depthLadder":{"anyOf":[{"type":"array","items":{"type":"object","properties":{"upTo":{"anyOf":[{"type":"integer","minimum":0},{"type":"null"}],"description":"The top of this accumulation bracket in whole inches; null on the last, open-ended bracket."},"rate":{"type":"number","minimum":0,"description":"The price per push in this bracket, in US dollars."}},"required":["upTo","rate"],"additionalProperties":false}},{"type":"null"}],"description":"Optional price per push by accumulation, only with a `flat` price; null when not used."}},"required":["triggerKind","triggerInches","offerWindowHours","depthLadder"],"additionalProperties":false,"description":"Snow terms; present only on snow services."},{"type":"null"}],"description":"Snow terms; present only on snow services."},"createdAt":{"type":"string","format":"date-time","description":"When the service was created, ISO 8601 in UTC."},"updatedAt":{"type":"string","format":"date-time","description":"When the service last changed, ISO 8601 in UTC."}},"required":["id","object","name","description","serviceType","status","priceStructure","rate","pricingTiers","completionMessage","availableForWorkerAddOns","snow","createdAt","updatedAt"],"additionalProperties":false,"description":"A service in the workspace's catalog."},"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/services":{"get":{"operationId":"services.list","tags":["Services"],"summary":"List services","description":"The service catalog, newest first, or by last change when `updatedSince` is set: standard, snow, and chemical services, active and deactivated, as the app's Services settings show them.\n\nReturns a list of [service objects](https://docs.shortcutco.com/developers/reference/objects/service).","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":"status","in":"query","required":false,"description":"Only services with this status.","schema":{"type":"string","enum":["active","deactivated"]}},{"name":"serviceType","in":"query","required":false,"description":"Only services of this type.","schema":{"type":"string","enum":["standard","snow","chemical"]}},{"name":"updatedSince","in":"query","required":false,"description":"ISO 8601 timestamp. Returns objects 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`.","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/Service"}},"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"}}}}}}
```

## Create a service

> Adds a standard or snow service to the catalog with the same rules as the app: names are unique regardless of case (deactivated and chemical services count), tier brackets only on \`per\_sqft\`, a depth ladder only on a \`flat\` snow price. If the workspace syncs with QuickBooks, the service is queued for sync. Send an \`Idempotency-Key\` to retry safely.\
> \
> Returns \[the service object]\(<https://docs.shortcutco.com/developers/reference/objects/service).\\>
> \
> \*\*Errors specific to this endpoint:\*\* \[\`already\_exists\`]\(<https://docs.shortcutco.com/developers/concepts/errors#already\\_exists>), \[\`feature\_unavailable\`]\(<https://docs.shortcutco.com/developers/concepts/errors#feature\\_unavailable>). 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":"Services","description":"A service is something the workspace sells, with its price structure and rate. Jobs and estimate lines are made from services.\n\nFields: [The service object](https://docs.shortcutco.com/developers/reference/objects/service)."}],"servers":[{"url":"https://api.shortcutco.com","description":"Production"}],"security":[{"bearerAuth":["services: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":{"Service":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"The service's id."},"object":{"type":"string","const":"service","description":"Always `service`."},"name":{"type":"string","description":"The service's name, unique in the workspace regardless of case."},"description":{"type":["string","null"],"description":"Description shown on estimates and invoices."},"serviceType":{"type":"string","enum":["standard","snow","chemical"],"description":"`standard`, `snow`, or `chemical`. Chemical services are read-only through the API."},"status":{"type":"string","enum":["active","deactivated"],"description":"Deactivated services stay on existing jobs but are no longer offered for new work."},"priceStructure":{"type":"string","enum":["per_hour","per_sqft","flat","per_man_hour"],"description":"How the price is computed: `flat` per visit, `per_sqft` by lawn area, `per_hour` per crew hour, or `per_man_hour` per person-hour on site."},"rate":{"type":["number","null"],"description":"The price in US dollars for the price structure; null when `pricingTiers` sets the price."},"pricingTiers":{"anyOf":[{"type":"array","items":{"type":"object","properties":{"upTo":{"anyOf":[{"type":"integer","minimum":0},{"type":"null"}],"description":"The top of this bracket in square feet (inclusive); null on the last, open-ended bracket."},"rate":{"type":"number","minimum":0,"description":"The per-square-foot rate in this bracket, in US dollars."}},"required":["upTo","rate"],"additionalProperties":false}},{"type":"null"}],"description":"Square-footage brackets, or null."},"completionMessage":{"type":["string","null"],"description":"The message customers get when a visit of this service is completed; null uses the default message."},"availableForWorkerAddOns":{"type":"boolean","description":"Whether crew members can add this service to a visit in the field."},"snow":{"anyOf":[{"type":"object","properties":{"triggerKind":{"type":"string","enum":["depth","any","manual","on_call"],"description":"When the service is due: `depth` at `triggerInches` of snow, `any` accumulation, `manual` (never auto-selected), or `on_call` (offered to the customer each time)."},"triggerInches":{"type":["number","null"],"description":"Inches of snow that make a `depth` service due; null for other kinds."},"offerWindowHours":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Hours an `on_call` offer stays open; null for other kinds."},"depthLadder":{"anyOf":[{"type":"array","items":{"type":"object","properties":{"upTo":{"anyOf":[{"type":"integer","minimum":0},{"type":"null"}],"description":"The top of this accumulation bracket in whole inches; null on the last, open-ended bracket."},"rate":{"type":"number","minimum":0,"description":"The price per push in this bracket, in US dollars."}},"required":["upTo","rate"],"additionalProperties":false}},{"type":"null"}],"description":"Optional price per push by accumulation, only with a `flat` price; null when not used."}},"required":["triggerKind","triggerInches","offerWindowHours","depthLadder"],"additionalProperties":false,"description":"Snow terms; present only on snow services."},{"type":"null"}],"description":"Snow terms; present only on snow services."},"createdAt":{"type":"string","format":"date-time","description":"When the service was created, ISO 8601 in UTC."},"updatedAt":{"type":"string","format":"date-time","description":"When the service last changed, ISO 8601 in UTC."}},"required":["id","object","name","description","serviceType","status","priceStructure","rate","pricingTiers","completionMessage","availableForWorkerAddOns","snow","createdAt","updatedAt"],"additionalProperties":false,"description":"A service in the workspace's catalog."},"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/services":{"post":{"operationId":"services.create","tags":["Services"],"summary":"Create a service","description":"Adds a standard or snow service to the catalog with the same rules as the app: names are unique regardless of case (deactivated and chemical services count), tier brackets only on `per_sqft`, a depth ladder only on a `flat` snow price. If the workspace syncs with QuickBooks, the service is queued for sync. Send an `Idempotency-Key` to retry safely.\n\nReturns [the service object](https://docs.shortcutco.com/developers/reference/objects/service).\n\n**Errors specific to this endpoint:** [`already_exists`](https://docs.shortcutco.com/developers/concepts/errors#already_exists), [`feature_unavailable`](https://docs.shortcutco.com/developers/concepts/errors#feature_unavailable). Every endpoint can also return the [common errors](https://docs.shortcutco.com/developers/concepts/errors).","parameters":[{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":140,"description":"The service's name; unique in the workspace regardless of case."},"description":{"anyOf":[{"type":"string","maxLength":2000},{"type":"null"}],"description":"Description shown on estimates and invoices; null clears it."},"priceStructure":{"type":"string","enum":["per_hour","per_sqft","flat","per_man_hour"],"description":"How the price is computed: `flat` per visit, `per_sqft` by lawn area, `per_hour` per crew hour, or `per_man_hour` per person-hour on site."},"rate":{"anyOf":[{"type":"number","minimum":0},{"type":"null"}],"description":"The price in US dollars. Required unless `pricingTiers` or a snow `depthLadder` sets the price."},"pricingTiers":{"anyOf":[{"type":"array","items":{"type":"object","properties":{"upTo":{"anyOf":[{"type":"integer","minimum":0},{"type":"null"}],"description":"The top of this bracket in square feet (inclusive); null on the last, open-ended bracket."},"rate":{"type":"number","minimum":0,"description":"The per-square-foot rate in this bracket, in US dollars."}},"required":["upTo","rate"],"additionalProperties":false},"minItems":2,"maxItems":10,"description":"Square-footage brackets for `per_sqft` services, ascending, the last one open-ended. When set, the brackets replace `rate`."},{"type":"null"}],"description":"Square-footage brackets for `per_sqft` services, ascending, the last one open-ended. When set, the brackets replace `rate`."},"completionMessage":{"anyOf":[{"type":"string","maxLength":480},{"type":"null"}],"description":"The message customers get when a visit of this service is completed; null or blank uses the default."},"snow":{"type":"object","properties":{"triggerKind":{"type":"string","enum":["depth","any","manual","on_call"],"description":"When the service is due: `depth` at `triggerInches` of snow, `any` accumulation, `manual` (never auto-selected), or `on_call` (offered to the customer each time)."},"triggerInches":{"type":["number","null"],"description":"Inches of snow that make a `depth` service due; null for other kinds."},"offerWindowHours":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Hours an `on_call` offer stays open; null for other kinds."},"depthLadder":{"anyOf":[{"type":"array","items":{"type":"object","properties":{"upTo":{"anyOf":[{"type":"integer","minimum":0},{"type":"null"}],"description":"The top of this accumulation bracket in whole inches; null on the last, open-ended bracket."},"rate":{"type":"number","minimum":0,"description":"The price per push in this bracket, in US dollars."}},"required":["upTo","rate"],"additionalProperties":false}},{"type":"null"}],"description":"Optional price per push by accumulation, only with a `flat` price; null when not used."}},"required":["triggerKind"],"additionalProperties":false,"description":"Snow terms. Required for snow services and refused on standard services."},"serviceType":{"type":"string","enum":["standard","snow"],"default":"standard","description":"`standard` (the default) or `snow`. Chemical services are created in the app and cannot be created through the API."}},"required":["name","priceStructure"],"additionalProperties":false}}}},"responses":{"201":{"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/Service"},"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"}}}}}}
```

## Get a service

> One service from the catalog.\
> \
> Returns \[the service object]\(<https://docs.shortcutco.com/developers/reference/objects/service>).

```json
{"openapi":"3.1.0","info":{"title":"Shortcut API","version":"v1"},"tags":[{"name":"Services","description":"A service is something the workspace sells, with its price structure and rate. Jobs and estimate lines are made from services.\n\nFields: [The service object](https://docs.shortcutco.com/developers/reference/objects/service)."}],"servers":[{"url":"https://api.shortcutco.com","description":"Production"}],"security":[{"bearerAuth":["services: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":{"Service":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"The service's id."},"object":{"type":"string","const":"service","description":"Always `service`."},"name":{"type":"string","description":"The service's name, unique in the workspace regardless of case."},"description":{"type":["string","null"],"description":"Description shown on estimates and invoices."},"serviceType":{"type":"string","enum":["standard","snow","chemical"],"description":"`standard`, `snow`, or `chemical`. Chemical services are read-only through the API."},"status":{"type":"string","enum":["active","deactivated"],"description":"Deactivated services stay on existing jobs but are no longer offered for new work."},"priceStructure":{"type":"string","enum":["per_hour","per_sqft","flat","per_man_hour"],"description":"How the price is computed: `flat` per visit, `per_sqft` by lawn area, `per_hour` per crew hour, or `per_man_hour` per person-hour on site."},"rate":{"type":["number","null"],"description":"The price in US dollars for the price structure; null when `pricingTiers` sets the price."},"pricingTiers":{"anyOf":[{"type":"array","items":{"type":"object","properties":{"upTo":{"anyOf":[{"type":"integer","minimum":0},{"type":"null"}],"description":"The top of this bracket in square feet (inclusive); null on the last, open-ended bracket."},"rate":{"type":"number","minimum":0,"description":"The per-square-foot rate in this bracket, in US dollars."}},"required":["upTo","rate"],"additionalProperties":false}},{"type":"null"}],"description":"Square-footage brackets, or null."},"completionMessage":{"type":["string","null"],"description":"The message customers get when a visit of this service is completed; null uses the default message."},"availableForWorkerAddOns":{"type":"boolean","description":"Whether crew members can add this service to a visit in the field."},"snow":{"anyOf":[{"type":"object","properties":{"triggerKind":{"type":"string","enum":["depth","any","manual","on_call"],"description":"When the service is due: `depth` at `triggerInches` of snow, `any` accumulation, `manual` (never auto-selected), or `on_call` (offered to the customer each time)."},"triggerInches":{"type":["number","null"],"description":"Inches of snow that make a `depth` service due; null for other kinds."},"offerWindowHours":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Hours an `on_call` offer stays open; null for other kinds."},"depthLadder":{"anyOf":[{"type":"array","items":{"type":"object","properties":{"upTo":{"anyOf":[{"type":"integer","minimum":0},{"type":"null"}],"description":"The top of this accumulation bracket in whole inches; null on the last, open-ended bracket."},"rate":{"type":"number","minimum":0,"description":"The price per push in this bracket, in US dollars."}},"required":["upTo","rate"],"additionalProperties":false}},{"type":"null"}],"description":"Optional price per push by accumulation, only with a `flat` price; null when not used."}},"required":["triggerKind","triggerInches","offerWindowHours","depthLadder"],"additionalProperties":false,"description":"Snow terms; present only on snow services."},{"type":"null"}],"description":"Snow terms; present only on snow services."},"createdAt":{"type":"string","format":"date-time","description":"When the service was created, ISO 8601 in UTC."},"updatedAt":{"type":"string","format":"date-time","description":"When the service last changed, ISO 8601 in UTC."}},"required":["id","object","name","description","serviceType","status","priceStructure","rate","pricingTiers","completionMessage","availableForWorkerAddOns","snow","createdAt","updatedAt"],"additionalProperties":false,"description":"A service in the workspace's catalog."},"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/services/{id}":{"get":{"operationId":"services.get","tags":["Services"],"summary":"Get a service","description":"One service from the catalog.\n\nReturns [the service object](https://docs.shortcutco.com/developers/reference/objects/service).","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/Service"},"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"}}}}}}
```

## Update a service

> Changes only the fields sent (a snow service with a depth ladder takes its rate from the first bracket unless \`rate\` is sent); the result must still satisfy the app's rules, so switching a tiered service to \`flat\` also needs \`pricingTiers: null\`. \`snow\` replaces the snow terms as a whole. The type cannot change. Chemical services are read-only (\`403 feature\_unavailable\`). Existing jobs keep their own prices. If the workspace syncs with QuickBooks, the change is queued for sync.\
> \
> Returns \[the service object]\(<https://docs.shortcutco.com/developers/reference/objects/service).\\>
> \
> \*\*Errors specific to this endpoint:\*\* \[\`already\_exists\`]\(<https://docs.shortcutco.com/developers/concepts/errors#already\\_exists>), \[\`feature\_unavailable\`]\(<https://docs.shortcutco.com/developers/concepts/errors#feature\\_unavailable>). 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":"Services","description":"A service is something the workspace sells, with its price structure and rate. Jobs and estimate lines are made from services.\n\nFields: [The service object](https://docs.shortcutco.com/developers/reference/objects/service)."}],"servers":[{"url":"https://api.shortcutco.com","description":"Production"}],"security":[{"bearerAuth":["services: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."}},"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":{"Service":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"The service's id."},"object":{"type":"string","const":"service","description":"Always `service`."},"name":{"type":"string","description":"The service's name, unique in the workspace regardless of case."},"description":{"type":["string","null"],"description":"Description shown on estimates and invoices."},"serviceType":{"type":"string","enum":["standard","snow","chemical"],"description":"`standard`, `snow`, or `chemical`. Chemical services are read-only through the API."},"status":{"type":"string","enum":["active","deactivated"],"description":"Deactivated services stay on existing jobs but are no longer offered for new work."},"priceStructure":{"type":"string","enum":["per_hour","per_sqft","flat","per_man_hour"],"description":"How the price is computed: `flat` per visit, `per_sqft` by lawn area, `per_hour` per crew hour, or `per_man_hour` per person-hour on site."},"rate":{"type":["number","null"],"description":"The price in US dollars for the price structure; null when `pricingTiers` sets the price."},"pricingTiers":{"anyOf":[{"type":"array","items":{"type":"object","properties":{"upTo":{"anyOf":[{"type":"integer","minimum":0},{"type":"null"}],"description":"The top of this bracket in square feet (inclusive); null on the last, open-ended bracket."},"rate":{"type":"number","minimum":0,"description":"The per-square-foot rate in this bracket, in US dollars."}},"required":["upTo","rate"],"additionalProperties":false}},{"type":"null"}],"description":"Square-footage brackets, or null."},"completionMessage":{"type":["string","null"],"description":"The message customers get when a visit of this service is completed; null uses the default message."},"availableForWorkerAddOns":{"type":"boolean","description":"Whether crew members can add this service to a visit in the field."},"snow":{"anyOf":[{"type":"object","properties":{"triggerKind":{"type":"string","enum":["depth","any","manual","on_call"],"description":"When the service is due: `depth` at `triggerInches` of snow, `any` accumulation, `manual` (never auto-selected), or `on_call` (offered to the customer each time)."},"triggerInches":{"type":["number","null"],"description":"Inches of snow that make a `depth` service due; null for other kinds."},"offerWindowHours":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Hours an `on_call` offer stays open; null for other kinds."},"depthLadder":{"anyOf":[{"type":"array","items":{"type":"object","properties":{"upTo":{"anyOf":[{"type":"integer","minimum":0},{"type":"null"}],"description":"The top of this accumulation bracket in whole inches; null on the last, open-ended bracket."},"rate":{"type":"number","minimum":0,"description":"The price per push in this bracket, in US dollars."}},"required":["upTo","rate"],"additionalProperties":false}},{"type":"null"}],"description":"Optional price per push by accumulation, only with a `flat` price; null when not used."}},"required":["triggerKind","triggerInches","offerWindowHours","depthLadder"],"additionalProperties":false,"description":"Snow terms; present only on snow services."},{"type":"null"}],"description":"Snow terms; present only on snow services."},"createdAt":{"type":"string","format":"date-time","description":"When the service was created, ISO 8601 in UTC."},"updatedAt":{"type":"string","format":"date-time","description":"When the service last changed, ISO 8601 in UTC."}},"required":["id","object","name","description","serviceType","status","priceStructure","rate","pricingTiers","completionMessage","availableForWorkerAddOns","snow","createdAt","updatedAt"],"additionalProperties":false,"description":"A service in the workspace's catalog."},"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/services/{id}":{"patch":{"operationId":"services.update","tags":["Services"],"summary":"Update a service","description":"Changes only the fields sent (a snow service with a depth ladder takes its rate from the first bracket unless `rate` is sent); the result must still satisfy the app's rules, so switching a tiered service to `flat` also needs `pricingTiers: null`. `snow` replaces the snow terms as a whole. The type cannot change. Chemical services are read-only (`403 feature_unavailable`). Existing jobs keep their own prices. If the workspace syncs with QuickBooks, the change is queued for sync.\n\nReturns [the service object](https://docs.shortcutco.com/developers/reference/objects/service).\n\n**Errors specific to this endpoint:** [`already_exists`](https://docs.shortcutco.com/developers/concepts/errors#already_exists), [`feature_unavailable`](https://docs.shortcutco.com/developers/concepts/errors#feature_unavailable). 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"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":140,"description":"The service's name; unique in the workspace regardless of case."},"description":{"anyOf":[{"type":"string","maxLength":2000},{"type":"null"}],"description":"Description shown on estimates and invoices; null clears it."},"priceStructure":{"type":"string","enum":["per_hour","per_sqft","flat","per_man_hour"],"description":"How the price is computed: `flat` per visit, `per_sqft` by lawn area, `per_hour` per crew hour, or `per_man_hour` per person-hour on site."},"rate":{"anyOf":[{"type":"number","minimum":0},{"type":"null"}],"description":"The price in US dollars. Required unless `pricingTiers` or a snow `depthLadder` sets the price."},"pricingTiers":{"anyOf":[{"type":"array","items":{"type":"object","properties":{"upTo":{"anyOf":[{"type":"integer","minimum":0},{"type":"null"}],"description":"The top of this bracket in square feet (inclusive); null on the last, open-ended bracket."},"rate":{"type":"number","minimum":0,"description":"The per-square-foot rate in this bracket, in US dollars."}},"required":["upTo","rate"],"additionalProperties":false},"minItems":2,"maxItems":10,"description":"Square-footage brackets for `per_sqft` services, ascending, the last one open-ended. When set, the brackets replace `rate`."},{"type":"null"}],"description":"Square-footage brackets for `per_sqft` services, ascending, the last one open-ended. When set, the brackets replace `rate`."},"completionMessage":{"anyOf":[{"type":"string","maxLength":480},{"type":"null"}],"description":"The message customers get when a visit of this service is completed; null or blank uses the default."},"snow":{"type":"object","properties":{"triggerKind":{"type":"string","enum":["depth","any","manual","on_call"],"description":"When the service is due: `depth` at `triggerInches` of snow, `any` accumulation, `manual` (never auto-selected), or `on_call` (offered to the customer each time)."},"triggerInches":{"type":["number","null"],"description":"Inches of snow that make a `depth` service due; null for other kinds."},"offerWindowHours":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Hours an `on_call` offer stays open; null for other kinds."},"depthLadder":{"anyOf":[{"type":"array","items":{"type":"object","properties":{"upTo":{"anyOf":[{"type":"integer","minimum":0},{"type":"null"}],"description":"The top of this accumulation bracket in whole inches; null on the last, open-ended bracket."},"rate":{"type":"number","minimum":0,"description":"The price per push in this bracket, in US dollars."}},"required":["upTo","rate"],"additionalProperties":false}},{"type":"null"}],"description":"Optional price per push by accumulation, only with a `flat` price; null when not used."}},"required":["triggerKind"],"additionalProperties":false,"description":"Snow terms. Required for snow services and refused on standard services."}},"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/Service"},"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"}}}}}}
```

## Deactivate a service

> Stops offering a service for new work. Like the app, a service still on open estimates or jobs that are not canceled is refused with \`409 state\_conflict\` naming the counts; pass \`force=true\` to deactivate it anyway, and those jobs keep it. Chemical services are read-only (\`403 feature\_unavailable\`). If the workspace syncs with QuickBooks, the change is queued for sync.\
> \
> Returns \[the service object]\(<https://docs.shortcutco.com/developers/reference/objects/service).\\>
> \
> \*\*Errors specific to this endpoint:\*\* \[\`feature\_unavailable\`]\(<https://docs.shortcutco.com/developers/concepts/errors#feature\\_unavailable>), \[\`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":"Services","description":"A service is something the workspace sells, with its price structure and rate. Jobs and estimate lines are made from services.\n\nFields: [The service object](https://docs.shortcutco.com/developers/reference/objects/service)."}],"servers":[{"url":"https://api.shortcutco.com","description":"Production"}],"security":[{"bearerAuth":["services: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":{"Service":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"The service's id."},"object":{"type":"string","const":"service","description":"Always `service`."},"name":{"type":"string","description":"The service's name, unique in the workspace regardless of case."},"description":{"type":["string","null"],"description":"Description shown on estimates and invoices."},"serviceType":{"type":"string","enum":["standard","snow","chemical"],"description":"`standard`, `snow`, or `chemical`. Chemical services are read-only through the API."},"status":{"type":"string","enum":["active","deactivated"],"description":"Deactivated services stay on existing jobs but are no longer offered for new work."},"priceStructure":{"type":"string","enum":["per_hour","per_sqft","flat","per_man_hour"],"description":"How the price is computed: `flat` per visit, `per_sqft` by lawn area, `per_hour` per crew hour, or `per_man_hour` per person-hour on site."},"rate":{"type":["number","null"],"description":"The price in US dollars for the price structure; null when `pricingTiers` sets the price."},"pricingTiers":{"anyOf":[{"type":"array","items":{"type":"object","properties":{"upTo":{"anyOf":[{"type":"integer","minimum":0},{"type":"null"}],"description":"The top of this bracket in square feet (inclusive); null on the last, open-ended bracket."},"rate":{"type":"number","minimum":0,"description":"The per-square-foot rate in this bracket, in US dollars."}},"required":["upTo","rate"],"additionalProperties":false}},{"type":"null"}],"description":"Square-footage brackets, or null."},"completionMessage":{"type":["string","null"],"description":"The message customers get when a visit of this service is completed; null uses the default message."},"availableForWorkerAddOns":{"type":"boolean","description":"Whether crew members can add this service to a visit in the field."},"snow":{"anyOf":[{"type":"object","properties":{"triggerKind":{"type":"string","enum":["depth","any","manual","on_call"],"description":"When the service is due: `depth` at `triggerInches` of snow, `any` accumulation, `manual` (never auto-selected), or `on_call` (offered to the customer each time)."},"triggerInches":{"type":["number","null"],"description":"Inches of snow that make a `depth` service due; null for other kinds."},"offerWindowHours":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Hours an `on_call` offer stays open; null for other kinds."},"depthLadder":{"anyOf":[{"type":"array","items":{"type":"object","properties":{"upTo":{"anyOf":[{"type":"integer","minimum":0},{"type":"null"}],"description":"The top of this accumulation bracket in whole inches; null on the last, open-ended bracket."},"rate":{"type":"number","minimum":0,"description":"The price per push in this bracket, in US dollars."}},"required":["upTo","rate"],"additionalProperties":false}},{"type":"null"}],"description":"Optional price per push by accumulation, only with a `flat` price; null when not used."}},"required":["triggerKind","triggerInches","offerWindowHours","depthLadder"],"additionalProperties":false,"description":"Snow terms; present only on snow services."},{"type":"null"}],"description":"Snow terms; present only on snow services."},"createdAt":{"type":"string","format":"date-time","description":"When the service was created, ISO 8601 in UTC."},"updatedAt":{"type":"string","format":"date-time","description":"When the service last changed, ISO 8601 in UTC."}},"required":["id","object","name","description","serviceType","status","priceStructure","rate","pricingTiers","completionMessage","availableForWorkerAddOns","snow","createdAt","updatedAt"],"additionalProperties":false,"description":"A service in the workspace's catalog."},"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/services/{id}/deactivate":{"post":{"operationId":"services.deactivate","tags":["Services"],"summary":"Deactivate a service","description":"Stops offering a service for new work. Like the app, a service still on open estimates or jobs that are not canceled is refused with `409 state_conflict` naming the counts; pass `force=true` to deactivate it anyway, and those jobs keep it. Chemical services are read-only (`403 feature_unavailable`). If the workspace syncs with QuickBooks, the change is queued for sync.\n\nReturns [the service object](https://docs.shortcutco.com/developers/reference/objects/service).\n\n**Errors specific to this endpoint:** [`feature_unavailable`](https://docs.shortcutco.com/developers/concepts/errors#feature_unavailable), [`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"}},{"name":"force","in":"query","required":false,"description":"Deactivate even when open estimates or jobs that are not canceled use the service.","schema":{"type":"boolean"}},{"$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/Service"},"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"}}}}}}
```

## Reactivate a service

> Offers a deactivated service for new work again. Chemical services are read-only (\`403 feature\_unavailable\`). If the workspace syncs with QuickBooks, the change is queued for sync.\
> \
> Returns \[the service object]\(<https://docs.shortcutco.com/developers/reference/objects/service).\\>
> \
> \*\*Errors specific to this endpoint:\*\* \[\`feature\_unavailable\`]\(<https://docs.shortcutco.com/developers/concepts/errors#feature\\_unavailable>). 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":"Services","description":"A service is something the workspace sells, with its price structure and rate. Jobs and estimate lines are made from services.\n\nFields: [The service object](https://docs.shortcutco.com/developers/reference/objects/service)."}],"servers":[{"url":"https://api.shortcutco.com","description":"Production"}],"security":[{"bearerAuth":["services: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":{"Service":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"The service's id."},"object":{"type":"string","const":"service","description":"Always `service`."},"name":{"type":"string","description":"The service's name, unique in the workspace regardless of case."},"description":{"type":["string","null"],"description":"Description shown on estimates and invoices."},"serviceType":{"type":"string","enum":["standard","snow","chemical"],"description":"`standard`, `snow`, or `chemical`. Chemical services are read-only through the API."},"status":{"type":"string","enum":["active","deactivated"],"description":"Deactivated services stay on existing jobs but are no longer offered for new work."},"priceStructure":{"type":"string","enum":["per_hour","per_sqft","flat","per_man_hour"],"description":"How the price is computed: `flat` per visit, `per_sqft` by lawn area, `per_hour` per crew hour, or `per_man_hour` per person-hour on site."},"rate":{"type":["number","null"],"description":"The price in US dollars for the price structure; null when `pricingTiers` sets the price."},"pricingTiers":{"anyOf":[{"type":"array","items":{"type":"object","properties":{"upTo":{"anyOf":[{"type":"integer","minimum":0},{"type":"null"}],"description":"The top of this bracket in square feet (inclusive); null on the last, open-ended bracket."},"rate":{"type":"number","minimum":0,"description":"The per-square-foot rate in this bracket, in US dollars."}},"required":["upTo","rate"],"additionalProperties":false}},{"type":"null"}],"description":"Square-footage brackets, or null."},"completionMessage":{"type":["string","null"],"description":"The message customers get when a visit of this service is completed; null uses the default message."},"availableForWorkerAddOns":{"type":"boolean","description":"Whether crew members can add this service to a visit in the field."},"snow":{"anyOf":[{"type":"object","properties":{"triggerKind":{"type":"string","enum":["depth","any","manual","on_call"],"description":"When the service is due: `depth` at `triggerInches` of snow, `any` accumulation, `manual` (never auto-selected), or `on_call` (offered to the customer each time)."},"triggerInches":{"type":["number","null"],"description":"Inches of snow that make a `depth` service due; null for other kinds."},"offerWindowHours":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Hours an `on_call` offer stays open; null for other kinds."},"depthLadder":{"anyOf":[{"type":"array","items":{"type":"object","properties":{"upTo":{"anyOf":[{"type":"integer","minimum":0},{"type":"null"}],"description":"The top of this accumulation bracket in whole inches; null on the last, open-ended bracket."},"rate":{"type":"number","minimum":0,"description":"The price per push in this bracket, in US dollars."}},"required":["upTo","rate"],"additionalProperties":false}},{"type":"null"}],"description":"Optional price per push by accumulation, only with a `flat` price; null when not used."}},"required":["triggerKind","triggerInches","offerWindowHours","depthLadder"],"additionalProperties":false,"description":"Snow terms; present only on snow services."},{"type":"null"}],"description":"Snow terms; present only on snow services."},"createdAt":{"type":"string","format":"date-time","description":"When the service was created, ISO 8601 in UTC."},"updatedAt":{"type":"string","format":"date-time","description":"When the service last changed, ISO 8601 in UTC."}},"required":["id","object","name","description","serviceType","status","priceStructure","rate","pricingTiers","completionMessage","availableForWorkerAddOns","snow","createdAt","updatedAt"],"additionalProperties":false,"description":"A service in the workspace's catalog."},"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/services/{id}/reactivate":{"post":{"operationId":"services.reactivate","tags":["Services"],"summary":"Reactivate a service","description":"Offers a deactivated service for new work again. Chemical services are read-only (`403 feature_unavailable`). If the workspace syncs with QuickBooks, the change is queued for sync.\n\nReturns [the service object](https://docs.shortcutco.com/developers/reference/objects/service).\n\n**Errors specific to this endpoint:** [`feature_unavailable`](https://docs.shortcutco.com/developers/concepts/errors#feature_unavailable). 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/Service"},"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"}}}}}}
```
