Triggers
Triggers automatically run an agent when something happens — no schedule required. Where a Job runs an agent on a fixed clock, a Trigger runs an agent in reaction to an event, letting your workspace respond the moment something changes.
ToothFairyAI supports two event sources:
- Native — ToothFairyAI's own platform events (a document is created, an agent completes, a planner is awaiting approval, etc.).
- External — Trigger events emitted by third-party apps (Google Drive, Slack, GitHub, Salesforce, Stripe, Notion, Jira, and many more). External triggers are acquired by polling the provider with a configured Authorisation.
When a trigger fires, it sends the bound prompt (or forced prompt) to the selected agent exactly as a manual chat run would.
Menu location
Triggers can be created and managed from the following menu:
Settings > Triggers > Create trigger
Create a trigger
Basic Information
- Click on the
Create triggerbutton. - Name — Assign a unique name to identify the trigger.
- Description (optional) — Describe what this trigger does and when it should fire.
Execution Configuration
- Agent — Select the agent that will run when the trigger fires. Voice-mode agents are excluded from the dropdown (triggers target text-capable agents).
- Prompt — Choose the prompt sent to the agent. Available prompts are your saved prompts (see Prompting). The dropdown only lists prompts made available to the selected agent. You can provide a Forced Prompt instead — free-text instructions (max 1024 characters) used directly as the agent's input. Either a prompt or a forced prompt is required.
If the selected agent has no prompts assigned to it — and you have not provided a forced prompt — the form shows a placeholder linking you straight to the Generation settings section to create one.
Event Configuration
- Event Source — Choose where the triggering event comes from:
Native (ToothFairyAI events)
React to events produced inside your ToothFairyAI workspace.
-
Native Event Type — The platform event to listen for (e.g.
document.created,agent_completed,planner_pending_approval). See the Native events table below. -
Data Filter (optional) — Narrow the trigger to events whose payload matches conditions you define. Each row is a
field / operator / valuetriple:Operator Meaning equalsField equals the value not equalsField does not equal the value includesField contains the value greater thanField is numerically greater than the value less thanField is numerically less than the value existsField is present in the payload Add as many rows as you need; an event must satisfy all rows to fire. Empty
fieldrows are ignored on save.
External (3rd-party app)
React to events emitted by an external provider.
- Provider — The third-party app to listen to (e.g. Google Drive, Slack, GitHub). Providers that are registered but not yet fully implemented are shown with a
(soon)badge and cannot be saved until their adapter lands. - Provider Event — The specific event from the provider (e.g.
drive.file.created,slack.message.mentioned,github.pr.merged). - Authorisation — The credential the trigger will use to poll the provider. The dropdown lists every Authorisation you have configured in the workspace; the selected authorisation's type is stored as the trigger's authorisation type on save.
- Acquisition Mode — How ToothFairyAI acquires the event:
- Polling (default) — Periodically polls the provider's API for new items.
- Webhook (soon) — Receive push events from the provider. Not yet available.
- Poll Interval (Polling only) — How often to poll. Options: 1, 2, 5, 10, or 30 minutes (default 5 minutes).
- Poll Endpoint (Generic REST provider only) — The full URL to poll, e.g.
https://api.example.com/v1/items. - JSONPath (Generic REST provider only) — The JSONPath expression used to extract the list of new items from each poll response, e.g.
$.items[*].
External triggers need a provider Authorisation to authenticate the poll. If no Authorisations exist when an external provider is selected, the form shows a hint — create an Authorisation first, then return to the trigger.
Status
-
Active — Toggle to arm or pause the trigger. When active, the trigger is saved with status ARMED and will fire on matching events. When inactive it is saved as PAUSED and will not fire until re-enabled.
-
Click on the
Createbutton to save the trigger.
Native events
These are ToothFairyAI's own platform events, organized by category:
| Event ID | Category | Label | Description |
|---|---|---|---|
document.created | documents | Document Created | A new document has been created in the workspace |
document.updated | documents | Document Updated | An existing document has been modified |
document.deleted | documents | Document Deleted | A document has been deleted from the workspace |
agent_completed | agent | Agent Completed | An agent has successfully completed processing a chat message |
agent_failed | agent | Agent Failed | An agent encountered an error while processing a chat message |
planner_completed | planner | Planner Completed | A planner has successfully completed all plan steps |
planner_failed | planner | Planner Failed | A planner encountered an error during execution |
planner_pending_approval | planner | Planner Pending Approval | A generated plan is awaiting user approval |
planner_stopped | planner | Planner Stopped | Plan execution was stopped by the user |
Native events are the same events ToothFairyAI emits over its webhooks. Pairing a trigger with a native event is the in-app way to react to those same lifecycle events.
Event payload shape
Every event — native or external — reaches the bound agent in a normalized payload envelope. Its fields are listed below:
| Field | Type | Description |
|---|---|---|
event_type | string | Normalized event id, e.g. "external.googleDrive.drive.file.created" or "document.updated". External events are always prefixed external.<provider>.<providerEvent>. |
event_category | `string | null` |
source | string | Where the event came from: "api" |
nativeEventId | string | Provider-canonical event name (e.g. googleDrive fileCreated, stripe payment_intent.succeeded). |
event_id | string | Unique event id — used to avoid processing the same event twice per trigger. |
timestamp | string (ISO-8601) | When the event occurred. |
data | object | Provider- or platform-specific payload (fields are detailed per event/provider in the reference below). This is the ONLY part the trigger data-filter rows evaluate against. |
Sample — native (document.created):
{
"event_type": "document.created",
"event_category": "documents",
"source": "api",
"nativeEventId": "document.created",
"event_id": "evt_document.created",
"timestamp": "2026-07-19T03:00:00.000Z",
"data": {
"document_id": 12345,
"external_path": null,
"topics": [],
"status": "draft"
}
}
Sample — external (googleDrive.drive.file.created):
{
"event_type": "external.googleDrive.drive.file.created",
"event_category": null,
"source": "poller",
"nativeEventId": "drive.fileCreated",
"event_id": "evt_googleDrive_drive.file.created",
"timestamp": "2026-07-19T03:00:00.000Z",
"data": {
"fileId": "1a2b3c",
"name": "Proposal.docx",
"mimeType": "application/vnd.google-apps.document",
"modifiedTime": "2026-07-19T03:00:00.000Z",
"eventType": "drive.fileCreated"
}
}
Documents
ToothFairyAI's lifecycle events. Each event below lists the payload the bound agent receives and example data-filter rows.
document.created
Fires when: A new document is created in the workspace — e.g. a file upload, a raw-text document, or a document generated by the API.
Sample payload the agent receives:
{
"event_type": "document.created",
"event_category": "documents",
"source": "api",
"nativeEventId": "document.created",
"event_id": "evt_document.created",
"timestamp": "2026-07-19T03:00:00.000Z",
"data": {
"document_id": 12345,
"external_path": null,
"topics": [],
"status": "draft"
}
}
Fields you can filter on (data):
| Field | Type | Meaning |
|---|---|---|
document_id | number | Internal id of the document |
external_path | `string | null` |
topics | string[] | Topic IDs (UUIDs) the document is assigned to — matching a topic means the trigger fires for documents on that topic |
status | string | Lifecycle status ("draft" |
Filter examples:
| Field | Operator | Value | Fires when |
|---|---|---|---|
status | equals | published | Only documents that are already published |
topics | includes | 5f9c2e4a-7c8d-4b3a-9e2f-1a2b3c4d5e6f | Only documents assigned to a specific topic (match its ID) |
To fire only when a document is assigned to a specific topic:
- Copy the topic's ID from
Settings > Topics(topics are identified by their UUID, e.g.5f9c2e4a-7c8d-4b3a-9e2f-1a2b3c4d5e6f). - Add a data-filter row — Field
topics, Operatorincludes, Value that topic ID. - The event's
data.topicsis an array of topic IDs the document carries, soincludesmatches when any ID in that array equals your value. - Add more rows to narrow further — every row must match. For example a second row
statusequalspublishedrestricts the trigger to published documents on that topic.
document.updated
Fires when: An existing document is modified — content changed, re-indexed or re-published.
Sample payload the agent receives:
{
"event_type": "document.updated",
"event_category": "documents",
"source": "api",
"nativeEventId": "document.updated",
"event_id": "evt_document.updated",
"timestamp": "2026-07-19T03:00:00.000Z",
"data": {
"document_id": 12345,
"external_path": null,
"topics": [],
"status": "published"
}
}
Fields you can filter on (data):
| Field | Type | Meaning |
|---|---|---|
document_id | number | Internal id of the document |
external_path | `string | null` |
topics | string[] | Topic IDs (UUIDs) the document is assigned to — matching a topic means the trigger fires for documents on that topic |
status | string | Lifecycle status ("draft" |
Filter examples:
| Field | Operator | Value | Fires when |
|---|---|---|---|
status | equals | published | Only edits to published documents |
topics | includes | 5f9c2e4a-7c8d-4b3a-9e2f-1a2b3c4d5e6f | Only edits to documents on a specific topic |
document_id | equals | 12345 | Watch one specific document |
document.deleted
Fires when: A document is deleted (archived) from the workspace.
Sample payload the agent receives:
{
"event_type": "document.deleted",
"event_category": "documents",
"source": "api",
"nativeEventId": "document.deleted",
"event_id": "evt_document.deleted",
"timestamp": "2026-07-19T03:00:00.000Z",
"data": {
"document_id": 12345,
"external_path": null,
"topics": [],
"status": "archived"
}
}
Fields you can filter on (data):
| Field | Type | Meaning |
|---|---|---|
document_id | number | Internal id of the document |
external_path | `string | null` |
topics | string[] | Topic IDs (UUIDs) the document is assigned to — matching a topic means the trigger fires for documents on that topic |
status | string | Lifecycle status ("archived") |
Filter examples:
| Field | Operator | Value | Fires when |
|---|---|---|---|
external_path | exists | — | Only documents that were deleted from an external source |
Agents
ToothFairyAI's execution outcomes. Each event below lists the payload the bound agent receives and example data-filter rows.
agent_completed
Fires when: An agent successfully finishes processing a chat message. Pair it with a downstream notification, logging or hand-off agent.
Sample payload the agent receives:
{
"event_type": "agent_completed",
"event_category": "agent",
"source": "system",
"nativeEventId": "agent_completed",
"event_id": "evt_agent_completed",
"timestamp": "2026-07-19T03:00:00.000Z",
"data": {
"status": "success",
"agent_id": null,
"is_from_planner": false,
"step_id": null
}
}
Fields you can filter on (data):
| Field | Type | Meaning |
|---|---|---|
status | string | "success" for this event |
agent_id | `string | null` |
is_from_planner | boolean | True when the run was a step of a planner plan |
step_id | `string | null` |
Filter examples:
| Field | Operator | Value | Fires when |
|---|---|---|---|
is_from_planner | equals | false | Only whole agent runs, not planner sub-steps |
agent_id | exists | — | Only runs attributable to an agent |
agent_failed
Fires when: An agent encounters an error while processing a chat message — useful to alert, log or re-route the work.
Sample payload the agent receives:
{
"event_type": "agent_failed",
"event_category": "agent",
"source": "system",
"nativeEventId": "agent_failed",
"event_id": "evt_agent_failed",
"timestamp": "2026-07-19T03:00:00.000Z",
"data": {
"status": "error",
"agent_id": null,
"is_from_planner": false,
"error": null
}
}
Fields you can filter on (data):
| Field | Type | Meaning |
|---|---|---|
status | string | "error" for this event |
agent_id | `string | null` |
is_from_planner | boolean | True when the run was a step of a planner plan |
error | `object | null` |
Filter examples:
| Field | Operator | Value | Fires when |
|---|---|---|---|
error | exists | — | Only failures that carry error details |
Planners
ToothFairyAI's plan lifecycles. Each event below lists the payload the bound agent receives and example data-filter rows.
planner_completed
Fires when: A planner successfully completes every step of a generated plan.
Sample payload the agent receives:
{
"event_type": "planner_completed",
"event_category": "planner",
"source": "system",
"nativeEventId": "planner_completed",
"event_id": "evt_planner_completed",
"timestamp": "2026-07-19T03:00:00.000Z",
"data": {
"status": "success",
"planner_agent_id": null,
"plan_status": "completed"
}
}
Fields you can filter on (data):
| Field | Type | Meaning |
|---|---|---|
status | string | "success" for this event |
planner_agent_id | `string | null` |
plan_status | string | "completed" for this event |
Filter examples:
| Field | Operator | Value | Fires when |
|---|---|---|---|
plan_status | equals | completed | Only fully completed plans |
planner_failed
Fires when: A planner fails while executing a plan step.
Sample payload the agent receives:
{
"event_type": "planner_failed",
"event_category": "planner",
"source": "system",
"nativeEventId": "planner_failed",
"event_id": "evt_planner_failed",
"timestamp": "2026-07-19T03:00:00.000Z",
"data": {
"status": "error",
"planner_agent_id": null,
"error": null
}
}
Fields you can filter on (data):
| Field | Type | Meaning |
|---|---|---|
status | string | "error" for this event |
planner_agent_id | `string | null` |
error | `object | null` |
Filter examples:
| Field | Operator | Value | Fires when |
|---|---|---|---|
error | exists | — | Only failures that carry error details |
planner_pending_approval
Fires when: A generated plan is awaiting your approval before execution — a natural place to send a Slack or email alert.
Sample payload the agent receives:
{
"event_type": "planner_pending_approval",
"event_category": "planner",
"source": "system",
"nativeEventId": "planner_pending_approval",
"event_id": "evt_planner_pending_approval",
"timestamp": "2026-07-19T03:00:00.000Z",
"data": {
"status": "pending_approval",
"planner_agent_id": null,
"plan_status": "awaiting_approval"
}
}
Fields you can filter on (data):
| Field | Type | Meaning |
|---|---|---|
status | string | "pending_approval" for this event |
planner_agent_id | `string | null` |
plan_status | string | "awaiting_approval" for this event |
Filter examples:
| Field | Operator | Value | Fires when |
|---|---|---|---|
status | equals | pending_approval | Only plans waiting on the user |
planner_stopped
Fires when: Execution of a plan is stopped by the user.
Sample payload the agent receives:
{
"event_type": "planner_stopped",
"event_category": "planner",
"source": "system",
"nativeEventId": "planner_stopped",
"event_id": "evt_planner_stopped",
"timestamp": "2026-07-19T03:00:00.000Z",
"data": {
"status": "stopped",
"planner_agent_id": null,
"plan_status": "stopped_by_user"
}
}
Fields you can filter on (data):
| Field | Type | Meaning |
|---|---|---|
status | string | "stopped" for this event |
planner_agent_id | `string | null` |
plan_status | string | "stopped_by_user" for this event |
Filter examples:
| Field | Operator | Value | Fires when |
|---|---|---|---|
plan_status | equals | stopped_by_user | Only plans stopped by the user (not cancelled) |
External providers
The provider catalog is served live from the ToothFairyAI backend and rendered in the form, so new providers appear automatically. The providers below are currently implemented (field-complete polling adapters):
| Provider | Auth type | Example events |
|---|---|---|
| Google Drive | OAuth | drive.file.created, drive.file.updated, drive.file.deleted, drive.folder.created |
| Microsoft Graph (SharePoint / Azure / OneDrive) | OAuth | graph.drive.item.created, graph.list.item.created, graph.calendar.event.created, graph.mail.received |
| Slack | OAuth | slack.message.posted, slack.message.mentioned, slack.reaction.added, slack.file.shared |
| GitHub | OAuth | github.issue.opened, github.pr.merged, github.push, github.release.published, github.star.created |
| Notion | OAuth | notion.page.created, notion.page.updated, notion.database.created |
| Dropbox | OAuth | dropbox.file.created, dropbox.file.updated, dropbox.file.deleted, dropbox.folder.created |
| Box | OAuth | box.file.created, box.file.updated, box.file.deleted, box.comment.created |
| OneDrive | OAuth | onedrive.file.created, onedrive.file.updated, onedrive.file.deleted |
| Salesforce | OAuth | salesforce.lead.created, salesforce.opportunity.updated, salesforce.case.created, salesforce.custom.object.created |
| HubSpot | OAuth | hubspot.contact.created, hubspot.deal.created, hubspot.ticket.created, hubspot.form.submitted |
| Linear | OAuth | linear.issue.created, linear.issue.status.changed, linear.project.created |
| Jira | OAuth | jira.issue.created, jira.issue.updated, jira.sprint.started, jira.version.released |
| Asana | OAuth | asana.task.created, asana.task.completed, asana.project.created |
| Trello | OAuth | trello.card.created, trello.card.moved, trello.card.commented |
| Zendesk | Basic | zendesk.ticket.created, zendesk.ticket.assigned, zendesk.user.created |
| ServiceNow | Basic | servicenow.incident.created, servicenow.change.request.created, servicenow.problem.created |
| YouTube | OAuth | youtube.video.uploaded, youtube.comment.created, youtube.subscriber.threshold |
| Gmail | OAuth | gmail.message.received, gmail.message.received.label, gmail.message.sent |
| Google Calendar | OAuth | calendar.event.created, calendar.event.started, calendar.event.attendee.response, calendar.reminder |
| Microsoft Forms | OAuth | forms.response.created, forms.response.updated, forms.form.created |
| Microsoft Teams | OAuth | teams.message.created, teams.message.mentioned, teams.channel.created, teams.member.added |
| Stripe | API Key | stripe.payment.intent.succeeded, stripe.charge.refunded, stripe.customer.created, stripe.subscription.created, stripe.invoice.paid |
| Generic REST (API Key / OAuth) | API Key | generic.poll — periodically GET a custom REST endpoint and emit items via JSONPath |
Each provider exposes its own event list in the Provider Event dropdown; only events valid for the selected provider are shown.
For a handful of providers (Slack, GitHub, Box, Linear, Zendesk, Stripe) the native acquisition mode is webhook-based; ToothFairyAI implements a polling adapter for these as a functional fallback, with webhook ingestion arriving in a later release.
External event reference
For each implemented provider, the table below lists every event in the Provider Event dropdown, a sample of the payload the bound agent receives, and the data fields your filter rows can target.
Google Drive
Auth type: oauth · Status: implemented
| Event ID | Label | Partner event | Sources | Pollable |
|---|---|---|---|---|
drive.file.created | File Created | drive.fileCreated | both | yes |
drive.file.updated | File Updated | drive.fileUpdated | both | yes |
drive.file.deleted | File Deleted | drive.fileDeleted | both | yes |
drive.file.shared | File Shared | drive.fileShared | n8n | no |
drive.folder.created | Folder Created | drive.folderCreated | both | yes |
drive.file.downloaded | File Downloaded | drive.fileDownloaded | activepieces | no |
Sample payload (drive.file.created):
{
"event_type": "external.googleDrive.drive.file.created",
"event_category": null,
"source": "poller",
"nativeEventId": "drive.fileCreated",
"event_id": "evt_googleDrive_drive.file.created",
"timestamp": "2026-07-19T03:00:00.000Z",
"data": {
"fileId": "1a2b3c",
"name": "Proposal.docx",
"mimeType": "application/vnd.google-apps.document",
"modifiedTime": "2026-07-19T03:00:00.000Z",
"eventType": "drive.fileCreated"
}
}
data fields your filter rows can target:
| Field | Type | Description |
|---|---|---|
fileId | string | Provider-native file id. |
name | string | File name. |
mimeType | string | File MIME type. |
modifiedTime | string (ISO-8601) | Last modification time. |
Microsoft Graph (SharePoint / Azure / OneDrive)
Auth type: oauth · Status: implemented
| Event ID | Label | Partner event | Sources | Pollable |
|---|---|---|---|---|
graph.drive.item.created | Drive Item Created | graph.driveItemCreated | both | yes |
graph.drive.item.updated | Drive Item Updated | graph.driveItemUpdated | both | yes |
graph.drive.item.deleted | Drive Item Deleted | graph.driveItemDeleted | both | yes |
graph.list.item.created | SharePoint List Item Created | graph.listItemCreated | both | yes |
graph.list.item.updated | SharePoint List Item Updated | graph.listItemUpdated | n8n | yes |
graph.team.message.created | Teams Message Created | graph.teamMessageCreated | both | no |
graph.team.message.reaction | Teams Message Reaction | graph.teamMessageReaction | activepieces | no |
graph.calendar.event.created | Outlook Event Created | graph.calendarEventCreated | both | yes |
graph.calendar.event.updated | Outlook Event Updated | graph.calendarEventUpdated | n8n | yes |
graph.mail.received | Outlook Mail Received | graph.mailReceived | both | no |
graph.contact.created | Outlook Contact Created | graph.contactCreated | activepieces | yes |
Sample payload (graph.drive.item.created):
{
"event_type": "external.microsoftGraph.graph.drive.item.created",
"event_category": null,
"source": "poller",
"nativeEventId": "graph.driveItemCreated",
"event_id": "evt_microsoftGraph_graph.drive.item.created",
"timestamp": "2026-07-19T03:00:00.000Z",
"data": {
"id": "01ABCDEFGHIJ",
"name": "Report.xlsx",
"lastModifiedDateTime": "2026-07-19T03:00:00Z",
"eventType": "graph.driveItemCreated"
}
}
data fields your filter rows can target:
| Field | Type | Description |
|---|---|---|
id | string | Provider-native entity id (driveItem/listItem/...). |
name | string | Entity display name. |
lastModifiedDateTime | string (ISO-8601) | Last modification time. |
Slack
Auth type: oauth · Status: implemented
| Event ID | Label | Partner event | Sources | Pollable |
|---|---|---|---|---|
slack.message.posted | Message Posted | message | both | no |
slack.message.mentioned | App Mentioned | app_mention | both | no |
slack.reaction.added | Reaction Added | reaction_added | both | no |
slack.reaction.removed | Reaction Removed | reaction_removed | n8n | no |
slack.file.shared | File Shared | file_share | both | no |
slack.channel.created | Channel Created | channel_created | activepieces | yes |
slack.user.joined | User Joined Channel | team_join | activepieces | yes |
slack.star.added | Star Added | star_added | n8n | no |
slack.pin.added | Pin Added | pin_added | n8n | no |
Sample payload (slack.message.posted):
{
"event_type": "external.slack.slack.message.posted",
"event_category": null,
"source": "poller",
"nativeEventId": "message",
"event_id": "evt_slack_slack.message.posted",
"timestamp": "2026-07-19T03:00:00.000Z",
"data": {
"ts": "1690000000.001200",
"user": "U02ABCDEF",
"text": "Hello team",
"channel": "C0123ABCDEF",
"ts_iso": "2026-07-19T03:00:00Z",
"eventType": "message"
}
}
data fields your filter rows can target:
| Field | Type | Description |
|---|---|---|
ts | string | Slack message timestamp, used as a stable event id. |
user | string | User id of the author. |
text | string | Message text. |
channel | string | Channel id the message was posted in. |
ts_iso | string (ISO-8601) | Timestamp in ISO format. |
Partner-native acquisition is webhook/Events API. n8n + Activepieces both use webhooks; this poll adapter is a fallback.
GitHub
Auth type: oauth · Status: implemented
| Event ID | Label | Partner event | Sources | Pollable |
|---|---|---|---|---|
github.issue.opened | Issue Opened | issues:opened | both | no |
github.issue.reopened | Issue Reopened | issues:reopened | both | no |
github.issue.closed | Issue Closed | issues:closed | both | no |
github.issue.assigned | Issue Assigned | issues:assigned | n8n | no |
github.issue.commented | Issue Commented | issue_comment:created | both | no |
github.pr.opened | Pull Request Opened | pull_request:opened | both | no |
github.pr.updated | Pull Request Updated | pull_request:edited | both | no |
github.pr.merged | Pull Request Merged | pull_request:closed | both | no |
github.pr.closed | Pull Request Closed | pull_request:closed | both | no |
github.pr.reviewed | Pull Request Reviewed | pull_request_review:submitted | activepieces | no |
github.push | Push | push | both | no |
github.star.created | Star Created | star:created | both | no |
github.fork.created | Fork Created | fork | both | no |
github.release.published | Release Published | release:published | both | no |
github.branch.created | Branch Created | create | activepieces | no |
github.branch.deleted | Branch Deleted | delete | activepieces | no |
github.label.created | Label Created | label:created | n8n | no |
Sample payload (github.issue.opened):
{
"event_type": "external.github.github.issue.opened",
"event_category": null,
"source": "poller",
"nativeEventId": "issues:opened",
"event_id": "evt_github_github.issue.opened",
"timestamp": "2026-07-19T03:00:00.000Z",
"data": {
"id": 1234,
"number": 42,
"title": "Fix login flow",
"state": "open",
"user": "octocat",
"updated_at": "2026-07-19T03:00:00Z",
"eventType": "issues:opened"
}
}
data fields your filter rows can target:
| Field | Type | Description |
|---|---|---|
id | number | GitHub-native id (issue/PR). |
number | number | Issue/PR number. |
title | string | Issue/PR title. |
state | string | Current state (open/closed). |
user | string | Login of the actor. |
updated_at | string (ISO-8601) | Last update time. |
Partner-native acquisition is webhook (repo hooks). n8n + Activepieces both use webhooks; this poll adapter is a fallback.
Notion
Auth type: oauth · Status: implemented
| Event ID | Label | Partner event | Sources | Pollable |
|---|---|---|---|---|
notion.page.created | Page Created | page:page.created | both | yes |
notion.page.updated | Page Updated | page:page.updated | both | yes |
notion.page.deleted | Page Deleted | page:page.archived | n8n | yes |
notion.database.created | Database Created | database:database.created | both | yes |
notion.database.updated | Database Updated | database:database.updated | activepieces | yes |
notion.block.updated | Block Updated | block:block.updated | n8n | yes |
Sample payload (notion.page.created):
{
"event_type": "external.notion.notion.page.created",
"event_category": null,
"source": "poller",
"nativeEventId": "page:page.created",
"event_id": "evt_notion_notion.page.created",
"timestamp": "2026-07-19T03:00:00.000Z",
"data": {
"id": "d23872cd-c106-4afa-b33d-d3fd66064ccb",
"url": "https://www.notion.so/Page-d23872cdc1064afab33dd3fd66064ccb",
"created_time": "2026-07-19T03:00:00.000Z",
"last_edited_time": "2026-07-19T03:00:00.000Z",
"eventType": "page:page.created"
}
}
data fields your filter rows can target:
| Field | Type | Description |
|---|---|---|
id | string | Notion page/database uuid. |
url | string | Public Notion URL. |
created_time | string (ISO-8601) | Creation time. |
last_edited_time | string (ISO-8601) | Last edit time — the poll watermark. |
archived | boolean | Whether the page/database is archived. |
Dropbox
Auth type: oauth · Status: implemented
| Event ID | Label | Partner event | Sources | Pollable |
|---|---|---|---|---|
dropbox.file.created | File Created | file:added | both | yes |
dropbox.file.updated | File Updated | file:modified | both | yes |
dropbox.file.deleted | File Deleted | file:deleted | both | yes |
dropbox.folder.created | Folder Created | folder:added | activepieces | yes |
dropbox.file.shared | File Shared | file:shared | n8n | no |
Sample payload (dropbox.file.created):
{
"event_type": "external.dropbox.dropbox.file.created",
"event_category": null,
"source": "poller",
"nativeEventId": "file:added",
"event_id": "evt_dropbox_dropbox.file.created",
"timestamp": "2026-07-19T03:00:00.000Z",
"data": {
"id": "id:abc",
"name": "notes.txt",
"path": "/notes.txt",
"tag": "file",
"eventType": "file:added"
}
}
data fields your filter rows can target:
| Field | Type | Description |
|---|---|---|
id | string | Dropbox file id. |
name | string | File name. |
path | string | Path within Dropbox. |
tag | string | Object type (file/folder). |
Box
Auth type: oauth · Status: implemented
| Event ID | Label | Partner event | Sources | Pollable |
|---|---|---|---|---|
box.file.created | File Created | ITEM_CREATE/ITEM_UPLOAD | both | yes |
box.file.updated | File Updated | ITEM_MODIFY | both | yes |
box.file.deleted | File Deleted | ITEM_TRASH | both | yes |
box.file.downloaded | File Downloaded | ITEM_DOWNLOAD | both | no |
box.folder.created | Folder Created | FOLDER_CREATE | activepieces | yes |
box.file.shared | File Shared | COLLAB_ADD | n8n | no |
box.comment.created | Comment Created | COMMENT_CREATE | n8n | no |
Sample payload (box.file.created):
{
"event_type": "external.box.box.file.created",
"event_category": null,
"source": "poller",
"nativeEventId": "ITEM_CREATE/ITEM_UPLOAD",
"event_id": "evt_box_box.file.created",
"timestamp": "2026-07-19T03:00:00.000Z",
"data": {
"id": "12345678",
"name": "contract.pdf",
"type": "file",
"eventType": "ITEM_CREATE/ITEM_UPLOAD"
}
}
data fields your filter rows can target:
| Field | Type | Description |
|---|---|---|
id | string | Box item id. |
name | string | Item name. |
type | string | Item type (file/folder). |
eventType | string | Box event type (ITEM_CREATE/ITEM_MODIFY/...). |
Partner-native acquisition is webhook (Box events stream). n8n + Activepieces both use webhooks; this poll adapter is a fallback.
OneDrive
Auth type: oauth · Status: implemented
| Event ID | Label | Partner event | Sources | Pollable |
|---|---|---|---|---|
onedrive.file.created | File Created | graph.driveItemCreated | both | yes |
onedrive.file.updated | File Updated | graph.driveItemUpdated | both | yes |
onedrive.file.deleted | File Deleted | graph.driveItemDeleted | both | yes |
onedrive.folder.created | Folder Created | graph.folderCreated | activepieces | yes |
onedrive.file.shared | File Shared | graph.driveItemShared | n8n | no |
Sample payload (onedrive.file.created):
{
"event_type": "external.onedrive.onedrive.file.created",
"event_category": null,
"source": "poller",
"nativeEventId": "graph.driveItemCreated",
"event_id": "evt_onedrive_onedrive.file.created",
"timestamp": "2026-07-19T03:00:00.000Z",
"data": {
"id": "01ABCDEF",
"name": "slides.pptx",
"lastModifiedDateTime": "2026-07-19T03:00:00Z",
"eventType": "graph.driveItemCreated"
}
}
data fields your filter rows can target:
| Field | Type | Description |
|---|---|---|
id | string | OneDrive/Graph item id. |
name | string | Item name. |
lastModifiedDateTime | string (ISO-8601) | Last modification time. |
Salesforce
Auth type: oauth · Status: implemented
| Event ID | Label | Partner event | Sources | Pollable |
|---|---|---|---|---|
salesforce.lead.created | Lead Created | Lead:create | both | yes |
salesforce.lead.updated | Lead Updated | Lead:update | both | yes |
salesforce.lead.converted | Lead Converted | Lead:convert | both | yes |
salesforce.contact.created | Contact Created | Contact:create | both | yes |
salesforce.contact.updated | Contact Updated | Contact:update | activepieces | yes |
salesforce.opportunity.created | Opportunity Created | Opportunity:create | both | yes |
salesforce.opportunity.updated | Opportunity Updated | Opportunity:update | both | yes |
salesforce.account.created | Account Created | Account:create | both | yes |
salesforce.account.updated | Account Updated | Account:update | activepieces | yes |
salesforce.case.created | Case Created | Case:create | n8n | yes |
salesforce.case.updated | Case Updated | Case:update | n8n | yes |
salesforce.custom.object.created | Custom Object Created | CustomObject:create | activepieces | yes |
salesforce.custom.object.updated | Custom Object Updated | CustomObject:update | activepieces | yes |
Sample payload (salesforce.lead.created):
{
"event_type": "external.salesforce.salesforce.lead.created",
"event_category": null,
"source": "poller",
"nativeEventId": "Lead:create",
"event_id": "evt_salesforce_salesforce.lead.created",
"timestamp": "2026-07-19T03:00:00.000Z",
"data": {
"id": "003...",
"name": "Jane Doe",
"systemModstamp": "2026-07-19T03:00:00Z",
"createdDate": "2026-07-19T03:00:00Z",
"eventType": "Lead:create"
}
}
data fields your filter rows can target:
| Field | Type | Description |
|---|---|---|
id | string | Record id (with prefix). |
name | string | Record display name. |
systemModstamp | string (ISO-8601) | System modification time — the poll watermark. |
createdDate | string (ISO-8601) | Creation time. |
HubSpot
Auth type: oauth · Status: implemented
| Event ID | Label | Partner event | Sources | Pollable |
|---|---|---|---|---|
hubspot.contact.created | Contact Created | contact.creation | both | yes |
hubspot.contact.updated | Contact Updated | contact.propertyChange | both | yes |
hubspot.contact.deleted | Contact Deleted | contact.deletion | both | yes |
hubspot.company.created | Company Created | company.creation | both | yes |
hubspot.company.updated | Company Updated | company.propertyChange | both | yes |
hubspot.deal.created | Deal Created | deal.creation | both | yes |
hubspot.deal.updated | Deal Updated | deal.propertyChange | both | yes |
hubspot.deal.deleted | Deal Deleted | deal.deletion | activepieces | yes |
hubspot.ticket.created | Ticket Created | ticket.creation | both | yes |
hubspot.ticket.updated | Ticket Updated | ticket.propertyChange | both | yes |
hubspot.form.submitted | Form Submitted | form_submission | both | yes |
hubspot.lead.created | Lead Created | lead.creation | activepieces | yes |
hubspot.list.added | Contact Added to List | contact_added_to_list | n8n | yes |
hubspot.email.opened | Email Opened | email_opened | n8n | no |
Sample payload (hubspot.contact.created):
{
"event_type": "external.hubspot.hubspot.contact.created",
"event_category": null,
"source": "poller",
"nativeEventId": "contact.creation",
"event_id": "evt_hubspot_hubspot.contact.created",
"timestamp": "2026-07-19T03:00:00.000Z",
"data": {
"id": "101",
"properties": {
"firstname": "Jane",
"lastname": "Doe",
"email": "jane@example.com"
},
"createdAt": "2026-07-19T03:00:00Z",
"eventType": "contact.creation"
}
}
data fields your filter rows can target:
| Field | Type | Description |
|---|---|---|
id | string | Object id. |
properties.firstname | string | First name (when present). |
properties.lastname | string | Last name (when present). |
properties.email | string | Email (when present). |
createdAt | string (ISO-8601) | Object creation time. |
Linear
Auth type: oauth · Status: implemented
| Event ID | Label | Partner event | Sources | Pollable |
|---|---|---|---|---|
linear.issue.created | Issue Created | Issue.create | both | yes |
linear.issue.updated | Issue Updated | Issue.update | both | yes |
linear.issue.deleted | Issue Deleted | Issue.remove | activepieces | yes |
linear.issue.comment.created | Issue Comment Created | Comment.create | both | yes |
linear.issue.status.changed | Issue Status Changed | Issue.update | activepieces | yes |
linear.project.created | Project Created | Project.create | both | yes |
linear.project.updated | Project Updated | Project.update | both | yes |
linear.cycle.created | Cycle Created | Cycle.create | activepieces | yes |
linear.label.created | Label Created | IssueLabel.create | n8n | yes |
Sample payload (linear.issue.created):
{
"event_type": "external.linear.linear.issue.created",
"event_category": null,
"source": "poller",
"nativeEventId": "Issue.create",
"event_id": "evt_linear_linear.issue.created",
"timestamp": "2026-07-19T03:00:00.000Z",
"data": {
"id": "ISSUE-001",
"identifier": "ENG-42",
"title": "Add feature flag",
"state": "In Progress",
"eventType": "Issue.create"
}
}
data fields your filter rows can target:
| Field | Type | Description |
|---|---|---|
id | string | Issue/project id. |
identifier | string | Human identifier (e.g. ENG-42). |
title | string | Title. |
state | string | Current workflow state. |
Partner-native acquisition is webhook. n8n + Activepieces both use webhooks; this poll adapter is a fallback.
Jira
Auth type: oauth · Status: implemented
| Event ID | Label | Partner event | Sources | Pollable |
|---|---|---|---|---|
jira.issue.created | Issue Created | jira:issue_created | both | yes |
jira.issue.updated | Issue Updated | jira:issue_updated | both | yes |
jira.issue.deleted | Issue Deleted | jira:issue_deleted | both | yes |
jira.issue.assigned | Issue Assigned | jira:issue_assigned | both | yes |
jira.issue.commented | Issue Commented | comment_created | both | yes |
jira.issue.transitioned | Issue Transitioned | jira:issue_transitioned | activepieces | yes |
jira.issue.linked | Issue Linked | issue_link | n8n | yes |
jira.project.created | Project Created | project_created | both | yes |
jira.project.updated | Project Updated | project_updated | activepieces | yes |
jira.sprint.started | Sprint Started | sprint_started | n8n | yes |
jira.sprint.closed | Sprint Closed | sprint_closed | n8n | yes |
jira.version.released | Version Released | jira:version_released | n8n | yes |
jira.worklog.created | Worklog Created | worklog_created | activepieces | yes |
Sample payload (jira.issue.created):
{
"event_type": "external.jira.jira.issue.created",
"event_category": null,
"source": "poller",
"nativeEventId": "jira:issue_created",
"event_id": "evt_jira_jira.issue.created",
"timestamp": "2026-07-19T03:00:00.000Z",
"data": {
"key": "PROJ-123",
"id": "10001",
"summary": "Investigate bug",
"status": "In Progress",
"assignee": "5f...",
"eventType": "jira:issue_created"
}
}
data fields your filter rows can target:
| Field | Type | Description |
|---|---|---|
key | string | Issue key (e.g. PROJ-123). |
id | string | Numeric issue id. |
summary | string | Issue summary. |
status | string | Current status. |
assignee | string | Assignee user key. |
Asana
Auth type: oauth · Status: implemented
| Event ID | Label | Partner event | Sources | Pollable |
|---|---|---|---|---|
asana.task.created | Task Created | task_added | both | yes |
asana.task.updated | Task Updated | task_changed | both | yes |
asana.task.deleted | Task Deleted | task_deleted | both | yes |
asana.task.completed | Task Completed | task_completed | both | yes |
asana.task.assigned | Task Assigned | task_assigned | activepieces | yes |
asana.task.commented | Task Commented | story_added | both | yes |
asana.project.created | Project Created | project_added | both | yes |
asana.project.updated | Project Updated | project_changed | activepieces | yes |
asana.section.created | Section Created | section_added | n8n | yes |
asana.tag.added | Tag Added | tag_added | n8n | yes |
Sample payload (asana.task.created):
{
"event_type": "external.asana.asana.task.created",
"event_category": null,
"source": "poller",
"nativeEventId": "task_added",
"event_id": "evt_asana_asana.task.created",
"timestamp": "2026-07-19T03:00:00.000Z",
"data": {
"id": "1201",
"gid": "1201",
"name": "Design review",
"completed": false,
"assignee": "12345",
"eventType": "task_added"
}
}
data fields your filter rows can target:
| Field | Type | Description |
|---|---|---|
id | string | Task/project gid. |
gid | string | Alias for the global id. |
name | string | Task/project name. |
completed | boolean | Whether the task is completed. |
assignee | string | Assignee user id. |
Trello
Auth type: oauth · Status: implemented
| Event ID | Label | Partner event | Sources | Pollable |
|---|---|---|---|---|
trello.card.created | Card Created | createCard | both | yes |
trello.card.updated | Card Updated | updateCard | both | yes |
trello.card.moved | Card Moved | updateCard:idList | both | yes |
trello.card.archived | Card Archived | updateCard:closed | both | yes |
trello.card.deleted | Card Deleted | deleteCard | activepieces | yes |
trello.card.commented | Card Commented | commentCard | both | yes |
trello.card.assigned | Card Member Added | addMemberToCard | both | yes |
trello.checklist.completed | Checklist Item Completed | updateCheckItemState | activepieces | yes |
trello.list.created | List Created | createList | both | yes |
trello.board.created | Board Created | createBoard | n8n | yes |
trello.attachment.added | Attachment Added | addAttachmentToCard | n8n | yes |
Sample payload (trello.card.created):
{
"event_type": "external.trello.trello.card.created",
"event_category": null,
"source": "poller",
"nativeEventId": "createCard",
"event_id": "evt_trello_trello.card.created",
"timestamp": "2026-07-19T03:00:00.000Z",
"data": {
"id": "5f...",
"name": "Write spec",
"listId": "list-1",
"closed": false,
"dateLastActivity": "2026-07-19T03:00:00Z",
"eventType": "createCard"
}
}
data fields your filter rows can target:
| Field | Type | Description |
|---|---|---|
id | string | Card/list/board id. |
name | string | Entity name. |
listId | string | Id of the parent list (cards). |
closed | boolean | Archived flag. |
dateLastActivity | string (ISO-8601) | Last activity time. |
Zendesk
Auth type: basic · Status: implemented
| Event ID | Label | Partner event | Sources | Pollable |
|---|---|---|---|---|
zendesk.ticket.created | Ticket Created | Ticket Created | both | yes |
zendesk.ticket.updated | Ticket Updated | Ticket Updated | both | yes |
zendesk.ticket.assigned | Ticket Assigned | Ticket Assigned | both | yes |
zendesk.ticket.commented | Ticket Commented | Comment Created | both | yes |
zendesk.ticket.status.changed | Ticket Status Changed | Ticket Status Changed | activepieces | yes |
zendesk.ticket.escalated | Ticket Escalated | Ticket Escalated | n8n | yes |
zendesk.user.created | User Created | User Created | both | yes |
zendesk.organization.created | Organization Created | Organization Created | both | yes |
zendesk.article.created | Help Center Article Created | Article Created | activepieces | yes |
zendesk.satisfaction.created | Satisfaction Rating Created | Satisfaction Rating Created | n8n | yes |
Sample payload (zendesk.ticket.created):
{
"event_type": "external.zendesk.zendesk.ticket.created",
"event_category": null,
"source": "poller",
"nativeEventId": "Ticket Created",
"event_id": "evt_zendesk_zendesk.ticket.created",
"timestamp": "2026-07-19T03:00:00.000Z",
"data": {
"id": 35436,
"subject": "Login issue",
"status": "open",
"assigneeId": 123,
"updatedAt": "2026-07-19T03:00:00Z",
"eventType": "Ticket Created"
}
}
data fields your filter rows can target:
| Field | Type | Description |
|---|---|---|
id | number | Ticket id. |
subject | string | Ticket subject. |
status | string | Ticket status (open/pending/...). |
assigneeId | number | Assignee user id. |
updatedAt | string (ISO-8601) | Last update time. |
Partner-native acquisition is webhook (Zendesk notifications). n8n + Activepieces both use webhooks; this poll adapter is a fallback.
ServiceNow
Auth type: basic · Status: implemented
| Event ID | Label | Partner event | Sources | Pollable |
|---|---|---|---|---|
servicenow.incident.created | Incident Created | sys_created_on:incident | both | yes |
servicenow.incident.updated | Incident Updated | sys_updated_on:incident | both | yes |
servicenow.incident.assigned | Incident Assigned | assigned_to:incident | both | yes |
servicenow.incident.resolved | Incident Resolved | state:7:incident | activepieces | yes |
servicenow.incident.closed | Incident Closed | state:8:incident | activepieces | yes |
servicenow.change.request.created | Change Request Created | change_request:create | both | yes |
servicenow.change.request.updated | Change Request Updated | change_request:update | both | yes |
servicenow.change.request.approved | Change Request Approved | change_request:approved | activepieces | yes |
servicenow.problem.created | Problem Created | problem:create | n8n | yes |
servicenow.problem.updated | Problem Updated | problem:update | n8n | yes |
servicenow.request.created | Service Request Created | sc_request:create | activepieces | yes |
servicenow.catalog.task.created | Catalog Task Created | sc_task:create | n8n | yes |
Sample payload (servicenow.incident.created):
{
"event_type": "external.servicenow.servicenow.incident.created",
"event_category": null,
"source": "poller",
"nativeEventId": "sys_created_on:incident",
"event_id": "evt_servicenow_servicenow.incident.created",
"timestamp": "2026-07-19T03:00:00.000Z",
"data": {
"sysId": "sys-abc",
"number": "INC0010001",
"state": "2",
"assignedTo": "user-1",
"updatedAt": "2026-07-19 03:00:00",
"eventType": "sys_created_on:incident"
}
}
data fields your filter rows can target:
| Field | Type | Description |
|---|---|---|
sysId | string | Record sys_id. |
number | string | Record number (e.g. INC0010001). |
state | string | State value as stored by ServiceNow. |
assignedTo | string | Assignee user id. |
updatedAt | string | Last update time. |
YouTube
Auth type: oauth · Status: implemented
| Event ID | Label | Partner event | Sources | Pollable |
|---|---|---|---|---|
youtube.video.uploaded | Video Uploaded | activities:upload | both | yes |
youtube.video.updated | Video Updated | activities:channelItem | both | yes |
youtube.video.published | Video Published | videos:public | activepieces | yes |
youtube.comment.created | Comment Created | commentThreads:insert | both | yes |
youtube.comment.replied | Comment Reply Created | comments:insert | activepieces | yes |
youtube.subscriber.threshold | Subscriber Threshold Reached | channels:subscriberCount | both | yes |
youtube.liked.video | New Liked Video | activities:likeItem | activepieces | yes |
youtube.playlist.created | Playlist Created | playlists:insert | n8n | yes |
youtube.live.broadcast.started | Live Broadcast Started | liveBroadcast:start | n8n | yes |
Sample payload (youtube.video.uploaded):
{
"event_type": "external.youtube.youtube.video.uploaded",
"event_category": null,
"source": "poller",
"nativeEventId": "activities:upload",
"event_id": "evt_youtube_youtube.video.uploaded",
"timestamp": "2026-07-19T03:00:00.000Z",
"data": {
"id": "abc",
"title": "New release",
"channelId": "UC...",
"publishedAt": "2026-07-19T03:00:00Z",
"eventType": "activities:upload"
}
}
data fields your filter rows can target:
| Field | Type | Description |
|---|---|---|
id | string | Video/comment/activity id. |
title | string | Content title. |
channelId | string | Owning channel id. |
publishedAt | string (ISO-8601) | Publish time. |
Gmail
Auth type: oauth · Status: implemented
| Event ID | Label | Partner event | Sources | Pollable |
|---|---|---|---|---|
gmail.message.received | Message Received | history:messageAdded | both | yes |
gmail.message.received.label | Message Received (Label) | history:messageAdded:label | both | yes |
gmail.message.sent | Message Sent | history:messageAdded:sent | both | yes |
gmail.thread.replied | Thread Replied | history:messageAdded:reply | activepieces | yes |
gmail.attachment.received | Attachment Received | history:messageAdded:attachment | activepieces | yes |
gmail.label.added | Label Added | history:addLabel | n8n | yes |
gmail.starred | Message Starred | history:star | n8n | yes |
gmail.draft.created | Draft Created | history:draftCreated | n8n | yes |
Sample payload (gmail.message.received):
{
"event_type": "external.gmail.gmail.message.received",
"event_category": null,
"source": "poller",
"nativeEventId": "history:messageAdded",
"event_id": "evt_gmail_gmail.message.received",
"timestamp": "2026-07-19T03:00:00.000Z",
"data": {
"id": "18c...",
"threadId": "18c...",
"labelIds": [
"INBOX"
],
"eventType": "history:messageAdded"
}
}
data fields your filter rows can target:
| Field | Type | Description |
|---|---|---|
id | string | Message id. |
threadId | string | Thread id. |
labelIds | string[] | Labels applied to the message. |
Google Calendar
Auth type: oauth · Status: implemented
| Event ID | Label | Partner event | Sources | Pollable |
|---|---|---|---|---|
calendar.event.started | Event Started | calendar.events:start | both | yes |
calendar.event.ends | Event Ends Soon | calendar.events:end | both | yes |
calendar.event.created | Event Created | calendar.events:created | both | yes |
calendar.event.updated | Event Updated | calendar.events:updated | both | yes |
calendar.event.deleted | Event Deleted | calendar.events:deleted | both | yes |
calendar.event.cancelled | Event Cancelled | calendar.events:cancelled | activepieces | yes |
calendar.event.attendee.response | Attendee Response | calendar.events:attendeeResponse | both | yes |
calendar.reminder | Event Reminder | calendar.events:reminder | activepieces | yes |
Sample payload (calendar.event.started):
{
"event_type": "external.calendar.calendar.event.started",
"event_category": null,
"source": "poller",
"nativeEventId": "calendar.events:start",
"event_id": "evt_calendar_calendar.event.started",
"timestamp": "2026-07-19T03:00:00.000Z",
"data": {
"id": "evt-1",
"summary": "Standup",
"status": "confirmed",
"start": {
"dateTime": "2026-07-19T09:00:00Z"
},
"eventType": "calendar.events:start"
}
}
data fields your filter rows can target:
| Field | Type | Description |
|---|---|---|
id | string | Calendar event id. |
summary | string | Event title. |
status | string | Event status (confirmed/tentative/cancelled). |
start.dateTime | string (ISO-8601) | Start time in the event's timezone. |
Microsoft Forms
Auth type: oauth · Status: implemented
| Event ID | Label | Partner event | Sources | Pollable |
|---|---|---|---|---|
forms.response.created | Response Created | forms:responseCreated | both | yes |
forms.response.updated | Response Updated | forms:responseUpdated | both | yes |
forms.form.created | Form Created | forms:formCreated | both | yes |
forms.form.updated | Form Updated | forms:formUpdated | activepieces | yes |
forms.response.submitted | Response Submitted | forms:responseSubmitted | n8n | yes |
Sample payload (forms.response.created):
{
"event_type": "external.forms.forms.response.created",
"event_category": null,
"source": "poller",
"nativeEventId": "forms:responseCreated",
"event_id": "evt_forms_forms.response.created",
"timestamp": "2026-07-19T03:00:00.000Z",
"data": {
"id": "resp-1",
"responder": {
"id": "user-1"
},
"submittedDateTime": "2026-07-19T03:00:00Z",
"eventType": "forms:responseCreated"
}
}
data fields your filter rows can target:
| Field | Type | Description |
|---|---|---|
id | string | Response id. |
responder.id | string | User id of the respondent. |
submittedDateTime | string (ISO-8601) | Submission time. |
Microsoft Teams
Auth type: oauth · Status: implemented
| Event ID | Label | Partner event | Sources | Pollable |
|---|---|---|---|---|
teams.message.created | Channel Message Created | message:channelMessage | both | no |
teams.message.replied | Channel Message Reply | message:reply | both | no |
teams.message.mentioned | App Mentioned | message:mention | both | no |
teams.chat.message.created | Chat Message Created | message:chat | activepieces | no |
teams.member.joined | Member Joined Team | teams:memberJoined | activepieces | yes |
teams.member.added | Member Added to Channel | teams:memberAdded | both | yes |
teams.channel.created | Channel Created | teams:channelCreated | both | yes |
teams.team.created | Team Created | teams:teamCreated | n8n | yes |
teams.card.action | Card Action Submitted | teams:cardAction | activepieces | no |
Sample payload (teams.message.created):
{
"event_type": "external.teams.teams.message.created",
"event_category": null,
"source": "poller",
"nativeEventId": "message:channelMessage",
"event_id": "evt_teams_teams.message.created",
"timestamp": "2026-07-19T03:00:00.000Z",
"data": {
"id": "1690000000000",
"from": "user-1",
"lastModifiedDateTime": "2026-07-19T03:00:00Z",
"eventType": "message:channelMessage"
}
}
data fields your filter rows can target:
| Field | Type | Description |
|---|---|---|
id | string | Activity/message activity id. |
from | string | Sending user id. |
lastModifiedDateTime | string (ISO-8601) | Activity time. |
Stripe
Auth type: apikey · Status: implemented
| Event ID | Label | Partner event | Sources | Pollable |
|---|---|---|---|---|
stripe.payment.intent.created | Payment Intent Created | payment_intent.created | both | yes |
stripe.payment.intent.succeeded | Payment Succeeded | payment_intent.succeeded | both | yes |
stripe.payment.intent.failed | Payment Failed | payment_intent.payment_failed | both | yes |
stripe.charge.created | Charge Created | charge.created | both | yes |
stripe.charge.refunded | Charge Refunded | charge.refunded | both | yes |
stripe.charge.dispute.created | Dispute Created | charge.dispute.created | both | yes |
stripe.customer.created | Customer Created | customer.created | both | yes |
stripe.customer.updated | Customer Updated | customer.updated | both | yes |
stripe.customer.deleted | Customer Deleted | customer.deleted | both | yes |
stripe.subscription.created | Subscription Created | customer.subscription.created | both | yes |
stripe.subscription.updated | Subscription Updated | customer.subscription.updated | both | yes |
stripe.subscription.deleted | Subscription Canceled | customer.subscription.deleted | both | yes |
stripe.invoice.created | Invoice Created | invoice.created | both | yes |
stripe.invoice.paid | Invoice Paid | invoice.paid | both | yes |
stripe.invoice.payment_failed | Invoice Payment Failed | invoice.payment_failed | activepieces | yes |
stripe.refund.created | Refund Created | refund.created | activepieces | yes |
stripe.checkout.session.completed | Checkout Session Completed | checkout.session.completed | n8n | yes |
stripe.payout.paid | Payout Paid | payout.paid | n8n | yes |
Sample payload (stripe.payment.intent.created):
{
"event_type": "external.stripe.stripe.payment.intent.created",
"event_category": null,
"source": "poller",
"nativeEventId": "payment_intent.created",
"event_id": "evt_stripe_stripe.payment.intent.created",
"timestamp": "2026-07-19T03:00:00.000Z",
"data": {
"id": "evt_1",
"type": "event",
"created": 1690000000,
"livemode": false,
"dataObjectId": "pi_3...",
"eventType": "payment_intent.created"
}
}
data fields your filter rows can target:
| Field | Type | Description |
|---|---|---|
id | string | Stripe event id (evt_...). |
type | string | Stripe event type (e.g. payment_intent.succeeded). |
created | number | Unix timestamp of the event. |
livemode | boolean | Whether the event is from a live account. |
dataObjectId | string | Id of the affected object. |
Partner-native acquisition is webhook (Stripe strongly discourages /v1/events polling). n8n + Activepieces both use webhooks; this poll adapter is a fallback.
Generic REST (API Key / OAuth)
Auth type: apikey · Status: implemented
| Event ID | Label | Partner event | Sources | Pollable |
|---|---|---|---|---|
generic.poll | Custom Polling Endpoint | generic.poll | both | yes |
Sample payload (generic.poll):
{
"event_type": "external.generic.generic.poll",
"event_category": null,
"source": "poller",
"nativeEventId": "generic.poll",
"event_id": "evt_generic_generic.poll",
"timestamp": "2026-07-19T03:00:00.000Z",
"data": {
"value": "custom-item",
"eventType": "generic.poll"
}
}
data fields your filter rows can target:
| Field | Type | Description |
|---|---|---|
value | any | Arbitrary item returned by the custom endpoint (or the JSONPath-selected object). |
Managing triggers
Once created, triggers appear in the triggers list with their name, bound agent, event source, and status.
| Status | Meaning |
|---|---|
| ARMED | Trigger is active and will fire on matching events |
| PAUSED | Trigger is inactive and will not fire |
| PENDING | Trigger creation is in progress (transient) |
| RUNNING | A fire is currently executing |
| FIRING | A matching event was accepted and the agent run has been submitted |
| COMPLETED | The last fire finished successfully |
| FAILED | The last fire failed (agent error, validation error, or all retries exhausted) |
| DISABLED | The trigger was permanently disabled |
A trigger briefly shows FIRING while its bound agent runs, then settles on COMPLETED or FAILED.
Edit a trigger
- Click on an existing trigger from the list.
- The edit modal displays the trigger ID and all configuration options.
- Modify any settings as needed.
- Click
Saveto update the trigger.
Delete a trigger
- Open the trigger you want to delete.
- Click the
Deletebutton at the bottom of the edit modal. - Confirm the deletion when prompted.
Triggers vs Jobs
| Triggers | Jobs | |
|---|---|---|
| Runs on | An event occurring | A fixed schedule |
| Best for | Real-time reaction to changes | Repetitive, clock-driven tasks |
| Event scope | Native platform events or 30+ external providers | Your workspace only |
| Acquisition | Polling (webhook soon) | Internal scheduler |
For proactive, time-boxed automation use a Job; for reactive, event-driven automation use a Trigger. Combine both — e.g. a Slack-triggered agent that runs on every new mention, plus a daily routine job that summarizes the day's activity.
Use cases
Native
- Document lifecycle — Re-index or summarize a document the moment it's created or updated.
- Agent completion — Trigger a downstream agent (notification, logging) whenever another agent finishes.
- Planner approval — Send a Slack or email alert when a generated plan is awaiting approval.
External
- Support triage —
zendesk.ticket.created→ an agent drafts a first-pass response and suggests a category. - Sales follow-up —
hubspot.deal.created/salesforce.opportunity.updated→ an agent drafts a tailored follow-up email. - Code review assist —
github.pr.opened→ an agent reads the diff and posts a review checklist. - Inbound email triage —
gmail.message.received(label) → an agent categorizes and routes the email. - Payment alerts —
stripe.charge.dispute.created→ an agent summarizes the dispute and drafts a customer response. - Calendar reminders —
calendar.event.starts→ an agent prepares an agenda from related materials. - Custom API —
generic.pollagainst your own REST endpoint → an agent acts on every new item.
Best practices
- Pick the lightest source — Prefer a Native event over an external poll when the workflow only needs to react to something inside ToothFairyAI.
- Use data filters — Narrow Native triggers with data-filter rows so the agent only fires on events it actually needs to act on.
- Right-size the poll interval — Use the smallest interval that still avoids hitting a provider's rate limits. 30 minutes is plenty for slow-moving data; 1–2 minutes only when latency matters.
- Scope prompts to the agent — Assign the bound prompt to the trigger's agent (via
availableToAgents) so the dropdown shows only relevant prompts. - Reuse Authorisations — One provider Authorisation can back several triggers; configure it once in Authorisations and reuse it.
- Naming — Use descriptive names that state provider + event + intent, e.g. "Slack mention → triage agent".
- Start armed, observe first — Arm the trigger and watch a few fires' outputs in External chats before relying on it in production.
- Pause, don't delete — Temporarily pausing a trigger keeps its configuration intact while you investigate or re-tune.
Triggers are subject to the same execution limits as manual agent runs — token limits, execution timeouts, and rate limits based on your subscription tier. Averted triggers still consume a poll against the provider's API on each interval.
Only agents that have been previously created and saved in your workspace appear in the agent dropdown. Voice-mode agents are excluded. Ensure the necessary agent is configured before creating a trigger.
What happens when a trigger fires
Triggers are processed asynchronously by ToothFairyAI's infrastructure and never block the operation that produced the event. The flow is:
- Event — A native platform event (
document.created,agent_completed,planner_pending_approval, ...) or an external provider event acquired by polling is normalized into a single flat envelope. - Match — For the event's workspace, every active trigger is evaluated. A native trigger fires only when its event type, event category, and all data-filter rows match the event payload; an external trigger fires only when the received
external.<provider>.<event>matches its configured provider event. - Fire — The matching trigger's agent is submitted as an execution job with the triggering event (and the forced prompt or saved prompt) attached. The trigger flips to FIRING.
- Run & settle — The agent executes exactly as a manual run would. The trigger settles to COMPLETED on a successful agent completion or FAILED if the run errors or exhausts its retries. The trigger's
triggerCountandlastEventIDare updated for traceability, and each event is processed at most once per trigger.
Each trigger fire is deduplicated per event (lastEventID), so redeliveries never double-fire an agent.
Troubleshooting
| Symptom | Cause & fix |
|---|---|
| Trigger stays ARMED, never moves to FIRING/COMPLETED/FAILED | The event never reached the match step or didn't match. Verify the event actually fires (e.g. the document lifecycle events fire on /doc/create, uploads and deletes), and check the payload — data.topics is an array of topic IDs, and every data-filter row must match. |
Trigger fires but settles FAILED with Invalid agent id for this workspace | The trigger's agent is global (not owned by the workspace). Re-select an agent from your workspace's agent list and save. |
Keyword equals / not equals / greater than / less than don't match in an integration | Filter operators accept both the friendly spellings shown in the form (equals, not equals, greater than, less than) and short forms (eq, neq, gt, lt); includes / exists are identical in both vocabularies. |
| External trigger "fires" but no agent run appears | External triggers need a workspace Authorisation with valid credentials — check the authorisation's token hasn't expired or been revoked. |
| Trigger stuck in FIRING for a long time | Agent runs with retrieval + LLM generation can take several minutes; if it remains in FIRING past the execution timeout, the run failed to settle — re-check the agent's health and the trigger's execution limits. |