Webhooks

Receive real-time notifications when events happen

Webhooks allow you to receive real-time HTTP notifications when events happen in your EntityEngine account. Instead of polling the API, you can subscribe to events and receive instant updates.

Real-time

Get notified instantly when events occur

Secure

HMAC-SHA256 signatures verify authenticity

Reliable

Automatic retries with exponential backoff

Setting Up Webhooks

Via Dashboard

  1. Log in to your EntityEngine account
  2. Navigate to Profile → Webhooks
  3. Click Create Webhook
  4. Enter your endpoint URL (must be HTTPS)
  5. Select the events you want to receive
  6. Save and copy your webhook secret

Via API

Create webhook via API
curl -X POST "https://app.entityengine.com/api/v1/webhooks" \
  -H "Authorization: Bearer sk_live_abc123" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://your-app.com/webhooks/entityengine",
    "events": ["entity.created", "entity.updated", "document.uploaded"],
    "description": "Production webhook"
  }'

Webhook Payload

All webhook payloads follow a consistent structure:

Webhook Payload Structure
{
  "id": "evt_abc123",
  "type": "entity.created",
  "created_at": "2024-01-20T14:00:00Z",
  "data": {
    // Event-specific data
  }
}

HTTP Headers

HeaderDescription
X-Webhook-IDUnique identifier for this webhook delivery
X-Webhook-TimestampUnix timestamp when the webhook was sent
X-Webhook-SignatureHMAC-SHA256 signature for verification

Verifying Signatures

Always verify webhook signatures

Verifying signatures ensures the webhook was sent by EntityEngine and hasn't been tampered with.

The signature is computed using HMAC-SHA256 with your webhook secret:

Signature Formula
signature = HMAC-SHA256(webhook_secret, timestamp + "." + payload)

Node.js Example

import crypto from 'crypto';

function verifyWebhookSignature(
  payload: string,
  signature: string,
  timestamp: string,
  secret: string
): boolean {
  const signedPayload = `${timestamp}.${payload}`;
  const expectedSignature = crypto
    .createHmac('sha256', secret)
    .update(signedPayload)
    .digest('hex');
  
  return crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(expectedSignature)
  );
}

// In your webhook handler
app.post('/webhooks/entityengine', (req, res) => {
  const signature = req.headers['x-webhook-signature'];
  const timestamp = req.headers['x-webhook-timestamp'];
  const payload = JSON.stringify(req.body);
  
  if (!verifyWebhookSignature(payload, signature, timestamp, WEBHOOK_SECRET)) {
    return res.status(401).json({ error: 'Invalid signature' });
  }
  
  // Process the webhook
  const event = req.body;
  console.log('Received event:', event.type);
  
  res.status(200).json({ received: true });
});

Retry Policy

If your endpoint returns a non-2xx status code or times out, we'll retry the delivery with exponential backoff:

AttemptDelay
1st retry1 minute
2nd retry5 minutes
3rd retry30 minutes
4th retry2 hours
5th retry (final)24 hours

Best Practice

Return a 200 status code as quickly as possible. Process the webhook asynchronously to avoid timeouts.

Event Types

entity.created

A new entity has been created

Example Payload
{
  "id": "evt_abc123",
  "type": "entity.created",
  "created_at": "2024-01-20T14:00:00Z",
  "data": {
    "entity_id": "ent_xyz789",
    "name": "My Company LLC",
    "status": "pre_incorporation",
    "jurisdiction_product_id": "jp_abc123"
  }
}
entity.updated

An entity has been updated

Example Payload
{
  "id": "evt_def456",
  "type": "entity.updated",
  "created_at": "2024-01-21T10:30:00Z",
  "data": {
    "entity_id": "ent_xyz789",
    "changes": {
      "status": {
        "from": "pre_incorporation",
        "to": "in_progress"
      }
    }
  }
}
entity.status_changed

An entity status has changed

Example Payload
{
  "id": "evt_ghi789",
  "type": "entity.status_changed",
  "created_at": "2024-01-22T09:00:00Z",
  "data": {
    "entity_id": "ent_xyz789",
    "previous_status": "in_progress",
    "new_status": "active"
  }
}
person.added

A person has been added to an entity

Example Payload
{
  "id": "evt_jkl012",
  "type": "person.added",
  "created_at": "2024-01-20T15:00:00Z",
  "data": {
    "entity_id": "ent_xyz789",
    "person_id": "per_abc123",
    "first_name": "John",
    "last_name": "Smith",
    "roles": ["director", "shareholder"]
  }
}
document.uploaded

A document has been uploaded

Example Payload
{
  "id": "evt_stu901",
  "type": "document.uploaded",
  "created_at": "2024-01-20T16:00:00Z",
  "data": {
    "entity_id": "ent_xyz789",
    "document_id": "doc_abc123",
    "document_type": "passport",
    "name": "passport_john_smith.pdf"
  }
}
document.approved

A document has been approved

Example Payload
{
  "id": "evt_vwx234",
  "type": "document.approved",
  "created_at": "2024-01-21T09:00:00Z",
  "data": {
    "entity_id": "ent_xyz789",
    "document_id": "doc_abc123",
    "document_type": "passport"
  }
}
kyc.completed

KYC verification has been completed for an entity

Example Payload
{
  "id": "evt_bcd890",
  "type": "kyc.completed",
  "created_at": "2024-01-23T10:00:00Z",
  "data": {
    "entity_id": "ent_xyz789",
    "status": "verified",
    "verified_persons": ["per_abc123", "per_def456"]
  }
}
share_class.created

A new share class has been created for an entity

Example Payload
{
  "id": "evt_cde901",
  "type": "share_class.created",
  "created_at": "2024-01-20T14:30:00Z",
  "data": {
    "entity_id": "ent_xyz789",
    "share_class_id": "sc_abc123",
    "name": "Ordinary Shares",
    "currency": "USD",
    "par_value": 1.00
  }
}
shareholding.created

A new shareholding has been allocated to a shareholder

Example Payload
{
  "id": "evt_def012",
  "type": "shareholding.created",
  "created_at": "2024-01-20T15:00:00Z",
  "data": {
    "entity_id": "ent_xyz789",
    "shareholding_id": "sh_abc123",
    "party_id": "pty_def456",
    "party_name": "John Smith",
    "share_class_id": "sc_abc123",
    "shares_held": 1000
  }
}

Webhook Management API