Fulfillment Metrics API
The same fulfillment data you see in the 3PL Pulse dashboard, available as a REST API. Pull metrics into your own dashboards, trigger Slack alerts on SLA breaches, feed weekly reports to your BI tools.
Developer Preview: We're piloting this with a small group of Shopify merchants. The spec below reflects real data we already collect. Request early access if you want programmatic access to your fulfillment metrics.
Overview
3PL Pulse connects to ShipBob, Amazon MCF, and other providers through direct API integrations, normalizes the events, and calculates fulfillment metrics: handoff time, SLA compliance, on-time rate, order timelines. This REST API exposes that data over standard HTTP endpoints.
Use it to pull metrics into internal dashboards, fire Slack alerts when orders breach their SLA, generate weekly performance reports, or feed fulfillment data into your BI tools. Any language, any platform, any cron job.
Looking for AI agent access instead? See the Fulfillment MCP Server, which exposes the same data through the Model Context Protocol.
What you can build
- Pull a weekly ops report with one GET request
- Fire Slack alerts when orders breach their SLA
- Feed normalized metrics into Looker or Metabase
- Compare providers on the same definitions and measurement points
Authentication
Bearer token authentication. API keys are generated from your 3PL Pulse dashboard and scoped to your account's connected providers.
curl -H "Authorization: Bearer pulse_live_abc123..." \
https://api.3plpulse.com/v1/metrics Keys can be scoped to read-only or full access. Revoke any key instantly from the dashboard.
Base URL
https://api.3plpulse.com/v1
All endpoints are versioned in the URL. The current version is v1.
Endpoints
Five read endpoints covering aggregate metrics, provider comparison, SLA breaches, order timelines, and order listing. All return JSON.
GET /v1/metrics
Aggregate fulfillment performance metrics for a given period.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
period | string | Yes | "today", "last_7_days", "last_30_days", or "custom" |
start_date | string | No | ISO 8601 date. Required when period is "custom" |
end_date | string | No | ISO 8601 date. Required when period is "custom" |
provider | string | No | Filter to a specific provider: "shipbob", "amazon_mcf", etc. |
granularity | string | No | "summary" (default) or "daily". Daily returns an array of data points |
Example Request
curl -H "Authorization: Bearer pulse_live_abc123..." \
"https://api.3plpulse.com/v1/metrics?period=last_7_days" Example Response
{
"period": "last_7_days",
"start_date": "2026-02-12",
"end_date": "2026-02-18",
"order_volume": 847,
"avg_handoff_time_hours": 16.3,
"handoff_time_p95_hours": 28.1,
"on_time_rate": 0.94,
"sla_compliance_rate": 0.91,
"sla_breaches": 8
} GET /v1/metrics/providers
Side-by-side performance comparison across your connected 3PL providers.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
period | string | No | Default: "last_30_days" |
start_date | string | No | ISO 8601 date. Required when period is "custom" |
end_date | string | No | ISO 8601 date. Required when period is "custom" |
providers | string | No | Comma-separated list. Default: all connected providers |
metric | string | No | "handoff_time", "on_time_rate", "sla_compliance", or "all" (default) |
Example Request
curl -H "Authorization: Bearer pulse_live_abc123..." \
"https://api.3plpulse.com/v1/metrics/providers?period=last_30_days" Example Response
{
"period": "last_30_days",
"providers": {
"shipbob": {
"order_volume": 2403,
"handoff_time": {
"p50_hours": 14.1,
"p95_hours": 26.8,
"trend": "worsening"
},
"on_time_rate": {
"rate": 0.92,
"trend": "stable"
},
"sla_compliance": {
"rate": 0.89,
"trend": "worsening"
}
},
"amazon_mcf": {
"order_volume": 891,
"handoff_time": {
"p50_hours": 8.4,
"p95_hours": 14.2,
"trend": "improving"
},
"on_time_rate": {
"rate": 0.98,
"trend": "stable"
},
"sla_compliance": {
"rate": 0.97,
"trend": "stable"
}
}
}
} GET /v1/breaches
Orders that have breached or are at risk of breaching their SLA threshold.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
threshold | string | No | Default: "2_business_days". Options: "1_business_day", "2_business_days", "3_business_days" |
status | string | No | "breached", "at_risk", or "all" (default) |
provider | string | No | Filter to a specific provider |
warehouse | string | No | Filter to a specific warehouse location |
limit | integer | No | Results per page. Default: 25, max: 100 |
offset | integer | No | Number of results to skip. Default: 0 |
Example Request
curl -H "Authorization: Bearer pulse_live_abc123..." \
"https://api.3plpulse.com/v1/breaches?status=breached&provider=shipbob" Example Response
{
"threshold": "2_business_days",
"total": 8,
"limit": 25,
"offset": 0,
"by_provider": {
"shipbob": {
"breached": 7,
"at_risk": 2
},
"amazon_mcf": {
"breached": 1,
"at_risk": 1
}
},
"orders": [
{
"order_id": "5765432",
"shopify_order_number": "#1847",
"provider": "shipbob",
"warehouse": "Cicero, IL",
"status": "breached",
"ordered_at": "2026-02-14T08:00:00Z",
"handoff_time_hours": 52.3,
"current_stage": "packed",
"sla_threshold_hours": 48
}
]
} GET /v1/orders/:order_id/timeline
Full fulfillment timeline for a specific order, from Shopify checkout through carrier delivery.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
order_id | string | Yes | Path parameter. Shopify order ID or order number (e.g., "1847" or "5765432") |
Example Request
curl -H "Authorization: Bearer pulse_live_abc123..." \
https://api.3plpulse.com/v1/orders/5765432/timeline Example Response
{
"order_id": "5765432",
"shopify_order_number": "#1847",
"provider": "shipbob",
"warehouse": "Cicero, IL",
"handoff_time_hours": 18.3,
"sla_status": "on_track",
"timeline": [
{
"stage": "order_placed",
"occurred_at": "2026-02-14T08:00:00Z",
"source": "shopify"
},
{
"stage": "received_by_3pl",
"occurred_at": "2026-02-14T08:15:00Z",
"source": "shipbob"
},
{
"stage": "picking_started",
"occurred_at": "2026-02-14T13:45:00Z",
"source": "shipbob"
},
{
"stage": "packed",
"occurred_at": "2026-02-14T14:23:00Z",
"source": "shipbob"
},
{
"stage": "carrier_pickup",
"occurred_at": "2026-02-14T17:00:00Z",
"source": "shipbob"
},
{
"stage": "in_transit",
"occurred_at": "2026-02-14T19:30:00Z",
"source": "carrier"
},
{
"stage": "delivered",
"occurred_at": "2026-02-16T14:12:00Z",
"source": "carrier"
}
],
"carrier": {
"name": "FedEx Ground",
"tracking_number": "794644790138"
}
} GET /v1/orders
List and filter orders across all providers with fulfillment status.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
provider | string | No | Filter to a specific provider |
status | string | No | "in_progress", "delivered", "breached", or "all" (default) |
start_date | string | No | Filter orders placed after this ISO 8601 date |
end_date | string | No | Filter orders placed before this ISO 8601 date |
limit | integer | No | Results per page. Default: 25, max: 100 |
offset | integer | No | Number of results to skip. Default: 0 |
Example Request
curl -H "Authorization: Bearer pulse_live_abc123..." \
"https://api.3plpulse.com/v1/orders?status=in_progress&limit=10" Example Response
{
"total": 127,
"limit": 10,
"offset": 0,
"orders": [
{
"order_id": "5765489",
"shopify_order_number": "#1902",
"provider": "shipbob",
"warehouse": "Cicero, IL",
"current_stage": "picking_started",
"ordered_at": "2026-02-18T14:30:00Z",
"handoff_time_hours": null,
"sla_status": "on_track"
},
{
"order_id": "5765490",
"shopify_order_number": "#1903",
"provider": "amazon_mcf",
"warehouse": "BFI4",
"current_stage": "in_transit",
"ordered_at": "2026-02-18T14:45:00Z",
"handoff_time_hours": 9.2,
"sla_status": "on_track"
}
]
} Webhooks
Get notified in real time when fulfillment events happen. Register a URL and we'll POST event payloads to it.
Available Events
| Event | Fires when |
|---|---|
sla.breach | An order passes its SLA threshold |
sla.at_risk | An order is approaching its SLA threshold (configurable buffer) |
metrics.drift | A provider's key metric shifts beyond a configurable threshold (e.g., handoff time increases 20%+) |
Registering a Webhook
curl -X POST \
-H "Authorization: Bearer pulse_live_abc123..." \
-H "Content-Type: application/json" \
-d '{"url":"https://your-app.com/webhooks/pulse","events":["sla.breach","sla.at_risk"],"secret":"whsec_your_signing_secret"}' \
https://api.3plpulse.com/v1/webhooks Response
{
"webhook_id": "wh_8a3f2b1c",
"url": "https://your-app.com/webhooks/pulse",
"events": [
"sla.breach",
"sla.at_risk"
],
"status": "active",
"created_at": "2026-02-18T10:00:00Z"
} Example Webhook Payload
When an order breaches its SLA, we POST:
{
"event": "sla.breach",
"occurred_at": "2026-02-18T14:00:00Z",
"order": {
"order_id": "5765432",
"shopify_order_number": "#1847",
"provider": "shipbob",
"warehouse": "Cicero, IL",
"handoff_time_hours": 52.3,
"sla_threshold_hours": 48,
"current_stage": "packed"
}
}
All webhook payloads include an X-Pulse-Signature header for HMAC-SHA256 verification using your signing secret.
Use Cases
Weekly Ops Report
Hit GET /v1/metrics?period=last_7_days and GET /v1/metrics/providers on Monday morning. Pipe the JSON into your reporting template. No more manually stitching data from three 3PL dashboards.
Slack Alerts on SLA Breach
Register a webhook for sla.breach events. When an order crosses the threshold, your Slack bot posts the order number, provider, warehouse, and how far past the SLA it is. Your ops team acts on it in minutes, not days.
BI Dashboard Integration
Use GET /v1/metrics?granularity=daily to pull daily data points into Looker, Metabase, or any BI tool. Track fulfillment trends over time with normalized data across all your providers.
Provider Performance Review
Before your quarterly 3PL review, pull GET /v1/metrics/providers?period=last_30_days for an apples-to-apples comparison. Same definitions, same measurement points, same clock. No more arguing about whose "on-time" number is right.
Rate Limits
| Request type | Limit |
|---|---|
Read endpoints (GET) | 1,000 requests/minute |
Write endpoints (POST, DELETE) | 100 requests/minute |
Exceeding the limit returns 429 Too Many Requests with a Retry-After header in seconds.
Status Codes & Errors
| Code | Meaning |
|---|---|
200 | Success |
400 | Bad request. Check parameters |
401 | Missing or invalid API key |
404 | Resource not found (e.g., invalid order ID) |
429 | Rate limit exceeded |
500 | Server error. Retry or contact support |
Error Response Format
{
"error": {
"code": "INVALID_PERIOD",
"message": "The period parameter must be one of: today, last_7_days, last_30_days, custom",
"param": "period"
}
} Supported Providers
Connects to the same providers as 3PL Pulse. Raw data from each provider is normalized into a consistent format, so you get uniform metrics regardless of which 3PL you use.
| Provider | Integration | Data Available |
|---|---|---|
| ShipBob | Direct API | Full timeline: received, picked, packed, shipped, delivered |
| Amazon MCF | Direct API | Order status, shipping events, delivery confirmation |
| SFTP Providers | SFTP file sync | Varies by provider export format |
We add providers regularly. If yours isn't listed, get in touch. We may already support it or can add it.
Request Early Access
We're piloting this with a small group of Shopify merchants. Join the developer preview to get programmatic access to your fulfillment metrics.
Get in TouchOr see the Fulfillment MCP Server for AI agent access to the same data.