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

# Leads

Requests for service, from your website, ads, or another system.

A lead is a request for service. Creating one through the API works like your website form: staff are notified, and the lead appears in Customers with the Lead label.

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

## List leads

> Leads newest first, or by last change when \`updatedSince\` is set. Dismissed leads are included unless you filter by \`status\`. \`externalSource\` and \`externalId\` together narrow the list to the lead with that id in your system.\
> \
> Returns a list of \[lead objects]\(<https://docs.shortcutco.com/developers/reference/objects/lead>).

```json
{"openapi":"3.1.0","info":{"title":"Shortcut API","version":"v1"},"tags":[{"name":"Leads","description":"A lead is a request for service. Creating one through the API works like your website form: staff are notified, and the lead appears in Customers with the Lead label.\n\nFields: [The lead object](https://docs.shortcutco.com/developers/reference/objects/lead)."}],"servers":[{"url":"https://api.shortcutco.com","description":"Production"}],"security":[{"bearerAuth":["leads: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":{"Lead":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"The lead's id."},"object":{"type":"string","const":"lead","description":"Always `lead`."},"firstName":{"type":"string","description":"First name."},"lastName":{"type":"string","description":"Last name."},"companyName":{"type":["string","null"],"description":"Company name, when the lead is a business."},"email":{"type":["string","null"],"description":"Email address, or null when none is on file."},"phone":{"type":["string","null"],"description":"Phone number in E.164 form, such as `+14065550142`, or null."},"address":{"type":"string","description":"The service address."},"servicesRequested":{"type":"array","items":{"type":"string"},"description":"What the lead asked for."},"specialRequests":{"type":["string","null"],"description":"Anything else the lead said, or null."},"estimatedHours":{"type":["number","null"],"description":"The office's estimate of the work in hours, or null."},"sqFootage":{"type":["number","null"],"description":"Square footage typed in by hand, or null."},"status":{"type":"string","enum":["pending","dismissed"],"description":"`pending` leads are open; `dismissed` leads were set aside."},"lifecycleStage":{"type":"string","enum":["lead","prospect","customer"],"description":"`lead` until an estimate is sent (`prospect`) or a job is booked (`customer`)."},"source":{"type":"string","enum":["intake_form","manual","csv","api"],"description":"How the lead arrived: `intake_form` for the website form, `manual` for leads added in the app, `csv` for an import, `api` for leads created with the API (leads it created before October 2026 read `manual`). New values may be added; treat an unknown one like `manual`."},"customerId":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"The customer account linked to the lead's email. It appears in the customers list and find_customer once it has a job or the lead converts. Null when the lead is not linked, for example when its email belongs to a staff member."},"propertyId":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"The lead's property (service address), when linked."},"externalReferences":{"type":"array","items":{"$ref":"#/components/schemas/ExternalReference"},"description":"Ids this lead has in your other systems, set with `externalReference`, the external upsert, or a link."},"createdAt":{"type":"string","format":"date-time","description":"When the lead was created, ISO 8601 in UTC."},"updatedAt":{"type":"string","format":"date-time","description":"When the lead last changed, ISO 8601 in UTC."}},"required":["id","object","firstName","lastName","companyName","email","phone","address","servicesRequested","specialRequests","estimatedHours","sqFootage","status","lifecycleStage","source","customerId","propertyId","externalReferences","createdAt","updatedAt"],"additionalProperties":false,"description":"A lead: someone who asked for service."},"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/leads":{"get":{"operationId":"leads.list","tags":["Leads"],"summary":"List leads","description":"Leads newest first, or by last change when `updatedSince` is set. Dismissed leads are included unless you filter by `status`. `externalSource` and `externalId` together narrow the list to the lead with that id in your system.\n\nReturns a list of [lead objects](https://docs.shortcutco.com/developers/reference/objects/lead).","parameters":[{"name":"limit","in":"query","required":false,"description":"How many items to return, 1-200. Defaults to 50.","schema":{"type":"integer","minimum":1,"maximum":200,"default":50}},{"name":"cursor","in":"query","required":false,"description":"The `meta.nextCursor` from the previous page. Omit it for the first page.","schema":{"type":"string","minLength":1,"maxLength":4096}},{"name":"status","in":"query","required":false,"description":"Only leads with this status.","schema":{"type":"string","enum":["pending","dismissed"]}},{"name":"lifecycleStage","in":"query","required":false,"description":"Only leads at this stage.","schema":{"type":"string","enum":["lead","prospect","customer"]}},{"name":"source","in":"query","required":false,"description":"Only leads that arrived this way.","schema":{"type":"string","enum":["intake_form","manual","csv","api"]}},{"name":"externalSource","in":"query","required":false,"description":"With `externalId`: only the lead 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 lead 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/Lead"}},"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 lead

> Creates a lead that behaves like one from the website form: staff are notified, and your new-lead automations run only if the token has \`automations:trigger\`. A new email gets a customer account and the address becomes its property; if the email belongs to an existing customer, the token also needs \`customers:write\`. Its \`source\` is \`api\`, which the app shows as API. With \`externalReference\`, your id is saved in the same request, and a duplicate fails the request with 409. At most 20 leads a minute per workspace. Send an \`Idempotency-Key\` to retry safely.\
> \
> Returns \[the lead object]\(<https://docs.shortcutco.com/developers/reference/objects/lead).\\>
> \
> \*\*Errors specific to this endpoint:\*\* \[\`already\_exists\`]\(<https://docs.shortcutco.com/developers/concepts/errors#already\\_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":"Leads","description":"A lead is a request for service. Creating one through the API works like your website form: staff are notified, and the lead appears in Customers with the Lead label.\n\nFields: [The lead object](https://docs.shortcutco.com/developers/reference/objects/lead)."}],"servers":[{"url":"https://api.shortcutco.com","description":"Production"}],"security":[{"bearerAuth":["leads: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":{"Lead":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"The lead's id."},"object":{"type":"string","const":"lead","description":"Always `lead`."},"firstName":{"type":"string","description":"First name."},"lastName":{"type":"string","description":"Last name."},"companyName":{"type":["string","null"],"description":"Company name, when the lead is a business."},"email":{"type":["string","null"],"description":"Email address, or null when none is on file."},"phone":{"type":["string","null"],"description":"Phone number in E.164 form, such as `+14065550142`, or null."},"address":{"type":"string","description":"The service address."},"servicesRequested":{"type":"array","items":{"type":"string"},"description":"What the lead asked for."},"specialRequests":{"type":["string","null"],"description":"Anything else the lead said, or null."},"estimatedHours":{"type":["number","null"],"description":"The office's estimate of the work in hours, or null."},"sqFootage":{"type":["number","null"],"description":"Square footage typed in by hand, or null."},"status":{"type":"string","enum":["pending","dismissed"],"description":"`pending` leads are open; `dismissed` leads were set aside."},"lifecycleStage":{"type":"string","enum":["lead","prospect","customer"],"description":"`lead` until an estimate is sent (`prospect`) or a job is booked (`customer`)."},"source":{"type":"string","enum":["intake_form","manual","csv","api"],"description":"How the lead arrived: `intake_form` for the website form, `manual` for leads added in the app, `csv` for an import, `api` for leads created with the API (leads it created before October 2026 read `manual`). New values may be added; treat an unknown one like `manual`."},"customerId":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"The customer account linked to the lead's email. It appears in the customers list and find_customer once it has a job or the lead converts. Null when the lead is not linked, for example when its email belongs to a staff member."},"propertyId":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"The lead's property (service address), when linked."},"externalReferences":{"type":"array","items":{"$ref":"#/components/schemas/ExternalReference"},"description":"Ids this lead has in your other systems, set with `externalReference`, the external upsert, or a link."},"createdAt":{"type":"string","format":"date-time","description":"When the lead was created, ISO 8601 in UTC."},"updatedAt":{"type":"string","format":"date-time","description":"When the lead last changed, ISO 8601 in UTC."}},"required":["id","object","firstName","lastName","companyName","email","phone","address","servicesRequested","specialRequests","estimatedHours","sqFootage","status","lifecycleStage","source","customerId","propertyId","externalReferences","createdAt","updatedAt"],"additionalProperties":false,"description":"A lead: someone who asked for service."},"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/leads":{"post":{"operationId":"leads.create","tags":["Leads"],"summary":"Create a lead","description":"Creates a lead that behaves like one from the website form: staff are notified, and your new-lead automations run only if the token has `automations:trigger`. A new email gets a customer account and the address becomes its property; if the email belongs to an existing customer, the token also needs `customers:write`. Its `source` is `api`, which the app shows as API. With `externalReference`, your id is saved in the same request, and a duplicate fails the request with 409. At most 20 leads a minute per workspace. Send an `Idempotency-Key` to retry safely.\n\nReturns [the lead object](https://docs.shortcutco.com/developers/reference/objects/lead).\n\n**Errors specific to this endpoint:** [`already_exists`](https://docs.shortcutco.com/developers/concepts/errors#already_exists). 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."},"email":{"type":"string","format":"email","maxLength":254,"description":"Email address. Required: the app uses it to match the lead to an existing customer."},"phone":{"type":"string","maxLength":30,"description":"Phone number, such as `(406) 555-0142`. US numbers may omit the country code."},"companyName":{"anyOf":[{"type":"string","maxLength":120},{"type":"null"}],"description":"Company name, when the lead is a business."},"address":{"type":"string","minLength":1,"maxLength":300,"description":"The service address on one line, such as `412 Elm St, Bozeman, MT 59715`."},"servicesRequested":{"type":"array","items":{"type":"string","minLength":1,"maxLength":120},"maxItems":50,"default":[],"description":"What the lead asked for, such as `Weekly mowing`. Duplicates are removed."},"specialRequests":{"type":"string","maxLength":2000,"description":"Anything else the lead said, shown on the lead in the app."},"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","email","address"],"additionalProperties":false,"description":"A new lead."}}}},"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/Lead"},"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 lead

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

```json
{"openapi":"3.1.0","info":{"title":"Shortcut API","version":"v1"},"tags":[{"name":"Leads","description":"A lead is a request for service. Creating one through the API works like your website form: staff are notified, and the lead appears in Customers with the Lead label.\n\nFields: [The lead object](https://docs.shortcutco.com/developers/reference/objects/lead)."}],"servers":[{"url":"https://api.shortcutco.com","description":"Production"}],"security":[{"bearerAuth":["leads: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":{"Lead":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"The lead's id."},"object":{"type":"string","const":"lead","description":"Always `lead`."},"firstName":{"type":"string","description":"First name."},"lastName":{"type":"string","description":"Last name."},"companyName":{"type":["string","null"],"description":"Company name, when the lead is a business."},"email":{"type":["string","null"],"description":"Email address, or null when none is on file."},"phone":{"type":["string","null"],"description":"Phone number in E.164 form, such as `+14065550142`, or null."},"address":{"type":"string","description":"The service address."},"servicesRequested":{"type":"array","items":{"type":"string"},"description":"What the lead asked for."},"specialRequests":{"type":["string","null"],"description":"Anything else the lead said, or null."},"estimatedHours":{"type":["number","null"],"description":"The office's estimate of the work in hours, or null."},"sqFootage":{"type":["number","null"],"description":"Square footage typed in by hand, or null."},"status":{"type":"string","enum":["pending","dismissed"],"description":"`pending` leads are open; `dismissed` leads were set aside."},"lifecycleStage":{"type":"string","enum":["lead","prospect","customer"],"description":"`lead` until an estimate is sent (`prospect`) or a job is booked (`customer`)."},"source":{"type":"string","enum":["intake_form","manual","csv","api"],"description":"How the lead arrived: `intake_form` for the website form, `manual` for leads added in the app, `csv` for an import, `api` for leads created with the API (leads it created before October 2026 read `manual`). New values may be added; treat an unknown one like `manual`."},"customerId":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"The customer account linked to the lead's email. It appears in the customers list and find_customer once it has a job or the lead converts. Null when the lead is not linked, for example when its email belongs to a staff member."},"propertyId":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"The lead's property (service address), when linked."},"externalReferences":{"type":"array","items":{"$ref":"#/components/schemas/ExternalReference"},"description":"Ids this lead has in your other systems, set with `externalReference`, the external upsert, or a link."},"createdAt":{"type":"string","format":"date-time","description":"When the lead was created, ISO 8601 in UTC."},"updatedAt":{"type":"string","format":"date-time","description":"When the lead last changed, ISO 8601 in UTC."}},"required":["id","object","firstName","lastName","companyName","email","phone","address","servicesRequested","specialRequests","estimatedHours","sqFootage","status","lifecycleStage","source","customerId","propertyId","externalReferences","createdAt","updatedAt"],"additionalProperties":false,"description":"A lead: someone who asked for service."},"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/leads/{id}":{"get":{"operationId":"leads.get","tags":["Leads"],"summary":"Get a lead","description":"One lead.\n\nReturns [the lead object](https://docs.shortcutco.com/developers/reference/objects/lead).","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/Lead"},"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 lead

> Changes a lead's contact details, address, hours estimate, or square footage, as editing the lead's profile in the app does. Send only the fields to change. A changed address needs \`addressLat\` and \`addressLng\`. Moving the address to another spot clears the lead's property map, its measurements, and a square footage taken from that map: the request is refused with \`409 property\_map\_would\_clear\` unless it sends \`confirmClearPropertyMap: true\`, and \`meta.effects\` lists what was cleared. Changing the square footage of a lead linked to a customer's property, or moving such a lead's address, also needs \`customers:write\`, as does giving an unlinked lead the email of an existing customer. Changing the email does not move the lead to another customer account.\
> \
> Returns \[the lead object]\(<https://docs.shortcutco.com/developers/reference/objects/lead).\\>
> \
> \*\*Errors specific to this endpoint:\*\* \[\`property\_map\_would\_clear\`]\(<https://docs.shortcutco.com/developers/concepts/errors#property\\_map\\_would\\_clear>). 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":"Leads","description":"A lead is a request for service. Creating one through the API works like your website form: staff are notified, and the lead appears in Customers with the Lead label.\n\nFields: [The lead object](https://docs.shortcutco.com/developers/reference/objects/lead)."}],"servers":[{"url":"https://api.shortcutco.com","description":"Production"}],"security":[{"bearerAuth":["leads: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":{"Lead":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"The lead's id."},"object":{"type":"string","const":"lead","description":"Always `lead`."},"firstName":{"type":"string","description":"First name."},"lastName":{"type":"string","description":"Last name."},"companyName":{"type":["string","null"],"description":"Company name, when the lead is a business."},"email":{"type":["string","null"],"description":"Email address, or null when none is on file."},"phone":{"type":["string","null"],"description":"Phone number in E.164 form, such as `+14065550142`, or null."},"address":{"type":"string","description":"The service address."},"servicesRequested":{"type":"array","items":{"type":"string"},"description":"What the lead asked for."},"specialRequests":{"type":["string","null"],"description":"Anything else the lead said, or null."},"estimatedHours":{"type":["number","null"],"description":"The office's estimate of the work in hours, or null."},"sqFootage":{"type":["number","null"],"description":"Square footage typed in by hand, or null."},"status":{"type":"string","enum":["pending","dismissed"],"description":"`pending` leads are open; `dismissed` leads were set aside."},"lifecycleStage":{"type":"string","enum":["lead","prospect","customer"],"description":"`lead` until an estimate is sent (`prospect`) or a job is booked (`customer`)."},"source":{"type":"string","enum":["intake_form","manual","csv","api"],"description":"How the lead arrived: `intake_form` for the website form, `manual` for leads added in the app, `csv` for an import, `api` for leads created with the API (leads it created before October 2026 read `manual`). New values may be added; treat an unknown one like `manual`."},"customerId":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"The customer account linked to the lead's email. It appears in the customers list and find_customer once it has a job or the lead converts. Null when the lead is not linked, for example when its email belongs to a staff member."},"propertyId":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"The lead's property (service address), when linked."},"externalReferences":{"type":"array","items":{"$ref":"#/components/schemas/ExternalReference"},"description":"Ids this lead has in your other systems, set with `externalReference`, the external upsert, or a link."},"createdAt":{"type":"string","format":"date-time","description":"When the lead was created, ISO 8601 in UTC."},"updatedAt":{"type":"string","format":"date-time","description":"When the lead last changed, ISO 8601 in UTC."}},"required":["id","object","firstName","lastName","companyName","email","phone","address","servicesRequested","specialRequests","estimatedHours","sqFootage","status","lifecycleStage","source","customerId","propertyId","externalReferences","createdAt","updatedAt"],"additionalProperties":false,"description":"A lead: someone who asked for service."},"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/leads/{id}":{"patch":{"operationId":"leads.update","tags":["Leads"],"summary":"Update a lead","description":"Changes a lead's contact details, address, hours estimate, or square footage, as editing the lead's profile in the app does. Send only the fields to change. A changed address needs `addressLat` and `addressLng`. Moving the address to another spot clears the lead's property map, its measurements, and a square footage taken from that map: the request is refused with `409 property_map_would_clear` unless it sends `confirmClearPropertyMap: true`, and `meta.effects` lists what was cleared. Changing the square footage of a lead linked to a customer's property, or moving such a lead's address, also needs `customers:write`, as does giving an unlinked lead the email of an existing customer. Changing the email does not move the lead to another customer account.\n\nReturns [the lead object](https://docs.shortcutco.com/developers/reference/objects/lead).\n\n**Errors specific to this endpoint:** [`property_map_would_clear`](https://docs.shortcutco.com/developers/concepts/errors#property_map_would_clear). 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 lead is a business. `null` clears it."},"email":{"type":"string","format":"email","maxLength":254,"description":"Email address. Changing it does not move the lead to another customer account; `customerId` stays as it is."},"phone":{"anyOf":[{"type":"string","maxLength":30},{"type":"null"}],"description":"Phone number, such as `(406) 555-0142`. US numbers may omit the country code. `null` clears it."},"address":{"type":"string","minLength":1,"maxLength":300,"description":"The service address on one line. A changed address needs `addressLat` and `addressLng`, which place it on the map. Moving it to another spot clears the lead's property map, its measurements, and a square footage taken from that map; send `confirmClearPropertyMap: true` to allow that."},"addressLat":{"type":"number","minimum":-90,"maximum":90,"description":"The address's latitude. Only with `address`."},"addressLng":{"type":"number","minimum":-180,"maximum":180,"description":"The address's longitude. Only with `address`."},"estimatedHours":{"anyOf":[{"type":"number","minimum":0,"maximum":10000},{"type":"null"}],"description":"The office's estimate of the work in hours. `null` clears it."},"sqFootage":{"anyOf":[{"type":"number","minimum":0,"maximum":100000000},{"type":"null"}],"description":"Square footage typed in by hand. `null` clears it, so a reviewed measurement of the property, if any, applies again. When the lead is linked to a customer's property, the property's square footage changes too, which needs `customers:write`."},"confirmClearPropertyMap":{"type":"boolean","description":"Set `true` to allow an address change that clears the lead's property map, measurements, or measured square footage. Without it such a change is refused with `property_map_would_clear` and nothing changes."}},"additionalProperties":false,"description":"Changes to a lead."}}}},"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/Lead"},"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"}}}}}}
```

## Dismiss a lead

> Sets a lead aside, as Dismiss does in the app: its status becomes \`dismissed\`. Dismissing a dismissed lead changes nothing and returns it as it is. Undo with restore. A lead that stands for a customer (at the customer stage, or linked to an active customer account) is refused with \`409 lead\_is\_customer\`; manage the customer instead. If the token has \`automations:trigger\`, the workspace's automations may react to a dismissed lead, for example by emailing or texting it, as they do when staff dismiss one in the app.\
> \
> Returns \[the lead object]\(<https://docs.shortcutco.com/developers/reference/objects/lead).\\>
> \
> \*\*Errors specific to this endpoint:\*\* \[\`lead\_is\_customer\`]\(<https://docs.shortcutco.com/developers/concepts/errors#lead\\_is\\_customer>). 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":"Leads","description":"A lead is a request for service. Creating one through the API works like your website form: staff are notified, and the lead appears in Customers with the Lead label.\n\nFields: [The lead object](https://docs.shortcutco.com/developers/reference/objects/lead)."}],"servers":[{"url":"https://api.shortcutco.com","description":"Production"}],"security":[{"bearerAuth":["leads: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":{"Lead":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"The lead's id."},"object":{"type":"string","const":"lead","description":"Always `lead`."},"firstName":{"type":"string","description":"First name."},"lastName":{"type":"string","description":"Last name."},"companyName":{"type":["string","null"],"description":"Company name, when the lead is a business."},"email":{"type":["string","null"],"description":"Email address, or null when none is on file."},"phone":{"type":["string","null"],"description":"Phone number in E.164 form, such as `+14065550142`, or null."},"address":{"type":"string","description":"The service address."},"servicesRequested":{"type":"array","items":{"type":"string"},"description":"What the lead asked for."},"specialRequests":{"type":["string","null"],"description":"Anything else the lead said, or null."},"estimatedHours":{"type":["number","null"],"description":"The office's estimate of the work in hours, or null."},"sqFootage":{"type":["number","null"],"description":"Square footage typed in by hand, or null."},"status":{"type":"string","enum":["pending","dismissed"],"description":"`pending` leads are open; `dismissed` leads were set aside."},"lifecycleStage":{"type":"string","enum":["lead","prospect","customer"],"description":"`lead` until an estimate is sent (`prospect`) or a job is booked (`customer`)."},"source":{"type":"string","enum":["intake_form","manual","csv","api"],"description":"How the lead arrived: `intake_form` for the website form, `manual` for leads added in the app, `csv` for an import, `api` for leads created with the API (leads it created before October 2026 read `manual`). New values may be added; treat an unknown one like `manual`."},"customerId":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"The customer account linked to the lead's email. It appears in the customers list and find_customer once it has a job or the lead converts. Null when the lead is not linked, for example when its email belongs to a staff member."},"propertyId":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"The lead's property (service address), when linked."},"externalReferences":{"type":"array","items":{"$ref":"#/components/schemas/ExternalReference"},"description":"Ids this lead has in your other systems, set with `externalReference`, the external upsert, or a link."},"createdAt":{"type":"string","format":"date-time","description":"When the lead was created, ISO 8601 in UTC."},"updatedAt":{"type":"string","format":"date-time","description":"When the lead last changed, ISO 8601 in UTC."}},"required":["id","object","firstName","lastName","companyName","email","phone","address","servicesRequested","specialRequests","estimatedHours","sqFootage","status","lifecycleStage","source","customerId","propertyId","externalReferences","createdAt","updatedAt"],"additionalProperties":false,"description":"A lead: someone who asked for service."},"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/leads/{id}/dismiss":{"post":{"operationId":"leads.dismiss","tags":["Leads"],"summary":"Dismiss a lead","description":"Sets a lead aside, as Dismiss does in the app: its status becomes `dismissed`. Dismissing a dismissed lead changes nothing and returns it as it is. Undo with restore. A lead that stands for a customer (at the customer stage, or linked to an active customer account) is refused with `409 lead_is_customer`; manage the customer instead. If the token has `automations:trigger`, the workspace's automations may react to a dismissed lead, for example by emailing or texting it, as they do when staff dismiss one in the app.\n\nReturns [the lead object](https://docs.shortcutco.com/developers/reference/objects/lead).\n\n**Errors specific to this endpoint:** [`lead_is_customer`](https://docs.shortcutco.com/developers/concepts/errors#lead_is_customer). Every endpoint can also return the [common errors](https://docs.shortcutco.com/developers/concepts/errors).","parameters":[{"name":"id","in":"path","required":true,"description":"The object's id.","schema":{"type":"string","format":"uuid"}},{"$ref":"#/components/parameters/IdempotencyKey"}],"responses":{"200":{"description":"Success.","headers":{"RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Lead"},"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 lead to your id

> Records \`externalId\` as this lead's id in \`source\`, so the external lookup and upsert find it. Linking is always explicit; the API never matches a lead to your id by email or address. Repeating the same link changes nothing. If the id already belongs to another lead, or this lead already has a different id in \`source\`, the request fails with 409 and nothing changes.\
> \
> Returns \[the lead object]\(<https://docs.shortcutco.com/developers/reference/objects/lead).\\>
> \
> \*\*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":"Leads","description":"A lead is a request for service. Creating one through the API works like your website form: staff are notified, and the lead appears in Customers with the Lead label.\n\nFields: [The lead object](https://docs.shortcutco.com/developers/reference/objects/lead)."}],"servers":[{"url":"https://api.shortcutco.com","description":"Production"}],"security":[{"bearerAuth":["leads: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":{"Lead":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"The lead's id."},"object":{"type":"string","const":"lead","description":"Always `lead`."},"firstName":{"type":"string","description":"First name."},"lastName":{"type":"string","description":"Last name."},"companyName":{"type":["string","null"],"description":"Company name, when the lead is a business."},"email":{"type":["string","null"],"description":"Email address, or null when none is on file."},"phone":{"type":["string","null"],"description":"Phone number in E.164 form, such as `+14065550142`, or null."},"address":{"type":"string","description":"The service address."},"servicesRequested":{"type":"array","items":{"type":"string"},"description":"What the lead asked for."},"specialRequests":{"type":["string","null"],"description":"Anything else the lead said, or null."},"estimatedHours":{"type":["number","null"],"description":"The office's estimate of the work in hours, or null."},"sqFootage":{"type":["number","null"],"description":"Square footage typed in by hand, or null."},"status":{"type":"string","enum":["pending","dismissed"],"description":"`pending` leads are open; `dismissed` leads were set aside."},"lifecycleStage":{"type":"string","enum":["lead","prospect","customer"],"description":"`lead` until an estimate is sent (`prospect`) or a job is booked (`customer`)."},"source":{"type":"string","enum":["intake_form","manual","csv","api"],"description":"How the lead arrived: `intake_form` for the website form, `manual` for leads added in the app, `csv` for an import, `api` for leads created with the API (leads it created before October 2026 read `manual`). New values may be added; treat an unknown one like `manual`."},"customerId":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"The customer account linked to the lead's email. It appears in the customers list and find_customer once it has a job or the lead converts. Null when the lead is not linked, for example when its email belongs to a staff member."},"propertyId":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"The lead's property (service address), when linked."},"externalReferences":{"type":"array","items":{"$ref":"#/components/schemas/ExternalReference"},"description":"Ids this lead has in your other systems, set with `externalReference`, the external upsert, or a link."},"createdAt":{"type":"string","format":"date-time","description":"When the lead was created, ISO 8601 in UTC."},"updatedAt":{"type":"string","format":"date-time","description":"When the lead last changed, ISO 8601 in UTC."}},"required":["id","object","firstName","lastName","companyName","email","phone","address","servicesRequested","specialRequests","estimatedHours","sqFootage","status","lifecycleStage","source","customerId","propertyId","externalReferences","createdAt","updatedAt"],"additionalProperties":false,"description":"A lead: someone who asked for service."},"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/leads/{id}/external-references/{source}":{"put":{"operationId":"leads.externalReferences.link","tags":["Leads"],"summary":"Link a lead to your id","description":"Records `externalId` as this lead's id in `source`, so the external lookup and upsert find it. Linking is always explicit; the API never matches a lead to your id by email or address. Repeating the same link changes nothing. If the id already belongs to another lead, or this lead already has a different id in `source`, the request fails with 409 and nothing changes.\n\nReturns [the lead object](https://docs.shortcutco.com/developers/reference/objects/lead).\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/Lead"},"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 lead from your id

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

```json
{"openapi":"3.1.0","info":{"title":"Shortcut API","version":"v1"},"tags":[{"name":"Leads","description":"A lead is a request for service. Creating one through the API works like your website form: staff are notified, and the lead appears in Customers with the Lead label.\n\nFields: [The lead object](https://docs.shortcutco.com/developers/reference/objects/lead)."}],"servers":[{"url":"https://api.shortcutco.com","description":"Production"}],"security":[{"bearerAuth":["leads: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":{"Lead":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"The lead's id."},"object":{"type":"string","const":"lead","description":"Always `lead`."},"firstName":{"type":"string","description":"First name."},"lastName":{"type":"string","description":"Last name."},"companyName":{"type":["string","null"],"description":"Company name, when the lead is a business."},"email":{"type":["string","null"],"description":"Email address, or null when none is on file."},"phone":{"type":["string","null"],"description":"Phone number in E.164 form, such as `+14065550142`, or null."},"address":{"type":"string","description":"The service address."},"servicesRequested":{"type":"array","items":{"type":"string"},"description":"What the lead asked for."},"specialRequests":{"type":["string","null"],"description":"Anything else the lead said, or null."},"estimatedHours":{"type":["number","null"],"description":"The office's estimate of the work in hours, or null."},"sqFootage":{"type":["number","null"],"description":"Square footage typed in by hand, or null."},"status":{"type":"string","enum":["pending","dismissed"],"description":"`pending` leads are open; `dismissed` leads were set aside."},"lifecycleStage":{"type":"string","enum":["lead","prospect","customer"],"description":"`lead` until an estimate is sent (`prospect`) or a job is booked (`customer`)."},"source":{"type":"string","enum":["intake_form","manual","csv","api"],"description":"How the lead arrived: `intake_form` for the website form, `manual` for leads added in the app, `csv` for an import, `api` for leads created with the API (leads it created before October 2026 read `manual`). New values may be added; treat an unknown one like `manual`."},"customerId":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"The customer account linked to the lead's email. It appears in the customers list and find_customer once it has a job or the lead converts. Null when the lead is not linked, for example when its email belongs to a staff member."},"propertyId":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"The lead's property (service address), when linked."},"externalReferences":{"type":"array","items":{"$ref":"#/components/schemas/ExternalReference"},"description":"Ids this lead has in your other systems, set with `externalReference`, the external upsert, or a link."},"createdAt":{"type":"string","format":"date-time","description":"When the lead was created, ISO 8601 in UTC."},"updatedAt":{"type":"string","format":"date-time","description":"When the lead last changed, ISO 8601 in UTC."}},"required":["id","object","firstName","lastName","companyName","email","phone","address","servicesRequested","specialRequests","estimatedHours","sqFootage","status","lifecycleStage","source","customerId","propertyId","externalReferences","createdAt","updatedAt"],"additionalProperties":false,"description":"A lead: someone who asked for service."},"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/leads/{id}/external-references/{source}":{"delete":{"operationId":"leads.externalReferences.unlink","tags":["Leads"],"summary":"Unlink a lead from your id","description":"Removes this lead's id in `source`. The lead itself is unchanged. Unlinking when there is no link changes nothing.\n\nReturns [the lead object](https://docs.shortcutco.com/developers/reference/objects/lead).","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/Lead"},"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"}}}}}}
```

## Restore a lead

> Brings a dismissed lead back, as Restore does in the app: its status becomes \`pending\`. Restoring an open lead changes nothing and returns it as it is.\
> \
> Returns \[the lead object]\(<https://docs.shortcutco.com/developers/reference/objects/lead>).

```json
{"openapi":"3.1.0","info":{"title":"Shortcut API","version":"v1"},"tags":[{"name":"Leads","description":"A lead is a request for service. Creating one through the API works like your website form: staff are notified, and the lead appears in Customers with the Lead label.\n\nFields: [The lead object](https://docs.shortcutco.com/developers/reference/objects/lead)."}],"servers":[{"url":"https://api.shortcutco.com","description":"Production"}],"security":[{"bearerAuth":["leads: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":{"Lead":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"The lead's id."},"object":{"type":"string","const":"lead","description":"Always `lead`."},"firstName":{"type":"string","description":"First name."},"lastName":{"type":"string","description":"Last name."},"companyName":{"type":["string","null"],"description":"Company name, when the lead is a business."},"email":{"type":["string","null"],"description":"Email address, or null when none is on file."},"phone":{"type":["string","null"],"description":"Phone number in E.164 form, such as `+14065550142`, or null."},"address":{"type":"string","description":"The service address."},"servicesRequested":{"type":"array","items":{"type":"string"},"description":"What the lead asked for."},"specialRequests":{"type":["string","null"],"description":"Anything else the lead said, or null."},"estimatedHours":{"type":["number","null"],"description":"The office's estimate of the work in hours, or null."},"sqFootage":{"type":["number","null"],"description":"Square footage typed in by hand, or null."},"status":{"type":"string","enum":["pending","dismissed"],"description":"`pending` leads are open; `dismissed` leads were set aside."},"lifecycleStage":{"type":"string","enum":["lead","prospect","customer"],"description":"`lead` until an estimate is sent (`prospect`) or a job is booked (`customer`)."},"source":{"type":"string","enum":["intake_form","manual","csv","api"],"description":"How the lead arrived: `intake_form` for the website form, `manual` for leads added in the app, `csv` for an import, `api` for leads created with the API (leads it created before October 2026 read `manual`). New values may be added; treat an unknown one like `manual`."},"customerId":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"The customer account linked to the lead's email. It appears in the customers list and find_customer once it has a job or the lead converts. Null when the lead is not linked, for example when its email belongs to a staff member."},"propertyId":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"The lead's property (service address), when linked."},"externalReferences":{"type":"array","items":{"$ref":"#/components/schemas/ExternalReference"},"description":"Ids this lead has in your other systems, set with `externalReference`, the external upsert, or a link."},"createdAt":{"type":"string","format":"date-time","description":"When the lead was created, ISO 8601 in UTC."},"updatedAt":{"type":"string","format":"date-time","description":"When the lead last changed, ISO 8601 in UTC."}},"required":["id","object","firstName","lastName","companyName","email","phone","address","servicesRequested","specialRequests","estimatedHours","sqFootage","status","lifecycleStage","source","customerId","propertyId","externalReferences","createdAt","updatedAt"],"additionalProperties":false,"description":"A lead: someone who asked for service."},"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/leads/{id}/restore":{"post":{"operationId":"leads.restore","tags":["Leads"],"summary":"Restore a lead","description":"Brings a dismissed lead back, as Restore does in the app: its status becomes `pending`. Restoring an open lead changes nothing and returns it as it is.\n\nReturns [the lead object](https://docs.shortcutco.com/developers/reference/objects/lead).","parameters":[{"name":"id","in":"path","required":true,"description":"The object's id.","schema":{"type":"string","format":"uuid"}},{"$ref":"#/components/parameters/IdempotencyKey"}],"responses":{"200":{"description":"Success.","headers":{"RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Lead"},"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 lead by your id

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

```json
{"openapi":"3.1.0","info":{"title":"Shortcut API","version":"v1"},"tags":[{"name":"Leads","description":"A lead is a request for service. Creating one through the API works like your website form: staff are notified, and the lead appears in Customers with the Lead label.\n\nFields: [The lead object](https://docs.shortcutco.com/developers/reference/objects/lead)."}],"servers":[{"url":"https://api.shortcutco.com","description":"Production"}],"security":[{"bearerAuth":["leads: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":{"Lead":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"The lead's id."},"object":{"type":"string","const":"lead","description":"Always `lead`."},"firstName":{"type":"string","description":"First name."},"lastName":{"type":"string","description":"Last name."},"companyName":{"type":["string","null"],"description":"Company name, when the lead is a business."},"email":{"type":["string","null"],"description":"Email address, or null when none is on file."},"phone":{"type":["string","null"],"description":"Phone number in E.164 form, such as `+14065550142`, or null."},"address":{"type":"string","description":"The service address."},"servicesRequested":{"type":"array","items":{"type":"string"},"description":"What the lead asked for."},"specialRequests":{"type":["string","null"],"description":"Anything else the lead said, or null."},"estimatedHours":{"type":["number","null"],"description":"The office's estimate of the work in hours, or null."},"sqFootage":{"type":["number","null"],"description":"Square footage typed in by hand, or null."},"status":{"type":"string","enum":["pending","dismissed"],"description":"`pending` leads are open; `dismissed` leads were set aside."},"lifecycleStage":{"type":"string","enum":["lead","prospect","customer"],"description":"`lead` until an estimate is sent (`prospect`) or a job is booked (`customer`)."},"source":{"type":"string","enum":["intake_form","manual","csv","api"],"description":"How the lead arrived: `intake_form` for the website form, `manual` for leads added in the app, `csv` for an import, `api` for leads created with the API (leads it created before October 2026 read `manual`). New values may be added; treat an unknown one like `manual`."},"customerId":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"The customer account linked to the lead's email. It appears in the customers list and find_customer once it has a job or the lead converts. Null when the lead is not linked, for example when its email belongs to a staff member."},"propertyId":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"The lead's property (service address), when linked."},"externalReferences":{"type":"array","items":{"$ref":"#/components/schemas/ExternalReference"},"description":"Ids this lead has in your other systems, set with `externalReference`, the external upsert, or a link."},"createdAt":{"type":"string","format":"date-time","description":"When the lead was created, ISO 8601 in UTC."},"updatedAt":{"type":"string","format":"date-time","description":"When the lead last changed, ISO 8601 in UTC."}},"required":["id","object","firstName","lastName","companyName","email","phone","address","servicesRequested","specialRequests","estimatedHours","sqFootage","status","lifecycleStage","source","customerId","propertyId","externalReferences","createdAt","updatedAt"],"additionalProperties":false,"description":"A lead: someone who asked for service."},"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/leads/external/{source}/{externalId}":{"get":{"operationId":"leads.external.get","tags":["Leads"],"summary":"Get a lead by your id","description":"The lead your id maps to, as `GET /v1/leads/{id}` returns it, or 404.\n\nReturns [the lead object](https://docs.shortcutco.com/developers/reference/objects/lead).","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/Lead"},"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 lead by your id

> The sync endpoint. If your id is new, creates the lead exactly as \`POST /v1/leads\` does and saves the id (\`created: true\`, status 201): staff are notified, your new-lead automations run only if the token has \`automations:trigger\`, an existing customer's email needs \`customers:write\`, and it counts toward the 20 leads a minute per workspace. If the id exists, applies the contact fields (names, company, email, phone) that differ from the stored ones as \`PATCH /v1/leads/{id}\` does, with its scope rules, and ignores \`address\`, \`servicesRequested\`, and \`specialRequests\` (\`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 leads.\
> \
> \*\*Errors specific to this endpoint:\*\* \[\`external\_reference\_changed\`]\(<https://docs.shortcutco.com/developers/concepts/errors#external\\_reference\\_changed>), \[\`property\_map\_would\_clear\`]\(<https://docs.shortcutco.com/developers/concepts/errors#property\\_map\\_would\\_clear>). 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":"Leads","description":"A lead is a request for service. Creating one through the API works like your website form: staff are notified, and the lead appears in Customers with the Lead label.\n\nFields: [The lead object](https://docs.shortcutco.com/developers/reference/objects/lead)."}],"servers":[{"url":"https://api.shortcutco.com","description":"Production"}],"security":[{"bearerAuth":["leads: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":{"Lead":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"The lead's id."},"object":{"type":"string","const":"lead","description":"Always `lead`."},"firstName":{"type":"string","description":"First name."},"lastName":{"type":"string","description":"Last name."},"companyName":{"type":["string","null"],"description":"Company name, when the lead is a business."},"email":{"type":["string","null"],"description":"Email address, or null when none is on file."},"phone":{"type":["string","null"],"description":"Phone number in E.164 form, such as `+14065550142`, or null."},"address":{"type":"string","description":"The service address."},"servicesRequested":{"type":"array","items":{"type":"string"},"description":"What the lead asked for."},"specialRequests":{"type":["string","null"],"description":"Anything else the lead said, or null."},"estimatedHours":{"type":["number","null"],"description":"The office's estimate of the work in hours, or null."},"sqFootage":{"type":["number","null"],"description":"Square footage typed in by hand, or null."},"status":{"type":"string","enum":["pending","dismissed"],"description":"`pending` leads are open; `dismissed` leads were set aside."},"lifecycleStage":{"type":"string","enum":["lead","prospect","customer"],"description":"`lead` until an estimate is sent (`prospect`) or a job is booked (`customer`)."},"source":{"type":"string","enum":["intake_form","manual","csv","api"],"description":"How the lead arrived: `intake_form` for the website form, `manual` for leads added in the app, `csv` for an import, `api` for leads created with the API (leads it created before October 2026 read `manual`). New values may be added; treat an unknown one like `manual`."},"customerId":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"The customer account linked to the lead's email. It appears in the customers list and find_customer once it has a job or the lead converts. Null when the lead is not linked, for example when its email belongs to a staff member."},"propertyId":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"The lead's property (service address), when linked."},"externalReferences":{"type":"array","items":{"$ref":"#/components/schemas/ExternalReference"},"description":"Ids this lead has in your other systems, set with `externalReference`, the external upsert, or a link."},"createdAt":{"type":"string","format":"date-time","description":"When the lead was created, ISO 8601 in UTC."},"updatedAt":{"type":"string","format":"date-time","description":"When the lead last changed, ISO 8601 in UTC."}},"required":["id","object","firstName","lastName","companyName","email","phone","address","servicesRequested","specialRequests","estimatedHours","sqFootage","status","lifecycleStage","source","customerId","propertyId","externalReferences","createdAt","updatedAt"],"additionalProperties":false,"description":"A lead: someone who asked for service."},"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/leads/external/{source}/{externalId}":{"put":{"operationId":"leads.external.upsert","tags":["Leads"],"summary":"Create or update a lead by your id","description":"The sync endpoint. If your id is new, creates the lead exactly as `POST /v1/leads` does and saves the id (`created: true`, status 201): staff are notified, your new-lead automations run only if the token has `automations:trigger`, an existing customer's email needs `customers:write`, and it counts toward the 20 leads a minute per workspace. If the id exists, applies the contact fields (names, company, email, phone) that differ from the stored ones as `PATCH /v1/leads/{id}` does, with its scope rules, and ignores `address`, `servicesRequested`, and `specialRequests` (`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 leads.\n\n**Errors specific to this endpoint:** [`external_reference_changed`](https://docs.shortcutco.com/developers/concepts/errors#external_reference_changed), [`property_map_would_clear`](https://docs.shortcutco.com/developers/concepts/errors#property_map_would_clear). 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."},"email":{"type":"string","format":"email","maxLength":254,"description":"Email address. Required: the app uses it to match the lead to an existing customer."},"phone":{"type":"string","maxLength":30,"description":"Phone number, such as `(406) 555-0142`. US numbers may omit the country code."},"companyName":{"anyOf":[{"type":"string","maxLength":120},{"type":"null"}],"description":"Company name, when the lead is a business."},"address":{"type":"string","minLength":1,"maxLength":300,"description":"The service address on one line, such as `412 Elm St, Bozeman, MT 59715`."},"servicesRequested":{"type":"array","items":{"type":"string","minLength":1,"maxLength":120},"maxItems":50,"default":[],"description":"What the lead asked for, such as `Weekly mowing`. Duplicates are removed."},"specialRequests":{"type":"string","maxLength":2000,"description":"Anything else the lead said, shown on the lead in the app."}},"required":["firstName","lastName","email","address"],"additionalProperties":false,"description":"The lead as in `POST /v1/leads`. When the reference is new the lead is created; when it exists, the contact fields (names, company, email, phone) that differ update the mapped lead, and `address`, `servicesRequested`, and `specialRequests` are 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 lead."},"lead":{"$ref":"#/components/schemas/Lead"}},"required":["created","lead"],"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 lead 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 lead."},"lead":{"$ref":"#/components/schemas/Lead"}},"required":["created","lead"],"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"}}}}}}
```
