{"openapi":"3.1.0","info":{"title":"Dawurobo Partner Platform API","version":"1.0.0","description":"One integration, many Dawurobo services (delivery and Safe catalog today). IMPORTANT: every endpoint requires a Dawurobo partner account and API keys — sign up (free, self-serve) and generate sandbox keys before making any call, and sign every request (X-API-Key + X-Signature + X-Timestamp + X-Nonce). Unauthenticated or unsigned requests return 401. The interactive 'Try it' here will fail without your own keys. Get started: https://docs.dawurobo.com/docs/getting-started"},"paths":{"/api/v1/delivery/health":{"get":{"operationId":"delivery.health","tags":["delivery"],"summary":"Health check","description":"Returns 200 with a static ok status. Used to verify API key + connectivity.","servers":[{"url":"https://delivery.dawurobo.com"}],"security":[{"ApiKeyAuth":[]}],"x-required-scope":"delivery:read","parameters":[{"name":"X-Signature","in":"header","required":true,"schema":{"type":"string"},"description":"HMAC-SHA256 signature of the canonical request, computed with your signing secret."},{"name":"X-Timestamp","in":"header","required":true,"schema":{"type":"string"},"description":"Request timestamp as a Unix timestamp in SECONDS (not milliseconds), e.g. Math.floor(Date.now()/1000). Included in the signed canonical request; requests more than 5 minutes off the server clock are rejected with 401 STALE_REQUEST."},{"name":"X-Nonce","in":"header","required":true,"schema":{"type":"string"},"description":"Unique per-request nonce included in the signed canonical request (replay protection)."}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","enum":["ok"],"description":"Always \"ok\" when the API key + connectivity check succeeds."}},"required":["status"],"additionalProperties":false}}}},"400":{"description":"Bad request — malformed JSON, missing/invalid fields, or a failed validation rule.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Unauthorized — missing/invalid API key, signature, timestamp, or signing setup.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Forbidden — insufficient scope, inactive partner, or environment not active.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found — unknown operation, or a resource that doesn't exist or isn't yours.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict — replayed nonce, or a duplicate reference on create operations.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/delivery/wallet.balance":{"get":{"operationId":"delivery.wallet.balance","tags":["delivery"],"summary":"Get wallet balance","description":"Returns the partner's delivery wallet balance in GHS. Production API keys only.","servers":[{"url":"https://delivery.dawurobo.com"}],"security":[{"ApiKeyAuth":[]}],"x-required-scope":"delivery:wallet:topup","parameters":[{"name":"X-Signature","in":"header","required":true,"schema":{"type":"string"},"description":"HMAC-SHA256 signature of the canonical request, computed with your signing secret."},{"name":"X-Timestamp","in":"header","required":true,"schema":{"type":"string"},"description":"Request timestamp as a Unix timestamp in SECONDS (not milliseconds), e.g. Math.floor(Date.now()/1000). Included in the signed canonical request; requests more than 5 minutes off the server clock are rejected with 401 STALE_REQUEST."},{"name":"X-Nonce","in":"header","required":true,"schema":{"type":"string"},"description":"Unique per-request nonce included in the signed canonical request (replay protection)."}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","enum":["success"]},"data":{"type":"object","properties":{"balance_ghs":{"type":"number","description":"Current wallet balance, in Ghana cedis."},"currency":{"type":"string","enum":["GHS"]}},"required":["balance_ghs","currency"],"additionalProperties":false}},"required":["status","data"],"additionalProperties":false}}}},"400":{"description":"Bad request — malformed JSON, missing/invalid fields, or a failed validation rule.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Unauthorized — missing/invalid API key, signature, timestamp, or signing setup.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Forbidden — insufficient scope, inactive partner, or environment not active.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found — unknown operation, or a resource that doesn't exist or isn't yours.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict — replayed nonce, or a duplicate reference on create operations.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/delivery/wallet.topup.initiate":{"post":{"operationId":"delivery.wallet.topup.initiate","tags":["delivery"],"summary":"Initiate a wallet top-up","description":"Starts a wallet top-up: persists a token → partner mapping and returns a payment gateway checkout URL. Production API keys only.","servers":[{"url":"https://delivery.dawurobo.com"}],"security":[{"ApiKeyAuth":[]}],"x-required-scope":"delivery:wallet:topup","parameters":[{"name":"X-Signature","in":"header","required":true,"schema":{"type":"string"},"description":"HMAC-SHA256 signature of the canonical request, computed with your signing secret."},{"name":"X-Timestamp","in":"header","required":true,"schema":{"type":"string"},"description":"Request timestamp as a Unix timestamp in SECONDS (not milliseconds), e.g. Math.floor(Date.now()/1000). Included in the signed canonical request; requests more than 5 minutes off the server clock are rejected with 401 STALE_REQUEST."},{"name":"X-Nonce","in":"header","required":true,"schema":{"type":"string"},"description":"Unique per-request nonce included in the signed canonical request (replay protection)."}],"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","enum":["success"]},"data":{"type":"object","properties":{"checkout_url":{"type":"string","description":"Payment gateway checkout URL — redirect the payer here to complete the top-up."},"client_reference":{"type":"string","description":"Token-based reference (dawuroboD_WA + 16 hex chars) — pass this to wallet.topup.verify."},"amount_ghs":{"type":"number","description":"Amount requested, in Ghana cedis."}},"required":["checkout_url","client_reference","amount_ghs"],"additionalProperties":false}},"required":["status","data"],"additionalProperties":false}}}},"400":{"description":"Bad request — malformed JSON, missing/invalid fields, or a failed validation rule.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Unauthorized — missing/invalid API key, signature, timestamp, or signing setup.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Forbidden — insufficient scope, inactive partner, or environment not active.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found — unknown operation, or a resource that doesn't exist or isn't yours.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict — replayed nonce, or a duplicate reference on create operations.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"amount_ghs":{"type":"number","exclusiveMinimum":true,"minimum":0,"description":"Amount to top up, in Ghana cedis. Minimum GHS 30."}},"required":["amount_ghs"],"additionalProperties":false}}}}}},"/api/v1/delivery/wallet.topup.verify":{"post":{"operationId":"delivery.wallet.topup.verify","tags":["delivery"],"summary":"Verify a wallet top-up","description":"Verifies a top-up's payment status with the gateway and, on success, credits the wallet exactly once (idempotent). Production API keys only.","servers":[{"url":"https://delivery.dawurobo.com"}],"security":[{"ApiKeyAuth":[]}],"x-required-scope":"delivery:wallet:topup","parameters":[{"name":"X-Signature","in":"header","required":true,"schema":{"type":"string"},"description":"HMAC-SHA256 signature of the canonical request, computed with your signing secret."},{"name":"X-Timestamp","in":"header","required":true,"schema":{"type":"string"},"description":"Request timestamp as a Unix timestamp in SECONDS (not milliseconds), e.g. Math.floor(Date.now()/1000). Included in the signed canonical request; requests more than 5 minutes off the server clock are rejected with 401 STALE_REQUEST."},{"name":"X-Nonce","in":"header","required":true,"schema":{"type":"string"},"description":"Unique per-request nonce included in the signed canonical request (replay protection)."}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","enum":["success"]},"data":{"type":"object","properties":{"credited":{"type":"boolean","description":"Whether this call credited the wallet. False when the payment isn't verified successful yet."},"state":{"type":"string","enum":["credited","already_credited","pending"],"description":"credited: wallet was just credited by this call. already_credited: idempotent replay — a prior call already credited it. pending: the gateway hasn't reported a successful payment yet; keep polling."},"amount_ghs":{"type":"number","description":"Amount credited, in Ghana cedis. Present when state is credited or already_credited."},"balance_ghs":{"type":"number","description":"Wallet balance after crediting, in Ghana cedis (best-effort; may be omitted on a read failure)."},"verification_status":{"type":"string","description":"Raw payment gateway status string. Present when state is pending."}},"required":["credited","state"],"additionalProperties":false}},"required":["status","data"],"additionalProperties":false}}}},"400":{"description":"Bad request — malformed JSON, missing/invalid fields, or a failed validation rule.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Unauthorized — missing/invalid API key, signature, timestamp, or signing setup.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Forbidden — insufficient scope, inactive partner, or environment not active.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found — unknown operation, or a resource that doesn't exist or isn't yours.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict — replayed nonce, or a duplicate reference on create operations.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"client_reference":{"type":"string","minLength":13,"description":"The client_reference returned by wallet.topup.initiate (starts with the dawuroboD_WA token prefix)."}},"required":["client_reference"],"additionalProperties":false}}}}}},"/api/v1/delivery/orders.create":{"post":{"operationId":"delivery.orders.create","tags":["delivery"],"summary":"Create a delivery order","description":"Creates a delivery order scoped to your app. Default billing is recipient-pays cash-on-delivery (no wallet touch). Set payment.payer to \"partner\" to fund the delivery fee from your Dawurobo wallet at creation — that path additionally requires the delivery:wallet:spend scope, valid pickup + delivery coordinates (the fee is always server-priced), and returns 402 if the wallet (and any credit headroom) is insufficient. order_reference is your idempotency key: a repeated reference returns 409 DUPLICATE_ORDER_REFERENCE instead of double-creating or double-charging.","servers":[{"url":"https://delivery.dawurobo.com"}],"security":[{"ApiKeyAuth":[]}],"x-required-scope":"delivery:write","parameters":[{"name":"X-Signature","in":"header","required":true,"schema":{"type":"string"},"description":"HMAC-SHA256 signature of the canonical request, computed with your signing secret."},{"name":"X-Timestamp","in":"header","required":true,"schema":{"type":"string"},"description":"Request timestamp as a Unix timestamp in SECONDS (not milliseconds), e.g. Math.floor(Date.now()/1000). Included in the signed canonical request; requests more than 5 minutes off the server clock are rejected with 401 STALE_REQUEST."},{"name":"X-Nonce","in":"header","required":true,"schema":{"type":"string"},"description":"Unique per-request nonce included in the signed canonical request (replay protection)."}],"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","enum":["success"]},"message":{"type":"string"},"data":{"type":"object","properties":{"order_details":{"type":"object","properties":{"order_id":{"type":"string","nullable":true,"description":"The Dawurobo order id — use it with orders.get / orders.track / orders.cancel."},"estimated_delivery":{"type":"string","description":"Human-readable estimated delivery window."}},"required":["order_id","estimated_delivery"],"additionalProperties":false},"status":{"type":"string","enum":["order_created"]}},"required":["order_details","status"],"additionalProperties":false}},"required":["status","message","data"],"additionalProperties":false}}}},"400":{"description":"Bad request — malformed JSON, missing/invalid fields, or a failed validation rule.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Unauthorized — missing/invalid API key, signature, timestamp, or signing setup.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Insufficient wallet balance (wallet-funded orders) — top up and retry.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Forbidden — insufficient scope, inactive partner, or environment not active.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found — unknown operation, or a resource that doesn't exist or isn't yours.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict — replayed nonce, or a duplicate reference on create operations.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"order_reference":{"type":"string","description":"Your unique reference for this order — also the idempotency key: creating again with the same reference returns 409 DUPLICATE_ORDER_REFERENCE instead of double-creating or double-charging, so retry a timed-out create with the SAME reference. Stored on the Dawurobo order and echoed back in status/track."},"customer":{"type":"object","properties":{"name":{"type":"string","description":"Recipient full name."},"phone":{"type":"string","description":"Recipient phone number (Ghana format)."},"whatsapp":{"type":"string","description":"Optional alternate/WhatsApp number for the recipient."}},"required":["name","phone"],"additionalProperties":false,"description":"The delivery recipient."},"delivery":{"type":"object","properties":{"address":{"type":"string","description":"Street/landmark address for delivery."},"city":{"type":"string","description":"Delivery city."},"region":{"type":"string","description":"Delivery region."},"coordinates":{"type":"object","properties":{"lat":{"type":"number","description":"Latitude in decimal degrees."},"lng":{"type":"number","description":"Longitude in decimal degrees."}},"required":["lat","lng"],"additionalProperties":false,"description":"WGS84 coordinates. Supplying pickup + delivery coordinates lets Dawurobo compute the delivery fee from distance."},"location_id":{"type":"string","description":"Optional Dawurobo location/zone id from locations.list."},"notes":{"type":"string","description":"Optional delivery notes."}},"required":["address","city","region"],"additionalProperties":false,"description":"Where the order is delivered."},"item":{"type":"string","description":"Human-readable description of the item(s) being delivered."},"pickup":{"type":"object","properties":{"address":{"type":"string","description":"Pickup street/landmark address."},"contact_person":{"type":"string","description":"Name of the pickup contact."},"contact_phone":{"type":"string","description":"Phone number of the pickup contact."},"coordinates":{"$ref":"#/properties/delivery/properties/coordinates","description":"WGS84 coordinates. Supplying pickup + delivery coordinates lets Dawurobo compute the delivery fee from distance."},"location_id":{"type":"string","description":"Optional Dawurobo location/zone id for the pickup point."}},"required":["contact_person","contact_phone"],"additionalProperties":false,"description":"Where the rider collects the order."},"payment":{"type":"object","properties":{"payer":{"type":"string","enum":["partner","recipient"],"description":"Who pays the delivery fee. \"recipient\" (default): cash on delivery — no wallet is touched. \"partner\": the fee is debited from your Dawurobo wallet at creation and REQUIRES the delivery:wallet:spend scope."},"method":{"type":"string","enum":["cash","mobile_money","card","bank_transfer"],"description":"Informational payment method."},"amount":{"type":"number","description":"Optional override/fallback for the delivery fee. Normally the fee is computed from pickup → delivery distance."},"is_paid":{"type":"boolean","description":"Informational: whether the item cost is already paid."}},"additionalProperties":false,"description":"Optional. Omit for recipient-pays cash-on-delivery (the default)."},"delivery_date":{"type":"string","description":"Optional ISO date for the requested delivery/pickup date."},"special_instructions":{"type":"string","description":"Optional free-text instructions attached to the order."},"webhook_url":{"type":"string","description":"Optional per-order webhook override."}},"required":["order_reference","customer","delivery","item","pickup"],"additionalProperties":false}}}}}},"/api/v1/delivery/orders.create_bulk":{"post":{"operationId":"delivery.orders.create_bulk","tags":["delivery"],"summary":"Create multiple delivery orders in one request","description":"Batch-creates up to 100 orders in one call, each in the same shape as orders.create. This is a thin loop over orders.create — each order gets its own atomic wallet pre-debit/reversal and its own order_reference idempotency guard, run with bounded concurrency (5 at a time), so a wallet-funded order still needs the delivery:wallet:spend scope on the individual item that sets payment.payer to \"partner\". One order failing never affects the others: the response is always 200 with a per-item ok/status_code/order_id or code/message, unless the batch itself is invalid (not an array, empty, or over 100 items), which returns 400 BATCH_TOO_LARGE (or BATCH_EMPTY) before any order is touched.","servers":[{"url":"https://delivery.dawurobo.com"}],"security":[{"ApiKeyAuth":[]}],"x-required-scope":"delivery:write","parameters":[{"name":"X-Signature","in":"header","required":true,"schema":{"type":"string"},"description":"HMAC-SHA256 signature of the canonical request, computed with your signing secret."},{"name":"X-Timestamp","in":"header","required":true,"schema":{"type":"string"},"description":"Request timestamp as a Unix timestamp in SECONDS (not milliseconds), e.g. Math.floor(Date.now()/1000). Included in the signed canonical request; requests more than 5 minutes off the server clock are rejected with 401 STALE_REQUEST."},{"name":"X-Nonce","in":"header","required":true,"schema":{"type":"string"},"description":"Unique per-request nonce included in the signed canonical request (replay protection)."}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","enum":["ok"]},"summary":{"type":"object","properties":{"total":{"type":"number"},"created":{"type":"number"},"failed":{"type":"number"}},"required":["total","created","failed"],"additionalProperties":false},"results":{"type":"array","items":{"type":"object","properties":{"order_reference":{"type":"string","description":"Echoes the order_reference from the corresponding request item."},"ok":{"type":"boolean","description":"Whether this individual order was created successfully."},"status_code":{"type":"number","description":"The status code orders.create would have returned for this item."},"order_id":{"type":"string","nullable":true,"description":"Present when ok is true: the created Dawurobo order id."},"code":{"type":"string","description":"Present when ok is false: the orders.create error code."},"message":{"type":"string","description":"Present when ok is false: a human-readable error message."}},"required":["order_reference","ok","status_code"],"additionalProperties":false}}},"required":["status","summary","results"],"additionalProperties":false}}}},"400":{"description":"Bad request — malformed JSON, missing/invalid fields, or a failed validation rule.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Unauthorized — missing/invalid API key, signature, timestamp, or signing setup.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Forbidden — insufficient scope, inactive partner, or environment not active.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found — unknown operation, or a resource that doesn't exist or isn't yours.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict — replayed nonce, or a duplicate reference on create operations.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"orders":{"type":"array","items":{"type":"object","additionalProperties":{}},"minItems":1,"maxItems":100,"description":"The orders to create, each in the same shape as orders.create (order_reference, customer, delivery, item, pickup, payment, delivery_date, special_instructions, webhook_url — see orders.create for field details). Max 100 per batch. Per-item field validation happens per-order, not against this envelope: a malformed item fails only that item in the response (see results[].code MISSING_REQUIRED_FIELD / INVALID_ORDER_PAYLOAD), it never rejects the whole batch."}},"required":["orders"],"additionalProperties":false}}}}}},"/api/v1/delivery/orders.get":{"post":{"operationId":"delivery.orders.get","tags":["delivery"],"summary":"Get order status","description":"Returns the current status and details of one of your orders by order_id. Orders that don't belong to your app return 404.","servers":[{"url":"https://delivery.dawurobo.com"}],"security":[{"ApiKeyAuth":[]}],"x-required-scope":"delivery:read","parameters":[{"name":"X-Signature","in":"header","required":true,"schema":{"type":"string"},"description":"HMAC-SHA256 signature of the canonical request, computed with your signing secret."},{"name":"X-Timestamp","in":"header","required":true,"schema":{"type":"string"},"description":"Request timestamp as a Unix timestamp in SECONDS (not milliseconds), e.g. Math.floor(Date.now()/1000). Included in the signed canonical request; requests more than 5 minutes off the server clock are rejected with 401 STALE_REQUEST."},{"name":"X-Nonce","in":"header","required":true,"schema":{"type":"string"},"description":"Unique per-request nonce included in the signed canonical request (replay protection)."}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","enum":["success"]},"message":{"type":"string"},"data":{"type":"object","properties":{"order_reference":{"type":"string","description":"Your original order_reference."},"internal_order_id":{"type":"string"},"status":{"type":"string","description":"Current order status."},"status_details":{"type":"object","properties":{"description":{"type":"string"},"timestamp":{"type":"string"}},"required":["description"],"additionalProperties":false},"order_info":{"type":"object","properties":{"recipient_name":{"type":"string"},"recipient_phone":{"type":"string"},"recipient_address":{"type":"string"},"delivery_date":{"type":"string"},"pickup_date":{"type":"string"},"amount":{"type":"number"},"payment_status":{"type":"string"}},"additionalProperties":false},"tracking_url":{"type":"string"}},"required":["order_reference","internal_order_id","status","status_details","order_info","tracking_url"],"additionalProperties":false}},"required":["status","message","data"],"additionalProperties":false}}}},"400":{"description":"Bad request — malformed JSON, missing/invalid fields, or a failed validation rule.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Unauthorized — missing/invalid API key, signature, timestamp, or signing setup.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Forbidden — insufficient scope, inactive partner, or environment not active.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found — unknown operation, or a resource that doesn't exist or isn't yours.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict — replayed nonce, or a duplicate reference on create operations.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"order_id":{"type":"string","description":"The Dawurobo order id returned by orders.create."}},"required":["order_id"],"additionalProperties":false}}}}}},"/api/v1/delivery/orders.track":{"post":{"operationId":"delivery.orders.track","tags":["delivery"],"summary":"Track an order","description":"Returns a delivery timeline for one of your orders by order_id. Orders that don't belong to your app return 404.","servers":[{"url":"https://delivery.dawurobo.com"}],"security":[{"ApiKeyAuth":[]}],"x-required-scope":"delivery:read","parameters":[{"name":"X-Signature","in":"header","required":true,"schema":{"type":"string"},"description":"HMAC-SHA256 signature of the canonical request, computed with your signing secret."},{"name":"X-Timestamp","in":"header","required":true,"schema":{"type":"string"},"description":"Request timestamp as a Unix timestamp in SECONDS (not milliseconds), e.g. Math.floor(Date.now()/1000). Included in the signed canonical request; requests more than 5 minutes off the server clock are rejected with 401 STALE_REQUEST."},{"name":"X-Nonce","in":"header","required":true,"schema":{"type":"string"},"description":"Unique per-request nonce included in the signed canonical request (replay protection)."}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","enum":["success"]},"message":{"type":"string"},"data":{"type":"object","properties":{"order_id":{"type":"string"},"order_reference":{"type":"string"},"recipient_name":{"type":"string"},"recipient_phone_last4":{"type":"string"},"current_status":{"type":"string"},"estimated_delivery_time":{"type":"string"},"timeline":{"type":"array","items":{"type":"object","properties":{"status":{"type":"string"},"title":{"type":"string"},"timestamp":{"type":"string"},"completed":{"type":"boolean"}},"required":["status","title","completed"],"additionalProperties":false}}},"required":["order_id","order_reference","recipient_phone_last4","current_status","timeline"],"additionalProperties":false}},"required":["status","message","data"],"additionalProperties":false}}}},"400":{"description":"Bad request — malformed JSON, missing/invalid fields, or a failed validation rule.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Unauthorized — missing/invalid API key, signature, timestamp, or signing setup.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Forbidden — insufficient scope, inactive partner, or environment not active.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found — unknown operation, or a resource that doesn't exist or isn't yours.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict — replayed nonce, or a duplicate reference on create operations.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"order_id":{"type":"string","description":"The Dawurobo order id returned by orders.create."}},"required":["order_id"],"additionalProperties":false}}}}}},"/api/v1/delivery/orders.estimate":{"post":{"operationId":"delivery.orders.estimate","tags":["delivery"],"summary":"Estimate delivery price and time","description":"Computes a delivery fee and pickup/delivery windows from pickup → delivery coordinates. Pure calculation — no order is created and no wallet is touched.","servers":[{"url":"https://delivery.dawurobo.com"}],"security":[{"ApiKeyAuth":[]}],"x-required-scope":"delivery:read","parameters":[{"name":"X-Signature","in":"header","required":true,"schema":{"type":"string"},"description":"HMAC-SHA256 signature of the canonical request, computed with your signing secret."},{"name":"X-Timestamp","in":"header","required":true,"schema":{"type":"string"},"description":"Request timestamp as a Unix timestamp in SECONDS (not milliseconds), e.g. Math.floor(Date.now()/1000). Included in the signed canonical request; requests more than 5 minutes off the server clock are rejected with 401 STALE_REQUEST."},{"name":"X-Nonce","in":"header","required":true,"schema":{"type":"string"},"description":"Unique per-request nonce included in the signed canonical request (replay protection)."}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","enum":["success"]},"message":{"type":"string"},"data":{"type":"object","properties":{"estimated_price":{"type":"number"},"estimated_delivery_time":{"type":"string"},"pickup_time":{"type":"string"},"delivery_time":{"type":"string"},"pickup_region":{"type":"string"},"dropoff_region":{"type":"string"},"pickup_description":{"type":"string"},"dropoff_description":{"type":"string"},"delivery_window":{"type":"object","properties":{"earliest":{"type":"string"},"latest":{"type":"string"}},"required":["earliest","latest"],"additionalProperties":false},"priority_level":{"type":"string"},"service_type":{"type":"string"},"available_options":{"type":"array","items":{"type":"object","properties":{"priority":{"type":"string"},"price":{"type":"number"},"description":{"type":"string"}},"required":["priority","price","description"],"additionalProperties":false}},"location_coverage":{"type":"object","properties":{"delivery_available":{"type":"boolean"},"service_area":{"type":"string"}},"required":["delivery_available","service_area"],"additionalProperties":false},"additional_info":{"type":"object","properties":{"weekend_delivery":{"type":"boolean"},"holiday_delivery":{"type":"boolean"},"tracking_available":{"type":"boolean"},"pickup_description":{"type":"string"},"delivery_description":{"type":"string"}},"required":["weekend_delivery","holiday_delivery","tracking_available","pickup_description","delivery_description"],"additionalProperties":false}},"required":["estimated_price","estimated_delivery_time","pickup_time","delivery_time","pickup_region","dropoff_region","pickup_description","dropoff_description","delivery_window","priority_level","service_type","available_options","location_coverage","additional_info"],"additionalProperties":false}},"required":["status","message","data"],"additionalProperties":false}}}},"400":{"description":"Bad request — malformed JSON, missing/invalid fields, or a failed validation rule.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Unauthorized — missing/invalid API key, signature, timestamp, or signing setup.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Forbidden — insufficient scope, inactive partner, or environment not active.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found — unknown operation, or a resource that doesn't exist or isn't yours.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict — replayed nonce, or a duplicate reference on create operations.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"pickup_location":{"type":"object","properties":{"address":{"type":"string"},"coordinates":{"type":"object","properties":{"lat":{"type":"number","description":"Latitude in decimal degrees."},"lng":{"type":"number","description":"Longitude in decimal degrees."}},"required":["lat","lng"],"additionalProperties":false,"description":"WGS84 coordinates. Supplying pickup + delivery coordinates lets Dawurobo compute the delivery fee from distance."}},"additionalProperties":false,"description":"Pickup point. Defaults to the Accra center when omitted."},"delivery_location":{"type":"object","properties":{"address":{"type":"string"},"coordinates":{"type":"object","properties":{"lat":{"$ref":"#/properties/pickup_location/properties/coordinates/properties/lat"},"lng":{"$ref":"#/properties/pickup_location/properties/coordinates/properties/lng"}},"required":["lat","lng"],"additionalProperties":false,"description":"Delivery coordinates are required for an estimate."}},"required":["coordinates"],"additionalProperties":false,"description":"Delivery point. Coordinates are required."},"priority":{"type":"string","enum":["standard","economy","cargo"],"description":"Delivery priority. Defaults to standard."},"order_date":{"type":"string","description":"Optional ISO order date used to build the pickup/delivery windows."}},"required":["delivery_location"],"additionalProperties":false}}}}}},"/api/v1/delivery/locations.list":{"post":{"operationId":"delivery.locations.list","tags":["delivery"],"summary":"List delivery locations","description":"Returns supported delivery zones/areas (major zones plus live zone/area data), optionally filtered by region or zone.","servers":[{"url":"https://delivery.dawurobo.com"}],"security":[{"ApiKeyAuth":[]}],"x-required-scope":"delivery:read","parameters":[{"name":"X-Signature","in":"header","required":true,"schema":{"type":"string"},"description":"HMAC-SHA256 signature of the canonical request, computed with your signing secret."},{"name":"X-Timestamp","in":"header","required":true,"schema":{"type":"string"},"description":"Request timestamp as a Unix timestamp in SECONDS (not milliseconds), e.g. Math.floor(Date.now()/1000). Included in the signed canonical request; requests more than 5 minutes off the server clock are rejected with 401 STALE_REQUEST."},{"name":"X-Nonce","in":"header","required":true,"schema":{"type":"string"},"description":"Unique per-request nonce included in the signed canonical request (replay protection)."}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","enum":["success"]},"message":{"type":"string"},"data":{"type":"object","properties":{"locations":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"region":{"type":"string"},"zone":{"type":"string"},"coordinates":{"type":"object","properties":{"lat":{"type":"number","description":"Latitude in decimal degrees."},"lng":{"type":"number","description":"Longitude in decimal degrees."}},"required":["lat","lng"],"additionalProperties":false,"description":"WGS84 coordinates. Supplying pickup + delivery coordinates lets Dawurobo compute the delivery fee from distance."}},"required":["id","name"],"additionalProperties":false}},"total":{"type":"number"},"filters":{"type":"object","properties":{"region":{"type":"string","nullable":true},"zone":{"type":"string","nullable":true}},"required":["region","zone"],"additionalProperties":false}},"required":["locations","total","filters"],"additionalProperties":false}},"required":["status","message","data"],"additionalProperties":false}}}},"400":{"description":"Bad request — malformed JSON, missing/invalid fields, or a failed validation rule.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Unauthorized — missing/invalid API key, signature, timestamp, or signing setup.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Forbidden — insufficient scope, inactive partner, or environment not active.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found — unknown operation, or a resource that doesn't exist or isn't yours.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict — replayed nonce, or a duplicate reference on create operations.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"region":{"type":"string","description":"Optional region filter (case-insensitive)."},"zone":{"type":"string","description":"Optional zone filter (case-insensitive)."},"include_coordinates":{"type":"boolean","description":"Include coordinates on locations that have them."}},"additionalProperties":false}}}}}},"/api/v1/delivery/orders.cancel":{"post":{"operationId":"delivery.orders.cancel","tags":["delivery"],"summary":"Cancel an order","description":"Cancels one of your orders by order_id. Orders that don't belong to your app return 404; already delivered/cancelled orders return 400.","servers":[{"url":"https://delivery.dawurobo.com"}],"security":[{"ApiKeyAuth":[]}],"x-required-scope":"delivery:write","parameters":[{"name":"X-Signature","in":"header","required":true,"schema":{"type":"string"},"description":"HMAC-SHA256 signature of the canonical request, computed with your signing secret."},{"name":"X-Timestamp","in":"header","required":true,"schema":{"type":"string"},"description":"Request timestamp as a Unix timestamp in SECONDS (not milliseconds), e.g. Math.floor(Date.now()/1000). Included in the signed canonical request; requests more than 5 minutes off the server clock are rejected with 401 STALE_REQUEST."},{"name":"X-Nonce","in":"header","required":true,"schema":{"type":"string"},"description":"Unique per-request nonce included in the signed canonical request (replay protection)."}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","enum":["success"]},"message":{"type":"string"},"data":{"type":"object","properties":{"order_reference":{"type":"string"},"internal_order_id":{"type":"string"},"status":{"type":"string","enum":["cancelled"]},"cancelled_at":{"type":"string"},"cancellation_reason":{"type":"string"},"refund_status":{"type":"string","enum":["pending","not_applicable"]}},"required":["order_reference","internal_order_id","status","cancelled_at","cancellation_reason","refund_status"],"additionalProperties":false}},"required":["status","message","data"],"additionalProperties":false}}}},"400":{"description":"Bad request — malformed JSON, missing/invalid fields, or a failed validation rule.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Unauthorized — missing/invalid API key, signature, timestamp, or signing setup.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Forbidden — insufficient scope, inactive partner, or environment not active.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found — unknown operation, or a resource that doesn't exist or isn't yours.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict — replayed nonce, or a duplicate reference on create operations.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"order_id":{"type":"string","description":"The Dawurobo order id to cancel."},"reason":{"type":"string","description":"Optional human-readable cancellation reason."}},"required":["order_id"],"additionalProperties":false}}}}}},"/api/v1/safe-catalog/health":{"get":{"operationId":"safe-catalog.health","tags":["safe-catalog"],"summary":"Health check","description":"Returns 200 with a static ok status. Used to verify API key + connectivity.","servers":[{"url":"https://safe.dawurobo.com"}],"security":[{"ApiKeyAuth":[]}],"x-required-scope":"safe:read","parameters":[{"name":"X-Signature","in":"header","required":true,"schema":{"type":"string"},"description":"HMAC-SHA256 signature of the canonical request, computed with your signing secret."},{"name":"X-Timestamp","in":"header","required":true,"schema":{"type":"string"},"description":"Request timestamp as a Unix timestamp in SECONDS (not milliseconds), e.g. Math.floor(Date.now()/1000). Included in the signed canonical request; requests more than 5 minutes off the server clock are rejected with 401 STALE_REQUEST."},{"name":"X-Nonce","in":"header","required":true,"schema":{"type":"string"},"description":"Unique per-request nonce included in the signed canonical request (replay protection)."}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","enum":["ok"],"description":"Always \"ok\" when the API key + connectivity check succeeds."}},"required":["status"],"additionalProperties":false}}}},"400":{"description":"Bad request — malformed JSON, missing/invalid fields, or a failed validation rule.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Unauthorized — missing/invalid API key, signature, timestamp, or signing setup.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Forbidden — insufficient scope, inactive partner, or environment not active.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found — unknown operation, or a resource that doesn't exist or isn't yours.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict — replayed nonce, or a duplicate reference on create operations.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/safe-catalog/catalog.list":{"get":{"operationId":"safe-catalog.catalog.list","tags":["safe-catalog"],"summary":"List syndicated catalog products","description":"Lists products from vendors opted into syndication. Optionally scoped to a single vendor_id, capped at limit (default 50, max 200).","servers":[{"url":"https://safe.dawurobo.com"}],"security":[{"ApiKeyAuth":[]}],"x-required-scope":"safe:read","parameters":[{"name":"X-Signature","in":"header","required":true,"schema":{"type":"string"},"description":"HMAC-SHA256 signature of the canonical request, computed with your signing secret."},{"name":"X-Timestamp","in":"header","required":true,"schema":{"type":"string"},"description":"Request timestamp as a Unix timestamp in SECONDS (not milliseconds), e.g. Math.floor(Date.now()/1000). Included in the signed canonical request; requests more than 5 minutes off the server clock are rejected with 401 STALE_REQUEST."},{"name":"X-Nonce","in":"header","required":true,"schema":{"type":"string"},"description":"Unique per-request nonce included in the signed canonical request (replay protection)."},{"name":"vendor_id","in":"query","required":false,"schema":{"type":"string","description":"Restrict the listing to one syndicated vendor."},"description":"Restrict the listing to one syndicated vendor."},{"name":"limit","in":"query","required":false,"schema":{"type":"number","description":"Max products to return. Default 50, capped at 200."},"description":"Max products to return. Default 50, capped at 200."}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","enum":["success"]},"data":{"type":"object","properties":{"products":{"type":"array","items":{"type":"object","properties":{"product_id":{"type":"string"},"vendor_id":{"type":"string"},"vendor_name":{"type":"string"},"title":{"type":"string"},"description":{"type":"string"},"images":{"type":"array","items":{"type":"string"}},"category":{"type":"string","nullable":true},"currency":{"type":"string"},"variants":{"type":"array","items":{"type":"object","properties":{"variant_id":{"type":"string"},"label":{"type":"string"},"price_ghs":{"type":"number"},"in_stock":{"type":"boolean"}},"required":["variant_id","label","price_ghs","in_stock"],"additionalProperties":false}}},"required":["product_id","vendor_id","vendor_name","title","description","images","category","currency","variants"],"additionalProperties":false}},"count":{"type":"number"}},"required":["products","count"],"additionalProperties":false}},"required":["status","data"],"additionalProperties":false}}}},"400":{"description":"Bad request — malformed JSON, missing/invalid fields, or a failed validation rule.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Unauthorized — missing/invalid API key, signature, timestamp, or signing setup.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Forbidden — insufficient scope, inactive partner, or environment not active.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found — unknown operation, or a resource that doesn't exist or isn't yours.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict — replayed nonce, or a duplicate reference on create operations.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/safe-catalog/catalog.get":{"get":{"operationId":"safe-catalog.catalog.get","tags":["safe-catalog"],"summary":"Get a single syndicated product","description":"Returns one product by product_id if it's active and its vendor is syndicatable; otherwise a uniform PRODUCT_NOT_FOUND.","servers":[{"url":"https://safe.dawurobo.com"}],"security":[{"ApiKeyAuth":[]}],"x-required-scope":"safe:read","parameters":[{"name":"X-Signature","in":"header","required":true,"schema":{"type":"string"},"description":"HMAC-SHA256 signature of the canonical request, computed with your signing secret."},{"name":"X-Timestamp","in":"header","required":true,"schema":{"type":"string"},"description":"Request timestamp as a Unix timestamp in SECONDS (not milliseconds), e.g. Math.floor(Date.now()/1000). Included in the signed canonical request; requests more than 5 minutes off the server clock are rejected with 401 STALE_REQUEST."},{"name":"X-Nonce","in":"header","required":true,"schema":{"type":"string"},"description":"Unique per-request nonce included in the signed canonical request (replay protection)."},{"name":"product_id","in":"query","required":true,"schema":{"type":"string","description":"Data Connect product id."},"description":"Data Connect product id."}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","enum":["success"]},"data":{"type":"object","properties":{"product_id":{"type":"string"},"vendor_id":{"type":"string"},"vendor_name":{"type":"string"},"title":{"type":"string"},"description":{"type":"string"},"images":{"type":"array","items":{"type":"string"}},"category":{"type":"string","nullable":true},"currency":{"type":"string"},"variants":{"type":"array","items":{"type":"object","properties":{"variant_id":{"type":"string"},"label":{"type":"string"},"price_ghs":{"type":"number"},"in_stock":{"type":"boolean"}},"required":["variant_id","label","price_ghs","in_stock"],"additionalProperties":false}}},"required":["product_id","vendor_id","vendor_name","title","description","images","category","currency","variants"],"additionalProperties":false}},"required":["status","data"],"additionalProperties":false}}}},"400":{"description":"Bad request — malformed JSON, missing/invalid fields, or a failed validation rule.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Unauthorized — missing/invalid API key, signature, timestamp, or signing setup.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Forbidden — insufficient scope, inactive partner, or environment not active.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found — unknown operation, or a resource that doesn't exist or isn't yours.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict — replayed nonce, or a duplicate reference on create operations.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/safe-catalog/orders.create":{"post":{"operationId":"safe-catalog.orders.create","tags":["safe-catalog"],"summary":"Create a syndicated order","description":"Single-vendor order creation: validates items, reserves stock, and quotes delivery. payment_method \"online\" starts a gateway charge (redirect the buyer to checkout_url); \"cod\" starts no charge — the rider collects subtotal + delivery fee in cash at the door and the order settles when orders.verify sees it delivered. reseller_markup_ghs is rejected on COD orders (collect your markup from your buyer directly). Production API keys only. external_reference is your idempotency key: a repeated reference returns 409 instead of double-charging.","servers":[{"url":"https://safe.dawurobo.com"}],"security":[{"ApiKeyAuth":[]}],"x-required-scope":"safe:write","parameters":[{"name":"X-Signature","in":"header","required":true,"schema":{"type":"string"},"description":"HMAC-SHA256 signature of the canonical request, computed with your signing secret."},{"name":"X-Timestamp","in":"header","required":true,"schema":{"type":"string"},"description":"Request timestamp as a Unix timestamp in SECONDS (not milliseconds), e.g. Math.floor(Date.now()/1000). Included in the signed canonical request; requests more than 5 minutes off the server clock are rejected with 401 STALE_REQUEST."},{"name":"X-Nonce","in":"header","required":true,"schema":{"type":"string"},"description":"Unique per-request nonce included in the signed canonical request (replay protection)."}],"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","enum":["success"]},"data":{"type":"object","properties":{"sale_id":{"type":"string","description":"Data Connect order id — pass this as sale_id to orders.verify/orders.get."},"reference":{"type":"string","description":"Human-facing order reference."},"checkout_url":{"type":"string","nullable":true,"description":"Payment gateway checkout URL — redirect the buyer here to complete payment. null for cash-on-delivery orders (there is nothing to pay online)."},"state":{"type":"string","enum":["awaiting_delivery"],"description":"Present only for cash-on-delivery orders: \"awaiting_delivery\" — poll orders.verify until the order is delivered (settles) or the delivery terminally fails (stock restocked)."},"subtotal_ghs":{"type":"number"},"delivery_fee_ghs":{"type":"number"},"markup_ghs":{"type":"number","description":"Partner resale markup included in the charge total. Always 0 for cash on delivery."},"total_ghs":{"type":"number","description":"Total amount charged via the gateway (subtotal + delivery fee + markup) — or, for cash on delivery, the cash the rider collects at the door (subtotal + delivery fee)."}},"required":["sale_id","reference","checkout_url","subtotal_ghs","delivery_fee_ghs","markup_ghs","total_ghs"],"additionalProperties":false}},"required":["status","data"],"additionalProperties":false}}}},"400":{"description":"Bad request — malformed JSON, missing/invalid fields, or a failed validation rule.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Unauthorized — missing/invalid API key, signature, timestamp, or signing setup.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Forbidden — insufficient scope, inactive partner, or environment not active.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found — unknown operation, or a resource that doesn't exist or isn't yours.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict — replayed nonce, or a duplicate reference on create operations.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"payment_method":{"type":"string","enum":["online","cod"],"description":"\"online\": prepaid — the buyer pays via the gateway checkout_url before dispatch. \"cod\": cash on delivery — no charge is started; the buyer pays the rider subtotal + delivery fee in cash at the door, and the order settles when orders.verify sees it delivered. reseller_markup_ghs is not supported with \"cod\"."},"vendor_id":{"type":"string","description":"The syndicated vendor's uid. All items in the order must belong to this vendor."},"items":{"type":"array","items":{"type":"object","properties":{"product_id":{"type":"string"},"variant_id":{"type":"string"},"quantity":{"type":"integer","exclusiveMinimum":true,"minimum":0}},"required":["product_id","variant_id","quantity"],"additionalProperties":false},"minItems":1,"description":"Order line items. Prices/stock are always resolved server-side, never trusted from the caller."},"buyer":{"type":"object","properties":{"name":{"type":"string"},"phone":{"type":"string"}},"required":["name","phone"],"additionalProperties":false},"delivery":{"type":"object","properties":{"address":{"type":"string"},"lat":{"type":"number"},"lng":{"type":"number"},"area_id":{"type":"string"}},"required":["address"],"additionalProperties":false},"reseller_markup_ghs":{"type":"number","description":"Partner resale markup added on top of subtotal + delivery fee. Must be between 0 and the subtotal. NOT supported with payment_method \"cod\" — a markup > 0 on a COD order is rejected with MARKUP_NOT_SUPPORTED_FOR_COD (the rider only collects subtotal + delivery fee; collect your markup from your buyer directly)."},"external_reference":{"type":"string","minLength":3,"maxLength":64,"description":"Your own order id (3-64 chars). Retrying with the same value returns DUPLICATE_REFERENCE instead of double-charging."}},"required":["payment_method","vendor_id","items","buyer","delivery","external_reference"],"additionalProperties":false}}}}}},"/api/v1/safe-catalog/orders.verify":{"post":{"operationId":"safe-catalog.orders.verify","tags":["safe-catalog"],"summary":"Verify + settle a syndicated order's payment","description":"Verifies the order and, once settled, appends the sale's settlement decomposition to the ledger (idempotent). Prepaid orders are verified against the payment gateway; cash-on-delivery orders are verified against the DELIVERY — they settle once the fulfillment reports delivered (poll until then), and a terminally failed delivery cancels the order and restocks its items. Production API keys only.","servers":[{"url":"https://safe.dawurobo.com"}],"security":[{"ApiKeyAuth":[]}],"x-required-scope":"safe:write","parameters":[{"name":"X-Signature","in":"header","required":true,"schema":{"type":"string"},"description":"HMAC-SHA256 signature of the canonical request, computed with your signing secret."},{"name":"X-Timestamp","in":"header","required":true,"schema":{"type":"string"},"description":"Request timestamp as a Unix timestamp in SECONDS (not milliseconds), e.g. Math.floor(Date.now()/1000). Included in the signed canonical request; requests more than 5 minutes off the server clock are rejected with 401 STALE_REQUEST."},{"name":"X-Nonce","in":"header","required":true,"schema":{"type":"string"},"description":"Unique per-request nonce included in the signed canonical request (replay protection)."}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","enum":["success"]},"data":{"type":"object","properties":{"sale_id":{"type":"string"},"state":{"type":"string","enum":["pending","awaiting_delivery","failed","confirmed"],"description":"pending: (prepaid) the gateway hasn't confirmed yet — keep polling the same sale_id. awaiting_delivery: (cash on delivery) the order hasn't been delivered yet — keep polling; COD settles on delivery, not at a gateway. failed: terminal — stock has been released; create a new order with a fresh external_reference. confirmed: settled (prepaid: payment verified; COD: delivered and cash collected at the door)."},"ledger":{"anyOf":[{"type":"object","properties":{"created":{"type":"number"},"skipped":{"type":"number"}},"required":["created","skipped"],"additionalProperties":false},{"type":"object","properties":{"error":{"type":"boolean","enum":[true]}},"required":["error"],"additionalProperties":false}],"description":"Settlement ledger append result. Present only when state is confirmed."}},"required":["sale_id","state"],"additionalProperties":false}},"required":["status","data"],"additionalProperties":false}}}},"400":{"description":"Bad request — malformed JSON, missing/invalid fields, or a failed validation rule.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Unauthorized — missing/invalid API key, signature, timestamp, or signing setup.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Forbidden — insufficient scope, inactive partner, or environment not active.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found — unknown operation, or a resource that doesn't exist or isn't yours.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict — replayed nonce, or a duplicate reference on create operations.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"sale_id":{"type":"string","description":"The sale_id returned by orders.create (Data Connect order id)."}},"required":["sale_id"],"additionalProperties":false}}}}}},"/api/v1/safe-catalog/orders.get":{"get":{"operationId":"safe-catalog.orders.get","tags":["safe-catalog"],"summary":"Get a syndicated order's status","description":"Read-only status check (payment + delivery state) for a syndicated order owned by the calling partner.","servers":[{"url":"https://safe.dawurobo.com"}],"security":[{"ApiKeyAuth":[]}],"x-required-scope":"safe:read","parameters":[{"name":"X-Signature","in":"header","required":true,"schema":{"type":"string"},"description":"HMAC-SHA256 signature of the canonical request, computed with your signing secret."},{"name":"X-Timestamp","in":"header","required":true,"schema":{"type":"string"},"description":"Request timestamp as a Unix timestamp in SECONDS (not milliseconds), e.g. Math.floor(Date.now()/1000). Included in the signed canonical request; requests more than 5 minutes off the server clock are rejected with 401 STALE_REQUEST."},{"name":"X-Nonce","in":"header","required":true,"schema":{"type":"string"},"description":"Unique per-request nonce included in the signed canonical request (replay protection)."},{"name":"sale_id","in":"query","required":true,"schema":{"type":"string","description":"The sale_id returned by orders.create (Data Connect order id)."},"description":"The sale_id returned by orders.create (Data Connect order id)."}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","enum":["success"]},"data":{"type":"object","properties":{"sale_id":{"type":"string"},"state":{"type":"string","enum":["confirmed","pending_payment","awaiting_delivery"],"description":"confirmed: settled. pending_payment: prepaid order still awaiting gateway payment. awaiting_delivery: cash-on-delivery order not yet delivered — it settles via orders.verify once delivered."},"payment_paid":{"type":"boolean"},"delivery_status":{"type":"string","nullable":true},"delivery_order_reference":{"type":"string","nullable":true},"amount_ghs":{"type":"number","nullable":true}},"required":["sale_id","state","payment_paid","delivery_status","delivery_order_reference","amount_ghs"],"additionalProperties":false}},"required":["status","data"],"additionalProperties":false}}}},"400":{"description":"Bad request — malformed JSON, missing/invalid fields, or a failed validation rule.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Unauthorized — missing/invalid API key, signature, timestamp, or signing setup.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Forbidden — insufficient scope, inactive partner, or environment not active.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found — unknown operation, or a resource that doesn't exist or isn't yours.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict — replayed nonce, or a duplicate reference on create operations.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}},"components":{"securitySchemes":{"ApiKeyAuth":{"type":"apiKey","in":"header","name":"X-API-Key","description":"Partner API key (X-API-Key). You need a Dawurobo partner account to get one — sign up and generate self-serve sandbox keys first. Every request must ALSO be signed: X-Signature (HMAC-SHA256 over the canonical request using your signing secret), X-Timestamp, and X-Nonce. Requests without a valid key and signature return 401."}},"schemas":{"Error":{"type":"object","properties":{"status":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"}}}}}}