Benefits of Measure Boost Webhooks
Measure Boost Webhooks is a service developed by RFMS Australasia which sits between RFMS Measure (Desktop and Mobile) and customer-developed integrations.
Measure Desktop provides a plug-in interface allowing third-parties to create a .DLL file with custom code to integrate with outside systems. Measure Mobile now provides something similar. However, there are significant technical obsticals to implementing an integration using these features:
Measure Desktop provides a plug-in interface allowing third-parties to create a .DLL file with custom code to integrate with outside systems. Measure Mobile now provides something similar. However, there are significant technical obsticals to implementing an integration using these features:
- The object structures and calls for Desktop and Mobile are very different
- Building a .DLL that can be loaded by Desktop requires a very different skill set than creating an API service
- The interfaces to the two applications are quirky and require considerable effort to get working reliably
- Units of measure (metric vs U.S.) are handled automatically and consistently
Measure Boost Webhooks resolves these issues by providing one consistent, modern interface that seamless works with both applications.
How it works
When you sign up for Measure Boost, three important bits of information will be exchanged:
- You will be given a unique API ID which you will enter in your Measure Desktop plug-in and Measure Mobile configuration to identify your users as yours.
- You will provide a callback URL for your implementation. Webhooks will be sent to this endpoint in real-time to serve requests made by your users.
- You will be given a shared secret which you can use to authenticate webhooks to ensure they are legitimate
When one of your users makes a supported request in Measure Desktop or Measure Mobile, your endpoint will be called to provide or accept the information.
See it in action
Webhook format
Sample Implementation
To make it easier to get started, we have created a sample webhook endpoint which you can use as a starting point or technical reference to guide your implementation. It provides all the code needed to respond to Measure Boost webhooks -- all that remains is your custom integration with your data.
To make it easier to get started, we have created a sample webhook endpoint which you can use as a starting point or technical reference to guide your implementation. It provides all the code needed to respond to Measure Boost webhooks -- all that remains is your custom integration with your data.
Endpoint
You will provide a root endpoint for your API implementation, it will look something like this:
https://www.mycompany.com/api/boost
The naming is not important, only that it can accept a HTTP POST in the format described below:
Headers
All messages will include these headers:
Headers
All messages will include these headers:
Content-Type: application/json X-Event-Type: <event.type - see below> X-Signature: sha256=<signature> X-Request-ID: <unique-id-for-tracing>
Verification
All webhook requests include an X-Signature header containing an HMAC-SHA256 signature for request verification. This signature proves the request originated from Measure Boost and hasn't been tampered with. To verify:
All webhook requests include an X-Signature header containing an HMAC-SHA256 signature for request verification. This signature proves the request originated from Measure Boost and hasn't been tampered with. To verify:
- Extract the signature from the X-Signature header (remove the sha256= prefix)
- Compute your own HMAC-SHA256 signature using:
- Key: Your shared secret
- Message: The raw request body (as received, unmodified)
- Algorithm: HMAC-SHA256
- Compare your computed signature with the received signature using a secure comparison method
Important Notes
- Use the raw request body - parsing and re-serializing will break verification
- Always use secure comparison methods to prevent timing attacks
- Signature verification is strongly recommended but optional
Errors and Retries
When a webhook is sent the user in Measure is waiting for a response in realtime. As a result, if if your webhook URL is unreachable or does not respond within 20 seconds, an error will be shown to the user and webhook will not be retried.
Event Types
The expected HTTP POST body and return value depends on the value in the X-Event-Type header. Each possible value is documented below:
verify
Simple method with no parameters to verify the connection is working. Your system can return a descriptive message to indicate connection details or issues.
Payload
None
Return value
Payload
None
Return value
{
"isSuccess": true,
"message": "ok"
}customer.search
Measure user is searching for a customer. Receives a JSON object in this form. This is the text the user is looking for in your customer database:
Payload
Payload
{
"searchString": "smith"
}Return value
JSON list of zero or more Customer objects. The Customer object structure can contain these elements:
[
{
"id": 113,
"source": "Customer",
"jobNumber": "HD-99202",
"soldTo": {
"firstName": "Noah",
"lastName": "Johnson",
"businessName": "Johnson Electrics",
"addressLine1": "87 Rundle Mall",
"addressLine2": "",
"city": "Adelaide",
"state": "SA",
"postalCode": "5000"
},
"shipTo": {
"firstName": "",
"lastName": "",
"businessName": "Johnson Electrics",
"addressLine1": "44 King William Street",
"addressLine2": "",
"city": "Mount Gambier",
"state": "SA",
"postalCode": "5290"
},
"phoneNumbers": [
"+61 8 8123 4567", "+61 8 8123 4569"
],
"emailAddresses": [
"noah.johnson@johnsonelectrics.au"
],
"salespeople": [
"Emily White"
]
}
]- id - Must uniquely identify this customer in your database.
- source - This value can be anything you like and will be returned to you if the customer is updated and when the worksheet is sent. It can allow you to distinguish between multiple customer sources. Just use "Customer" if this is not needed in your solution.
- jobNumber - An arbitrary alphanumeric string that will flow through the system and be included in the export data.
- soldTo/ShipTo - These are address blocks with the same elements. SoldTo is sometimes called Customer Address and ShipTo is sometimes called Job Address in Measure.
- businessName - Measure Desktop does not support a business name and first/last name at the same time. If businessName is provided, it will take precedence over firstName/lastName.
- phoneNumbers - An array of zero to three phone numbers -- these will translate to Customer phone 1, Customer phone 2, and Job phone, in that order. Any beyond 3 will be ignored.
- emailAddresses - An array of zero to two email addresses -- these will translate to Customer email and Job email, in that order. Any beyond 2 will be ignored.
- salespeople - An array of zero to two salespeople.
product.search
Payload
{
"searchString": "blue",
"isSKU": false,
"limitToProductType": ""
}- searchString - the text the user entered into the search box
- isSKU - Measure Mobile has a search by SKU feature -- this flag will be set to true when that search is being used.
- limitToProductType - The search dialog allows limiting the search to only products of a certain type. When this is in use, the product type will be included here - otherwise it will be an empty string.
Return value
Zero or more products:
Zero or more products:
[
{
"Id": "PRD-0002",
"ProductType": "RollCarpet",
"MeasurementsAreInches": false,
"StyleName": "Venetian Dreams",
"StyleNumber": "VP-2024-002",
"Supplier": "Premium Floor Coverings Inc",
"LabelWidthMeasurement": 3.0,
"UsableWidthMeasurement": 3.0,
"PatternWidthMeasurement": 1.0,
"PatternLengthMeasurement": 1.0,
"PatternDropPercent": 0.5,
"MaximumTSeams": 0,
"CutSquare": false,
"CutGapMeasurement": 0.5,
"CutGapMethod": 1,
"AllowTileRotation": false,
"ExtraWasteAmount": 5.0,
"ExtraWasteType": 2,
"UseAsAddonOnly": false,
"UnitPrice": 99.99,
"UnitCost": 45.50,
"SaleUnits": "SM",
"IsTaxable": true,
"QuantityPerBox": 0.0,
"ProductColorOptions": [
{
"Id": 18934,
"ColorName": "Golden Glory",
"ColorNumber": "WB-011",
"SKU": "VP-2024-002-WB"
},
{
"Id": 23442,
"ColorName": "April Showers",
"ColorNumber": "SG-012",
"SKU": "VP-2024-002-SG"
}
]
}
]Basic Description
- Id - Unique alphanumeric identifier
-
ProductType - Controls how the product will be estimated and where it will be filed in the product list. Valid options are:
- Roll allocation: RollCarpet, RollVinyl, RollWallpaper
- Tile allocation: TileCeramic, TileLaminate, TileWood, TileOther
- Planks: PlankLaminate, PlankWood
- Labor: ItemService
- Items: ItemMisc
- MeasurementsAreInches - Several elements contain the word "Measurement" - this flag controls how those elements should be understood. If true, these should be expressed in inches, otherwise in metres.
- SaleUnits - Valid options are SY, SF, SM, LY, LF, LM, EA
Roll Products
These all correspond with product attributes in Measure. See the Measure documentation for more information.
These all correspond with product attributes in Measure. See the Measure documentation for more information.
- LabelWidthMeasurement - is the advertised width of a roll product
- UsableWidthMeasurement - is the width that can actually be used for allocation - sometimes the usable width is less than the label width because of a ragged edge
- PatternWidthMeasurement, PatternLengthMeasurement - Optional, but if present describes the repeating pattern
- PatternDropPercent - If the pattern is offset, the offset should be specified here -- must be one of these values: 0, 0.5, 0.333334, 0.25, 0.125.
- MaximumTSeams - Maximum number of t-seams allowed
-
CutGapMethod - Must be one of three values:
- 0 = Guillotine, 1 = Length, 2 = All sides
-
ExtraWasteAmount - Value depends on ExtraWasteType:
- ExtraWasteType = 0, ExtraWasteAmount = Waste percentage (0.1 = 10%)
- ExtraWasteType = 1, ExtraWasteAmount = Quantity in SaleUnits to add
- ExtraWasteType = 2, ExtraWasteAmount = Waste length to be added (in the units specified by MeasurementsAreInches)
Tile Products
- PatternWidthMeasurement, PatternLengthMeasurement - define the size of the tile
product.get
Accepts one or more product Id values:
[ "PRD-0002", "PRD-0011" ]
Returns
Same values as product.search above.
estimate.save
The user has exported a project worksheet. The payload looks like this:
{
"project": {
"id": "8a78c2a5-86b9-443b-8fec-527360a0d3d1",
"title": "Johnson, Noah",
"status": "Draft",
"quoteNumber": ""
},
"customer": {
"id": 113,
"source": "Customer",
"jobNumber": "M23-218",
"soldTo": {
"firstName": "Noah",
"lastName": "Johnson",
"businessName": "Johnson Electrics",
"addressLine1": "87 Rundle Mall",
"addressLine2": "",
"city": "Adelaide",
"state": "SA",
"postalCode": "5000"
},
"shipTo": {
"firstName": "Noah",
"lastName": "Johnson",
"businessName": "Johnson Electrics",
"addressLine1": "87 Rundle Mall",
"addressLine2": "",
"city": "Adelaide",
"state": "SA",
"postalCode": "5000"
},
"phoneNumbers": [
"+61 8 8123 4567"
],
"emailAddresses": [
"noah.johnson@johnsonelectrics.au"
]
},
"lines": [
{
"product": {
"id": "PRD-0004",
"productType": "TileCeramic",
"styleName": "Joyful Times",
"styleNumber": "TS-2023-010",
"colorName": "Foster",
"colorNumber": "WS-111",
"supplier": "Premium Floor Coverings Inc."
},
"quantity": 30,
"saleUnits": "SM",
"unitPrice": 22.99,
"unitCost": 10.5,
"lineTotal": 689.7,
"taxAmount": 68.97,
"isFixedTotal": false,
"hidden": false,
"notes": "",
"internalNotes": ""
},
{
"product": {
"id": "PRD-0005",
"productType": "ItemService",
"styleName": "Installation Fee",
"styleNumber": "INSTALL-1",
"colorName": "",
"colorNumber": "",
"supplier": ""
},
"quantity": 5,
"saleUnits": "SM",
"unitPrice": 19.99,
"unitCost": 0,
"lineTotal": 99.95,
"taxAmount": 9.99,
"isFixedTotal": false,
"hidden": false,
"notes": "",
"internalNotes": ""
}
],
"attachments": [
{
"title": "Project",
"attachmentType": "Photo",
"downloadUrl": "https://measuredata1.blob.core.windows.net/photos/e87648a2-c429-4e93-98b5-bbe62d5f2a66/95e2c632-841f-4a02-a010-61b3067c02ae?sv=2014-02-14&sr=b&sig=8RyUyTsOwWM38oOsUku8kpvKd0fn6uvaW2Uhz%2FXkhi8%3D&st=2025-08-14T17%3A23%3A06Z&se=2025-08-14T17%3A38%3A06Z&sp=r",
"lineNumber": 0
},
{
"title": "Room: 1",
"attachmentType": "Photo",
"downloadUrl": "https://measuredata1.blob.core.windows.net/photos/e87648a2-c429-4e93-98b5-bbe62d5f2a66/bcdf313d-8633-4793-9528-e9165a326418?sv=2014-02-14&sr=b&sig=9tf7Aif079PUijxu20gG8IwfEdTnJWTtJzs6ZkOza8Y%3D&st=2025-08-14T17%3A23%3A06Z&se=2025-08-14T17%3A38%3A06Z&sp=r",
"lineNumber": 1
},
{
"title": "export_roomplan.jpg",
"downloadUrl": "https://devboostapidata.blob.core.windows.net/desktop-upload-attachments/8822385/c5b560b9c3f446ddb21bf47b459b9d77?skoid=c1c79724-87b7-4839-a2d6-137b0db4784d&sktid=96469d96-59b4-43f1-9385-6eee51187335&skt=2026-02-02T18%3A51%3A27Z&ske=2026-02-02T19%3A06%3A27Z&sks=b&skv=2025-07-05&sv=2025-07-05&se=2026-02-02T19%3A06%3A27Z&sr=b&sp=r&sig=GqxBjbbs%2F%2F1OJogzKh4RujqWw6kREFR4s9h8zquzfyA%3D",
"lineNumber": 0,
"attachmentType": "RoomPlan"
}
]
}Return value
{
"isSuccess": true,
"estimateId": "Q123456",
"message": "ok"
}Notes
- The url provided to download attached photos will only be valid for 10 minutes
- Photos attached but not yet synch'd to the cloud in Measure Mobile will not be included
- You can return an "estimateId" which will be assigned to the Measure Mobile project as quote number. Desktop does not support this.
Comments
0 comments
Please sign in to leave a comment.