Skip to main content
Webhooks allow you to receive real-time HTTP notifications when events occur in your Intelliprint account, such as when letters are printed, dispatched, delivered, or returned.
Configure webhooks at account.intelliprint.net/api_keys. Powered by Svix for reliable, enterprise-grade event delivery.

Benefits of Webhooks

Instead of constantly polling the API to check print job status:

Real-time Updates

Receive instant notifications when events occur

Reduced API Calls

No need to poll for status changes

Scalable

Handle thousands of events reliably

Automatic Retries

Svix automatically retries failed deliveries

Event Types

Intelliprint sends webhooks for the following events:
Event TypeDescriptionWhen It Fires
letter.updatedLetter status changedWhen a confirmed letter’s status is updated (e.g., waiting_to_print, printing, enclosing, shipping, sent, returned, failed_wrong_address)
mailing_list.addresses_validatedAddress validation completedWhen all recipients in a mailing list have been validated
Each letter.updated event includes the letter’s current status, allowing you to track the full lifecycle from confirmation through delivery or return.

Setting Up Webhooks

1. Access Webhook Settings

Configure webhooks in your Intelliprint account:
1

Go to API Settings

Navigate to account.intelliprint.net/api_keys and access the webhooks section.
2

Create Endpoint

Add the URL where you want to receive webhook events:
https://your-app.com/webhooks/intelliprint
3

Select Events

Choose which events you want to receive (e.g., letter.updated, mailing_list.addresses_validated).
4

Test Webhook

Use the built-in testing tools to send test events to your endpoint.
Powered by Svix: Webhook management is handled by Svix, ensuring reliable delivery with automatic retries. You can also access the Svix dashboard directly for advanced features.

2. Create Your Webhook Endpoint

Implement an endpoint in your application to receive webhook events:
import express from 'express';
import { Webhook } from 'svix';

const app = express();

app.post('/webhooks/intelliprint', 
  express.raw({ type: 'application/json' }),
  (req, res) => {
    const webhookSecret = process.env.SVIX_WEBHOOK_SECRET;
    const webhook = new Webhook(webhookSecret);
    
    let event;
    
    try {
      // Verify webhook signature
      event = webhook.verify(req.body, {
        'svix-id': req.headers['svix-id'],
        'svix-timestamp': req.headers['svix-timestamp'],
        'svix-signature': req.headers['svix-signature']
      });
    } catch (err) {
      console.error('Webhook verification failed:', err);
      return res.status(400).send('Invalid signature');
    }
    
    // Handle the event
    switch (event.type) {
      case 'letter.updated':
        console.log(`Letter ${event.data.id} updated: ${event.data.status}`);
        
        // Handle different letter statuses
        switch (event.data.status) {
          case 'sent':
            // Letter dispatched to Royal Mail
            console.log(`Letter dispatched. Tracking: ${event.data.tracking_number}`);
            break;
          case 'returned':
            // Letter returned
            console.log(`Letter returned: ${event.data.returned.reason}`);
            break;
          case 'failed_wrong_address':
            // Delivery failed
            console.log('Delivery failed - wrong address');
            break;
        }
        break;
        
      case 'mailing_list.addresses_validated':
        console.log(`Mailing list ${event.data.id} validated`);
        console.log(`Passed: ${event.data.address_validation.recipients.passed}`);
        console.log(`Failed: ${event.data.address_validation.recipients.failed}`);
        break;
        
      default:
        console.log(`Unhandled event type: ${event.type}`);
    }
    
    // Return 200 to acknowledge receipt
    res.sendStatus(200);
  }
);

app.listen(3000);

Event Payload Structure

letter.updated

Fired when a confirmed letter’s status changes:
{
  "type": "letter.updated",
  "account": "acc_example",
  "id": "ltr_example",
  "print_id": "print_example",
  "reference": "My Print Job 1",
  "status": "sent",
  "envelope": "c5",
  "postage_service": "uk_second_class",
  "tracking_number": "ABC123456GB",
  "shipped_date": 1701869673,
  "testmode": false
}
Possible status values:
  • waiting_to_print - Queued for printing
  • printing - Currently being printed
  • enclosing - Being placed in envelope
  • shipping - Handed to Royal Mail
  • sent - Dispatched
  • returned - Returned to sender
  • failed_wrong_address - Delivery failed
Returned letter example:
{
  "type": "letter.updated",
  "account": "acc_example",
  "id": "ltr_example",
  "print_id": "print_example",
  "reference": "My Print Job 1",
  "status": "returned",
  "envelope": "c5",
  "postage_service": "uk_second_class",
  "shipped_date": 1701869673,
  "returned": {
    "date": 1701969673,
    "reason": "Delivery Refused"
  },
  "testmode": false
}

mailing_list.addresses_validated

Triggered when all recipients in a mailing list have been validated:
{
  "type": "mailing_list.addresses_validated",
  "account": "acc_example",
  "id": "mal_example",
  "name": "Black Friday Campaign",
  "recipients": 1000,
  "address_validation": {
    "completed": true,
    "recipients": {
      "passed": 987,
      "failed": 13
    }
  }
}

Webhook Security

Verify Signatures

Always verify webhook signatures to ensure the request came from Intelliprint (via Svix) and wasn’t tampered with.
Svix signs all webhooks with a secret key. Use the Svix SDK to verify:
const webhook = new Webhook(webhookSecret);

try {
  const event = webhook.verify(payload, headers);
  // ✅ Signature valid - process event
} catch (err) {
  // ❌ Invalid signature - reject request
  return res.status(400).send('Invalid signature');
}

Get Your Webhook Secret

Find your webhook secret in your API settings or in the Svix dashboard under your endpoint settings.
Each webhook endpoint has its own unique secret. Keep these secrets secure and never commit them to version control.

Best Practices

1. Return 200 Quickly

Respond with HTTP 200 as quickly as possible, then process the event asynchronously:
app.post('/webhooks/intelliprint', async (req, res) => {
  const event = verifyWebhook(req);
  
  // ✅ Return 200 immediately
  res.sendStatus(200);
  
  // Process asynchronously
  await processEventAsync(event);
});

2. Handle Idempotency

Webhooks may be delivered more than once. Use the event ID to avoid duplicate processing:
const processedEvents = new Set();

function handleWebhook(event) {
  if (processedEvents.has(event.id)) {
    console.log('Duplicate event, skipping');
    return;
  }
  
  processedEvents.add(event.id);
  // Process event...
}

3. Implement Retry Logic

If your endpoint fails, Svix will automatically retry with exponential backoff. Ensure your endpoint is idempotent to handle retries safely.

4. Monitor Webhook Health

Check webhook delivery success rates in your API settings or the Svix dashboard:
  • Delivery success/failure rates
  • Response times
  • Error logs
  • Retry attempts

5. Use Test Mode

Test your webhook integration using test mode events:
// Create test print job
const printJob = await ip.prints.create({
  testmode: true,  // Fires test mode webhooks
  content: '<h1>Test</h1>',
  recipients: [{address: {/* ... */}}],
  confirmed: true
});

Testing Webhooks Locally

Use Built-in Testing

Test webhooks locally using the testing tools or ngrok:

Troubleshooting

Webhooks Not Receiving Events

Ensure your endpoint is publicly accessible and returns HTTP 200.
Make sure you’re correctly verifying the Svix signature.
View detailed delivery logs in your API settings or the Svix dashboard.
Use the built-in testing tools to send test events to your endpoint.

Common Errors

ErrorCauseSolution
400 Invalid signatureSignature verification failedCheck webhook secret is correct
timeoutEndpoint took too long to respondReturn 200 faster, process async
connection refusedEndpoint not accessibleCheck firewall, ensure server is running

Webhook Management Features

Manage your webhooks at account.intelliprint.net/api_keys:

Real-time Logs

View all webhook deliveries and responses

Manual Retry

Manually retry failed deliveries

Event Inspector

Inspect payload and headers

Testing Tools

Send test events to your endpoint
Advanced users: Access the Svix dashboard directly for additional features like webhook transformations, custom headers, and advanced filtering.

Rate Limits

Webhook delivery is not subject to API rate limits, but your endpoint should be able to handle:
  • Burst: Up to 100 requests/second during high-volume periods
  • Sustained: Average of 10-50 requests/second

Need Help?