• Use Cases
  • Pricing
  • Security
  • Docs
Sign InStart free

The outbound integration layer for SaaS products: emit once, then let Meshes handle routing, retries, fan-out, and delivery history.

© Copyright 2026 Meshes, Inc. All Rights Reserved.

About
  • About
  • Security
  • Blog
  • Contact
  • FAQ
Product
  • Pricing
  • Demo
  • Integrations
  • Guides
  • Changelog
  • Status
Compare
  • All comparisons
  • Build vs buy
  • vs Paragon
  • vs Merge
  • vs n8n
  • vs Zapier
  • vs Make
Use Cases
  • All use cases
  • Embedded CRM sync
  • Per-tenant Slack
  • HMAC webhooks
  • Multi-env workspaces
  • Payment failed
  • User signup fan-out
  • Churn prevention
  • Trial expired events
Developers
  • Documentation
  • Agents
  • Tools
  • API Reference
  • MCP Server
  • llms.txt
Legal
  • Terms of Service
  • Privacy Policy
  • Acceptable Use Policy
  • Cookie Policy

Changelog

What's new in Meshes

July 9, 2026New

Re-emit Events with Payload Editing

Cover Image for Re-emit Events with Payload Editing
June 29, 2026Improvement

Integration Setup and Delivery Improvements

June 27, 2026Improvement

More Precise Outcome Codes Across Integrations

The June observability update gave delivery attempts a shared outcome-code vocabulary across integrations. This follow-up makes those codes more precise in cases that were still too broad, so failed deliveries are easier to triage from the event detail page and API.

More specific failed-attempt labels

Several destination responses now land on more specific outcome codes. A throttled request reports rate_limited, a missing destination record reports destination_not_found, invalid mapped fields report validation_failed, and expired credentials report auth_failed.

That precision makes it easier to compare delivery behavior across a workspace. Support teams can answer why a customer-facing integration failed, and product teams can build dashboards or alerts around actionable outcomes instead of broad error categories.

Clearer destination responses

Common destination responses that previously appeared as broad client errors now report more specific outcomes, so the event detail page points closer to the action needed: fix a field value, reconnect credentials, retry after throttling, or update a missing destination reference.

The result is less guesswork when reviewing failed attempts. The attempt history shows the delivery status, the outcome code, and the destination response details where available, so a rejected event can be triaged from the dashboard or API without reproducing the delivery first.

For API consumers

The outcome-code enum remains additive from the June observability release. Existing clients that already handle the published values do not need a schema change, but clients that group errors by destination should see more failed attempts land in the most specific available category.

Learn more

  • API Reference
  • Core Concepts
June 13, 2026Improvement

Granular Outcome Codes for Delivery Attempts

The per-attempt observability launch in May gave every delivery attempt a structured outcome code. This update makes those codes considerably more precise: outcome codes now reflect the destination's actual response, seven new codes cover the most common rejection modes, and failed attempts keep the provider's own error detail for inspection.

Seven new outcome codes

The outcome vocabulary grows from nine to sixteen codes. The new additions distinguish rejection modes that previously landed in the generic client-error bucket:

  • invalid_request — the destination rejected the request as malformed
  • validation_failed — the destination rejected one or more field values
  • destination_not_found — the target resource no longer exists at the destination
  • destination_conflict — the request conflicted with current destination state
  • destination_gone — the destination reported it is permanently gone
  • destination_timeout — the destination reported a request timeout
  • payload_too_large — the destination refused the payload size

These join the existing delivered, rate_limited, auth_failed, timeout, network_error, mapping_error, rejected_client_error, rejected_server_error, and internal_error codes. The attempt drill-down on the event detail page renders all sixteen.

Codes that reflect the destination's response

Outcome codes previously reported the broad category of a failure, so many distinct rejections looked the same. They now reflect the destination's actual HTTP response — the real status code plus the provider's own error code. A missing HubSpot list shows as destination_not_found, a rejected field value as validation_failed, a throttled request as rate_limited, and so on.

Every integration maps its destination's responses to the same shared vocabulary, so a rate_limited from HubSpot means the same thing as a rate_limited from a custom webhook — one set of codes to build dashboards and alerting against, regardless of where the event was headed.

Provider error detail on failed attempts

When a delivery fails, the attempt now records a structured response: the HTTP status, the provider's own error code (for example, the error category HubSpot returns), and the destination's response body. The response details view in the attempt drill-down shows exactly what the destination said, so debugging a rejected delivery no longer requires reproducing the call yourself. Response details remain permission-gated the same way as before.

May 21, 2026New

Per-Attempt Visibility on Event Deliveries

Cover Image for Per-Attempt Visibility on Event Deliveries

When a product event lands in a destination, you should know exactly what happened — not just whether it ended up green or red. This release turns every event in Meshes into a full delivery story, attempt by attempt, with the controls to act on what you find.

Every attempt, in context

Open any event in the dashboard and each routing rule now expands inline to show the full attempt history. You can see the order things happened in, how long each attempt took, what the destination said, and which attempt finally succeeded or what is still being retried. Failed attempts that captured a response from the destination expose that response on demand, so debugging a flaky webhook or a misconfigured CRM no longer means digging through your own logs to figure out what Meshes saw.

Outcomes that explain themselves

Attempts now carry a structured outcome — delivered, rate limited, auth failure, timeout, server error, and others — so you can tell apart a transient destination blip from a credential problem from a mapping mistake at a glance. The same outcome flows through the API, so dashboards, automations, and support tooling can react to specific failure modes instead of treating every red row the same. The full list of outcome codes is in the API reference.

Status that tells you what to expect

Event and rule status now distinguishes work that is actively being retried from work that has stopped. Retrying means a previous attempt failed but Meshes will try again; canceled means delivery has been stopped on purpose and will not resume. Combined with the new countdown that shows when the next attempt will fire, you always know whether an event is making progress or sitting still.

Take action without leaving the page

Two new controls live directly on the event detail page:

  • Cancel stops further delivery for one rule or for the whole event in a single click. In-flight requests are allowed to finish; nothing new is scheduled afterward.
  • Retry now fires the next attempt immediately for a rule that is in a retry loop, so you can confirm a fix without waiting for the next scheduled backoff.

Both actions require workspace edit permission. Per-rule cancel and retry-now are available in embedded Meshes experiences your customers see in your own product; event-scope cancel stays inside your team's own dashboard.

Why this matters

  • Support gets faster. Front-line teams can answer "did our event reach HubSpot?" without escalating to engineering.
  • Customers trust the integration. When something does go wrong, the dashboard shows exactly which attempt failed, why, and when the next one will run.
  • You stay in control. A bad destination, a stuck rule, or a runaway retry no longer requires a deploy or a support ticket — it is a click on the event detail page.
May 5, 2026New

Pipedrive Integration

Cover Image for Pipedrive Integration

Pipedrive is now available as a Meshes destination. Connect a Pipedrive account with OAuth and route product events into Person records and labels without building a separate Pipedrive sync path in your app.

What it does

The Pipedrive integration focuses on Person updates driven by the events you already send through Meshes.

  • Sync Person creates or updates a Pipedrive Person by email.
  • Update Person Field syncs the mapped Person data and sets one supported editable Person field from the connected account.
  • Add Label to Person and Remove Label from Person sync the mapped Person data and keep Person labels aligned with lifecycle and product status changes.
  • Meshes loads the connected account's Person field catalog and label list so mappings reflect the actual Pipedrive workspace, including supported custom fields.

Example workflow

A trial.started event can create or update the Person in Pipedrive, set a lifecycle custom field, and add a Person label for the trial state. From there, Pipedrive automations can handle follow-up tasks, deal routing, or campaign enrollment based on those Person updates.

Get started

Create a Pipedrive connection, add a rule for the event you want to send, choose the Person action that fits the workflow, and map the fields Meshes should write. Use Send Test Event to verify the Person update before turning the rule on. See the Pipedrive docs for setup and mapping details.

April 16, 2026New

Customer.io Integration

Cover Image for Customer.io Integration

Customer.io is now available as a Meshes destination. Use it to identify people, sync customer traits, and track behavioral events from the product events your app already emits to Meshes.

What it does

The Customer.io integration helps lifecycle, growth, and product teams keep Customer.io profiles and campaigns aligned with real product activity.

  • Identify profiles with userId, email, or anonymousId.
  • Send additional payload fields as Customer.io traits.
  • Track behavioral events with the Meshes event name or an optional event_name_override.
  • Connect with a Customer.io CDP API Key.
  • Choose the US or EU Customer.io region for the connection.

Example workflow

A user.signup event can identify the new profile in Customer.io, attach traits like email, plan, and first_name, and record the signup event so Customer.io campaigns and segments can react to it.

Get started

Create a Customer.io connection, add a rule for the event you want to send, map the identity fields, and use Send Test Event to verify the delivery. See the Customer.io docs for the setup flow and field mapping details.

April 4, 2026New

Discord Integration

Cover Image for Discord Integration

Discord is now available as a connection type in Meshes. Add the Meshes bot to your Discord server, pick the destination channel in the rule builder, configure an embed title and message template, and Meshes handles delivery with retries.

Channel-aware rule setup

Each rule targeting a Discord connection includes a live channel picker backed by the connected server. After the bot is authorized, Meshes loads the available text and announcement channels so you can route each event to the right destination without hardcoded channel IDs.

Embed titles and templated message delivery

Discord rules use a required embed title plus a message template with {{field}} interpolation. When an event fires, Meshes renders the title and body from the event payload and posts a rich embed to the selected channel.

Example rule values:

Title: Payment failed

Template:

Customer: {{customer.email}}
Plan: {{plan}}
Retry at: {{retry_at}}

Templates support nested field access such as {{user.name}}, so Discord notifications can stay concise while still carrying the product context your team needs.

How it works

  1. Connect Discord from the Connections page and authorize the Meshes bot for your server
  2. Create a rule targeting the Discord connection
  3. Select a channel, set the embed title, and write the message template
  4. Meshes renders the embed, delivers it to Discord, and retries transient failures automatically

Discord is the latest supported integration, joining HubSpot, Salesforce, Intercom, Mailchimp, ActiveCampaign, Resend, Zoom, AWeber, MailerLite, Slack, and Webhooks.

April 4, 2026New

SendGrid Integration

Cover Image for SendGrid Integration

SendGrid is now available as a connection type in Meshes. You can connect a SendGrid account with an API key, select a Dynamic Template in the rule builder, or send an inline HTML email directly from the event that should trigger the message.

This integration supports two actions: Send Email (Template) for SendGrid Dynamic Templates and Send Email for inline HTML delivery. That means welcome emails, trial onboarding prompts, billing confirmations, and other transactional sends can all run from the same product events you already route to the rest of your stack.

No custom SendGrid worker is required. Create the connection in Connections -> New Connection -> SendGrid, add a rule for the event you care about, map email plus any template_variables you need, and Meshes handles the delivery path.

March 30, 2026New

ActiveCampaign Sync Contact Action

ActiveCampaign connections now support a Sync Contact action alongside the existing list and tag actions.

Sync Contact creates or updates the contact record in ActiveCampaign using the fields mapped in your Meshes rule. Unlike the list and tag actions, it does not require selecting a target list or tag — the mapped fields are the entire operation. This is useful when the goal is keeping contact data current without triggering list-based or tag-based automation.

When to use it

  • Keep ActiveCampaign contact properties up to date from product events without subscribing the contact to a list.
  • Upsert contacts with custom field values before a separate rule handles list or tag assignment.
  • Sync profile data like name, phone, or custom fields from events where the only goal is a contact record update.

How it works

  1. Open Rules and create a new rule.
  2. Select your ActiveCampaign connection and choose Sync Contact.
  3. Map the event fields to ActiveCampaign contact fields. The mapping catalog includes core fields (email, firstName, lastName, phone) and custom fields from the connected account.
  4. Save the rule and send a test event to verify the contact is created or updated.

email is required for all ActiveCampaign contact actions, including Sync Contact.

Learn more

  • ActiveCampaign integration docs
  • Integrations overview
March 27, 2026New

Webhook Authentication, HMAC Signing, and Delivery Controls

Cover Image for Webhook Authentication, HMAC Signing, and Delivery Controls

Meshes webhooks are no longer config-only. Every webhook connection now supports authenticated, signed delivery with full control over how the request reaches your endpoint.

Authentication

Attach credentials to every webhook request. Choose from:

  • None — no auth headers
  • Basic Auth — Authorization: Basic header from a username and password
  • Bearer Token — Authorization: Bearer header
  • Custom Header — any header name and value, such as X-API-Key

All credentials are encrypted at rest and never returned in plaintext after they are saved.

HMAC payload signing

Enable HMAC-SHA256 or HMAC-SHA512 so your endpoint can cryptographically verify that every request body came from Meshes and has not been tampered with. The signature is computed from the exact bytes sent and attached in a configurable header (default X-Meshes-Signature). Signing is independent of authentication — use both together for defense in depth.

Custom headers

Add up to five static headers to every request for routing keys, tenant identifiers, or any metadata your endpoint expects.

Payload format

Choose Wrapped to send the full Meshes event envelope, or Raw to send only the payload object. In raw mode, event metadata is promoted to X-Meshes-* HTTP headers so your endpoint can still access the event ID, name, resource, and timestamps.

HTTP method

Select POST, PUT, or PATCH per connection. The default is POST.

Learn more

  • Webhook integration docs
  • Integrations overview
March 22, 2026Improvement

Resource-Scoped and Dashboard-Only Embed Sessions

Cover Image for Resource-Scoped and Dashboard-Only Embed Sessions

Meshes embed sessions now support two new additive access shapes on top of the existing workspace session model.

What is new

  • Resource sessions lock the iframe to one resource + resource_id pair
  • Dashboard sessions expose a read-only dashboard-only embed
  • launch_page replaces raw launch paths with a small initial-page enum
  • Server-side enforcement now keeps resource and dashboard sessions constrained even when a token is used directly against the API

What resource sessions can do

  • launch into dashboard, rules, or events
  • view only in-scope rules and events
  • create rules and emit or retry events only inside the locked resource scope
  • open matching Event Detail when the event belongs to that resource pair

What dashboard sessions can do

  • launch into dashboard
  • read dashboard shell data and dashboard metrics
  • stay read-only and dashboard-only

What changed for integrators

  • use launch_page instead of raw route strings
  • choose session_type when minting a session
  • send resource and resource_id only for resource sessions

Learn more

  • Embed overview
  • Session API overview
  • Workspace pages available in embed
March 15, 2026New

Embedded Workspaces with Session-Based Access

Cover Image for Embedded Workspaces with Session-Based Access

You can now embed key Meshes workspace pages directly inside your own product with session-based access and an iframe-ready launch flow.

This release adds a new embedded workspace surface for teams that want to expose integrations to their own customers without sending them to a separate admin app. Your backend mints a short-lived session, your frontend mounts the returned launch_url, and the embedded experience handles refresh, navigation, and resizing through a small postMessage contract.

What is included

  • Embedded workspace pages for dashboard, connections, rules, events, event detail, and connection mappings
  • Session minting and refresh with POST /api/v1/sessions and POST /api/v1/sessions/:sessionId/refresh
  • Launch URLs for iframe bootstrap
  • Iframe messaging for ready, auth, refresh, expired, navigation, and resize events
  • Scoped payload access with the events.payload:read session scope

What this unlocks

  • expose customer-specific integration settings inside your own app
  • keep access scoped to a single Meshes workspace
  • refresh embedded access without remounting the entire iframe
  • handle iframe height and token refresh from your host app

Typical integration flow

  1. your backend mints a session for the correct workspace
  2. your frontend mounts the returned launch_url
  3. the iframe sends meshes:ready
  4. your frontend sends meshes:auth with the current access_token
  5. your frontend refreshes the session when the iframe asks for a new token

Learn more

  • Embed overview
  • Embed quickstart
  • Session API overview
  • Iframe message contract
March 7, 2026New

Slack Integration

Cover Image for Slack Integration

Slack is now available as a connection type in Meshes. Connect your Slack workspace via OAuth, pick a destination channel, configure a message template, and Meshes handles delivery with retries.

Templated messages

Each rule targeting a Slack connection includes a message template with {{field}} interpolation. When an event fires, Meshes renders the template with the event payload and posts to the configured channel.

Example template:

🎉 New signup: {{email}}
Plan: {{plan}}
Source: {{source}}

Templates support Slack markdown formatting and nested field access via dot notation (e.g., {{user.name}}). Missing fields render as empty strings rather than broken template syntax.

How it works

  1. Connect your Slack workspace from the Connections page
  2. Create a rule targeting the Slack connection
  3. Select a channel and write your message template
  4. Meshes routes matching events to Slack with automatic retries

Slack is the latest supported integration, joining HubSpot, Salesforce, Intercom, Mailchimp, ActiveCampaign, Resend, Zoom, AWeber, MailerLite, and Webhooks.

March 6, 2026New

Textarea Field Type for Rule Configuration

Rule actions now support a textarea field type for multiline input. This powers Slack's message template editor and is available for any integration that needs multiline configuration in rule setup.

Previously, rule action fields only supported single-line text and password inputs. The new textarea type renders a resizable monospace text area in the rule configuration form - useful for templates, message bodies, or any structured text input.

This is a platform-level change, not specific to Slack. Any integration can now define a kind: "field" action data entry with type: "textarea" and get multiline input in the rule form automatically.

March 1, 2026New

Meshes is Live

Cover Image for Meshes is Live

Meshes is now live with paid plans. Send product events from your app and route them to HubSpot, Salesforce, Intercom, Mailchimp, ActiveCampaign, Resend, Zoom, AWeber, MailerLite, and custom webhooks — with retries, deduplication, and delivery guarantees built in.

What you get

  • Fan-out routing — one event, multiple destinations, delivered in parallel
  • Automatic retries — exponential backoff with jitter, dead letter queues for failures
  • Field mappings — transform event payloads into the format each destination expects
  • Multi-tenant workspaces — isolate connections, rules, and credentials per customer
  • 10 integrations — CRMs, email platforms, messaging tools, and webhooks

Getting started

Sign up at meshes.io and send your first event in minutes. The Developer tier is free — 100 events/month, 1 workspace, 3 connections. Card required to activate your account.

Paid plans start at $49/mo (Builder) with annual pricing available with 2 months free.

When a delivery fails because the payload was wrong, retrying the same event just fails the same way again. And until now, the only way to send a corrected version was to go back to your own application and emit it from scratch. This release adds Re-emit: create a new event from an existing one — with the stored payload or an edited one — directly from the event detail page or the API.

A new event, not another retry

Retry now re-runs a delivery of the same event. Re-emit is different: it creates a brand-new event with its own event ID, its own rule matching, and its own delivery attempts. The original event's payload, rules, and attempt history stay exactly as they were, so the record of what happened is never rewritten.

Re-emit works on an event in any state — completed, failed, canceled, or still retrying. You do not have to wait for an event to exhaust its retries before sending a corrected version; if you can already see what went wrong, you can act on it immediately.

Fix the payload before it goes out

The re-emit dialog shows the stored source payload and lets you edit the JSON before submitting, or leave it unchanged to reuse the original. A payment.failed event that was rejected because cus_greyjoy shipped with a malformed email can go back out with the corrected value in seconds — no code change, no redeploy. Edited payloads are validated the same way as ordinary event ingestion before the new event is accepted.

Optionally stop the original

The dialog includes an Also cancel remaining attempts option. When selected, any deliveries on the original event that have not yet finished are canceled after the new event is accepted — in-flight requests are allowed to complete, and deliveries that already reached a final state are untouched. If some cancellations do not go through, the dashboard tells you exactly how many, so nothing fails silently.

Provenance you can follow

Both events link to each other on the event detail page: the source event shows Re-emitted as links to every event created from it, and each new event shows a Re-emitted from link back to its source. The same provenance is available in the API as re_emitted_from and re_emitted_as on the event, so support tooling can walk the chain too. A single event can be re-emitted up to 100 times.

Available in the dashboard, embeds, and the API

  • Dashboard: the Re-emit button appears on event detail for members with workspace edit permission.
  • Embedded experiences: workspace and resource sessions can re-emit from the embedded event detail page when the session has edit access and the events.payload:read scope. Resource sessions can re-emit only events within their resource scope, and the new event keeps that same scope.
  • API: POST /api/v1/events/{event_id}/re-emit accepts an optional payload override and an optional cancel_remaining flag, and returns the newly created event along with a cancel summary when cancellation was requested.

Re-emitted events are processed like any other event you emit — they go through normal rule matching and deduplication, and they count toward your plan's event volume.

Learn more

  • API Reference
  • Core Concepts

Two small improvements make integration setup and delivery recovery easier to reason about: Salesforce setup now calls out the package requirement earlier, and manual retries keep the visible next-attempt countdown in place.

Clearer Salesforce setup

Salesforce admins can use the Meshes package install link before starting OAuth, and the Salesforce integration docs now explain the org-level package requirement during setup.

That extra setup context helps teams prepare the Salesforce org before connecting it to Meshes, with the package prerequisite visible before a connection is configured.

Retry now keeps the countdown

Using Retry now on a rule in a retry loop no longer resets the next-attempt countdown shown on the event detail page. If the manual attempt fails, the countdown keeps pointing at the same upcoming automatic retry.

That keeps the recovery flow predictable. A manual retry can confirm whether a fix worked immediately, while the visible countdown remains stable if the destination is still unavailable or still rejecting the delivery.

Learn more

  • Salesforce integration docs
  • API Reference

Fetch a single rule execution from the API

A new endpoint, GET /api/v1/events/{event_id}/rules/{rule_id}, returns one rule execution for an event — status, attempt count, outcome, and next-attempt timing — without fetching the whole event. It is useful for polling a specific delivery after a retry, and it is available to embedded workspace and resource sessions with the same scoping as the event detail page.

For API consumers

The new outcome codes are additive to the outcome_code enum — existing responses still parse. Consumers that switch exhaustively on outcome codes should add branches for the seven new values. Attempts written before this release keep the codes they were recorded with.

Learn more

  • API Reference
  • Core Concepts

For API consumers

The event and rule status enums now include retrying and canceled in addition to the existing values. The change is additive — existing responses still parse — but consumers that do an exhaustive switch on status should add branches for the two new values. Attempts written before this release do not carry an outcome code, so SDK clients should treat that field as optional.

Learn more

  • API Reference
  • Embed overview