How to test webhooks in the Synthetic Data (Sandbox) environment

Updated:


November 5, 2026

Unified's Synthetic Data environment (called Sandbox in the API) gives you test connections filled with realistic sample data, without needing a real account with the integration. You can create webhooks on these connections to build and test your webhook handler before going live.

This guide covers doing that from the Unified app, the API and the Unified MCP server.

How webhooks behave in Synthetic Data

Before you start, here's what's different from Production:

  • Only virtual webhooks are supported. Native webhooks rely on the integration pushing events to Unified, and there's no real integration behind a Synthetic Data connection. Virtual webhooks poll the connection on an interval and send you any new or changed records, so they work the same way they do in Production.
  • Sample data doesn't change on its own. Synthetic Data is generated once when you activate the integration. To receive created or updated events, create or update records yourself through the API on that connection (see Generate events).
  • Payloads contain the integration's supported fields only. Each record includes the fields that integration supports for that object, the same as in Production. You can narrow this further with the webhook's fields setting.
  • raw is always empty ({}), because there's no response from a real integration.
  • Events that only support native webhooks can't be tested here. If an object or event is native-only for an integration, you'll need a real connection to test it.

💡 Virtual webhooks require a paid plan. If you use an environment-restricted API key, it must have access to the Sandbox environment.

What you'll need

  • A Unified workspace on a plan that includes virtual webhooks
  • A publicly reachable URL for your webhook handler. If you're developing locally, use a tunnel such as ngrok or npx localtunnel --port <port>.
  • Your workspace API key (for the API and MCP options)

Step 1: Create a Synthetic Data connection

In the app

  1. Use the environment switcher to change to Synthetic Data.
  2. Go to Integrations, open the integration you want (for example HubSpot) and activate it. You don't need to configure credentials; they're mocked in Synthetic Data. Activating it generates the sample data.
  3. Go to Connections and click Create test connection, then pick the integration.

image.png

image.png

With the API

Activate the integration in the Synthetic Data environment from the app first, then create a connection with environment set to Sandbox. No auth is needed:

curl -X POST https://api.unified.to/unified/connection \
  -H "Authorization: Bearer $UNIFIED_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "integration_type": "hubspot",
    "environment": "Sandbox",
    "categories": ["crm"],
    "permissions": ["crm_contact_read", "crm_contact_write"]
  }'

Save the returned id: that's your connection_id.

With the MCP server

Connect your AI client to https://api.unified.to/mcp with Authorization: Bearer <your workspace API key>, then ask it to create the connection. It uses the create_unified_connection tool with environment: "Sandbox".

Step 2: Create a virtual webhook

In the app

  1. Go to Webhooks and create a new webhook.
  2. Select your Synthetic Data connection.
  3. Pick the object and event, and make sure you choose the option with the yellow Virtual badge. Native options won't work in Synthetic Data.
  4. Enter your webhook URL.
  5. Optional settings:
  • Interval: how often to check for changes (as low as 1 minute on paid plans).
  • Included fields: limit the payload to specific fields. Leave all unchecked to receive every supported field. raw isn't included by default, and it's empty in Synthetic Data anyway.
  • Include all / initial sync: send the existing sample records when the webhook starts.
  1. Save.

image.png

With the API

curl -X POST "https://api.unified.to/unified/webhook?include_all=true" \
  -H "Authorization: Bearer $UNIFIED_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "connection_id": "<your_connection_id>",
    "object_type": "crm_contact",
    "event": "created",
    "hook_url": "https://your-server.example.com/webhook",
    "webhook_type": "virtual",
    "interval": 1
  }'
  • Always set "webhook_type": "virtual" on Synthetic Data connections. If you leave it out, the default can be native for some integrations, and the request is rejected with "Cannot create native webhooks in Sandbox environment".
  • include_all=true sends the existing sample records on the first run, so you'll get a payload straight away. Leave it out to receive only new changes.

With the MCP server

Ask your AI client to create a virtual webhook for the connection. It uses the create_unified_webhook tool with the same fields as the API (connection_id, object_type, event, hook_url, webhook_type: "virtual", interval). You can check it with list_unified_webhooks or get_unified_webhook.

Step 3: Check that your endpoint is reachable

In the app, open the webhook and click Send test event. Unified sends your URL a payload with an empty data array and an x-unified-test: true header, and shows you the status code your server returned. This checks connectivity and signature handling only; it doesn't send sample records.

Step 4: Generate events

Because Synthetic Data doesn't change on its own, create or update records on the same connection to produce events:

# created event
curl -X POST https://api.unified.to/crm/<connection_id>/contact \
  -H "Authorization: Bearer $UNIFIED_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "name": "Test Contact", "emails": [{ "email": "test@example.com" }] }'

# updated event
curl -X PUT https://api.unified.to/crm/<connection_id>/contact/<contact_id> \
  -H "Authorization: Bearer $UNIFIED_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "title": "Updated title" }'

With the MCP server, use the connection's tools (for example create_crm_contact or update_crm_contact), or just ask your AI client to create or update a record.

Step 5: Run the webhook now

You don't have to wait for the interval:

  • App: open the webhook and click Run now.
  • API: PUT https://api.unified.to/unified/webhook/{id}/trigger
  • MCP: the update_unified_webhook_trigger tool

Unified checks the connection for changes immediately and sends anything new to your URL.

What you'll receive

A webhook delivery looks like this:

{
  "data": [ { "id": "...", "name": "Test Contact", "emails": [ ... ], "raw": {} } ],
  "webhook": { "id": "...", "connection_id": "...", "object_type": "crm_contact", "event": "created", ... },
  "type": "VIRTUAL",
  "nonce": "...",
  "sig256": "..."
}
  • type is INITIAL-PARTIAL / INITIAL-COMPLETE while existing records are being sent (when you used include all), then VIRTUAL for later changes.
  • Verify sig256 with your workspace secret the same way you would in Production.

Troubleshooting

ProblemWhat to check
"Cannot create native webhooks in Sandbox environment"Choose the Virtual option in the app, or set "webhook_type": "virtual" in the API.
"... does not support webhook event ..."That integration doesn't support webhooks for this object or event. Try another object or integration.
"Virtual webhooks are not supported on your ... plan"Virtual webhooks need a paid plan.
"not authorized to access this environment"Your API key is restricted to another environment. Use a key with Sandbox access.
The webhook is created but nothing arrivesSample data is static. Create or update a record, then click Run now. If you didn't use include all, no existing records are sent.
Fields are missing from the payloadOnly fields the integration supports for that object are sent. Check the integration's supported fields, and the webhook's Included fields setting.
raw is emptyExpected in Synthetic Data: there's no real integration response.

Going to Production

When you're ready, create a connection in Production with a real account and recreate the webhook. In Production you can also use native webhooks where the integration supports them. Your handler code doesn't need to change: the payload format is the same.

Share
All guidesWebhooksWebhook modelVirtual webhooksAdvertising Report Metrics by IntegrationATS to Vector DB: How to Power Talent Intelligence with Real-Time DataBuilding AI applications with Unified and LangbaseConcur & Concur (Company) — Connection GuideConfigure Greenhouse Native Candidate WebhooksConnect Amazon Seller Central to Unified.toConnecting BambooHR via OAuth 2Connecting Google Workspace Integrations with a Service AccountCorrect WelcomeKit Scopes for Jungle IntegrationCreating Ads using the Unified Ads APICreating Walmart Items via UnifiedEnd-Users, Integrations, and ConnectionsEnriching Unified Objects with Custom MetadataEnterprise-managed authorization (EMA) with a static keyEnterprise-managed authorization (EMA) with a workspace secretEnterprise-managed authorization (EMA) with Microsoft Entra IDExtended observability — pushing API logs to ClickHouseExtended observability — pushing API logs to Grafana / LokiExtended Observability - Pushing API Logs to your Datadog InstanceFacebook Messenger Webhook SetupFireflies Integration GuideGetting started with WorkableHandling Delegated vs. Application Scopes in Microsoft IntegrationsHiBob & Unified: connection and time off guideHow long are logs retainedHow to access employees and usersHow to add API support for the Create Activity in CrelateHow to Associate a Connection ID with Your End-UserHow to build a Candidate Assessment product withHow to build a candidate sourcing or job board app with Unified.toHow to build a Discord support bot with Unified.to and LangbaseHow to Build a Fintech Application with Unified's Payments APIHow to Build an E-Commerce Product Integration with UnifiedHow to build an invoicing system with Unified.toHow to build Enterprise Search using RAGHow to configure Bullhorn Redirect URI for creating a connectionHow to configure webhooks in HubSpotHow to configure webhooks in Thrive LearningHow to configure webhooks in Toast for UnifiedHow to Connect Anthropic to Real-Time SaaS Data with Unified.to MCP ServerHow to Connect Cohere to Real-Time SaaS Data with Unified.to MCP ServerHow to Connect Google Gemini to Real-Time SaaS Data with Unified.to MCP ServerHow to Connect LLMs to Real-Time SaaS Data with Unified.to MCP ServerHow to Connect OpenAI to Real-Time SaaS Data with Unified.to MCP ServerHow to Connect Zoom and Zoom PhoneHow to create a Connection In Microsoft TeamsHow to create a token-based connection in HighlevelHow to Create a Unified.to Connection to HighLevelHow to Create a Xero Connection in Unified.toHow to create and configure webhooksHow to create Connection with HubspotHow to customize portal URLs for Stripe and GoCardlessHow to filter webhook eventsHow-to Get a Private Support Channel for Your Unified IntegrationHow to get help fromHow to get your 8x8 Connect API Key and Account ID: Step-by-step guideHow to get your ADP Workforce Now Oauth2 client ID, Oauth2 client secret, Oauth2 PEM certificate and Oauth2 private key: Step-by-step guideHow to get your Amazon S3 AWS Region, AWS S3 Key and AWS S3 Secret: Step-by-step guideHow to get your Ashby API Key: Step-by-step guideHow to get your Brex API token: Step-by-step guideHow to get your Bullhorn OAuth2 Client ID, OAuth2 Client Secret, API Username and API Password: Step-by-step guideHow to get your Ceridian Dayforce Username, Password and Client Namespace: Step-by-step guideHow to get your Crelate API key: Step-by-step guideHow to get your Dashlane API Key: Step-by-step guideHow to get your Deel Access Token: Step-by-step guideHow to get your Dialpad API Key: Step-by-step guideHow to get your Discord OAuth 2 credentials and bot tokenHow to get your ELMO client ID and client secret: Step-by-step guideHow to get your Gainsight Client ID, Client Secret and Gainsight API Domain: Step-by-step guideHow to get your Greenhouse API Key and Job board token: Step-by-step guideHow to get your Helpscout API Key: Step-by-step guideHow to get your HiBob Service User ID and Service User Token: Step-by-step guideHow to get your HighLevel API Key and Location ID: Step-by-step guideHow to get your HubSpot developer key and OAuth 2 credentials (Legacy Apps)How to get your Humaans API Key: Step-by-step guideHow to get your iCIMS API Username, API Password and Customer ID: Step-by-step guideHow to get your JobDiva Client ID, Username/email and Password: Step-by-step guideHow to get your Jobvite API Key, API Key Secret and Email: Step-by-step guideHow to get your Lever API Key: Step-by-step guideHow to get your Loxo Agency slug, API Key and Agency ID: Step-by-step guideHow to get your Microsoft Active Directory / Entra ID Client ID, Client Secret and Tenant ID: Step-by-step guideHow to get your Microsoft Azure AD OAuth 2 credentialsHow to get your OAuth 2 credentials for GmailHow to get your OAuth 2 credentials for Microsoft Dynamics 365How to get your OAuth 2 credentials in PipeDriveHow to get your OpenAI API Key: Step-by-step guideHow to get your Paycom SID/Username and Token/Password: Step-by-step guideHow to get your PCRecruiter Username, Password, Database ID, App Key and App ID: Step-by-step guideHow to get your SAP SuccessFactors (OpenID Connect) Username, Password, Client ID, Client Secret, Dependency Name, IAS Host and API URL: Step-by-step guideHow to get your SAP SuccessFactors Username, Company ID, Password and API URL: Step-by-step guideHow to get your Shopify Admin API access token and Store ID: Step-by-step guideHow to get your Wayfair Client ID, Client Secret and Vendor Encrypted Key: Step-by-step guideHow to get your Workable API Token and Subdomain: Step-by-step guideHow to get your yotpo APP Key / Store ID and Secret Key: Step-by-step guideHow to Handle Attachments in Invoice, Bill and Credit MemoHow to migrate or import your integrations into Unified.toHow to obtain your GitHub OAuth2 credentialsHow to Power Claude with Live Customer Data Using Unified MCPHow to receive assessment orders from an ATS with Unified.toHow to register a Google developer app and get OAuth 2 credentialsHow to register a Salesforce developer app and get OAuth 2 credentialsHow to register a Slack developer account and get OAuth 2 credentialsHow to Register a Workday Developer App and Get OAUTH2 CredentialsHow to Register a Workday Developer App and Get OAUTH2/ SOAP CredentialsHow to Register a ZendeskSell Developer App and Get OAUTH2 CredentialsHow to Register a Zoho Developer App and Get OAUTH2 CredentialsHow to Register an ADP Developer App and Get OAUTH2 CredentialsHow to Register an Atlassian Developer App and Get OAUTH2 CredentialsHow to Register your Facebook OAuth2 ApplicationHow to Register your Google Ads OAuth2 ApplicationHow to Register your MetaAds OAuth2 applicationHow To Request & Write Raw Integration DataHow to Retrieve Microsoft Dynamics 365 Business Central CredentialsHow to set up a custom API URL with a CNAMEHow to set up a HiBob marketplace installHow to Set Up a Microsoft Teams Bot with UnifiedHow to set up and configure NotionHow to set up Google Business Profile API access and get OAuth 2 credentialsHow to Set Up LinkedIn Webhooks with UnifiedHow to set up native webhooks for QuickBooks Online with UnifiedHow to set up Slack webhooks using event subscriptionsHow to set up Telegram (bot) with Unified.toHow to set up your scopes in HubSpotHow to setup a Freshbooks developer appHow to setup a TikTok Shop applicationHow to Setup AWS Assume Role for AWS Secret ManagerHow to setup Oracle JD EdwardsHow to Setup Quickbooks DesktopHow to setup Sage 100 with Unified.toHow to troubleshoot unhealthy connectionsHow to troubleshoot unhealthy webhooksHow to use SCIM with the Unified APIHow to use the Passthrough APIHow to Use Unified.to's Generative AI API with OpenAI and ClaudeHow to use User Provisioning and Verification with UnifiedHow virtual webhook retry and recovery worksIntegration set-up guide for LeverManaging custom validation rules in SalesforceNetSuite Authentication Setup for UnifiedNotice of Deprecation of Fields and Objects (Nov 2025)Oracle HCM / Taleo OAuth Credentials GuideRetrieval-Augmented Generation (RAG)SalesForce (External Client Apps) on Multiple OrganizationsSAML Single-Sign-OnScaling MCP Tools with Anthropic's (& OpenAI's) Defer LoadingSet Environments for your Unified.to WorkspaceSetting up a Slack Bot Connection with Unified.toSetting up OAuth 2 Credentials for Greenhouse's APIsTrello Connection Guide in UnifiedUnderstanding OAuth2 Authorization flowsUnderstanding Response Time Headers in the Unified APIUnified Assessment API: Embed Assessments Inside ATS PlatformsUnified's MCP ServerUnified MCP Server with LangChain and LangGraphUnlock real-time data with virtual webhooksUse Unified to sign in your users into your applicationWorkable: Creating candidates and attaching them to jobsWorkday vs Workday Legacy — Why Unified.to Supports BothWorking with hierarchical tree data in Storage, Messaging, and KMS APIs
Are we missing anything? Let us know
Was this page helpful?