A workspace becomes much more useful when it can tell other systems what just happened. A new Helpdesk ticket should be able to open an incident workflow. A task assignment should be able to notify an external planning tool. A submitted form should be able to create a lead, update a database, or call a custom automation.

That is why Aamu.app now supports outbound webhooks. A team can register an endpoint URL, choose the events it wants to receive, optionally narrow the webhook to selected projects, and let Aamu send signed HTTP requests when matching workspace activity happens.

The first version is intentionally practical: server-side delivery, signed payloads, visible delivery logs, and event coverage across the parts of Aamu where integrations usually start.

What webhooks are for

An API is useful when another system asks Aamu for data. A webhook is useful when Aamu tells another system about a change.

For example, an integration can listen for helpdesk.ticket.created and immediately start a triage workflow. Another can listen for task.status_changed and update an external reporting dashboard. A third can listen for form.submitted and send the response to a CRM or internal queue.

The important difference is timing. Instead of polling Aamu every few minutes and asking "anything new?", the receiving system gets called when the event happens.

Team-level setup with project filters

Aamu webhooks are configured at the team level. That means the webhook belongs to the workspace team, not to a single browser session or one local client.

Many Aamu events are project-specific, so webhook definitions can also include project filters. If a webhook is limited to one project, it receives only matching events from that project. If it has no project filter, it can receive matching events from across the team.

Some events, such as team member changes, are naturally team-level and do not have a project id. Project filters apply when the event itself has project context.

Events Aamu can send

The current webhook event list covers the main operational objects in Aamu:

  • Helpdesk: tickets, status changes, assignment, comments, email replies, and messages.

  • Tasks: created, updated, status changes, assignment changes, due date changes, and comments.

  • Forms: created, updated, deleted, and submitted.

  • Email: received, sent, and replied.

  • Meetings: created, updated, deleted, and comments.

  • Files: created, updated, deleted, and comments.

  • Projects and teams: project lifecycle events, project member changes, and team member role changes.

  • Docs: created, updated, deleted, and comments.

  • Databases: databases, tables, and rows being created, updated, or deleted.

  • Posts: created, updated, deleted, and comments.

The event names are explicit, such as task.created, helpdesk.ticket.assigned, email.received, meeting.updated, db.row.created, and project.member.added. This makes it easy for the receiving service to route events by type.

What a delivery looks like

When an event matches an enabled webhook, Aamu sends an HTTP POST request to the configured URL. The request body is JSON and includes the event id, event type, creation time, team id, optional project id, actor id, and event-specific data.

{
  "id": "evt_92ac2f69-6dbd-4ced-ac0a-dbc793396571",
  "type": "task.created",
  "createdAt": "2026-06-05T14:47:14.806Z",
  "teamId": "TEAM_ID",
  "projectId": "PROJECT_ID",
  "actorId": "USER_ID",
  "data": {
    "task": {
      "id": "TASK_ID",
      "title": "Follow up with the customer",
      "status": "active"
    }
  }
}

The request also includes headers that help the receiver identify and verify the delivery:

user-agent: Aamu-Webhooks/1.0
x-aamu-delivery-id: whd_c5784f35-59bc-48e7-9017-d4447d9ed631
x-aamu-event-id: evt_92ac2f69-6dbd-4ced-ac0a-dbc793396571
x-aamu-event-type: task.created
x-aamu-signature: t=1780670836831,v1=f3056005aa0deb8d50a96156ed7dcc8a9ed73dda1042466c72a086a5f568a93c

Signed requests

Webhook requests are signed with a shared secret. The receiving service should verify the x-aamu-signature header before trusting the request.

The header contains a timestamp and a versioned HMAC SHA-256 signature. A receiver can rebuild the signed payload from the timestamp and raw request body, calculate the expected HMAC with the webhook secret, and compare it to the v1 value.

This protects the integration from accepting random HTTP requests that merely look like Aamu webhook deliveries.

Logs for both success and failure

Webhook development is much easier when failures are visible. Aamu records webhook events and delivery attempts so the team can see what was sent, where it was sent, whether it succeeded, how long it took, and what error happened when delivery failed.

That visibility matters because webhook failures are often environmental. The URL might be unreachable from the server. A local test server might not be running. The receiver might return a non-2xx status. A signing secret might be missing. Without delivery logs, all of those problems feel the same from the product UI: nothing happened.

With logs, the integration builder can see the difference between "the event was not emitted", "the event was emitted but did not match this webhook", "the delivery failed before sending", and "the receiver returned an error".

Testing with a local endpoint

A simple way to test a webhook is to run a local HTTP server that prints incoming requests and then configure an Aamu webhook to call it. During development, the receiver can log headers and body so the integration author sees the exact payload shape.

--- webhook received ---
POST /webhook
x-aamu-event-type: task.created
x-aamu-delivery-id: whd_...
x-aamu-signature: t=...,v1=...

{
  "id": "evt_...",
  "type": "task.created",
  "teamId": "TEAM_ID",
  "projectId": "PROJECT_ID",
  "data": { "task": { "id": "TASK_ID", "title": "Test task" } }
}

For local machine testing, remember that the Aamu server must be able to reach the URL. If Aamu is running somewhere else, 127.0.0.1 points to that server's own machine, not to the developer's laptop. In that case, use a reachable tunnel or a test endpoint hosted where Aamu can call it.

Example integrations

The first webhook use cases are straightforward but powerful:

  • Create an external incident when an urgent Helpdesk ticket is created.

  • Send task changes to a reporting database or data warehouse.

  • Push form submissions into a CRM or sales workflow.

  • Notify an operations channel when a database row is created or updated.

  • Start a document review workflow when an important Doc changes.

  • Sync project membership changes to an internal access-management process.

Because webhooks carry both team and project context, the receiving service can decide whether to treat the event as a workspace-wide automation, a project-specific workflow, or a customer-specific integration.

How this fits with the Aamu API

Webhooks and the Aamu API work well together. The webhook tells the integration that something changed. The API can then fetch more detail, create follow-up work, update a Doc, write a Helpdesk draft, or send data into another part of Aamu.

A common pattern is:

  1. Receive a webhook event.

  2. Verify the signature.

  3. Use the event type and ids to choose a workflow.

  4. Call the Aamu API if more context or a follow-up action is needed.

  5. Store the delivery id so repeated deliveries can be handled idempotently.

That separation keeps webhook payloads focused while still allowing integrations to do richer work when they need it.

The bottom line

Outbound webhooks make Aamu easier to connect to the rest of a team's tools. Tasks, Helpdesk tickets, email, forms, meetings, files, docs, databases, posts, projects, and team membership can now become real-time integration triggers.

The design is deliberately boring in the best sense: server-side delivery, explicit event names, signed requests, project filtering, and delivery logs. Those are the pieces an integration needs before it can be trusted in everyday work.