***

title: Simulations
description: Test your webhook integration safely without affecting production data
-----------------------------------------------------------------------------------

## Overview

Webhook simulation allows you to test your integration without triggering real business processes or affecting production data. Simulated events work exactly like production webhooks but are clearly marked so you can handle them differently.

* **Safe Testing:** Test without affecting real data
* **Production-Like:** Uses same infrastructure as real events
* **Easy Debugging:** Validate configuration before going live

## Why Simulate Webhooks?

<AccordionGroup>
  <Accordion title="Validate Configuration" icon="check">
    Ensure your webhook endpoint is configured correctly:

    * URL is accessible
    * Signature verification works
    * Response time is acceptable
    * Error handling is robust
  </Accordion>

  <Accordion title="Test Integration Logic" icon="code">
    Verify your application handles events correctly:

    * Events are parsed properly
    * Business logic executes as expected
    * Database updates work correctly
    * No side effects in production systems
  </Accordion>

  <Accordion title="Debug Issues" icon="wrench">
    Troubleshoot problems safely:

    * Reproduce error conditions
    * Test edge cases
    * Verify fixes without risk
    * Check logs and monitoring
  </Accordion>

  <Accordion title="Train Your Team" icon="users">
    Help developers understand the integration:

    * See real webhook payloads
    * Learn event structures
    * Practice responding to events
    * Build confidence before production
  </Accordion>
</AccordionGroup>

## How Simulation Works

When you simulate a webhook event:

1. **Deel sends a test payload** to your configured endpoint
2. **The payload is marked** with `"is_simulation": true`
3. **Same authentication and retry logic** applies as production
4. **Event is logged** in webhook delivery history
5. **Your endpoint receives** a realistic test event

<Info>
  Simulated events use the same infrastructure as production webhooks, so they're an accurate test of your integration's reliability.
</Info>

## Simulating Events in Developer Center

<Steps>
  <Step title="Navigate to Developer Center">
    Log in to [app.deel.com](https://app.deel.com) and go to **More** → **Developer** → **Webhooks**
  </Step>

  <Step title="Select your webhook">
    Click on the webhook subscription you want to test
  </Step>

  <Step title="View subscribed events">
    In the webhook details page, you'll see all events you're subscribed to
  </Step>

  <Step title="Expand event type">
    Expand the event type you want to simulate
  </Step>

  <Step title="Click Simulate">
    Click the **Simulate** button next to the event. A dialog appears confirming the simulation was successful.
  </Step>

  <Step title="Verify delivery">
    Check your endpoint logs to confirm the webhook was received
  </Step>
</Steps>

<Tip>
  **Quick testing tip:** Keep the Developer Center open while testing your local endpoint with ngrok. You can simulate events instantly and see results in real-time.
</Tip>

## Simulated Event Payload

Simulated webhooks include the `is_simulation` flag in the payload:

```json
{
  "data": {
    "meta": {
      "event_type": "contract.created",
      "organization_id": "org_abc123",
      "event_id": "evt_sim_xyz789",
      "occurred_at": "2025-02-05T15:39:38.070Z",
      "is_simulation": true  // ← Simulation flag
    },
    "resource": [
      {
        "contract_id": "ctr_test_123",
        "worker_email": "test.worker@example.com",
        "status": "pending",
        "type": "eor",
        "country": "US"
      }
    ]
  },
  "timestamp": "2025-02-05T15:39:38.070Z"
}
```

## Handling Simulated Events

You can detect and handle simulated events differently in your code:

<CodeGroup>
  ```javascript Node.js
  app.post('/webhooks/deel', async (req, res) => {
    const { meta } = req.body.data;
    const resource = req.body.data.resource[0];

    // Check if this is a simulation
    if (meta.is_simulation) {
      console.log('📋 Received simulated event:', meta.event_type);

      // Log but don't process
      await logSimulatedEvent(meta.event_type, resource);

      return res.status(200).send('Simulation received');
    }

    // Process real events normally
    await processEvent(meta.event_type, resource);

    res.status(200).send('OK');
  });
  ```

  ```python Python
  @app.route('/webhooks/deel', methods=['POST'])
  def handle_webhook():
      meta = request.json['data']['meta']
      resource = request.json['data']['resource'][0]

      # Check if this is a simulation
      if meta.get('is_simulation'):
          print(f'📋 Received simulated event: {meta["event_type"]}')

          # Log but don't process
          log_simulated_event(meta['event_type'], resource)

          return jsonify({'status': 'Simulation received'}), 200

      # Process real events normally
      process_event(meta['event_type'], resource)

      return jsonify({'status': 'success'}), 200
  ```
</CodeGroup>

<Warning>
  **Important:** Always check the `is_simulation` flag to avoid processing test data as if it were real. This prevents duplicate records, incorrect metrics, and unintended side effects.
</Warning>

## Best Practices

<AccordionGroup>
  <Accordion title="Test all subscribed events" icon="check-double">
    Simulate each event type you're subscribed to:

    ```javascript
    const eventsToTest = [
      'contract.created',
      'contract.signed',
      'payment.completed'
    ];

    // Test each one in Developer Center
    eventsToTest.forEach(event => {
      console.log(`✓ Test ${event}`);
    });
    ```
  </Accordion>

  <Accordion title="Check logs after each simulation" icon="list">
    Always verify:

    * Event was received
    * Status code is correct
    * Response time is acceptable
    * No errors in your application logs
  </Accordion>

  <Accordion title="Test with production-like data" icon="database">
    Use realistic test data that mirrors your production use cases:

    * Actual country codes
    * Valid email formats
    * Realistic contract amounts
    * Expected date formats
  </Accordion>

  <Accordion title="Simulate edge cases" icon="triangle-exclamation">
    Test unusual scenarios:

    * Very long field values
    * Special characters in names
    * Multiple resources in array
    * Missing optional fields
  </Accordion>

  <Accordion title="Use simulation flag properly" icon="flag">
    Don't process simulated events as real data:

    ```javascript
    if (meta.is_simulation) {
      // Log, validate, test - but don't create real records
      await validateWebhookStructure(resource);
      await testBusinessLogic(resource);
      return;
    }

    // Only process real events
    await createDatabaseRecords(resource);
    ```
  </Accordion>
</AccordionGroup>

## Troubleshooting Simulations

<AccordionGroup>
  <Accordion title="Simulation not arriving" icon="bell-slash">
    **Check:**

    * Is your endpoint accessible?
    * Is the webhook enabled?
    * Did you hit the rate limit (10/hour)?
    * Is your server responding to requests?

    **Test connectivity:**

    ```bash
    curl -X POST https://your-endpoint.com/webhooks/deel \
      -H "Content-Type: application/json" \
      -d '{"test": "data"}'
    ```
  </Accordion>

  <Accordion title="Simulation failing but production works" icon="circle-exclamation">
    **Possible causes:**

    * Your code rejects simulated events
    * Different validation for test data
    * Sandbox vs production environment mismatch

    **Solution:**
    Ensure simulated events can pass through your validation:

    ```javascript
    // Allow both real and simulated events
    if (!meta.is_simulation) {
      // Only validate real events strictly
      await strictValidation(resource);
    }
    ```
  </Accordion>

  <Accordion title="Want to simulate more than 10 times per hour" icon="clock">
    **Options:**

    1. Create additional webhook subscriptions for testing
    2. Use webhook logs to replay past events
    3. Retrieve sample payloads from API and test locally
    4. Use the event structure documentation to build test payloads

    **Local testing:**

    ```javascript
    // Create test payload locally
    const testPayload = {
      data: {
        meta: {
          event_type: 'contract.created',
          is_simulation: true
        },
        resource: [{ /* test data */ }]
      }
    };

    // Test your handler
    await handleWebhook(testPayload);
    ```
  </Accordion>
</AccordionGroup>

## Additional Resources

<CardGroup cols={2}>
  <Card title="Webhook Events" icon="fa-light bell" href="/api/webhooks/events">
    Explore all available event types
  </Card>

  <Card title="Managing Webhooks" icon="fa-light sliders" href="/api/webhooks/no-code">
    Create and configure webhooks
  </Card>
</CardGroup>
