Skip to content

Webhooks

View as Markdown

Outbound, signed webhooks and their delivery log.

Operation Method and path
List webhooks GET /v1/workspaces/{workspace}/webhooks
Create a webhook POST /v1/workspaces/{workspace}/webhooks
Get a webhook GET /v1/workspaces/{workspace}/webhooks/{webhook_id}
Update a webhook PATCH /v1/workspaces/{workspace}/webhooks/{webhook_id}
Delete a webhook DELETE /v1/workspaces/{workspace}/webhooks/{webhook_id}
Rotate the signing secret POST /v1/workspaces/{workspace}/webhooks/{webhook_id}/rotate-secret
Send a test event POST /v1/workspaces/{workspace}/webhooks/{webhook_id}/test
Delivery log GET /v1/workspaces/{workspace}/webhooks/{webhook_id}/deliveries
Redeliver an event POST /v1/workspaces/{workspace}/webhooks/{webhook_id}/deliveries/{delivery_id}/redeliver
GET /v1/workspaces/{workspace}/webhooks
  • Operation: listWebhooks
  • Scopes: webhooks:read
  • Paginated: ?limit= and ?cursor=

Parameters

Name In Type Description
workspace * path string Workspace id (ws_…) or slug.

Responses

Status Meaning Body
200 OK A page of Webhook objects. WebhookList

Errors: 400, 401, 403, 404, 429, 500, as problem+json with a stable code.

Example

Terminal window
curl https://api.guv.dev/v1/workspaces/acme/webhooks \
-H "Authorization: Bearer $GUV_TOKEN"

Example response

{
"data": [
{
"id": "whk_01jbx2m9k7q4r8t5v6w3y0z1pr",
"workspace_id": "string",
"url": "https://guv.dev/",
"description": "string",
"events": [
"deployment.created"
],
"project_ids": [
"string"
],
"enabled": false,
"secret_prefix": "whsec_Ab3d",
"last_delivery": {
"status": "string",
"at": "2026-10-22T13:05:00Z"
},
"created_at": "2026-10-22T13:05:00Z",
"updated_at": "2026-10-22T13:05:00Z"
}
],
"next_cursor": "string",
"has_more": false
}
POST /v1/workspaces/{workspace}/webhooks

The signing secret is returned once.

  • Operation: createWebhook
  • Scopes: webhooks:write
  • Idempotency-Key: required; supports ?dry_run=true

Parameters

Name In Type Description
workspace * path string Workspace id (ws_…) or slug.

Request body (application/json, required): WebhookCreate

Field Type Description
url * string (uri)
description string
events * array of WebhookEventType
project_ids array of string or null
enabled boolean Default true.

Responses

Status Meaning Body
200 OK Dry run. Nothing was changed; this is what would happen. Plan
201 Created Created. WebhookCreated

Errors: 400, 401, 403, 404, 409, 422, 429, 500, as problem+json with a stable code.

Example

Terminal window
curl -X POST https://api.guv.dev/v1/workspaces/acme/webhooks \
-H "Authorization: Bearer $GUV_TOKEN" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{
"url": "https://guv.dev/",
"description": "string",
"events": [
"deployment.created"
],
"project_ids": [
"string"
],
"enabled": true
}'

Example response

{
"id": "whk_01jbx2m9k7q4r8t5v6w3y0z1pr",
"workspace_id": "string",
"url": "https://guv.dev/",
"description": "string",
"events": [
"deployment.created"
],
"project_ids": [
"string"
],
"enabled": false,
"secret_prefix": "whsec_Ab3d",
"last_delivery": {
"status": "string",
"at": "2026-10-22T13:05:00Z"
},
"created_at": "2026-10-22T13:05:00Z",
"updated_at": "2026-10-22T13:05:00Z",
"secret": "string"
}
GET /v1/workspaces/{workspace}/webhooks/{webhook_id}
  • Operation: getWebhook
  • Scopes: webhooks:read

Parameters

Name In Type Description
workspace * path string Workspace id (ws_…) or slug.
webhook_id * path string

Responses

Status Meaning Body
200 OK OK. Webhook

Errors: 400, 401, 403, 404, 429, 500, as problem+json with a stable code.

Example

Terminal window
curl https://api.guv.dev/v1/workspaces/acme/webhooks/web_01jbx2m9k7q4r8t5v6w3y0z1pr \
-H "Authorization: Bearer $GUV_TOKEN"

Example response

{
"id": "whk_01jbx2m9k7q4r8t5v6w3y0z1pr",
"workspace_id": "string",
"url": "https://guv.dev/",
"description": "string",
"events": [
"deployment.created"
],
"project_ids": [
"string"
],
"enabled": false,
"secret_prefix": "whsec_Ab3d",
"last_delivery": {
"status": "string",
"at": "2026-10-22T13:05:00Z"
},
"created_at": "2026-10-22T13:05:00Z",
"updated_at": "2026-10-22T13:05:00Z"
}
PATCH /v1/workspaces/{workspace}/webhooks/{webhook_id}
  • Operation: updateWebhook
  • Scopes: webhooks:write
  • Idempotency-Key: required; supports ?dry_run=true
  • Concurrency: send the ETag you read as If-Match

Parameters

Name In Type Description
workspace * path string Workspace id (ws_…) or slug.
webhook_id * path string

Request body (application/json, required): WebhookUpdate

Field Type Description
url string (uri)
description string
events array of WebhookEventType
project_ids array of string or null
enabled boolean

Responses

Status Meaning Body
200 OK OK. With dry_run=true: a Plan (application/vnd.guv.plan+json) and nothing changes. Webhook

Errors: 400, 401, 403, 404, 409, 412, 422, 429, 500, as problem+json with a stable code.

Example

Terminal window
curl -X PATCH https://api.guv.dev/v1/workspaces/acme/webhooks/web_01jbx2m9k7q4r8t5v6w3y0z1pr \
-H "Authorization: Bearer $GUV_TOKEN" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{
"url": "https://guv.dev/",
"description": "string",
"events": [
"deployment.created"
],
"project_ids": [
"string"
],
"enabled": false
}'

Example response

{
"id": "whk_01jbx2m9k7q4r8t5v6w3y0z1pr",
"workspace_id": "string",
"url": "https://guv.dev/",
"description": "string",
"events": [
"deployment.created"
],
"project_ids": [
"string"
],
"enabled": false,
"secret_prefix": "whsec_Ab3d",
"last_delivery": {
"status": "string",
"at": "2026-10-22T13:05:00Z"
},
"created_at": "2026-10-22T13:05:00Z",
"updated_at": "2026-10-22T13:05:00Z"
}
DELETE /v1/workspaces/{workspace}/webhooks/{webhook_id}
  • Operation: deleteWebhook
  • Scopes: webhooks:write
  • Idempotency-Key: required; supports ?dry_run=true
  • Concurrency: send the ETag you read as If-Match

Parameters

Name In Type Description
workspace * path string Workspace id (ws_…) or slug.
webhook_id * path string

Responses

Status Meaning Body
200 OK Dry run. Nothing was changed; this is what would happen. Plan
204 No Content Done. No body. none

Errors: 400, 401, 403, 404, 409, 412, 422, 429, 500, as problem+json with a stable code.

Example

Terminal window
curl -X DELETE https://api.guv.dev/v1/workspaces/acme/webhooks/web_01jbx2m9k7q4r8t5v6w3y0z1pr \
-H "Authorization: Bearer $GUV_TOKEN" \
-H "Idempotency-Key: $(uuidgen)"
POST /v1/workspaces/{workspace}/webhooks/{webhook_id}/rotate-secret

The old secret keeps working for 24 hours.

  • Operation: rotateWebhookSecret
  • Scopes: webhooks:write
  • Idempotency-Key: required

Parameters

Name In Type Description
workspace * path string Workspace id (ws_…) or slug.
webhook_id * path string

Responses

Status Meaning Body
200 OK OK. WebhookSecret

Errors: 400, 401, 403, 404, 409, 422, 429, 500, as problem+json with a stable code.

Example

Terminal window
curl -X POST https://api.guv.dev/v1/workspaces/acme/webhooks/web_01jbx2m9k7q4r8t5v6w3y0z1pr/rotate-secret \
-H "Authorization: Bearer $GUV_TOKEN" \
-H "Idempotency-Key: $(uuidgen)"

Example response

{
"secret": "string"
}
POST /v1/workspaces/{workspace}/webhooks/{webhook_id}/test
  • Operation: testWebhook
  • Scopes: webhooks:write
  • Idempotency-Key: required

Parameters

Name In Type Description
workspace * path string Workspace id (ws_…) or slug.
webhook_id * path string

Responses

Status Meaning Body
201 Created Created. WebhookDelivery

Errors: 400, 401, 403, 404, 409, 422, 429, 500, as problem+json with a stable code.

Example

Terminal window
curl -X POST https://api.guv.dev/v1/workspaces/acme/webhooks/web_01jbx2m9k7q4r8t5v6w3y0z1pr/test \
-H "Authorization: Bearer $GUV_TOKEN" \
-H "Idempotency-Key: $(uuidgen)"

Example response

{
"id": "whd_01jbx2m9k7q4r8t5v6w3y0z1pr",
"webhook_id": "string",
"event_id": "string",
"event_type": "deployment.created",
"attempt": 1,
"status": "pending",
"request": {
"headers": {
"key": "string"
},
"body": "string"
},
"response": {
"status": 1,
"body_excerpt": "string",
"duration_ms": 1
},
"next_attempt_at": "2026-10-22T13:05:00Z",
"created_at": "2026-10-22T13:05:00Z",
"delivered_at": "2026-10-22T13:05:00Z"
}
GET /v1/workspaces/{workspace}/webhooks/{webhook_id}/deliveries
  • Operation: listWebhookDeliveries
  • Scopes: webhooks:read
  • Paginated: ?limit= and ?cursor=

Parameters

Name In Type Description
workspace * path string Workspace id (ws_…) or slug.
webhook_id * path string
status query pending, succeeded, failed, retrying

Responses

Status Meaning Body
200 OK A page of WebhookDelivery objects. WebhookDeliveryList

Errors: 400, 401, 403, 404, 429, 500, as problem+json with a stable code.

Example

Terminal window
curl https://api.guv.dev/v1/workspaces/acme/webhooks/web_01jbx2m9k7q4r8t5v6w3y0z1pr/deliveries \
-H "Authorization: Bearer $GUV_TOKEN"

Example response

{
"data": [
{
"id": "whd_01jbx2m9k7q4r8t5v6w3y0z1pr",
"webhook_id": "string",
"event_id": "string",
"event_type": "deployment.created",
"attempt": 1,
"status": "pending",
"request": {
"headers": {
"key": "string"
},
"body": "string"
},
"response": {
"status": 1,
"body_excerpt": "string",
"duration_ms": 1
},
"next_attempt_at": "2026-10-22T13:05:00Z",
"created_at": "2026-10-22T13:05:00Z",
"delivered_at": "2026-10-22T13:05:00Z"
}
],
"next_cursor": "string",
"has_more": false
}
POST /v1/workspaces/{workspace}/webhooks/{webhook_id}/deliveries/{delivery_id}/redeliver
  • Operation: redeliverWebhook
  • Scopes: webhooks:write
  • Idempotency-Key: required

Parameters

Name In Type Description
workspace * path string Workspace id (ws_…) or slug.
webhook_id * path string
delivery_id * path string

Responses

Status Meaning Body
201 Created Created. WebhookDelivery

Errors: 400, 401, 403, 404, 409, 422, 429, 500, as problem+json with a stable code.

Example

Terminal window
curl -X POST https://api.guv.dev/v1/workspaces/acme/webhooks/web_01jbx2m9k7q4r8t5v6w3y0z1pr/deliveries/del_01jbx2m9k7q4r8t5v6w3y0z1pr/redeliver \
-H "Authorization: Bearer $GUV_TOKEN" \
-H "Idempotency-Key: $(uuidgen)"

Example response

{
"id": "whd_01jbx2m9k7q4r8t5v6w3y0z1pr",
"webhook_id": "string",
"event_id": "string",
"event_type": "deployment.created",
"attempt": 1,
"status": "pending",
"request": {
"headers": {
"key": "string"
},
"body": "string"
},
"response": {
"status": 1,
"body_excerpt": "string",
"duration_ms": 1
},
"next_attempt_at": "2026-10-22T13:05:00Z",
"created_at": "2026-10-22T13:05:00Z",
"delivered_at": "2026-10-22T13:05:00Z"
}

Sent for each subscribed event type. Respond 2xx within 10 seconds. Failed deliveries are retried with exponential backoff for 24 hours and appear in the delivery log.

Headers Guv sends

Header Description
Guv-Signature t=<unix seconds>,v1=<hex HMAC-SHA256 of "<t>.<raw body>">
Guv-Event-Id
Guv-Delivery-Id

Body: WebhookEvent

Field Type Description
id * string
type * WebhookEventType
api_version string
created_at * string (date-time)
workspace_id * string
project_id string or null
data * object The resource the event is about (for example a Deployment), as returned by the API.

Example payload

{
"id": "evt_01jbx2m9k7q4r8t5v6w3y0z1ev",
"type": "deployment.succeeded",
"api_version": "2026-11-01",
"created_at": "2026-10-23T14:05:12Z",
"workspace_id": "ws_01jbx2m9k7q4r8t5v6w3y0z1ws",
"project_id": "prj_01jbx2m9k7q4r8t5v6w3y0z1pr",
"data": {
"id": "dep_01jbx2m9k7q4r8t5v6w3y0z1dp",
"status": "active",
"service_name": "web",
"environment_name": "production"
}
}