Quickstart β three calls, five minutes
- Mint a key β fleet owners go to Fleet β Developer console, name the key, pick scopes, copy the
pk_live_β¦secret (shown once β only its SHA-256 digest is stored). - Verify it β
GET /api/v1/mereturns your scopes, plan, and rate limits. - Ship a delivery β
POST /api/v1/delivery-requestslands a pending request in the fleet's Dispatch queue.
curl https://api.primetransit.com/api/v1/me \
-H "X-Api-Key: pk_live_β¦"
curl -X POST https://api.primetransit.com/api/v1/delivery-requests \
-H "X-Api-Key: pk_live_β¦" \
-H "Content-Type: application/json" \
-d '{
"customer": { "name": "Ava Chen", "email": "ava@example.com", "phone": "+15551234567" },
"pickup": { "address": "1200 S Main St, Burbank, CA 91506" },
"dropoff": { "address": "88 Oak Ave, Glendale, CA 91205" },
"vehicleClass": "van",
"scheduledAt": "2026-10-16T15:00:00-07:00",
"notes": "Order #1042 β leave at door"
}'{
"success": true,
"requestId": "7f3cβ¦",
"trackingCode": "PT-8KQ2-MP4R",
"jobNumber": "PRIME-000482",
"trackUrl": "https://primetransit.com/track?id=β¦"
}Send trackUrl to your customer β it's a live tracking page that updates as the fleet accepts, assigns, and completes the delivery.
Authentication & scopes
Every v1 request carries an API key in the X-Api-Key header. Keys are fleet-scoped β a key can only read and write its own fleet's data.
| Key prefix | Environment | Use for |
|---|---|---|
| pk_live_β¦ | Live | Production traffic β real requests hit Dispatch |
| pk_test_β¦ | Test | Development and CI β same API, flagged for safe testing |
Scopes gate every endpoint. A call without the required scope returns 403 listing the missing scopes.
| Scope | Grants |
|---|---|
| jobs:read | List and fetch jobs |
| requests:read | List and fetch delivery requests |
| requests:write | Create delivery requests (order handoff) |
| drivers:read | List drivers |
| vehicles:read | List vehicles |
| tracking:read | Track by code or job number |
| invoices:read | List invoices |
| webhooks:manage | Register/update/delete webhook endpoints |
Keys are managed at /fleet/developers or via /api/api-keys (JWT-authenticated). Disable a key instantly with PATCH { "active": false }, or revoke permanently.
Rate limits by plan
Limits are per API key and follow your fleet's subscription. Every response carries headers so you can back off before hitting the wall.
| Plan | Requests / minute | Requests / day |
|---|---|---|
| Free | 30 | 1,000 |
| Starter | 60 | 5,000 |
| Growth | 120 | 20,000 |
| Enterprise | 300 | 100,000 |
| Header | Meaning |
|---|---|
| X-RateLimit-Limit | Allowed requests per minute |
| X-RateLimit-Remaining | Requests left in the current window |
| X-RateLimit-Reset | Unix seconds when the window resets |
| Retry-After | Seconds to wait (429 responses only) |
{
"success": false,
"error": "Rate limit exceeded",
"limit": 30,
"window": "1 minute",
"retryAfter": 42
}Endpoint reference
Base URL: https://api.primetransit.com Β· Lists accept ?limit=1..200&offset=0 and return { data: [...], count: N }.
/api/v1/meany key/api/v1/usageany key/api/v1/delivery-requestsrequests:writeCreate a delivery request in the fleet's queue. Same engine as the public booking form β the fleet is notified and can accept β assign β dispatch.
{
"customer": { "name": "Ava Chen", "email": "ava@example.com", "phone": "+15551234567" },
"pickup": { "address": "1200 S Main St, Burbank, CA", "lat": 34.18, "lng": -118.33 },
"dropoff": { "address": "88 Oak Ave, Glendale, CA" },
"serviceType": "delivery",
"vehicleClass": "van",
"scheduledAt": "2026-10-16T15:00:00-07:00",
"packageDetails": { "size": "boxes", "pieces": 3, "weightLbs": 42 },
"notes": "Order #1042"
}/api/v1/delivery-requestsrequests:read?status=pending|accepted|declined|cancelled|expired./api/v1/delivery-requests/:idrequests:read/api/v1/jobsjobs:read?status=./api/v1/jobs/:idjobs:read/api/v1/tracking/:codetracking:readPT-XXXX-XXXX tracking code or job number./api/v1/driversdrivers:read/api/v1/vehiclesvehicles:read/api/v1/invoicesinvoices:read/api/v1/webhookswebhooks:manage/api/v1/webhookswebhooks:manage/api/v1/webhooks/:idwebhooks:manage/api/v1/webhooks/:idwebhooks:manage/api/v1/webhooks/:id/deliverieswebhooks:manage/api/v1/webhooks/:id/testwebhooks:managewebhook.test ping β verify your receiver end-to-end./api/v1/webhooks/:id/rotate-secretwebhooks:manageRequest lifecycle
What happens after your POST β and which webhook fires at each step.
| Stage | Request status | Job status | Webhook |
|---|---|---|---|
| Created via API/SMS/web | pending | β | delivery_request.created |
| Fleet accepts in Dispatch | accepted | dispatched | job.created + delivery_request β job link |
| Assigned to a driver | accepted | assigned | job.assigned |
| Driver en route / picked up | accepted | in_progress | job.status_changed |
| Delivered | accepted | completed | job.completed |
| Fleet declines | declined | β | β |
| TTL expires (48h or pickup+4h) | expired | β | delivery_request.expired |
| Cancelled | cancelled | cancelled | job.cancelled |
Poll GET /api/v1/tracking/:code or subscribe to job.status_changed β webhooks are the right tool for real-time sync.
Webhooks β signed, retried, observable
Register an HTTPS URL and PRIME POSTs signed events. Deliveries retry up to 3 times with exponential backoff (~1s, ~5s + jitter). Every attempt is logged β inspect via GET /api/v1/webhooks/:id/deliveries.
| Header | Value |
|---|---|
| x-prime-event | Event name, e.g. job.status_changed |
| x-prime-delivery-id | Unique delivery id (use for idempotency) |
| x-prime-signature | t=<unix-seconds>,v1=<HMAC-SHA256 hex of "t.<raw-body>"> |
const crypto = require('crypto');
function verifyPrimeSignature(rawBody, header, secret) {
const parts = Object.fromEntries(
header.split(',').map(kv => kv.split('='))
);
const expected = crypto
.createHmac('sha256', secret)
.update(`${parts.t}.${rawBody}`)
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(expected), Buffer.from(parts.v1 || '')
);
}curl -X POST https://api.primetransit.com/api/v1/webhooks \
-H "X-Api-Key: pk_live_β¦" \
-H "Content-Type: application/json" \
-d '{ "url": "https://your-app.com/hooks/prime", "events": ["delivery_request.created", "job.completed"] }'Full event catalog: job.*, driver.*, vehicle.*, lead.*, ticket.*, delivery_request.*, payment.*, invoice.*, subscription.*, shift.* β or subscribe to * for everything.
Shopify β orders become deliveries
No native app install needed: two webhook hops and every paid order lands in Dispatch.
- Shopify β your middleware β in Shopify Admin β Settings β Notifications β Webhooks, subscribe
orders/paidto your endpoint (or use Shopify Flow β "Send HTTP request" on the Advanced plan). - Middleware β Prime Fabric β map the order to a delivery request and POST it with your key.
- Status back to Shopify β subscribe your middleware to
job.status_changedand update the order's fulfillment status.
app.post('/shopify/order-paid', express.raw({ type: 'application/json' }), async (req, res) => {
const order = JSON.parse(req.body);
const a = order.shipping_address;
const resp = await fetch('https://api.primetransit.com/api/v1/delivery-requests', {
method: 'POST',
headers: {
'X-Api-Key': process.env.PRIME_API_KEY,
'Content-Type': 'application/json',
},
body: JSON.stringify({
customer: {
name: `${a.first_name} ${a.last_name}`,
email: order.email,
phone: a.phone || order.phone,
},
pickup: { address: process.env.WAREHOUSE_ADDRESS },
dropoff: { address: `${a.address1}, ${a.city}, ${a.province_code} ${a.zip}` },
notes: `Shopify order ${order.name}`,
packageDetails: {
weightLbs: order.total_weight ? order.total_weight / 453.6 : undefined,
pieces: order.line_items.reduce((n, li) => n + li.quantity, 0),
},
}),
});
const created = await resp.json();
// created.trackUrl β send to the customer or attach to the order
res.json({ ok: true, requestId: created.requestId });
});Zero-code alternative: Zapier/Make β trigger on "New Paid Order (Shopify)", action "Webhooks β POST" to /api/v1/delivery-requests with the X-Api-Key header. For simple "book a delivery" buttons on product pages, embed the hosted form (see WordPress section β the iframe works anywhere).
WordPress β PRIME Booking plugin
The prime-booking plugin embeds your fleet's hosted booking form. Requests land in Dispatch exactly like API-created ones.
- Get your fleet's booking slug from Fleet β Integrations (the "Website booking widget" panel also generates the embed snippet).
- Upload
prime-booking.zipvia Plugins β Add New β Upload, activate. - Set the slug under Settings β PRIME Booking.
[prime_book] <!-- inline booking form --> [prime_book_button] <!-- button that opens the form in a modal --> [prime_book_button label="Get a delivery quote"]
Deeper integration (order handoff from WooCommerce, custom forms) β use the REST API directly: POST /api/v1/delivery-requests from your theme/plugin PHP with wp_remote_post, same body as the Shopify example.
Booking by SMS β zero code
Customers text your fleet's phone number; the platform parses pickup/dropoff with AI, creates a pending delivery request, and replies with a tracking link. No app, no form.
Customer: "Need a pickup at 1200 S Main St Burbank to 88 Oak Ave Glendale by 3pm"
Fleet #: "PRIME FLEET received your request!
Pickup: 1200 S Main St Burbank to 88 Oak Ave Glendale
Ref: PRIME-000483
Track: https://primetransit.com/track?id=β¦
Reply STOP to unsubscribe."Telnyx inbound webhook β POST /api/webhooks/telnyx/inbound β AI parse β delivery_request (source=sms) β signed reply. STOP/START/HELP keywords are handled for 10DLC compliance automatically.
Errors & versioning
| Status | Meaning | Fix |
|---|---|---|
| 400 | Validation failed β message lists the bad fields | Check DTO shape |
| 401 | Missing / invalid / expired / revoked key | Verify X-Api-Key, mint a new one |
| 403 | Key valid but missing scope | Add the scope (message names it) |
| 404 | Resource not found β or belongs to another fleet | Check the id |
| 429 | Rate limited | Wait Retry-After seconds |
| 503 | Upstream dependency unavailable | Retry with backoff |
Error body: { "statusCode", "message", "error" }. The API is versioned by URL (/api/v1) β additive changes (new fields, endpoints, events) ship without a version bump; breaking changes get a new version path.
Feedback & support
The API grows from real integrations β tell us what you're building and what's missing.