Webhooks

Webhooks allow you to receive real-time HTTP notifications when events occur in your Price2b account. Instead of polling the API, your server receives a POST request when something happens.

Available events

EventDescription
order.createdNew order received
order.updatedOrder status changed
order.cancelledOrder was cancelled
shipment.createdLabel generated, tracking available
shipment.deliveredPackage delivered
inventory.low_stockStock below threshold
manifest.processedCourier manifest completed

Configuring webhooks

  1. Go to Account SettingsWebhooks
  2. Click Add Webhook Endpoint
  3. Enter your endpoint URL
  4. Select the events to subscribe to
  5. Save and note your signing secret

Webhook payload

All webhooks are sent as POST requests with a JSON body:

{
  "id": "evt_abc123",
  "type": "order.created",
  "created_at": "2026-01-20T14:30:00Z",
  "data": {
    "id": 5001,
    "order_number": "ORD-2026-001234",
    "channel": "amazon",
    "status": "pending",
    "totals": {
      "total": 114.98,
      "currency": "USD"
    }
  }
}
FieldDescription
idUnique event identifier
typeEvent type
created_atWhen the event occurred
dataEvent-specific payload

Verifying signatures

All webhooks include a signature for verification:

X-Price2b-Signature: sha256=abc123...
X-Price2b-Timestamp: 1706284200

Verify the signature to ensure the webhook is authentic:

Signature verification

const crypto = require('crypto')

function verifyWebhook(payload, signature, timestamp, secret) {
  const signedPayload = `${timestamp}.${payload}`
  const expectedSignature = crypto
    .createHmac('sha256', secret)
    .update(signedPayload)
    .digest('hex')

  return `sha256=${expectedSignature}` === signature
}

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

  if (!verifyWebhook(payload, signature, timestamp, WEBHOOK_SECRET)) {
    return res.status(401).send('Invalid signature')
  }

  // Process the webhook
  handleEvent(req.body)
  res.status(200).send('OK')
})

Event payloads

order.created

{
  "id": "evt_abc123",
  "type": "order.created",
  "data": {
    "id": 5001,
    "order_number": "ORD-2026-001234",
    "channel": "amazon",
    "channel_order_id": "114-1234567-1234567",
    "status": "pending",
    "customer": {
      "name": "Juan Pérez",
      "email": "juan@example.com"
    },
    "items": [...],
    "totals": {
      "subtotal": 99.98,
      "shipping": 15.00,
      "total": 114.98,
      "currency": "USD"
    },
    "created_at": "2026-01-20T14:30:00Z"
  }
}

shipment.created

{
  "id": "evt_def456",
  "type": "shipment.created",
  "data": {
    "shipment_id": 12345,
    "order_id": 5001,
    "carrier": "fedex",
    "service": "INTERNATIONAL_ECONOMY",
    "tracking_number": "794644790303",
    "label_url": "https://app.price2b.com/api/v1/shipping/shipments/12345/label",
    "estimated_delivery": "2026-02-05",
    "created_at": "2026-01-20T15:00:00Z"
  }
}

inventory.low_stock

{
  "id": "evt_ghi789",
  "type": "inventory.low_stock",
  "data": {
    "product_id": 12345,
    "sku": "PROD-001",
    "name": "Wireless Headphones",
    "current_stock": 5,
    "threshold": 10,
    "warehouse_id": 1,
    "warehouse_name": "Miami Warehouse"
  }
}

Best practices

  1. Respond quickly - Return 200 within 5 seconds, process async
  2. Handle duplicates - Use id to detect and ignore duplicates
  3. Verify signatures - Always validate before processing
  4. Log everything - Keep records for debugging
  5. Handle failures - We retry failed webhooks with exponential backoff

Retry policy

Failed webhooks (non-2xx response or timeout) are retried:

AttemptDelay
1Immediate
21 minute
35 minutes
430 minutes
52 hours
624 hours

After 6 failed attempts, the webhook is marked as failed and no more retries are attempted. You can manually retry from the dashboard.

Testing webhooks

Use the Send Test button in the webhook configuration to send a test payload to your endpoint. This helps verify your integration before going live.


Webhook Subscriptions API

Manage webhook subscriptions programmatically via the API.

Base Path: /api/webhook-subscriptions Authentication: Bearer token (Sanctum)


GET/api/webhook-subscriptions/available-events

List available events

Get all events available for webhook subscription.

Available events

EventDescription
manifest.processing_completedManifest processing completed successfully
manifest.invalid_cuit_detectedInvalid CUITs detected (quota=0 or validation error)
manifest.total_dueTotal due amount calculated for manifest
manifest.processing_failedManifest processing failed critically
document.uploadedTransport document uploaded
document.validatedTransport document passed validation
document.approvedTransport document approved
document.rejectedTransport document rejected
document.supersededTransport document replaced by newer version
document.downloadedTransport document downloaded

Request

GET
/api/webhook-subscriptions/available-events
curl https://app.price2b.com/api/webhook-subscriptions/available-events \
  -H "Authorization: Bearer {token}"

Response

{
  "success": true,
  "data": [
    {
      "event": "manifest.processing_completed",
      "type": "manifest",
      "action": "processing_completed",
      "description": "Fired when manifest processing completes successfully"
    },
    {
      "event": "manifest.invalid_cuit_detected",
      "type": "manifest",
      "action": "invalid_cuit_detected",
      "description": "Fired when invalid CUITs detected"
    },
    {
      "event": "document.uploaded",
      "type": "document",
      "action": "uploaded",
      "description": "Fired when a transport document is uploaded"
    }
  ],
  "count": 10
}

GET/api/webhook-subscriptions

List subscriptions

Get all webhook subscriptions for the authenticated user.

Request

GET
/api/webhook-subscriptions
curl https://app.price2b.com/api/webhook-subscriptions \
  -H "Authorization: Bearer {token}"

Response

{
  "success": true,
  "data": [
    {
      "id": 1,
      "endpoint_url": "https://partner.example.com/webhooks/price2b",
      "events": ["manifest.processing_completed", "manifest.invalid_cuit_detected"],
      "active": true,
      "health_status": "healthy",
      "health_status_color": "green",
      "failed_deliveries": 0,
      "last_delivery_at": "2026-01-20T18:30:00+00:00",
      "last_success_at": "2026-01-20T18:30:00+00:00",
      "created_at": "2026-01-01T12:00:00+00:00",
      "updated_at": "2026-01-20T18:30:00+00:00"
    }
  ],
  "count": 1
}

POST/api/webhook-subscriptions

Create subscription

Create a new webhook subscription. An HMAC secret is generated automatically and shown only once.

Required attributes

  • Name
    endpoint_url
    Type
    string
    Description

    URL where webhooks will be sent. Max 500 characters.

  • Name
    events
    Type
    array
    Description

    List of events to subscribe to.

Optional attributes

  • Name
    active
    Type
    boolean
    Description

    Activate subscription immediately (default: true).

Save the hmac_secret securely. It is only shown once during creation and is required for verifying webhook signatures.

Request

POST
/api/webhook-subscriptions
curl -X POST https://app.price2b.com/api/webhook-subscriptions \
  -H "Authorization: Bearer {token}" \
  -H "Content-Type: application/json" \
  -d '{
    "endpoint_url": "https://partner.example.com/webhooks/price2b",
    "events": [
      "manifest.processing_completed",
      "manifest.invalid_cuit_detected",
      "document.approved"
    ],
    "active": true
  }'

Response (201 Created)

{
  "success": true,
  "message": "Webhook subscription created successfully",
  "data": {
    "id": 1,
    "endpoint_url": "https://partner.example.com/webhooks/price2b",
    "hmac_secret": "a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7r8s9t0u1v2w3x4y5z6",
    "events": [
      "manifest.processing_completed",
      "manifest.invalid_cuit_detected",
      "document.approved"
    ],
    "active": true,
    "created_at": "2026-01-20T18:00:00+00:00"
  },
  "important": "Save the hmac_secret securely. It will not be shown again."
}

GET/api/webhook-subscriptions/{id}

Get subscription

Get details of a specific subscription including health status and delivery history.

Request

GET
/api/webhook-subscriptions/1
curl https://app.price2b.com/api/webhook-subscriptions/1 \
  -H "Authorization: Bearer {token}"

Response

{
  "success": true,
  "data": {
    "id": 1,
    "endpoint_url": "https://partner.example.com/webhooks/price2b",
    "events": ["manifest.processing_completed"],
    "active": true,
    "health_status": "healthy",
    "health_status_color": "green",
    "failed_deliveries": 0,
    "last_delivery_at": "2026-01-20T18:30:00+00:00",
    "last_success_at": "2026-01-20T18:30:00+00:00",
    "created_at": "2026-01-01T12:00:00+00:00",
    "updated_at": "2026-01-20T18:30:00+00:00"
  }
}

PUT/api/webhook-subscriptions/{id}

Update subscription

Update an existing subscription. Can change endpoint URL, events, or active status.

Optional attributes

  • Name
    endpoint_url
    Type
    string
    Description

    New endpoint URL.

  • Name
    events
    Type
    array
    Description

    New list of events to subscribe to.

  • Name
    active
    Type
    boolean
    Description

    Activate or deactivate the subscription.

Request

PUT
/api/webhook-subscriptions/1
curl -X PUT https://app.price2b.com/api/webhook-subscriptions/1 \
  -H "Authorization: Bearer {token}" \
  -H "Content-Type: application/json" \
  -d '{
    "events": [
      "manifest.processing_completed",
      "document.approved",
      "document.rejected"
    ],
    "active": true
  }'

Response

{
  "success": true,
  "message": "Webhook subscription updated successfully",
  "data": {
    "id": 1,
    "endpoint_url": "https://partner.example.com/webhooks/price2b",
    "events": [
      "manifest.processing_completed",
      "document.approved",
      "document.rejected"
    ],
    "active": true,
    "updated_at": "2026-01-20T18:45:00+00:00"
  }
}

DELETE/api/webhook-subscriptions/{id}

Delete subscription

Delete a webhook subscription. This action cannot be undone.

Request

DELETE
/api/webhook-subscriptions/1
curl -X DELETE https://app.price2b.com/api/webhook-subscriptions/1 \
  -H "Authorization: Bearer {token}"

Response

{
  "success": true,
  "message": "Webhook subscription deleted successfully"
}

POST/api/webhook-subscriptions/{id}/test

Test subscription

Send a test webhook to verify your endpoint is correctly configured.

Request

POST
/api/webhook-subscriptions/1/test
curl -X POST https://app.price2b.com/api/webhook-subscriptions/1/test \
  -H "Authorization: Bearer {token}"

Response (Success)

{
  "success": true,
  "message": "Test webhook sent successfully",
  "data": {
    "status_code": 200,
    "response_time_ms": 245
  }
}

Response (Failure)

{
  "success": false,
  "message": "Test webhook delivery failed",
  "data": {
    "status_code": 500,
    "error": "Connection refused"
  }
}

Health status

Subscriptions have a health status based on delivery success:

StatusColorDescription
healthygreenNo failed deliveries
degradedyellow1-5 consecutive failures
unhealthyred6-9 consecutive failures
disabledgray10+ failures (auto-disabled)

After 10 consecutive failures, the subscription is automatically deactivated. Reactivate it after fixing your endpoint.

Was this page helpful?