# Dragonfly Partner API — Agent & Merchant Guide
_Version 2026-07-02.2 · Base URL: `https://dragonfly-dsp-os-source-staging.up.railway.app` · Interactive OpenAPI explorer: [`/docs`](https://dragonfly-dsp-os-source-staging.up.railway.app/docs)_
Dragonfly OS lets merchants — and their AI agents (MCP, CLI, or plain REST) — sign up,
get approved, and dispatch real last-mile deliveries.
## Try it NOW — sandbox (no approval needed)
Pass `"sandbox": true` to signup and you get a fully working playground account
**in one request** — API key included in the response. Sandbox orders simulate the
full lifecycle (PENDING → ASSIGNED → PICKED_UP → DELIVERED over ~3 minutes), no real
drivers move, nothing is ever billed.
```bash
curl -s https://dragonfly-dsp-os-source-staging.up.railway.app/v1/signup -H 'content-type: application/json' -d '{
"sandbox": true,
"businessName": "My Test Kitchen",
"contactName": "Dev Agent",
"email": "dev@example.com",
"vertical": "catering"
}'
# → { data: { sandbox: true, status: "APPROVED", apiKey: "dfk_...", ... } }
```
Then create orders immediately (same API as production — see §3). When you're ready
for real deliveries, sign up again without `sandbox` for a reviewed production account.
**Human-friendly demo:** a live read-through of the merchant portal (sample data +
walkthrough video) is at [merchants.trydragonfly.com/demo](https://merchants.trydragonfly.com/demo).
## Quick start (production happy path)
1. **Apply**: `POST /v1/signup` (no auth). Save `applicationId` + `pollToken`.
2. **Poll**: `GET /v1/signup/{applicationId}` with header `X-Signup-Token: <pollToken>`
until `status=APPROVED`. The **first** poll after approval returns your
`apiKey` + `signingSecret` **exactly once** — store them.
3. **Create orders**: `POST /v1/orders` with `Authorization: Bearer <apiKey>`.
4. **Track**: `GET /v1/orders/{externalId}`, or register a callback URL for signed push updates.
## 1. Sign up — `POST /v1/signup`
```bash
curl -s https://dragonfly-dsp-os-source-staging.up.railway.app/v1/signup -H 'content-type: application/json' -d '{
"businessName": "Oak Street Kitchen",
"contactName": "Dana Smith",
"email": "dana@oakstreetkitchen.com",
"phone": "+13125550100",
"vertical": "catering",
"pickupAddress": "14 Oak St, Chicago, IL 60601",
"expectedWeeklyOrders": 40
}'
```
`vertical` ∈ `catering | restaurant | grocery | parcels | industrial_3pl | pharmacy | medical | meal_kits | other`.
Your vertical sets your default pricing (rate card); an account manager can adjust it after onboarding.
Response (201): `{ data: { applicationId, pollToken, status: "PENDING", ... } }`
⚠️ `pollToken` is shown **once**. One live application per email. Rate limit: 10/hour.
## 2. Poll for approval — `GET /v1/signup/{id}`
```bash
curl -s https://dragonfly-dsp-os-source-staging.up.railway.app/v1/signup/APPLICATION_ID -H 'X-Signup-Token: POLL_TOKEN'
```
- `PENDING` → keep polling (a human approves; typically within 1 business day — poll every few minutes, not seconds).
- `REJECTED` → `reviewNotes` says why.
- `APPROVED` → the **first** poll returns `{ apiKey, signingSecret, merchantId, subMerchantId }` once.
Later polls return `apiKeyClaimed: true` (ask an admin to rotate if lost).
## 3. Create an order — `POST /v1/orders`
Auth: `Authorization: Bearer <apiKey>` (or HMAC mode, below). Idempotent on `externalId` —
retry safely; a replay returns the existing order, never a duplicate.
```bash
curl -s https://dragonfly-dsp-os-source-staging.up.railway.app/v1/orders \
-H "Authorization: Bearer $DRAGONFLY_API_KEY" -H 'content-type: application/json' -d '{
"externalId": "order-1001",
"pickup": { "address": "14 Oak St, Chicago, IL 60601", "contactName": "Kitchen", "contactPhone": "+13125550100" },
"dropoff": { "address": "445 Michigan Ave, Chicago, IL 60611", "contactName": "Reception", "contactPhone": "+13125550111", "windowStart": "2026-07-03T17:00:00Z", "windowEnd": "2026-07-03T17:30:00Z" },
"subtotalCents": 42500,
"tipCents": 5000
}'
```
- Single dropoff → `dropoff`. Multi-stop route (2–25 stops) → `dropoffs: [...]`. Routing is automatic.
- Every stop **requires** a reachable `contactPhone`.
- Money is integer **cents**. `subtotalCents` drives tiered pricing — send it.
- Response: `{ data: { orderId, status, trackingUrl, dispatchedTo, idempotentReplay } }`
## 4. Track — `GET /v1/orders/{externalId}`
Status lifecycle: `PENDING → ASSIGNED → PICKED_UP → DELIVERED` (`FAILED`/`CANCELLED` terminal).
Response includes `trackingUrl`, `promisedDeliveryAt`, `deliveredAt`, `onTime`.
### Push callbacks
Ask for a `callbackUrl` on your key (or at signup review) and Dragonfly POSTs signed
events (`order.created`, status transitions) to it. Verify `X-Dragonfly-Signature`:
HMAC-SHA256 of the raw body with your `signingSecret`.
## Auth modes
| Mode | How |
|------|-----|
| Bearer (default) | `Authorization: Bearer <apiKey>` |
| HMAC | `X-Dragonfly-Key: <keyPrefix>` + `X-Dragonfly-Signature: hex(hmacSHA256(rawBody, signingSecret))` |
## CLI
```bash
curl -s https://dragonfly-dsp-os-source-staging.up.railway.app/v1/cli -o dragonfly.mjs
export DRAGONFLY_API_KEY=df_... # after approval
node dragonfly.mjs signup signup.json # apply (writes .dragonfly-signup.json)
node dragonfly.mjs poll # poll + auto-claim the API key
node dragonfly.mjs create-order order.json # create an order
node dragonfly.mjs get-order order-1001 # status
```
## MCP server (Claude Desktop / Claude Code / any MCP client)
```bash
curl -s https://dragonfly-dsp-os-source-staging.up.railway.app/v1/mcp -o dragonfly-mcp.mjs
```
```json
{ "mcpServers": { "dragonfly": {
"command": "node", "args": ["/path/to/dragonfly-mcp.mjs"],
"env": { "DRAGONFLY_API_KEY": "df_...", "DRAGONFLY_API_URL": "https://dragonfly-dsp-os-source-staging.up.railway.app" }
} } }
```
Tools exposed: `dragonfly_signup`, `dragonfly_signup_status`, `dragonfly_create_order`, `dragonfly_get_order`.
## Limits & rules
- 100 requests/min per API key (429 with `RATE_LIMITED` beyond).
- Signup: 10/hour per IP. Poll: 60/hour.
- 1–25 dropoffs per order. Idempotency window: forever (externalId is permanent).
- Billing: weekly invoice per your vertical's rate card; details in your merchant portal
(you also receive a portal invite email on approval).
_Questions: support@trydragonfly.com · This page: `GET /v1/docs` (markdown; `?format=html` for a styled page)._