Skip to content

Webhooks

Webhooks let you send real-time HTTP notifications to external services when events occur in SetGet. Every time a work item is created, a comment is posted, a cycle starts, or any other tracked event happens, SetGet sends a JSON payload to the URL you specify. Use webhooks to connect SetGet with CI/CD pipelines, monitoring dashboards, custom bots, or any service that accepts HTTP callbacks.

How webhooks work

  1. You create a webhook in SetGet and specify a URL, a secret, and the events you want to listen to.
  2. When a matching event occurs, SetGet constructs a JSON payload describing the event.
  3. SetGet sends an HTTP POST request to your URL with the payload in the body and a signature in the headers.
  4. Your server processes the payload and responds with an HTTP 2xx status code.
  5. If delivery fails, SetGet retries with exponential backoff.

Creating a webhook

  1. Go to Settings > Webhooks (workspace-level) or Project Settings > Webhooks (project-level).
  2. Click Create Webhook.
  3. Fill in the fields:
FieldRequiredDescription
URLYesThe endpoint that will receive POST requests
SecretRecommendedA shared secret used to sign payloads for verification
EventsYesOne or more event types to subscribe to
DescriptionNoA human-readable note about the webhook's purpose
ActiveYesToggle to enable or disable without deleting
  1. Click Save.

TIP

Always set a webhook secret. Without it, you cannot verify that incoming requests are genuinely from SetGet.

Event types

Work item events

EventTrigger
work_item.createdA new work item is created
work_item.updatedA work item's fields change (state, priority, assignee, labels, dates, title, description)
work_item.deletedA work item is deleted
work_item.archivedA work item is archived
work_item.unarchivedA work item is restored from archive

Comment events

EventTrigger
comment.createdA comment is added to a work item
comment.updatedA comment is edited
comment.deletedA comment is removed

Cycle events

EventTrigger
cycle.createdA new cycle is created
cycle.updatedA cycle's dates, title, or status change
cycle.startedA cycle's start date is reached
cycle.completedA cycle's end date is reached or it is manually completed
cycle.deletedA cycle is deleted

Module events

EventTrigger
module.createdA new module is created
module.updatedA module's fields change
module.deletedA module is deleted

Project events

EventTrigger
project.createdA new project is created in the workspace
project.updatedA project's settings change
project.deletedA project is deleted

Member events

EventTrigger
member.invitedA new member is invited to the workspace
member.joinedAn invited member accepts and joins
member.removedA member is removed from the workspace
member.role_changedA member's role is updated

Label events

EventTrigger
label.createdA new label is created
label.updatedA label is renamed or its color changes
label.deletedA label is deleted

Page events

EventTrigger
page.createdA new page is created
page.updatedA page's content or title changes
page.deletedA page is deleted

Intake events

EventTrigger
intake.submittedA new intake request is submitted
intake.acceptedAn intake request is accepted and converted to a work item
intake.declinedAn intake request is declined

Payload format

All webhook payloads follow the same JSON structure:

json
{
  "event": "work_item.created",
  "timestamp": "2026-03-29T14:30:00Z",
  "workspace": {
    "id": "ws_abc123",
    "slug": "my-workspace"
  },
  "project": {
    "id": "proj_def456",
    "name": "Web App",
    "identifier": "WEB"
  },
  "data": {
    "id": "wi_ghi789",
    "title": "Fix dashboard loading issue",
    "state": "Backlog",
    "priority": "High",
    "assignees": ["alice@example.com"],
    "labels": ["bug", "frontend"],
    "created_at": "2026-03-29T14:30:00Z",
    "updated_at": "2026-03-29T14:30:00Z"
  },
  "actor": {
    "id": "user_jkl012",
    "email": "bob@example.com",
    "display_name": "Bob"
  }
}

Field descriptions

FieldTypeDescription
eventstringThe event type (e.g., work_item.created)
timestampstring (ISO 8601)When the event occurred
workspaceobjectWorkspace identifiers
projectobjectProject identifiers (null for workspace-level events)
dataobjectThe full entity data relevant to the event
actorobjectThe user who triggered the event (null for system events)

Update payloads

For *.updated events, the data object includes a changes field:

json
{
  "event": "work_item.updated",
  "data": {
    "id": "wi_ghi789",
    "title": "Fix dashboard loading issue",
    "changes": {
      "state": {
        "old": "Backlog",
        "new": "In Progress"
      },
      "assignees": {
        "old": [],
        "new": ["alice@example.com"]
      }
    }
  }
}

Webhook delivery

Request format

SetGet sends webhooks as HTTP POST requests with the following headers:

HeaderValue
Content-Typeapplication/json
X-SetGet-EventThe event type (e.g., work_item.created)
X-SetGet-SignatureHMAC-SHA256 signature of the payload body
X-SetGet-TimestampUnix timestamp of the delivery attempt
X-SetGet-Delivery-IDUnique identifier for this delivery
User-AgentSetGet-Webhook/1.0

Retry policy

If your endpoint does not respond with an HTTP 2xx status code within 10 seconds, SetGet retries:

AttemptDelay after failure
1st retry1 minute
2nd retry5 minutes
3rd retry30 minutes
4th retry2 hours
5th retry12 hours

After 5 failed retries (6 total attempts), the delivery is marked as failed. Permanently failing webhooks are automatically disabled after 3 consecutive events fail all retries.

WARNING

Ensure your endpoint responds within 10 seconds. Long-running processing should be handled asynchronously after sending the 200 response.

Delivery ordering

Webhook deliveries are sent in the order events occur, but due to network conditions and retries, your endpoint may receive them out of order. Use the timestamp field to determine the correct sequence.

Testing webhooks

Built-in test

  1. Go to the webhook configuration page.
  2. Click Send Test.
  3. SetGet sends a test event with sample data to your URL.
  4. Check the delivery log to see the response.

Using a public inspection tool

For initial testing, use a service like https://webhook.site or https://requestbin.com to capture and inspect payloads before pointing the webhook at your production endpoint.

Webhook logs

Every webhook delivery is logged. To view logs:

  1. Go to Settings > Webhooks or Project Settings > Webhooks.
  2. Click on the webhook.
  3. Open the Delivery Log tab.

Each log entry shows:

ColumnDescription
EventThe event type
StatusSuccess (2xx), failed, or pending retry
Response codeThe HTTP status code returned by your endpoint
TimestampWhen the delivery was attempted
DurationResponse time in milliseconds
Delivery IDUnique identifier for tracing

Click on a log entry to see the full request payload and response body.

TIP

Use delivery logs to debug integration issues. If your endpoint returns a 4xx or 5xx error, the response body is captured in the log.

Editing a webhook

  1. Go to the webhook list.
  2. Click on the webhook you want to edit.
  3. Modify the URL, secret, events, or active status.
  4. Click Save.

Changes take effect immediately for future events.

Deleting a webhook

  1. Go to the webhook list.
  2. Click the Delete button (or the trash icon) next to the webhook.
  3. Confirm the deletion.

Deleting a webhook stops all future deliveries and removes the delivery log history.

Security -- Signature verification

Every webhook request includes an X-SetGet-Signature header containing an HMAC-SHA256 signature. Verify this signature on your server to confirm the request is from SetGet.

Verification steps

  1. Extract the X-SetGet-Signature header value.
  2. Compute the HMAC-SHA256 of the raw request body using your webhook secret as the key.
  3. Compare the computed signature with the header value using a constant-time comparison function.
  4. If they match, the request is authentic. If not, reject it.

Example (Go)

go
func verifySignature(body []byte, secret, signature string) bool {
    mac := hmac.New(sha256.New, []byte(secret))
    mac.Write(body)
    expected := hex.EncodeToString(mac.Sum(nil))
    return hmac.Equal([]byte(expected), []byte(signature))
}

Example (Node.js)

javascript
const crypto = require("crypto");

function verifySignature(body, secret, signature) {
  const expected = crypto.createHmac("sha256", secret).update(body).digest("hex");
  return crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(signature));
}

WARNING

Never skip signature verification in production. Without it, any party that knows your webhook URL can send fake events.

Best practices

  • Use HTTPS -- always use an HTTPS endpoint to prevent payload interception.
  • Respond quickly -- return a 200 immediately and process the payload asynchronously.
  • Handle duplicates -- use the X-SetGet-Delivery-ID header to deduplicate if the same event is received twice.
  • Rotate secrets -- periodically rotate your webhook secret and update it in SetGet.
  • Monitor delivery logs -- check logs regularly to catch failing webhooks before they are auto-disabled.