Zapier and Make

Connect NorTech to Zapier or Make

Start a Zap when a customer is added or an invoice is paid, and create customers, jobs and invoices from any form, spreadsheet or app. It works with the standard Webhooks and HTTP modules, so there is nothing to install.

Before you start

You need a NorTech Pro Business plan or higher, which includes API access. In the pro app, open Developers and create an API key. Give it only the scopes the automation needs, for example customers:write to add customers or invoices:read to read invoices. Copy the key when it is shown; it is not shown again.

Where this stands

NorTech is not listed in the Zapier app directory. You connect with the built-in Webhooks by Zapier app (or the HTTP module in Make), using the steps below. Everything is documented in the API reference and the OpenAPI file.

Triggers

A trigger starts your workflow. Each one below is a webhook event that NorTech sends the moment it happens, signed so you can check it came from NorTech. If you prefer to poll, the right-hand column shows the read call that returns the same records.

TriggerWebhook eventPolling instead
New customercustomer.createdGET /customers?updated_since=...
Estimate acceptedestimate.acceptedGET /estimates?status=ACCEPTED
Job scheduledjob.scheduledGET /jobs?status=SCHEDULED
Job completedjob.completedGET /jobs?status=COMPLETED
New invoiceinvoice.createdGET /invoices?updated_since=...
Invoice paidinvoice.paidGET /payments?received_since=...
Invoice overdueinvoice.overdueGET /invoices?status=OVERDUE
New reviewreview.receivedUse the webhook trigger

Set up a trigger in Zapier

  1. Create a Zap. For the trigger choose Webhooks by Zapier and the event Catch Hook. Zapier shows a URL that looks like https://hooks.zapier.com/hooks/catch/.... Copy it.
  2. In NorTech open Developers, add a webhook, paste the URL and tick the events you want. Or create it from code with the request below. Choose Send test event.
  3. Back in Zapier choose Test trigger. The test event appears. Build your steps from the fields in it (see the sample payloads below).
  4. Turn the Zap on. Deliveries show in the NorTech delivery log with the answer Zapier gave.
Create the webhook from code
POST https://nortech.site/api/v1/pro/webhooks
Authorization: Bearer ntk_xxxxxxxx_your_key
Content-Type: application/json

{
  "url": "https://hooks.zapier.com/hooks/catch/123456/abcdef/",
  "events": ["invoice.paid"],
  "description": "Zapier: invoice paid"
}

Zapier's Catch Hook does not check signatures by itself. If you want to, add a Code step that applies the check shown in the signature guide to the raw body and the NorTech-Signature header.

Polling trigger (Retrieve Poll)
GET https://nortech.site/api/v1/pro/invoices?status=PAID&updated_since=2026-10-01T00:00:00Z&limit=100
Authorization: Bearer ntk_xxxxxxxx_your_key

Actions

An action makes NorTech do something. Each is one REST call.

ActionCallScopeFields
Create customerPOST /api/v1/pro/customerscustomers:writename, email, phone, company, notes, tags
Add propertyPOST /api/v1/pro/propertiesproperties:writecustomer_id, street, city, state, zip, label, notes
Create estimatePOST /api/v1/pro/estimatesestimates:writecustomer_id, title, line_items, property_id, valid_until
Schedule jobPOST /api/v1/pro/jobsjobs:writecustomer_id, title, scheduled_start, scheduled_end, property_id, notes
Create invoicePOST /api/v1/pro/invoicesinvoices:writecustomer_id, line_items, due_date, job_id
Update jobPATCH /api/v1/pro/jobs/{id}jobs:writestatus, scheduled_start, scheduled_end, notes
Add price book itemPOST /api/v1/pro/price-bookprice_book:writename, unit_price_cents, unit, taxable

Set up an action in Zapier

  1. Add an action step, choose Webhooks by Zapier and the event Custom Request.
  2. Method: the one in the table. URL: https://nortech.site/api/v1/pro/customers (or the path for your action).
  3. Data Pass-Through: no. Data: the JSON body below, with fields from earlier steps. Unflatten: yes.
  4. Headers: Authorization = Bearer ntk_xxxxxxxx_your_key, Content-Type = application/json, and Idempotency-Key = a value unique to the run, such as the Zap run id, so a retry never creates a duplicate.
  5. Test the step. A 201 answer returns the new record with its id, which later steps can use.
Body for Create customer
{
  "name": "{{Name from your form}}",
  "email": "{{Email from your form}}",
  "phone": "{{Phone from your form}}",
  "tags": ["website"]
}

If a customer with the same email or phone already exists, the answer is 409 duplicate_customer and the message names the existing id, so a Zap can branch to update instead.

Make

In Make use Webhooks > Custom webhook as the trigger module: copy its address into a NorTech webhook exactly as above. For actions use HTTP > Make a request with the same URL, headers and JSON body, and parse the answer as JSON. To read many records, loop on next_cursor until has_more is false.

Sample payloads

Every webhook has the same envelope. The record is in data.object.

New customer customer.created

{
  "id": "evt_5f2a9c0b41d37e6a8c1f02d3",
  "type": "customer.created",
  "api_version": "2026-10-01",
  "created": "2026-10-14T15:30:02.114Z",
  "data": {
    "object": {
      "object": "customer",
      "id": "0b7f1c9e-5a2d-4c1b-9d1e-6f3a2b8c4d10",
      "name": "Dana Whitfield",
      "email": "dana@example.com",
      "phone": "+14085550142",
      "company": "Whitfield Dental",
      "notes": "Gate code 4471",
      "tags": [
        "repeat",
        "commercial"
      ],
      "created_at": "2026-10-01T16:20:00.000Z",
      "updated_at": "2026-10-02T09:05:00.000Z"
    }
  }
}

Estimate accepted estimate.accepted

{
  "id": "evt_5f2a9c0b41d37e6a8c1f02d3",
  "type": "estimate.accepted",
  "api_version": "2026-10-01",
  "created": "2026-10-14T15:30:02.114Z",
  "data": {
    "object": {
      "object": "estimate",
      "id": "0b7f1c9e-5a2d-4c1b-9d1e-6f3a2b8c4d10",
      "number": "EST-0042",
      "customer_id": "0b7f1c9e-5a2d-4c1b-9d1e-6f3a2b8c4d10",
      "property_id": "5d0a6e4b-77c2-4f1f-8a63-0e9a3d1b7c22",
      "title": "Replace kitchen faucet",
      "status": "ACCEPTED",
      "line_items": [
        {
          "description": "Faucet and install",
          "quantity": 1,
          "unit_price_cents": 18500,
          "taxable": false
        }
      ],
      "subtotal_cents": 18500,
      "tax_cents": 0,
      "total_cents": 18500,
      "valid_until": "2026-10-31",
      "accepted_at": "2026-10-05T18:12:00.000Z",
      "created_at": "2026-10-01T16:20:00.000Z",
      "updated_at": "2026-10-02T09:05:00.000Z"
    }
  }
}

Job scheduled job.scheduled

{
  "id": "evt_5f2a9c0b41d37e6a8c1f02d3",
  "type": "job.scheduled",
  "api_version": "2026-10-01",
  "created": "2026-10-14T15:30:02.114Z",
  "data": {
    "object": {
      "object": "job",
      "id": "0b7f1c9e-5a2d-4c1b-9d1e-6f3a2b8c4d10",
      "customer_id": "0b7f1c9e-5a2d-4c1b-9d1e-6f3a2b8c4d10",
      "property_id": "5d0a6e4b-77c2-4f1f-8a63-0e9a3d1b7c22",
      "estimate_id": null,
      "title": "Replace kitchen faucet",
      "status": "SCHEDULED",
      "scheduled_start": "2026-10-12T17:00:00.000Z",
      "scheduled_end": "2026-10-12T19:00:00.000Z",
      "completed_at": null,
      "notes": "Bring a 3/8 inch supply line",
      "created_at": "2026-10-01T16:20:00.000Z",
      "updated_at": "2026-10-02T09:05:00.000Z"
    }
  }
}

Job completed job.completed

{
  "id": "evt_5f2a9c0b41d37e6a8c1f02d3",
  "type": "job.completed",
  "api_version": "2026-10-01",
  "created": "2026-10-14T15:30:02.114Z",
  "data": {
    "object": {
      "object": "job",
      "id": "0b7f1c9e-5a2d-4c1b-9d1e-6f3a2b8c4d10",
      "customer_id": "0b7f1c9e-5a2d-4c1b-9d1e-6f3a2b8c4d10",
      "property_id": "5d0a6e4b-77c2-4f1f-8a63-0e9a3d1b7c22",
      "estimate_id": null,
      "title": "Replace kitchen faucet",
      "status": "COMPLETED",
      "scheduled_start": "2026-10-12T17:00:00.000Z",
      "scheduled_end": "2026-10-12T19:00:00.000Z",
      "completed_at": "2026-10-12T19:10:00.000Z",
      "notes": "Bring a 3/8 inch supply line",
      "created_at": "2026-10-01T16:20:00.000Z",
      "updated_at": "2026-10-02T09:05:00.000Z"
    }
  }
}

New invoice invoice.created

{
  "id": "evt_5f2a9c0b41d37e6a8c1f02d3",
  "type": "invoice.created",
  "api_version": "2026-10-01",
  "created": "2026-10-14T15:30:02.114Z",
  "data": {
    "object": {
      "object": "invoice",
      "id": "0b7f1c9e-5a2d-4c1b-9d1e-6f3a2b8c4d10",
      "number": "INV-0108",
      "customer_id": "0b7f1c9e-5a2d-4c1b-9d1e-6f3a2b8c4d10",
      "job_id": null,
      "title": "Faucet replacement",
      "status": "SENT",
      "line_items": [
        {
          "description": "Labor, 2 hours",
          "quantity": 2,
          "unit_price_cents": 9500,
          "taxable": false
        }
      ],
      "subtotal_cents": 19000,
      "tax_cents": 0,
      "total_cents": 19000,
      "amount_paid_cents": 0,
      "due_date": "2026-10-26",
      "issued_at": "2026-10-12T20:00:00.000Z",
      "paid_at": null,
      "created_at": "2026-10-01T16:20:00.000Z",
      "updated_at": "2026-10-02T09:05:00.000Z"
    }
  }
}

Invoice paid invoice.paid

{
  "id": "evt_5f2a9c0b41d37e6a8c1f02d3",
  "type": "invoice.paid",
  "api_version": "2026-10-01",
  "created": "2026-10-14T15:30:02.114Z",
  "data": {
    "object": {
      "object": "invoice",
      "id": "0b7f1c9e-5a2d-4c1b-9d1e-6f3a2b8c4d10",
      "number": "INV-0108",
      "customer_id": "0b7f1c9e-5a2d-4c1b-9d1e-6f3a2b8c4d10",
      "job_id": null,
      "title": "Faucet replacement",
      "status": "PAID",
      "line_items": [
        {
          "description": "Labor, 2 hours",
          "quantity": 2,
          "unit_price_cents": 9500,
          "taxable": false
        }
      ],
      "subtotal_cents": 19000,
      "tax_cents": 0,
      "total_cents": 19000,
      "amount_paid_cents": 19000,
      "due_date": "2026-10-26",
      "issued_at": "2026-10-12T20:00:00.000Z",
      "paid_at": "2026-10-14T15:30:00.000Z",
      "created_at": "2026-10-01T16:20:00.000Z",
      "updated_at": "2026-10-02T09:05:00.000Z"
    }
  }
}

Invoice overdue invoice.overdue

{
  "id": "evt_5f2a9c0b41d37e6a8c1f02d3",
  "type": "invoice.overdue",
  "api_version": "2026-10-01",
  "created": "2026-10-14T15:30:02.114Z",
  "data": {
    "object": {
      "object": "invoice",
      "id": "0b7f1c9e-5a2d-4c1b-9d1e-6f3a2b8c4d10",
      "number": "INV-0108",
      "customer_id": "0b7f1c9e-5a2d-4c1b-9d1e-6f3a2b8c4d10",
      "job_id": null,
      "title": "Faucet replacement",
      "status": "OVERDUE",
      "line_items": [
        {
          "description": "Labor, 2 hours",
          "quantity": 2,
          "unit_price_cents": 9500,
          "taxable": false
        }
      ],
      "subtotal_cents": 19000,
      "tax_cents": 0,
      "total_cents": 19000,
      "amount_paid_cents": 0,
      "due_date": "2026-10-26",
      "issued_at": "2026-10-12T20:00:00.000Z",
      "paid_at": null,
      "created_at": "2026-10-01T16:20:00.000Z",
      "updated_at": "2026-10-02T09:05:00.000Z"
    }
  }
}

New review review.received

{
  "id": "evt_5f2a9c0b41d37e6a8c1f02d3",
  "type": "review.received",
  "api_version": "2026-10-01",
  "created": "2026-10-14T15:30:02.114Z",
  "data": {
    "object": {
      "object": "review",
      "id": "9c2d1e4f-0a5b-4e77-b1c3-3d8e6f7a9b01",
      "rating": 5,
      "comment": "Fast, tidy and fair.",
      "customer_name": "Dana W.",
      "job_id": "0b7f1c9e-5a2d-4c1b-9d1e-6f3a2b8c4d10",
      "created_at": "2026-10-15T10:00:00.000Z"
    }
  }
}