Our Task Webhook will push data to any external system when task changes occur. We will send the task for all events and our intent is that the partner or receiving system can decide which events to process and which events not to. Our webhook follows the observer pattern so that other systems can listen for events.


Subscribing to Webhooks

To subscribe to our task webhook, you can utilize the /subscribe endpoint documented here.

The endpoint takes two parameters, url and type_webhook. The url parameter should be an endpoint in the client system which will receive the events triggered in the Breezeway system. For the Task webhook, task can be passed in the type_webhook parameter. This will create a subscription to the task events, and the client system will begin receiving notifications within an hour.

curl --location -g --request POST '{{url_base}}/public/webhook/v1/subscribe' \
--header 'Authorization: JWT {TOKEN} \
--data-raw '{
    "url": "http://www.testwebhooksub.com",
    "webhook_type": "task"
}'

Subscribing for cross company access:

curl --location -g --request POST '{{url_base}}/public/webhook/v1/subscribe' \
--header 'Authorization: JWT {TOKEN} \
--data-raw '{
    "url": "http://www.testwebhooksub.com",
    "webhook_type": "task",
		"company_id": 6332,
}'

Events

Our webhooks follow the observer pattern and create an event registry for task events so other systems can listen for them. We tell the receiver the event at the top level and send consistent data for all events, which allows us to take a most up-to-date truth approach.

If multiple events are triggered in a short time, we will always send the most accurate picture of the task, not a paper trail of what changed over time. For example, if 6 assignments were added in rapid succession, before our first event triggers, we send a fully updated task object to the receiver and not 6 different events.

Each event will include a last updated timestamp allowing the receiver to ignore events that have the same updated timestamp.


What Notifications Can I Receive?

Task Webhook Events

- task-created
- task-committed
- task-updated
    - Any data field updated, such as description, priority...etc
- task-deleted
- task-assignment-updated
    - changes to assignment from admin
    - accept or decline from user
- task-started
- task-paused
- task-resumed
- task-completed
- task-cost-updated
- task-supplies-updated
- task-comment-created

Task Webhook Open API Spec

{
  "paths": {},
  "info": {
    "title": "Breezeway Webhooks",
    "version": "1.0.0"
  },
  "openapi": "3.0.2",
  "components": {
    "schemas": {
      "TypeTaskStatus": {
        "type": "object",
        "properties": {
          "code": {
            "type": "string",
            "maxLength": 64
          },
          "id": {
            "type": "integer"
          },
          "name": {
            "type": "string",
            "maxLength": 64
          }
        }
      },
      "TaskSupply": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer"
          },
          "name": {
            "type": "string",
            "maxLength": 128
          },
          "unit_cost": {
            "type": "number"
          },
          "size": {
            "type": "string",
            "maxLength": 128
          },
          "quantity": {
            "type": "integer"
          },
          "description": {
            "type": "string",
            "maxLength": 255
          }
        },
        "required": [
          "description",
          "name",
          "quantity",
          "size"
        ]
      },
      "CompanyPerson": {
        "type": "object",
        "properties": {
          "full_name": {
            "type": "string"
          },
          "id": {
            "type": "integer"
          }
        }
      },
      "TaskPeople": {
        "type": "object",
        "properties": {
          "full_name": {
            "type": "string"
          },
          "id": {
            "type": "integer"
          }
        }
      },
      "TaskComment": {
        "type": "object",
        "properties": {
          "comment": {
            "type": "string",
            "nullable": true
          },
          "id": {
            "type": "integer"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "comment_by": {
            "type": "string"
          }
        }
      },
      "TypePriority": {
        "type": "object",
        "properties": {
          "code": {
            "type": "string",
            "maxLength": 64
          },
          "id": {
            "type": "integer"
          },
          "name": {
            "type": "string",
            "maxLength": 64
          }
        }
      },
      "TaskNote": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "note": {
            "type": "string",
            "nullable": true
          }
        }
      },
      "TypeTaskRequester": {
        "type": "object",
        "properties": {
          "code": {
            "type": "string",
            "maxLength": 64
          },
          "id": {
            "type": "integer"
          },
          "name": {
            "type": "string",
            "maxLength": 64
          }
        }
      },
      "SettingTaskTemplate": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer"
          },
          "name": {
            "type": "string",
            "nullable": true,
            "maxLength": 128
          }
        }
      },
      "TypeDepartment": {
        "type": "object",
        "properties": {
          "code": {
            "type": "string",
            "maxLength": 64
          },
          "id": {
            "type": "integer"
          },
          "name": {
            "type": "string",
            "maxLength": 64
          }
        }
      },
      "TypeCost": {
        "type": "object",
        "properties": {
          "code": {
            "type": "string",
            "maxLength": 64
          },
          "id": {
            "type": "integer"
          },
          "name": {
            "type": "string",
            "maxLength": 64
          }
        }
      },
      "TaskCost": {
        "type": "object",
        "properties": {
          "deleted_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "id": {
            "type": "integer"
          },
          "cost": {
            "type": "number"
          },
          "type_cost": {
            "$ref": "#/components/schemas/TypeCost"
          },
          "description": {
            "type": "string",
            "nullable": true,
            "maxLength": 255
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "Home": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer"
          },
          "name": {
            "type": "string",
            "nullable": true,
            "maxLength": 128
          }
        }
      },
      "TaskWebhookTask": {
        "type": "object",
        "properties": {
          "estimated_time": {
            "type": "string"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          },
          "estimated_rate": {
            "type": "number",
            "nullable": true
          },
          "rate_paid": {
            "type": "number"
          },
          "status": {
            "$ref": "#/components/schemas/TypeTaskStatus"
          },
          "task_series_id": {
            "type": "integer"
          },
          "started_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "assigned_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "photos": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "deleted_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "finished_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "supplies": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/TaskSupply"
            }
          },
          "started_by": {
            "$ref": "#/components/schemas/CompanyPerson"
          },
          "assignments": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/TaskPeople"
            }
          },
          "comments": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/TaskComment"
            }
          },
          "due_date": {
            "type": "string",
            "format": "date"
          },
          "created_by": {
            "$ref": "#/components/schemas/CompanyPerson"
          },
          "due_time": {
            "type": "string"
          },
          "reported_tasks": {
            "type": "array",
            "items": {
              "type": "integer"
            }
          },
          "priority": {
            "$ref": "#/components/schemas/TypePriority"
          },
          "total_cost": {
            "type": "number"
          },
          "summary": {
            "$ref": "#/components/schemas/TaskNote"
          },
          "end_date": {
            "type": "string",
            "format": "date",
            "nullable": true
          },
          "requested_by": {
            "$ref": "#/components/schemas/TypeTaskRequester"
          },
          "template": {
            "$ref": "#/components/schemas/SettingTaskTemplate"
          },
          "id": {
            "type": "integer"
          },
          "name": {
            "type": "string",
            "nullable": true,
            "maxLength": 128
          },
          "tags": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "description": {
            "type": "string",
            "nullable": true
          },
          "total_time": {
            "type": "string"
          },
          "company_id": {
            "type": "integer"
          },
          "task_report_url": {
            "type": "string"
          },
          "bill_to": {
            "type": "string"
          },         
          "parent_task_id": {
            "type": "integer"
          },
          "department": {
            "$ref": "#/components/schemas/TypeDepartment"
          },
          "itemized_cost": {
            "type": "boolean",
            "nullable": true
          },
          "finished_by": {
            "$ref": "#/components/schemas/CompanyPerson"
          },
          "costs": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/TaskCost"
            }
          },
          "home": {
            "$ref": "#/components/schemas/Home"
          },
          "linked_reservation": {
            "type": "object",
            "nullable": true,
            "properties": {
              "id": {
                "type": "number"
              },
              "external_reservation_id": {
                "type": "string",
                "nullable": true,
                "maxLength": 50
              }
            }
          }
        }
      },
      "task-webhook": {
        "type": "object",
        "properties": {
          "event_type": {
            "type": "string"
          },
          "task": {
            "$ref": "#/components/schemas/TaskWebhookTask"
          },
          "last_updated": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "last_updated"
        ]
      }
    }
  }
}