pandago-API-version-1.1.0-1

Download as pdf or txt
Download as pdf or txt
You are on page 1of 22

pandago API

version 1.1.0

Introduction
The pandago API provides system-to-system integration to facilitate on-demand courier delivery
service requests. Each integration is scoped as a specific Brand using a ClientID. Each delivery
request will be called an Order.

Client
Client represents a single integration for a specific Brand. Client information will include the
following:
● Customer known name of the Brand/Branch
● Address of the Brand/Branch that includes Latitude and Longitude.

A Client would typically represent a logistical system that manages a Brand with a few branch
locations. This system will usually manage or will need an order allocation to distribute order to
its branches. The pandago API supports dynamic pick-up location that allows orders to be
picked up from any branch location.

Integration Step(s)
1. Register a Client as a Brand with pandago.
2. Register all Branches/Outlets which relates to the Brand.
3. Use
Note: Accuracy of branch’s latitude and longitude is important for the branch matching process
the same ClientID when submitting orders from any branch within the registered Brand.

Ordering Step(s)
1. The Sender address must be specified when submitting an Order.
The Sender latitude and longitude will be used to find the matching Branch/Outlet with a
tight tolerance.
Note: system will reject the order when it fails to find the matching Branch/Outlet latitude and longitude.

Order
Order is the principal object that encompasses the package delivery process from the start to
the end. Once a new order is submitted, pandago will respond with the order details and will
start looking for an available courier. OrderID should be used to get updates on the order
status.
Status Updates
Order status updates can be obtained from the following method:
1. Push method
A Callback URL can be provided as part of the Client information. This will allow the
pandago API to push status updates to the Callback URL.
2. Pull method
A Get Order endpoint can be pulled periodically to get the latest status.

Available Statuses
Status Description

NEW Order has been created

RECEIVED We've accepted the order and will be assigning it to a courier

WAITING_FOR_TRANSPORT Assigning order to a courier

ASSIGNED_TO_TRANSPORT Courier has accepted to pick up and deliver the order

NEAR_VENDOR Courier is near the pick-up point

PICKED_UP Courier has picked up the order

COURIER_LEFT_VENDOR Courier has left from pick-up point

NEAR_CUSTOMER Courier is near the drop-off point

DELIVERED Courier has delivered the order

DELAYED Order delivery has been delayed and estimated delivery time has
been updated

CANCELLED Order has been cancelled

Note: This is not an exhaustive list of all the available statuses

Supported Payment Methods


Payment Method Description

PAID Order has been fully paid already and courier will not collect any
amount from the end customer

CASH_ON_DELIVERY Courier will collect payment (order amount) from the end customer
upon delivery

*For the billing of the pandago delivery fee, this will be settled separately according to the
agreed billing schedule and process

Getting Started
These are the steps to start using the pandago API:
1. Generate Key Pair (Private Key and Public Key) to support secure communication with
the pandago API.
Follow these commands on a terminal:
# Generate private key
# output: client.pem file
openssl genrsa -out client.pem 2048

# Generate public key from the generated private one


# input: client.pem file
# output: client.pub file
openssl rsa -in client.pem -pubout > client.pub
Or, follow these steps:
a. Open a browser and access this Online RSA Generator
(https://cryptotools.net/rsagen)
b. Select key length to 2048 bit, and click the Generate Key Pair button. c. Copy
and save the Private Key to a file with .pem extension (e.g. client.pem). d. Copy
and save the Public Key to a file with .pub extension (e.g. client.pub).
2. Contact a pandago representative stating your interest in using the pandago API and
provide the following information:
a. Public Key (file: client.pub)
b. Brand or Branch details:
Attribute Description Example

Name Customer known name for your Brand or Branch Store ABC

Address Address of your Brand or Branch.


12 Street 3 unit #4-56
This address will be used as default sender.

Latitude Latitude of the Address 1.2867416

Longitude Longitude of the Address 103.8523024

Callback URL [OPTIONAL]


https://example.io/update
The Callback URL for pushing Order statuses must
be an HTTPS with valid SSL certificate.
See: Order Status Callback

3. The pandago representative will provide you with ClientID, KeyID and Scope that your
service will need to generate an Access Token for thepandago API.
Attribute Example Description

ClientID pandago:sg:00000000-0000-0000-0000-000000000000 Your service identifier

KeyID 00000000-0000-0000-0000-000000000001 Your public key identifier

Scope pandago.api.sg.* Access scope of your service

Authentication
All pandago API endpoints support OAuth 2.0 authentication protocol.
Your service will need to generate an Access Token using your service Private Key, ClientID,
KeyID and Scope from the pandago Authenticator.

Host

Sandbox environment

https://sts-asia-st.deliveryhero.io

Live Production environment

https://sts-asia.deliveryhero.io

Method and Path

POST oauth2/token

Request

Header

Content-Type: application/x-www-form-urlencoded

Body
There are 2 steps to generate the body.
1. Generate assertion as a signed token in Javascript Web Token (JWT) format.
This is the payload structure of the token:
{
"alg":"RS256",
"typ":"JWT",
"kid": "{{KeyID}}"
}
.
{
"iss":"{{ClientID}}",
"sub":"{{ClientID}}",
"jti":"{{random uuid}}",
"exp":{{unix timestamp in the future}},
"aud":"https://sts.deliveryhero.io"
}
And use the Private Key to sign the token.
2. Construct the following body

grant_type=client_credentials;
client_id={{ClientID}};
client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer;
client_assertion={{SignedJWT}};
scope={{Scope}};

Example

curl --location --request POST 'https://sts-asia-st.deliveryhero.io/oauth2/token' \


--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'grant_type=client_credentials' \
--data-urlencode 'client_id={{ClientID}}' \
--data-urlencode 'client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer' \
--data-urlencode 'client_assertion={{SignedJWT}}' \
--data-urlencode 'scope={{Scope}}'

Response

Header

Content-Type: application/json

Body
Attribute Type Required Description

access_token string yes access token to be used as authorizer header

expires_in string yes length of token validity in seconds

Example:
{
“access_token”:”{{AccessToken}}”,
“expires_in”:”{{expirity in seconds}}”
}
Orders

Host and Base Path


Sandbox environment of pandago API is published in this domain with /sg/ base path:
https://pandago-api-sandbox.deliveryhero.io/sg/

Features

Estimate Fee for an Order

Method and Path

POST /api/v1/orders/fee

Request

Header

Content-Type: application/json
Authorization: Bearer {{AccessToken}}

Body
See Submit New Order > Request > Body

Response

Success
This is the expected response upon successful estimation of the order’s fee.

Header

Status: HTTP 200 (OK)


Content-Type: application/json

Body
Attribute Type Required Description

client_order_id string no Your system reference id for this order (default: empty)

estimated_delivery_fee float yes pandago delivery fee for this order


Example:
{
“client_order_id”: ”client-ref-000001”,
“estimated_delivery_fee”:8.17
}

Invalid Payload
This error response covers any invalid formatting of the request payload and the issue will be
described in the response message.

Header

Status: HTTP 400 (Bad Request)


Content-Type: application/json

Body
Attribute Type Required Description

message string yes explanation of the error(s)

Example
{
“message”: “Invalid request payload\n - recipient.phone_number is required”
}

Unable to Process Request


This error response covers any semantic issues from the request payload.
For example:
● Coordinates are outside the deliverable area/radius.
● Unable to find branch based on sender coordinates.

Header

Status: HTTP 422 (Unprocessable Entity)


Content-Type: application/json

Body
Attribute Type Required Description

message string yes explanation of the error(s)

Example
{
“message”: “No Branch found that is close enough to the given sender coordinates”
}

Server Error
This error response covers any internal issues which prevent the service to estimate the order’s
fee.

Header

Status: HTTP 500 (Internal Server Error)


Content-Type: application/json

Body
Attribute Type Required Description

message string yes explanation of the error(s)

Example
{
“message”: “Unable to proceed, something went wrong”
}

Estimate Time for an Order

Method and Path

POST /api/v1/orders/time

Request

Header

Content-Type: application/json
Authorization: Bearer {{AccessToken}}

Body
See Submit New Order > Request > Body

Response

Success
This is the expected response upon successful estimation of the order’s time.
Header

Status: HTTP 200 (OK)


Content-Type: application/json

Body
Attribute Type Required Description

client_order_id string no Your system reference id for this order (default: empty)

estimated_pickup_time string no Estimated pick-up time in ISO Datetime (default: blank)

estimated_delivery_time string no Estimated delivery time in ISO Datetime (default: blank)

Example:
{
“client_order_id”: ”client-ref-000001”,
“estimated_pickup_time”:“2018-09-13T01:30:52.123Z”,
“estimated_delivery_time”:“2018-09-13T01:45:52.123Z”
}

Invalid Payload
This error response covers any invalid formatting of the request payload and the issue will be
described in the response message.

Header

Status: HTTP 400 (Bad Request)


Content-Type: application/json

Body
Attribute Type Required Description

message string yes explanation of the error(s)

Example
{
“message”: “Invalid request payload\n - recipient.phone_number is required”
}

Unable to Process Request


This error response covers any semantic issues from the request payload.
For example:
● Coordinates are outside the deliverable area/radius.
● Unable to find branch based on sender coordinates.
Header

Status: HTTP 422 (Unprocessable Entity)


Content-Type: application/json

Body
Attribute Type Required Description

message string yes explanation of the error(s)

Example
{
“message”: “No Branch found that is close enough to the given sender coordinates”

Server Error

This error response covers any internal issues which prevent the service from estimating the
order’s time.

Header

Status: HTTP 500 (Internal Server Error)


Content-Type: application/json

Body
Attribute Type Required Description

message string yes explanation of the error(s)

Example
{
“message”: “Unable to proceed, something went wrong”
}

Submit New Order

Method and Path


POST /api/v1/orders

Request

Header

Content-Type: application/json
Authorization: Bearer {{AccessToken}}

Body
Attribute Type Required Description

client_order_id string no Your system reference id for this order (default: empty)

sender object yes Contact and location of sender

sender.name string yes Name of sender

sender.phone_number string yes Phone number of sender following ITU-T E.164 standard

sender.location object yes Location of sender

sender.location.address string yes Full address of sender

sender.location.latitude float yes Latitude of sender location

sender.location.longitude float yes Longitude of sender location

sender.location.notes string no Notes relevant for rider for pick-up (default: blank)

recipient object yes Contact and location of recipient

recipient.name string yes Name of recipient

recipient.phone_number string yes Phone number of recipient following ITU-T E.164


standard

recipient.location object yes Location of recipient

recipient.location.address string yes Full address of recipient

recipient.location.latitude float yes Latitude of recipient location

recipient.location.longitude float yes Longitude of recipient location


recipient.location.not string no Notes relevant for rider for drop-off (default: blank) yes

es payment_method string See: Supported Payment Methods

coldbag_needed boolean no State if Coldbag is needed (default: false)

amount float required


Sum of all item(s) amount in the order (default: 0.0).
when COD
This attribute is required when payment_method is
CASH_ON_DELIVERY

description string(255) yes Describe all item(s) in the order that will be used for
verification (max of 255 characters)

Example:
{
“sender”: {
“name”:”pandago”,
“phone_number”:”+650000000”,
“location”: {
“address”:”1 2nd Street #08-01”,
“latitude”:1.2923742,
“longitude”:103.8486029,
“notes”: “use the left side door”,
}
},
“recipient”: {
“name”:”Merlion”,
“phone_number”:”+650000000”,
“location”: {
“address”:”20 Esplanade Drive”,
“latitude”:1.2857488,
“longitude”:103.8548608,
“notes”: “use lift A and leave at the front door”,
}
},

“amount”: 23.50,
“payment_method”:”PAID”,
}

Response(s)

Success
This is the expected response upon successful creation of the order.

Header

Status: HTTP 201 (Created)


Content-Type: application/json
Body
Attribute Type Required Description

order_id string yes pandago reference number for this order

client_order_id string no Your system reference id for this order (default: empty)

sender object yes Contact and location of sender

sender.name string yes Name of sender

sender.phone_number string yes Phone number of sender following ITU-T E.164 standard

sender.location object yes Location of sender

sender.location.address string yes Full address of sender

sender.location.latitude float yes Latitude of sender location

sender.location.longitude float yes Longitude of sender location

sender.location.notes string no Notes relevant for rider for pick-up (default: blank)

recipient object yes Contact and location of recipient

recipient.name string yes Name of recipient

recipient.phone_number string yes Phone number of recipient following ITU-T E.164


standard

recipient.location object yes Location of recipient

recipient.location.address string yes Full address of recipient

recipient.location.latitude float yes Latitude of recipient location

recipient.location.longitude float yes Longitude of recipient location

recipient.location.notes string no Notes relevant for rider for drop-off (default: blank)

payment_method string yes See Supported Payment Method

coldbag_needed boole no State if Coldbag is needed (default: false)


an

amount float no Price of the order that customer paid (default: 0.0)

description string( no Any relevant description about the order (max of 255
255) characters) (default: blank)

status string yes See Status Types

delivery_fee float yes pandago delivery fee for this order


timeline object yes Time estimation for Pick-Up and Delivery

timeline.estimated_pickup_time string no Estimated pick-up time in ISO Datetime (default: blank)

timeline.estimated_delivery_ti string no Estimated delivery time in ISO Datetime (default: blank) yes

me driver object Assigned driver detail to this order

driver.id string no Driver’s id (default: blank)

driver.name string no Driver’s name (default: blank)

driver.phone_number string no Driver’s phone number (default: blank)

created_at int yes Created time in UNIX timestamp updated_at int yes Updated time in

UNIX timestamp

Example:
{
“order_id”:“y0ud-000001”,
“client_order_id”: “client-ref-000001”,
“recipient”: {
“name”:”Merlion”,
“phone_number”:”+650000000”,
“location”: {
“Address”:”20 1st Street #08-01”,
“latitude”:1.2857488,
“longitude”:103.8548608,
“notes”:”place the item on the footstool”
}
},
“payment_method”:”PAID”,
“coldbag_needed”:false,
“amount”:10.2,
“description”:”new decoration for Merlion’s footstool”
“status”:”NEW”,
“delivery_fee”:8.17,
“timeline”: {
“estimated_pickup_time”:“”,
“estimated_delivery_time”:“”,
},
“driver”: {
“id”:””,
“created_at”:1536802000, “updated_at”:1536802000 }

Invalid Payload

“name”:””,
“phone_number”:””
},
This error response covers any invalid formatting of the request payload and the issue will be
described in the response message.

Header

Status: HTTP 400 (Bad Request)


Content-Type: application/json

Body
Attribute Type Required Description

message string yes explanation of the error(s)

Example
{
“message”: “Invalid request payload\n - recipient.phone_number is required”
}

Unable to Process Request


This error response covers any semantic issues from the request payload.
For example:
● Coordinates are outside the deliverable area/radius.
● Unable to find branch based on sender coordinates.

Header

Status: HTTP 422 (Unprocessable Entity)


Content-Type: application/json

Body
Attribute Type Required Description

message string yes explanation of the error(s)

Example
{
“message”: “No Branch found that is close enough to the given sender coordinates”
}

Server Error

This error response covers any internal issues which prevent the service to process the order
creation.

Header

Status: HTTP 500 (Internal Server Error)


Content-Type: application/json

Body
Attribute Type Required Description

message string yes explanation of the error(s)

Example
{
“message”: “Unable to proceed, something went wrong”
}

Get Specific Order

Method and Path

GET /api/v1/orders/{{OrderID}}

Request

Header

Content-Type: application/json
Authorization: Bearer {{AccessToken}}

Response

Success
This is the expected response upon successful read of the order details.

Header

Status: HTTP 200 (OK)


Content-Type: application/json

Body
See Submit New Order > Response > Body

Not Found
This response represents when the desired order does not exist.

Header

Status: HTTP 404 (Not Found)


Content-Type: application/json

Body
Attribute Type Required Description

message string yes explanation of the error(s)

Example
{
“message”: “Order not found”
}

Server Error
This error response covers any internal issues which prevent the service to read the order
details.

Header

Status: HTTP 500 (Internal Server Error)


Content-Type: application/json

Body
Attribute Type Required Description

message string yes explanation of the error(s)

Example
{
“message”: “Unable to proceed, something went wrong”
}

Get Specific Order Current Location Coordinates


Method and Path

GET /api/v1/orders/{{OrderID}}/coordinates

Request

Header

Content-Type: application/json
Authorization: Bearer {{AccessToken}}

Response

Success
This is the expected response upon successful read of the order’s coordinates.

Header

Status: HTTP 200 (OK)


Content-Type: application/json

Body
Attribute Type Required Description

client_order_id string no Your system reference id for this order (default: empty)

latitude float yes Latitude of driver location

longitude float yes Longitude of driver location

updated_at int no Updated time in UNIX timestamp

Example:
{
“client_order_id”: “client-ref-000001”,
“latitude”:1.2857488,
“longitude”:103.8548608,
“updated_at”:1536802252
}

Not Found
This response represents when the desired order does not exist.

Header

Status: HTTP 404 (Not Found)


Content-Type: application/json

Body
Attribute Type Required Description

message string yes explanation of the error(s)

Example
{
“message”: “Order not found”
}

Server Error
This error response covers any internal issues which prevent the service to read the order
details.

Header

Status: HTTP 500 (Internal Server Error)


Content-Type: application/json

Body
Attribute Type Required Description

message string yes explanation of the error(s)

Example
{
“message”: “Unable to proceed, something went wrong”
}

Cancel Specific Order


An order can only be canceled when it has not been assigned to a courier.

Method and Path

DELETE /api/v1/orders/{{OrderID}}

Request

Header
Content-Type: application/json
Authorization: Bearer {{AccessToken}}

Body
Attribute Type Required Description

reason string yes Reason of cancellation

Example:
{
“reason”:”customer cancel the order”
}

Response

Success
This is the expected response upon successful order cancellation.

Header

Status: HTTP 204 (No Content)


Content-Type: application/json

Body

-No Content

Uncancellable
This response represents that the desired order is no longer cancellable.

Header

Status: HTTP 409 (Conflict)


Content-Type: application/json

Body
Attribute Type Required Description

message string yes explanation of the error(s)

Example
{
“message”: “Order is not cancellable”
}

Not Found
This response represents when the desired order does not exist.

Header

Status: HTTP 404 (Not Found)


Content-Type: application/json

Body
Attribute Type Required Description

message string yes explanation of the error(s)

Example
{
“message”: “Order not found”
}

Server Error
This error response covers any internal issues which prevent the service to cancel the order.

Header

Status: HTTP 500 (Internal Server Error)


Content-Type: application/json

Body
Attribute Type Required Description

message string yes explanation of the error(s)

Example
{
“message”: “Unable to proceed, something went wrong”
}

Order Status Callback


The Callback URL will need to be HTTPS with a valid SSL certificate.
Body posted by this feature is stripped of any Personally Identifiable Information
(PII). Full Order body can be fetched using the Get Specific Order feature.

Method and Path

POST {{your callback URL}}

Request

Header

Content-Type: application/json

Body
Attribute Type Required Description

order_id string yes pandago reference number for this order

client_order_id string no Your system reference id for this order (default: empty)

status string yes See Status Types

timeline object yes Time estimation for Pick-Up and Delivery

timeline.estimated_pickup_time string no Estimated pick-up time in ISO Datetime (default: blank)

timeline.estimated_delivery_tim string no Estimated delivery time in ISO Datetime (default: blank)


e

driver object yes Assigned courier detail to this order

driver.id string no Courier’s id (default: blank)

created_at int yes Created time in UNIX timestamp

updated_at int yes Updated time in UNIX timestamp

Example:
{
“order_id”:“y0ud-000001”,
“client_order_id”: “client-ref-000001”,
“status”:”PICKED_UP”,
“timeline”: {
“estimated_pickup_time”:“2018-09-13T01:30:52.123Z”,
“estimated_delivery_time”:“2018-09-13T01:45:52.123Z”,
},
“driver”: {
“id”:”12324”,
},
“created_at”:1536802000,
“updated_at”:1536802252
}

You might also like