> ## Documentation Index
> Fetch the complete documentation index at: https://docs.atlaspay.cc/llms.txt
> Use this file to discover all available pages before exploring further.

# Webhooks

Receive real-time notifications for payment events.

## Overview

Webhooks allow your server to receive automatic notifications when events occur in your Atlas account. This is essential for:

* Order fulfillment after successful payments
* Sending confirmation emails
* Updating inventory
* Handling failed payments

## Setting Up Webhooks

1. Go to your [Dashboard](https://atlas.co/dashboard/webhooks)
2. Add your endpoint URL (e.g., `https://yoursite.com/webhooks/atlas`)
3. Select the events you want to receive
4. Copy your webhook signing secret

## Event Types

| Event                | Description                             |
| -------------------- | --------------------------------------- |
| `payment.authorized` | Payment was authorized (manual capture) |
| `payment.captured`   | Payment was captured successfully       |
| `payment.failed`     | Payment was declined or failed          |
| `payment.refunded`   | Payment was refunded (full or partial)  |
| `session.expired`    | Payment session expired                 |
| `session.canceled`   | Payment session was canceled            |

## Webhook Payload

```json theme={null}
{
  "id": "evt_1234567890",
  "type": "payment.captured",
  "created": "2024-01-15T10:30:00Z",
  "livemode": false,
  "data": {
    "object": {
      "id": "pay_8xM2nQ4vR7kL9pYz",
      "session_id": "sess_2xK9mN7vQ3pL8wYz",
      "amount": 4990,
      "currency": "USD",
      "status": "captured",
      "payment_method_type": "card",
      "card": {
        "brand": "visa",
        "last4": "4242"
      }
    }
  }
}
```

## Verifying Signatures

Always verify webhook signatures to ensure requests are from Atlas:

```javascript theme={null}
const crypto = require('crypto');

function verifyWebhookSignature(payload, signature, secret) {
  const expectedSignature = crypto
    .createHmac('sha256', secret)
    .update(payload)
    .digest('hex');

  return crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(expectedSignature)
  );
}

// In your webhook handler
app.post('/webhooks/atlas', (req, res) => {
  const signature = req.headers['x-atlas-signature'];
  const payload = JSON.stringify(req.body);

  if (!verifyWebhookSignature(payload, signature, process.env.WEBHOOK_SECRET)) {
    return res.status(401).send('Invalid signature');
  }

  const event = req.body;

  switch (event.type) {
    case 'payment.captured':
      // Fulfill the order
      await fulfillOrder(event.data.object.session_id);
      break;
    case 'payment.failed':
      // Notify the customer
      await notifyPaymentFailed(event.data.object);
      break;
  }

  res.status(200).send('OK');
});
```

## Best Practices

1. **Return 200 quickly** - Process webhooks asynchronously to avoid timeouts
2. **Handle duplicates** - Use idempotency keys or check if you've already processed the event
3. **Verify signatures** - Always verify the `x-atlas-signature` header
4. **Use HTTPS** - Webhook endpoints must use HTTPS in production
5. **Retry logic** - Atlas retries failed webhooks with exponential backoff

## Retry Policy

If your endpoint returns a non-2xx status code, Atlas will retry:

| Attempt | Delay      |
| ------- | ---------- |
| 1       | Immediate  |
| 2       | 5 minutes  |
| 3       | 30 minutes |
| 4       | 2 hours    |
| 5       | 24 hours   |

After 5 failed attempts, the webhook is marked as failed and won't be retried.
