Get automatic, real-time updates from airfocus by connecting your favorite apps using our Webhooks.
Benefits of using webhooks
Webhooks let airfocus and other apps work together easily and in real-time. This means updates and notifications happen quickly without needing extra apps or complicated coding.
Initial setup of a new webhook
Create a new workspace in airfocus, or select the one you would like to create a new webhook in.
Requirements:
- “Full” permissions to the workspace in which you want to set up the webhook.
- Paid subscription to Professional or Enterprise plan.
- Technical knowledge for proper configuration.
You can add multiple webhooks to a given workspace (e.g. to different Slack channels for different stakeholder audiences).
To do that, simply go to the Extensions section within your workspace, click on "Add integrations" and "Connect" under Webhook.
Next, give your webhook a name (optional) and select which events the requests should be triggered for.
In the request options, choose the placeholder format, and method and paste your webhook URL into the URL field. You can also add headers to your requests if needed.
Optionally you can also configure your request's body in the placeholder format chosen above.
{
"blocks": [
{
"type": "divider"
},
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": "{{title|esc}}"
},
"accessory": {
"type": "button",
"text": {
"type": "plain_text",
"text": "Open in airfocus",
"emoji": true
},
"value": "click_me_123",
"url": "{{url}}",
"action_id": "button-action"
}
},
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": "{{details|esc}}"
}
}
]
}For detailed documentation of customization options for your webhooks please read the following section.
Use case - receive Slack notifications for airfocus updates
For this use case, our goal is to configure a webhook that will send a Slack message to a channel of our choice every time an item of the workspace we configure the webhook for gets its status updated.
To do so, we need to set up a Slack app to generate a webhook URL and then configure the rest of the integration in airfocus.
How to create a webhook URL to your Slack channel:
-
Create a new Slack app in the Slack workspace where you want to receive the airfocus notifications.
- From the Features page, turn on the Activate Incoming Webhooks option.
- Click Add New Webhook to Workspace.
- Pick a channel that the app will post to, then click Allow.
-
Copy the webhook URL and open the airfocus workspace for which you want to setup the updates.
How to configure your webhook in airfocus to send event update notifications to Slack:
- In the extensions popover, click on “Add integrations”.
- On the integrations overview, click on “Connect” underneath the “Webhooks” integration.
- Give your webhook a name (optional) and select which events the requests should be triggered for. → “Status updated” for this use case.
- In the request options, select “Slack markdown” as the placeholder format and “POST” as the method. Now paste the webhook URL you copied from Slack into the URL field.
- To receive properly formatted Slack messages, paste the following template into the body field and press update.
-
{
"blocks": [
{
"type": "divider"
},
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": "{{title|esc}}"
},
"accessory": {
"type": "button",
"text": {
"type": "plain_text",
"text": "Open in airfocus",
"emoji": true
},
"value": "click_me_123",
"url": "{{url}}",
"action_id": "button-action"
}
},
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": "{{details|esc}}"
}
}
]
}
-
- You will now receive a Slack message to the channel you chose when any item in the workspace has its Status changed.
Get airfocus updates in Microsoft Teams
Note: The Microsoft Teams webhook connector feature is being deprecated at the end of April 2026. The guide below includes steps for how to use the Workflows feature as an alternative.
The Microsoft Teams Workflows feature allows you to configure a webhook that sends a Teams message to a designated channel when items within a particular airfocus workspace are updated. To do this, you’ll need to generate a webhook URL on Microsoft Teams and then configure the rest of the integration in airfocus.
Create a webhook URL in Microsoft Teams
To generate a webhook URL in Microsoft Teams, follow these steps:
- Log in to Microsoft Teams.
- Click the three-dot menu in the navigation menu on the far left side.
- Select Workflows.
- In the search bar, search “webhook”.
- Select Post to a channel when a webhook request is received.
- Type a name for your workflow (e.g., "Airfocus updates").
- Click Next.
- Under “Details”, select the specific Team and Channel where you want the updates to appear.
- Click Add workflow.
- On the confirmation screen, copy the POST URL.
- This is the webhook URL you will need to paste into airfocus.
- Click Done to finalize the setup.
Configure your webhook in airfocus
To configure your webhook in airfocus, follow these steps:
- Open the airfocus workspace for which you want to send updates to Microsoft Teams.
- Click Extensions from the top-right corner of the workspace.
- Select Add integrations.
- Under “Webhooks”, click Connect.
- Type a name for the webhook.
- Under “Events”, select what type of updates you want to be sent to Microsoft Teams.
- Under “Placeholder format”, select Markdown.
- Under “Method”, select POST then paste the URL you generated in Microsoft Teams under “URL”.
- Select + Add header.
- Under “Header name”, type “Content-Type”.
- Under “Header value”, type “application/json”.
- To receive properly formatted Microsoft Teams messages, paste the following template into the body field.
{ "type": "AdaptiveCard", "$schema": "http://adaptivecards.io/schemas/adaptive-card.json", "version": "1.4", "body": [ { "type": "TextBlock", "text": "{{title}}", "size": "Medium", "weight": "Bolder", "wrap": true }, { "type": "TextBlock", "text": "{{details}}", "wrap": true } ], "actions": [ { "type": "Action.OpenUrl", "title": "Open in airfocus", "url": "{{url}}" } ] }
- Click Update from the bottom-right of the page.
You’ll now receive updates to the Microsoft Teams channel you set up in the first section.
Configuring HTTP request - technical documentation
Method
It’s set to POST by default, but can be changed also to GET or PUT. Other methods are not supported.
URL
- should not be empty
- can only start with https:// (other schemes or empty scheme is not supported)
- should have a public domain name with a well-known top-level-domain (IPs are not supported)
Headers
- Authorization is supported
- Content-Type is supported
- custom headers which start with x- are supported
- any other headers are not supported
Body
Defines a request body of the webhook.
Can contain any text up to 2000 characters long.
In order to fill out the request body with meaningful event-data, we provide a bunch of placeholders which our server replaces with event-data before sending the request.
Placeholder format
Specifies how the placeholders with RichText type should be pre-rendered by our server. For example {{title}} placeholder can contain a string like “John updated field Labels on item Fix the button” which contains some rich-text formatting like bold, italic, etc, and therefore the placeholder format specifies in which specific syntax this formatting should be transformed. Available formats:
| Name | Description | Example |
| markdown | default markdown | John updated field Labels on item Fix the button |
| html | <b>John</b> updated field <i>Labels</i> on item <b>Fix the button</b> |
|
| text | formatting removed | John updated field Labels on item Fix the button |
| slack | special Slack mrkdwn | *John* updated field *Labels* on item *Fix the button* |
Placeholders
| Placeholder | Type | Description | Example |
{{type}} |
String | type of event | updatedItem |
{{title}} |
String (RichText) | describes event action | John updated field Labels on item Fix the button |
{{details}} |
String (RichText) | additional event details (e.g. what was changed) | Old value ⇒ New value |
{{url}} |
String | call-to-action URL for each specific event (e.g. a link to a workspace or an item) |
https://myteam.airfocus.com/w/workspaceId?item=itemId *replace airfocus.com with airfocus.app if you are located in the US or APAC region and your account was created after September 2025 |
{{event}} |
JSON | full JSON data about the current event | See the Event Payload Model below |
{{title|esc}} |
String (RichText) | same as {{title}} but all double quotes are escaped |
transforms string with "double" quotes into string with \"double\" quotes |
{{details|esc}} |
String (RichText) | same as {{details}} but all double quotes are escaped |
transforms string with "double" quotes into string with \"double\" quotes |
Data Models
Event Payload Model
A top level object, produced for each event. It contains data about the event as well as embedded basic data about all entities which are related to this event.
| Field | Type | Required | Description |
| event | Event | yes | basic data about the event |
| embed | EventEmbed | yes | additional data about the event - mostly names of items/workspaces/fields/etc which are related to this event |
| matchedFilter | EventFilter | yes | one of the event-filters selected in the integration settings, which matched the current event |
Event Model
Basic data about the event
| Field | Type | Required | Description |
| id | UUID | yes | unique ID of the event |
| initiator | EventInitiator | yes | information about who initiated this event |
| data | EventData | yes | the actual data of the event. It’s different per each specific event-type |
| createdAt | timestamp | yes | when the event has happened |
EventInitiator Model
Information about who initiated this event. In most cases the userId will be defined. It’s also possible that there will be both userId and integrationId defined - e.g. if a user pressed the “synchronise integration” button which then produced the event.
| Field | Type | Required | Description |
| userId | UUID | no | defined if this event was initiated by a user |
| appId | UUID | no | defined if this event was initiated by an app |
| integrationId | UUID | no | defined if this event was initiated by an integration |
| eventId | UUID | no | defined if this event was initiated by another event |
| requestId | UUID | no | defined if this event was initiated inside an HTTP request |
EventEmbed Model
Additional data about the event - mostly names of items/workspaces/fields/etc which are related to this event.
| Field | Type | Required | Description |
| teams | {UUID: TeamInfo} | no | a hash-map of team IDs to team data |
| users | {UUID: UserInfo} | no | a hash-map of user IDs to user data |
| apps | {UUID: AppInfo} | no | a hash-map of app IDs to app data |
| workspaces | {UUID: WorkspaceInfo} | no | a hash-map of workspace IDs to workspace data |
| integrations | {UUID: IntegrationInfo} | no | a hash-map of integration IDs to integration data |
| fields | {UUID: FieldInfo} | no | a hash-map of field IDs to field data |
| statuses | {UUID: StatusInfo} | no | a hash-map of status IDs to status data |
| items | {UUID: ItemInfo} | no | a hash-map of item IDs to item data |
TeamInfo Model
| Field | Type | Required | Description |
| name | String | yes | team name |
| slug | String | yes | team URL slug |
| baseUrl | String | yes | example: https://myteam.airfocus.com *replace airfocus.com with airfocus.app if you are located in the US or APAC region and your account was created after September 2025 |
UserInfo Model
| Field | Type | Required | Description |
| teamId | UUID | yes | ID of the team this user belongs to |
| fullName | String | yes | user’s full name |
AppInfo Model
| Field | Type | Required | Description |
| teamId | UUID | yes | ID of the team this app belongs to |
| typeId | String | yes | one of: forms, insights, mirror, portal, prioritization |
WorkspaceInfo Model
| Field | Type | Required | Description |
| teamId | UUID | yes | ID of the team this workspace belongs to |
| name | String | yes | workspace name |
IntegrationInfo Model
| Field | Type | Required | Description |
| workspaceId | UUID | yes | ID of the workspace this integration belongs to |
| typeId | String | yes | one of: asana, azure-devops, clubhouse, github, intercom, jira, planner, trello |
StatusInfo Model
| Field | Type | Required | Description |
| workspaceId | UUID | yes | ID of the workspace this status belongs to |
| name | String | yes | name of the status |
| category | String | yes | one of: draft, active, closed |
ItemInfo Model
| Field | Type | Required | Description |
| workspaceId | UUID | yes | ID of the workspace this item belongs to |
| statusId | UUID | yes | ID of the item’s status |
| name | String | yes | item’s name |
EventData Model
EventData is a union type - it can either of the specified types:
CreatedItem
| Field | Type | Required | Description |
| itemId | UUID | yes | id of the created item |
UpdatedItem
| Field | Type | Required | Description |
| itemId | UUID | yes | id of the updated item |
| status | {prev: UUID, next: UUID} | no | old and new IDs of the status (if changed) |
| color | {prev: String, next: String} | no | old and new IDs of the item colour (if changed) |
| assigneeUserIds | {prev: UUID[], next: UUID[]} | no | old and new list of assigned user IDs (if changed) |
| name | {prev: String, next: String} | no | old and new item name (if changed) |
| description | {prev: RichText, next: RichText} | no | old and new item description (if changed) |
| description | { UUID: { prev: JSON, next: JSON } } | no | a hash-map of field-ids to their changed values each value is some JSON which depends of the field-type |
| archived | {prev: Boolean, next: Boolean} | no | old and new archived (if changed) |
Give feedback on this article
Have feedback about this article? Tell us about your experience here.