For Store / Marketplace
In this case, the system owner will create an account with Delyva and have direct billing with Delyva, and all the merchants if there are more than one will be using the system owner’s account with Delyva.
For SaaS / Platform
In this case, the merchants or SaaS subscribers will create an account with Delyva and have direct billing with Delyva. SaaS platform owners will earn 1% of the order amount as revenue sharing by Delyva.
Recommended Settings For SaaS / Platform
In this case, there must be a settings/configuration page for the user to enter their API keys:
Delyva Settings
- API Parameters
- Company code: [text input]
- Company ID: [text input]
- User ID: [text input]
- Customer ID: [text input]
- Item Type: [dropdown: PARCEL/PACKAGE/BULKY]
- Checkout Rates:
- Enable/Disable [/]
- Checkout Rates Adjustment
- Adjustment type: [Mark-up / Discount]
- Percentage rate: [Number: 0-100]
- Flat rate: [Number:0-100]
- *Checkout rate adjustment formula: [Delivery rate = service price + % rate + flat rate]
- Free Shipping/Delivery when order total amount equal to or above (0=disable): [Number]
How to integrate with Delyva API?
API Documentation
You may refer to Delyva API Documentation – https://docs.api.delyva.com/.
Normally store or marketplace will be integrating with these endpoints:
- Service > Price Quote API
- Create Order > Create Order API
- Create Order > Process/Confirm Order
- Create Order > Get Order Details
- Create Order > Cancel Order
- Create Order > Print Label
- Getting Delivery Order Status Updates via Webhook
Request API Header
{ “Content-Type”:”application/json” “X-Delyvax-Access-Token”: <apiKey>. }
Getting the API Keys
You can get the API keys in Delyva customer portal > Settings > API Integrations
- Sign up and Log on to Delyva customer portal
- Development: https://trydx.delyva.app/customer
- Production: https://my.delyva.app/customer
- Go to Settings > API Integrations
- Copy the API parameters: Company code, Company ID, User ID, Customer ID.
- Click Add a new key, enter any name and copy the generated API key “apiKey”.
- For webhook verification, you will need to use apiSecret. To get apiSecret, call GET /user and get user.apiSecret in the response.
Getting The List of Services & Delivery Rates
POST Price Quote
POST https://api.delyva.app/v1.0/service/instantQuote
{ “customerId”: 123, //mandatory "origin": { "address1": "28 Jalan 5", "address2": "Taman Mesra", "city": "Kajang", "state": "Selangor", "postcode": "43000", "country": "MY", "coord": { "lat": "3.013478", "lon": "101.779682" } }, "destination": { "address1": "F-11-19 Pacific Place", "address2": "Ara Damansara", "city": "Petaling Jaya", "state": "Selangor", "postcode": "47301", "country": "MY", "coord": { "lat": "3.11100853226846", "lon": "101.58726936290537" } }, "extId": "your-internal-vendor-id", //optional "weight": { "unit": "kg", "value": 0.9000 }, “itemType”: <itemType> //optional eg PARCEl/PACKAGE/FOOD/BULKY, "inventory": [ { "weight": { "value": 1, "unit": "kg" },"dimension": { "unit": "cm", "width": 10, "length": 15, "height": 5 }, "quantity": 1 }, { "weight": { "value": 0.5, "unit": "kg" }, "dimension": { "unit": "cm", "width": 10, "length": 15, "height": 5 }, "quantity": 1 } ], }
From the response, you will need to save selected service value – services[selected-service].serviceCompany.companyCode . You will use this value when creating the delivery order later on. Take note of the service-supported item types.
If your platform will be using instant delivery or same-day delivery services for address accuracy and to avoid any issues with the pick-up and delivery process, it is best if your system submits origin and destination coordinates (coord{lat,lng}). If your system does not have the coordinates, do not submit “coord” at all, and Delyva will geocode the address but it will not be as accurate, most of the time will only be building-level, or street-level accurate.
You can also filter by service type:
{ .. "serviceType":"INSTANT", }
Service type available:
- NDD: Next Day Delivery Courier Services (Pick-up services)
- NDD-DROP: Next Day Delivery Courier Services (Drop-off services)
- COD-NDD: Next Day Delivery Courier Services with Collect Cash On Delivery Service (COD) (Pick-up services)
- COD-NDD-DROP: Next Day Delivery Courier Services with Collect Cash On Delivery Service (COD) (Drop-off services)
- INSTANT – Instant Delivery Courier Services (1-2 hours)
- SD – Same-Delivery Courier Services (3-4 hours)
- INTERNATIONAL – International Courier Services
- MOTO – Motorcycle Transport Services
Create a Delivery Order
Once buyers have paid for the order, you may call POST Create Order API and set process: false, to create the delivery order as a draft.
POST Create Order API
POST https://api.delyva.app/v1.0/order
{ "customerId": 123, "process": false, //if this is false, delivery order will be created as draft "serviceCode": <services[selected-service].serviceCompany.companyCode>, “source”: "your-system-code”, //add this source so we could identify this order coming from your system "extId": "your-internal-vendor-id", //optional "referenceNo": "your-internal-order-reference-number", //optional "note": "order-note", "waypoint": [{ "type": "PICKUP", //this means origin / sender info "scheduledAt": "2020-12-24T12:00:00+0800", "note": "optional note to personnel at this waypoint", "inventory": [ { "name": "Mee Kari", "type": <itemType>, //you can get available item type from selected service "price": { "amount": "10.50", "currency": "MYR" }, "weight": { "value": 1, "unit": "kg" }, "dimension": { "unit": "cm", "width": 10, "length": 15, "height": 5 }, "quantity": 1, "description": "" }, { "name": "Ayam Goreng", "type": <itemType>, //you can get available item type from selected service "price": { "amount": "8.00", "currency": "MYR" }, "weight": { "value": 0.5, "unit": "kg" }, "dimension": { "unit": "cm", "width": 10, "length": 15, "height": 5 }, "quantity": 1, "description": "" } ], "contact": { "name": "Test Sender", "email": "[email protected]", "phone": "60124433300", "unitNo": "", "address1": "157, Jalan Ampang", "address2": "", "city": "Wilayah Persekutuan", "state": "Kuala Lumpur", "postcode": "55000", "country": "MY", "coord": { "lat": "3.013478", "lon": "101.779682" } } }, { "type": "DROPOFF", //this means delivery / receiver info "scheduledAt": "2020-12-24T13:00:00+0800", "note": "optional note to personnel at this waypoint", "inventory": [ { "name": "Mee Kari", "type": <itemType>, //you can get available item type from selected service "price": { "amount": "10.50", "currency": "MYR" }, "weight": { "value": 1, "unit": "kg" }, "dimension": { "unit": "cm", "width": 10, "length": 15, "height": 5 }, "quantity": 1, "description": "" }, { "name": "Ayam Goreng", "type": <itemType>, //you can get available item type from selected service "price": { "amount": "8.00", "currency": "MYR" }, "weight": { "value": 0.5, "unit": "kg" }, "dimension": { "unit": "cm", "width": 10, "length": 15, "height": 5 }, "quantity": 1, "description": "" } ], "contact": { "name": "Mr Receiver", "email": "[email protected]", "phone": "60124433300", "mobile": "60124433300", "unitNo": "6-8", "address1": "MRT Sungai Jernih (SBK33)", "address2": "1, Kampung Sungai Kantan", "city": "Kajang", "state": "Selangor", "postcode": "43000", "country": "MY", "coord": { "lat": "3.11100853226846", "lon": "101.58726936290537" } } }] }
From the response, you will need to save order.id which you will be used in other API endpoints.
Take note, delivery order total weight will be taken into account of all inventory unit weight x quantity. Eg. Total weight = 0.5 kg x 4 pc = 2.0kg
If your platform will be using instant delivery or same-day delivery services, for address accuracy and to avoid any issues with the pick-up and delivery process, it is best if your system submits origin and destination coordinates ( coord{lat,lng}). If your system does not have the coordinates, do not submit “coord” at all, and Delyva will geocode the address but it will not be as accurate, most of the time will only be building-level, or street-level accurate.
Process/Confirm Draft Order
Once the merchant has prepared/packed the package, call POST Process/Confirm Order to process the delivery order. You may also call this API in advance with the scheduled date & time if you are sure the package will be ready by the scheduled date & time.
POST {{API_ENDPOINT}}/v1.0/order/<:orderId>/process
{ "serviceCode": "", "originScheduledAt": "", "destinationScheduledAt": "" }
Get the Tracking Number and Delivery Order Details
Use the order.id in Create Order API response to get tracking number / consignment number, call GET Get Order Details API > response “consignmentNo”.
GET {{API_ENDPOINT}}/v1.0/order/<:order_id>
You can also get driver information from this API response: order.personnel.
Cancel a Delivery Order
To cancel any order, call POST Cancel Order API.
POST {{API_ENDPOINT}}/v1.0/order/<:orderId>/cancel
Cancellation rule
- For courier services, you can only cancel the delivery order before order.statusCode equals to 110 (Label has been printed). For cancellation after this status code, please contact Delyva customer support. This rule is set due to some merchants proceeding to send the package to the couriers even after the delivery order has been canceled.
- For instant and same-day delivery services, you can only cancel the delivery order before order.statusCode equals to 200 (Driver has accepted the order). This is to respect drivers’ effort and time in performing their duties.
Print Shipping Label
To print a shipping label/consignment label/ airway bill (AWB), simply call GET Print label API.
GET {{API_ENDPOINT}}/v1.0/order/<:orderId>/label?companyId=<:companyId>
The API will generate a label in PDF format, you can also put a link in your system [Print label] and open a new tab to print the label.
Print Multiple Shipping Labels
GET {{API_ENDPOINT}}/v1.0/order/<:orderId>,<:orderId>,<:orderId>/label?companyId=<:companyId>
Print Shipping Label with Packing List
GET {{API_ENDPOINT}}/v1.0/order/<:orderId>/label?companyId=<:companyId>packingList=true
Print Multiple Shipping Labels with Packing List
GET {{API_ENDPOINT}}/v1.0/order/<:orderId>,<:orderId>,<:orderId>/label?companyId=<:companyId>packingList=true
Getting Order Status Updates
To get real-time delivery order status updates, please subscribe to
- Subscribe to Webhook(s)
- Webhook: order.created
- Webhook: order.failed
- Webhook: order_tracking.change
- Webhook: order_tracking.update
If you decide to show real-time driver movement, you may embed this real-time map with ETA URL (display this only for orders with statusCode > 200 and < 700): https://my.delyva.app/customer/rmap?trackingNo=
Subscribe to Webhook
You can add your webhook URL in Delyva customer portal > Settings > Webhook.
You may programmatically subscribe to any of the webhook by calling the POST Subscribe API.
Order Tracking Status Updates
Example payload for order_tracking.update and order_tracking.change https://gist.github.com/suhaimi-hz/8b20cfa4fd12686c6fda2ab94121934c
{ companyId: '2cab0b07-7a5d-4971-aeba-5ffac537a455', orderId: '6264954f-014b-4fe9-b077-a8864511f518', customerId: 32, userId: '33aee880-003c-11ea-b96b-d53dda460f07', consignmentNo: '000002009ASD', statusCode: 400, statusText: 'In transit', description: 'In-transit by personnel', location: '-', driverId: 126, taskId: 2149, createdAt: '2021-01-11T16:10:48.237Z', id: 2641, coord: { lon: 101.7381374, lat: 3.1401939 }, personnel: { name: 'Suhaimi Pic1', phone: '60137778595', vehicleName: '-', vehicleType: '-', vehicleRegNo: '-' }, arrival: { distance: { value: 2232, unit: 'm' }, duration: { value: 286, unit: 's' }, accuracy: 1 }, invoiceId: null }
Example payload order.created / order.updated / order.failed (the same as GET Get Order Details response without “data”)
{ "id": "ca3ad567-4e50-4f7e-bb86-3732a1f1acfd", "companyId": "9e0aed8a-5c67-42a4-82b6-e01bf7687f31", "userId": "c2f29360-f62d-11ea-ba2e-99a2a4722cf9", "customerId": 414, "serviceId": 297, "serviceCode": "NJVMY", "price": { "amount": 4.33, "currency": "MYR" }, "revenue": { "amount": 1.19, "currency": "MYR" }, "commission": { "amount": 3.14, "currency": "MYR" }, "distance": { "unit": "km", "value": 2.42 }, "weight": { "unit": "kg", "value": 0.1 }, "cod": { "amount": 0, "currency": "MYR" }, "consignmentNo": "DM003675M", "paymentTerm": "debit", "itemType": "PARCEL", "itemTypeId": 14, "dimension": { "unit": "cm", "width": 0, "height": 0, "length": 0 }, "statusCode": 110, "status": "ready", "createdAt": "2021-05-04T23:28:21.705Z", "updatedAt": "2021-05-06T13:59:27.793Z", "deletedAt": null, "failedReason": "", "promoCode": "", "vehicleId": null, "invoiceId": "a8fbec6b-8ccf-47e1-ae40-30ad5fd68b25", "discountPrice": "0.00", "discount": "0.00", "personnelId": null, "note": "", "extId": "", "extIdType": "", "serviceAddon": [], "rating": null, "ratingNote": "", "agentCommission": null, "billing": { "city": "-", "name": "-", "email": "[email protected]", "phone": "60123456789", "state": "Selangor", "mobile": "", "unitNo": "", "country": "MY", "address1": "-", "address2": "-", "postcode": "-" }, "paymentMethodId": 0, "cancelledReason": null, "source": "api", "promoValue": "0.00", "cron": 0, "metadata": {}, "personnel": null, "surcharge": "0.00", "commodityId": "", "pluginId": null, "requestPickup": false, "insurance": null, "waypoint": [ { "id": "wp_nE5tscYM1VMWVgMwGzUbhP", "orderId": "ca3ad567-4e50-4f7e-bb86-3732a1f1acfd", "no": 1, "inventory": [ { "name": "Parcel", "type": "PARCEL", "price": { "amount": 0, "currency": "MYR" }, "action": "P", "weight": { "unit": "kg", "value": 0.1 }, "quantity": 1, "description": "-" } ], "contact": { "city": "Petaling Jaya", "name": "Ahmad", "coord": { "lat": "3.11283", "lon": "101.59857" }, "phone": "60123456789", "state": "Selangor", "mobile": "60123456789", "country": "MY", "address1": "Ara Damansara", "postcode": "47301", "sortCode": "KV" }, "type": "PICKUP", "description": "-", "status": "pending", "note": "-", "scheduledAt": "2021-05-04T23:28:21.723Z", "createdAt": "2021-05-04T23:28:21.723Z", "updatedAt": "2021-05-04T23:28:23.607Z", "deletedAt": null, "cash": { "amount": 0, "currency": "MYR" }, "placeId": null, "actualScheduledAt": null, "startAt": "2021-05-04T16:00:21.723Z", "actualStartAt": null }, { "id": "wp_rS2vgBusBQq9GLPztKUNmQ", "orderId": "ca3ad567-4e50-4f7e-bb86-3732a1f1acfd", "no": 2, "inventory": [ { "name": "Parcel", "type": "PARCEL", "price": { "amount": 0, "currency": "MYR" }, "action": "D", "weight": { "unit": "kg", "value": 0.1 }, "quantity": 1, "description": "-" } ], "contact": { "city": "Petaling Jaya", "name": "Ali", "coord": { "lat": "3.1102867", "lon": "101.5857838" }, "phone": "60123456789", "state": "Selangor", "mobile": "60123456789", "country": "MY", "address1": "Pacific Place, Ara Damansara", "postcode": "47301", "sortCode": "KV" }, "type": "DROPOFF", "description": "-", "status": "pending", "note": "-", "scheduledAt": "2021-05-04T23:33:22.288Z", "createdAt": "2021-05-04T23:28:21.723Z", "updatedAt": "2021-05-04T23:28:23.607Z", "deletedAt": null, "cash": { "amount": 0, "currency": "MYR" }, "placeId": null, "actualScheduledAt": null, "startAt": "2021-05-04T23:30:22.288Z", "actualStartAt": null } ], "paymentMethod": "Credit" }
How to test your order tracking status updates webhook?
- Using the above samples of webhook payload, you can manually send the payload using Postman to your webhook URL.
- Download DelyvaX Driver App (only available in Android) and log in using the same development customer login. Notify us and we will activate you as a driver to update the status from driver acceptance to pick-up success to delivery successful.
Addons: Collect Cash On Delivery (COD) / Insurance Premium
- Send a normal price quote and get the list of services.
- Then, the customer/merchant selects a service with an add-on, then, send another Price Quote API request with the selected service code and add-on value.
Price Quote API
PriceQuote for COD (addon id: -1)
serviceAddon: [ {id: -1, value: "500"} ]
PriceQuote for Insurance (addon id: -3)
serviceAddon: [ {id: -3, value: "400"} ]
PriceQuote for both Insurance & COD
serviceAddon: [ {id: -1, value: "500"}, {id: -3, value: "400"} ]
Create Order API
For insurance premium
Create Order API, add
insurance = { currency: "MYR",amount: 1000 }
For Cash On Delivery
Create Order API, add
cod = { currency: "MYR",amount: 1000 }
Bonus: Programmatically authenticate, generate API key and get latest customer’s wallet balance
- Authenticate
- Create API key
- Get the customer’s latest wallet balance
1. Authenticate
POST https://api.delyva.app/v1.0/auth/login
Sample request:
{ "companyCode": "<companyCode>", "username": "<email>", "password": "<password>" }'
Sample response:
{ "data": { "accessToken": .. } }
* Use data.accessToken as Bearer token when requesting #2 Create an API Key.
2. Create and get the API key
POST https://api.delyva.app/v1.0/auth/personalAccessToken
Request:
{"name":"<API key name>"}
—-
Response (Store token as API key and use it for any new request):
{ "companyId":"xx", "id":"xx", "token":"xx", <--- API key "userId":"xx", }
3. Price Quote API
GET https://api.delyva.app/v1.0/customer
Response: { 'data':{ 'walletBalance': 10.00 } }