Ninja Van Tariff API
Estimate the shipping price for a parcel between an origin and destination (POST /{countryCode}/1.0/public/price), given weight and dimensions.
Estimate the shipping price for a parcel between an origin and destination (POST /{countryCode}/1.0/public/price), given weight and dimensions.
openapi: 3.0.3
info:
title: Ninja Van API (ninjaAPI)
description: >-
ninjaAPI is Ninja Van's REST API for integrating last-mile logistics across
Southeast Asia (Singapore, Malaysia, Indonesia, Philippines, Vietnam,
Thailand). Merchants create and cancel delivery orders, generate waybills
(AWB), estimate tariffs, look up Ninja Point (PUDO) locations, and pull
tracking events; Ninja Van pushes order status changes back to merchants via
webhooks. Every request is country-scoped - the country code is the first
path segment (for example /SG/, /MY/, /ID/) - and authenticated with an
OAuth2 client-credentials bearer token. Production access is granted per
merchant after an integration audit; the sandbox only supports the Singapore
(sg) country code.
Paths, methods, and versions in this document are grounded in Ninja Van's
published OpenAPI specification (v4.1.0). Request/response schemas are
modeled from the documentation and are simplified; verify exact field lists
against the live API reference before production use.
version: '4.1.0'
contact:
name: Ninja Van Developer Support
url: https://api-docs.ninjavan.co/
servers:
- url: https://api.ninjavan.co/{countryCode}
description: Production (countryCode is one of sg, my, id, ph, vn, th)
variables:
countryCode:
default: sg
enum:
- sg
- my
- id
- ph
- vn
- th
- url: https://api-sandbox.ninjavan.co/{countryCode}
description: Sandbox (only the sg country code is supported)
variables:
countryCode:
default: sg
enum:
- sg
security:
- bearerAuth: []
tags:
- name: OAuth API
description: OAuth2 client-credentials token issuance.
- name: Order API
description: Create and cancel delivery orders and generate waybills.
- name: Tracking API
description: Pull tracking events for parcels.
- name: Tariff API
description: Estimate shipping price.
- name: PUDO API
description: Ninja Point pick-up / drop-off locations and shipper drop-off.
paths:
/2.0/oauth/access_token:
post:
operationId: requestAccessToken
tags:
- OAuth API
summary: Request access token
description: >-
Exchanges a client ID and client secret for a short-lived OAuth2 access
token using the client-credentials grant. Attach the returned token as a
Bearer token on all subsequent requests.
security: []
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/AccessTokenRequest'
responses:
'200':
description: An access token.
content:
application/json:
schema:
$ref: '#/components/schemas/AccessTokenResponse'
'401':
$ref: '#/components/responses/Unauthorized'
/4.2/orders:
post:
operationId: createOrderV42
tags:
- Order API
summary: Create delivery order (v4.2)
description: >-
Creates a delivery order. Version 4.2 of the create-order endpoint. The
request describes the service, the pickup (from) and delivery (to)
parties, and the parcel job (dimensions, delivery instructions, cash on
delivery, delivery timeframe).
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/OrderInput'
responses:
'200':
description: The created order, including the assigned tracking number.
content:
application/json:
schema:
$ref: '#/components/schemas/Order'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
/4.1/orders:
post:
operationId: createOrderV41
tags:
- Order API
summary: Create delivery order (v4.1)
description: >-
Creates a delivery order using version 4.1 of the create-order endpoint.
Retained alongside 4.2 for existing integrations.
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/OrderInput'
responses:
'200':
description: The created order, including the assigned tracking number.
content:
application/json:
schema:
$ref: '#/components/schemas/Order'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
/2.2/orders/{trackingNo}:
delete:
operationId: cancelOrder
tags:
- Order API
summary: Cancel order
description: Cancels an order that has not yet been picked up, by its tracking number.
parameters:
- name: trackingNo
in: path
required: true
description: The tracking number of the order to cancel.
schema:
type: string
responses:
'200':
description: Cancellation result.
content:
application/json:
schema:
$ref: '#/components/schemas/CancelResponse'
'401':
$ref: '#/components/responses/Unauthorized'
'404':
$ref: '#/components/responses/NotFound'
/2.0/reports/waybill:
get:
operationId: generateWaybill
tags:
- Order API
summary: Generate waybill
description: >-
Generates a waybill (air waybill / shipping label) PDF for one or more
tracking numbers. Access to this endpoint must be granted by Ninja Van
before use.
parameters:
- name: tid
in: query
required: true
description: One or more tracking numbers to include on the waybill.
schema:
type: string
- name: hide_shipper_details
in: query
required: false
description: Whether to hide the shipper's details on the waybill.
schema:
type: boolean
- name: orientation
in: query
required: false
description: Waybill orientation.
schema:
type: string
enum:
- portrait
- landscape
responses:
'200':
description: A waybill document.
content:
application/pdf:
schema:
type: string
format: binary
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
/2.0/reports/international-waybills:
get:
operationId: generateInternationalWaybill
tags:
- Order API
summary: Generate international waybill
description: Generates an international waybill document for cross-border parcels.
parameters:
- name: tid
in: query
required: true
description: One or more tracking numbers to include on the waybill.
schema:
type: string
responses:
'200':
description: An international waybill document.
content:
application/pdf:
schema:
type: string
format: binary
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
/1.0/public/price:
post:
operationId: getPriceEstimate
tags:
- Tariff API
summary: Get price estimate
description: >-
Returns an estimated shipping price for a parcel between an origin and a
destination, based on weight and dimensions.
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/PriceEstimateInput'
responses:
'200':
description: A price estimate.
content:
application/json:
schema:
$ref: '#/components/schemas/PriceEstimate'
'400':
$ref: '#/components/responses/BadRequest'
/2.0/pudos:
get:
operationId: listNinjaPoints
tags:
- PUDO API
summary: List Ninja Points (PUDO locations)
description: >-
Lists Ninja Point pick-up / drop-off (PUDO) locations and their
capabilities (customer collection, shipper send, returns, and so on).
parameters:
- name: can_customer_collect
in: query
required: false
schema:
type: boolean
- name: allow_shipper_send
in: query
required: false
schema:
type: boolean
- name: allow_customer_return
in: query
required: false
schema:
type: boolean
responses:
'200':
description: A list of Ninja Point locations.
content:
application/json:
schema:
type: object
properties:
data:
type: array
items:
$ref: '#/components/schemas/PudoLocation'
'401':
$ref: '#/components/responses/Unauthorized'
/1.0/send-orders/drop-off:
post:
operationId: triggerShipperDropOff
tags:
- PUDO API
summary: Trigger shipper drop-off for parcel
description: Triggers the shipper drop-off flow for a parcel at a Ninja Point.
requestBody:
required: true
content:
application/json:
schema:
type: object
additionalProperties: true
responses:
'200':
description: Drop-off acknowledgement.
content:
application/json:
schema:
type: object
additionalProperties: true
'401':
$ref: '#/components/responses/Unauthorized'
/1.0/send-orders/{trackingId}:
get:
operationId: scanParcelForDropOff
tags:
- PUDO API
summary: Scan parcel for shipper drop-off
description: Scans a parcel by tracking ID as part of the shipper drop-off flow.
parameters:
- name: trackingId
in: path
required: true
schema:
type: string
responses:
'200':
description: Scan result.
content:
application/json:
schema:
type: object
additionalProperties: true
'401':
$ref: '#/components/responses/Unauthorized'
'404':
$ref: '#/components/responses/NotFound'
/1.0/orders/tracking-events/{trackingNumber}:
get:
operationId: getTrackingEventsForParcel
tags:
- Tracking API
summary: Get events for single parcel
description: Returns the tracking events recorded for a single parcel.
parameters:
- name: trackingNumber
in: path
required: true
schema:
type: string
responses:
'200':
description: Tracking events for the parcel.
content:
application/json:
schema:
type: object
properties:
data:
type: array
items:
$ref: '#/components/schemas/TrackingEvent'
'401':
$ref: '#/components/responses/Unauthorized'
'404':
$ref: '#/components/responses/NotFound'
/1.0/orders/tracking-events:
get:
operationId: getTrackingEventsForParcels
tags:
- Tracking API
summary: Get events for list of parcels
description: Returns tracking events for a list of parcels.
parameters:
- name: tracking_number
in: query
required: true
description: Comma-separated or repeated tracking numbers.
schema:
type: string
responses:
'200':
description: Tracking events for the requested parcels.
content:
application/json:
schema:
type: object
properties:
data:
type: array
items:
$ref: '#/components/schemas/TrackingEvent'
'401':
$ref: '#/components/responses/Unauthorized'
components:
securitySchemes:
bearerAuth:
type: http
scheme: bearer
description: >-
OAuth2 client-credentials access token obtained from POST
/{countryCode}/2.0/oauth/access_token, passed as
`Authorization: Bearer ACCESS_TOKEN`.
responses:
BadRequest:
description: The request was malformed or failed validation.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
Unauthorized:
description: Missing or invalid access token.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
Forbidden:
description: >-
The caller lacks permission - wrong environment/country code, integration
audit not passed, waybill access not granted, or a frozen account.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
NotFound:
description: The requested resource was not found.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
schemas:
Error:
type: object
properties:
error:
type: object
properties:
title:
type: string
message:
type: string
details:
type: object
additionalProperties: true
AccessTokenRequest:
type: object
required:
- client_id
- client_secret
- grant_type
properties:
client_id:
type: string
client_secret:
type: string
grant_type:
type: string
enum:
- client_credentials
default: client_credentials
AccessTokenResponse:
type: object
properties:
access_token:
type: string
token_type:
type: string
example: bearer
expires:
type: integer
description: Expiry as a Unix timestamp.
expires_in:
type: integer
description: Lifetime of the token in seconds.
Contact:
type: object
description: A pickup or delivery party.
properties:
name:
type: string
phone_number:
type: string
email:
type: string
address:
type: object
properties:
address1:
type: string
address2:
type: string
area:
type: string
city:
type: string
state:
type: string
address_type:
type: string
country:
type: string
postcode:
type: string
ParcelJob:
type: object
description: Details of the parcel and how it should be handled.
properties:
is_pickup_required:
type: boolean
pickup_service_type:
type: string
pickup_date:
type: string
format: date
delivery_start_date:
type: string
format: date
delivery_timeslot:
type: object
additionalProperties: true
dimensions:
type: object
properties:
weight:
type: number
length:
type: number
width:
type: number
height:
type: number
cash_on_delivery:
type: number
allow_weekend_delivery:
type: boolean
OrderInput:
type: object
required:
- service_type
- from
- to
- parcel_job
properties:
service_type:
type: string
description: For example Parcel.
service_level:
type: string
description: For example Standard.
requested_tracking_number:
type: string
reference:
type: object
properties:
merchant_order_number:
type: string
from:
$ref: '#/components/schemas/Contact'
to:
$ref: '#/components/schemas/Contact'
parcel_job:
$ref: '#/components/schemas/ParcelJob'
marketplace:
type: object
additionalProperties: true
Order:
allOf:
- $ref: '#/components/schemas/OrderInput'
- type: object
properties:
tracking_number:
type: string
status:
type: string
created_at:
type: string
format: date-time
CancelResponse:
type: object
properties:
tracking_number:
type: string
status:
type: string
PriceEstimateInput:
type: object
properties:
service_type:
type: string
service_level:
type: string
from:
$ref: '#/components/schemas/Contact'
to:
$ref: '#/components/schemas/Contact'
weight:
type: number
dimensions:
type: object
properties:
length:
type: number
width:
type: number
height:
type: number
PriceEstimate:
type: object
properties:
currency:
type: string
price:
type: number
breakdown:
type: object
additionalProperties: true
PudoLocation:
type: object
properties:
id:
type: string
name:
type: string
address:
type: string
latitude:
type: number
longitude:
type: number
can_customer_collect:
type: boolean
allow_shipper_send:
type: boolean
TrackingEvent:
type: object
properties:
tracking_number:
type: string
status:
type: string
timestamp:
type: string
format: date-time
description:
type: string