Insites Docs Developers guide IntegrationsRunning Custom Logic from a CRM Field Update

AI answers drawn only from these docs, with links to the pages used.

Running Custom Logic from a CRM Field Update

Last updated on October 09, 2026.

Sometimes you want custom server-side functionality to run automatically when an administrator updates a single field on a CRM record in the Insites Instance Admin (IIA), such as a field on a contact profile or on a company. You do not need to build a custom admin screen, and you do not need to poll for changes. The CRM sends a webhook when the record is updated, the webhook calls your endpoint, and your endpoint runs the work.

This is a common and powerful pattern: an administrator changes one field using the native IIA, and that single change drives an entire workflow.

When to use this pattern

  • Issue and email a certificate when an admin sets an assessment status to Passed.
  • Start an onboarding sequence when a contact stage changes.
  • Push an update to a third-party system when a company field changes.
  • Generate a document, send a notification, or update a related record in response to a manual review decision.

How it works

The flow has five steps:

  • An administrator updates a field on a contact or company in the IIA.
  • The CRM sends the webhook (a company update sends ).
  • The webhook calls your API endpoint directly. There is no middleware application in between.
  • Your endpoint checks a secret token, checks that the field you care about changed, guards against duplicate processing, enqueues a background job, and returns immediately.
  • The background job runs the custom logic: generate a PDF, send an email, call an external API, update a related record, and so on.

Prerequisites

  • The CRM module. Contact and company updates trigger webhooks, and the payload supports three modes.
  • Familiarity with Background Jobs and the API.

Webhook payload modes

The webhook can send one of three payloads. You choose the Payload Format when you configure the webhook:

  • Changes Only: only the fields that changed. Each change is an object with an value and a value.
  • Changes with Snapshot: the fields that changed, plus the full record. Recommended for this pattern, because you can confirm your field changed and read the rest of the record in a single call.
  • Full Object (default): the entire record, with no indication of what changed.

Step 1: Choose the trigger field

Decide which field an admin will update to start the workflow. This can be an existing CRM profile field or one you add to the schema. Use a clear, dedicated field, for example a status field whose value an admin sets to Passed.

Step 2: Configure the CRM webhook

Point a CRM webhook at the endpoint you build in step 3, and set the Payload Format to Changes with Snapshot. The webhook is sent on contact updates (or company updates). Add a long random token to the webhook URL, for example , and store the same token as the constant .

Step 3: Build the webhook receiver endpoint

Create a POST page that receives the webhook. It checks a secret token, checks the field, guards against duplicate processing, enqueues a background job, and returns 200 quickly. Keep all logic in commands and background jobs; the page is only a controller.

app/views/pages/webhooks/contact-updated.json.liquid

---
slug: webhooks/contact-updated
method: post
---
{% liquid
  assign payload = context.params

  # the CRM does not sign its requests, so compare the token in the URL with the stored secret
  if context.params.token != context.constants.WEBHOOK_SECRET
    response_status 401
  else
    # only act when the field we care about changed to Passed
    # each change is an object with old and new; a custom field is keyed custom_field.<name>
    assign new_status = payload.changes['custom_field.level2_review_status'].new

    if new_status == 'Passed'
      background source_name: 'issue_certificate', max_attempts: 3, contact_id: payload.snapshot.id, level: 2
        function _ = 'lib/commands/certificates/issue', contact_id: contact_id, level: level
      endbackground
    endif

    response_status 200
  endif
%}

The exact payload keys depend on the webhook mode you select. Inspect a sample delivery to confirm the field paths before relying on them.

Step 4: Run the work in a background job

The background job calls a command that performs the work. Because the job runs asynchronously, the webhook request returns straight away while the slow work (PDF generation, email, external API calls) happens in the background, with automatic retries on failure.

Important considerations

Make it idempotent

The update webhook is sent on every change to the record, not only the change you care about. Always guard the work so it runs once. For example, before issuing a certificate, check that one has not already been issued for that contact. The field changing is necessary but not sufficient; already done is the real stop condition.

Return quickly

Check the token and enqueue, then return 200. Do not do slow work inside the request. Offload it to a background job.

Avoid loops

If your background job updates the same record, make sure it cannot re-trigger the same workflow. The idempotency guard above handles this.

Verify the source

The CRM webhook does not sign its requests and sends no secret header. Add a long random token to the webhook URL, store the same token as a constant, and compare with before acting on the request.

Related

Have a suggestion for this page?

Didn't quite find what you are looking for or have feedback on how we can make the content better then we would love to hear from you. Please provide us feedback and we will get back to you shortly.