Hoowla can make a HTTP POST request to a url provided when certain events occur. These events include when quotes are raised and when they are instructed. As well as actions run within Hoowla cases.
Once an action is performed you can expect to received the webhook within a minute, all being well.
When sending the webhook it will be marked as successful if a response code between 200-299
is received. Also, if the response back is returned as 406
it will be marked as not acceptable and rejected.
There is a timeout on the http request of 20 seconds, so a response over this time will be considered to have a status code of 0 (and be retried).
Anything other than the situations above and the webhook will be retried as follows:
Listed below are all the fields sent in the webhook request, sent as application/x-www-form-urlencoded
.
Name | Type | Desc |
---|---|---|
timestamp | int | the current unix timestamp in utc (number of seconds since 01/01/1970) generated when sending a request. |
signature | string | the request signature used to verify authenticity in hexadecimal HMAC form and generated by the SHA256 algorithm. |
id | string | a unique id for this payload, so subsequent attempts after failure will have same id. It's not tied to the quote, but to the event. |
type | string |
the type of hook:
|
payload | string | a json string holding the relevant data, more info shown below. |
Along with the body, HTTP Headers will be included:
To verify that the message originated from Hoowla you will need to:
timestamp
and the payload
stringsignature
field sent across and check it's not an old requestExample PHP Code:
<?php
// Step 1 & 2: Concatinate and Generate Hash
$both = $_POST['timestamp'] . $_POST['payload'];
$gen = hash_hmac('sha256', $both, '{ YOUR API KEY }');
// Step 3: Compare Hash to Signature and verify that the request is recent
$isValid = (
hash_equals($gen, $_POST['signature'])
&& $_POST['timestamp'] > strtotime('-7 days')
);
?>
Below is an example payload for a purchase quote raised.
{
"clients": [
{
"person_id": 12345,
"person_title": "Mr.",
"person_fname": "Frank",
"person_lname": "Curtis",
"person_email": "frank@hoowla.com",
"person_dob": "2020-01-01",
"person_ni": "NI123456",
"person_source": "Webhook Example",
"address_line1": "Buckingham Palace",
"address_line2": "",
"address_city": "LONDON",
"address_county": "",
"address_postcode": "SW1A 1AA",
"phone_numbers": [
"01234 567 890",
"+44 1234 567 890"
]
}
],
"quotes": [
{
"id": 12345678,
"type": 1,
"line1": "Buckingham Palace",
"line2": "",
"city": "LONDON",
"county": "London",
"postcode": "SW1A 1AA",
"value": 130000,
"people": 1,
"holding": 2,
"title": "DN100",
"mortgaged": true,
"unregistered": false,
"shared_ownership": false,
"new_build": false,
"help_to_buy_equity_loan": false,
"help_to_buy_isa": false,
"buy_to_let": false,
"first_time_buyer": true,
"right_to_buy": false,
"islamic_mortgage": false,
"auction\/repossession": false,
"self_build": false,
"gifted_deposit": false,
"share_of_freehold": false,
"flat_or_apartment": false,
"equity_release_advice": false,
"lifetime_isa": false,
"non_uk_resident": false,
"client_is_company": false,
"land_reg_has_run": true,
"custom": [
"my_test_custom_situation"
],
"region": "england",
"expiry": "2020-12-01 00:00:00",
"supplements": [
{
"name": "Leasehold Fee",
"fee": "150.00"
},
{
"name": "VAT at 20%",
"fee": "135.00"
}
],
"disbursements": [
{
"name": "ID Verification fee (per person)",
"fee": "3.70"
},
{
"name": "Search Pack (approx)",
"fee": "199.00"
},
{
"name": "Land Registry Fees",
"fee": "95.00"
},
{
"name": "Stamp Duty (SDLT)",
"fee": "100.00"
}
],
"total_legal_fee_ex": "525.00",
"total_legal_fee_inc": "630.00",
"total_ex": "675.00",
"total_inc": "1207.70"
}
]
}
All Quotes:
Name | Type | Desc |
---|---|---|
id | int | the quote's unique id, this can be used later to link quotes raised to quotes instructed |
type | int | the quote type: 1 = purchase, 2 = sale, 4 = remortgage, 8 = transfer of equity |
line1 | string | line 1 of the property address |
line2 | string | line 2 of the property address |
city | string | town/city of the property |
county | string | the property's county |
postcode | string | the property's postcode |
value | float | the property value |
people | int | number of people involved in the quote - certain supplements and disbursements will be per person |
holding | int |
the tenure:
|
title | string | the land registry title number (if the check was made) |
mortgaged | bool | if the property is or will be using a mortgage |
custom | array | this will list any 'activated' custom situations on the quote |
region | string |
the country the property is within, options include:
|
expiry | string | when the quote is due to expire, in YYYY-MM-DD HH-MM-SS format |
supplements | array | a list of supplements for the quote, with the fee listed ex-vat |
disbursements | array | a list of disbursements for the quote, with the fee listed inc-vat |
total_legal_fee_ex | string | the legal fee for the quote, as an ex-vat price |
total_legal_fee_inc | string | the legal fee for the quote, as an inc-vat price |
total_ex | string | the quote's total price, as an ex-vat value (= supplements (except vat row) + disbursements + legal fee ex vat) |
total_inc | string | the quote's total price, as an inc-vat value (= supplements (including vat row) + disbursements + legal fee ex vat) |
Purchase Extras:
Name | Type | Desc |
---|---|---|
unregistered | bool | if the property is not registered with the land registry |
shared_ownership | bool | if the property purchase will be a shared ownership |
new_build | bool | if the property is a new build |
help_to_buy_equity_loan | bool | if the purchase is using a help to buy loan |
help_to_buy_isa | bool | if the purchase is using a help to buy ISA |
buy_to_let | bool | if the property is being purchased to let out (or is used as a 2nd home) |
first_time_buyer | bool | if the purchaser has never purchased a property before |
right_to_buy | bool | if the purchaser is under the right to buy scheme |
islamic_mortgage | bool | if the purchaser is using an islamic mortgage |
auction/repossession | bool | is being bought through an auction |
self_build | bool | is a self build property |
gifted_deposit | bool | if the deposit given was a gift to the client |
share_of_freehold | bool | if the purchase is a share of a freehold |
flat_or_apartment | bool | if this property is a flat or apartment |
equity_release_advice | bool | whether equity release advice is offered |
lifetime_isa | bool | is a Lifetime ISA is included in the quote |
non_uk_resident | bool | if the client is a non-uk resident (will change SDLT calculations) |
client_is_company | bool | if the client purchasing the residential property is a company (will change SDLT calculations) |
Sale Extras:
Name | Type | Desc |
---|---|---|
unregistered | bool | if the property is not registered with the land registry |
shared_ownership | bool | if the property is part of a shared ownership |
help_to_buy_equity_loan | bool | if the sale involves a help to buy loan |
share_of_freehold | bool | if the sale involves a share of a freehold |
flat_or_apartment | bool | if this property is a flat or apartment |
client_is_company | bool | if the client selling the property is a company |
Below is an example payload for a quote which has been instructed.
{
"id": 1234,
"case_id": 5678,
"created_at": "2026-01-01 00:00:00"
}
Name | Type | Desc |
---|---|---|
id | int | the quote's unique id, this can be used to link to the original quote |
case_id | int | if there is a case linked to this quote then the case id will be included, otherwise it will be null |
created_at | string | when the instruction occurred in Europe/London timezone (GMT/BST) |
Quote edit payloads are near identical to Quote Raised payloads and are structured as such. These webhooks are fired when someone edits a quote, even if nothing is changed.
Key differences:
quote_edited
{
"clients": [
{
"person_id": 1234,
"person_title": "",
"person_fname": "John",
"person_lname": "Doe",
"person_email": "john.doe@example.com",
"person_dob": "2021-11-24",
"person_ni": "",
"person_source": "",
"address_line1": "32",
"address_line2": "Example Lane",
"address_city": "Exampleton",
"address_county": "Yorkshire",
"address_postcode": "DY5 3EH",
"phone_numbers": [
"00000 2000000"
]
}
],
"quotes": [
{
"id": 375710,
"type": 2,
"line1": "Example Lane",
"line2": "",
"city": "",
"county": "",
"postcode": "EXAM 8LE",
"value": "200,000.00",
"people": 2,
"leasehold": false,
"mortgaged": true,
"unregistered": false,
"shared_ownership": false,
"holding": "",
"title": "",
"region": "england",
"expiry": "2024-10-22 14:30:15",
"supplements": [
{
"name": "Mortgage Fee",
"fee": "125.00"
},
{
"name": "Repayment of Mortgage",
"fee": "50.00"
},
{
"name": "VAT at 20%",
"fee": "140.00"
}
],
"disbursements": [
{
"name": "ID Verification fee (per person)",
"fee": "3.70"
},
{
"name": "OCEs (Title & Plan)",
"fee": "8.00"
},
{
"name": "Telegraphic Transfer",
"fee": "33.00"
},
{
"name": "office copies",
"fee": "6.00"
}
],
"total_legal_fee_ex": "525.00",
"total_legal_fee_inc": "630.00",
"total_ex": "750.70",
"total_inc": "890.70"
}
]
}
Please refer to the table for Quote Raised which details the data types. In Quote Edit, the types which have changed are as follows:
Name | Type | Desc |
---|---|---|
value | string | the property value |
consideration | string | the total monetary value exchanged for the property |
When creating a webhook within Hoowla, there's an option to send a test request with dummy data to help develop against. This can be found in:
Setup > Quote Calculators > Edit > Manage Webhooks > Send Test
Below is a basic example payload for a webhook raised in Hoowla via case rules.
{
"rule_name": "my rule name",
"rule_run": "2025-01-01 13:00:00",
"rule_run_by": 1234,
"case_id": 2345,
"taskgroup_name": "Purchase Leasehold",
"task_id": 3456,
"task_name": "Closed",
"status_id": null,
"status_name": null,
"custom_field_id": null,
"custom_field_title": null,
"custom_field_slug": null,
"custom_field_type": null,
"custom_field_value": null,
}
Another example, demonstrating when the rule is run for custom field changes.
{
"rule_name": "my custom field rule",
"rule_run": "2025-01-01 13:00:00",
"rule_run_by": 1234,
"case_id": 2345,
"taskgroup_name": null,
"task_id": null,
"task_name": null,
"status_id": null,
"status_name": null,
"custom_field_id": 109945,
"custom_field_title": "completion date",
"custom_field_slug": "551-completion-date",
"custom_field_type": "date",
"custom_field_value": "2025-02-21"
}
Name | Type | Desc |
---|---|---|
rule_name | string | the name given to the rule inside Hoowla |
rule_run | string | the datetime of when the rule was fired (as it could be a few seconds before you receive the webhook) |
rule_run_by | int | the id of the user who triggered the rule to fire |
case_id | int | the case the rule fired within |
taskgroup_name | string | the workflow name the rule is run from (e.g. purchase / sale) |
task_id | int | the task/milestone the rule fired within |
task_name | string | the name of the task/milestone the rule fired within or for |
status_id | int | the status/todo item which this rule fired against |
status_name | string | the name of the status/todo item which this rule fired against |
custom_field_id | string | the custom field id within Hoowla |
custom_field_title | string | the custom field human-readable title |
custom_field_slug | string | the unqiue custom field slug used for things like documents |
custom_field_type | string | the custom field type ('date', 'number', 'checkbox', 'radio', 'textarea', 'select' and 'text' are all valid values) |
custom_field_value | string | the custom field's new value |
You can also customize the rule webhooks with variable placeholders, e.g. @case-id@ and @reference-number@. Entered into the URL, this will be replaced by their custom fields on sending.
Below is an example payload for a person added payload.
{
"case":
{
"case_id" : 1234
},
"person":
{
"person_id": 12345,
"person_title": "Mr.",
"person_fname": "Frank",
"person_lname": "Curtis",
"person_email": "frank@hoowla.com",
"person_dob": "2020-01-01",
"person_ni": "NI123456",
"person_source": "Webhook Example",
"person_type": "Individual",
"person_side" : "Buyer",
"address_line1": "Buckingham Palace",
"address_line2": "",
"address_city": "LONDON",
"address_county": "",
"address_postcode": "SW1A 1AA",
"phone_numbers": [
"01234 567 890",
"+44 1234 567 890"
]
}
]
}
Name | Type | Desc |
---|---|---|
case_id | int | The id of the case in Hoowla |
person_id | int | the id of the person in Hoowla that has been added to the case |
person_title | string | the title of the person added to the case |
person_fname | string | the first name of the person added to the case |
person_lname | string | the last name of the person added to the case |
person_email | string | the email address of the person added to the case |
person_dob | string | the date of birth of the person added to the case |
person_ni | string | the national insurance number of the person added to the case (If available) |
person_source | string | the source of the person added to the case (If available) |
person_type | string | the company type of the person added to the case |
person_side | string | the side of the person added to the case |
address_line1 | string | the first line of the address of the person added to the case |
address_line2 | string | the second line of the address of the person added to the case |
address_city | string | the city of the address of the person added to the case |
address_county | string | the county of the address of the person added to the case |
address_postcode | string | the postcode of the address of the person added to the case |
phone_numbers | array | an array of phone numbers of the person added to the case |
Below is an example payload for when a person is removed from a case.
{
"case":
{
"case_id" : 1234
},
"person":
{
"person_id": 12345,
"person_title": "Mr.",
"person_fname": "Frank",
"person_lname": "Curtis",
"person_email": "frank@hoowla.com",
"person_dob": "2020-01-01",
"person_ni": "NI123456",
"person_source": "Webhook Example",
"person_type": "Individual",
"person_side" : "Buyer",
"address_line1": "Buckingham Palace",
"address_line2": "",
"address_city": "LONDON",
"address_county": "",
"address_postcode": "SW1A 1AA",
"phone_numbers": [
"01234 567 890",
"+44 1234 567 890"
]
}
]
}
Name | Type | Desc |
---|---|---|
case_id | int | The id of the case in Hoowla |
person_id | int | the id of the person in Hoowla that has been removed from the case |
person_title | string | the title of the person removed from the case |
person_fname | string | the first name of the person removed from the case |
person_lname | string | the last name of the person removed from the case |
person_email | string | the email address of the person removed from the case |
person_dob | string | the date of birth of the person removed from the case |
person_ni | string | the national insurance number of the person removed from the case (If available) |
person_source | string | the source of the person removed from the case (If available) |
person_type | string | the company type of the person removed from the case |
person_side | string | the side of the person removed from the case |
address_line1 | string | the first line of the address of the person removed from the case |
address_line2 | string | the second line of the address of the person removed from the case |
address_city | string | the city of the address of the person removed from the case |
address_county | string | the county of the address of the person removed from the case |
address_postcode | string | the postcode of the address of the person removed from the case |
phone_numbers | array | an array of phone numbers of the person removed from the case |
Below is an example payload for a Note being added to a case.
{
"case":
{
"case_id" : 1234
},
"note":
{
"note_id": 12345,
"note_case": 1234,
"note_task": "123456",
"note_user": 1,
"note_user_full_name": "frank@hoowla.com",
"note_creator": 1,
"note_creator_full_name": "frank@hoowla.com",
"note_text": "Test Note",
"note_is_alert": 0,
"note_permissions": "CUSTOM",
"custom_permissions": [
{
"user": 1,
"created": "2021-05-01 09:50:00"
}
],
"note_type": "General",
"note_status": null
}
]
}
Name | Type | Desc |
---|---|---|
case_id | int | The id of the case in Hoowla |
note_id | int | the id of the note in Hoowla that has been added to the case |
note_case | int | the case associated with the note added to the case |
note_task | int | the task associated with the note added to the case |
note_user | int | the id of the user who the note is assigned as being from |
note_user_full_name | string | the name of the user who the note is assigned as being from |
note_creator | int | the id of the user who created the note |
note_creator_full_name | string | the name of the user who created the note |
note_text | string | the text content of the note |
note_is_alert | boolean | if the note is set as an alert |
note_permissions | string |
The permissions of the note, which will be one of the following
|
custom_permissions | array |
if the note has CUSTOM Permissions, an array of user_ids with the date they had permissions
|
note_type | string | the name of the type of note. |
note_status | string |
the status of the note, if not null it will be either:
|
Below is an example payload for a case status being updated.
Note: This webhook will also fire when a case is re-opened.{
"case_id": 125382,
"status_old": "Live",
"status_new": "Fallen Through"
}
Name | Type | Desc |
---|---|---|
case_id | int | The id of the case in Hoowla |
status_old | string | This is the old status which the case has just been updated from. |
status_new | string | This is the new status which the case has just been updated to. |
Types of Case Status |
---|
Live |
In Abeyance |
Post Completion |
On Hold |
Fallen Through |
Deleted |
For Case Rules:
You can access and test these by adding a rule to a workflow in Hoowla. This is in:
Setup > Workflows > Hover-over a milestone (the green circles) > Click "Create Rule" button
View our Help Guide on creating rules
Once you're in the create rule view, you'll need to add an action like below:
Put your URL into the text box, provide an API key if you wish to secure it, then save.
For Person & Notes:
When creating a webhook within Hoowla, there's an option to send a test request with dummy data to help develop against. This can be found in:
Setup > Case Settings > Manage Webhooks > Send Test
What's the difference? These webhooks are able to send even if the person is not attached to a case.
Setup > People Area Settings > Manage Webhooks
Below is an example payload for a person edited payload.
{
"person": {
"person_id": 1234,
"person_title": "",
"person_fname": "Adam",
"person_lname": "Curtis",
"person_dob": "2024-12-02",
"person_email": "testing@example.com",
"person_website": "www.hoowla.com",
"person_source": "Webhook Documentation",
"person_ni": "ABCDEFG",
"person_is_company": 1,
"person_company": "Hoowla",
"person_locked_at": null,
"person_locked_by": null,
"person_created": "2024-12-02 09:29:53",
"person_edited": "2024-12-05 13:18:19",
"person_type": "Individual",
"gender_id": 1,
"gender_description": "Male",
"maritalstatus_id": 0,
"maritalstatus_description": null,
"address_line1": "64 Example Lane",
"address_line2": "Example Town",
"address_city": "Example City",
"address_county": "Swansea",
"address_postcode": "EX4 MPL3",
"phone_numbers": [
{
"phone_number": "+00000000000",
"phone_primary": true,
"phone_type_description": "Home"
},
{
"phone_number": "+00000000000",
"phone_primary": false,
"phone_type_description": "Mobile"
}
],
"relationships": []
}
}
Name | Type | Desc |
---|---|---|
person_id | int | the id of the person in Hoowla |
person_title | string | the title of the person, e.g., 'Mr' |
person_fname | string | the first name of the person |
person_lname | string | the last name of the person |
person_dob | string | the date of birth of the person |
person_email | string | the email address of the person |
person_website | string | the website url of the person (If available) |
person_source | string | the source of the person (If available) |
person_ni | string | the national insurance number of the person (If available) |
person_is_company | int | 1 if the person is a company, 0 otherwise. |
person_company | string | the company name of the person |
person_locked_at | string | the time the person was locked (If applicable) |
person_locked_by | string | the user id belonging to who locked the person (If applicable) |
person_created | string | the time that the person was created |
person_edited | string | the time that the person was last edited |
person_type | string | the company type of the person, e.g., 'Individual' |
gender_id | int | the id of the gender type for the person |
gender_description | string | the gender of the person, e.g., 'Female' |
maritalstatus_id | int | the marital status id of the person |
maritalstatus_description | string | the marital status description of the person |
address_line1 | string | the first line of the address of the person |
address_line2 | string | the second line of the address of the person |
address_city | string | the city of the address of the person |
address_county | string | the county of the address of the person/td> |
address_postcode | string | the postcode of the address of the person |
phone_numbers | array | an array of phone numbers of the person including phone_number, phone_primary and phone_type_description |
relationships | array | an array of relationships this person has with other people |
Any questions, get in touch through our contact page - https://www.hoowla.com/contact-us/