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.create | Task created |
| task.status | Task status changes |
| task.close | Task closed |
| task.reopen | Task system status changes |
| task.delete | Task deleted |
| project.create | Project created |
| project.delete | Project deleted |
| project.status | Project status changed |
| timelog.create | Time report created |
| timelog.update | Reported 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.