Webhook Documentation
For CRM As A Service
Welcome to the Webhook Documentation for CRM as a Service! This comprehensive developer's guide is your key to seamlessly integrating CRM functionality into your applications.


What is Webhook?
Webhooks are one of the most powerful automation tools available today. Think of them as real-time notifications that allow CRM As A Service to instantly "push" information to other applications your team uses
When a specific event happens in your CRM (like a new Lead is created or a Quotation is marked "Accepted"), a Webhook automatically sends that data to a unique URL, allowing you to trigger actions in external systems like marketing platforms, data dashboards, or custom databases.
Configuring the Webhook in the CRM
Your first step is to tell CRM as a Service where and when to send data.
-
Navigate to the Webhooks Menu: In the CRM app, go to Settings > Automations > Webhooks. Click + Webhook.
-
Configure Your Endpoint: An "Add New Webhook" pop-up will appear. As a developer, here is what these fields mean for your implementation:

-
Webhook name: A clear, descriptive name for your reference.
-
Event entity: The CRM record you want to monitor (e.g., "Lead," "Opportunity").
-
Event action: The specific action that triggers the Webhook (e.g., "Create," "Update").
-
URL: This is your server's public endpoint. CRM as a Service will send a POST request to this HTTPS URL.
-
Secret key: This is your shared secret. You must create and securely store this complex key (e.g., in your server's environment variables). It is used to validate that the request is authentic.
Click Save. Your Webhook is now active and will begin sending payloads when the specified events occur.
Validating Data is Sent and Received
Once your Webhook is active, you can monitor its health directly from the Webhook list view in CRM as a Service. The Response code column is your primary indicator of success or failure.
Successful Delivery
When your endpoint receives the request and acknowledges it correctly, the CRM will display a green status box.

The green 201 box under "Response code" confirms that the connection works perfectly. It is proof that the data didn't just hit the server, but was accepted and processed correctly.
Failed Delivery(No Response)

If the Webhook fails to reach your server (e.g., DNS issues, server timeout, or incorrect URL), the system will not receive an acknowledgement
Validating the X-Crm-Signature-256 (Security)
This is the most critical step. Do not trust the payload until you validate its signature. This process confirms the request came from your CRM and was not altered. The signature is an HMAC SHA256 digest, computed using your Secret key and the raw request body.
Here is a general implementation example using C+/ TypeScript:
TypeScript:
function validateHmac(secretKey: string, data: any, receivedHmac: string) {
// Compute the HMAC using the secret key and SHA256
const computedHmac = crypto
.createHmac('sha256', secretKey)
.update(data)
.digest('hex');
// Securely compare the received HMAC with the computed one
return crypto.timingSafeEqual(
Buffer.from(receivedHmac, 'hex'),
Buffer.from(computedHmac, 'hex')
);
}
C+:
public static bool ValidateHmac(string secretKey, string data, string receivedHmac)
{
// Convert the secret key and message to byte arrays
var keyBytes = Encoding.UTF8.GetBytes(secretKey);
var dataBytes = Encoding.UTF8.GetBytes(data);
// Compute the HMAC using SHA256
using (var hmac = new HMACSHA256(keyBytes))
{
var computedHmacBytes = hmac.ComputeHash(dataBytes);
var computedHmac = BitConverter.ToString(computedHmacBytes).Replace("-", "").ToLower();
// Securely compare the received HMAC with the computed one
return CryptographicOperations.FixedTimeEquals(
Encoding.UTF8.GetBytes(receivedHmac),
Encoding.UTF8.GetBytes(computedHmac)
);
}
}
```
Payload Field Definitions
The JSON payload provides a clear, structured log of the event. Here is the definition of each field you will receive:
Field | Type | Description |
|---|---|---|
id | string | The unique identifier of this delivery event. |
event | string | The event type (for example, ticket.created or alert.sla_rt_breached). |
timestamp | string | The time the event occurred, formatted as an ISO 8601 date string. |
version | string | The payload schema version (current: v1). |
tenantId | string | The unique identifier of the Microsoft 365 tenant. |
instanceId | string | The unique identifier of the Ticketing instance. |
data | object | Event-specific data. Always contains ticket, ticketUrl, and user. May also contain changes, status, comment, attachment, or alert depending on the event type. |
data.ticket | object | The current ticket entity, following the Ticketing GET /tickets/{ticketId} resource shape. |
data.ticketUrl | string | A reference to the ticket entity endpoint: /tickets/{ticket-guid}. |
data.user | object | The user who triggered the event. |
data.changes | array | Present on ticket.updated, ticket.assigned, and ticket.status_changed. Lists only the fields that changed, each with field, from, and to. |
data.status | object | Present on ticket.status_changed and ticket.resolved. Contains from, to, targetId, transitionLabel, and resolution when applicable. |
data.comment | object | Present on comment.created. Contains comment id, isPrivate, and source. |
data.attachment | object | Present on attachment events. Contains attachment metadata only. File content is not included. |
data.alert | object | Present on alert events. Contains alert-specific metadata relevant to the event type. |
Receiving the Payload
The CRM will send a POST request with the following:
-
Headers: The most important header is X-Crm-Signature-256. This contains the HMAC signature.
-
Body: A JSON payload containing the event data.
Example Responses
The following samples shows a real webhook request as displayed using Postman. You can use this example to understand the structure of the HTTP headers and body your endpoint will receive.
1.) CREATE Response:
Description: When a new item is create, itemAfter will contain the full object of the newly created item. This example demonstrates the creation of a new Opportunity.
Example Header:
host: "your-own-domain"
...
x-crm-signature-256: "56a112c124f0e63xxxxxxxxxxxxxxxxxxx97c587abf92aa2bb"
...
Example Body:
Body: { "action": "CREATE", "entity": "Leads", "itemId": "220", "createdOn": "2025-11-10T04:19:11.637Z", "creator": { "id": "xxxxx-xxxx-xxxx-xxxxxxx-xxxx", "name": "Alex Wilber", "email": "AlexW@M365.OnMicrosoft.com" }, "tenantId": "xxxxx-xxxx-xxxx-xxxxxxx-xxxx", "itemAfter": { "id": "220", "title": "Creating a new Lead", "_value": { "code": "USD", "amount": 0 }, "origin": "", "leadRating": "", "note": "", "createdOn": "2025-11-10T04:19:11.541Z", "updatedOn": "2025-11-10T04:19:11.541Z", "archivedOn": "", "convertedOn": "", "lastActivityClosedOn": "2025-11-10T04:19:11.541Z", "owner": { "id": "xxxxx-xxxx-xxxx-xxxxxxx-xxxx", "name": "Alex Wilber", "email": "AlexW@M365.OnMicrosoft.com" }, "creator": { "id": "xxxxx-xxxx-xxxx-xxxxxxx-xxxx", "name": "Alex Wilber", "email": "AlexW@M365.OnMicrosoft.com" }, "lastUpdatedBy": { "id": "exxxxx-xxxx-xxxx-xxxxxxx-xxxx", "name": "Alex Wilber", "email": "AlexW@M365.OnMicrosoft.com" }, "organization": { "id": "132", "name": "Test" }, "contact": {}, "tenantId": "xxxxx-xxxx-xxxx-xxxxxxx-xxxx", "isArchived": false, "isConverted": false, "formVersion": 20, "customFields": { "e5f1f1b6-19bc-45e2-bf06-febf5b88b110": "", "27ca3541-4a49-4f7a-af6a-071e76647340": [ "3ad8be38-949b-4990-98fb-e2250526a362" ], "992f665c-33a4-490e-bfe5-9df470052935": "", "2da764f6-0451-47fe-aa56-e62f0c0fc60c": "", "39617cb2-8db9-4d65-b848-ed35d8035233": "", "159d382c-3107-43e1-b1ed-4eed3747bc3e": [], "f6978a73-3393-4c30-99be-998f96ae5c00": "", "0634edda-a068-4bc2-ada0-58fdf41137f9": [ "e0e1539d-4329-407a-9f36-a3da9b9863b2" ] }, "customFieldsDropdownIndex": { "e5f1f1b6-19bc-45e2-bf06-febf5b88b110": "", "27ca3541-4a49-4f7a-af6a-071e76647340": 0, "2da764f6-0451-47fe-aa56-e62f0c0fc60c": "", "f6978a73-3393-4c30-99be-998f96ae5c00": "", "0634edda-a068-4bc2-ada0-58fdf41137f9": 0 }, "_rid": "spk+AKg6jLpVVQAAAAAAAA==", "_self": "dbs/spk+AA==/colls/spk+AKg6jLo=/docs/spk+AKg6jLpVVQAAAAAAAA==/", "_etag": "\"22000bfc-0000-0700-0000-691167bf0000\"", "_attachments": "attachments/", "_ts": 1762748351 } }
2.) UPDATE Response:
Description: When an item is updated, itemBefore will contain the item's state before the change, and itemAfter will contain the state after the change.
Example Header:
host: "your-own-domain"
...
x-crm-signature-256: "5cb673081382xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxa673"
...
Example Body:
Body: { "action": "UPDATE", "entity": "Cases", "itemId": "1", "createdOn": "2025-11-10T07:21:43.207Z", "creator": { "id": "xxxxxxx-xxxx-xxxx-xxxxxxxxx", "name": "Alex Wilber", "email": "AlexW@M365.OnMicrosoft.com" }, "tenantId": "xxxxxxx-xxxx-xxxx-xxxxxxxxx", "itemBefore": { "id": "1", "status": "Open", "title": "Test Case", "description": "", "caseTypeId": "1", "organization": { "id": "105", "name": "Test Inc" }, "contact": { "id": "107", "name": "Test Person" }, "priority": "", "expectedDate": "2025-09-17", "createdOn": "2025-09-17T02:05:53.399Z", "updatedOn": "2025-10-28T06:16:47.833Z", "owner": { "id": "xxxxxxx-xxxx-xxxx-xxxxxxxxx", "name": "Allan Deyoung", "email": "AllanD@M365.OnMicrosoft.com" }, "creator": { "id": "xxxxxxx-xxxx-xxxx-xxxxxxxxx", "name": "Allan Deyoung", "email": "AllanD@M365.OnMicrosoft.com" }, "lastUpdatedBy": { "id": "xxxxxxx-xxxx-xxxx-xxxxxxxxx", "name": "Alex Wilber", "email": "AlexW@M365.OnMicrosoft.com" }, "tenantId": "xxxxxxx-xxxx-xxxx-xxxxxxxxx", "customFields": {}, "customFieldsDropdownIndex": { "priority": "" }, "version": 1, "workflow": [ { "id": "Open", "label": "Open", "nextSteps": [ { "targetId": "Closed", "transitionLabel": "Close", "recordComment": false }, { "targetId": "In Progress", "transitionLabel": "Start", "recordComment": false }, { "targetId": "Closed", "transitionLabel": "Cancel", "recordComment": true }, { "targetId": "Resolved", "transitionLabel": "Resolve", "recordComment": true } ] }, { "id": "In Progress", "label": "In Progress", "nextSteps": [ { "targetId": "Resolved", "transitionLabel": "Resolve", "recordComment": true }, { "targetId": "Closed", "transitionLabel": "Close", "recordComment": true } ] }, { "id": "Resolved", "label": "Resolved", "nextSteps": [ { "targetId": "Closed", "transitionLabel": "Close", "recordComment": true }, { "targetId": "Reopened", "transitionLabel": "Reopen", "recordComment": true } ] }, { "id": "Closed", "label": "Closed", "nextSteps": [ { "targetId": "Reopened", "transitionLabel": "Reopen", "recordComment": true } ] }, { "id": "Reopened", "label": "Reopened", "nextSteps": [ { "targetId": "Closed", "transitionLabel": "Close", "recordComment": true }, { "targetId": "Resolved", "transitionLabel": "Resolve", "recordComment": true } ] } ], "_rid": "eSACAJw+l13WAAAAAAAAAA==", "_self": "dbs/eSACAA==/colls/eSACAJw+l10=/docs/eSACAJw+l13WAAAAAAAAAA==/", "_etag": "\"2a00a6d3-0000-0700-0000-69005fd20000\"", "_attachments": "attachments/", "_ts": 1761632210 }, "itemAfter": { "id": "1", "status": "Open", "title": "Test Case", "description": "Testing Description", "caseTypeId": "1", "organization": { "id": "105", "name": "Test Inc" }, "contact": { "id": "107", "name": "Test Person" }, "priority": "", "expectedDate": "2025-09-17", "createdOn": "2025-09-17T02:05:53.399Z", "updatedOn": "2025-11-10T07:21:43.173Z", "owner": { "id": "xxxxxxx-xxxx-xxxx-xxxxxxxxx", "name": "Allan Deyoung", "email": "AllanD@M365.OnMicrosoft.com" }, "creator": { "id": "xxxxxxx-xxxx-xxxx-xxxxxxxxx", "name": "Allan Deyoung", "email": "AllanD@M365.OnMicrosoft.com" }, "lastUpdatedBy": { "id": "xxxxxxx-xxxx-xxxx-xxxxxxxxx", "name": "Alex Wilber", "email": "AlexW@M365.OnMicrosoft.com" }, "tenantId": "xxxxxxx-xxxx-xxxx-xxxxxxxxx", "customFields": {}, "customFieldsDropdownIndex": { "priority": "" }, "version": 2, "workflow": [ { "id": "Open", "label": "Open", "nextSteps": [ { "targetId": "Closed", "transitionLabel": "Close", "recordComment": false }, { "targetId": "In Progress", "transitionLabel": "Start", "recordComment": false }, { "targetId": "Closed", "transitionLabel": "Cancel", "recordComment": true }, { "targetId": "Resolved", "transitionLabel": "Resolve", "recordComment": true } ] }, { "id": "In Progress", "label": "In Progress", "nextSteps": [ { "targetId": "Resolved", "transitionLabel": "Resolve", "recordComment": true }, { "targetId": "Closed", "transitionLabel": "Close", "recordComment": true } ] }, { "id": "Resolved", "label": "Resolved", "nextSteps": [ { "targetId": "Closed", "transitionLabel": "Close", "recordComment": true }, { "targetId": "Reopened", "transitionLabel": "Reopen", "recordComment": true } ] }, { "id": "Closed", "label": "Closed", "nextSteps": [ { "targetId": "Reopened", "transitionLabel": "Reopen", "recordComment": true } ] }, { "id": "Reopened", "label": "Reopened", "nextSteps": [ { "targetId": "Closed", "transitionLabel": "Close", "recordComment": true }, { "targetId": "Resolved", "transitionLabel": "Resolve", "recordComment": true } ] } ], "_rid": "eSACAJw+l13WAAAAAAAAAA==", "_self": "dbs/eSACAA==/colls/eSACAJw+l10=/docs/eSACAJw+l13WAAAAAAAAAA==/", "_etag": "\"d600afbd-0000-0700-0000-691192870000\"", "_attachments": "attachments/", "_ts": 1762759303 } }
3.) DELETE Response
Description: When an item is deleted, itemBefore will contain the full object of the item before it was deleted, and itemAfter will be null.
Example Header:
host: "your-own-domain"
...
x-crm-signature-256: "71725cd91133bxxxxxxxxxxxxxxxxxxxxx514ad102b17ebcf553ccde"
...
Example
Body: { "action": "DELETE", "entity": "Cases", "itemId": "1", "createdOn": "2025-11-10T07:59:54.326Z", "creator": { "id": "xxxxxxx-xxxx-xxxx-xxxxxxxx", "name": "Alex Wilber", "email": "AlexW@M365.OnMicrosoft.com" }, "tenantId": "xxxxxxx-xxxx-xxxx-xxxxxxxx", "itemBefore": { "id": "1", "status": "Open", "title": "Test Case", "description": "Testing Description", "caseTypeId": "1", "organization": { "id": "105", "name": "Test Inc" }, "contact": { "id": "107", "name": "Test Person" }, "priority": "", "expectedDate": "2025-09-17", "createdOn": "2025-09-17T02:05:53.399Z", "updatedOn": "2025-11-10T07:21:43.173Z", "owner": { "id": "xxxxxxx-xxxx-xxxx-xxxxxxxx", "name": "Allan Deyoung", "email": "AllanD@M365x.OnMicrosoft.com" }, "creator": { "id": "xxxxxxx-xxxx-xxxx-xxxxxxxx", "name": "Allan Deyoung", "email": "AllanD@M365x.OnMicrosoft.com" }, "lastUpdatedBy": { "id": "xxxxxxx-xxxx-xxxx-xxxxxxxx", "name": "Alex Wilber", "email": "AlexW@M365.OnMicrosoft.com" }, "tenantId": "xxxxxxx-xxxx-xxxx-xxxxxxxx", "customFields": {}, "customFieldsDropdownIndex": { "priority": "" }, "version": 2, "workflow": [ { "id": "Open", "label": "Open", "nextSteps": [ { "targetId": "Closed", "transitionLabel": "Close", "recordComment": false }, { "targetId": "In Progress", "transitionLabel": "Start", "recordComment": false }, { "targetId": "Closed", "transitionLabel": "Cancel", "recordComment": true }, { "targetId": "Resolved", "transitionLabel": "Resolve", "recordComment": true } ] }, { "id": "In Progress", "label": "In Progress", "nextSteps": [ { "targetId": "Resolved", "transitionLabel": "Resolve", "recordComment": true }, { "targetId": "Closed", "transitionLabel": "Close", "recordComment": true } ] }, { "id": "Resolved", "label": "Resolved", "nextSteps": [ { "targetId": "Closed", "transitionLabel": "Close", "recordComment": true }, { "targetId": "Reopened", "transitionLabel": "Reopen", "recordComment": true } ] }, { "id": "Closed", "label": "Closed", "nextSteps": [ { "targetId": "Reopened", "transitionLabel": "Reopen", "recordComment": true } ] }, { "id": "Reopened", "label": "Reopened", "nextSteps": [ { "targetId": "Closed", "transitionLabel": "Close", "recordComment": true }, { "targetId": "Resolved", "transitionLabel": "Resolve", "recordComment": true } ] } ], "_rid": "eSACAJw+l13WAAAAAAAAAA==", "_self": "dbs/eSACAA==/colls/eSACAJw+l10=/docs/eSACAJw+l13WAAAAAAAAAA==/", "_etag": "\"d600afbd-0000-0700-0000-691192870000\"", "_attachments": "attachments/", "_ts": 1762759303 } }