Introduction
Welcome to Lalamove Plus API.
What is Lalamove Plus?
Lalamove Plus is our advanced solution tailored to meet your expanded logistic needs, beyond just on-demand/instant deliveries. From handling mid/last mile deliveries to facilitating first-mile pickup services, its capabilities are adept at addressing a wider spectrum of logistic requirements.
If you find the current Lalamove on-demand platform falls short in accomodating your scheduled non-urgent deliveries requisites, Lalamove Plus offers the more comprehensive solution engineered to to deliver higher operational efficiencies at a reduced cost, perfectly meeting the complex requirements of sizable logistics operations.
With a focus on flexibility and adaptability for Enterprise customers, Lalamove Plus offers a high degree of customization to precisely match your unique specifications. Whether it pertains to tailoring service level benchmarks, operational protocols, or intricate status and item tracking mechanisms, Lalamove Plus stands ready to meet your needs, ensuring a seamless integration with your operation.
What is the key difference between Lalamove On-Demand vs. Lalamove Plus?
Lalamove On-Demand offers: - District/distance-based dynamic pricing - Fluctuating service level dependent on real time supply & demand conditions - Best fitted for point-to-point on-demand/instant deliveries - Best fitted for Full Truckload (FTL) services
Lalamove Plus offers: - Customisable pricing models based on your requirement - Guaranteed fulfilment & service level expectations - Airway bill and/or label generation & scanning capabilities - Detailed, trackable status updates and SLA monitoring on a per-item basis - Customizable driver handling and SOPs based on requirement (e.g. failed delivery/return flow) - Generation of End-of-Day reports - Best fitted for scheduled deliveries dispatched from centralised location(s) (e.g. parcel) - Best fitted for Less Than Truckload (LTL) services
N.B. Lalamove and Lalamove Plus have separate portals and user interfaces for all its components.
Authentication
Lalamove Plus API uses HMAC (SHA256) as its authentication mechanism.
You will be provided with an API KEY
, and an API SECRET
by partner.support@lalamove.com that you can use to generate a HMAC signature (SIGNATURE
).
# With shell, you can just pass the correct header with each request
curl 'https://rest.sandbox.lalamove.com/v3/quotations' \
-H 'Authorization: hmac {}' \
-H 'Content-Type: application/json' \
-H 'Market: HK'
-H 'Platform: PLUS'
All API requests must be made over HTTPS. Calls made over plain HTTP will fail.
Lalamove environment has different Base URL that you can use. This is shown below:
Environment | Base URL |
---|---|
Sandbox | https://rest.sandbox.lalamove.com |
Production | https://rest.lalamove.com |
Signature
Example in JavaScript
const SECRET = 'sk_test_Lalamove_API_KEY';
const time = new Date().getTime().toString(); // => `1545880607433`
const method = 'POST';
const path = '/v3/quotations';
const body = JSON.stringify({...}); // => the whole body for '/v3/quotations'
const rawSignature = `${time}\r\n${method}\r\n${path}\r\n\r\n${body}`;
//const rawSignature = `${time}\r\n${method}\r\n${path}\r\n\r\n`; if the method is GET
// => '1546222219293\r\nPOST\r\n/v3/quotations\r\n\r\n{\n"data":{...}'
const SIGNATURE = CryptoJS.HmacSHA256(rawSignature, SECRET).toString();
// => '5133946c6a0ba25932cc18fa3aa1b5c3dfa2c7f99de0f8599b28c2da88ed9d42'
SIGNATURE = HmacSHA256ToHex(<TIMESTAMP>\r\n<HTTP_VERB>\r\n<PATH>\r\n\r\n<BODY>, <SECRET>)
SIGNATURE
is in lowercase hex (base 16) encoding.
SECRET |
Your API secret |
TIMESTAMP |
Unix timestamp in milliseconds eg. 1545880607433 |
METHOD |
Method (GET , POST , DELETE , PATCH ) of the specific API call |
PATH |
The pathname of the specific API call including version. eg. /v3/quotations |
BODY |
The request body in JSON string |
Useful links
- Examples of creating base64 hashes using HMAC SHA256 in different languages
- SHA256 HMAC in different languages (both hex & base64 encoding)
Headers
Example in JavaScript (cont.)
const API_KEY = 'pk_test_Lalamove_API_key'
const TOKEN = `${API_KEY}:${time}:${SIGNATURE}`
Authorization: hmac <TOKEN>
Market: <YOUR_MARKET>
Request-ID: <NONCE>
Platform: PLUS
Example
Authorization: hmac 914c9e52e6414d9494e299708d176a41:1545880607433:5133946c6a0ba25932cc18fa3aa1b5c3dfa2c7f99de0f8599b28c2da88ed9d42
Market: TH
Request-ID: 211b9d85-a2cc-476f-8675-b61ec923cc27
Platform: PLUS
Authorization
TOKEN = <KEY>:<TIMESTAMP>:<SIGNATURE>
KEY |
Your API key |
TIMESTAMP |
MUST be identical to TIMESTAMP in SIGNATURE |
SIGNATURE |
As described in Signature in lowercase hex (base 16) |
Market
Please specify the market you are placing orders in UN/LOCODE format. For example, Indonesia will be listed as ID
. See Available Markets for details.
Request-ID
Provide a Nonce to be used as a unique Request ID. If you are having trouble with any request, sharing the Request ID with us will be the fastest way.
Available Markets
Lalamove Plus API is currently available in the following 2 markets.
Market | Market Code |
---|---|
Hong Kong, China | HK |
Indonesia | ID |
Philippines | PH |
Singapore | SG |
Taiwan, China | TW |
Thailand | TH |
Order Flow
Plus currently offers 2 kinds of order statuses IN_PROGRESS
and end-states (DELIVERED
, CANCELED
, CLOSED
)
Order State | Order Statuses |
---|---|
During Order | IN_PROGRESS |
Finished Order (end-state) | DELIVERED , CANCELED , CLOSED |
Order Status | Description |
---|---|
IN_PROGRESS |
Overarching status during the delivery for details. For detailed status inside IN_PROGRESS , please see below |
DELIVERED |
Delivery completed |
CLOSED |
Customer requested cancellation after failed pick-up or drop-off. No parcel is delivered as a result |
CANCELED |
Customer requested cancellation |
IN_PROGRESS
can be further broken down like below.
AWAIT_DRIVER |
Waiting for driver to be assigned |
AWAIT_PICKUP |
A driver is assigned |
DELIVERING |
The driver has arrived at the pick-up point and submitted their form |
FAILED_PICKUP |
The driver has failed to pick-up the item at the pick-up point |
FAILED |
The driver has failed to drop-off the item at the drop-off point |
RETURNED |
The order is returned to pick-up point |
Create Quotation
POST
Sandbox: https://rest.sandbox.lalamove.com/v3/quotations
Production: https://rest.lalamove.com/v3/quotations
> Body
{
"data": {
"scheduleAt": "2020-09-01T14:30:00.00Z",
"deliveryBy": "2020-09-01T17:30:00.00Z", // optional
"serviceType": "PLUS",
"stops": [<DeliveryStop>],
"item": { // optional
"quantity": "3",
"weight": "2.5",
"categories": ["FOOD_DELIVERY","OFFICE_ITEM"],
"handlingInstructions": ["KEEP_UPRIGHT"]
},
"deliveryStage": "LAST_MILE" // optional
}
}
Responses
201
Quotation Created
{
"data": {
"quotationId": "1514140994227007571",
"scheduleAt": "2022-04-13T07:18:38.00Z",
"deliveryBy": "2022-04-13T11:18:38.00Z",
"deliveryStage": "LAST_MILE",
"expiresAt": "2022-04-13T07:23:39.00Z",
"serviceType": "PLUS",
"stops": [
{
"stopId": "1514140995971838016",
"coordinates": {
"lat": "22.3354735",
"lng": "114.1761581"
},
"address": "Innocentre, 72 Tat Chee Ave, Kowloon Tong"
},
{
"stopId": "1514140995971838017",
"coordinates": {
"lat": "22.2812946",
"lng": "114.1598610"
},
"address": "Statue Square, Des Voeux Rd Central, Central"
}
],
"priceBreakdown": null,
"item": {
"weight": "2.5",
"categories": [
"OFFICE_ITEM",
"OTHERS"
]
},
"locationID": "HK_HKG"
}
}
422
Invalid market, getting a quotation from a market not supported
{ "message": "ERR_INVALID_MARKET" }
422
Invalid phone number, refer to Phone Validation
{ "message": "ERR_INVALID_PHONE_NUMBER" }
422
Out of service area
{ "message": "ERR_OUT_OF_SERVICE_AREA" }
422
Fail to reverse from address to location, providelat
andlng
{ "message": "ERR_REVERSE_GEOCODE_FAILURE" }
POST
/v3/quotations
Request a quotation.
Will return an object containing quotationId
, and stops
based on information provided. Note that price
is purposefully left blank for now since each client will have different pricing scheme.
Body
scheduleAt |
string |
Pick up time in UTC timezone and ISO 8601 format. Must be later than current time |
serviceType |
string |
Supports only PLUS (all capitalized) |
stops |
DeliveryStop[] |
Length 2 array of DeliveryStop |
Optional fields | ||
---|---|---|
deliveryBy |
string |
To-be-delivered time in UTC timezone and ISO 8601 format; Lalamove will add 4 hours to scheduleAt if no deliveryBy is passed. Must be at 1 hour later than scheduleAt time. |
deliveryStage |
string |
Default to LAST_MILE . Clients can configure it to FIRST_MILE if needed |
item |
Object |
Object of delivery item's information |
scheduleAt
You can schedule orders up to 30 days in advance.
Our API will interpret the
scheduleAt
time in UTC format (Coordinated Universal Time) only. Therefore please make sure you submit your requests factoring this in. Please see the example below.
You would like to place an order with a scheduleAt time of 2022-06-10 15:00, local time in Singapore. Singapore is UTC +8 timezone. Therefore your scheduleAt
time entry should be 2022-06-10T07:00:00.000Z
. Please find below your current timezone compared side-by-side with UTC.
Your Local Time | UTC Time |
---|---|
- ISO 8601 format
Delivery Stop
Delivery Stop
{
"coordinates": {
"lat": "22.3353139",
"lng": "114.1758402"
},
"address": "Jl. Perum Dasana"
}
coordinates.lat |
string |
Latitude |
coordinates.lng |
string |
Longitude |
address |
string |
Street address in plain text. |
Item Information
(Experimental) Information about the delivered item. This will help drivers deliver more reliably and efficiently.
Item Information
{
"item":{
"quantity":"12",
"weight":"2.5",
"categories":[
"FOOD_DELIVERY",
"OFFICE_ITEM"
],
"handlingInstructions":[
"KEEP_UPRIGHT",
"FRAGILE"
]
}
}
quantity |
string |
Number of items |
weight |
string |
Weight of items in kg |
categories |
Array |
Categories of the items |
handlingInstructions |
Array |
Handling instructions for items |
Place Order
POST
Sandbox: https://rest.sandbox.lalamove.com/v3/orders
Production: https://rest.lalamove.com/v3/orders
cURL --location --request POST 'https://rest.sandbox.lalamove.com/v3/orders' \
-H 'Content-Type: application/json' \
-H 'Authorization: hmac {API_KEY}:{timestamp}:{Signature}' \
-H 'Market: HK' \
-H 'Request-ID: cd8c5259-5719-4efc-8431-eecf02a66238' \
-H 'Platform: PLUS'
--data-raw '{"data"...}'
Body
{
"data": {
"quotationId": "1471722666401517645",
"sender": {
"stopId": "112345623",
"name": "Brian",
"phone": "11955555555",
"remarks": "Remark from the sender at pick-up" // optional
},
"recipients": [
{
"stopId": "112345678",
"name": "Guillermo",
"phone": "+660923447537",
"remarks": "Remark for recipient at drop-off" // optional
}
],
"clientRef": "PARCEL_TRACKING_NUMBER",
"metadata": { // optional
"interalID": "1234"
},
"partner": "Lalamove Plus Partner", // optional
"generateLabel": true // optional
}
}
Responses
201
Order Created
{
"data": {
"orderId": "107900701184",
"quotationId": "1471722666401517645",
"scheduleAt": "2022-05-31T08:26:27.000Z",
"deliveryBy": "2022-05-31T10:26:27.000Z",
"serviceType": "PLUS",
"driverId": "33522",
"shareLink": "https://plus-share.stage.lalamove.com/order/91237423232?=sg",
"status": "IN_PROGRESS",
"distance": {
"value": "16200",
"unit": "m"
},
"item": {...},
"clientRef": "PARCEL_TRACKING_NUMBER",
"priceBreakdown": null,
"stops": [
{
"coordinates": {
"lat": "22.3353139",
"lng": "114.1758402"
},
"address": "Jl. Perum Dasana",
"name": "dodo",
"phone": "+660923447537",
"remarks": "Remark from sender at pick-up" // TBC - where does this show up in BE
},
{
"stopId": "1231231231",
"coordinates": {
"lat": "22.3203648",
"lng": "114.169773"
},
"address": "Jl. Kartini, Ruko No. 1E",
"name": "dodo",
"phone": "+660923447537",
"remarks": "Remark for recipient at drop-off" // TBC
}
],
"deliveryLogs": [
{
"status": "AWAITS_DRIVER",
"updatedAt": "2022-06-21T07:55:47.000Z"
}
],
"metadata": {...}
}
}
generateLabel is true
{
"data": {
...
"label": {"url": null, "status": "GENERATING"}
}
}
OR
json { "data": { ... "label": { "url": "https://lalamove-app-resources.s3.ap-southeast-1.amazonaws.com/config/llmplus/stage/labelPDF_Order_b295f011-8dcc-41de-af30-895fde1cc55b_LAST_MILE_1662114519156.pdf?AWSAccessKeyId=AKIAYCL66G253N4CCJFF&Expires=1662200919&Signature=fqO1Fjj292D0flCRTQQxFHAroao%3D", "status": "GENERATED" }, } }
generateLabel is false
{
"data": {
...
"label": null
}
}
POST
/v3/orders
Place order based on the quotation provided. You must get a quotation first to submit the order.
Body
quotationId |
string |
quotationId from /quotations |
clientRef |
string |
This information is used to identify the delivered parcel. Must be unique. |
sender |
DeliveryDetails[] |
An array of DeliveryDetails , containing sender contact and instruction at pick-up |
recipients |
DeliveryDetails[] |
An array of DeliveryDetails , containing recipient contact and instruction at drop-off |
Optional Fields | ||
---|---|---|
partner |
string |
Specify Partner's name for effective tracking and organization. This field is only applicable for channel partners. Please contact partner.support@lalamove.com if you would like to request for your Partner ID |
metadata |
key-value pair |
An object with key-value pairs containing client-specific information |
generateLabel |
boolean |
When user wants to generateLabel set to true. default false |
DeliveryDetails
DeliveryDetails
{
"stopId": "11841184218725152",
"name": "Sachin",
"phone": "+6600000000",
"remarks": "ORDER#94\r\n1. Tshirt จำนวน 1\r\n2. Hoodie จำนวน 1\r\n"
}
Contact person, mobile phone number and remarks for each Delivery Stop for both pick-up and drop-off point
stopId |
number |
Identifier for each stop returned from Lalamove at quotations |
name |
string |
Name of the given stop's recipient |
phone |
string |
Phone number of the given stop's recipient, check out Phone Number Validation for exact validation logic. Must be a valid number with region code (ex: +65) |
Optional fields | ||
---|---|---|
remarks |
string |
Additional info about the delivery. eg. building, floor and flat. Use newline \r\n for better readability. Up to 1500 characters. |
Phone Validation
We accept E.164 standard format and use below regex rule as our core validation logic. We further validate by using Google's Lib Phone Number library.
Markets | Sample | Regex |
---|---|---|
All Markets | +85212345678 | ^\+[1-9]\d{1,14}$ |
Order Details
GET
Sandbox: https://rest.sandbox.lalamove.com/v3/orders/{orderId} OR https://rest.sandbox.lalamove.com/v3/orders/ref/[clientRef]
Production: https://rest.lalamove.com/v3/orders/{orderId} OR https://rest.lalamove.com/v3/orders/ref/[clientRef]
GET
/v3/orders/{orderId}
OR
GET
/v3/orders/ref/[clientRef]
Params
orderId |
<orderId> (returned by /v3/orders/ ) |
clientRef |
<clientRef> (provided when calling /v3/orders/ ) |
Responses
200
Same as the response of POST /orders
{
"data": {
"orderId": "107900701184",
...
"clientRef": "PARCEL_TRACKING_NUMBER",
...
"deliveryLogs": [
{
"status": "AWAITS_DRIVER",
"updatedAt": "2022-06-21T07:55:47.000Z"
},
{
"status": "AWAITS_PICKUP",
"updatedAt": "2022-06-21T08:30:47.000Z"
},
]
}
}
generateLabel is true
{
"data": {
...
"label": {"url": null , "status": "GENERATING"}
}
}
generateLabel is true
{
"data": {
...
"label": {"url": "https://test.com/llmplus/1_85212345678_2202_2H_220210180643.pdf", "status": "GENERATED" }
}
}
generateLabel is false
{
"data": {
...
"label": null
}
}
Delivery Logs
Note that each delivery status will be recorded and timestamped in the deliveryLogs
.
You can check the last status to get the current status of the delivery.
Edit Order
PATCH
Sandbox: https://rest.sandbox.lalamove.com/v3/orders/{orderId}
Production: https://rest.lalamove.com/v3/orders/{orderId}
> Body
{
"data": {
"scheduleAt": "2022-05-31T08:26:27.276Z",
"deliveryBy": "2022-05-31T15:26:27.276Z",
"stops": [
{
"coordinates": {
"lat": "22.3354735",
"lng": "114.1761581",
},
"address": "Innocentre, 72 Tat Chee Ave, Kowloon Tong",
"name": "Michal",
"phone": "+85238485765",
"remarks": "please call when you have arrived"
},
{
"coordinates": {
"lat": "22.26308035863828",
"lng": "114.13081794602759",
},
"address": "Telegraph Bay, Cyberport Rd, 薄扶林 Cyberport 1",
"name": "Michal",
"phone": "+85212345679",
"remarks": "please leave the package on the porch"
},
],
"item": {...}, // optional
"metadata": {...}, // optional
},
};
Responses
201
Created
> Response
{
"id": "1",
"quotationId": "1471722666401517645",
"clientId": "ACME",
"deliveryStage": "LAST_MILE",
"clientRef": "TEST_01",
"label": {
"url": null,
"status": "GENERATING",
},
"address": [
{
"stopId": "8322222650735159331",
"text": "InnoCentre, 72 Tat Chee Avenue",
"contacts": [
{
"name": "test",
"phone": "+85212345678"
}
],
"remarks": "test"
},
{
"stopId": "8322222650735159331",
"text": "InnoCentre, 72 Tat Chee Avenue",
"contacts": [
{
"name": "test",
"phone": "+85212345678"
}
],
"remarks": "test"
}
],
"extras": [
{}
],
"locationId": "HK_HKG",
"parcelNum": 1,
"totalWeight": 1,
"notes": [
{
"categories": [
"test"
],
"handlingInstructions": [
"test"
],
"weight": "LESS_THAN_3_KG"
}
],
"pickupAt": "2021-09-10T04:40:51.000Z",
"deliveryBy": "2021-09-11T03:40:51.000Z",
"createdAt": "2021-09-10T03:40:51.000Z",
"updatedAt": "2021-09-10T03:40:51.000Z",
"status": "IN_PROGRESS",
"attributes": {},
"pickupDistrict": "Unknown District",
"deliveryDistrict": "Unknown District",
"pickupCoordinate": "22.3216654,114.1617644",
"deliveryCoordinate": "22.3216654,114.1617644",
"distance": "100",
"isCancelled": false,
"changeLogs": [],
"users": [],
"tags": [],
"shareLink": "",
"userIds": [],
"deliveries": {
"createdAt": "2021-09-10T03:40:51.000Z",
"updatedAt": "2021-09-10T03:40:51.000Z",
"pickupAt": "2021-09-10T04:40:51.000Z",
"deliveryBy": "2021-09-11T03:40:51.000Z",
"id": "1",
"clientId": "ACME",
"hasSla": true,
"isFlagged": false,
"orderId": "1",
"meta": {
"barcodeFormats": [],
"frames": []
},
"orderRef": "TEST_01",
"parcelRef": "TEST_01",
"formSubmissions": [
{}
]
}
}
generateLabel is true
{
"data": {
...
"label": {"url": null, "status": "GENERATING" }
}
}
generateLabel is false
{
"data": {
...
"label": null
}
}
PATCH
/v3/orders/{orderId}
Update the order information (scheduleAt
, deliveryBy
, stops
, item
, and metadata
) during the IN_PROGRESS
status.
No update will be allowed if the order is CANCELED
, DELIVERED
, CLOSED
.
URL Params
scheduleAt |
(New) pick up time in UTC timezone and ISO 8601 format. Must be later than current time. |
deliveryBy |
(New) To-be-delivered time in UTC timezone and ISO 8601 format. Must be later than current time and more than 1 hour from the scheduleAt |
stops |
DeliveryStop[] |
Optional fields | ||
---|---|---|
metadata |
string |
Object of key-value pairs that clients can use to attach to each order |
item |
Object |
Object of delivery item's information |
Note that if optional fields are not passed, existing metadata
and item
will persist
Cancel Order
DELETE
https://rest.lalamove.com/v3/orders/{orderId}
Responses
204
409
Cancellation Forbidden
{ "message": "ERR_CANCELLATION_FORBIDDEN" }
DELETE
/v3/orders/{orderId}
Cancellation will only be allowed if the order is in IN_PROGRESS
URL Params
orderId |
<LALAMOVE_ORDER_ID> |
Tutorial
To help you kick-start, you can check out the attached POSTMAN collection.
Postman Configurations
POSTMAN Environment | POSTMAN Collection |
---|---|
Environment | Collection |
Support
Drop us an email at partner.support@lalamove.com with your questions.