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

# Webhook subscriptions

Signed events sent to your HTTPS endpoint.

Subscribe an endpoint to event types, then read its deliveries, retry one, send a test event, pause, resume, or rotate its signing secret.

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

## List webhooks

> The workspace's webhook subscriptions, newest first, whoever created them. At most 20 exist per workspace, so the list is never paged.\
> \
> Returns a list of \[webhook objects]\(<https://docs.shortcutco.com/developers/reference/objects/webhook>).

```json
{"openapi":"3.1.0","info":{"title":"Shortcut API","version":"v1"},"tags":[{"name":"Webhook subscriptions","description":"Subscribe an endpoint to event types, then read its deliveries, retry one, send a test event, pause, resume, or rotate its signing secret.\n\nFields: [The webhook object](https://docs.shortcutco.com/developers/reference/objects/webhook) · [The webhook delivery object](https://docs.shortcutco.com/developers/reference/objects/webhook-delivery)."}],"servers":[{"url":"https://api.shortcutco.com","description":"Production"}],"security":[{"bearerAuth":["webhooks:manage"]}],"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":{"Webhook":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"The subscription's id."},"object":{"type":"string","const":"webhook","description":"Always `webhook`."},"url":{"type":"string","description":"The HTTPS endpoint (port 443) events are sent to."},"description":{"type":["string","null"],"description":"A note to tell subscriptions apart."},"eventTypes":{"type":"array","items":{"type":"string","enum":["customer.created","customer.updated","customer.deactivated","lead.created","lead.updated","lead.dismissed","estimate.sent","estimate.approved","estimate.declined","estimate.voided","job.created","job.updated","job.paused","job.resumed","job.canceled","visit.scheduled","visit.rescheduled","visit.assigned","visit.completed","visit.canceled","visit.deleted","invoice.created","invoice.sent","invoice.paid","invoice.overdue","invoice.voided","payment.recorded","payment.reversed"],"description":"A webhook event type, such as `invoice.paid`."},"description":"The event types this subscription receives."},"requiredScopes":{"type":"array","items":{"type":"string"},"description":"The read scopes of the subscribed event families, fixed when the subscription was created or its events last changed. Payloads are serialized under exactly these scopes."},"status":{"type":"string","enum":["active","paused","disabled"],"description":"`active` subscriptions receive events. `paused` ones hold their events until resumed. `disabled` ones were turned off after 50 failed deliveries in a row; events that happen while disabled are not kept."},"consecutiveFailures":{"type":"integer","description":"Failed delivery attempts in a row; a success resets it."},"disabledAt":{"anyOf":[{"type":"string","format":"date-time","description":"When delivery turned the subscription off, ISO 8601 in UTC."},{"type":"null"}],"description":"When delivery turned the subscription off, ISO 8601 in UTC."},"previousSecretExpiresAt":{"anyOf":[{"type":"string","format":"date-time","description":"Until when the secret replaced by the last rotation still signs deliveries (24 hours after rotating), ISO 8601 in UTC."},{"type":"null"}],"description":"Until when the secret replaced by the last rotation still signs deliveries (24 hours after rotating), ISO 8601 in UTC."},"createdVia":{"type":"string","enum":["settings","api_token"],"description":"Whether an admin created it in Settings or an integration created it with a token."},"createdAt":{"type":"string","format":"date-time","description":"When the subscription was created, ISO 8601 in UTC."},"updatedAt":{"type":"string","format":"date-time","description":"When the subscription last changed, ISO 8601 in UTC."}},"required":["id","object","url","description","eventTypes","requiredScopes","status","consecutiveFailures","disabledAt","previousSecretExpiresAt","createdVia","createdAt","updatedAt"],"additionalProperties":false,"description":"A webhook subscription: where to send which events."},"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/webhooks":{"get":{"operationId":"webhooks.list","tags":["Webhook subscriptions"],"summary":"List webhooks","description":"The workspace's webhook subscriptions, newest first, whoever created them. At most 20 exist per workspace, so the list is never paged.\n\nReturns a list of [webhook objects](https://docs.shortcutco.com/developers/reference/objects/webhook).","parameters":[],"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/Webhook"}},"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 a webhook

> Subscribes an HTTPS endpoint (port 443, public address) to event types. Subscribing to a family needs its read scope as well as \`webhooks:manage\` (for example \`invoices:read\` for \`invoice.paid\`); those read scopes are stored as \`requiredScopes\`, and every payload is limited to them. The response carries the signing \`secret\` once; it is not kept for idempotent replays, so a replay omits it. The subscription belongs to the workspace and keeps working if this token is revoked. At most 20 per workspace.\
> \
> Returns \[the webhook object]\(<https://docs.shortcutco.com/developers/reference/objects/webhook).\\>
> \
> \*\*Errors specific to this endpoint:\*\* \[\`invalid\_webhook\_url\`]\(<https://docs.shortcutco.com/developers/concepts/errors#invalid\\_webhook\\_url>), \[\`webhook\_limit\_reached\`]\(<https://docs.shortcutco.com/developers/concepts/errors#webhook\\_limit\\_reached>), \[\`webhook\_signing\_unavailable\`]\(<https://docs.shortcutco.com/developers/concepts/errors#webhook\\_signing\\_unavailable>). Every endpoint can also return the \[common errors]\(<https://docs.shortcutco.com/developers/concepts/errors>).

```json
{"openapi":"3.1.0","info":{"title":"Shortcut API","version":"v1"},"tags":[{"name":"Webhook subscriptions","description":"Subscribe an endpoint to event types, then read its deliveries, retry one, send a test event, pause, resume, or rotate its signing secret.\n\nFields: [The webhook object](https://docs.shortcutco.com/developers/reference/objects/webhook) · [The webhook delivery object](https://docs.shortcutco.com/developers/reference/objects/webhook-delivery)."}],"servers":[{"url":"https://api.shortcutco.com","description":"Production"}],"security":[{"bearerAuth":["webhooks:manage"]}],"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":{"WebhookWithSecret":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"The subscription's id."},"object":{"type":"string","const":"webhook","description":"Always `webhook`."},"url":{"type":"string","description":"The HTTPS endpoint (port 443) events are sent to."},"description":{"type":["string","null"],"description":"A note to tell subscriptions apart."},"eventTypes":{"type":"array","items":{"type":"string","enum":["customer.created","customer.updated","customer.deactivated","lead.created","lead.updated","lead.dismissed","estimate.sent","estimate.approved","estimate.declined","estimate.voided","job.created","job.updated","job.paused","job.resumed","job.canceled","visit.scheduled","visit.rescheduled","visit.assigned","visit.completed","visit.canceled","visit.deleted","invoice.created","invoice.sent","invoice.paid","invoice.overdue","invoice.voided","payment.recorded","payment.reversed"],"description":"A webhook event type, such as `invoice.paid`."},"description":"The event types this subscription receives."},"requiredScopes":{"type":"array","items":{"type":"string"},"description":"The read scopes of the subscribed event families, fixed when the subscription was created or its events last changed. Payloads are serialized under exactly these scopes."},"status":{"type":"string","enum":["active","paused","disabled"],"description":"`active` subscriptions receive events. `paused` ones hold their events until resumed. `disabled` ones were turned off after 50 failed deliveries in a row; events that happen while disabled are not kept."},"consecutiveFailures":{"type":"integer","description":"Failed delivery attempts in a row; a success resets it."},"disabledAt":{"anyOf":[{"type":"string","format":"date-time","description":"When delivery turned the subscription off, ISO 8601 in UTC."},{"type":"null"}],"description":"When delivery turned the subscription off, ISO 8601 in UTC."},"previousSecretExpiresAt":{"anyOf":[{"type":"string","format":"date-time","description":"Until when the secret replaced by the last rotation still signs deliveries (24 hours after rotating), ISO 8601 in UTC."},{"type":"null"}],"description":"Until when the secret replaced by the last rotation still signs deliveries (24 hours after rotating), ISO 8601 in UTC."},"createdVia":{"type":"string","enum":["settings","api_token"],"description":"Whether an admin created it in Settings or an integration created it with a token."},"createdAt":{"type":"string","format":"date-time","description":"When the subscription was created, ISO 8601 in UTC."},"updatedAt":{"type":"string","format":"date-time","description":"When the subscription last changed, ISO 8601 in UTC."},"secret":{"type":"string","description":"The signing secret (`whsec_…`), returned only in this response. It is not stored for idempotent replays: a replay omits it, so rotate the secret if you lost the first response."}},"required":["id","object","url","description","eventTypes","requiredScopes","status","consecutiveFailures","disabledAt","previousSecretExpiresAt","createdVia","createdAt","updatedAt"],"additionalProperties":false,"description":"A webhook subscription: where to send which events."},"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/webhooks":{"post":{"operationId":"webhooks.create","tags":["Webhook subscriptions"],"summary":"Create a webhook","description":"Subscribes an HTTPS endpoint (port 443, public address) to event types. Subscribing to a family needs its read scope as well as `webhooks:manage` (for example `invoices:read` for `invoice.paid`); those read scopes are stored as `requiredScopes`, and every payload is limited to them. The response carries the signing `secret` once; it is not kept for idempotent replays, so a replay omits it. The subscription belongs to the workspace and keeps working if this token is revoked. At most 20 per workspace.\n\nReturns [the webhook object](https://docs.shortcutco.com/developers/reference/objects/webhook).\n\n**Errors specific to this endpoint:** [`invalid_webhook_url`](https://docs.shortcutco.com/developers/concepts/errors#invalid_webhook_url), [`webhook_limit_reached`](https://docs.shortcutco.com/developers/concepts/errors#webhook_limit_reached), [`webhook_signing_unavailable`](https://docs.shortcutco.com/developers/concepts/errors#webhook_signing_unavailable). Every endpoint can also return the [common errors](https://docs.shortcutco.com/developers/concepts/errors).","parameters":[{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string","minLength":1,"maxLength":2048,"description":"The HTTPS endpoint (port 443) to send events to."},"description":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"description":"A note to tell subscriptions apart, such as `Zapier: new invoices`."},"eventTypes":{"type":"array","items":{"type":"string","enum":["customer.created","customer.updated","customer.deactivated","lead.created","lead.updated","lead.dismissed","estimate.sent","estimate.approved","estimate.declined","estimate.voided","job.created","job.updated","job.paused","job.resumed","job.canceled","visit.scheduled","visit.rescheduled","visit.assigned","visit.completed","visit.canceled","visit.deleted","invoice.created","invoice.sent","invoice.paid","invoice.overdue","invoice.voided","payment.recorded","payment.reversed"]},"minItems":1,"maxItems":28,"description":"The event types to receive, such as `invoice.paid`. Each family needs its read scope."}},"required":["url","eventTypes"],"additionalProperties":false}}}},"responses":{"201":{"description":"Success.","headers":{"RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/WebhookWithSecret"},"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 webhook

> One webhook subscription. The signing secret is never returned here.\
> \
> Returns \[the webhook object]\(<https://docs.shortcutco.com/developers/reference/objects/webhook>).

```json
{"openapi":"3.1.0","info":{"title":"Shortcut API","version":"v1"},"tags":[{"name":"Webhook subscriptions","description":"Subscribe an endpoint to event types, then read its deliveries, retry one, send a test event, pause, resume, or rotate its signing secret.\n\nFields: [The webhook object](https://docs.shortcutco.com/developers/reference/objects/webhook) · [The webhook delivery object](https://docs.shortcutco.com/developers/reference/objects/webhook-delivery)."}],"servers":[{"url":"https://api.shortcutco.com","description":"Production"}],"security":[{"bearerAuth":["webhooks:manage"]}],"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":{"Webhook":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"The subscription's id."},"object":{"type":"string","const":"webhook","description":"Always `webhook`."},"url":{"type":"string","description":"The HTTPS endpoint (port 443) events are sent to."},"description":{"type":["string","null"],"description":"A note to tell subscriptions apart."},"eventTypes":{"type":"array","items":{"type":"string","enum":["customer.created","customer.updated","customer.deactivated","lead.created","lead.updated","lead.dismissed","estimate.sent","estimate.approved","estimate.declined","estimate.voided","job.created","job.updated","job.paused","job.resumed","job.canceled","visit.scheduled","visit.rescheduled","visit.assigned","visit.completed","visit.canceled","visit.deleted","invoice.created","invoice.sent","invoice.paid","invoice.overdue","invoice.voided","payment.recorded","payment.reversed"],"description":"A webhook event type, such as `invoice.paid`."},"description":"The event types this subscription receives."},"requiredScopes":{"type":"array","items":{"type":"string"},"description":"The read scopes of the subscribed event families, fixed when the subscription was created or its events last changed. Payloads are serialized under exactly these scopes."},"status":{"type":"string","enum":["active","paused","disabled"],"description":"`active` subscriptions receive events. `paused` ones hold their events until resumed. `disabled` ones were turned off after 50 failed deliveries in a row; events that happen while disabled are not kept."},"consecutiveFailures":{"type":"integer","description":"Failed delivery attempts in a row; a success resets it."},"disabledAt":{"anyOf":[{"type":"string","format":"date-time","description":"When delivery turned the subscription off, ISO 8601 in UTC."},{"type":"null"}],"description":"When delivery turned the subscription off, ISO 8601 in UTC."},"previousSecretExpiresAt":{"anyOf":[{"type":"string","format":"date-time","description":"Until when the secret replaced by the last rotation still signs deliveries (24 hours after rotating), ISO 8601 in UTC."},{"type":"null"}],"description":"Until when the secret replaced by the last rotation still signs deliveries (24 hours after rotating), ISO 8601 in UTC."},"createdVia":{"type":"string","enum":["settings","api_token"],"description":"Whether an admin created it in Settings or an integration created it with a token."},"createdAt":{"type":"string","format":"date-time","description":"When the subscription was created, ISO 8601 in UTC."},"updatedAt":{"type":"string","format":"date-time","description":"When the subscription last changed, ISO 8601 in UTC."}},"required":["id","object","url","description","eventTypes","requiredScopes","status","consecutiveFailures","disabledAt","previousSecretExpiresAt","createdVia","createdAt","updatedAt"],"additionalProperties":false,"description":"A webhook subscription: where to send which events."},"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/webhooks/{id}":{"get":{"operationId":"webhooks.get","tags":["Webhook subscriptions"],"summary":"Get a webhook","description":"One webhook subscription. The signing secret is never returned here.\n\nReturns [the webhook object](https://docs.shortcutco.com/developers/reference/objects/webhook).","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/Webhook"},"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"}}}}}}
```

## Delete a webhook

> Deletes a webhook subscription with its delivery history and returns it. Nothing new is sent to it; a request already in progress when it was deleted (at most one per delivery) may still arrive.\
> \
> Returns \[the webhook object]\(<https://docs.shortcutco.com/developers/reference/objects/webhook>).

```json
{"openapi":"3.1.0","info":{"title":"Shortcut API","version":"v1"},"tags":[{"name":"Webhook subscriptions","description":"Subscribe an endpoint to event types, then read its deliveries, retry one, send a test event, pause, resume, or rotate its signing secret.\n\nFields: [The webhook object](https://docs.shortcutco.com/developers/reference/objects/webhook) · [The webhook delivery object](https://docs.shortcutco.com/developers/reference/objects/webhook-delivery)."}],"servers":[{"url":"https://api.shortcutco.com","description":"Production"}],"security":[{"bearerAuth":["webhooks:manage"]}],"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":{"Webhook":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"The subscription's id."},"object":{"type":"string","const":"webhook","description":"Always `webhook`."},"url":{"type":"string","description":"The HTTPS endpoint (port 443) events are sent to."},"description":{"type":["string","null"],"description":"A note to tell subscriptions apart."},"eventTypes":{"type":"array","items":{"type":"string","enum":["customer.created","customer.updated","customer.deactivated","lead.created","lead.updated","lead.dismissed","estimate.sent","estimate.approved","estimate.declined","estimate.voided","job.created","job.updated","job.paused","job.resumed","job.canceled","visit.scheduled","visit.rescheduled","visit.assigned","visit.completed","visit.canceled","visit.deleted","invoice.created","invoice.sent","invoice.paid","invoice.overdue","invoice.voided","payment.recorded","payment.reversed"],"description":"A webhook event type, such as `invoice.paid`."},"description":"The event types this subscription receives."},"requiredScopes":{"type":"array","items":{"type":"string"},"description":"The read scopes of the subscribed event families, fixed when the subscription was created or its events last changed. Payloads are serialized under exactly these scopes."},"status":{"type":"string","enum":["active","paused","disabled"],"description":"`active` subscriptions receive events. `paused` ones hold their events until resumed. `disabled` ones were turned off after 50 failed deliveries in a row; events that happen while disabled are not kept."},"consecutiveFailures":{"type":"integer","description":"Failed delivery attempts in a row; a success resets it."},"disabledAt":{"anyOf":[{"type":"string","format":"date-time","description":"When delivery turned the subscription off, ISO 8601 in UTC."},{"type":"null"}],"description":"When delivery turned the subscription off, ISO 8601 in UTC."},"previousSecretExpiresAt":{"anyOf":[{"type":"string","format":"date-time","description":"Until when the secret replaced by the last rotation still signs deliveries (24 hours after rotating), ISO 8601 in UTC."},{"type":"null"}],"description":"Until when the secret replaced by the last rotation still signs deliveries (24 hours after rotating), ISO 8601 in UTC."},"createdVia":{"type":"string","enum":["settings","api_token"],"description":"Whether an admin created it in Settings or an integration created it with a token."},"createdAt":{"type":"string","format":"date-time","description":"When the subscription was created, ISO 8601 in UTC."},"updatedAt":{"type":"string","format":"date-time","description":"When the subscription last changed, ISO 8601 in UTC."}},"required":["id","object","url","description","eventTypes","requiredScopes","status","consecutiveFailures","disabledAt","previousSecretExpiresAt","createdVia","createdAt","updatedAt"],"additionalProperties":false,"description":"A webhook subscription: where to send which events."},"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/webhooks/{id}":{"delete":{"operationId":"webhooks.delete","tags":["Webhook subscriptions"],"summary":"Delete a webhook","description":"Deletes a webhook subscription with its delivery history and returns it. Nothing new is sent to it; a request already in progress when it was deleted (at most one per delivery) may still arrive.\n\nReturns [the webhook object](https://docs.shortcutco.com/developers/reference/objects/webhook).","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/Webhook"},"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"}}}}}}
```

## Update a webhook

> Changes a webhook's URL, description, or event types, or pauses or resumes it. Send only the fields to change. \`status: paused\` (from \`active\` only) holds everything not yet sent until it is set back to \`active\`, which sends the held deliveries, about two a minute; setting a \`disabled\` webhook to \`active\` turns it back on and resets its failure count, and a \`disabled\` webhook cannot be paused (\`409 state\_conflict\`). Except for pausing, the token must hold the webhook's read scopes (its \`requiredScopes\` after the change), so a token cannot redirect events it could not read.\
> \
> Returns \[the webhook object]\(<https://docs.shortcutco.com/developers/reference/objects/webhook).\\>
> \
> \*\*Errors specific to this endpoint:\*\* \[\`invalid\_webhook\_url\`]\(<https://docs.shortcutco.com/developers/concepts/errors#invalid\\_webhook\\_url>), \[\`state\_conflict\`]\(<https://docs.shortcutco.com/developers/concepts/errors#state\\_conflict>). Every endpoint can also return the \[common errors]\(<https://docs.shortcutco.com/developers/concepts/errors>).

```json
{"openapi":"3.1.0","info":{"title":"Shortcut API","version":"v1"},"tags":[{"name":"Webhook subscriptions","description":"Subscribe an endpoint to event types, then read its deliveries, retry one, send a test event, pause, resume, or rotate its signing secret.\n\nFields: [The webhook object](https://docs.shortcutco.com/developers/reference/objects/webhook) · [The webhook delivery object](https://docs.shortcutco.com/developers/reference/objects/webhook-delivery)."}],"servers":[{"url":"https://api.shortcutco.com","description":"Production"}],"security":[{"bearerAuth":["webhooks:manage"]}],"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":{"Webhook":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"The subscription's id."},"object":{"type":"string","const":"webhook","description":"Always `webhook`."},"url":{"type":"string","description":"The HTTPS endpoint (port 443) events are sent to."},"description":{"type":["string","null"],"description":"A note to tell subscriptions apart."},"eventTypes":{"type":"array","items":{"type":"string","enum":["customer.created","customer.updated","customer.deactivated","lead.created","lead.updated","lead.dismissed","estimate.sent","estimate.approved","estimate.declined","estimate.voided","job.created","job.updated","job.paused","job.resumed","job.canceled","visit.scheduled","visit.rescheduled","visit.assigned","visit.completed","visit.canceled","visit.deleted","invoice.created","invoice.sent","invoice.paid","invoice.overdue","invoice.voided","payment.recorded","payment.reversed"],"description":"A webhook event type, such as `invoice.paid`."},"description":"The event types this subscription receives."},"requiredScopes":{"type":"array","items":{"type":"string"},"description":"The read scopes of the subscribed event families, fixed when the subscription was created or its events last changed. Payloads are serialized under exactly these scopes."},"status":{"type":"string","enum":["active","paused","disabled"],"description":"`active` subscriptions receive events. `paused` ones hold their events until resumed. `disabled` ones were turned off after 50 failed deliveries in a row; events that happen while disabled are not kept."},"consecutiveFailures":{"type":"integer","description":"Failed delivery attempts in a row; a success resets it."},"disabledAt":{"anyOf":[{"type":"string","format":"date-time","description":"When delivery turned the subscription off, ISO 8601 in UTC."},{"type":"null"}],"description":"When delivery turned the subscription off, ISO 8601 in UTC."},"previousSecretExpiresAt":{"anyOf":[{"type":"string","format":"date-time","description":"Until when the secret replaced by the last rotation still signs deliveries (24 hours after rotating), ISO 8601 in UTC."},{"type":"null"}],"description":"Until when the secret replaced by the last rotation still signs deliveries (24 hours after rotating), ISO 8601 in UTC."},"createdVia":{"type":"string","enum":["settings","api_token"],"description":"Whether an admin created it in Settings or an integration created it with a token."},"createdAt":{"type":"string","format":"date-time","description":"When the subscription was created, ISO 8601 in UTC."},"updatedAt":{"type":"string","format":"date-time","description":"When the subscription last changed, ISO 8601 in UTC."}},"required":["id","object","url","description","eventTypes","requiredScopes","status","consecutiveFailures","disabledAt","previousSecretExpiresAt","createdVia","createdAt","updatedAt"],"additionalProperties":false,"description":"A webhook subscription: where to send which events."},"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/webhooks/{id}":{"patch":{"operationId":"webhooks.update","tags":["Webhook subscriptions"],"summary":"Update a webhook","description":"Changes a webhook's URL, description, or event types, or pauses or resumes it. Send only the fields to change. `status: paused` (from `active` only) holds everything not yet sent until it is set back to `active`, which sends the held deliveries, about two a minute; setting a `disabled` webhook to `active` turns it back on and resets its failure count, and a `disabled` webhook cannot be paused (`409 state_conflict`). Except for pausing, the token must hold the webhook's read scopes (its `requiredScopes` after the change), so a token cannot redirect events it could not read.\n\nReturns [the webhook object](https://docs.shortcutco.com/developers/reference/objects/webhook).\n\n**Errors specific to this endpoint:** [`invalid_webhook_url`](https://docs.shortcutco.com/developers/concepts/errors#invalid_webhook_url), [`state_conflict`](https://docs.shortcutco.com/developers/concepts/errors#state_conflict). Every endpoint can also return the [common errors](https://docs.shortcutco.com/developers/concepts/errors).","parameters":[{"name":"id","in":"path","required":true,"description":"The object's id.","schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string","minLength":1,"maxLength":2048,"description":"The HTTPS endpoint (port 443) to send events to."},"description":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"description":"A note to tell subscriptions apart, such as `Zapier: new invoices`."},"eventTypes":{"type":"array","items":{"type":"string","enum":["customer.created","customer.updated","customer.deactivated","lead.created","lead.updated","lead.dismissed","estimate.sent","estimate.approved","estimate.declined","estimate.voided","job.created","job.updated","job.paused","job.resumed","job.canceled","visit.scheduled","visit.rescheduled","visit.assigned","visit.completed","visit.canceled","visit.deleted","invoice.created","invoice.sent","invoice.paid","invoice.overdue","invoice.voided","payment.recorded","payment.reversed"]},"minItems":1,"maxItems":28,"description":"The event types to receive, such as `invoice.paid`. Each family needs its read scope."},"status":{"type":"string","enum":["active","paused"],"description":"`paused` holds new events until the subscription is set back to `active`. Setting a disabled subscription to `active` turns it back on and resets its failure count."}},"additionalProperties":false}}}},"responses":{"200":{"description":"Success.","headers":{"RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Webhook"},"meta":{"type":"object","properties":{},"additionalProperties":true,"description":"Facts about this request beside the object, such as `alreadyReminded` on a repeated reminder. Present only when there is something to report."}},"required":["data"],"additionalProperties":false}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthenticated"},"402":{"$ref":"#/components/responses/SubscriptionRequired"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"},"422":{"$ref":"#/components/responses/Unprocessable"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/Unavailable"}}}}}}
```

## List a webhook's deliveries

> The webhook's deliveries, newest first, test events included, with each one's status, attempts, last response status, and a redacted excerpt of the last response. Deliveries are kept for 30 days.\
> \
> Returns a list of \[webhook delivery objects]\(<https://docs.shortcutco.com/developers/reference/objects/webhook-delivery>).

```json
{"openapi":"3.1.0","info":{"title":"Shortcut API","version":"v1"},"tags":[{"name":"Webhook subscriptions","description":"Subscribe an endpoint to event types, then read its deliveries, retry one, send a test event, pause, resume, or rotate its signing secret.\n\nFields: [The webhook object](https://docs.shortcutco.com/developers/reference/objects/webhook) · [The webhook delivery object](https://docs.shortcutco.com/developers/reference/objects/webhook-delivery)."}],"servers":[{"url":"https://api.shortcutco.com","description":"Production"}],"security":[{"bearerAuth":["webhooks:manage"]}],"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":{"WebhookDelivery":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"The delivery's id (also sent as the `Shortcut-Delivery-Id` header)."},"object":{"type":"string","const":"webhook_delivery","description":"Always `webhook_delivery`."},"webhookId":{"type":"string","format":"uuid","description":"The subscription it was sent to."},"eventId":{"type":"string","description":"The envelope `id` (`evt_…`), the same on every retry; use it to drop duplicates."},"eventType":{"type":"string","description":"The event type, or `webhook.test` for a test event."},"status":{"type":"string","enum":["pending","held","succeeded","failed","exhausted"],"description":"`pending` waits for its next attempt. `held` waits for a paused subscription to resume, or for the workspace's billing. `succeeded` got a 2xx. `failed` failed its last attempt and will be retried at `nextAttemptAt`. `exhausted` will not be tried again."},"attempts":{"type":"integer","description":"Attempts made so far."},"nextAttemptAt":{"anyOf":[{"type":"string","format":"date-time","description":"When the next attempt is due, ISO 8601 in UTC."},{"type":"null"}],"description":"When the next attempt is due, ISO 8601 in UTC."},"deliveredAt":{"anyOf":[{"type":"string","format":"date-time","description":"When the receiver answered with a 2xx, ISO 8601 in UTC."},{"type":"null"}],"description":"When the receiver answered with a 2xx, ISO 8601 in UTC."},"lastResponseStatus":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"The HTTP status of the last attempt, if a response arrived."},"lastError":{"type":["string","null"],"description":"Why the last attempt failed or the delivery ended: `http_<status>`, `timeout`, `connect_timeout`, `unresolvable`, `private_address`, `port_not_allowed`, `not_https`, `object_not_found`, `scope_missing`, `subscription_disabled`, `event_type_unsubscribed`, `expired`, `held_expired`, `secret_unavailable`, or another short code."},"lastResponseExcerpt":{"type":["string","null"],"description":"The first 500 characters of the last response body, with secrets and contact details redacted."},"createdAt":{"type":"string","format":"date-time","description":"When the delivery was created, ISO 8601 in UTC."}},"required":["id","object","webhookId","eventId","eventType","status","attempts","nextAttemptAt","deliveredAt","lastResponseStatus","lastError","lastResponseExcerpt","createdAt"],"additionalProperties":false,"description":"One event sent, or to be sent, to one subscription."},"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/webhooks/{id}/deliveries":{"get":{"operationId":"webhooks.deliveries.list","tags":["Webhook subscriptions"],"summary":"List a webhook's deliveries","description":"The webhook's deliveries, newest first, test events included, with each one's status, attempts, last response status, and a redacted excerpt of the last response. Deliveries are kept for 30 days.\n\nReturns a list of [webhook delivery objects](https://docs.shortcutco.com/developers/reference/objects/webhook-delivery).","parameters":[{"name":"id","in":"path","required":true,"description":"The object's id.","schema":{"type":"string","format":"uuid"}},{"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 deliveries in this status.","schema":{"type":"string","enum":["pending","held","succeeded","failed","exhausted"]}}],"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/WebhookDelivery"}},"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"}}}}}}
```

## Retry a delivery

> Sends a failed or exhausted delivery again within about a minute, with the object as it is now. The webhook must be active, and the token must hold its read scopes. Test events cannot be retried; send another.\
> \
> Returns \[the webhook delivery object]\(<https://docs.shortcutco.com/developers/reference/objects/webhook-delivery).\\>
> \
> \*\*Errors specific to this endpoint:\*\* \[\`delivery\_not\_retryable\`]\(<https://docs.shortcutco.com/developers/concepts/errors#delivery\\_not\\_retryable>), \[\`webhook\_not\_active\`]\(<https://docs.shortcutco.com/developers/concepts/errors#webhook\\_not\\_active>). 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":"Webhook subscriptions","description":"Subscribe an endpoint to event types, then read its deliveries, retry one, send a test event, pause, resume, or rotate its signing secret.\n\nFields: [The webhook object](https://docs.shortcutco.com/developers/reference/objects/webhook) · [The webhook delivery object](https://docs.shortcutco.com/developers/reference/objects/webhook-delivery)."}],"servers":[{"url":"https://api.shortcutco.com","description":"Production"}],"security":[{"bearerAuth":["webhooks:manage"]}],"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":{"WebhookDelivery":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"The delivery's id (also sent as the `Shortcut-Delivery-Id` header)."},"object":{"type":"string","const":"webhook_delivery","description":"Always `webhook_delivery`."},"webhookId":{"type":"string","format":"uuid","description":"The subscription it was sent to."},"eventId":{"type":"string","description":"The envelope `id` (`evt_…`), the same on every retry; use it to drop duplicates."},"eventType":{"type":"string","description":"The event type, or `webhook.test` for a test event."},"status":{"type":"string","enum":["pending","held","succeeded","failed","exhausted"],"description":"`pending` waits for its next attempt. `held` waits for a paused subscription to resume, or for the workspace's billing. `succeeded` got a 2xx. `failed` failed its last attempt and will be retried at `nextAttemptAt`. `exhausted` will not be tried again."},"attempts":{"type":"integer","description":"Attempts made so far."},"nextAttemptAt":{"anyOf":[{"type":"string","format":"date-time","description":"When the next attempt is due, ISO 8601 in UTC."},{"type":"null"}],"description":"When the next attempt is due, ISO 8601 in UTC."},"deliveredAt":{"anyOf":[{"type":"string","format":"date-time","description":"When the receiver answered with a 2xx, ISO 8601 in UTC."},{"type":"null"}],"description":"When the receiver answered with a 2xx, ISO 8601 in UTC."},"lastResponseStatus":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"The HTTP status of the last attempt, if a response arrived."},"lastError":{"type":["string","null"],"description":"Why the last attempt failed or the delivery ended: `http_<status>`, `timeout`, `connect_timeout`, `unresolvable`, `private_address`, `port_not_allowed`, `not_https`, `object_not_found`, `scope_missing`, `subscription_disabled`, `event_type_unsubscribed`, `expired`, `held_expired`, `secret_unavailable`, or another short code."},"lastResponseExcerpt":{"type":["string","null"],"description":"The first 500 characters of the last response body, with secrets and contact details redacted."},"createdAt":{"type":"string","format":"date-time","description":"When the delivery was created, ISO 8601 in UTC."}},"required":["id","object","webhookId","eventId","eventType","status","attempts","nextAttemptAt","deliveredAt","lastResponseStatus","lastError","lastResponseExcerpt","createdAt"],"additionalProperties":false,"description":"One event sent, or to be sent, to one subscription."},"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/webhooks/{id}/deliveries/{deliveryId}/retry":{"post":{"operationId":"webhooks.deliveries.retry","tags":["Webhook subscriptions"],"summary":"Retry a delivery","description":"Sends a failed or exhausted delivery again within about a minute, with the object as it is now. The webhook must be active, and the token must hold its read scopes. Test events cannot be retried; send another.\n\nReturns [the webhook delivery object](https://docs.shortcutco.com/developers/reference/objects/webhook-delivery).\n\n**Errors specific to this endpoint:** [`delivery_not_retryable`](https://docs.shortcutco.com/developers/concepts/errors#delivery_not_retryable), [`webhook_not_active`](https://docs.shortcutco.com/developers/concepts/errors#webhook_not_active). Every endpoint can also return the [common errors](https://docs.shortcutco.com/developers/concepts/errors).","parameters":[{"name":"id","in":"path","required":true,"description":"The webhook's id.","schema":{"type":"string","format":"uuid"}},{"name":"deliveryId","in":"path","required":true,"description":"The delivery'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/WebhookDelivery"},"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"}}}}}}
```

## Rotate a webhook's signing secret

> Issues a new signing secret, returned once as \`secret\`. For the next 24 hours every delivery is signed with both the new and the previous secret (two \`v1=\` signatures), so the receiver can switch without missing events. A replay omits the secret; rotate again if you lost it. The token must hold the webhook's read scopes.\
> \
> Returns \[the webhook object]\(<https://docs.shortcutco.com/developers/reference/objects/webhook).\\>
> \
> \*\*Errors specific to this endpoint:\*\* \[\`webhook\_signing\_unavailable\`]\(<https://docs.shortcutco.com/developers/concepts/errors#webhook\\_signing\\_unavailable>). Every endpoint can also return the \[common errors]\(<https://docs.shortcutco.com/developers/concepts/errors>).

```json
{"openapi":"3.1.0","info":{"title":"Shortcut API","version":"v1"},"tags":[{"name":"Webhook subscriptions","description":"Subscribe an endpoint to event types, then read its deliveries, retry one, send a test event, pause, resume, or rotate its signing secret.\n\nFields: [The webhook object](https://docs.shortcutco.com/developers/reference/objects/webhook) · [The webhook delivery object](https://docs.shortcutco.com/developers/reference/objects/webhook-delivery)."}],"servers":[{"url":"https://api.shortcutco.com","description":"Production"}],"security":[{"bearerAuth":["webhooks:manage"]}],"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":{"WebhookWithSecret":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"The subscription's id."},"object":{"type":"string","const":"webhook","description":"Always `webhook`."},"url":{"type":"string","description":"The HTTPS endpoint (port 443) events are sent to."},"description":{"type":["string","null"],"description":"A note to tell subscriptions apart."},"eventTypes":{"type":"array","items":{"type":"string","enum":["customer.created","customer.updated","customer.deactivated","lead.created","lead.updated","lead.dismissed","estimate.sent","estimate.approved","estimate.declined","estimate.voided","job.created","job.updated","job.paused","job.resumed","job.canceled","visit.scheduled","visit.rescheduled","visit.assigned","visit.completed","visit.canceled","visit.deleted","invoice.created","invoice.sent","invoice.paid","invoice.overdue","invoice.voided","payment.recorded","payment.reversed"],"description":"A webhook event type, such as `invoice.paid`."},"description":"The event types this subscription receives."},"requiredScopes":{"type":"array","items":{"type":"string"},"description":"The read scopes of the subscribed event families, fixed when the subscription was created or its events last changed. Payloads are serialized under exactly these scopes."},"status":{"type":"string","enum":["active","paused","disabled"],"description":"`active` subscriptions receive events. `paused` ones hold their events until resumed. `disabled` ones were turned off after 50 failed deliveries in a row; events that happen while disabled are not kept."},"consecutiveFailures":{"type":"integer","description":"Failed delivery attempts in a row; a success resets it."},"disabledAt":{"anyOf":[{"type":"string","format":"date-time","description":"When delivery turned the subscription off, ISO 8601 in UTC."},{"type":"null"}],"description":"When delivery turned the subscription off, ISO 8601 in UTC."},"previousSecretExpiresAt":{"anyOf":[{"type":"string","format":"date-time","description":"Until when the secret replaced by the last rotation still signs deliveries (24 hours after rotating), ISO 8601 in UTC."},{"type":"null"}],"description":"Until when the secret replaced by the last rotation still signs deliveries (24 hours after rotating), ISO 8601 in UTC."},"createdVia":{"type":"string","enum":["settings","api_token"],"description":"Whether an admin created it in Settings or an integration created it with a token."},"createdAt":{"type":"string","format":"date-time","description":"When the subscription was created, ISO 8601 in UTC."},"updatedAt":{"type":"string","format":"date-time","description":"When the subscription last changed, ISO 8601 in UTC."},"secret":{"type":"string","description":"The signing secret (`whsec_…`), returned only in this response. It is not stored for idempotent replays: a replay omits it, so rotate the secret if you lost the first response."}},"required":["id","object","url","description","eventTypes","requiredScopes","status","consecutiveFailures","disabledAt","previousSecretExpiresAt","createdVia","createdAt","updatedAt"],"additionalProperties":false,"description":"A webhook subscription: where to send which events."},"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/webhooks/{id}/rotate-secret":{"post":{"operationId":"webhooks.rotate_secret","tags":["Webhook subscriptions"],"summary":"Rotate a webhook's signing secret","description":"Issues a new signing secret, returned once as `secret`. For the next 24 hours every delivery is signed with both the new and the previous secret (two `v1=` signatures), so the receiver can switch without missing events. A replay omits the secret; rotate again if you lost it. The token must hold the webhook's read scopes.\n\nReturns [the webhook object](https://docs.shortcutco.com/developers/reference/objects/webhook).\n\n**Errors specific to this endpoint:** [`webhook_signing_unavailable`](https://docs.shortcutco.com/developers/concepts/errors#webhook_signing_unavailable). Every endpoint can also return the [common errors](https://docs.shortcutco.com/developers/concepts/errors).","parameters":[{"name":"id","in":"path","required":true,"description":"The object's id.","schema":{"type":"string","format":"uuid"}},{"$ref":"#/components/parameters/IdempotencyKey"}],"responses":{"200":{"description":"Success.","headers":{"RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"}},"content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/WebhookWithSecret"},"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"}}}}}}
```

## Send a test event

> Sends one signed \`webhook.test\` event to the webhook now and returns the delivery with the receiver's answer. It carries no workspace data, is not retried, does not count toward the failure limit, and works whatever the webhook's status.\
> \
> Returns \[the webhook delivery object]\(<https://docs.shortcutco.com/developers/reference/objects/webhook-delivery>).

```json
{"openapi":"3.1.0","info":{"title":"Shortcut API","version":"v1"},"tags":[{"name":"Webhook subscriptions","description":"Subscribe an endpoint to event types, then read its deliveries, retry one, send a test event, pause, resume, or rotate its signing secret.\n\nFields: [The webhook object](https://docs.shortcutco.com/developers/reference/objects/webhook) · [The webhook delivery object](https://docs.shortcutco.com/developers/reference/objects/webhook-delivery)."}],"servers":[{"url":"https://api.shortcutco.com","description":"Production"}],"security":[{"bearerAuth":["webhooks:manage"]}],"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":{"WebhookDelivery":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"The delivery's id (also sent as the `Shortcut-Delivery-Id` header)."},"object":{"type":"string","const":"webhook_delivery","description":"Always `webhook_delivery`."},"webhookId":{"type":"string","format":"uuid","description":"The subscription it was sent to."},"eventId":{"type":"string","description":"The envelope `id` (`evt_…`), the same on every retry; use it to drop duplicates."},"eventType":{"type":"string","description":"The event type, or `webhook.test` for a test event."},"status":{"type":"string","enum":["pending","held","succeeded","failed","exhausted"],"description":"`pending` waits for its next attempt. `held` waits for a paused subscription to resume, or for the workspace's billing. `succeeded` got a 2xx. `failed` failed its last attempt and will be retried at `nextAttemptAt`. `exhausted` will not be tried again."},"attempts":{"type":"integer","description":"Attempts made so far."},"nextAttemptAt":{"anyOf":[{"type":"string","format":"date-time","description":"When the next attempt is due, ISO 8601 in UTC."},{"type":"null"}],"description":"When the next attempt is due, ISO 8601 in UTC."},"deliveredAt":{"anyOf":[{"type":"string","format":"date-time","description":"When the receiver answered with a 2xx, ISO 8601 in UTC."},{"type":"null"}],"description":"When the receiver answered with a 2xx, ISO 8601 in UTC."},"lastResponseStatus":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"The HTTP status of the last attempt, if a response arrived."},"lastError":{"type":["string","null"],"description":"Why the last attempt failed or the delivery ended: `http_<status>`, `timeout`, `connect_timeout`, `unresolvable`, `private_address`, `port_not_allowed`, `not_https`, `object_not_found`, `scope_missing`, `subscription_disabled`, `event_type_unsubscribed`, `expired`, `held_expired`, `secret_unavailable`, or another short code."},"lastResponseExcerpt":{"type":["string","null"],"description":"The first 500 characters of the last response body, with secrets and contact details redacted."},"createdAt":{"type":"string","format":"date-time","description":"When the delivery was created, ISO 8601 in UTC."}},"required":["id","object","webhookId","eventId","eventType","status","attempts","nextAttemptAt","deliveredAt","lastResponseStatus","lastError","lastResponseExcerpt","createdAt"],"additionalProperties":false,"description":"One event sent, or to be sent, to one subscription."},"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/webhooks/{id}/test":{"post":{"operationId":"webhooks.test","tags":["Webhook subscriptions"],"summary":"Send a test event","description":"Sends one signed `webhook.test` event to the webhook now and returns the delivery with the receiver's answer. It carries no workspace data, is not retried, does not count toward the failure limit, and works whatever the webhook's status.\n\nReturns [the webhook delivery object](https://docs.shortcutco.com/developers/reference/objects/webhook-delivery).","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/WebhookDelivery"},"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"}}}}}}
```
