Skip to main content

Webhooks

Webhooks allow you to receive real-time event notifications from AXRO (such as order updates, shipment notifications, etc.) by subscribing an HTTPS endpoint. When events occur, AXRO will send an HTTP POST request to your configured endpoint with a signed JSON payload.

Overview

Authentication: All webhook subscription management endpoints require Authorization: Bearer YOUR_ACCESS_TOKEN.

Security: Each subscription includes an API token that:

  • Is used as the HMAC secret to sign the request body
  • Should be validated on your endpoint to verify authenticity

Delivery Semantics:

  • Single attempt: Webhooks are delivered once with a 10-second HTTP timeout
  • Success: Any 2xx HTTP response is considered successful
  • Failures: Non-2xx responses or timeouts are logged but not retried
  • No Dead Letter Queue: Failed deliveries are not stored or replayed

Signature Verification: Each webhook includes:

  • X-Signature-Algorithm: Always HMAC-SHA256
  • X-Signature-Timestamp: Unix timestamp (seconds) when the signature was generated
  • X-Signature: Format is sha256={hex} where hex is the HMAC-SHA256 signature of "{timestamp}.{raw_body_bytes}" using your API token as the secret

Create or Update Webhook Subscription

POST/api/v1/webhook/subscribe/

Create or update the webhook subscription for your customer account. If a subscription already exists, it will be updated with the new endpoint URL and token.

JSON body parameters

NameTypeRequiredDescription
endpoint_urlstringYour webhook endpoint URL. Must be https:// or http://localhost (for testing)
api_tokenstringToken used for authentication and HMAC signature verification

URL Validation:

  • https:// is allowed for any domain
  • http:// is only allowed for localhost, 127.0.0.1, or 0.0.0.0
  • Invalid URLs return HTTP 422 Unprocessable Entity

Example Request

curl -X POST "https://api.axro.com/api/v1/webhook/subscribe/" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"endpoint_url": "https://webhooks.example.com/axro",
"api_token": "your_secure_webhook_token_here"
}'

Example Response

{
"customer_number": "123456",
"endpoint_url": "https://webhooks.example.com/axro",
"active": true,
"token_tail": "_here"
}

Response Fields:

  • customer_number: Your customer number
  • endpoint_url: The subscribed webhook URL
  • active: Whether the subscription is active
  • token_tail: Last 4 characters of the API token (for verification)

Get Webhook Subscription

GET/api/v1/webhook/subscription/

Retrieve the current webhook subscription for your customer account.

Example Request

curl -X GET "https://api.axro.com/api/v1/webhook/subscription/" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN"

Example Response

{
"customer_number": "123456",
"endpoint_url": "https://webhooks.example.com/axro",
"active": true,
"token_tail": null
}

Note: The token_tail field is null when retrieving a subscription (only shown when creating/updating). Returns HTTP 404 if no subscription exists.


Delete Webhook Subscription

DELETE/api/v1/webhook/subscription/

Delete the webhook subscription for your customer account.

Example Request

curl -X DELETE "https://api.axro.com/api/v1/webhook/subscription/" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN"

Response

HTTP 204 No Content - The subscription was successfully deleted (no response body).


Webhook Delivery Format

When events occur, AXRO sends an HTTP POST request to your configured endpoint.

HTTP Request Details

  • Method: POST
  • Content-Type: application/json
  • Timeout: 10 seconds
  • Retries: None (single attempt only)
  • Success: Any 2xx HTTP status code

HTTP Headers

Each webhook request includes the following headers:

HeaderDescription
Content-TypeAlways application/json
X-Signature-AlgorithmAlways HMAC-SHA256
X-Signature-TimestampUnix timestamp (seconds) when the signature was generated
X-SignatureHMAC signature in format sha256={hex}
X-Event-IDUnique event identifier (UUID) - use for idempotency
X-Event-TypeEvent type (e.g., customer:address:completed, order:status:changed)
X-Customer-NumberYour customer number

Example headers:

Content-Type: application/json
X-Signature-Algorithm: HMAC-SHA256
X-Signature-Timestamp: 1730798400
X-Signature: sha256=3f6b2c1a4e8d9f0e7c5b3a2d1f9e8c7b6a5d4e3f2c1b0a9f8e7d6c5b4a3d2e1f0
X-Event-ID: 8c1b7c3e-9c5a-4b6a-8a8e-22a6be2a8f41
X-Event-Type: order:created
X-Customer-Number: 123456

Request Body (Event Envelope)

All webhook payloads follow this canonical envelope structure:

Customer Address Verified Event Example

{
"id": "8c1b7c3e-9c5a-4b6a-8a8e-22a6be2a8f41",
"type": "customer:address:completed",
"timestamp": "2025-06-25T14:30:00Z",
"customer_number": "123456",
"data": {
"address_id": "03e6ad6b-205d-56fa-9a99-3c6acd0f9123",
"customer_number": "123456"
}
}

Order Status Changed Event Example

{
"id": "8c1b7c3e-9c5a-4b6a-8a8e-22a6be2a8f41",
"type": "order:status:changed",
"timestamp": "2025-06-25T14:30:00Z",
"customer_number": "123456",
"data": {
"customer_number": "123456",
"order_number": "233945",
"shipment_number": "9876543",
"commission": "my custom reference"
}
}

Order Tracking Created Event Example

{
"id": "8c1b7c3e-9c5a-4b6a-8a8e-22a6be2a8f41",
"type": "order:tracking:created",
"timestamp": "2025-06-25T14:30:00Z",
"customer_number": "123456",
"data": {
"customer_number": "123456",
"shipment_number": "9876543",
"tracking_code": "1Z657290bb5140c1234",
"carrier": "UPS",
"commission": "my custom reference"
}
}
  • Use shipment_number to look up shipment details via Get Shipment API
  • Use shipment_number to look up tracking info via Get Tracking API
  • Use tracking_code and carrier to provide tracking updates to your customers

Envelope Fields:

  • id: Unique event ID - use for deduplication
  • type: Event type (matches X-Event-Type header)
  • timestamp: ISO 8601 UTC timestamp with Z suffix
  • customer_number: Your customer number
  • data: Event-specific payload (structure varies by event type)

Signature Verification

To verify the webhook signature and ensure the request is authentic:

  1. Extract the signature components:

    • Get the X-Signature-Timestamp header value
    • Get the X-Signature header value and remove the sha256= prefix
    • Read the raw request body bytes (do not parse or modify)
  2. Construct the signed string:

    string_to_sign = "{timestamp}.{raw_body_bytes}"

    Example: "1730798400.{\"id\":\"8c1b..."}" (timestamp as string, followed by dot, followed by the exact raw body)

  3. Compute the expected signature:

    expected_signature = hex(hmac_sha256(api_token, string_to_sign))
  4. Compare signatures:

    • Use constant-time comparison to prevent timing attacks
    • The computed signature should match the value from the X-Signature header (after removing sha256=)
  5. Validate timestamp (recommended):

    • Check that the timestamp is recent (e.g., within 5 minutes)
    • This prevents replay attacks

Example verification code:

function verifyWebhookSignature($apiToken, $rawBody, $timestamp, $signature) {
// Remove 'sha256=' prefix from signature
$receivedSig = str_replace('sha256=', '', $signature);

// Construct the string to sign
$stringToSign = $timestamp . '.' . $rawBody;

// Compute expected signature
$expectedSig = hash_hmac('sha256', $stringToSign, $apiToken);

// Constant-time comparison
if (!hash_equals($expectedSig, $receivedSig)) {
return false;
}

// Verify timestamp is recent (within 5 minutes)
$now = time();
if (abs($now - intval($timestamp)) > 300) {
return false;
}

return true;
}

// Usage in your webhook endpoint
$apiToken = 'your_secure_webhook_token_here';
$rawBody = file_get_contents('php://input');
$timestamp = $_SERVER['HTTP_X_SIGNATURE_TIMESTAMP'];
$signature = $_SERVER['HTTP_X_SIGNATURE'];

if (!verifyWebhookSignature($apiToken, $rawBody, $timestamp, $signature)) {
http_response_code(401);
exit('Invalid signature');
}

// Process the webhook...
$payload = json_decode($rawBody, true);

Best Practices

  1. Respond quickly: Return a 2xx status code as soon as you receive and verify the webhook. Process the event asynchronously if needed.
  2. Idempotency: Use the X-Event-ID header to track processed events and prevent duplicate processing.
  3. Validate signatures: Always verify the HMAC signature before processing the payload.
  4. Check timestamps: Reject webhooks with timestamps older than 5 minutes to prevent replay attacks.
  5. Log deliveries: Keep logs of received webhooks for debugging and auditing.
  6. Handle failures gracefully: Since there are no retries, ensure your endpoint is highly available.
  7. Use HTTPS: Always use HTTPS endpoints in production to protect the webhook data in transit.