EspoCRM webhooks for event-driven integrations

Learn how EspoCRM webhooks send record changes to other systems in near real time, how to secure and verify them, and what breaks when deliveries fail.

On this page

How EspoCRM webhooks push record changes to other systems

A team that needs CRM changes to reach an ERP, a data warehouse, a messaging tool or a custom service should not build a polling job against the EspoCRM API. EspoCRM webhooks are the supported outbound method, and you configure them through the REST API using a dedicated API user rather than a personal login. Each webhook subscribes to an event on a chosen entity type and sends an HTTP request to a URL you control when that event happens. The sending side is EspoCRM; the receiving endpoint, its parsing, its storage and its downstream logic must be built by your team or a partner. Nothing in the product provides a ready-made consumer for your ERP or warehouse.

The event types differ in what they carry, and your receiver should be designed around that. A create event sends all attributes of the record. An update event sends only the attributes that changed, so a receiver that keeps a copy of each record must merge partial payloads instead of overwriting them. A delete event identifies the removed record. For narrower triggers, ENTITY_TYPE.fieldUpdate.FIELD fires only when a specific field changes, for example Account.fieldUpdate.assignedUserId when account ownership moves. Subscribing to field-level events rather than all updates reduces traffic and the processing your downstream system must handle. The webhook owner's own changes can also echo back into the subscription. From version 9.2, the skipOwn parameter skips events that the webhook owner initiated, which matters when the receiver writes back to EspoCRM. Confirm the exact payload shape for your version in the webhooks documentation before you write the parser.

Before you go live, confirm the API user's permissions. According to the EspoCRM webhooks documentation, the API user needs the Webhooks scope and access to every entity type it subscribes to, so a missing entity permission will block a subscription you expected to work. Decide who may create webhooks and keep that API user separate from people and other integrations. The receiver should verify the signature with the secret key before it trusts a payload, and your team should also decide how failed deliveries are handled, how duplicates are recognized, and how events are replayed from your own logs, since you cannot assume delivery is exactly once. Ask your implementation partner to document these decisions in the statement of work so that the receiver, the API user and the monitoring are designed together.

What you need before creating the first EspoCRM webhook

A webhook is only as reliable as the instance, identity and endpoint behind it. The cards below cover the EspoCRM version, the hosting model, the API user, the receiving endpoint and the secret store, which together decide whether the first event arrives and whether it can be trusted.

Confirm the EspoCRM version

Run the 10.0.x line, which is the current major series on the releases page. The skipOwn parameter needs version 9.2 or later, so confirm the exact build in Administration before you design subscriptions around it. Check the release notes for your build because delivery behavior and header details can change between versions, and confirm them in the webhook documentation for that version before you write any receiver.

Pick the hosting model

Decide whether the instance is self-hosted in your own infrastructure or runs on EspoCRM Cloud. Either way, the receiving system must be able to reach the instance, and the instance must be able to reach the receiver over HTTPS. Confirm which outbound network paths, firewall rules and proxy settings apply, since a webhook sent from behind a restricted network can fail silently.

Create a dedicated API user

Webhooks are configured under an API user, not a person's login. That user needs the Webhooks scope and read access to every entity type it subscribes to. Create a separate user for each integration so that permissions, rotation and audit trails stay isolated. Grant the minimum access needed, and record which entity types the integration depends on so access reviews stay accurate.

Prepare the receiving endpoint

The receiver needs a publicly reachable HTTPS endpoint with a valid TLS certificate, a route that accepts POST requests, and logging for every inbound delivery. Plan for duplicate and out-of-order deliveries by making the handler idempotent, keyed on the record ID and the event time. Test it with a non-production instance before pointing production events at it.

Choose the signing key store

Webhook signature checking depends on a secret that both EspoCRM and the receiver hold. Decide where that secret lives before creation, such as a secrets manager your team already operates, and who may read or rotate it. Keep it out of source control and out of ticket comments, and document the rotation procedure, because replacing the key later requires coordinated changes on both sides.

Plan the event and retry handling

Before creating the first webhook, decide how the receiver responds to failed deliveries and how the team learns about them. Define an alert threshold, a dead-letter location for payloads that cannot be processed, and an owner for each subscription. Confirm the retry behavior in the documentation for your version, since EspoCRM's exact retry handling is not described in the topic facts and should be verified in your own tests.

Configure a webhook subscription step by step

This sequence takes a team from a locked-down API user to a verified, signed webhook that fires on the right record changes and nothing else. Each step ends with a check that proves the permission boundary and payload shape work before any production system relies on them.

  1. Create a dedicated API user

    An administrator creates a separate API user in EspoCRM for the webhook integration, rather than reusing a person's account or an admin account. Keep it distinct from users who work in the interface so its activity is traceable in logs and its access can be changed without affecting staff. Record who owns the user and which downstream system depends on it. The step is done when the user exists, is active, and is not a member of any team or role that grants broader access than the integration needs.

  2. Limit the role to subscribed entities

    Build a role for the API user that grants read access only to the entity types the webhook will subscribe to, such as Account or Opportunity, and nothing else. The EspoCRM webhooks documentation requires access to every entity type a subscription covers, so a missing permission will block events for that entity. Set record scope (own, team, or all) deliberately, since it determines which records generate events for this user. The check is a test request made as the API user against an entity outside the role, which should be rejected.

  3. Grant the Webhooks scope

    Add the Webhooks scope to the same role, because the API user cannot create subscriptions without it. Keep the scope limited to the integration's role so that no interactive user can manage webhooks by accident. Confirm the scope is saved by attempting a webhook request as the API user. If the request is accepted, the scope works; if it returns an authorization error, the role is missing the scope or the entity access from the previous step.

  4. Choose HMAC authentication for the API user

    Configure the API user with HMAC authentication, which the EspoCRM REST API documentation describes as the most secure of its supported methods. Basic authentication is documented as not recommended, so avoid it for any integration that writes or subscribes to events. Store the API key and secret in your secrets manager and restrict the user's access by IP address where your network allows. The check is a signed test request from the integration host that succeeds, followed by the same request with a wrong secret, which must fail.

  5. Create the webhook through the API

    Send a request as the API user to create the webhook, specifying the event name, such as Account.create or Account.update, and the target URL of the receiving system. The target should be an HTTPS endpoint you control, and the response returns the webhook record, including the secret key used to verify signatures. Store that secret in the receiving system before going further. The check is that the webhook appears in the list of webhooks with the expected event and URL, and that it is active.

  6. Fire a test event and inspect the payload

    Make a change to a non-production record, such as creating a test account and then updating it, and confirm the receiving endpoint logs a delivery. Compare the two payloads: according to the EspoCRM webhooks documentation, a create event sends all attributes, while an update event sends only the attributes that changed. Verify the receiving system checks the signature before it reads the body. The step closes when one create and one update delivery are logged with the payload shapes you expected.

  7. Add field-level subscriptions last

    Once entity-level events are verified, add field-level subscriptions in the form ENTITY_TYPE.fieldUpdate.FIELD, such as Account.fieldUpdate.assignedUserId, so the receiver is notified only when a specific field changes. Adding them last keeps any fault in the earlier steps easy to isolate. Test each field-level event with a change to that field and a change to another field, which should not trigger a delivery. Ask your EspoCRM administrator to confirm the event names against the version you run, since event support depends on the release.

Mapping events, payloads and API user permissions

This table compares the webhook event types EspoCRM can send, what each one carries, the names a receiver must handle, and the API user access each one needs. Read each row as a checklist for both the EspoCRM configuration and the receiving system's parser. The main takeaway is that a missing entity permission on the API user will silently stop a subscription from delivering the events you expect.

Event typeWhat the payload containsNames the receiver must expectAPI user access required
CreateAll attributes of the new recordEntity type name and every attribute of that entity, including empty fieldsWebhooks scope plus read access to the subscribed entity type
UpdateOnly the attributes that changedEntity type name and changed attribute names only, so missing fields mean unchangedWebhooks scope plus read access to the subscribed entity type
DeleteIdentifiers of the removed recordEntity type name and record identifier; confirm the exact fields in a test in your versionWebhooks scope plus access to the subscribed entity type
Field-level updateTriggered when one named field changesEvent name in the form ENTITY_TYPE.fieldUpdate.FIELD, for example Account.fieldUpdate.assignedUserIdWebhooks scope plus access to the entity type that owns the field
Loop prevention (skipOwn)Suppresses events the webhook owner initiatedNo change to payload; the receiver should still guard against repeat writesAvailable from version 9.2; confirm the version in your instance before relying on it
Entity without accessNo events delivered for that entitySubscription may appear configured but produce no deliveriesRead access to every entity type the subscription uses, checked for the API user's role

Choosing between entity events and field-level events

Entity-level subscriptions fit audit trails, search indexes and full synchronization to a downstream store, where the receiver needs to see every create, update and delete on an entity type. A create event sends all attributes of the record, which gives the receiver a complete starting copy. An update event sends only the attributes that changed, so the receiver must keep its own copy current and apply partial changes correctly. Broad subscriptions are the simplest to reason about because one rule covers the whole entity type.

  • Complete baseline: Create events carry the full record, so a new consumer can seed itself without a separate export.
  • Partial updates: Update events carry only changed attributes, so merge logic must not overwrite fields that were absent from the payload.
  • Delete handling: Subscribe to delete events explicitly if the downstream copy must be removed or archived.
  • Permission coverage: The API user needs the Webhooks scope and access to every entity type it subscribes to, so a broad subscription also widens the user's role.
  • Volume: Busy entities such as activity or email records generate far more events than master records.

Before you choose entity-level subscriptions, confirm with your team which entity types truly need mirroring and whether the receiver can handle the peak event volume.

Verifying signatures and hardening the receiver

A webhook receiver is an internet-facing endpoint that accepts changes from your CRM, so it needs to prove each request is genuine before it acts on it. The cards below cover signature checking, freshness, network limits, the API user that sends events, and where the secret lives. Together they decide whether a forged or replayed request can change your downstream systems.

Verify the signature before trusting the payload

Compute the expected signature over the raw request body using the webhook secret key, then compare it with the signature header EspoCRM sends. Reject any request that fails this check before parsing the body or writing anything. Confirm the exact header name and algorithm in the webhooks documentation for your EspoCRM version, since your receiver must match them exactly. Use a constant-time comparison so the check does not leak timing information.

Reject unsigned and stale requests

Treat any request without a signature, with a malformed signature, or with an event timestamp outside your accepted window as invalid. Stale requests are the usual route for replaying a captured valid payload later. Ask the vendor or your own tests whether timestamps are included in the signed content and how your receiver should handle clock skew between servers. Log rejections with source address and event type so repeated failures are visible.

Restrict the endpoint by network origin

Where your network design allows it, accept webhook traffic only from the EspoCRM server's outbound address or from a dedicated egress range. Enforce this at the reverse proxy or firewall, not only in application code. IP restriction is a second layer, not a replacement for signature checks, because addresses can change when EspoCRM moves hosts or sits behind a NAT. Confirm the source addresses with your team before you apply the rule.

Authenticate the API user with HMAC

The API user that EspoCRM uses to manage webhook subscriptions and read records should authenticate with HMAC, which the EspoCRM API docs describe as the most secure option among the supported methods. Basic authentication is not recommended. Keep the API user's role limited to the Webhooks scope and the entity types it actually needs, so a compromised key cannot read or change data beyond that scope.

Keep admin accounts out of integrations

Do not create webhook subscriptions or API credentials under a administrator account used for daily work. Use a dedicated, non-interactive API user with its own role, and review its permissions whenever a new subscription is added. The EspoCRM security guidance also recommends avoiding admin accounts for daily work and limiting token lifetime, so apply the same discipline to integration identities. Document who owns each API user and which systems depend on it.

Store the secret outside the configuration files

Keep the webhook secret key in a secrets manager or a restricted environment variable on the receiver side, not in a file that is committed to version control or copied into shared runbooks. Rotate the secret on a schedule you define and after any staff change, then confirm the receiver accepts the new value before retiring the old one. Restrict read access to the receiver's service account and to the people who operate it.

Why webhook deliveries fail or go missing

This table lists the failure patterns that most often stop EspoCRM webhooks from reaching a receiver, with the cause and fix for each. Read it before go-live and again when a receiving system reports missing or duplicate events. Confirm retry behavior in the EspoCRM webhooks documentation for your installed version, because retry handling is not something to assume.

FailureLikely causeFix
Webhook never firesThe API user lacks the Webhooks scope in its roleGrant the Webhooks scope to the API user, then create a test record and confirm the event arrives
Some events silently skippedThe API user cannot access every entity type it subscribes toGive the API user read access to each subscribed entity type, and test with a record the user can and cannot see
Field-level event missingThe subscription uses the wrong ENTITY_TYPE.fieldUpdate.FIELD name or the field did not actually changeCheck the exact entity and field name, and change the field value in the test to confirm the event fires
Receiver times outThe receiving endpoint responds slowly, so the delivery is treated as failedAcknowledge quickly, queue the payload for processing, and keep heavy work out of the HTTP handler
Signature check failsThe secret key was rotated or copied incorrectly, so the receiver computes a different signatureUpdate the stored secret on the receiver, verify against the raw request body, and retest after every change
Duplicate records downstreamRetries or repeated updates arrive again, and the receiver has no idempotency keyStore processed event identifiers and skip repeats, so each event applies only once
Events stop or arrive lateBackground jobs are not running because cron or the scheduled task is missing or stalledConfirm cron runs on the schedule the server configuration requires, and check job logs after each change
Own changes echo backThe webhook owner's own updates trigger the subscription againUse skipOwn where your version supports it (as of version 9.2), and confirm the parameter in the docs for your release

Questions buyers ask before outsourcing EspoCRM webhook work

What drives the effort of an EspoCRM webhook integration?

Effort rises with four things: how many entity types and field-level events you need, how many receiving systems consume them, how much transformation each receiver needs, and how carefully failures must be handled. A single entity with create and update events sending to one endpoint is a small job. Several entities, field-level triggers on fields such as assigned user, multiple receivers with different payload shapes, and a requirement to retry safely and alert on failures multiply the design, build and test work. Ask the partner to break the estimate down by entity, event type, receiver and error path so you can see which items you can reduce.

Can our team build EspoCRM webhooks without a partner?

Often yes, if you have an engineer comfortable with REST APIs, HTTP signing and queue-based retry logic, and someone who knows the CRM data model well. The EspoCRM webhook docs cover subscription through the API, the difference between create and update payloads, and field-level events such as Account.fieldUpdate.assignedUserId. The harder parts are usually outside the CRM: idempotent receivers, dead-letter handling, monitoring and agreeing on payload contracts with the teams that own each receiving system. If those skills are thin in-house, a fixed-scope engagement can cover design and build while your team takes over operations.

What do we need to provide before the work starts?

Plan to provide a dedicated EspoCRM instance or test environment, an administrator who can create API users and roles, and named owners for each receiving system who can confirm payload needs and test endpoints. You will also need representative test records covering the entities and field changes in scope, plus a decision on where secrets are stored. The API user needs the Webhooks scope and access to every entity type it subscribes to, so the CRM owner must agree on those permissions up front. Missing endpoint owners are the most common cause of delay.

How long does an EspoCRM webhook project usually take?

Duration depends on scope, not on a fixed figure. The main variables are the number of entities and events, how many receivers must be built and tested, how much error handling and monitoring you require, and how quickly your receiving teams can review payloads and test in their own environments. Ask for a timeline in the written scope with milestones for payload design, a first working subscription, receiver testing and cutover. Timelines that do not name the receiving-system owners and their review windows are usually optimistic.

Does DeployOpen issue certifications for webhook security?

No. DeployOpen does not issue audit reports, attestations or certifications. For webhook work, DeployOpen can design and implement signature checking with the secret key, document the flow, prepare logs and evidence of delivery and failure handling, and support readiness work for compliance assessments. Independent auditors and certification bodies perform any formal assessment. Ask your auditor which evidence they will want to see, such as access control for API users and records of configuration changes, and include that in the scope.

What does a fixed-scope quote for this work cover?

A fixed-scope quote follows from a written scope agreed before work starts. It should list the entities and events in scope, each receiving system and its payload requirements, the signature and authentication design, the error handling and retry approach, permissions for API users, testing and cutover steps, documentation and handover, and what is excluded. Each item should name who does what, including what your team must provide. Ask whether the quote includes post-launch support and whether ongoing monitoring or upgrade work is priced separately as a retainer.

What should we ask about security and API user permissions?

Ask how the API user will be scoped and how the secret key will be stored and rotated. The EspoCRM docs describe HMAC as the most secure API authentication method and advise against basic authentication, so confirm the method your design uses. Ask who can read webhook configuration, how receivers verify signatures before processing, and how the skipOwn parameter (available as of version 9.2) will be used to avoid loops. Confirm your EspoCRM version supports every feature in the design before committing to scope.

How DeployOpen scopes and delivers EspoCRM webhook integrations

DeployOpen plans, builds, tests and hands over EspoCRM webhook integrations inside your own infrastructure, starting from a written scope that names each event, receiving system and API user. Engagements are fixed-scope, so the subscriptions, signature checks, retry handling and access rules are agreed before any build work starts.

How we scope

  • We list every entity type and event your receiving systems need, including create, update and field-level changes such as assignedUserId.
  • We document which fields each receiving system needs, since update events carry only changed attributes.
  • We confirm the EspoCRM version and the API user, Webhooks scope and entity permissions the integration will depend on.

How we build

  • We create webhook subscriptions through the API, keeping each subscription tied to a dedicated API user with least-privilege roles.
  • We implement signature verification with the secret key on the receiving side and test rejection of unsigned or altered payloads.
  • We design error handling and retry behavior for failed deliveries, and test how the integration behaves when a receiver is offline.

How we hand over

  • You receive subscription definitions, API user roles, signature check code and a runbook describing each event flow.
  • We document the retry and failure paths, with the steps your team takes when deliveries stop or a secret must be rotated.
  • We walk your engineers through the test cases so they can repeat verification after changes to EspoCRM or the receiving system.

How we support

  • Ongoing support, upgrades and continuous testing are available as retainers, so changes to EspoCRM versions can be checked against your subscriptions.
  • Upgrade planning covers event behavior changes, such as skipOwn handling introduced in version 9.2, before your production instance is changed.
  • Support scope, response expectations and any SLA are written into the retainer agreement, which you should confirm before signing.

Talk to our team.

Tell us what you're working on, whether it's a deployment, an audit, a security test or a cyber range. You'll speak with an engineer who can help you scope it.

  • 30-minute call: free, with no obligation.
  • NDA on request: we can sign before you share details.
  • Clear next steps: a scope and plan after the call.