All articles

Integrations

Appointment Webhook — Connect Calendly / Cal.com / Acuity

Auto-create customers in JewelTrak when they book an appointment in your external calendar tool (Calendly, Cal.com, Acuity, or any tool with webhooks).

Appointment Webhook — Connect Calendly / Cal.com / Acuity

Most jewelry shops that take appointments use a third-party calendar tool (Calendly is the most common). JewelTrak’s appointment webhook lets that tool push bookings into JewelTrak so the customer auto-creates in your contacts table — by the time they walk in, they’re already in the system.

Works with any tool that supports outbound webhooks, not just Calendly.

Setup (~5 minutes)

  1. In JewelTrak, go to Settings → Integrations → Appointment Webhook.
  2. Click Generate secret. The page shows you a webhook URL and a secret. Copy both — the secret is shown once, then masked.
  3. In your calendar tool, configure an outbound webhook on the booking-created event:
    • URL: paste the webhook URL
    • Auth: pass the secret either as Authorization: Bearer <secret> header OR as ?token=<secret> query param on the URL — whichever your tool supports
  4. Save the webhook in the calendar tool. Most tools have a “Send test” — fire one to confirm the round-trip.

What happens when an appointment fires

  1. Your calendar tool POSTs the booking to your JT URL.
  2. JT validates the secret.
  3. JT looks up the contact by email (case-insensitive). Match found → uses that contact. No match → auto-creates a new contact with the booker’s name + email + phone, marked IsCustomer=1.
  4. JT records the appointment row in appointments.
  5. Returns HTTP 200 with the appointment ID + contact ID + a created: true/false flag.

By the time the customer walks in for their appointment, they’re already a customer in JT.

The payload JewelTrak expects

For tools that let you customize the webhook body, this is the normalized shape:

{
  "customer_email": "jane@example.com",     // required
  "customer_name": "Jane Smith",
  "customer_phone": "+15555551212",
  "start_time": "2026-06-15T14:00:00Z",
  "duration_minutes": 60,
  "appointment_type": "Custom design consult",
  "notes": "Wants to discuss engagement ring",
  "external_id": "cal-abc123",              // for idempotent retries
  "source": "acuity"                        // free-form label — name your tool
}

customer_email is the only required field. JewelTrak also accepts common aliases without any mapping: email, name, phone, startTime / start, type, externalId. So most tools work even if you can’t customize the body.

Per-provider setup

Calendly

Calendly’s native v2 payload is auto-unwrapped — no payload transformation needed. Two paths:

  • Easiest: save a Calendly Personal Access Token on the settings page and click Register webhook with Calendly. JT registers the booking webhook over Calendly’s API for you (Calendly has no webhook screen in its UI). The token also lets JT look up each booking’s real start time and the host — its webhook doesn’t include them inline.
  • The token’s scopes: users:read, scheduled_events:read, webhook_subscriptions:read, webhook_subscriptions:write.

It also captures two booking-form questions when present: “How can we help you?” (becomes the appointment type) and “Referred by?” (saved as a Referrer relationship on newly created contacts).

Cal.com

  1. In Cal.com: Settings → Developer → Webhooks → New.
  2. Subscriber URL = your JT webhook URL with the token appended: …/api/webhooks/appointment/<orgId>?token=<secret> (Cal.com doesn’t send a custom auth header, so use the ?token= form).
  3. Event triggers: check Booking created (and Booking cancelled if you want JT to mark cancellations).
  4. Cal.com sends the start time inline, so no API token needed — times are accurate out of the box.

Acuity Scheduling

Acuity’s native webhook only sends an appointment ID, not the details, so it needs a thin translation layer:

  1. Use Zapier, Make, or n8n with an Acuity → Webhook flow (see below). The middle step looks up the appointment and posts the normalized JSON to your JT URL.
  2. Set source to "acuity" and pass the secret as Authorization: Bearer <secret>.

Square Appointments

Square’s webhooks (booking.created) post a booking object. Route it through Zapier/Make/n8n (below) to reshape it into the JT payload, mapping the customer email/name/phone and start_atstart_time.

Any other tool (Zapier / Make / n8n fallback)

If a tool can’t POST a custom webhook directly, put a no-code automation in the middle:

  1. Trigger: your calendar tool’s “appointment booked” event.
  2. Action: Webhooks → POST to your JT URL.
  3. Headers: Authorization: Bearer <secret> (or use ?token=<secret>).
  4. Body (JSON): map the tool’s fields into the shape above. Set a descriptive source (e.g. "square", "acuity") so you can tell bookings apart in the Recent list.

This is also how you’d connect a fully custom booking page on your website.

Idempotent retries

Most webhook providers retry on non-2xx responses (network blips, brief downtime). JT dedupes via the (Source, ExternalID) tuple — if you send the same booking twice, you get the existing appointment row’s ID back with created: false. No ghost duplicates.

Recent appointments view

The settings page shows the last 20 received appointments — source, customer, type, start time, received time. Useful for spot-checking the integration is firing.

Rotating the secret

If the secret leaks (don’t post it publicly!), click Rotate secret — generates a new one, invalidates the old. Update your calendar tool with the new value.

Disable endpoint clears the secret entirely. The URL still exists but every request returns 404 until you regenerate.

Why this isn’t a Calendly-specific integration

Different shops use different calendar tools. By making this a generic webhook with a per-tenant URL, every tool that supports outbound webhooks works — Calendly, Cal.com, Acuity, Square Appointments, even Zapier or n8n as a translation layer for tools that don’t natively support webhooks.

See also

  • Contacts Overview — broader contact model
  • Customer Wishlist — pairs naturally with consult appointments