Webhooks tell your system the moment something changes in Avaza, so it doesn't have to keep asking. For example, subscribe to invoice_sent and Avaza posts to your web page whenever an invoice is sent, or marked as sent.

You manage subscriptions through the API, with a personal access token or an OAuth app. See getting started with the Avaza API.

Before you start

  • Scopes: the token or app needs webhook_notifications, plus the read scope for the records you want to hear about (see the table below). The matching write scope works too.
  • Roles: Administrators can see and manage every subscription in the account. Finance Managers, Portfolio Managers, Project Managers, Project Collaborators and Timesheet/Expense Users can manage their own. Other roles can't use the webhook endpoints.
  • An endpoint: a web address that accepts POST requests. It must be an http or https URL on a public address, not a local or private network. Use https.

Subscribe to an event

Post the event and your address to https://api.avaza.com/api/Webhook. Each subscription covers one event, so subscribe once per event.

curl -X POST https://api.avaza.com/api/Webhook \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"target_url": "https://yourapp.example.com/avaza-webhook", "event": "timesheet_created", "secret": "YOUR_WEBHOOK_SECRET"}'

secret is optional, up to 255 characters (see below). Avaza answers 201 with the new subscription's ID, for example {"ID": 10}. If the same app already has that event on that address, you get 409 instead.

Events

Records

Events

Scope

Companies (customers)

company_created, company_updated, company_deleted

read_contacts

Contacts

contact_created, contact_updated, contact_deleted

read_contacts

Team members

team_member_created, team_member_updated, team_member_deleted

read_users

Projects

project_created, project_updated, project_deleted

read_projects

Tasks

task_created, task_updated, task_deleted

read_projects

Timesheets

timesheet_created, timesheet_updated, timesheet_deleted

read_timesheets

Expenses

expense_created, expense_updated, expense_deleted

read_expenses

Schedule bookings

scheduleseries_created, scheduleseries_updated, scheduleseries_deleted

read_schedule

Invoices

invoice_created, invoice_updated, invoice_sent, invoice_deleted

read_financials

Estimates

estimate_created, estimate_updated, estimate_deleted

read_financials

Bills

bill_created, bill_updated

read_financials

To ask for another event, contact Avaza support.

You only receive notifications about records your user can see. Administrators receive everything. A Timesheet/Expense User only hears about their own timesheets and expenses. Team member events go to Administrators only, and invoice, estimate and bill events to Administrators and Finance Managers.

Changes made in the Avaza web app and through the Avaza MCP Server send webhooks. Changes you make through the API only send them if the request includes "SendWebhooks": true, so your integration doesn't hear its own changes back.

Handle a notification

Avaza posts a JSON array with one item: a snapshot of the record at the moment of the event, plus four fields that identify the notification. Here is a timesheet_created notification:

[
  {
    "TimeSheetEntryID": 18528,
    "Duration": 4.0,
    "EntryDate": "2026-09-14T00:00:00Z",
    "UserIDFK": 93,
    "ProjectIDFK": 137,
    "TimeSheetCategoryIDFK": 21,
    "Notes": "Drafted the launch email",
    "TimeSheetEntryApprovalStatusCode": "Draft",
    "isBillable": true,
    "isInvoiced": false,
    "DateCreated": "2026-09-14T05:25:36Z",
    "DateUpdated": "2026-09-14T05:25:36Z",
    "WebhookNotificationItemID": 552301,
    "SubscriptionID": 10,
    "EventCode": "timesheet_created",
    "AccountID": 4521
  }
]

Each event has its own fields. The _deleted events carry only the IDs, because the record is gone. To see the exact format of an event, point a test subscription at a free service such as Webhook.site.

  • Answer with a 2xx status, such as 200, as soon as you've stored the notification. Do the slow work afterwards.
  • Check the secret. If you set one, every notification has the header Authorization: Basic followed by your secret in Base64. Reject posts without it.
  • Answer 410 Gone to unsubscribe. Avaza then deletes that subscription.

Retries

If your endpoint doesn't answer with a 2xx status, Avaza tries again with growing gaps: after about 10 minutes, then 30 minutes, 90 minutes, 190 minutes and so on. Retries go out every 15 minutes, so each gap can be up to 15 minutes longer. After 14 retries, about 11 days, Avaza drops the notification.

A retry sends the same snapshot with the same WebhookNotificationItemID, so use that ID to skip duplicates. The snapshot shows the record as it was when the event happened, not as it is now.

List and delete subscriptions

Call

What it does

GET /api/Webhook

Lists subscriptions: every one in the account for Administrators, your own for everyone else

GET /api/Webhook/{id}

Gets one subscription

DELETE /api/Webhook/{id}

Deletes a subscription by its ID

DELETE /api/Webhook?target_url=...

Deletes the subscriptions for an address

You can only delete subscriptions that were created with the same app or personal access token, and only your own unless you're an Administrator. A delete answers 200 even if nothing matched, so list the subscriptions afterwards to check.