Event Types & Delivery

This page provides detailed information about all webhook event types, their payloads, and delivery mechanics.

Event categories

Stampee webhooks are organized into four categories:

CategoryEventsDescription
Customer3 eventsCustomer delegation lifecycle
Message4 eventsMessage sending and delivery status
Consent4 eventsConsent request lifecycle
Evidence1 eventEvidence document generation

Customer events

customer_accepted

Triggered when a customer accepts your delegation request.

Payload:

{
  "type": "customer_accepted",
  "timestamp": "2025-02-07T14:30:00.000Z",
  "data": {
    "customer_id": "550e8400-e29b-41d4-a716-446655440000",
    "customer_name": "Acme Corporation",
    "customer_email": "[email protected]",
    "accepted_at": "2025-02-07T14:30:00.000Z"
  }
}

When to use:

  • Enable sending messages on behalf of this customer
  • Notify your team of successful customer onboarding
  • Update customer status in your system

customer_refused

Triggered when a customer refuses your delegation request.

Payload:

{
  "type": "customer_refused",
  "timestamp": "2025-02-07T15:00:00.000Z",
  "data": {
    "customer_id": "550e8400-e29b-41d4-a716-446655440000",
    "customer_name": "Acme Corporation",
    "customer_email": "[email protected]",
    "refused_at": "2025-02-07T15:00:00.000Z"
  }
}

When to use:

  • Alert your team to follow up with the customer
  • Update customer status to refused
  • Trigger re-engagement campaigns

customer_pvid_established

Triggered when a customer completes KYC verification and can send LRE messages.

Payload:

{
  "type": "customer_pvid_established",
  "timestamp": "2025-02-07T16:00:00.000Z",
  "data": {
    "customer_id": "550e8400-e29b-41d4-a716-446655440000",
    "customer_name": "Acme Corporation",
    "customer_email": "[email protected]",
    "established_at": "2025-02-07T16:00:00.000Z"
  }
}

When to use:

  • Enable LRE message sending for this customer
  • Notify customer they can now send registered letters
  • Update customer capabilities in your system

Message events

lre_sent

Triggered when an LRE (registered letter) is successfully sent.

Payload:

{
  "type": "lre_sent",
  "timestamp": "2025-02-07T14:35:00.000Z",
  "data": {
    "message_id": "123456789012",
    "recipient_name": "John Doe",
    "recipient_email": "[email protected]",
    "sender_name": "Acme Corporation",
    "sent_at": "2025-02-07T14:35:00.000Z"
  }
}

When to use:

  • Update message status to sent in your database
  • Track delivery metrics
  • Notify sender of successful delivery

lre_failed

Triggered when an LRE message fails to send.

Payload:

{
  "type": "lre_failed",
  "timestamp": "2025-02-07T14:40:00.000Z",
  "data": {
    "message_id": "123456789012",
    "recipient_name": "John Doe",
    "recipient_email": "[email protected]",
    "sender_name": "Acme Corporation",
    "failed_at": "2025-02-07T14:40:00.000Z"
  }
}

When to use:

  • Alert sender of failed delivery
  • Suggest correcting recipient email
  • Log failed delivery attempts

ls_sent

Triggered when an LS (simple letter) is successfully sent.

Payload:

{
  "type": "ls_sent",
  "timestamp": "2025-02-07T14:45:00.000Z",
  "data": {
    "message_id": "987654321098",
    "recipient_name": "Jane Smith",
    "recipient_email": "[email protected]",
    "sender_name": "Widget Inc",
    "sent_at": "2025-02-07T14:45:00.000Z"
  }
}

When to use:

  • Update message status to sent
  • Track sending volume
  • Trigger follow-up actions

ls_failed

Triggered when an LS message fails to send.

Payload:

{
  "type": "ls_failed",
  "timestamp": "2025-02-07T14:50:00.000Z",
  "data": {
    "message_id": "987654321098",
    "recipient_name": "Jane Smith",
    "recipient_email": "[email protected]",
    "sender_name": "Widget Inc",
    "failed_at": "2025-02-07T14:50:00.000Z"
  }
}

When to use:

  • Alert sender of failed delivery
  • Validate recipient email addresses
  • Monitor delivery failures

Consent events

consent_sent

Triggered when a consent request is sent to a recipient.

Payload:

{
  "type": "consent_sent",
  "timestamp": "2025-02-07T15:00:00.000Z",
  "data": {
    "consent_id": "550e8400-e29b-41d4-a716-446655440000",
    "contact_id": "660e8400-e29b-41d4-a716-446655440001",
    "recipient_name": "Alice Johnson",
    "recipient_email": "[email protected]",
    "consent_type": "EMAIL",
    "consent_delay_days": 7,
    "expires_at": "2025-02-14T15:00:00.000Z"
  }
}

For LINK type consents, additional fields:

{
  "type": "consent_sent",
  "timestamp": "2025-02-07T15:00:00.000Z",
  "data": {
    "consent_id": "550e8400-e29b-41d4-a716-446655440000",
    "contact_id": "660e8400-e29b-41d4-a716-446655440001",
    "recipient_name": "Bob Wilson",
    "recipient_email": "[email protected]",
    "consent_type": "LINK",
    "consent_delay_days": 14,
    "expires_at": "2025-02-21T15:00:00.000Z",
    "link_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
    "consent_url": "https://app.stampee.fr/consents/eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
  }
}

When to use:

  • Track consent request status
  • Send reminder emails before expiration
  • Monitor consent pipeline

consent_accepted

Triggered when a recipient accepts a consent request.

Payload:

{
  "type": "consent_accepted",
  "timestamp": "2025-02-08T10:00:00.000Z",
  "data": {
    "consent_id": "550e8400-e29b-41d4-a716-446655440000",
    "contact_id": "660e8400-e29b-41d4-a716-446655440001",
    "recipient_name": "Alice Johnson",
    "recipient_email": "[email protected]",
    "consent_type": "EMAIL",
    "accepted_at": "2025-02-08T10:00:00.000Z"
  }
}

When to use:

  • Enable sending LRE messages to this recipient
  • Update recipient consent status
  • Trigger welcome workflows

consent_rejected

Triggered when a recipient rejects a consent request.

Payload:

{
  "type": "consent_rejected",
  "timestamp": "2025-02-08T11:00:00.000Z",
  "data": {
    "consent_id": "550e8400-e29b-41d4-a716-446655440000",
    "contact_id": "660e8400-e29b-41d4-a716-446655440001",
    "recipient_name": "Alice Johnson",
    "recipient_email": "[email protected]",
    "consent_type": "EMAIL",
    "rejected_at": "2025-02-08T11:00:00.000Z"
  }
}

When to use:

  • Mark recipient as not consenting
  • Remove from LRE mailing lists
  • Track rejection reasons

consent_expired

Triggered when a consent request expires without response.

Payload:

{
  "type": "consent_expired",
  "timestamp": "2025-02-14T15:00:00.000Z",
  "data": {
    "consent_id": "550e8400-e29b-41d4-a716-446655440000",
    "contact_id": "660e8400-e29b-41d4-a716-446655440001",
    "recipient_name": "Alice Johnson",
    "recipient_email": "[email protected]",
    "consent_type": "EMAIL",
    "expires_at": "2025-02-14T15:00:00.000Z"
  }
}

When to use:

  • Send follow-up consent request
  • Update consent status to expired
  • Track consent completion rates

Evidence events

evidence_generated

Triggered when an evidence PDF document is generated and ready for download.

For message evidence:

{
  "type": "evidence_generated",
  "timestamp": "2025-02-07T15:00:00.000Z",
  "data": {
    "message_id": "123456789012",
    "customer_name": "Acme Corporation",
    "customer_email": "[email protected]",
    "sent_at": "2025-02-07T14:35:00.000Z",
    "recipient_name": "John Doe",
    "recipient_email": "[email protected]",
    "evidence_id": "770e8400-e29b-41d4-a716-446655440002",
    "event_type": "SENT",
    "download_url": "https://storage.stampee.fr/evidences/xxx.pdf?sig=abc&expires=1707404400",
    "created_at": "2025-02-07T15:00:00.000Z",
    "details": null,
  }
}

For consent evidence:

{
  "type": "evidence_generated",
  "timestamp": "2025-02-08T10:30:00.000Z",
  "data": {
    "consent_id": "550e8400-e29b-41d4-a716-446655440000",
    "customer_name": "Acme Corporation",
    "customer_email": "[email protected]",
    "sent_at": "2025-02-08T10:00:00.000Z",
    "recipient_name": "Alice Johnson",
    "recipient_email": "[email protected]",
    "evidence_id": "880e8400-e29b-41d4-a716-446655440003",
    "event_type": "CONSENT_ACCEPTED",
    "download_url": "https://storage.stampee.fr/evidences/yyy.pdf?sig=def&expires=1707491400",
    "created_at": "2025-02-08T10:30:00.000Z"
  }
}

When to use:

  • Download and archive evidence documents
  • Notify stakeholders evidence is available
  • Trigger compliance workflows

Download URL expiration

The download_url is signed and valid for 7 days. Download the evidence promptly or store it in your own system.

Evidence event types:

  • SENT - Message was sent
  • RECEIVED - Message was received (LS only)
  • ACCEPTED - Message was accepted (LRE only)
  • REFUSED - Message was refused (LRE only)
  • EXPIRED - Message expired
  • UNDELIVERED - Message undeliverable
  • CONSENT_SENT - Consent request sent
  • CONSENT_ACCEPTED - Consent accepted
  • CONSENT_REJECTED - Consent rejected
  • CONSENT_EXPIRED - Consent expired

Event delivery

Delivery timing

Events are delivered within 5 minutes of occurrence. Most events are delivered within 1 minute.

Delivery guarantees

  • At-least-once delivery - Events may be delivered multiple times
  • Ordering - Events may arrive out of order; use timestamp to reorder
  • Retries - Failed deliveries are retried up to 10 times over 24 hours

Response requirements

Your endpoint must:

  • Respond with HTTP 200-299 status code
  • Respond within 10 seconds
  • Not modify the request body before signature verification

Handling failures

4xx responses and 5xx responses (client and server errors):

  • Will retry with exponential backoff 3 times

Idempotency

Use the webhook-id header to ensure idempotent processing. Store processed webhook IDs to avoid duplicate handling:

// Example: Check if already processed
const webhookId = req.headers['webhook-id'];
const alreadyProcessed = await db.webhookLogs.exists({ webhookId });

if (alreadyProcessed) {
  return res.status(200).json({ status: 'already_processed' });
}

// Process event...

// Store webhook ID
await db.webhookLogs.create({ webhookId, processedAt: new Date() });

Next steps

Need help?