API module
Base URLs:- Live:
https://api.waysdrop.com - Staging:
https://staging-api.waysdrop.com
/api
This module is intended for third‑party integrations. All endpoints require the api-key header.
Response shapes
Success
No content
Some endpoints return204 No Content with an empty body.
Errors
Errors are returned using the global error envelope described in Errors.Conventions
- Decimals — Prisma
Decimalfields serialize as strings in JSON (e.g."1650.00","2.00000"). - Coordinates — Resolved locations use flat
lat/lonnumbers, not a nestedlocobject. - Optional fields — Geo/admin fields on resolved addresses vary by what was geocoded; omitted keys are not returned.
Origin and destination
Endpoints that acceptorigin and destination (POST /api/route, POST /api/pricing, POST /api/request) use the same address model. You can send a plain string, a minimal geocode object, or a full resolved object from your map picker.
Request input
Legacy string — geocoded server-side:/api/route response. Extra geo/admin fields are preserved; geocoding uses address (or addressLine1), lat/lon, and googlePlaceId.
On
POST /api/request, origin contact fields can also be set at the top level (originContactName, originContactPhone, originContactEmail). Top-level destination contact fields are required unless already present on the destination object.
Resolved address object
After geocoding (in/api/route responses, delivery records, etc.), origin and destination resolve to this shape. All fields except country are optional — presence depends on the geocode result.
Persisted addresses on deliveries (
GET /api/deliveries/:deliveryId, POST /api/request → delivery.origin / delivery.destination) include id and timestamps in addition to the fields above.
Endpoints
GET /api/countries
Fetch available countries for routing and pricing. Querysearch(optional, string)
Without
search, returns up to 50 results.
GET /api/states
Fetch available states. Querysearch(optional, string)
GET /api/cities
Fetch available cities. Querysearch(optional, string)
valueisgooglePlaceIdwhen available, otherwiselocationId.lat/lonare the coordinates used for distance and ETA calculations.- Without
search, returns up to 50 results.
POST /api/route
Get route data between two addresses. Bodyoriginanddestinationuse the resolved address object shape. Contact fields are not included unless you sent them on input.routeTypeis one ofINTER_CITY,INTER_STATE,INTER_REGION,INTER_COUNTRY, orINTER_CONTINENT.distance.distanceKmanddistance.etaSecondsuse the max of line and road distance for safety.
GET /api/fleet-types
Fetch available fleet types. 200 Responseicon and description may be null.
POST /api/pricing
Get pricing for a delivery request. Two pricing modes are supported — use one or the other. Mode A — by package IDs (preferred) Resolves weight and value from your saved packages. Matches the pricing logic used byPOST /api/request. Requires an authenticated user (API key owner).
Mode A response — packagesId
200 Response
costs.total=deliverySubtotal+serviceFee(+ hub commission when applicable).deliveryFeedescribes who pays what before a request is created.matchingEligibleistruewhen courier matching can start immediately after payment.- When
courierSelectionisSPECIFIC, acourierobject may also be included. - Auto-promotions are not applied on this endpoint.
Mode B response — totalWeight + totalValue
200 Response
courierPricingRule is populated and weight/fleet/surcharge may be zeroed:
400Provide packagesId or both totalWeight and totalValue400Authenticated user is required when pricing by packagesId
POST /api/request
Create a delivery request (P2P). Bodyorigin / destination satisfy contact requirements — top-level originContact* / destinationContact* fields are optional in that case.
Body fields
Courier selection
ANYONE— any available courier on the platformSPECIFIC— assign a courier you already have in the system (courierIdrequired)MERCHANT_SPECIAL_COURIERS— assign from your merchant-specific courier list (requires couriers added in the merchant dashboard)
Response — paymentMethodType: WALLET (default)
201 Response
Response — paymentMethodType: CHECKOUT
Returns a Paystack checkout payload instead of debiting the wallet immediately:
Response — payOnDelivery: true
Adds a payOnDelivery block:
totalWeightandtotalValueon the P2P record are strings (Decimal).delivery.distanceKmis a number (float).delivery.statusis alwaysREQUEST_CREATEDon create;statuson the P2P record reflects payment state (PENDING,PENDING_PAYMENT, etc.).- Full
origin/destinationuse the resolved address object plusidand timestamps.
422Insufficient balance400Invalid packages selection400Origin and destination cannot be the same404Fleet type not found404No merchant specific couriers found(when usingMERCHANT_SPECIAL_COURIERSwithout configured couriers)
POST /api/request/:deliveryId/cancel
Cancel an eligible delivery request. Path paramsdeliveryId(uuid)
404Delivery request not found400Delivery request can not be canceled due to its current status400You can only cancel a delivery request twice every 3 hours
POST /api/package
Create or edit a package. Body Use this endpoint to create a new package or update an existing one.- To create, omit
packageIdand provide all required fields. - To update, include
packageIdand provide only the fields you want to change.
Weight is derived from
size on create — you do not send weight directly.
201 Response
DELETE /api/package/:packageId
Delete a package. Path paramspackageId(uuid)
- No content
GET /api/packages
Get packages that have not been assigned to a delivery (for the authenticated user). 200 ResponseDeliveryPackage record for each unassigned package.
GET /api/deliveries/:deliveryId
Get a delivery (for the authenticated user). Path paramsdeliveryId(uuid)
- The delivery object includes all scalar
Deliveryfields — the example shows the most useful ones. originanddestinationuse the full resolved address object withidand timestamps.courieris omitted (notnull) until a courier is assigned.currentLocationuses flatlat/lon, not a nestedlocobject.- Proof
codeisnulluntil the proof has been scanned (scannedAtis set). deliveryStepsonly includes visible steps (hiddensteps are excluded).p2pDelivery.totalWeightandtotalValueare strings (Decimal).