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.io/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 via POST /entities.

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": "draft",
    "jurisdiction_product_id": "jp_abc123"
  }
}
entity.updated

Entity details have been updated.

Example Payload
{
  "id": "evt_def456",
  "type": "entity.updated",
  "created_at": "2024-01-21T10:30:00Z",
  "data": {
    "entity_id": "ent_xyz789",
    "changes": {
      "name": {
        "from": "My Company LLC",
        "to": "My Company Ltd"
      }
    }
  }
}
entity.status_changed

Entity status has changed — fired on every status transition (submitted, in_review, returned_for_changes, submitted_to_csp, incorporated, etc.).

Example Payload
{
  "id": "evt_ghi789",
  "type": "entity.status_changed",
  "created_at": "2024-01-22T09:00:00Z",
  "data": {
    "entity_id": "ent_xyz789",
    "name": "My Company Ltd",
    "old_status": "submitted_to_csp",
    "new_status": "incorporated",
    "company_number": "12345678",
    "incorp_date": "2024-01-22"
  }
}
entity.invoiced

An invoice has been issued for an entity via POST /entities/{id}/invoice.

Example Payload
{
  "id": "evt_inv001",
  "type": "entity.invoiced",
  "created_at": "2024-01-20T15:00:00Z",
  "data": {
    "entity_id": "ent_xyz789",
    "invoice_id": "inv_abc123",
    "invoice_number": "INV-001",
    "total_minor": 150000,
    "currency": "USD"
  }
}
entity.feedback_created

Admin has raised a review issue requiring your response.

Example Payload
{
  "id": "evt_fb001",
  "type": "entity.feedback_created",
  "created_at": "2024-01-21T11:00:00Z",
  "data": {
    "entity_id": "ent_xyz789",
    "feedback_id": "fb_abc123",
    "feedback_type": "document_issue",
    "message": "The passport scan is unclear. Please upload a higher quality image."
  }
}
entity.feedback_resolved

A feedback issue has been resolved by admin.

Example Payload
{
  "id": "evt_fb002",
  "type": "entity.feedback_resolved",
  "created_at": "2024-01-22T14:00:00Z",
  "data": {
    "entity_id": "ent_xyz789",
    "feedback_id": "fb_abc123",
    "resolution_note": "Document accepted."
  }
}
document.uploaded

A document has been uploaded for an entity.

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 by admin.

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"
  }
}
document.rejected

A document has been rejected by admin.

Example Payload
{
  "id": "evt_doc003",
  "type": "document.rejected",
  "created_at": "2024-01-21T09:30:00Z",
  "data": {
    "entity_id": "ent_xyz789",
    "document_id": "doc_abc123",
    "document_type": "passport",
    "rejected_reason": "Image quality too low."
  }
}
party.added

A party (person, company, or foundation) has been added to an entity.

Example Payload
{
  "id": "evt_jkl012",
  "type": "party.added",
  "created_at": "2024-01-20T15:00:00Z",
  "data": {
    "entity_id": "ent_xyz789",
    "party_id": "pty_abc123",
    "party_type": "person",
    "first_name": "John",
    "last_name": "Smith",
    "roles": ["director", "shareholder"]
  }
}
party.updated

A party's details have been updated.

Example Payload
{
  "id": "evt_per002",
  "type": "party.updated",
  "created_at": "2024-01-21T10:00:00Z",
  "data": {
    "entity_id": "ent_xyz789",
    "party_id": "pty_abc123",
    "party_type": "person",
    "first_name": "John",
    "last_name": "Smith"
  }
}
party.removed

A party has been removed from an entity.

Example Payload
{
  "id": "evt_per003",
  "type": "party.removed",
  "created_at": "2024-01-21T11:00:00Z",
  "data": {
    "entity_id": "ent_xyz789",
    "party_id": "pty_abc123",
    "party_type": "person"
  }
}
payment.session_created

A hosted Stripe or Radom checkout session has been created for an invoice.

Example Payload
{
  "id": "evt_pay001",
  "type": "payment.session_created",
  "created_at": "2024-01-20T15:30:00Z",
  "data": {
    "invoice_id": "inv_abc123",
    "entity_id": "ent_xyz789",
    "provider": "stripe",
    "checkout_url": "https://checkout.stripe.com/..."
  }
}
payment.session_expired

A hosted checkout session expired before payment was completed. Regenerate via POST /invoices/{id}/checkout-session.

Example Payload
{
  "id": "evt_pay002",
  "type": "payment.session_expired",
  "created_at": "2024-01-21T15:30:00Z",
  "data": {
    "invoice_id": "inv_abc123",
    "entity_id": "ent_xyz789",
    "provider": "stripe"
  }
}
payment.received

Payment has been received and the invoice is marked paid.

Example Payload
{
  "id": "evt_pay003",
  "type": "payment.received",
  "created_at": "2024-01-21T16:00:00Z",
  "data": {
    "invoice_id": "inv_abc123",
    "entity_id": "ent_xyz789",
    "amount_minor": 150000,
    "currency": "USD",
    "provider": "stripe"
  }
}
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
  }
}
shareholding.updated

The number of shares held in an existing shareholding has been updated.

Example Payload
{
  "id": "evt_def013",
  "type": "shareholding.updated",
  "created_at": "2024-01-21T10:00:00Z",
  "data": {
    "entity_id": "ent_xyz789",
    "shareholding_id": "sh_abc123",
    "party_id": "pty_def456",
    "share_class_id": "sc_abc123",
    "shares_held": 750
  }
}
addon.purchased

An addon has been purchased for an entity.

Example Payload
{
  "id": "evt_adn001",
  "type": "addon.purchased",
  "created_at": "2024-01-20T15:00:00Z",
  "data": {
    "entity_id": "ent_xyz789",
    "addon_id": "addon_ein_123",
    "addon_slug": "ein-registration"
  }
}
addon.status_changed

An addon status has changed (e.g., submitted for review, approved, completed).

Example Payload
{
  "id": "evt_adn002",
  "type": "addon.status_changed",
  "created_at": "2024-01-22T10:00:00Z",
  "data": {
    "entity_id": "ent_xyz789",
    "addon_id": "addon_ein_123",
    "old_status": "submitted_for_review",
    "new_status": "approved"
  }
}
addon.invoiced

A separate invoice has been raised for an addon purchase (post-submission addons that require additional payment).

Example Payload
{
  "id": "evt_adn003",
  "type": "addon.invoiced",
  "created_at": "2024-01-22T11:00:00Z",
  "data": {
    "entity_id": "ent_xyz789",
    "addon_slug": "ein-registration",
    "entity_addon_id": "ea_abc123",
    "invoice_id": "inv_xyz789",
    "total_minor": 25000,
    "currency": "USD",
    "checkout_url": "https://checkout.stripe.com/..."
  }
}
invitation.sent

A collaborator invitation has been sent for an entity.

Example Payload
{
  "id": "evt_inv001",
  "type": "invitation.sent",
  "created_at": "2024-01-20T12:00:00Z",
  "data": {
    "entity_id": "ent_xyz789",
    "invitation_id": "ivt_abc123",
    "email": "colleague@example.com",
    "expires_at": "2024-01-27T12:00:00Z"
  }
}
invitation.accepted

A collaborator invitation has been accepted.

Example Payload
{
  "id": "evt_inv002",
  "type": "invitation.accepted",
  "created_at": "2024-01-21T09:00:00Z",
  "data": {
    "entity_id": "ent_xyz789",
    "invitation_id": "ivt_abc123",
    "email": "colleague@example.com"
  }
}
invitation.expired

A collaborator invitation expired before being accepted.

Example Payload
{
  "id": "evt_inv003",
  "type": "invitation.expired",
  "created_at": "2024-01-27T12:00:00Z",
  "data": {
    "entity_id": "ent_xyz789",
    "invitation_id": "ivt_abc123",
    "email": "colleague@example.com"
  }
}
invitation.revoked

A pending collaborator invitation has been revoked via DELETE /invitations/{id}.

Example Payload
{
  "id": "evt_inv004",
  "type": "invitation.revoked",
  "created_at": "2024-01-22T10:00:00Z",
  "data": {
    "entity_id": "ent_xyz789",
    "invitation_id": "ivt_abc123",
    "email": "colleague@example.com"
  }
}
collaborator.added

A collaborator has gained access to an entity after accepting an invitation.

Example Payload
{
  "id": "evt_col001",
  "type": "collaborator.added",
  "created_at": "2024-01-20T13:00:00Z",
  "data": {
    "entity_id": "ent_xyz789",
    "user_id": "usr_abc123",
    "email": "colleague@example.com"
  }
}
collaborator.removed

A collaborator has been removed from an entity.

Example Payload
{
  "id": "evt_col002",
  "type": "collaborator.removed",
  "created_at": "2024-01-23T14:00:00Z",
  "data": {
    "entity_id": "ent_xyz789",
    "user_id": "usr_abc123"
  }
}

Webhook Management API