Initial commit
This commit is contained in:
Executable
+148
@@ -0,0 +1,148 @@
|
||||
# Overview
|
||||
|
||||
# What is a Webhook?
|
||||
|
||||
A Webhook is a tool for retrieving and storing data from a certain event. They allow you to register an http\:// or https\:// URL where the event data can be received in JSON formats.
|
||||
|
||||
ServiceM8 Webhooks are commonly used for:
|
||||
|
||||
* Receiving scheduling changes
|
||||
* Updating item/material’s price changes in your app
|
||||
* Notifying staff with real-time job changes
|
||||
* Collecting data for data-warehousing
|
||||
* Integrating your accounting software
|
||||
|
||||
Think of it this way, if you would otherwise have to poll for a substantial amount of data, you should be using webhooks.
|
||||
|
||||
> 📘 Note that updates only indicate that a particular field has changed, they do not include the value of the field. When your application receives a webhook update from ServiceM8, you will need to use the [REST API](/documentation/rest-api/overview) to retrieve the record and get the field values.
|
||||
|
||||
# Creating and Updating Subscriptions
|
||||
|
||||
Webhooks are subscribed to by using the Webhooks API endpoint: `https://api.servicem8.com/webhook_subscriptions`
|
||||
|
||||
The basic operations are:
|
||||
|
||||
* Add or modify a subscription.
|
||||
* List each of your existing subscriptions.
|
||||
* Delete subscriptions.
|
||||
|
||||
# Setting Up your Callback URL
|
||||
|
||||
First you’ll need to prepare the page that will act as your callback URL. This URL will need to be accessible by ServiceM8 servers, and be able to receive form-encoded POST data that is sent when an update happens, and in order to verify subscriptions.
|
||||
|
||||
This URL should always return a HTTP 200 response when invoked by ServiceM8.
|
||||
|
||||
# Handling Verification Requests
|
||||
|
||||
> 🚧 Public Applications Only
|
||||
>
|
||||
> Public applications (OAuth 2) must complete a challenge request to subscribe to webhooks.
|
||||
>
|
||||
> Note that API key requests are not required to complete the challenge request process.
|
||||
|
||||
When you add a new subscription, or modify an existing one, ServiceM8 servers will make a HTTP POST request to your callback URL in order to verify the validity of the callback server. The request will include the following POST parameters.
|
||||
|
||||
| Parameter | Value |
|
||||
| :-------- | :--------------- |
|
||||
| mode | subscribe |
|
||||
| challenge | \<random string> |
|
||||
|
||||
When your server receives one of these requests, it needs to render a response to the request that includes only the challenge value. This confirms that this server is configured to accept callbacks, and is used for security verification on ServiceM8’s side.
|
||||
|
||||
Here's a simple example of how to implement the verification step.
|
||||
|
||||
```php
|
||||
<?php
|
||||
|
||||
if ($_REQUEST['mode'] == 'subscribe' && $_REQUEST['challenge']) {
|
||||
echo $_REQUEST['challenge'];
|
||||
} // else: handle webhook POST data
|
||||
```
|
||||
|
||||
# Handling Webhooks
|
||||
|
||||
After your callback URL has been verified, ServiceM8 will send a HTTP POST to that URL each time one of the fields on the subscribed object changes. The data POSTed to your callback URL will be JSON in the following format:
|
||||
|
||||
```
|
||||
{
|
||||
"object": "job",
|
||||
"entry": [{
|
||||
"changed_fields": ["badges","generated_job_id"],
|
||||
"time": "2015-01-01 00:00:00",
|
||||
"uuid": "de305d54-75b4-431b-adb2-eb6b9e546013"
|
||||
}],
|
||||
"resource_url": "https://api.servicem8.com/api_1.0/job/de305d54-75b4-431b-adb2-eb6b9e546013.json"
|
||||
}
|
||||
```
|
||||
|
||||
The **entry** parameter is an array which contains a single object. To read the values you'll need to use code similar to `myValue = entry[0].time`.
|
||||
|
||||
Note that the data POSTed to your callback URL does not contain the object itself — only the UUID and a list of fields that changed. You can request the URL specified by resource\_url to obtain the object itself. The timestamp provided will be in UTC.
|
||||
|
||||
> 📘 Most timestamps in ServiceM8 are in the account's local timezone. Webhooks are different, as they use UTC timestamps.
|
||||
|
||||
## Callback URL Response Codes
|
||||
|
||||
| Code | Title | Description |
|
||||
| :------ | :-------- | :------------------------------------------------------------------------------------------------------------ |
|
||||
| 200 | Success | Webhook has completed successfully |
|
||||
| 410 | Gone | Webhook will be unsubscribed (the same as if you had called the webhook subscription endpoint and removed it) |
|
||||
| 429 | Throttled | Webhook request volume will be gradually throttled for 15 minutes for this account |
|
||||
| 4xx/5xx | Error | Webhook will be retried for up to 72 hours, before automatically being cancelled |
|
||||
|
||||
## Troubleshooting Failed Webhooks
|
||||
|
||||
`GET /webhook_subscriptions` now supports a `status` query parameter so you can inspect deactivated subscriptions as part of debugging.
|
||||
|
||||
* `status=active` returns active subscriptions only. This is the default.
|
||||
* `status=inactive` returns deactivated subscriptions only.
|
||||
* `status=all` returns both active and inactive subscriptions.
|
||||
|
||||
If a webhook has stopped firing, request the inactive subscriptions and inspect the last recorded failure details:
|
||||
|
||||
```http
|
||||
GET /webhook_subscriptions?status=inactive
|
||||
```
|
||||
|
||||
Each returned subscription now includes these troubleshooting fields:
|
||||
|
||||
* `active` indicates whether the subscription is currently active.
|
||||
* `last_failure_reason` contains the most recent failure reason recorded for the subscription, or `null` if none has been recorded.
|
||||
* `last_failure_at` contains the UTC timestamp of the most recent recorded failure, or `null` if none has been recorded.
|
||||
|
||||
Example response:
|
||||
|
||||
```json
|
||||
[
|
||||
{
|
||||
"type": "object",
|
||||
"object": "job",
|
||||
"callback_url": "https://example.com/hooks/JobChanged",
|
||||
"fields": ["uuid", "status"],
|
||||
"unique_id": "integration-a",
|
||||
"active": false,
|
||||
"last_failure_reason": "Webhook request failed for over 12 hours",
|
||||
"last_failure_at": "2026-04-14 03:25:00"
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
Use `status=all` if you want to compare active and inactive subscriptions in the same response. When a subscription is successfully reactivated, its stored failure snapshot is cleared, so inspect the failure details before reactivating if you need them for debugging.
|
||||
|
||||
## How to Use the Webhooks API
|
||||
|
||||
Refer to the [Webhooks API Reference](https://developer.servicem8.com/reference/webhook-subscription) for details of the Webhooks endpoint.
|
||||
|
||||
## Which objects support webhooks?
|
||||
|
||||
The following objects/endpoints support webhooks:
|
||||
|
||||
* Job Activity
|
||||
* Job
|
||||
* Job Payment
|
||||
* Note
|
||||
* Task
|
||||
* Material
|
||||
* Company
|
||||
* Attachment
|
||||
* Form Response
|
||||
Reference in New Issue
Block a user