All articles

Getting started

Send visits to Zapier or n8n with a webhook

Set up a webhook so Zapier, n8n or your own system hears about every completed visit, and check that each delivery really comes from Rytmia.

A webhook lets Rytmia tell another system when something happens. You give Rytmia a URL, and every time a visit is completed, Rytmia sends a message to that URL with the visit, the client, the site and who did the work.

The URL usually belongs to an automation tool such as Zapier or n8n. There you decide what happens next: send the client a review request, add a row to a spreadsheet, post in a chat channel, or anything else the tool can do.

What gets sent

Today Rytmia sends one event:

Event in Rytmia Type in the message Sent when
Visit completed work-shift.completed Every coworker on a visit has completed their part. Coworkers who were excused or declined the visit do not count.

More events will be added later. Each webhook chooses which events it receives.

What you need

  • Permission to change integrations in Rytmia. By default, owners and office personnel have it. Field workers do not.
  • Somewhere to receive the messages. A Zap in Zapier, a workflow in n8n, or your own system. The address must start with https:// and be reachable from the internet. Webhooks by Zapier is not included in Zapier’s free plan.

An organization can have up to 10 webhooks.

Set it up in Zapier

  1. In Zapier, create a Zap. As the trigger, choose Webhooks by Zapier.

  2. Under Trigger event, choose Catch Hook and then Continue.

    If you are going to check the signature (see Check the signature), choose Catch Raw Hook instead. It keeps the message exactly as Rytmia sent it.

  3. On the Test tab, copy the webhook URL.

  4. In Rytmia, create the webhook with that URL and send a test event.

  5. Back in Zapier, choose Test trigger. The test event shows up.

The test event only says it is a test. To map fields such as the client’s name or the address into later steps, Zapier needs a real Visit completed. Once a visit has been completed, choose Test trigger again and pick that request.

Zapier answers every message with a success as long as the Zap exists. If you turn the Zap off or delete it, Zapier starts refusing messages, and Rytmia eventually stops sending (see When deliveries fail).

Set it up in n8n

  1. In n8n, add a Webhook node as the first node of a workflow.

  2. Set HTTP Method to POST.

    If you are going to check the signature, also turn on Raw Body under the node’s options.

  3. The node has two URLs, a Test URL and a Production URL. Copy the Test URL first.

  4. In Rytmia, create the webhook with the Test URL.

  5. In n8n, choose Listen for test event. Then, within a couple of minutes, send a test event from Rytmia. The event shows up in the node.

  6. When the workflow is ready, publish it (in older versions of n8n: activate it). Copy the Production URL, then edit the webhook in Rytmia and replace the Test URL with it.

Don’t leave the Test URL in Rytmia. n8n only listens on it for a short while after you choose Listen for test event. At any other time, every message fails, and after about two days Rytmia turns the webhook off. The Production URL contains /webhook/, the Test URL contains /webhook-test/.

Messages that reach the Production URL do not show in the editor. You find them under the workflow’s Executions tab.

Create the webhook in Rytmia

  1. Go to Administration → Integrations.
  2. Under Webhooks, choose Manage.
  3. Choose New.
  4. Under URL, paste the address from Zapier, n8n or your own system.
  5. Under Description, write what the webhook is for, for example Zapier – review requests. This is optional, but helps when you have several.
  6. Under Events, tick Visit completed.
  7. Choose Save.

Rytmia then shows the webhook’s signing secret. It starts with whsec_. Copy it and keep it somewhere safe, such as your password manager. It is shown only this once. You need it to check the signature. Choose I’ve saved it to close the dialog.

If you lose the secret, choose New signing secret in the webhook’s menu. The old secret stops working at once, so update it in your receiver straight away.

Send a test event

In the webhook’s menu, choose Send test event. The Delivery log opens and shows the test being sent.

A test event looks like this:

{
  "type": "webhook.test",
  "timestamp": "2026-10-08T12:41:07+00:00",
  "data": {
    "webhookEndpointId": "0199c3a2-7f1e-7c3a-9b1d-2f6e8a4c5d10"
  }
}

A test is tried only once. If it fails, the delivery log shows why: the HTTP status your receiver answered with, or the error. Fix the receiver and send another test. A failed test never turns the webhook off.

The delivery log

Choose Delivery log in the webhook’s menu to see what Rytmia has sent to it, newest first. The log is kept for 30 days.

Status Meaning
Queued Waiting for its first attempt, usually a few seconds.
Retrying An attempt failed. Rytmia tries again later.
Delivered The receiver accepted it.
Failed Every attempt failed. Rytmia has stopped trying.
Not sent The webhook was turned off or deleted before it went out.

Open a delivery to see the HTTP status, the number of attempts, the last error and the JSON sent, exactly as it went out. Copy the JSON when you need to see which fields there are to map.

What a visit completed message contains

Every message is a POST with a JSON body. The body has the event’s type, a timestamp in UTC, and the data:

{
  "type": "work-shift.completed",
  "timestamp": "2026-10-08T12:41:07+00:00",
  "data": {
    "id": "0199c1f0-3b2a-7d4e-8f10-5a6b7c8d9e01",
    "startsAt": "2026-10-08T13:00:00+02:00",
    "endsAt": "2026-10-08T14:30:00+02:00",
    "timezone": "Europe/Stockholm",
    "completedAt": "2026-10-08T14:41:07+02:00",
    "order": {
      "id": "0199a8e4-1c2d-7e3f-9a0b-1c2d3e4f5a6b",
      "number": "1042"
    },
    "client": {
      "id": "01999b7d-4e5f-7a6b-8c9d-0e1f2a3b4c5d",
      "name": "Acme AB",
      "customerNumber": "10023"
    },
    "serviceLocation": {
      "id": "01999b7d-6a7b-7c8d-9e0f-1a2b3c4d5e6f",
      "name": "Acme head office",
      "line1": "Storgatan 1",
      "line2": null,
      "postalCode": "111 22",
      "city": "Stockholm",
      "country": "SWE"
    },
    "coworkers": [
      { "id": "0199a001-2b3c-7d4e-8f5a-6b7c8d9e0f1a", "name": "Anna Andersson" },
      { "id": "0199a001-9c8d-7e6f-8a5b-4c3d2e1f0a9b", "name": "Erik Berg" }
    ]
  }
}
Field What it is
id The visit.
startsAt, endsAt When the visit was scheduled, in the visit’s own timezone, with the offset.
timezone That timezone.
completedAt When the visit was completed, in the same timezone.
order The order the visit belongs to, and its number.
client The client’s name and customer number.
serviceLocation The site: its name and address. country is a three-letter code, such as SWE.
coworkers The coworkers who completed their part of the visit. Excused coworkers are not listed.

Every field is always present, even when it is empty. An empty value is null, so a mapping you set up on one visit still finds its field on the next. Rytmia may add fields to a message later, but does not rename or remove them.

The message describes the visit as it was when it was sent. If something changes afterwards, such as the client’s name, earlier messages are not sent again.

Check the signature

Anyone who knows your webhook URL can send messages to it. The signature lets your receiver check that a message really comes from Rytmia and has not been changed. Check it whenever the automation does something that matters, such as sending messages to clients.

Rytmia signs messages the Standard Webhooks way. Every message has three headers:

Header What it is
webhook-id The message’s id. It stays the same when a message is sent again.
webhook-timestamp When this attempt was sent, in seconds since 1970.
webhook-signature v1, followed by the signature.

In your own system, use one of the Standard Webhooks libraries, available for JavaScript, Python, PHP, Ruby, Go, Java, C#, Rust and Elixir. Give the library the signing secret as it is, whsec_ included, together with the headers and the body exactly as you received it. The library also turns away messages that are too old.

In Zapier or n8n, add a code step right after the trigger that runs the check below, and stop the workflow when it returns false. The check needs the body exactly as Rytmia sent it, character for character, so use Catch Raw Hook in Zapier or turn on Raw Body in the n8n Webhook node.

const crypto = require('crypto');

function isFromRytmia(secret, id, timestamp, signature, body) {
  const key = Buffer.from(secret.replace(/^whsec_/, ''), 'base64');
  const expected = crypto.createHmac('sha256', key)
    .update(`${id}.${timestamp}.${body}`)
    .digest('base64');
  const fresh = Math.abs(Date.now() / 1000 - Number(timestamp)) <= 5 * 60;
  return fresh && signature.split(' ').includes(`v1,${expected}`);
}

secret is your signing secret, id, timestamp and signature are the three headers, and body is the raw body. On self-hosted n8n, the Code node can only load crypto if the instance allows it with the NODE_FUNCTION_ALLOW_BUILTIN setting.

Each attempt is signed again with a new timestamp, so a message that is sent again later still passes the check.

When deliveries fail

A delivery has succeeded when the receiver answers with a status in the 200s within 10 seconds. Anything else is a failed attempt: an error status, a redirect, or no answer in time.

After a failed attempt, Rytmia tries again after 1 minute, 5 minutes, 30 minutes, 2 hours, 6 hours, 12 hours and 24 hours. That is eight attempts over about two days. If the last one fails too, the delivery is Failed.

Rytmia turns the webhook off when a delivery has failed every attempt and nothing else has reached the webhook in the meantime, which means about two days without a single delivery getting through. The webhook then shows Turned off after failures, and a message at the top of the page says so. To start again:

  1. Open the Delivery log and read the last error.
  2. Fix the receiver. For example, turn the Zap back on, publish the n8n workflow, or replace an n8n Test URL with the Production URL.
  3. Choose Turn on in the webhook’s menu, and send a test event.

While a webhook is off, nothing is sent to it, and deliveries that were waiting are dropped. Visits completed while it was off are not sent when you turn it on again.

You can also turn a webhook off yourself with Turn off, for example while you rebuild a Zap. Delete removes the webhook and its delivery log.

Good to know

  • The same message can arrive twice. If Rytmia can’t tell whether an attempt arrived, it sends the message again. It has the same webhook-id, so a receiver that keeps track of ids can skip repeats.
  • An undone completion is not announced. If a visit is completed and the completion is later undone, for example because an excuse is cleared, Rytmia sends nothing. When the visit is completed again, a second Visit completed is sent, with a new webhook-id.
  • Messages go out within seconds, but are not guaranteed to arrive in the order the visits were completed. Use completedAt when the order matters.

Still need help?

If you cannot find the answer here, the Rytmia team will help you move forward.

Contact Rytmia