Small integration service that receives Shopify order webhooks, verifies authenticity, validates and transforms the payload into an internal SalesOrder contract, applies business rules, prevents duplicate processing, and stores the processed event.
Commerce and operations teams often receive raw order events from ecommerce platforms, but those payloads are not always ready to use for internal workflows such as fulfillment, invoicing, CRM, or operational reporting.
This project shows how to:
- Receive external webhook events
- Verify webhook authenticity
- Validate incoming payloads
- Transform external data into an internal business contract
- Apply operational business rules
- Prevent duplicate processing
- Store processed events for traceability
Shopify Webhook
↓
POST /webhooks/shopify/orders-created
↓
Verify HMAC signature
↓
Validate payload with Zod
↓
Map to internal SalesOrder
↓
Apply business rules
↓
Check idempotency
↓
Store processed event
↓
Return structured response
- Node.js
- TypeScript
- Express
- Zod
- Pino
- Firebase Admin / Firestore
- Vitest
- Health check endpoint
- Shopify webhook endpoint
- Raw body capture for HMAC verification
- HMAC signature validation
- Payload validation with Zod
- Mapping to internal
SalesOrder - Business rules:
invoiceRequiredcustomerTypeprioritycontainsConsumables
- Idempotency using
webhookIdor order fallback - Event persistence
- Event query endpoints
- Unit tests
Returns service health information.
Receives a Shopify order webhook, validates it, transforms it, and stores the processed event.
Returns stored processed events.
Returns a processed event by idempotency key.
{
"source": "shopify",
"sourceOrderId": "1001",
"sourceOrderName": "#1001",
"channel": "ecommerce",
"createdAt": "2026-03-12T10:00:00Z",
"customer": {
"fullName": "Juan Pérez",
"email": "cliente@test.com",
"type": "business"
},
"totals": {
"currency": "MXN",
"totalAmount": 2499
},
"flags": {
"invoiceRequired": true,
"priority": "high",
"containsConsumables": true
},
"shippingAddress": {
"city": "CDMX",
"state": "Ciudad de México",
"country": "Mexico",
"zipCode": "06000"
},
"items": [
{
"sku": "ALX-FILTER-01",
"name": "Filtro ALX1 PCC",
"quantity": 2,
"unitPrice": 999.5
}
]
}npm installCreate a .env file based on .env.example.
npm run devThis project supports two persistence modes:
filefirestore
Set this in .env:
EVENT_REPOSITORY=firestoreFor local Firestore access, provide Google Application Default Credentials:
export GOOGLE_APPLICATION_CREDENTIALS="/path/to/service-account.json"Run unit tests with:
npm testA sample payload is included in:
examples/shopify-order-created.json
src/
config/
controllers/
domain/
mappers/
schemas/
lib/
repositories/
routes/
services/
types/
tests/
unit/
examples/
storage/
scripts/
- No frontend
- No dashboard
- No user authentication
- No multi-provider support in v1
- No queues or event bus in v1
The goal is to keep the project small, realistic, and focused on integration and operational workflows.