API 2.0
Webhooks

Webhooks

Overview

A webhook lets GoodDay send data to another system when an event occurs in your workspace.

A webhook defines where the data is sent: a URL and a secret used to authenticate requests. An automation defines when to send it and what data to include, using the Send webhook action.

Automation
  trigger + conditions + actions
                         |
                         +-- Send webhook --> Webhook
                                              URL + secret
    

Automations can send webhook requests for events involving tasks, comments, tags, projects, and time reports.

How to set up a webhook

1. Create a webhook

Go to Settings → Integrations → Webhooks and add a webhook. Give it a name and enter the endpoint URL that should receive the requests.

A secret is generated automatically. Store it securely — you will use it to verify that requests received by your system were sent by GoodDay.

2. Create an automation

Go to Tools → Automations and create a new Automation. Select a trigger that should send the webhook, such as a task being created or its status changing.

Add the Send webhook action and select the webhook you created in step 1.

3. Done

That's it. GoodDay calls your webhook each time an event matches your trigger and conditions.

Delivery

When an automation sends a webhook, GoodDay makes an HTTP POST request to the webhook URL.

POST <your endpoint>
Content-Type: application/json
User-Agent: goodday.work webhook

The request body contains the event data and the webhook secret used to authenticate the request. See Webhook body for the body structure.

Your endpoint should:

  • Verify the webhook secret and reject requests with an invalid secret.
  • Return a 2xx response within 5 seconds.
  • Process the event asynchronously after responding.

GoodDay does not retry failed deliveries. After three consecutive failed deliveries, the webhook is suspended until you reactivate it in Settings → Integrations → Webhooks.

You can view delivery attempts and their results in Settings → Integrations → Webhooks → Logs.

Webhook body

Every webhook request has the same body structure:

Field Description
requestId Unique identifier of the request.
momentUTC When the request was sent, in UTC.
secret The webhook secret. Compare it with the stored value to verify the request.
automationId The automation that sent the request.
entityType The type of entity in payload: TASK, TASK-MESSAGE, TASK-TAG, PROJECT or TIME-REPORT.
systemEvents What happened, as a list of event names. See System events.
payload The entity data. Its structure depends on entityType.

Request body

Sample request body →
{
  "requestId": "9f1e2c34-5a6b-11f0-9c8d-0242ac120002",
  "momentUTC": "2026-08-05T09:20:01.123456",
  "secret": "5f3a9c1e...",
  "automationId": "AUTOMATION-ID",
  "entityType": "TASK",
  "systemEvents": ["task.update", "task.status", "task.close"],
  "payload": {}
}

System events

The systemEvents field lists what happened to the entity in the payload. Which values can appear depends on entityType:

entityType Created Deleted Changed
TASK task.create task.delete task.update, plus task.status when the status moved, plus task.close or task.reopen when it crossed the open / closed line
TASK-MESSAGE task.message.create task.message.delete task.message.edit
TASK-TAG task.tag.add task.tag.remove
PROJECT project.create project.delete project.update, plus project.status when either status moved
TIME-REPORT timelog.create timelog.delete timelog.update

Sample Payloads

Custom fields and story points are not part of the payload. Read them through API 2.0 when needed.

Task Payload

Sample task payload →
{
  "id": "TASK-ID",
  "shortId": "37202",
  "name": "Adjust component update broken analysis.",
  "title": "Adjust component update broken analysis.",
  "companyId": "COMPANY-ID",
  "projectId": "PROJECT-ID",
  "parentTaskId": null,
  "taskTypeId": "TASK-TYPE-ID",
  "systemType": 1,
  "systemStatus": 3,
  "statusId": "STATUS-ID",
  "assignedToUserId": "USER-ID",
  "actionRequiredUserId": "USER-ID",
  "createdByUserId": "USER-ID",
  "createdOnBehalfByUserId": null,
  "priority": 5,
  "progress": null,
  "estimate": null,
  "deadline": null,
  "startDate": null,
  "endDate": null,
  "scheduleStatus": 0,
  "scheduleDate": null,
  "momentCreated": "2025-10-15T15:36:22.933162",
  "momentClosed": null,
  "latestActivityMoment": "2025-10-15T15:36:22.933162",
  "actionRequiredSince": "2025-10-15T15:36:22.933162",
  "isDeleted": false
}

Task Message Payload

Sample task message payload →
{
  "id": "TASK-MESSAGE-ID",
  "taskId": "TASK-ID",
  "companyId": "COMPANY-ID",
  "userId": "USER-ID",
  "actionRequiredUserId": null,
  "message": "Please review this today",
  "momentCreated": "2026-08-05 09:20:00.123456",
  "editDate": null,
  "editByUserId": null
}

Tag Payload

Sample tag payload →
{
  "project": {
    "id": "TAG-ID",
    "name": "Blocked"
  },
  "task": {
    "id": "TASK-ID",
    "title": "Adjust component update broken analysis."
  }
}

Project Payload

Sample project payload →
{
  "id": "PROJECT-ID",
  "companyId": "COMPANY-ID",
  "parentProjectId": "PARENT-PROJECT-ID",
  "statusId": "STATUS-ID",
  "name": "Website redesign",
  "shortName": "WR",
  "systemType": "PROJECT",
  "systemStatus": 4,
  "statusComments": null,
  "color": 21,
  "icon": "project",
  "description": "Use projects to organize work items with a common goal.",
  "momentCreated": "2026-07-31T12:42:16.849374",
  "startDate": null,
  "endDate": null,
  "estimate": null,
  "priority": 5,
  "progress": null,
  "health": null,
  "isDeleted": false
}

Time Report Payload

Sample time report payload →
{
  "id": "TIME-REPORT-ID",
  "companyId": "COMPANY-ID",
  "userId": "USER-ID",
  "taskId": "TASK-ID",
  "taskMessageId": "TASK-MESSAGE-ID",
  "projectId": null,
  "date": "2026-03-10",
  "timeReported": 120,
  "startMoment": null,
  "endMoment": null,
  "momentCreated": "2026-07-30T17:07:42.628873",
  "isBillable": true,
  "commentTxt": ""
}

Legacy webhooks

Legacy webhooks are the original webhook system in GoodDay. The webhook itself defines which events it subscribes to.

Legacy webhooks are no longer available to new organizations, but existing webhooks continue to work. No migration is required.

The new webhook system works differently: the webhook only defines where requests are sent, while an automation determines when to send them.

Legacy webhook Webhook + automation
What triggers it Events selected on the webhook Automation trigger
Filtering Company, project, and event type Automation conditions and scope
Payload Task, project, or time report The entity that triggered the automation
Reuse One event subscription One webhook can be used by multiple automations

Legacy events and their automation equivalents

The new webhook payload uses the same systemEvents vocabulary for equivalent events, so existing receivers can continue using the same event handling logic.

Legacy event Automation trigger
task.createTask created
task.statusTask status changes
task.closeTask closed
task.reopenTask system status changes
task.deleteTask deleted
project.createProject created
project.deleteProject deleted
project.statusProject status changed
timelog.createTime report created
timelog.updateReported time changed

The new webhook system also supports events that were not available in legacy webhooks, including comments, tags, project system status changes, and deleted time entries.

The new webhook system covers all data available through legacy webhooks, so existing integrations can be moved to the new system without changing the data they receive.