# Best Practices

{% hint style="success" %}
**Pro Tip:** Following these best practices ensures reliable webhook processing and optimal performance.
{% endhint %}

## 1. Endpoint requirements

* **HTTPS Only**: Webhook endpoints must use HTTPS for security
* **Response Time**: Respond within 5 seconds to avoid timeouts
* **Status Codes**: Return 2xx status codes to acknowledge receipt
* **Error Handling**: Return 4xx/5xx status codes to trigger retry mechanism

## 2. Idempotency

Webhooks may be resent if no acknowledgment is received. Implement idempotency using:

```javascript
// Use webhookId to prevent duplicate processing
const processedWebhooks = new Set();

app.post('/webhook', (req, res) => {
  const {webhookId} = req.body;
  
  if (processedWebhooks.has(webhookId)) {
    return res.status(200).send('Already processed');
  }
  
  // Process webhook...
  processedWebhooks.add(webhookId);
  res.status(200).send('OK');
});
```

## 3. Async processing

For long-running processes, respond immediately and queue for background processing:

```javascript
app.post('/webhook', async (req, res) => {
  // Respond immediately
  res.status(200).send('OK');
  
  // Queue for background processing
  await addToQueue('webhook-processing', req.body);
});
```

## 4. Error monitoring

Implement proper logging and monitoring:

```javascript
app.post('/webhook', (req, res) => {
  try {
    // Verify HMAC
    if (!verifyWebhook(req.body, req.headers['x-joy-loyalty-hmac-sha256'], SECRET_KEY)) {
      console.error('Invalid HMAC signature', {
        headers: req.headers,
        body: req.body
      });
      return res.status(401).send('Invalid signature');
    }
    
    // Process webhook
    processWebhook(req.body);
    res.status(200).send('OK');
    
  } catch (error) {
    console.error('Webhook processing error', {
      error: error.message,
      stack: error.stack,
      body: req.body
    });
    
    // Still return 200 to prevent retries for application errors
    res.status(200).send('Error logged');
  }
});
```

## 5. Testing

Test your webhook endpoints thoroughly:

```bash
# Test webhook endpoint with sample payload
curl -X POST "https://your-server.com/webhook/points" \
  -H "Content-Type: application/json" \
  -H "X-Joy-Loyalty-Hmac-Sha256: your_test_signature" \
  -H "X-Joy-Loyalty-Topic: points/earned" \
  -d '{
    "webhookId": "test_webhook_123",
    "triggeredAt": "2024-01-15T10:30:00.000Z",
    "customer": {
      "email": "test@example.com",
      "name": "Test Customer",
      "shopifyCustomerId": "gid://shopify/Customer/123"
    }
  }'
```
