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

# Customers

The people and businesses the workspace serves.

A customer has contact details, tags, custom field values, one or more properties, and the ids you gave it in your other systems.

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

## List customers

> Customers newest first, or by last change when \`updatedSince\` is set. Customers are the same people the app's Customers list shows. Attaching or removing a tag and changing a custom-field value count as changes to the customer.\
> \
> Returns a list of \[customer objects]\(<https://docs.shortcutco.com/developers/reference/objects/customer>).

```json
{"openapi":"3.1.0","info":{"title":"Shortcut API","version":"v1"},"tags":[{"name":"Customers","description":"A customer has contact details, tags, custom field values, one or more properties, and the ids you gave it in your other systems.\n\nFields: [The customer object](https://docs.shortcutco.com/developers/reference/objects/customer)."}],"servers":[{"url":"https://api.shortcutco.com","description":"Production"}],"security":[{"bearerAuth":["customers: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":{"Customer":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"The customer's id."},"object":{"type":"string","const":"customer","description":"Always `customer`."},"firstName":{"type":"string","description":"First name."},"lastName":{"type":"string","description":"Last name."},"companyName":{"type":["string","null"],"description":"Company name, when the customer is a business."},"email":{"type":["string","null"],"description":"Email address, or null when the customer has none on file."},"phone":{"type":["string","null"],"description":"Phone number as entered in the app."},"status":{"type":"string","enum":["active","inactive","invited"],"description":"`active` customers are served; `inactive` customers were deactivated."},"tags":{"type":"array","items":{"$ref":"#/components/schemas/TagReference"},"description":"Tags in the order they were attached."},"externalReferences":{"type":"array","items":{"$ref":"#/components/schemas/ExternalReference"},"description":"Ids this customer has in your other systems, set with `externalReference` or the external upsert."},"createdAt":{"type":"string","format":"date-time","description":"When the customer was created, ISO 8601 in UTC."},"updatedAt":{"type":"string","format":"date-time","description":"When the customer last changed, ISO 8601 in UTC."}},"required":["id","object","firstName","lastName","companyName","email","phone","status","tags","externalReferences","createdAt","updatedAt"],"additionalProperties":false,"description":"A customer: someone the workspace serves."},"TagReference":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"The tag's id."},"name":{"type":"string","description":"The tag's name as shown in the app."}},"required":["id","name"],"additionalProperties":false,"description":"A tag attached to the customer."},"ExternalReference":{"type":"object","properties":{"source":{"type":"string","description":"The system the id comes from."},"externalId":{"type":"string","description":"The object's id in that system."}},"required":["source","externalId"],"additionalProperties":false,"description":"An id this object has in another system."},"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/customers":{"get":{"operationId":"customers.list","tags":["Customers"],"summary":"List customers","description":"Customers newest first, or by last change when `updatedSince` is set. Customers are the same people the app's Customers list shows. Attaching or removing a tag and changing a custom-field value count as changes to the customer.\n\nReturns a list of [customer objects](https://docs.shortcutco.com/developers/reference/objects/customer).","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":"q","in":"query","required":false,"description":"Case-insensitive search over name, company name, and email.","schema":{"type":"string","minLength":1,"maxLength":200}},{"name":"status","in":"query","required":false,"description":"Only customers with this status.","schema":{"type":"string","enum":["active","inactive","invited"]}},{"name":"tagId","in":"query","required":false,"description":"Only customers with this tag attached.","schema":{"type":"string","format":"uuid"}},{"name":"externalSource","in":"query","required":false,"description":"With `externalId`: only the customer with this id in your system.","schema":{"type":"string","pattern":"^[a-z0-9][a-z0-9_.-]{0,63}$"}},{"name":"externalId","in":"query","required":false,"description":"With `externalSource`: only the customer with this id in your system.","schema":{"type":"string","minLength":1,"maxLength":255,"pattern":"^[^\\p{Cc}\\s/\\\\]+$"}},{"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/Customer"}},"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 customer

> Creates a customer with their first property, like adding one in the app. Email is optional; it must not belong to another customer or a team member. With \`externalReference\`, your id is saved in the same request, and a duplicate fails the request with 409. If QuickBooks is connected, the customer is queued for sync. Your automations, including those that start when a customer is created, run only if the token has \`automations:trigger\`, and then as they do for customers added in the app. Send an \`Idempotency-Key\` to retry safely.\
> \
> Returns \[the customer object]\(<https://docs.shortcutco.com/developers/reference/objects/customer).\\>
> \
> \*\*Errors specific to this endpoint:\*\* \[\`already\_exists\`]\(<https://docs.shortcutco.com/developers/concepts/errors#already\\_exists>), \[\`email\_in\_use\`]\(<https://docs.shortcutco.com/developers/concepts/errors#email\\_in\\_use>). 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":"Customers","description":"A customer has contact details, tags, custom field values, one or more properties, and the ids you gave it in your other systems.\n\nFields: [The customer object](https://docs.shortcutco.com/developers/reference/objects/customer)."}],"servers":[{"url":"https://api.shortcutco.com","description":"Production"}],"security":[{"bearerAuth":["customers: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":{"CustomerWithProperties":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"The customer's id."},"object":{"type":"string","const":"customer","description":"Always `customer`."},"firstName":{"type":"string","description":"First name."},"lastName":{"type":"string","description":"Last name."},"companyName":{"type":["string","null"],"description":"Company name, when the customer is a business."},"email":{"type":["string","null"],"description":"Email address, or null when the customer has none on file."},"phone":{"type":["string","null"],"description":"Phone number as entered in the app."},"status":{"type":"string","enum":["active","inactive","invited"],"description":"`active` customers are served; `inactive` customers were deactivated."},"tags":{"type":"array","items":{"$ref":"#/components/schemas/TagReference"},"description":"Tags in the order they were attached."},"externalReferences":{"type":"array","items":{"$ref":"#/components/schemas/ExternalReference"},"description":"Ids this customer has in your other systems, set with `externalReference` or the external upsert."},"createdAt":{"type":"string","format":"date-time","description":"When the customer was created, ISO 8601 in UTC."},"updatedAt":{"type":"string","format":"date-time","description":"When the customer last changed, ISO 8601 in UTC."},"properties":{"type":"array","items":{"$ref":"#/components/schemas/PropertySummary"},"description":"The customer's properties, oldest first."}},"required":["id","object","firstName","lastName","companyName","email","phone","status","tags","externalReferences","createdAt","updatedAt","properties"],"additionalProperties":false,"description":"A customer with their properties."},"TagReference":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"The tag's id."},"name":{"type":"string","description":"The tag's name as shown in the app."}},"required":["id","name"],"additionalProperties":false,"description":"A tag attached to the customer."},"ExternalReference":{"type":"object","properties":{"source":{"type":"string","description":"The system the id comes from."},"externalId":{"type":"string","description":"The object's id in that system."}},"required":["source","externalId"],"additionalProperties":false,"description":"An id this object has in another system."},"PropertySummary":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"The property's id."},"object":{"type":"string","const":"property","description":"Always `property`."},"label":{"type":["string","null"],"description":"A short name for the property, such as `Home`."},"address":{"type":"string","description":"The full street address."},"latitude":{"type":["number","null"],"description":"Latitude, when the address was located."},"longitude":{"type":["number","null"],"description":"Longitude, when the address was located."},"squareFeet":{"type":["number","null"],"description":"Measured lawn area in square feet."},"status":{"type":"string","enum":["active","inactive"],"description":"Inactive properties are no longer serviced."},"createdAt":{"type":"string","format":"date-time","description":"When the property was created, ISO 8601 in UTC."},"updatedAt":{"type":"string","format":"date-time","description":"When the property last changed, ISO 8601 in UTC."}},"required":["id","object","label","address","latitude","longitude","squareFeet","status","createdAt","updatedAt"],"additionalProperties":false,"description":"A property (service address) belonging to a customer."},"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/customers":{"post":{"operationId":"customers.create","tags":["Customers"],"summary":"Create a customer","description":"Creates a customer with their first property, like adding one in the app. Email is optional; it must not belong to another customer or a team member. With `externalReference`, your id is saved in the same request, and a duplicate fails the request with 409. If QuickBooks is connected, the customer is queued for sync. Your automations, including those that start when a customer is created, run only if the token has `automations:trigger`, and then as they do for customers added in the app. Send an `Idempotency-Key` to retry safely.\n\nReturns [the customer object](https://docs.shortcutco.com/developers/reference/objects/customer).\n\n**Errors specific to this endpoint:** [`already_exists`](https://docs.shortcutco.com/developers/concepts/errors#already_exists), [`email_in_use`](https://docs.shortcutco.com/developers/concepts/errors#email_in_use). 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":{"firstName":{"type":"string","minLength":1,"maxLength":100,"description":"First name."},"lastName":{"type":"string","minLength":1,"maxLength":100,"description":"Last name."},"companyName":{"anyOf":[{"type":"string","maxLength":120},{"type":"null"}],"description":"Company name, when the customer is a business. Null or empty clears it."},"email":{"type":"string","format":"email","maxLength":254,"description":"Email address. Optional: without one the customer gets no email from the app. It must not belong to another customer or a team member."},"phone":{"type":"string","maxLength":30,"description":"Phone number, such as `(406) 555-0142`. US numbers may omit the country code."},"property":{"type":"object","properties":{"address":{"type":"string","minLength":1,"maxLength":300,"description":"The service address on one line, such as `412 Elm St, Bozeman, MT 59715`."},"label":{"type":"string","maxLength":120,"description":"A short name for the property, such as `Home`."},"latitude":{"type":"number","minimum":-90,"maximum":90,"description":"Latitude of the address. Send with `longitude`."},"longitude":{"type":"number","minimum":-180,"maximum":180,"description":"Longitude of the address. Send with `latitude`."}},"required":["address"],"additionalProperties":false,"description":"The customer's first property (service address). Add more with `POST /v1/customers/{id}/properties`."},"externalReference":{"type":"object","properties":{"source":{"type":"string","pattern":"^[a-z0-9][a-z0-9_.-]{0,63}$","description":"Your name for the system the id comes from, such as `hubspot` or `mywebsite`: 1-64 lowercase letters, digits, `_`, `.`, or `-`, starting with a letter or digit."},"externalId":{"type":"string","minLength":1,"maxLength":255,"pattern":"^[^\\p{Cc}\\s/\\\\]+$","description":"The object's id in that system: 1-255 characters, no spaces, slashes, or control characters."}},"required":["source","externalId"],"additionalProperties":false,"description":"Your id for this object. It is saved with the object in the same request; if another object already has it, nothing is created and the response is 409 `already_exists`."}},"required":["firstName","lastName","property"],"additionalProperties":false,"description":"A new customer with their first property."}}}},"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/CustomerWithProperties"},"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 customer

> One customer with their tags, properties, and external ids.\
> \
> Returns \[the customer object]\(<https://docs.shortcutco.com/developers/reference/objects/customer>).

```json
{"openapi":"3.1.0","info":{"title":"Shortcut API","version":"v1"},"tags":[{"name":"Customers","description":"A customer has contact details, tags, custom field values, one or more properties, and the ids you gave it in your other systems.\n\nFields: [The customer object](https://docs.shortcutco.com/developers/reference/objects/customer)."}],"servers":[{"url":"https://api.shortcutco.com","description":"Production"}],"security":[{"bearerAuth":["customers: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":{"CustomerWithProperties":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"The customer's id."},"object":{"type":"string","const":"customer","description":"Always `customer`."},"firstName":{"type":"string","description":"First name."},"lastName":{"type":"string","description":"Last name."},"companyName":{"type":["string","null"],"description":"Company name, when the customer is a business."},"email":{"type":["string","null"],"description":"Email address, or null when the customer has none on file."},"phone":{"type":["string","null"],"description":"Phone number as entered in the app."},"status":{"type":"string","enum":["active","inactive","invited"],"description":"`active` customers are served; `inactive` customers were deactivated."},"tags":{"type":"array","items":{"$ref":"#/components/schemas/TagReference"},"description":"Tags in the order they were attached."},"externalReferences":{"type":"array","items":{"$ref":"#/components/schemas/ExternalReference"},"description":"Ids this customer has in your other systems, set with `externalReference` or the external upsert."},"createdAt":{"type":"string","format":"date-time","description":"When the customer was created, ISO 8601 in UTC."},"updatedAt":{"type":"string","format":"date-time","description":"When the customer last changed, ISO 8601 in UTC."},"properties":{"type":"array","items":{"$ref":"#/components/schemas/PropertySummary"},"description":"The customer's properties, oldest first."}},"required":["id","object","firstName","lastName","companyName","email","phone","status","tags","externalReferences","createdAt","updatedAt","properties"],"additionalProperties":false,"description":"A customer with their properties."},"TagReference":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"The tag's id."},"name":{"type":"string","description":"The tag's name as shown in the app."}},"required":["id","name"],"additionalProperties":false,"description":"A tag attached to the customer."},"ExternalReference":{"type":"object","properties":{"source":{"type":"string","description":"The system the id comes from."},"externalId":{"type":"string","description":"The object's id in that system."}},"required":["source","externalId"],"additionalProperties":false,"description":"An id this object has in another system."},"PropertySummary":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"The property's id."},"object":{"type":"string","const":"property","description":"Always `property`."},"label":{"type":["string","null"],"description":"A short name for the property, such as `Home`."},"address":{"type":"string","description":"The full street address."},"latitude":{"type":["number","null"],"description":"Latitude, when the address was located."},"longitude":{"type":["number","null"],"description":"Longitude, when the address was located."},"squareFeet":{"type":["number","null"],"description":"Measured lawn area in square feet."},"status":{"type":"string","enum":["active","inactive"],"description":"Inactive properties are no longer serviced."},"createdAt":{"type":"string","format":"date-time","description":"When the property was created, ISO 8601 in UTC."},"updatedAt":{"type":"string","format":"date-time","description":"When the property last changed, ISO 8601 in UTC."}},"required":["id","object","label","address","latitude","longitude","squareFeet","status","createdAt","updatedAt"],"additionalProperties":false,"description":"A property (service address) belonging to a customer."},"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/customers/{id}":{"get":{"operationId":"customers.get","tags":["Customers"],"summary":"Get a customer","description":"One customer with their tags, properties, and external ids.\n\nReturns [the customer object](https://docs.shortcutco.com/developers/reference/objects/customer).","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/CustomerWithProperties"},"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 customer

> Changes a customer's name, company, email, or phone, like editing their profile in the app. Fields you leave out are unchanged. A new email must not belong to another customer or a team member; changing it clears the workspace's delivery blocks for both addresses so the next email is tried again. If QuickBooks is connected, the change is queued for sync.\
> \
> Returns \[the customer object]\(<https://docs.shortcutco.com/developers/reference/objects/customer).\\>
> \
> \*\*Errors specific to this endpoint:\*\* \[\`email\_in\_use\`]\(<https://docs.shortcutco.com/developers/concepts/errors#email\\_in\\_use>). 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":"Customers","description":"A customer has contact details, tags, custom field values, one or more properties, and the ids you gave it in your other systems.\n\nFields: [The customer object](https://docs.shortcutco.com/developers/reference/objects/customer)."}],"servers":[{"url":"https://api.shortcutco.com","description":"Production"}],"security":[{"bearerAuth":["customers: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":{"Customer":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"The customer's id."},"object":{"type":"string","const":"customer","description":"Always `customer`."},"firstName":{"type":"string","description":"First name."},"lastName":{"type":"string","description":"Last name."},"companyName":{"type":["string","null"],"description":"Company name, when the customer is a business."},"email":{"type":["string","null"],"description":"Email address, or null when the customer has none on file."},"phone":{"type":["string","null"],"description":"Phone number as entered in the app."},"status":{"type":"string","enum":["active","inactive","invited"],"description":"`active` customers are served; `inactive` customers were deactivated."},"tags":{"type":"array","items":{"$ref":"#/components/schemas/TagReference"},"description":"Tags in the order they were attached."},"externalReferences":{"type":"array","items":{"$ref":"#/components/schemas/ExternalReference"},"description":"Ids this customer has in your other systems, set with `externalReference` or the external upsert."},"createdAt":{"type":"string","format":"date-time","description":"When the customer was created, ISO 8601 in UTC."},"updatedAt":{"type":"string","format":"date-time","description":"When the customer last changed, ISO 8601 in UTC."}},"required":["id","object","firstName","lastName","companyName","email","phone","status","tags","externalReferences","createdAt","updatedAt"],"additionalProperties":false,"description":"A customer: someone the workspace serves."},"TagReference":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"The tag's id."},"name":{"type":"string","description":"The tag's name as shown in the app."}},"required":["id","name"],"additionalProperties":false,"description":"A tag attached to the customer."},"ExternalReference":{"type":"object","properties":{"source":{"type":"string","description":"The system the id comes from."},"externalId":{"type":"string","description":"The object's id in that system."}},"required":["source","externalId"],"additionalProperties":false,"description":"An id this object has in another system."},"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/customers/{id}":{"patch":{"operationId":"customers.update","tags":["Customers"],"summary":"Update a customer","description":"Changes a customer's name, company, email, or phone, like editing their profile in the app. Fields you leave out are unchanged. A new email must not belong to another customer or a team member; changing it clears the workspace's delivery blocks for both addresses so the next email is tried again. If QuickBooks is connected, the change is queued for sync.\n\nReturns [the customer object](https://docs.shortcutco.com/developers/reference/objects/customer).\n\n**Errors specific to this endpoint:** [`email_in_use`](https://docs.shortcutco.com/developers/concepts/errors#email_in_use). 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":{"firstName":{"type":"string","minLength":1,"maxLength":100,"description":"First name."},"lastName":{"type":"string","minLength":1,"maxLength":100,"description":"Last name."},"companyName":{"anyOf":[{"type":"string","maxLength":120},{"type":"null"}],"description":"Company name, when the customer is a business. Null or empty clears it."},"email":{"type":"string","format":"email","maxLength":254,"description":"Email address. It must not belong to another customer or a team member in the workspace."},"phone":{"anyOf":[{"type":"string","maxLength":30,"description":"Phone number, such as `(406) 555-0142`. US numbers may omit the country code."},{"type":"null"}],"description":"Phone number. Null or empty clears it."}},"additionalProperties":false,"description":"The contact fields to change. Fields you leave out are unchanged."}}}},"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/Customer"},"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 customer

> Marks the customer inactive, records a churn reason, and pauses every pending, scheduled, or paused job they have, exactly as archiving in the app does. A note on the customer names the token. Every body field is optional; send \`{}\` when you have nothing to add. Deactivating an inactive customer changes nothing. If the token has \`automations:trigger\`, automations that start on a customer status change run as they do in the app. Undo with \`POST /v1/customers/{id}/reactivate\`.

```json
{"openapi":"3.1.0","info":{"title":"Shortcut API","version":"v1"},"tags":[{"name":"Customers","description":"A customer has contact details, tags, custom field values, one or more properties, and the ids you gave it in your other systems.\n\nFields: [The customer object](https://docs.shortcutco.com/developers/reference/objects/customer)."}],"servers":[{"url":"https://api.shortcutco.com","description":"Production"}],"security":[{"bearerAuth":["customers: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":{"Customer":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"The customer's id."},"object":{"type":"string","const":"customer","description":"Always `customer`."},"firstName":{"type":"string","description":"First name."},"lastName":{"type":"string","description":"Last name."},"companyName":{"type":["string","null"],"description":"Company name, when the customer is a business."},"email":{"type":["string","null"],"description":"Email address, or null when the customer has none on file."},"phone":{"type":["string","null"],"description":"Phone number as entered in the app."},"status":{"type":"string","enum":["active","inactive","invited"],"description":"`active` customers are served; `inactive` customers were deactivated."},"tags":{"type":"array","items":{"$ref":"#/components/schemas/TagReference"},"description":"Tags in the order they were attached."},"externalReferences":{"type":"array","items":{"$ref":"#/components/schemas/ExternalReference"},"description":"Ids this customer has in your other systems, set with `externalReference` or the external upsert."},"createdAt":{"type":"string","format":"date-time","description":"When the customer was created, ISO 8601 in UTC."},"updatedAt":{"type":"string","format":"date-time","description":"When the customer last changed, ISO 8601 in UTC."}},"required":["id","object","firstName","lastName","companyName","email","phone","status","tags","externalReferences","createdAt","updatedAt"],"additionalProperties":false,"description":"A customer: someone the workspace serves."},"TagReference":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"The tag's id."},"name":{"type":"string","description":"The tag's name as shown in the app."}},"required":["id","name"],"additionalProperties":false,"description":"A tag attached to the customer."},"ExternalReference":{"type":"object","properties":{"source":{"type":"string","description":"The system the id comes from."},"externalId":{"type":"string","description":"The object's id in that system."}},"required":["source","externalId"],"additionalProperties":false,"description":"An id this object has in another system."},"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/customers/{id}/deactivate":{"post":{"operationId":"customers.deactivate","tags":["Customers"],"summary":"Deactivate a customer","description":"Marks the customer inactive, records a churn reason, and pauses every pending, scheduled, or paused job they have, exactly as archiving in the app does. A note on the customer names the token. Every body field is optional; send `{}` when you have nothing to add. Deactivating an inactive customer changes nothing. If the token has `automations:trigger`, automations that start on a customer status change run as they do in the app. Undo with `POST /v1/customers/{id}/reactivate`.","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":{"reason":{"type":"string","maxLength":500,"description":"Why, saved on the customer's note in the app."},"churnReason":{"type":"string","enum":["moved_away","price","service_issues","unknown"],"description":"The churn reason for retention reports. Defaults to `unknown`."}},"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":{"type":"object","properties":{"customer":{"$ref":"#/components/schemas/Customer"},"changed":{"type":"boolean","description":"False when the customer was already inactive."},"pausedJobs":{"type":"integer","description":"How many of the customer's jobs were paused."}},"required":["customer","changed","pausedJobs"],"additionalProperties":false},"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"}}}}}}
```

## Link a customer to your id

> Records \`externalId\` as this customer's id in \`source\`, so the external lookup and upsert find it. Linking is always explicit; the API never matches a customer to your id by email or address. Repeating the same link changes nothing. If the id already belongs to another customer, or this customer already has a different id in \`source\`, the request fails with 409 and nothing changes.\
> \
> Returns \[the customer object]\(<https://docs.shortcutco.com/developers/reference/objects/customer).\\>
> \
> \*\*Errors specific to this endpoint:\*\* \[\`already\_exists\`]\(<https://docs.shortcutco.com/developers/concepts/errors#already\\_exists>), \[\`external\_reference\_exists\`]\(<https://docs.shortcutco.com/developers/concepts/errors#external\\_reference\\_exists>). 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":"Customers","description":"A customer has contact details, tags, custom field values, one or more properties, and the ids you gave it in your other systems.\n\nFields: [The customer object](https://docs.shortcutco.com/developers/reference/objects/customer)."}],"servers":[{"url":"https://api.shortcutco.com","description":"Production"}],"security":[{"bearerAuth":["customers: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":{"CustomerWithProperties":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"The customer's id."},"object":{"type":"string","const":"customer","description":"Always `customer`."},"firstName":{"type":"string","description":"First name."},"lastName":{"type":"string","description":"Last name."},"companyName":{"type":["string","null"],"description":"Company name, when the customer is a business."},"email":{"type":["string","null"],"description":"Email address, or null when the customer has none on file."},"phone":{"type":["string","null"],"description":"Phone number as entered in the app."},"status":{"type":"string","enum":["active","inactive","invited"],"description":"`active` customers are served; `inactive` customers were deactivated."},"tags":{"type":"array","items":{"$ref":"#/components/schemas/TagReference"},"description":"Tags in the order they were attached."},"externalReferences":{"type":"array","items":{"$ref":"#/components/schemas/ExternalReference"},"description":"Ids this customer has in your other systems, set with `externalReference` or the external upsert."},"createdAt":{"type":"string","format":"date-time","description":"When the customer was created, ISO 8601 in UTC."},"updatedAt":{"type":"string","format":"date-time","description":"When the customer last changed, ISO 8601 in UTC."},"properties":{"type":"array","items":{"$ref":"#/components/schemas/PropertySummary"},"description":"The customer's properties, oldest first."}},"required":["id","object","firstName","lastName","companyName","email","phone","status","tags","externalReferences","createdAt","updatedAt","properties"],"additionalProperties":false,"description":"A customer with their properties."},"TagReference":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"The tag's id."},"name":{"type":"string","description":"The tag's name as shown in the app."}},"required":["id","name"],"additionalProperties":false,"description":"A tag attached to the customer."},"ExternalReference":{"type":"object","properties":{"source":{"type":"string","description":"The system the id comes from."},"externalId":{"type":"string","description":"The object's id in that system."}},"required":["source","externalId"],"additionalProperties":false,"description":"An id this object has in another system."},"PropertySummary":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"The property's id."},"object":{"type":"string","const":"property","description":"Always `property`."},"label":{"type":["string","null"],"description":"A short name for the property, such as `Home`."},"address":{"type":"string","description":"The full street address."},"latitude":{"type":["number","null"],"description":"Latitude, when the address was located."},"longitude":{"type":["number","null"],"description":"Longitude, when the address was located."},"squareFeet":{"type":["number","null"],"description":"Measured lawn area in square feet."},"status":{"type":"string","enum":["active","inactive"],"description":"Inactive properties are no longer serviced."},"createdAt":{"type":"string","format":"date-time","description":"When the property was created, ISO 8601 in UTC."},"updatedAt":{"type":"string","format":"date-time","description":"When the property last changed, ISO 8601 in UTC."}},"required":["id","object","label","address","latitude","longitude","squareFeet","status","createdAt","updatedAt"],"additionalProperties":false,"description":"A property (service address) belonging to a customer."},"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/customers/{id}/external-references/{source}":{"put":{"operationId":"customers.externalReferences.link","tags":["Customers"],"summary":"Link a customer to your id","description":"Records `externalId` as this customer's id in `source`, so the external lookup and upsert find it. Linking is always explicit; the API never matches a customer to your id by email or address. Repeating the same link changes nothing. If the id already belongs to another customer, or this customer already has a different id in `source`, the request fails with 409 and nothing changes.\n\nReturns [the customer object](https://docs.shortcutco.com/developers/reference/objects/customer).\n\n**Errors specific to this endpoint:** [`already_exists`](https://docs.shortcutco.com/developers/concepts/errors#already_exists), [`external_reference_exists`](https://docs.shortcutco.com/developers/concepts/errors#external_reference_exists). 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":"source","in":"path","required":true,"description":"Your name for the system the id comes from, such as `hubspot` or `mywebsite`: 1-64 lowercase letters, digits, `_`, `.`, or `-`, starting with a letter or digit.","schema":{"type":"string","pattern":"^[a-z0-9][a-z0-9_.-]{0,63}$"}},{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"externalId":{"type":"string","minLength":1,"maxLength":255,"pattern":"^[^\\p{Cc}\\s/\\\\]+$","description":"The object's id in that system: 1-255 characters, no spaces, slashes, or control characters."}},"required":["externalId"],"additionalProperties":false,"description":"The object's id in that system."}}}},"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/CustomerWithProperties"},"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"}}}}}}
```

## Unlink a customer from your id

> Removes this customer's id in \`source\`. The customer itself is unchanged. Unlinking when there is no link changes nothing.\
> \
> Returns \[the customer object]\(<https://docs.shortcutco.com/developers/reference/objects/customer>).

```json
{"openapi":"3.1.0","info":{"title":"Shortcut API","version":"v1"},"tags":[{"name":"Customers","description":"A customer has contact details, tags, custom field values, one or more properties, and the ids you gave it in your other systems.\n\nFields: [The customer object](https://docs.shortcutco.com/developers/reference/objects/customer)."}],"servers":[{"url":"https://api.shortcutco.com","description":"Production"}],"security":[{"bearerAuth":["customers: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":{"CustomerWithProperties":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"The customer's id."},"object":{"type":"string","const":"customer","description":"Always `customer`."},"firstName":{"type":"string","description":"First name."},"lastName":{"type":"string","description":"Last name."},"companyName":{"type":["string","null"],"description":"Company name, when the customer is a business."},"email":{"type":["string","null"],"description":"Email address, or null when the customer has none on file."},"phone":{"type":["string","null"],"description":"Phone number as entered in the app."},"status":{"type":"string","enum":["active","inactive","invited"],"description":"`active` customers are served; `inactive` customers were deactivated."},"tags":{"type":"array","items":{"$ref":"#/components/schemas/TagReference"},"description":"Tags in the order they were attached."},"externalReferences":{"type":"array","items":{"$ref":"#/components/schemas/ExternalReference"},"description":"Ids this customer has in your other systems, set with `externalReference` or the external upsert."},"createdAt":{"type":"string","format":"date-time","description":"When the customer was created, ISO 8601 in UTC."},"updatedAt":{"type":"string","format":"date-time","description":"When the customer last changed, ISO 8601 in UTC."},"properties":{"type":"array","items":{"$ref":"#/components/schemas/PropertySummary"},"description":"The customer's properties, oldest first."}},"required":["id","object","firstName","lastName","companyName","email","phone","status","tags","externalReferences","createdAt","updatedAt","properties"],"additionalProperties":false,"description":"A customer with their properties."},"TagReference":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"The tag's id."},"name":{"type":"string","description":"The tag's name as shown in the app."}},"required":["id","name"],"additionalProperties":false,"description":"A tag attached to the customer."},"ExternalReference":{"type":"object","properties":{"source":{"type":"string","description":"The system the id comes from."},"externalId":{"type":"string","description":"The object's id in that system."}},"required":["source","externalId"],"additionalProperties":false,"description":"An id this object has in another system."},"PropertySummary":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"The property's id."},"object":{"type":"string","const":"property","description":"Always `property`."},"label":{"type":["string","null"],"description":"A short name for the property, such as `Home`."},"address":{"type":"string","description":"The full street address."},"latitude":{"type":["number","null"],"description":"Latitude, when the address was located."},"longitude":{"type":["number","null"],"description":"Longitude, when the address was located."},"squareFeet":{"type":["number","null"],"description":"Measured lawn area in square feet."},"status":{"type":"string","enum":["active","inactive"],"description":"Inactive properties are no longer serviced."},"createdAt":{"type":"string","format":"date-time","description":"When the property was created, ISO 8601 in UTC."},"updatedAt":{"type":"string","format":"date-time","description":"When the property last changed, ISO 8601 in UTC."}},"required":["id","object","label","address","latitude","longitude","squareFeet","status","createdAt","updatedAt"],"additionalProperties":false,"description":"A property (service address) belonging to a customer."},"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/customers/{id}/external-references/{source}":{"delete":{"operationId":"customers.externalReferences.unlink","tags":["Customers"],"summary":"Unlink a customer from your id","description":"Removes this customer's id in `source`. The customer itself is unchanged. Unlinking when there is no link changes nothing.\n\nReturns [the customer object](https://docs.shortcutco.com/developers/reference/objects/customer).","parameters":[{"name":"id","in":"path","required":true,"description":"The object's id.","schema":{"type":"string","format":"uuid"}},{"name":"source","in":"path","required":true,"description":"Your name for the system the id comes from, such as `hubspot` or `mywebsite`: 1-64 lowercase letters, digits, `_`, `.`, or `-`, starting with a letter or digit.","schema":{"type":"string","pattern":"^[a-z0-9][a-z0-9_.-]{0,63}$"}}],"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/CustomerWithProperties"},"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 customer

> Marks an inactive customer active again and clears the churn reason, as reactivating in the app does. A customer who is not inactive is left alone: \`changed: false\` with \`resumeJobs: keep\_paused\`, and 409 \`customer\_not\_inactive\` when asked to resume jobs. Their paused jobs stay paused unless \`resumeJobs\` is \`now\` or \`date\`, which resumes every paused job and needs the \`jobs:write\` scope. Every body field is optional; send \`{}\` to reactivate without resuming jobs. A note on the customer names the token. If the token has \`automations:trigger\`, automations that start on a customer status change run as they do in the app.\
> \
> \*\*Errors specific to this endpoint:\*\* \[\`customer\_not\_inactive\`]\(<https://docs.shortcutco.com/developers/concepts/errors#customer\\_not\\_inactive>), \[\`jobs\_not\_resumable\`]\(<https://docs.shortcutco.com/developers/concepts/errors#jobs\\_not\\_resumable>). 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":"Customers","description":"A customer has contact details, tags, custom field values, one or more properties, and the ids you gave it in your other systems.\n\nFields: [The customer object](https://docs.shortcutco.com/developers/reference/objects/customer)."}],"servers":[{"url":"https://api.shortcutco.com","description":"Production"}],"security":[{"bearerAuth":["customers: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":{"Customer":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"The customer's id."},"object":{"type":"string","const":"customer","description":"Always `customer`."},"firstName":{"type":"string","description":"First name."},"lastName":{"type":"string","description":"Last name."},"companyName":{"type":["string","null"],"description":"Company name, when the customer is a business."},"email":{"type":["string","null"],"description":"Email address, or null when the customer has none on file."},"phone":{"type":["string","null"],"description":"Phone number as entered in the app."},"status":{"type":"string","enum":["active","inactive","invited"],"description":"`active` customers are served; `inactive` customers were deactivated."},"tags":{"type":"array","items":{"$ref":"#/components/schemas/TagReference"},"description":"Tags in the order they were attached."},"externalReferences":{"type":"array","items":{"$ref":"#/components/schemas/ExternalReference"},"description":"Ids this customer has in your other systems, set with `externalReference` or the external upsert."},"createdAt":{"type":"string","format":"date-time","description":"When the customer was created, ISO 8601 in UTC."},"updatedAt":{"type":"string","format":"date-time","description":"When the customer last changed, ISO 8601 in UTC."}},"required":["id","object","firstName","lastName","companyName","email","phone","status","tags","externalReferences","createdAt","updatedAt"],"additionalProperties":false,"description":"A customer: someone the workspace serves."},"TagReference":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"The tag's id."},"name":{"type":"string","description":"The tag's name as shown in the app."}},"required":["id","name"],"additionalProperties":false,"description":"A tag attached to the customer."},"ExternalReference":{"type":"object","properties":{"source":{"type":"string","description":"The system the id comes from."},"externalId":{"type":"string","description":"The object's id in that system."}},"required":["source","externalId"],"additionalProperties":false,"description":"An id this object has in another system."},"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/customers/{id}/reactivate":{"post":{"operationId":"customers.reactivate","tags":["Customers"],"summary":"Reactivate a customer","description":"Marks an inactive customer active again and clears the churn reason, as reactivating in the app does. A customer who is not inactive is left alone: `changed: false` with `resumeJobs: keep_paused`, and 409 `customer_not_inactive` when asked to resume jobs. Their paused jobs stay paused unless `resumeJobs` is `now` or `date`, which resumes every paused job and needs the `jobs:write` scope. Every body field is optional; send `{}` to reactivate without resuming jobs. A note on the customer names the token. If the token has `automations:trigger`, automations that start on a customer status change run as they do in the app.\n\n**Errors specific to this endpoint:** [`customer_not_inactive`](https://docs.shortcutco.com/developers/concepts/errors#customer_not_inactive), [`jobs_not_resumable`](https://docs.shortcutco.com/developers/concepts/errors#jobs_not_resumable). 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":{"resumeJobs":{"type":"string","enum":["keep_paused","now","date"],"description":"What happens to the customer's paused jobs: `keep_paused` (the default) leaves them paused, `now` resumes them from today, `date` from `resumeDate`. Resuming needs the `jobs:write` scope."},"resumeDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"With `resumeJobs: date`, the workspace-local date (YYYY-MM-DD, today or later) jobs resume from."},"reason":{"type":"string","maxLength":500,"description":"Why, saved on the customer's note in the app."}},"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":{"type":"object","properties":{"customer":{"$ref":"#/components/schemas/Customer"},"changed":{"type":"boolean","description":"False when the customer was already active and no jobs resumed."},"resumedJobs":{"type":"integer","description":"How many paused jobs were resumed."}},"required":["customer","changed","resumedJobs"],"additionalProperties":false},"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"}}}}}}
```

## List a customer's tags

> The tags attached to the customer, in the order they were attached.

```json
{"openapi":"3.1.0","info":{"title":"Shortcut API","version":"v1"},"tags":[{"name":"Customers","description":"A customer has contact details, tags, custom field values, one or more properties, and the ids you gave it in your other systems.\n\nFields: [The customer object](https://docs.shortcutco.com/developers/reference/objects/customer)."}],"servers":[{"url":"https://api.shortcutco.com","description":"Production"}],"security":[{"bearerAuth":["customers: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":{"TagReference":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"The tag's id."},"name":{"type":"string","description":"The tag's name as shown in the app."}},"required":["id","name"],"additionalProperties":false,"description":"A tag attached to the customer."},"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/customers/{id}/tags":{"get":{"operationId":"customers.tags.list","tags":["Customers"],"summary":"List a customer's tags","description":"The tags attached to the customer, in the order they were attached.","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":{"type":"array","items":{"$ref":"#/components/schemas/TagReference"},"description":"The customer's tags in the order they were attached."},"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"}}}}}}
```

## Set a customer's tags

> Replaces the customer's whole tag list with \`tagIds\`: missing tags are attached (in the order given) and every tag not listed is removed. Tags must exist (\`POST /v1/tags\` creates one). Any change counts as a change to the customer for \`updatedSince\`. If the token has \`automations:trigger\`, automations that start when a tag is added or removed run as they do for changes in the app.

```json
{"openapi":"3.1.0","info":{"title":"Shortcut API","version":"v1"},"tags":[{"name":"Customers","description":"A customer has contact details, tags, custom field values, one or more properties, and the ids you gave it in your other systems.\n\nFields: [The customer object](https://docs.shortcutco.com/developers/reference/objects/customer)."}],"servers":[{"url":"https://api.shortcutco.com","description":"Production"}],"security":[{"bearerAuth":["customers: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":{"TagReference":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"The tag's id."},"name":{"type":"string","description":"The tag's name as shown in the app."}},"required":["id","name"],"additionalProperties":false,"description":"A tag attached to the customer."},"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/customers/{id}/tags":{"put":{"operationId":"customers.tags.set","tags":["Customers"],"summary":"Set a customer's tags","description":"Replaces the customer's whole tag list with `tagIds`: missing tags are attached (in the order given) and every tag not listed is removed. Tags must exist (`POST /v1/tags` creates one). Any change counts as a change to the customer for `updatedSince`. If the token has `automations:trigger`, automations that start when a tag is added or removed run as they do for changes in the app.","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":{"tagIds":{"type":"array","items":{"type":"string","format":"uuid"},"maxItems":100,"description":"Every tag the customer should have, by id. Tags not listed are removed; an empty list removes all."}},"required":["tagIds"],"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":{"type":"array","items":{"$ref":"#/components/schemas/TagReference"},"description":"The customer's tags in the order they were attached."},"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 customer by your id

> The customer your id maps to, as \`GET /v1/customers/{id}\` returns it, or 404.\
> \
> Returns \[the customer object]\(<https://docs.shortcutco.com/developers/reference/objects/customer>).

```json
{"openapi":"3.1.0","info":{"title":"Shortcut API","version":"v1"},"tags":[{"name":"Customers","description":"A customer has contact details, tags, custom field values, one or more properties, and the ids you gave it in your other systems.\n\nFields: [The customer object](https://docs.shortcutco.com/developers/reference/objects/customer)."}],"servers":[{"url":"https://api.shortcutco.com","description":"Production"}],"security":[{"bearerAuth":["customers: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":{"CustomerWithProperties":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"The customer's id."},"object":{"type":"string","const":"customer","description":"Always `customer`."},"firstName":{"type":"string","description":"First name."},"lastName":{"type":"string","description":"Last name."},"companyName":{"type":["string","null"],"description":"Company name, when the customer is a business."},"email":{"type":["string","null"],"description":"Email address, or null when the customer has none on file."},"phone":{"type":["string","null"],"description":"Phone number as entered in the app."},"status":{"type":"string","enum":["active","inactive","invited"],"description":"`active` customers are served; `inactive` customers were deactivated."},"tags":{"type":"array","items":{"$ref":"#/components/schemas/TagReference"},"description":"Tags in the order they were attached."},"externalReferences":{"type":"array","items":{"$ref":"#/components/schemas/ExternalReference"},"description":"Ids this customer has in your other systems, set with `externalReference` or the external upsert."},"createdAt":{"type":"string","format":"date-time","description":"When the customer was created, ISO 8601 in UTC."},"updatedAt":{"type":"string","format":"date-time","description":"When the customer last changed, ISO 8601 in UTC."},"properties":{"type":"array","items":{"$ref":"#/components/schemas/PropertySummary"},"description":"The customer's properties, oldest first."}},"required":["id","object","firstName","lastName","companyName","email","phone","status","tags","externalReferences","createdAt","updatedAt","properties"],"additionalProperties":false,"description":"A customer with their properties."},"TagReference":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"The tag's id."},"name":{"type":"string","description":"The tag's name as shown in the app."}},"required":["id","name"],"additionalProperties":false,"description":"A tag attached to the customer."},"ExternalReference":{"type":"object","properties":{"source":{"type":"string","description":"The system the id comes from."},"externalId":{"type":"string","description":"The object's id in that system."}},"required":["source","externalId"],"additionalProperties":false,"description":"An id this object has in another system."},"PropertySummary":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"The property's id."},"object":{"type":"string","const":"property","description":"Always `property`."},"label":{"type":["string","null"],"description":"A short name for the property, such as `Home`."},"address":{"type":"string","description":"The full street address."},"latitude":{"type":["number","null"],"description":"Latitude, when the address was located."},"longitude":{"type":["number","null"],"description":"Longitude, when the address was located."},"squareFeet":{"type":["number","null"],"description":"Measured lawn area in square feet."},"status":{"type":"string","enum":["active","inactive"],"description":"Inactive properties are no longer serviced."},"createdAt":{"type":"string","format":"date-time","description":"When the property was created, ISO 8601 in UTC."},"updatedAt":{"type":"string","format":"date-time","description":"When the property last changed, ISO 8601 in UTC."}},"required":["id","object","label","address","latitude","longitude","squareFeet","status","createdAt","updatedAt"],"additionalProperties":false,"description":"A property (service address) belonging to a customer."},"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/customers/external/{source}/{externalId}":{"get":{"operationId":"customers.external.get","tags":["Customers"],"summary":"Get a customer by your id","description":"The customer your id maps to, as `GET /v1/customers/{id}` returns it, or 404.\n\nReturns [the customer object](https://docs.shortcutco.com/developers/reference/objects/customer).","parameters":[{"name":"source","in":"path","required":true,"description":"Your name for the system the id comes from, such as `hubspot` or `mywebsite`: 1-64 lowercase letters, digits, `_`, `.`, or `-`, starting with a letter or digit.","schema":{"type":"string","pattern":"^[a-z0-9][a-z0-9_.-]{0,63}$"}},{"name":"externalId","in":"path","required":true,"description":"The object's id in that system: 1-255 characters, no spaces, slashes, or control characters.","schema":{"type":"string","minLength":1,"maxLength":255,"pattern":"^[^\\p{Cc}\\s/\\\\]+$"}}],"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/CustomerWithProperties"},"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"}}}}}}
```

## Create or update a customer by your id

> The sync endpoint. If your id is new, creates the customer as \`POST /v1/customers\` does and saves the id (\`created: true\`, status 201). If it exists, applies the contact fields that differ from the stored ones as \`PATCH\` does and ignores \`property\` (\`created: false\`, status 200); a request that changes nothing writes nothing. Concurrent requests for the same id run one after another, so they never create two customers.\
> \
> \*\*Errors specific to this endpoint:\*\* \[\`email\_in\_use\`]\(<https://docs.shortcutco.com/developers/concepts/errors#email\\_in\\_use>), \[\`external\_reference\_changed\`]\(<https://docs.shortcutco.com/developers/concepts/errors#external\\_reference\\_changed>). 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":"Customers","description":"A customer has contact details, tags, custom field values, one or more properties, and the ids you gave it in your other systems.\n\nFields: [The customer object](https://docs.shortcutco.com/developers/reference/objects/customer)."}],"servers":[{"url":"https://api.shortcutco.com","description":"Production"}],"security":[{"bearerAuth":["customers: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":{"CustomerWithProperties":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"The customer's id."},"object":{"type":"string","const":"customer","description":"Always `customer`."},"firstName":{"type":"string","description":"First name."},"lastName":{"type":"string","description":"Last name."},"companyName":{"type":["string","null"],"description":"Company name, when the customer is a business."},"email":{"type":["string","null"],"description":"Email address, or null when the customer has none on file."},"phone":{"type":["string","null"],"description":"Phone number as entered in the app."},"status":{"type":"string","enum":["active","inactive","invited"],"description":"`active` customers are served; `inactive` customers were deactivated."},"tags":{"type":"array","items":{"$ref":"#/components/schemas/TagReference"},"description":"Tags in the order they were attached."},"externalReferences":{"type":"array","items":{"$ref":"#/components/schemas/ExternalReference"},"description":"Ids this customer has in your other systems, set with `externalReference` or the external upsert."},"createdAt":{"type":"string","format":"date-time","description":"When the customer was created, ISO 8601 in UTC."},"updatedAt":{"type":"string","format":"date-time","description":"When the customer last changed, ISO 8601 in UTC."},"properties":{"type":"array","items":{"$ref":"#/components/schemas/PropertySummary"},"description":"The customer's properties, oldest first."}},"required":["id","object","firstName","lastName","companyName","email","phone","status","tags","externalReferences","createdAt","updatedAt","properties"],"additionalProperties":false,"description":"A customer with their properties."},"TagReference":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"The tag's id."},"name":{"type":"string","description":"The tag's name as shown in the app."}},"required":["id","name"],"additionalProperties":false,"description":"A tag attached to the customer."},"ExternalReference":{"type":"object","properties":{"source":{"type":"string","description":"The system the id comes from."},"externalId":{"type":"string","description":"The object's id in that system."}},"required":["source","externalId"],"additionalProperties":false,"description":"An id this object has in another system."},"PropertySummary":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"The property's id."},"object":{"type":"string","const":"property","description":"Always `property`."},"label":{"type":["string","null"],"description":"A short name for the property, such as `Home`."},"address":{"type":"string","description":"The full street address."},"latitude":{"type":["number","null"],"description":"Latitude, when the address was located."},"longitude":{"type":["number","null"],"description":"Longitude, when the address was located."},"squareFeet":{"type":["number","null"],"description":"Measured lawn area in square feet."},"status":{"type":"string","enum":["active","inactive"],"description":"Inactive properties are no longer serviced."},"createdAt":{"type":"string","format":"date-time","description":"When the property was created, ISO 8601 in UTC."},"updatedAt":{"type":"string","format":"date-time","description":"When the property last changed, ISO 8601 in UTC."}},"required":["id","object","label","address","latitude","longitude","squareFeet","status","createdAt","updatedAt"],"additionalProperties":false,"description":"A property (service address) belonging to a customer."},"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/customers/external/{source}/{externalId}":{"put":{"operationId":"customers.external.upsert","tags":["Customers"],"summary":"Create or update a customer by your id","description":"The sync endpoint. If your id is new, creates the customer as `POST /v1/customers` does and saves the id (`created: true`, status 201). If it exists, applies the contact fields that differ from the stored ones as `PATCH` does and ignores `property` (`created: false`, status 200); a request that changes nothing writes nothing. Concurrent requests for the same id run one after another, so they never create two customers.\n\n**Errors specific to this endpoint:** [`email_in_use`](https://docs.shortcutco.com/developers/concepts/errors#email_in_use), [`external_reference_changed`](https://docs.shortcutco.com/developers/concepts/errors#external_reference_changed). Every endpoint can also return the [common errors](https://docs.shortcutco.com/developers/concepts/errors).","parameters":[{"name":"source","in":"path","required":true,"description":"Your name for the system the id comes from, such as `hubspot` or `mywebsite`: 1-64 lowercase letters, digits, `_`, `.`, or `-`, starting with a letter or digit.","schema":{"type":"string","pattern":"^[a-z0-9][a-z0-9_.-]{0,63}$"}},{"name":"externalId","in":"path","required":true,"description":"The object's id in that system: 1-255 characters, no spaces, slashes, or control characters.","schema":{"type":"string","minLength":1,"maxLength":255,"pattern":"^[^\\p{Cc}\\s/\\\\]+$"}},{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"firstName":{"type":"string","minLength":1,"maxLength":100,"description":"First name."},"lastName":{"type":"string","minLength":1,"maxLength":100,"description":"Last name."},"companyName":{"anyOf":[{"type":"string","maxLength":120},{"type":"null"}],"description":"Company name, when the customer is a business. Null or empty clears it."},"email":{"type":"string","format":"email","maxLength":254,"description":"Email address. Optional: without one the customer gets no email from the app. It must not belong to another customer or a team member."},"phone":{"type":"string","maxLength":30,"description":"Phone number, such as `(406) 555-0142`. US numbers may omit the country code."},"property":{"type":"object","properties":{"address":{"type":"string","minLength":1,"maxLength":300,"description":"The service address on one line, such as `412 Elm St, Bozeman, MT 59715`."},"label":{"type":"string","maxLength":120,"description":"A short name for the property, such as `Home`."},"latitude":{"type":"number","minimum":-90,"maximum":90,"description":"Latitude of the address. Send with `longitude`."},"longitude":{"type":"number","minimum":-180,"maximum":180,"description":"Longitude of the address. Send with `latitude`."}},"required":["address"],"additionalProperties":false,"description":"The customer's first property (service address). Add more with `POST /v1/customers/{id}/properties`."}},"required":["firstName","lastName","property"],"additionalProperties":false,"description":"The customer as in `POST /v1/customers`. When the reference is new the customer is created; when it exists, the contact fields update the mapped customer and `property` is ignored."}}}},"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":"object","properties":{"created":{"type":"boolean","description":"True when this request created the customer."},"customer":{"$ref":"#/components/schemas/CustomerWithProperties"}},"required":["created","customer"],"additionalProperties":false},"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}}}},"201":{"description":"Your id was new: the customer was created and your id saved (`created: true`).","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":"object","properties":{"created":{"type":"boolean","description":"True when this request created the customer."},"customer":{"$ref":"#/components/schemas/CustomerWithProperties"}},"required":["created","customer"],"additionalProperties":false},"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"}}}}}}
```
