# 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"
    }
  }'
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://devdocs.joy.so/webhook-api/best-practices.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
