---
title: "Webhooks"
description: "Send real-time notifications to external services when events occur"
---

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

# Webhooks

Webhooks allow you to send real-time HTTP notifications to external services when specific events occur in your store, such as order completions, refunds, or tracking updates.

---

## What Are Webhooks?

Webhooks are automated messages sent from FirearmCart to a URL you specify when certain events happen. They're useful for:

- **Syncing with external systems** - Update inventory, CRM, or accounting software
- **Triggering automations** - Send notifications, update databases, trigger workflows
- **Custom integrations** - Connect with any service that accepts HTTP requests

> **Access required:** Outgoing webhooks are part of **API & Webhooks** access â€” included on plans that carry it, or added with the API & Webhooks addon. Without it the Webhooks page redirects to billing, and no webhooks fire even if you configured them earlier.

---

## Available Events

### Standard Events

These webhook events are available with API & Webhooks access:

| Event | Description |
|-------|-------------|
| **Order Completed** | Triggered when a customer completes checkout |
| **Order Refunded** | Triggered when an order is refunded |
| **Order Voided** | Triggered when an order is voided |
| **Tracking Assigned** | Triggered when tracking information is added |
| **Order Delivered** | Triggered when an order is marked as delivered |
| **Customer Created** | Triggered when a customer record is first created |
| **Customer Updated** | Triggered when a customer's details change |

**Customer Created** fires wherever the record comes from: a checkout, a newsletter or account signup, a lead posted to the API, an imported marketplace order, or the **Customers** page in your dashboard. A returning shopper who checks out against an existing record does not fire it again.

**Customer Updated** fires when one of these changes: first name, last name, email, phone, marketing consent, tags, assigned FFL, tax customer code, or entity use code. Routine background writes — the shopper's IP address, timestamps — are ignored, so an order does not produce a Customer Updated webhook on its own. The **Customer Updated Fields** value tells you which fields changed.

### Enhanced Tracking Events

These events require **Enhanced Shipment Tracking** â€” a plan that includes it, or the Enhanced Tracking addon. Without it they don't appear in the Events picker, and they are never dispatched:

| Event | Description |
|-------|-------------|
| **Shipment In Transit** | Triggered when carrier scans package in transit |
| **Shipment Out for Delivery** | Triggered when package is out for delivery |
| **Shipment Delivered** | Triggered when carrier confirms delivery |

---

## Creating a Webhook

### Step 1: Open Webhook Settings

1. Go to **Settings > Webhooks**
2. Click **Add Webhook**

### Step 2: Configure Basic Settings

1. **Name** - Enter a descriptive name (e.g., "Inventory Sync", "CRM Update")
2. **Events** - Select which events should trigger this webhook
3. **Method** - Choose POST or GET
4. **Webhook URL** - Enter the endpoint URL that will receive the webhook

### Step 3: Set Up Security

1. **Secret Key** - Enter or generate a secret key (minimum 16 characters)
2. This secret is sent as the `X-Webhook-Secret` header with every request
3. Use it to verify requests are from FirearmCart

> **Tip:** Click **Generate** to create a secure random 32-character secret.

> **Note:** When editing an existing webhook, leaving the Secret Key blank keeps the current secret.

### Step 4: Configure Parameters

Map data fields to your webhook payload:

1. Click **Add Parameter**
2. Enter the parameter name (what your endpoint expects)
3. Select a value from the dropdown, or use a custom static value
4. Click the pencil icon to enter a custom value instead

### Step 5: Add Custom Headers (Optional)

Add any additional HTTP headers your endpoint requires:

1. Click **Add Header**
2. Enter the header name (e.g., "X-API-Key")
3. Enter the header value

### Step 6: Save

Click **Add Webhook** to create the webhook.

---

## Available Data Fields

When configuring parameters, you can map these data fields:

### Order Data

| Field | Description |
|-------|-------------|
| Order ID | Internal order identifier |
| Order Status | Current order status |
| Order Total | Total amount |
| Order Subtotal | Subtotal before tax/shipping |
| Order Tax | Tax amount |
| Order Shipping | Shipping cost |
| Order Discount | Discount applied |
| Order Created Date | When the order was placed |

### Customer Data

| Field | Description |
|-------|-------------|
| Customer ID | Internal customer identifier |
| Customer First Name | Customer's first name |
| Customer Last Name | Customer's last name |
| Customer Email | Customer's email address |
| Customer Phone | Customer's phone number |
| Customer Accepts Marketing | Whether the customer accepts marketing (`true` / `false`) |
| Customer Tags | The customer's tags, comma-separated |
| Customer Created Date | When the customer record was created |
| Customer Updated Date | When the customer record last changed |
| Customer Updated Fields | On **Customer Updated**, the fields that changed, comma-separated (for example `email,phone`) |

### Shipping Address

| Field | Description |
|-------|-------------|
| Shipping First Name | Recipient first name |
| Shipping Last Name | Recipient last name |
| Shipping Address 1 | Street address line 1 |
| Shipping Address 2 | Street address line 2 |
| Shipping City | City |
| Shipping State | State/Province |
| Shipping ZIP | Postal/ZIP code |
| Shipping Country | Country |

### Billing Address

| Field | Description |
|-------|-------------|
| Billing First Name | Billing first name |
| Billing Last Name | Billing last name |
| Billing Address 1 | Street address line 1 |
| Billing Address 2 | Street address line 2 |
| Billing City | City |
| Billing State | State/Province |
| Billing ZIP | Postal/ZIP code |
| Billing Country | Country |

The name on an address is the customer's — an address on file stores street, city, state and ZIP only — and the country is always `US`.

### Fulfillment Data

| Field | Description |
|-------|-------------|
| Fulfillment ID | Internal fulfillment identifier |
| Tracking Number | Carrier tracking number |
| Tracking Carrier | Shipping carrier name |
| Tracking URL | Direct link to tracking page |
| Fulfillment Status | Current fulfillment status |

---

## Webhook Headers

Every webhook request includes these headers:

| Header | Description |
|--------|-------------|
| `Content-Type` | Always `application/json` |
| `X-Webhook-Secret` | Your configured secret key |
| `X-Webhook-Event` | The event that triggered the webhook |

Plus any custom headers you configure.

---

## Webhook Payload

The payload includes:

- Your configured parameters with their mapped values
- `_event` - The event name that triggered the webhook
- `_timestamp` - ISO 8601 timestamp of when the webhook was sent

**Example payload:**

```json
{
  "order_id": "1042",
  "customer_email": "customer@example.com",
  "total": "299.99",
  "tracking_number": "1Z999AA10123456784",
  "_event": "tracking.assigned",
  "_timestamp": "2026-01-11T15:30:00Z"
}
```

Every field is optional, and a field that has no value for the event that fired is sent as `null`. Customer fields are filled in on every event that has a customer behind it, including the order events. The reverse is not true: the customer events carry customer fields only, so order, shipping, billing and fulfillment fields are `null` on them — map those on a webhook subscribed to the order events instead.

**Example customer payload:**

```json
{
  "customer_id": "1043",
  "customer_email": "customer@example.com",
  "customer_accepts_marketing": true,
  "customer_updated_fields": "email,phone",
  "_event": "customer.updated",
  "_timestamp": "2026-09-16T15:30:00Z"
}
```

---

## Managing Webhooks

### Viewing Webhooks

Go to **Settings > Webhooks** to see all your webhooks with:

- ID, name and URL
- Subscribed events (first two shown, the rest as a `+n` badge)
- Status toggle
- Action menu

Use the search box to filter by name, URL, or ID.

### Editing a Webhook

1. Click the **...** menu on a webhook
2. Select **Edit**
3. Update settings as needed
4. Click **Save Changes**

### Enabling/Disabling

Toggle the switch in the **Status** column to enable or disable a webhook without deleting it. Disabled webhooks are skipped entirely when an event fires.

### Viewing Logs

1. Click the **...** menu on a webhook
2. Select **View Logs** (the count of stored logs is shown next to it)
3. Review delivery history including:
   - Event
   - Status (pending, success, failed)
   - Response status code
   - Attempts (out of 3)
   - Date

### Deleting a Webhook

1. Click the **...** menu on a webhook
2. Select **Delete**
3. Confirm deletion

> **Note:** Deleting a webhook stops all future deliveries. Existing delivery logs are not removed immediately â€” they age out with the normal 30-day log retention.

---

## Delivery & Retries

### Delivery Behavior

- Webhooks are delivered within seconds of the event
- Timeout: 30 seconds per request
- Successful delivery: HTTP 2xx response

### Retry Policy

If delivery fails, FirearmCart retries automatically. There are **3 delivery attempts in total** â€” the initial send plus two retries:

| Attempt | When |
|---------|------|
| Initial delivery | Immediately after the event |
| 1st retry | ~5 minutes after the initial failure |
| 2nd retry | ~30 minutes after the first retry fails |

After the third attempt fails, the log row is marked **failed** and no further retries are scheduled. The **Attempts** column in the log shows progress as `1/3`, `2/3`, `3/3`.

### Log Retention

Webhook logs are retained for 30 days.

---

## Troubleshooting

### Webhooks Not Triggering

**Symptoms:** Events occur but webhooks aren't sent

**Solutions:**
- Confirm your plan or addon still includes API & Webhooks access â€” without it nothing is dispatched, even for webhooks you created earlier
- Verify the webhook is Active (switch is on)
- Check that the event is selected
- For the three shipment events, confirm you still have Enhanced Shipment Tracking
- Review webhook logs for errors

### Delivery Failures

**Symptoms:** Webhook logs show failed status

**Solutions:**
- Verify your endpoint URL is correct
- Check your server is accepting connections
- Ensure your endpoint returns HTTP 2xx for success
- Check server logs for errors

### Invalid Secret Error

**Symptoms:** Your endpoint rejects the webhook

**Solutions:**
- Compare the secret in FirearmCart with your endpoint configuration
- Ensure you're reading the `X-Webhook-Secret` header correctly
- Check for whitespace or encoding issues

### Missing Data

**Symptoms:** Webhook payload is missing expected fields

**Solutions:**
- Review your parameter configuration
- Ensure you've mapped all needed fields
- Check that the data exists for the order (e.g., customer has phone number)

---

## Security Best Practices

### Verify the Secret

Always verify the `X-Webhook-Secret` header matches your configured secret before processing.

### Use HTTPS

Always use HTTPS URLs to encrypt webhook data in transit.

### Validate Data

Don't trust webhook data blindly. Validate and sanitize before using.

### Respond Quickly

Return a response within 30 seconds to avoid timeouts and retries.

---

## Related Documentation

- [Integrations](/integrations) - All available integrations
- [Orders](/orders) - Order management
- [Printify](/integrations/printify) - Print-on-demand fulfillment
- [ShipStation](/integrations/shipstation) - Shipping integration

Source: https://docs.firearmcart.com/integrations/webhooks/index.mdx
