On this page
Two building blocks
| You want | HailMate side | Automation-tool side |
|---|---|---|
| HailMate starts it — “when a claim is approved…” | A webhook to the tool’s URL | Zapier: Catch Hook · Make: Custom webhook · n8n: Webhook node |
| HailMate does it — “…then create a job” | An API request with your key | Zapier: Custom Request · Make: Make a request · n8n: HTTP Request node |
For both you need an API key: in HailMate open Settings → Integrations → API & Webhooks and press New key. Give each tool its own key, so revoking one never breaks another, and use a read-only key for anything that only reads.
The headers every request needs
Authorization: Bearer hm_live_… on every call, and Content-Type: application/json on anything that sends a body. The base URL is https://app.hailmate.ai/api/v1.Zapier
Trigger: Webhooks by Zapier → Catch Hook
- Create a Zap. For the trigger choose Webhooks by Zapier, event Catch Hook, and copy the webhook URL Zapier shows you.
- In HailMate, open Settings → Integrations → API & Webhooks, add a webhook, pick the event and any filters, and paste that URL. (Or subscribe it with
POST /webhooks.) - Press Send test in HailMate, then Test trigger in Zapier. The record’s fields arrive at the top level of the delivery, ready to map.
Action: Webhooks by Zapier → Custom Request
| Field | Value |
|---|---|
| Method | POST |
| URL | https://app.hailmate.ai/api/v1/jobs |
| Data | The JSON body, with fields from earlier steps mapped in |
| Headers | Authorization → Bearer hm_live_…Content-Type → application/jsonIdempotency-Key → an id from the trigger, e.g. the form submission id |
The simpler GET and POST actions work too — for POST, set Payload Type to json. Webhooks by Zapier is one of Zapier’s premium apps, so check that your Zapier plan includes it.
Make
Trigger: Webhooks → Custom webhook
- Add a Webhooks module, choose Custom webhook, add a new webhook and copy its address.
- Add that address as a webhook in HailMate, as for Zapier.
- With the module waiting for data (Redetermine data structure), press Send test in HailMate. Make learns every field from the delivery.
Action: HTTP → Make a request
- URL
https://app.hailmate.ai/api/v1/…and the Method. - Headers:
Authorization=Bearer hm_live_…. - Body type Raw, Content type JSON (application/json), and the JSON in Request content.
- Turn on Parse response so later modules can map the answer’s fields, such as the new job’s
id.
n8n
Trigger: Webhook node
- Add a Webhook node with HTTP method
POST. - Give HailMate the node’s Production URL — the Test URL only answers while the editor is listening — and activate the workflow.
- To check signatures, turn on the node’s raw-body option and compare an HMAC-SHA256 of
<t>.<raw body>(a Crypto node) with thev1inX-HailMate-Signature. How signing works.
Action: HTTP Request node
- Authentication: Generic credential type → Header Auth, with name
Authorizationand valueBearer hm_live_…. The key is then stored as a credential, not pasted into every node. - Send Body on, Body Content Type JSON.
- For lists, the node’s Pagination option can follow
next_cursorfor you: send it back as thecursorquery parameter until it comes back empty.
Tips that save an afternoon
- Filter in HailMate, not in the tool. A webhook filter such as
{"stage": "Claim Approved"}means the automation only runs when it should — a cleaner run history, and no runs spent on events you throw away. - Map fields from a real delivery. Send test in Settings, or
GET /webhooks/samples/job.created, shows every field before anything real has happened. - Search before you create.
GET /contacts/searchmatches a phone number however it was typed, so a form lead who is already a homeowner in HailMate is found rather than duplicated. - Send an Idempotency-Key built from something stable in the trigger, such as the form submission id. When the tool retries a step, HailMate replays the first answer instead of making a second job.
- Send stages by label.
"stage": "Inspection Scheduled"works as well as the key. - Appointment times are wall-clock.
due_datehas no time zone; show it as it is. A formatter step that assumes UTC will shift it by hours. - When a step fails, its error names the
fieldthat was wrong, and Settings → Integrations → API & Webhooks lists every request a key made, and every delivery, for you to look at.
Recipes
Eight automations roofers ask for. Each works in Zapier, Make or n8n; placeholders like {{email}} stand for a field mapped from an earlier step.
- Website form → contact and job, without duplicates
- Slack message when a claim is approved
- A Google Sheets row for every signed estimate
- Payments into your accounting app
- Text the crew when a build day is booked
- An “interested” door becomes a lead
- Storm list ready → the mail house
- Tag a new lead with its hail history
Website form → contact and job, without duplicates
Trigger: a new submission from your website form, a Facebook lead ad or any form tool.
- Look them up.
GET /contacts/search?email={{email}}&phone={{phone}}tries email, then phone. - Only if
datais empty (a Filter, Path or Router step), create them withPOST /contacts. - Create the job with the contact’s
idfrom step 1 or 2, and the submission id as theIdempotency-Key, so a retried step never makes a second job.
{
"name": "{{name}}",
"email": "{{email}}",
"phone": "{{phone}}",
"address": "{{street}}",
"city": "{{city}}",
"state": "{{state}}",
"postal_code": "{{zip}}"
}{
"name": "{{street}}",
"address": "{{street}}",
"city": "{{city}}",
"state": "{{state}}",
"postal_code": "{{zip}}",
"homeowner_id": "{{contact_id}}",
"lead_source": "Website",
"notes": "{{message}}"
}Slack message when a claim is approved
Trigger: job.stage_changed with the filter {"stage": "Claim Approved"} — use your board’s own stage name.
Action: Slack → send a channel message. The delivery already carries the old and new stage and a link to the job:
✅ {{name}} moved from {{previous_stage_label}} to {{stage_label}}
RCV {{rcv_amount}} · {{assigned_to_name}}
{{url}}A Google Sheets row for every signed estimate
Trigger: estimate.signed
- Optional:
GET /jobs/{{job_id}}for the address and the homeowner’s name. - Google Sheets → create a row:
estimate_number,title,total,selected_tier,signer_name,signed_at, and the job’saddress.
total is the package the homeowner chose, computed the way the PDF computes it — the number that belongs in a sales sheet.
Payments into your accounting app
Trigger: payment.received, optionally filtered — e.g. {"payer_type": "insurance"}.
GET /jobs/{{job_id}}for the customer:homeowner.nameand the job’saddress.- In your accounting app, record the payment:
amount,date_received,payment_method,check_numberandnotes. - Add a second automation on payment.refunded — a refund is its own payment with a negative
amount.
Text the crew when a build day is booked
Trigger: appointment.created with the filter {"appointment_type": "build_day"}.
GET /jobs/{{job_id}}for the address.- Send the text — your SMS app, or a message in the crew’s chat — with the job’s address and
due_date.
due_date is the crew’s local time with no offset (2026-10-02T07:00:00 is 7 AM on site). Format it as it is. To catch reschedules, add task.updated with the same filter and continue only when changed_fields contains due_date.
An “interested” door becomes a lead
Trigger: pin.result_changed with the filter {"knock_result": "interested"} — and pin.created with the same filter, for doors marked interested on the first knock.
Send it wherever your setters work — a dialer, a shared sheet, another CRM — with homeowner_name, phone, email, address, created_by_name (the rep) and map_url. Skip pins whose job_id is already set: that door has been turned into a job in HailMate.
Storm list ready → the mail house
Trigger: storm_list.ready
GET /storm_lists/{{id}}/properties?mailable=true&limit=200, followingnext_cursoruntil it is empty (n8n’s pagination option or Make’s repeater do this well).- Send the rows —
owner_name,mailing_address,mailing_city,mailing_state,mailing_zip,hail_size_in,hail_event_date— to your mail house, as a sheet or a file.
mail_deliverable is HailMate’s own judgement from the address on file — not a CASS or NCOA result. Run your own address validation before you spend postage.Tag a new lead with its hail history
Trigger: job.created
GET /hail_history?address={{address}}, {{city}}, {{state}} {{postal_code}}— the same Evidence Grade™ ruling HailMate’s maps and storm reports use.- Write it onto the job’s timeline with
POST /notes.
{
"job_id": "{{id}}",
"content": "Hail history: {{hail_day_count}} hail days since {{since}}. Largest {{largest_hail_in}} in, most recent {{last_hail_date}}."
}Hail lookups are limited to 20 a minute per key — plenty for new leads, but pace a bulk backfill of your whole book.