· 5 years ago · Jun 03, 2020, 02:02 PM
1{
2 "swagger": "2.0",
3 "info": {
4 "description": "Delivery order API is a RESTful API that caters for creation of `order` resource and also actions like calculation of delivery order price.\n\nFor your convenience, other common API endpoints are also documented here.\n#### Sample Requests\nFor a list of sample requests, do take a look at our document [here](https://drive.google.com/open?id=1mvxVf1FsjIRfflxLrEIOVc9-IN8GxA3i).\n\n#### Important Integration Requirement\nPlease take note of the following points:\n* We require shippers to cache the authorization access tokens for their API integration.\n* Shippers are encouraged to retry order creation requests IF a ***HTTP 5xx*** error is returned from our API.\n* If a ***HTTP 4xx*** error is returned, please log the response for your debugging purposes.\n * ***DO NOT*** retry the same order creation request without fixing the error specified in the response.\n\n* If access to waybill generation API is required, please take note that access to the API is conditional.\n * Shipper ***must*** cache waybill upon generation and avoid excessive calls to the waybill API.\n\n* An integration audit will be done before access to production API can be granted.\n * Please send in 3 different orders, reflective of the type of orders you will be sending in production, with accurate address and other information.\n * We are looking for order requests sent in via the integration that was built.\n * Drop us an email at devsupport@ninjavan.co with the tracking numbers of those orders and the business requirements and we will do a check.\n\n\n#### Base URL Mapping By Environment\n\n | Environment | Base URL |\n |-------------|----------|\n | Production | https://api.ninjavan.co |\n | Sandbox | https://api-sandbox.ninjavan.co (***REFER TO NOTE BELOW***)|\n \n***NOTE:*** Please send all sandbox requests to the Singapore sandbox API. However, you will be able to send in localized addresses for the countries that you are testing for.\n\nIn other words, you can craft the API request as you would for the production environment; the only difference is the URL.\n#### Tracking API (Webooks)\n\n We provide a webhook API for ***PUSH*** type updates for tracking of parcels. \n More information available [here](https://drive.google.com/open?id=1Xt48_WRIqMIj9tEWTLh4z5Z588d93A9V).\n \n \n Unfortunately for now, we do not support any ***PULL*** type status tracking APIs.",
5 "version": "4.1.0",
6 "title": "Order API",
7 "contact": {
8 "email": "devsupport@ninjavan.co"
9 }
10 },
11 "host": "api.ninjavan.co",
12 "basePath": "/",
13 "schemes": [
14 "https"
15 ],
16 "paths": {
17 "/{countryCode}/2.0/oauth/access_token": {
18 "x-summary": "Generate OAuth Access Token",
19 "post": {
20 "description": "Request a new OAuth Bearer Access Token.\n\nShippers will need their client ID and secret for this request. The client ID and secret can be retrieved from the shipper's dashboard, under the API settings section.\n\n***Please ensure that the following flow is followed in your implementation***:\n* Generate an OAuth access token.\n* Store it in persistent storage (database) or cache and also store the expiration timestamp.\n* Attach access token as a bearer token with every API request to Ninja Van API. \n * i.e. For the `Authorization` HTTP header, the value should be `Bearer <INSERT ACCESS TOKEN>`.\n\n* 5 minutes before the token expires, or if the API request to Ninja Van API is responded with a ***HTTP 401*** error, generate a new OAuth access token.\n\n***NOTE:*** Validity period is dynamic, and it might change from time to time. The minimum validity period will be ***1 hour***.",
21 "consumes": [
22 "application/json"
23 ],
24 "produces": [
25 "application/json"
26 ],
27 "parameters": [
28 {
29 "name": "countryCode",
30 "in": "path",
31 "description": "Country Code",
32 "required": true,
33 "type": "string",
34 "enum": [
35 "SG",
36 "MY",
37 "TH",
38 "ID",
39 "VN",
40 "PH",
41 "MM"
42 ]
43 },
44 {
45 "in": "body",
46 "name": "body",
47 "required": false,
48 "schema": {
49 "$ref": "#/definitions/AccessTokenGrantRequest"
50 }
51 }
52 ],
53 "responses": {
54 "200": {
55 "description": "Access token was successfully generated.",
56 "schema": {
57 "$ref": "#/definitions/AccessTokenGrantResponse"
58 }
59 },
60 "400": {
61 "description": "Access token was NOT generated because of an issue with the request.",
62 "schema": {
63 "$ref": "#/definitions/ErrorResponse"
64 }
65 },
66 "500": {
67 "description": "Access token was NOT generated because of an issue with the server.",
68 "schema": {
69 "$ref": "#/definitions/ErrorResponse"
70 }
71 }
72 }
73 }
74 },
75 "/{countryCode}/4.1/orders": {
76 "x-summary": "Create Order (v4.1 - Latest)",
77 "post": {
78 "description": "Creates a new delivery order. \n\nTo avoid create duplicate orders, please send in the `requested_tracking_number` field, and the API will use it to generate the waybill tracking number. ***This is highly recommended.***\n\nIf your shipper account is a prefixless account, `requested_tracking_number` is ***required***.\n\nIf your shipper account has a tracking number prefix configured, the API will concat your prefix with the `requested_tracking_number` to generate the waybill tracking number.\n\nIf `requested_tracking_number` is not provided, the API will auto-generate a random tracking number, and concat your prefix with the `requested_tracking_number` to generate the waybill tracking number. A generic prefix will be used for this request, if your account does not have a prefix *AND* if the `requested_tracking_number` is not provided.\n\nThe total length of the generated `tracking_number` is also further validated based on your shipper setting. The default length for `tracking_number` is usually around 18 characters. If the `requested_tracking_number` is too short, the API will auto-pad the value with `0`s. Please check with us if you have any questions regarding your shipper account settings.\n\nFor marketplace platforms, `marketplace` information is required. Using the provided `seller_id`, the API will automatically create a new Ninja Van shipper account for your marketplace seller, _IF_ the `seller_id` was not registered in Ninja Van's systems beforehand.\n\n#### Address fields\n\n | Country | Field | Description |\n |---------|-------|-------------|\n | Singapore | address1 | |\n | Singapore | address2 | |\n | Singapore | country | |\n | Singapore | postcode | |\n | Singapore | latitude | |\n | Singapore | longitude | |\n | Singapore | address_type | |\n | Malaysia | address1 | |\n | Malaysia | address2 | |\n | Malaysia | area | |\n | Malaysia | city | |\n | Malaysia | state | |\n | Malaysia | country | |\n | Malaysia | postcode | |\n | Malaysia | latitude | |\n | Malaysia | longitude | |\n | Malaysia | address_type | |\n | Thailand | address1 | |\n | Thailand | address2 | |\n | Thailand | sub_district | |\n | Thailand | district | |\n | Thailand | province | |\n | Thailand | country | |\n | Thailand | postcode | |\n | Thailand | latitude | |\n | Thailand | longitude | |\n | Thailand | address_type | |\n | Indonesia | address1 | |\n | Indonesia | address2 | |\n | Indonesia | kelurahan | |\n | Indonesia | kecamatan | |\n | Indonesia | city | |\n | Indonesia | province | |\n | Indonesia | country | |\n | Indonesia | postcode | |\n | Indonesia | latitude | |\n | Indonesia | longitude | |\n | Indonesia | address_type | |\n | Philippines | address1 | |\n | Philippines | address2 | |\n | Philippines | subdivision | Also known as \"Barangay\"|\n | Philippines | district | |\n | Philippines | city | |\n | Philippines | province | |\n | Philippines | country | |\n | Philippines | postcode | |\n | Philippines | latitude | |\n | Philippines | longitude | |\n | Philippines | address_type | |\n | Vietnam | address1 | |\n | Vietnam | address2 | |\n | Vietnam | ward | |\n | Vietnam | district | |\n | Vietnam | city | |\n | Vietnam | country | |\n | Vietnam | latitude | |\n | Vietnam | longitude | |\n | Vietnam | address_type | |\n | Myanmar | address1 | |\n | Myanmar | address2 | |\n | Myanmar | township | |\n | Myanmar | district | |\n | Myanmar | state | |\n | Myanmar | country | |\n | Myanmar | postcode | |\n | Myanmar | latitude | |\n | Myanmar | longitude | |\n | Myanmar | address_type | |\n | Others | address1 | |\n | Others | address2 | |\n | Others | city | |\n | Others | state | |\n | Others | country | |\n | Others | postcode | |\n\n ",
79 "consumes": [
80 "application/json"
81 ],
82 "produces": [
83 "application/json"
84 ],
85 "parameters": [
86 {
87 "name": "Authorization",
88 "in": "header",
89 "required": true,
90 "type": "string",
91 "description": "Please include your bearer token here."
92 },
93 {
94 "name": "countryCode",
95 "in": "path",
96 "description": "Country Code",
97 "required": true,
98 "type": "string",
99 "enum": [
100 "SG",
101 "MY",
102 "TH",
103 "ID",
104 "VN",
105 "PH",
106 "MM"
107 ]
108 },
109 {
110 "in": "body",
111 "name": "body",
112 "required": false,
113 "schema": {
114 "$ref": "#/definitions/NewOrderV4.1"
115 }
116 }
117 ],
118 "responses": {
119 "200": {
120 "description": "Order successfully created.",
121 "schema": {
122 "$ref": "#/definitions/OrderV4.1"
123 }
124 },
125 "400": {
126 "description": "Order was NOT created because of an issue with the request.",
127 "schema": {
128 "$ref": "#/definitions/ErrorResponse"
129 }
130 },
131 "500": {
132 "description": "Order was NOT created because of an issue with the server.",
133 "schema": {
134 "$ref": "#/definitions/ErrorResponse"
135 }
136 }
137 }
138 }
139 },
140 "/{countryCode}/4.0/orders": {
141 "x-summary": "Create Order (V4.0 - Deprecated)",
142 "post": {
143 "description": "***NOTE:*** _DEPRECATED!_ Please do not use.\nCreates a new delivery order. \n\nTo avoid create duplicate orders, please send in the `requested_tracking_number` field, and the API will use it to generate the waybill tracking number. ***This is highly recommended.***\n\nIf your shipper account is a prefixless account, `requested_tracking_number` is ***required***.\n\nIf your shipper account has a tracking number prefix configured, the API will concat your prefix with the `requested_tracking_number` to generate the waybill tracking number.\n\nIf `requested_tracking_number` is not provided, the API will auto-generate a random tracking number, and concat your prefix with the `requested_tracking_number` to generate the waybill tracking number. A generic prefix will be used for this request, if your account does not have a prefix *AND* if the `requested_tracking_number` is not provided.\n\nThe total length of the generated `tracking_number` is also further validated based on your shipper setting. The default length for `tracking_number` is usually around 18 characters. If the `requested_tracking_number` is too short, the API will auto-pad the value with `0`s. Please check with us if you have any questions regarding your shipper account settings.\n\nFor marketplace platforms, `marketplace` information is required. Using the provided `seller_id`, the API will automatically create a new Ninja Van shipper account for your marketplace seller, _IF_ the `seller_id` was not registered in Ninja Van's systems beforehand.",
144 "consumes": [
145 "application/json"
146 ],
147 "produces": [
148 "application/json"
149 ],
150 "parameters": [
151 {
152 "name": "Authorization",
153 "in": "header",
154 "required": true,
155 "type": "string",
156 "description": "Please include your bearer token here."
157 },
158 {
159 "name": "countryCode",
160 "in": "path",
161 "description": "Country Code",
162 "required": true,
163 "type": "string",
164 "enum": [
165 "SG",
166 "MY",
167 "TH",
168 "ID",
169 "VN",
170 "PH",
171 "MM"
172 ]
173 },
174 {
175 "in": "body",
176 "name": "body",
177 "required": false,
178 "schema": {
179 "$ref": "#/definitions/NewOrderV4"
180 }
181 }
182 ],
183 "responses": {
184 "200": {
185 "description": "Order successfully created.",
186 "schema": {
187 "$ref": "#/definitions/OrderV4"
188 }
189 },
190 "400": {
191 "description": "Order was NOT created because of an issue with the request.",
192 "schema": {
193 "$ref": "#/definitions/ErrorResponse"
194 }
195 },
196 "500": {
197 "description": "Order was NOT created because of an issue with the server.",
198 "schema": {
199 "$ref": "#/definitions/ErrorResponse"
200 }
201 }
202 }
203 }
204 },
205 "/{countryCode}/2.0/reports/waybill": {
206 "x-summary": "Generate Waybill",
207 "get": {
208 "description": "Generate waybill for an order that has been processed successfully.\n\n***NOTE:*** Please take note that access to the Waybill API is *conditional*. By default, permissions for this API would not granted to any shipper, even in the sandbox environment. Please take a look at our integration requirements first, and email in to devsupport@ninjavan.co to request for permission.\n\n***NOTE:*** Waybill can only be generated for orders that have been successfully processed. After an order is accepted by the order create API, it goes into a queue for further processing. When an order is fully processed, a `Pending Pickup` webhook is generated. This webhook should give your system a good indication of when a waybill can be generated.",
209 "consumes": [
210 "application/json"
211 ],
212 "produces": [
213 "application/json"
214 ],
215 "parameters": [
216 {
217 "name": "Authorization",
218 "in": "header",
219 "required": true,
220 "type": "string",
221 "description": "Please include your bearer token here."
222 },
223 {
224 "name": "countryCode",
225 "in": "path",
226 "description": "Country Code",
227 "required": true,
228 "type": "string",
229 "enum": [
230 "SG",
231 "MY",
232 "TH",
233 "ID",
234 "VN",
235 "PH",
236 "MM"
237 ]
238 },
239 {
240 "name": "tids",
241 "in": "query",
242 "description": "The `tracking_number` as generated by the order create API.",
243 "required": true,
244 "type": "string",
245 "pattern": "^([a-zA-Z0-9]+[-])*[a-zA-Z0-9]+$",
246 "minLength": 9
247 },
248 {
249 "name": "h",
250 "in": "query",
251 "description": "A flag for hiding shipper details (e.g. shipper's contact) on the waybill.",
252 "required": false,
253 "type": "integer",
254 "format": "int32",
255 "minimum": 0,
256 "maximum": 1
257 }
258 ],
259 "responses": {
260 "200": {
261 "description": "Waybill successfully generated. A PDF file will be returned in the response."
262 },
263 "400": {
264 "description": "Waybill was NOT generated because of an invalid request."
265 }
266 }
267 }
268 },
269 "/{countryCode}/2.2/orders/{trackingNo}": {
270 "x-summary": "Cancel Order",
271 "delete": {
272 "description": "Cancels an existing delivery order.\n\n***NOTE:*** Parameters are named slightly differently, because this endpoint has not been migrated to the v4 API specs.\n\n***NOTE:*** For cancellation of orders, please note that only orders that are `Pending Pickup` can be cancelled.",
273 "consumes": [
274 "application/json"
275 ],
276 "produces": [
277 "application/json"
278 ],
279 "parameters": [
280 {
281 "name": "Authorization",
282 "in": "header",
283 "required": true,
284 "type": "string",
285 "description": "Please include your bearer token here."
286 },
287 {
288 "name": "countryCode",
289 "in": "path",
290 "description": "Country Code",
291 "required": true,
292 "type": "string",
293 "enum": [
294 "SG",
295 "MY",
296 "TH",
297 "ID",
298 "VN",
299 "PH",
300 "MM"
301 ]
302 },
303 {
304 "name": "trackingNo",
305 "in": "path",
306 "description": "The `requested_tracking_number` provided by the shipper in the order create request.",
307 "required": true,
308 "type": "string",
309 "pattern": "^([a-zA-Z0-9]+[-])*[a-zA-Z0-9]+$",
310 "minLength": 9
311 }
312 ],
313 "responses": {
314 "200": {
315 "description": "Order successfully cancelled.",
316 "schema": {
317 "$ref": "#/definitions/CancelOrderResponse"
318 }
319 },
320 "400": {
321 "description": "Order was NOT cancelled because of an issue with the request."
322 },
323 "404": {
324 "description": "Order was NOT cancelled because no orders were found that matched the query parameters."
325 },
326 "500": {
327 "description": "Order was NOT cancelled because of an issue with the server."
328 }
329 }
330 }
331 }
332 },
333 "definitions": {
334 "LegacyOrder": {
335 "type": "object",
336 "properties": {
337 "tracking_id": {
338 "type": "string"
339 },
340 "requested_tracking_id": {
341 "type": "string"
342 },
343 "order_ref_no": {
344 "type": "string"
345 },
346 "type": {
347 "type": "string"
348 },
349 "from_postcode": {
350 "type": "string"
351 },
352 "from_address1": {
353 "type": "string"
354 },
355 "from_address2": {
356 "type": "string"
357 },
358 "from_locality": {
359 "type": "string"
360 },
361 "from_city": {
362 "type": "string"
363 },
364 "from_country": {
365 "type": "string"
366 },
367 "from_email": {
368 "type": "string"
369 },
370 "from_name": {
371 "type": "string"
372 },
373 "from_contact": {
374 "type": "string"
375 },
376 "to_postcode": {
377 "type": "string"
378 },
379 "to_address1": {
380 "type": "string"
381 },
382 "to_address2": {
383 "type": "string"
384 },
385 "to_locality": {
386 "type": "string"
387 },
388 "to_city": {
389 "type": "string"
390 },
391 "to_country": {
392 "type": "string"
393 },
394 "to_email": {
395 "type": "string"
396 },
397 "to_name": {
398 "type": "string"
399 },
400 "to_contact": {
401 "type": "string"
402 },
403 "pickup_instructions": {
404 "type": "string"
405 },
406 "delivery_instructions": {
407 "type": "string"
408 },
409 "delivery_date": {
410 "type": "string"
411 },
412 "parcel_size": {
413 "type": "integer"
414 },
415 "parcel_volume": {
416 "type": "integer",
417 "format": "double"
418 },
419 "parcel_weight": {
420 "type": "integer",
421 "format": "double"
422 },
423 "max_delivery_days": {
424 "type": "integer",
425 "format": "int32",
426 "minimum": 0,
427 "maximum": 10
428 },
429 "id": {
430 "type": "string",
431 "description": "Async handle of the order."
432 }
433 }
434 },
435 "OrderV4": {
436 "type": "object",
437 "allOf": [
438 {
439 "$ref": "#/definitions/NewOrderV4"
440 },
441 {
442 "required": [
443 "tracking_number"
444 ],
445 "properties": {
446 "tracking_number": {
447 "type": "string",
448 "pattern": "^([a-zA-Z0-9]+[-])*[a-zA-Z0-9]+$"
449 }
450 }
451 }
452 ],
453 "example": {
454 "service_type": "Parcel",
455 "service_level": "Standard",
456 "tracking_number": "1234-56789",
457 "requested_tracking_number": "1234-56789",
458 "reference": {
459 "merchant_order_number": "SHIP-1234-56789"
460 },
461 "from": {
462 "name": "John Doe",
463 "phone_number": "+60122222222",
464 "email": "john.doe@gmail.com",
465 "address": {
466 "address1": "17 Lorong Jambu 3",
467 "address2": "",
468 "area": "Taman Sri Delima",
469 "city": "Simpang Ampat",
470 "state": "Pulau Pinang",
471 "country": "MY",
472 "postcode": "51200"
473 }
474 },
475 "to": {
476 "name": "Jane Doe",
477 "phone_number": "+6212222222222",
478 "email": "jane.doe@gmail.com",
479 "address": {
480 "address1": "Gedung Balaikota DKI Jakarta",
481 "address2": "Jalan Medan Merdeka Selatan No. 10",
482 "kelurahan": "Kelurahan Gambir",
483 "kecamatan": "Kecamatan Gambir",
484 "city": "Jakarta Selatan",
485 "province": "Jakarta",
486 "country": "ID",
487 "postcode": "10110"
488 }
489 },
490 "parcel_job": {
491 "pickup_instructions": "Pickup with care!",
492 "delivery_instructions": "If recipient is not around, leave parcel in power riser.",
493 "delivery_start_date": "2017-01-20",
494 "delivery_timeslot": {
495 "start_time": "09:00",
496 "end_time": "22:00",
497 "timezone": "Asia/Singapore"
498 }
499 }
500 }
501 },
502 "NewOrderV4": {
503 "type": "object",
504 "required": [
505 "service_type",
506 "service_level",
507 "from",
508 "to"
509 ],
510 "properties": {
511 "service_type": {
512 "$ref": "#/definitions/ServiceType"
513 },
514 "service_level": {
515 "$ref": "#/definitions/ServiceLevel"
516 },
517 "requested_tracking_number": {
518 "type": "string",
519 "pattern": "^([a-zA-Z0-9]+[-])*[a-zA-Z0-9]+$",
520 "minLength": 9,
521 "description": "If your shipper account is a prefixless account, `requested_tracking_number` is ***required***.\n\nIf your shipper account has a tracking number prefix configured, the API will concat your prefix with the `requested_tracking_number` to generate the waybill tracking number.\n\nIf `requested_tracking_number` is not provided, the API will auto-generate a random tracking number, and concat your prefix with the `requested_tracking_number` to generate the waybill tracking number.\n\nThe total length of the generated `tracking_number` is also further validated based on your shipper setting. The default length for `tracking_number` is usually around 18 characters. If the `requested_tracking_number` is too short, the API will auto-pad the value with `0`s. Please check with us if you have any questions regarding your shipper account settings.\n\nFor marketplace platforms, `marketplace` information is required. Using the provided `seller_id`, the API will automatically create a new Ninja Van shipper account for your marketplace seller, _IF_ the `seller_id` was not registered in Ninja Van's systems beforehand."
522 },
523 "reference": {
524 "type": "object",
525 "description": "Reference information. This information is returned to shipper via webhooks, and can be used as query parameters when retrieving orders from Ninja Van's API.",
526 "properties": {
527 "merchant_order_number": {
528 "type": "string",
529 "description": "Identifier of order in shipper's systems.",
530 "maxLength": 255
531 }
532 }
533 },
534 "from": {
535 "type": "object",
536 "description": "This data is used for the following purposes:\nIt is used:\n* As the contact details for informing sender regarding parcel updates,\n* As the address details to be printed in the waybill",
537 "allOf": [
538 {
539 "$ref": "#/definitions/NewRecipient"
540 }
541 ]
542 },
543 "to": {
544 "type": "object",
545 "description": "This data is used as the delivery destination\nIt is used \n* as the contact details for informing recipient regarding parcel updates,\n* as the address details to be printed in the waybill",
546 "allOf": [
547 {
548 "$ref": "#/definitions/NewRecipient"
549 }
550 ]
551 },
552 "marketplace": {
553 "$ref": "#/definitions/NewMarketplaceOrder"
554 },
555 "parcel_job": {
556 "type": "object",
557 "description": "Details of parcel pickup and delivery job.\n\nIf pickup address is not provided, we will rely on the default pickup address, specified in the shipper pickup reservation settings.",
558 "required": [
559 "is_pickup_required",
560 "delivery_timeslot",
561 "delivery_start_date"
562 ],
563 "properties": {
564 "ready_to_ship_date": {
565 "type": "string",
566 "pattern": "^([12]\\d{3}-(0[1-9]|1[0-2])-(0[1-9]|[12]\\d|3[01]))$",
567 "description": "If shipper can only ship the parcel on a later date, please indicate the `ready_to_ship_date`. Please take note that the acceptable format is `yyyy-MM-dd`.\n\nThis will be used for Ninja Van's auto pickup reservations; If a shipper is configured for auto pickup reservations, we will create a pickup reservation on the `ready_to_ship_date`. If `ready_to_ship_date` is not provided, and the shipper is configured for auto pickup reservations, we will assume that the parcel is ready to ship at the point of order creation.\n\n***NOTE:*** This is different from `pickup_date`, and this parameter will only be applied for shippers configured for auto-pickup reservations."
568 },
569 "is_pickup_required": {
570 "type": "boolean",
571 "description": "Boolean flag that indicates whether or not a pickup reservation is required. \nIf specified as `true`, the system will check if a pickup reservation exists with the same:\n* `pickup_date`\n* `pickup_address_slot_id`\n\nA new pickup reservation will be created if none exists, and it will be tied to the specified `pickup_address_slot_id`.\n\nTo update the pickup address for a specific `pickup_address_slot_id`, the options are:\n* Calling Ninja Van's shipper support hotline.\n* Updating the address tied to the `pickup_address_slot_id` via an API that will be released in the future.\n* Sending in a new order with an updated pickup address.\n * The pickup address specified in either the `from` or `pickup_address` field will be used to update the address\n tied to the `pickup_address_slot_id`.\n \n * ***NOTE:*** Existing pickup reservations tied to this `pickup_address_slot_id` will not be modified in any way.\n\n\nTo update the pickup timeslot for a specific pickup reservation, the options are:\n* Calling Ninja Van's shipper support hotline.\n* Sending in a new order with the same `pickup_address_slot_id`, `pickup_date` but with a different `pickup_timeslot`.\n\nFor more details, please refer to the notes for `pickup_timeslot` and `pickup_address_slot_id` fields.\n\nPlease note that the following fields must be provided if pickup is required:\n* `pickup_date`\n* `pickup_timeslot`\n* `pickup_address_slot_id`\n* `pickup_approx_volume`\n\n***NOTE:*** Please do not use this parameter if your shipper account is configured for auto-pickup reservations.",
572 "default": false
573 },
574 "pickup_address": {
575 "$ref": "#/definitions/NewRecipient"
576 },
577 "pickup_address_slot_id": {
578 "type": "integer",
579 "minimum": 1,
580 "maximum": 10,
581 "description": "Every shipper has 10 different pickup address slots allocated in the system. Please indicate a pickup slot (from 1 to 10) to use for storing this pickup address.\n\nFor each order create API request, if pickup is requested, the system will check if the specified pickup address (taken from the `from` or `pickup_address` field) is different from the existing address stored in the specified pickup address slot.\n\nIf the specified pickup address is different from the existing address stored in the pickup address slot, the system will:\n* Perform a `PUT` operation and replace the address stored in the pickup address slot.\n* Update the address for all pickup reservations tied to this pickup address slot."
582 },
583 "pickup_date": {
584 "type": "string",
585 "pattern": "^([12]\\d{3}-(0[1-9]|1[0-2])-(0[1-9]|[12]\\d|3[01]))$",
586 "description": "Specifies the date for which the pickup will occur. Please take note that the acceptable format is `yyyy-MM-dd`.\n\nThe system will adjust the pickup date automatically to the next available working day, if the specified pickup date:\n* Is on a blocked date (e.g. public holiday or warehouse closure),\n* Does not meet the cut-off time for pickup reservations for that day.\n\nAny adjustments to pickup date will be returned in the response."
587 },
588 "pickup_timeslot": {
589 "$ref": "#/definitions/TimeslotInfo",
590 "description": "Specifies the timeslot for which the pickup will occur.\n\nIf the specified pickup timeslot is different from the existing pickup reservation for the specified `pickup_date`, for the specified pickup address, the system will:\n\n* Perform a `PUT` operation and replace the pickup timeslot for the existing pickup reservation on the specified `pickup_date` at the specified pickup address.\n\n***Note:*** Valid timeslots are:\n* \"09:00\" to \"12:00\"\n* \"09:00\" to \"18:00\"\n* \"09:00\" to \"22:00\"\n* \"12:00\" to \"15:00\"\n* \"15:00\" to \"18:00\"\n* \"18:00\" to \"22:00\""
591 },
592 "pickup_approx_volume": {
593 "type": "string",
594 "enum": [
595 "Full-Van Load",
596 "Half-Van Load",
597 "Larger than Van Load",
598 "Less than 10 Parcels",
599 "Less than 3 Parcels",
600 "Trolley Required"
601 ],
602 "default": "Less than 3 Parcels"
603 },
604 "pickup_instructions": {
605 "type": "string",
606 "description": "Instruction to driver for pickup attempts."
607 },
608 "delivery_start_date": {
609 "type": "string",
610 "pattern": "^([12]\\d{3}-(0[1-9]|1[0-2])-(0[1-9]|[12]\\d|3[01]))$",
611 "description": "Specifies the start date of the delivery period. E.g. For standard orders that takes 3 days, if the `delivery_start_date` is on `2017-02-10`, the delivery will be attempted anytime from `2017-02-10` to `2017-02-12`. Please take note that the acceptable format is `yyyy-MM-dd`. \n\nDate will be adjusted for blocked dates automatically. Please double check adjusted `delivery_start_date` in response.\n\nIf order is created before cut-off time, `delivery_start_date` is defaulted to the same day (if that day is not a blocked date); otherwise `delivery_start_date` is defaulted to the next available date."
612 },
613 "delivery_timeslot": {
614 "$ref": "#/definitions/TimeslotInfo"
615 },
616 "delivery_instructions": {
617 "type": "string",
618 "description": "Instruction to driver for delivery attempts."
619 },
620 "allow_weekend_delivery": {
621 "type": "boolean",
622 "default": true,
623 "description": "Specifies whether or not deliveries should be attempted on weekends."
624 },
625 "cash_on_delivery": {
626 "type": "number",
627 "format": "double",
628 "description": "Specifies the cash that should be picked up from recipient of the parcel."
629 },
630 "insured_value": {
631 "type": "number",
632 "format": "double",
633 "description": "Specifies the desired insured value of the parcel."
634 },
635 "dimensions": {
636 "$ref": "#/definitions/Dimension",
637 "description": "Specifies the dimension of the parcel. This is used for parcel rates calcuations.\n\n***NOTE:*** Please check with your Ninja Van sales rep to see which dimension properties should you be sending in."
638 }
639 }
640 }
641 },
642 "example": {
643 "service_type": "Parcel",
644 "service_level": "Standard",
645 "requested_tracking_number": "1234-56789",
646 "reference": {
647 "merchant_order_number": "SHIP-1234-56789"
648 },
649 "from": {
650 "name": "John Doe",
651 "phone_number": "+60122222222",
652 "email": "john.doe@gmail.com",
653 "address": {
654 "address1": "17 Lorong Jambu 3",
655 "address2": "",
656 "area": "Taman Sri Delima",
657 "city": "Simpang Ampat",
658 "state": "Pulau Pinang",
659 "country": "MY",
660 "postcode": "51200"
661 }
662 },
663 "to": {
664 "name": "Jane Doe",
665 "phone_number": "+6212222222222",
666 "email": "jane.doe@gmail.com",
667 "address": {
668 "address1": "Gedung Balaikota DKI Jakarta",
669 "address2": "Jalan Medan Merdeka Selatan No. 10",
670 "kelurahan": "Kelurahan Gambir",
671 "kecamatan": "Kecamatan Gambir",
672 "city": "Jakarta Selatan",
673 "province": "Jakarta",
674 "country": "ID",
675 "postcode": "10110"
676 }
677 },
678 "parcel_job": {
679 "pickup_instructions": "Pickup with care!",
680 "delivery_instructions": "If recipient is not around, leave parcel in power riser.",
681 "delivery_start_date": "2017-01-20",
682 "delivery_timeslot": {
683 "start_time": "09:00",
684 "end_time": "22:00",
685 "timezone": "Asia/Singapore"
686 }
687 }
688 }
689 },
690 "OrderV4.1": {
691 "type": "object",
692 "allOf": [
693 {
694 "$ref": "#/definitions/NewOrderV4.1"
695 },
696 {
697 "required": [
698 "tracking_number"
699 ],
700 "properties": {
701 "tracking_number": {
702 "type": "string",
703 "pattern": "^([a-zA-Z0-9]+[-])*[a-zA-Z0-9]+$"
704 }
705 }
706 }
707 ],
708 "example": {
709 "service_type": "Parcel",
710 "service_level": "Standard",
711 "tracking_number": "PREFIX-1234-56789",
712 "requested_tracking_number": "1234-56789",
713 "reference": {
714 "merchant_order_number": "SHIP-1234-56789"
715 },
716 "from": {
717 "name": "John Doe",
718 "phone_number": "+60122222222",
719 "email": "john.doe@gmail.com",
720 "address": {
721 "address1": "17 Lorong Jambu 3",
722 "address2": "",
723 "area": "Taman Sri Delima",
724 "city": "Simpang Ampat",
725 "state": "Pulau Pinang",
726 "country": "MY",
727 "postcode": "51200"
728 }
729 },
730 "to": {
731 "name": "Jane Doe",
732 "phone_number": "+6212222222222",
733 "email": "jane.doe@gmail.com",
734 "address": {
735 "address1": "Gedung Balaikota DKI Jakarta",
736 "address2": "Jalan Medan Merdeka Selatan No. 10",
737 "kelurahan": "Kelurahan Gambir",
738 "kecamatan": "Kecamatan Gambir",
739 "city": "Jakarta Selatan",
740 "province": "Jakarta",
741 "country": "ID",
742 "postcode": "10110"
743 }
744 },
745 "parcel_job": {
746 "is_pickup_required": true,
747 "pickup_address_id": 98989012,
748 "pickup_service_type": "Scheduled",
749 "pickup_service_level": "Premium",
750 "pickup_date": "2018-01-18",
751 "pickup_timeslot": {
752 "start_time": "09:00",
753 "end_time": "12:00",
754 "timezone": "Asia/Singapore"
755 },
756 "pickup_instructions": "Pickup with care!",
757 "delivery_instructions": "If recipient is not around, leave parcel in power riser.",
758 "delivery_start_date": "2018-01-19",
759 "delivery_timeslot": {
760 "start_time": "09:00",
761 "end_time": "22:00",
762 "timezone": "Asia/Singapore"
763 }
764 }
765 }
766 },
767 "NewOrderV4.1": {
768 "type": "object",
769 "required": [
770 "service_type",
771 "service_level",
772 "from",
773 "to"
774 ],
775 "properties": {
776 "service_type": {
777 "$ref": "#/definitions/ServiceType"
778 },
779 "service_level": {
780 "$ref": "#/definitions/ServiceLevel"
781 },
782 "requested_tracking_number": {
783 "type": "string",
784 "pattern": "^([a-zA-Z0-9]+[-])*[a-zA-Z0-9]+$",
785 "minLength": 9,
786 "description": "If your shipper account is a prefixless account, `requested_tracking_number` is ***required***.\n\nIf your shipper account has a tracking number prefix configured, the API will concat your prefix with the `requested_tracking_number` to generate the waybill tracking number.\n\nIf `requested_tracking_number` is not provided, the API will auto-generate a random tracking number, and concat your prefix with the `requested_tracking_number` to generate the waybill tracking number.\n\nThe total length of the generated `tracking_number` is also further validated based on your shipper setting. The default length for `tracking_number` is usually around 18 characters. If the `requested_tracking_number` is too short, the API will auto-pad the value with `0`s. Please check with us if you have any questions regarding your shipper account settings.\n\nFor marketplace platforms, `marketplace` information is required. Using the provided `seller_id`, the API will automatically create a new Ninja Van shipper account for your marketplace seller, _IF_ the `seller_id` was not registered in Ninja Van's systems beforehand."
787 },
788 "reference": {
789 "type": "object",
790 "description": "Reference information. This information is returned to shipper via webhooks, and can be used as query parameters when retrieving orders from Ninja Van's API.",
791 "properties": {
792 "merchant_order_number": {
793 "type": "string",
794 "description": "Identifier of order in shipper's systems.",
795 "maxLength": 255
796 }
797 }
798 },
799 "from": {
800 "type": "object",
801 "description": "This data is used for the following purposes:\nIt is used:\n* As the contact details for informing sender regarding parcel updates,\n* As the address details to be printed in the waybill",
802 "allOf": [
803 {
804 "$ref": "#/definitions/NewRecipient"
805 }
806 ]
807 },
808 "to": {
809 "type": "object",
810 "description": "This data is used as the delivery destination\nIt is used \n* as the contact details for informing recipient regarding parcel updates,\n* as the address details to be printed in the waybill",
811 "allOf": [
812 {
813 "$ref": "#/definitions/NewRecipient"
814 }
815 ]
816 },
817 "marketplace": {
818 "$ref": "#/definitions/NewMarketplaceOrder"
819 },
820 "international": {
821 "type": "object",
822 "description": "Details of cross-border specifics.",
823 "required": [
824 "portation"
825 ],
826 "properties": {
827 "portation": {
828 "type": "string",
829 "enum": [
830 "Import",
831 "Export"
832 ],
833 "description": "For orders that involve goods which has been / needs to be imported into the country (be it by a forwarder or by Ninja Van), please indicate `Import` as the portation type.\n\nFor orders that require goods to be exported by Ninja Van to another country, please indicate `Export` as the portation type."
834 }
835 }
836 },
837 "parcel_job": {
838 "type": "object",
839 "description": "Details of parcel pickup and delivery job.\n\nIf pickup address is not provided, we will rely on the default pickup address, specified in the shipper pickup reservation settings.",
840 "required": [
841 "is_pickup_required",
842 "delivery_timeslot",
843 "delivery_start_date"
844 ],
845 "properties": {
846 "allow_self_collection": {
847 "type": "boolean",
848 "description": "Boolean flag that indicates whether or not customer is allowed to self collect the parcels.\n***Compulsory*** if a valid delivery collection point (`to.collection_point`) is specified."
849 },
850 "is_pickup_required": {
851 "type": "boolean",
852 "description": "Boolean flag that indicates whether or not a pickup reservation is required. \nIf specified as `true`, the system will check if a pickup reservation exists with the same:\n* `pickup_date`\n* Pickup Address (Detected from the `parcel_job.pickup_address` or `from.address`)\n\nA new pickup reservation will be created if none exists for the current pickup date and address.\n\nTo update the pickup address for a specific `pickup_address_slot_id`, the options are:\n* Calling Ninja Van's shipper support hotline.\n* Updating the address tied to the `pickup_address_id` via the pickup reservation API.\n* Sending in a new order with an updated pickup address.\n * The pickup address specified in either the `from` or `pickup_address` field will be used to update the address\n tied to the `pickup_address_id`.\n \n * ***NOTE:*** Existing pickup reservations tied to this `pickup_address_id`, that are already in progress will not be modified in any way.\n \n * ***NOTE:*** You account can be configured to _NOT_ update future pickup reservation addresses even if the address tied to the `pickup_address_id` has changed.\n\n\nTo update the pickup timeslot for a specific pickup reservation, the options are:\n* Calling Ninja Van's shipper support hotline.\n* Sending in a new order with the same `pickup_address_id`, `pickup_date` but with a different `pickup_timeslot`.\n\nFor more details, please refer to the notes for `pickup_timeslot` and `pickup_address_id` fields.\n\nPlease note that the following fields must be provided if a `Scheduled` pickup is required:\n* `pickup_date`\n* `pickup_timeslot`\n* `pickup_approx_volume`",
853 "default": false
854 },
855 "pickup_address": {
856 "$ref": "#/definitions/NewRecipient"
857 },
858 "pickup_address_id": {
859 "type": "string",
860 "pattern": "^([a-zA-Z0-9]+[-])*[a-zA-Z0-9]+$",
861 "description": "For each order create API request, if pickup is requested, the system will check if the specified pickup address (taken from the `from` or `pickup_address` field) is different from the existing address stored with the specified `pickup_address_id`.\n\nThis pickup_address_id can be mapped to your internal address DB ID. If you store address in a database table, passing in the address ID from your DB is one of the ways you can provide Ninja Van with a `pickup_address_id`.\n\nIf the specified pickup_address_id is not mapped to an existing address, the system will:\n* Perform a `POST` operation and creates a new address, mapped to the provided `pickup_address_id`.\n\nIf the specified pickup address is different from the existing address stored with the specified `pickup_address_id`, the system will:\n* Perform a `PUT` operation and replace the address stored with the specified `pickup_address_id`.\n* Update the address for all future pickup reservations tied to the old address.",
862 "minLength": 1,
863 "maxLength": 64
864 },
865 "pickup_service_type": {
866 "type": "string",
867 "enum": [
868 "Scheduled",
869 "On-Demand"
870 ],
871 "default": "Scheduled",
872 "description": "Please indicate the pickup service type that you require. Do check with your Ninja Van sales rep which pickup type(s) your account is configured for.\n\n* If you need to indicate a specific pickup date and/or timeslot, please use `Scheduled` pickups.\n* If you require an immediate pickup, do use `On-Demand`. \n\nWe will reject the request if your account is not configured for the specified `pickup_service_type`."
873 },
874 "pickup_service_level": {
875 "type": "string",
876 "enum": [
877 "Standard",
878 "Premium"
879 ],
880 "default": "Standard",
881 "description": "***Note:*** Does not apply to `On-Demand` pickups.\n\nFor `Scheduled` pickups, you have the option of choosing `Standard` or `Premium` pickup service levels.\n\n`Premium` pickups have shorter pickup timeslot windows, and the cut-off rules are more relaxed. Please check with your Ninja Van sales rep to see if your account is eligible for `Premium` pickups."
882 },
883 "pickup_date": {
884 "type": "string",
885 "pattern": "^([12]\\d{3}-(0[1-9]|1[0-2])-(0[1-9]|[12]\\d|3[01]))$",
886 "description": "Specifies the date for which the pickup will occur. Please take note that the acceptable format is `yyyy-MM-dd`.\n\nThe system will adjust the pickup date automatically to the next available working day, if the specified pickup date:\n* Is on a blocked date (e.g. public holiday or warehouse closure),\n* Does not meet the cut-off time for pickup reservations for that day.\n\nAny adjustments to pickup date will be returned in the response."
887 },
888 "pickup_timeslot": {
889 "$ref": "#/definitions/TimeslotInfo",
890 "description": "Specifies the timeslot for which the pickup will occur.\n\nIf the specified pickup timeslot is different from the existing pickup reservation for the specified `pickup_date`, for the specified pickup address, the system will:\n\n* Perform a `PUT` operation and replace the pickup timeslot for the existing pickup reservation on the specified `pickup_date` at the specified pickup address.\n\n***Note:*** Valid timeslots are:\n* \"09:00\" to \"12:00\"\n* \"09:00\" to \"18:00\"\n* \"09:00\" to \"22:00\"\n* \"12:00\" to \"15:00\"\n* \"15:00\" to \"18:00\"\n* \"18:00\" to \"22:00\"\n\n***NOTE:*** For shippers who are eligible for `Premium` pickups, a longer list of timeslots with shorter time windows are available to you. Please check with your Ninja Van sales rep on your available options."
891 },
892 "pickup_approx_volume": {
893 "type": "string",
894 "enum": [
895 "Full-Van Load",
896 "Half-Van Load",
897 "Larger than Van Load",
898 "Less than 10 Parcels",
899 "Less than 3 Parcels",
900 "Trolley Required"
901 ],
902 "default": "Less than 3 Parcels"
903 },
904 "pickup_instructions": {
905 "type": "string",
906 "description": "Instruction to driver for pickup attempts."
907 },
908 "delivery_start_date": {
909 "type": "string",
910 "pattern": "^([12]\\d{3}-(0[1-9]|1[0-2])-(0[1-9]|[12]\\d|3[01]))$",
911 "description": "Specifies the start date of the delivery period. E.g. For standard orders that takes 3 days, if the `delivery_start_date` is on `2017-02-10`, the delivery will be attempted anytime from `2017-02-10` to `2017-02-12`. Please take note that the acceptable format is `yyyy-MM-dd`.\n\nDate will be adjusted for blocked dates automatically. Please double check adjusted `delivery_start_date` in response.\n\nIf order is created before cut-off time, `delivery_start_date` is defaulted to the same day (if that day is not a blocked date); otherwise `delivery_start_date` is defaulted to the next available date."
912 },
913 "delivery_timeslot": {
914 "$ref": "#/definitions/TimeslotInfo"
915 },
916 "delivery_instructions": {
917 "type": "string",
918 "description": "Instruction to driver for delivery attempts."
919 },
920 "allow_weekend_delivery": {
921 "type": "boolean",
922 "default": true,
923 "description": "Specifies whether or not deliveries should be attempted on weekends."
924 },
925 "cash_on_delivery": {
926 "type": "number",
927 "format": "double",
928 "description": "Specifies the cash that should be picked up from recipient of the parcel."
929 },
930 "insured_value": {
931 "type": "number",
932 "format": "double",
933 "description": "Specifies the desired insured value of the parcel."
934 },
935 "dimensions": {
936 "$ref": "#/definitions/Dimension",
937 "description": "Specifies the dimension of the parcel. This is used for parcel rates calcuations.\n\n***NOTE:*** Please check with your Ninja Van sales rep to see which dimension properties should you be sending in."
938 }
939 }
940 }
941 },
942 "example": {
943 "service_type": "Parcel",
944 "service_level": "Standard",
945 "requested_tracking_number": "1234-56789",
946 "reference": {
947 "merchant_order_number": "SHIP-1234-56789"
948 },
949 "from": {
950 "name": "John Doe",
951 "phone_number": "+60122222222",
952 "email": "john.doe@gmail.com",
953 "address": {
954 "address1": "17 Lorong Jambu 3",
955 "address2": "",
956 "area": "Taman Sri Delima",
957 "city": "Simpang Ampat",
958 "state": "Pulau Pinang",
959 "address_type": "office",
960 "country": "MY",
961 "postcode": "51200"
962 }
963 },
964 "to": {
965 "name": "Jane Doe",
966 "phone_number": "+6212222222222",
967 "email": "jane.doe@gmail.com",
968 "address": {
969 "address1": "Gedung Balaikota DKI Jakarta",
970 "address2": "Jalan Medan Merdeka Selatan No. 10",
971 "kelurahan": "Kelurahan Gambir",
972 "kecamatan": "Kecamatan Gambir",
973 "city": "Jakarta Selatan",
974 "province": "Jakarta",
975 "country": "ID",
976 "postcode": "10110"
977 }
978 },
979 "parcel_job": {
980 "is_pickup_required": true,
981 "pickup_address_id": 98989012,
982 "pickup_service_type": "Scheduled",
983 "pickup_service_level": "Premium",
984 "pickup_date": "2018-01-18",
985 "pickup_timeslot": {
986 "start_time": "09:00",
987 "end_time": "12:00",
988 "timezone": "Asia/Singapore"
989 },
990 "pickup_instructions": "Pickup with care!",
991 "delivery_instructions": "If recipient is not around, leave parcel in power riser.",
992 "delivery_start_date": "2018-01-19",
993 "delivery_timeslot": {
994 "start_time": "09:00",
995 "end_time": "22:00",
996 "timezone": "Asia/Singapore"
997 }
998 }
999 }
1000 },
1001 "NewMarketplaceOrder": {
1002 "type": "object",
1003 "description": "Required if order `type` is `Marketplace`.",
1004 "required": [
1005 "seller_id",
1006 "seller_company_name"
1007 ],
1008 "properties": {
1009 "seller_id": {
1010 "type": "string",
1011 "pattern": "^([a-zA-Z0-9]+[-])*[a-zA-Z0-9]+$",
1012 "description": "External reference for this marketplace seller. If your platform is a marketplace, and you are creating an order for a seller on your platform, do pass in the unique seller ID in this field.",
1013 "minLength": 1,
1014 "maxLength": 255
1015 },
1016 "seller_company_name": {
1017 "type": "string",
1018 "description": "Company name of this marketplace seller.",
1019 "minLength": 2,
1020 "maxLength": 255
1021 }
1022 }
1023 },
1024 "NewRecipient": {
1025 "type": "object",
1026 "required": [
1027 "name",
1028 "phone_number",
1029 "email",
1030 "address"
1031 ],
1032 "properties": {
1033 "name": {
1034 "type": "string",
1035 "example": "John Doe",
1036 "minLength": 3,
1037 "maxLength": 255
1038 },
1039 "phone_number": {
1040 "type": "string",
1041 "description": "Phone number of the contact.\n\nAPI will attempt to format the number based on the E.164 format, using the country code of the address provided. If it can be formatted, we will take that the number is a valid one.\n\nAPI only requires that either the `email` or `phone_number` is valid. ",
1042 "maxLength": 32,
1043 "minLength": 6,
1044 "example": "+65 98761234"
1045 },
1046 "email": {
1047 "type": "string",
1048 "description": "Email address of the contact.\n\nMust be a valid email address format. The formal definitions are in `RFC 5322` (sections 3.2.3 and 3.4.1) and `RFC 5321`; with a more readable form given in the informational `RFC 3696` and the associated errata.\n\nAPI only requires that either the `email` or `phone_number` is valid; but if email is provided, it will be validated and an error will be thrown if the validation fails.",
1049 "format": "email",
1050 "example": "john.doe@mail.com"
1051 },
1052 "address": {
1053 "$ref": "#/definitions/NewAddress"
1054 },
1055 "collection_point": {
1056 "type": "string",
1057 "enum": [
1058 "Ninja PUDO @ NUH",
1059 "Ninja PUDO @ Orchard"
1060 ],
1061 "description": "***Experimental***"
1062 }
1063 }
1064 },
1065 "NewAddress": {
1066 "type": "object",
1067 "required": [
1068 "address1",
1069 "country"
1070 ],
1071 "properties": {
1072 "address1": {
1073 "type": "string",
1074 "example": "123 Awesome Street",
1075 "description": "If you are collecting granular address information, please concat the Building No, Building Name, and Street information in this field."
1076 },
1077 "address2": {
1078 "type": "string",
1079 "example": "#01-01"
1080 },
1081 "country": {
1082 "$ref": "#/definitions/CountryCode"
1083 },
1084 "latitude": {
1085 "type": "number",
1086 "format": "double",
1087 "minimum": -90,
1088 "maximum": 90
1089 },
1090 "longitude": {
1091 "type": "number",
1092 "format": "double",
1093 "minimum": -180,
1094 "maximum": 180
1095 },
1096 "address_type": {
1097 "type": "string",
1098 "example": "office",
1099 "description": "To indicate the type of the address. Value must be either `home` or `office`"
1100 }
1101 },
1102 "allOf": [
1103 {
1104 "$ref": "#/definitions/NewIndonesiaAddress"
1105 },
1106 {
1107 "$ref": "#/definitions/NewMyanmarAddress"
1108 },
1109 {
1110 "$ref": "#/definitions/NewMalaysiaAddress"
1111 },
1112 {
1113 "$ref": "#/definitions/NewPhilippinesAddress"
1114 },
1115 {
1116 "$ref": "#/definitions/NewSingaporeAddress"
1117 },
1118 {
1119 "$ref": "#/definitions/NewThailandAddress"
1120 },
1121 {
1122 "$ref": "#/definitions/NewVietnamAddress"
1123 }
1124 ]
1125 },
1126 "NewIndonesiaAddress": {
1127 "type": "object",
1128 "description": "Indonesia specific address fields.",
1129 "required": [
1130 "postcode"
1131 ],
1132 "properties": {
1133 "kelurahan": {
1134 "type": "string",
1135 "description": "For ID addresses."
1136 },
1137 "kecamatan": {
1138 "type": "string",
1139 "description": "For ID addresses."
1140 },
1141 "city": {
1142 "type": "string",
1143 "description": "For ID addresses."
1144 },
1145 "province": {
1146 "type": "string",
1147 "description": "For ID addresses."
1148 },
1149 "postcode": {
1150 "type": "string",
1151 "description": "Postal Code for ID addresses."
1152 }
1153 },
1154 "example": {
1155 "kelurahan": "Kelurahan Gambir",
1156 "kecamatan": "Kecamatan Gambir",
1157 "city": "Jakarta Selatan",
1158 "province": "Jakarta",
1159 "postcode": "10110"
1160 }
1161 },
1162 "NewMyanmarAddress": {
1163 "type": "object",
1164 "description": "Myanmar specific address fields.",
1165 "required": [
1166 "postcode"
1167 ],
1168 "properties": {
1169 "township": {
1170 "type": "string",
1171 "description": "For MM addresses."
1172 },
1173 "district": {
1174 "type": "string",
1175 "description": "For MM addresses."
1176 },
1177 "state": {
1178 "type": "string",
1179 "description": "For MM addresses."
1180 },
1181 "postcode": {
1182 "type": "string",
1183 "description": "Postal Code for MM addresses."
1184 }
1185 },
1186 "example": {
1187 "township": "San Lorenzo South Subdivision",
1188 "district": "Malitlit",
1189 "state": "LAGUNA",
1190 "postcode": "4026"
1191 }
1192 },
1193 "NewMalaysiaAddress": {
1194 "type": "object",
1195 "description": "Malaysia specific address fields.",
1196 "required": [
1197 "postcode"
1198 ],
1199 "properties": {
1200 "area": {
1201 "type": "string",
1202 "description": "For MY addresses."
1203 },
1204 "city": {
1205 "type": "string",
1206 "description": "For MY addresses."
1207 },
1208 "state": {
1209 "type": "string",
1210 "description": "For MY addresses."
1211 },
1212 "postcode": {
1213 "type": "string",
1214 "description": "Postal Code for MY addresses."
1215 }
1216 },
1217 "example": {
1218 "area": "Taman Sri Delima",
1219 "city": "Simpang Ampat",
1220 "state": "Pulau Pinang",
1221 "postcode": "51200"
1222 }
1223 },
1224 "NewPhilippinesAddress": {
1225 "type": "object",
1226 "description": "Philippines specific address fields.",
1227 "required": [
1228 "postcode"
1229 ],
1230 "properties": {
1231 "subdivision": {
1232 "type": "string",
1233 "description": "For PH addresses."
1234 },
1235 "district": {
1236 "type": "string",
1237 "description": "For PH addresses."
1238 },
1239 "city": {
1240 "type": "string",
1241 "description": "For PH addresses."
1242 },
1243 "province": {
1244 "type": "string",
1245 "description": "For PH addresses."
1246 },
1247 "postcode": {
1248 "type": "string",
1249 "description": "Postal Code for PH addresses."
1250 }
1251 },
1252 "example": {
1253 "subdivision": "San Lorenzo South Subdivision",
1254 "district": "Malitlit",
1255 "city": "Santa Rosa",
1256 "province": "LAGUNA",
1257 "postcode": "4026"
1258 }
1259 },
1260 "NewSingaporeAddress": {
1261 "type": "object",
1262 "description": "Singapore specific address fields.",
1263 "required": [
1264 "postcode"
1265 ],
1266 "properties": {
1267 "postcode": {
1268 "type": "string",
1269 "description": "Postal Code for SG addresses."
1270 }
1271 }
1272 },
1273 "NewThailandAddress": {
1274 "type": "object",
1275 "description": "Thailand specific address fields.",
1276 "required": [
1277 "postcode"
1278 ],
1279 "properties": {
1280 "sub-district": {
1281 "type": "string",
1282 "description": "For TH addresses."
1283 },
1284 "district": {
1285 "type": "string",
1286 "description": "For TH addresses."
1287 },
1288 "province": {
1289 "type": "string",
1290 "description": "For TH addresses."
1291 },
1292 "postcode": {
1293 "type": "string",
1294 "description": "Postal Code for TH addresses."
1295 }
1296 },
1297 "example": {
1298 "sub-district": "Bangyai",
1299 "district": "Bangyai",
1300 "province": "Nonthaburi",
1301 "postcode": "11140"
1302 }
1303 },
1304 "NewVietnamAddress": {
1305 "type": "object",
1306 "description": "Vietnam specific address fields.",
1307 "properties": {
1308 "ward": {
1309 "type": "string",
1310 "description": "For VN addresses."
1311 },
1312 "district": {
1313 "type": "string",
1314 "description": "For VN addresses."
1315 },
1316 "city": {
1317 "type": "string",
1318 "description": "For VN addresses."
1319 }
1320 },
1321 "example": {
1322 "ward": "phường Nguyễn Du",
1323 "district": "quận Hai Bà Trưng",
1324 "city": "thành phố Hà Nội"
1325 }
1326 },
1327 "CountryCode": {
1328 "type": "string",
1329 "enum": [
1330 "SG",
1331 "MY",
1332 "TH",
1333 "ID",
1334 "VN",
1335 "PH",
1336 "MM"
1337 ],
1338 "example": "SG"
1339 },
1340 "ServiceType": {
1341 "type": "string",
1342 "description": "Service type. This will be used as a instruction to inform Ninja Van on what jobs to schedule for this order.",
1343 "enum": [
1344 "Parcel",
1345 "Return",
1346 "Marketplace",
1347 "Bulky",
1348 "International"
1349 ]
1350 },
1351 "ServiceLevel": {
1352 "type": "string",
1353 "description": "Shipment service level.",
1354 "enum": [
1355 "Standard",
1356 "Express",
1357 "Sameday",
1358 "Nextday"
1359 ]
1360 },
1361 "TimeslotInfo": {
1362 "type": "object",
1363 "description": "Timeslot information.\n\nValid timeslots are:\n\n * \"09:00\" to \"12:00\"\n * \"09:00\" to \"18:00\"\n * \"09:00\" to \"22:00\"\n * \"12:00\" to \"15:00\"\n * \"15:00\" to \"18:00\"\n * \"18:00\" to \"22:00\"",
1364 "required": [
1365 "start_time",
1366 "end_time"
1367 ],
1368 "properties": {
1369 "start_time": {
1370 "type": "string",
1371 "pattern": "^([0-1][0-9]|2[0-3]):[0-5][0-9]$"
1372 },
1373 "end_time": {
1374 "type": "string",
1375 "pattern": "^([0-1][0-9]|2[0-3]):[0-5][0-9]$"
1376 },
1377 "timezone": {
1378 "$ref": "#/definitions/Timezone"
1379 }
1380 }
1381 },
1382 "Timezone": {
1383 "type": "string",
1384 "enum": [
1385 "Asia/Singapore",
1386 "Asia/Kuala_Lumpur",
1387 "Asia/Jakarta",
1388 "Asia/Jayapura",
1389 "Asia/Makassar",
1390 "Asia/Bangkok",
1391 "Asia/Manila",
1392 "Asia/Ho_Chi_Minh",
1393 "Asia/Yangon"
1394 ]
1395 },
1396 "Dimension": {
1397 "type": "object",
1398 "description": "Dimension information about parcels or objects.",
1399 "properties": {
1400 "size": {
1401 "type": "string",
1402 "enum": [
1403 "S",
1404 "M",
1405 "L",
1406 "XL",
1407 "XXL"
1408 ]
1409 },
1410 "weight": {
1411 "type": "number",
1412 "description": "The weight of the parcel, in kilograms (k.g.).",
1413 "format": "double"
1414 },
1415 "length": {
1416 "type": "number",
1417 "description": "The length of the parcel, in centimeters (c.m.).",
1418 "format": "double"
1419 },
1420 "width": {
1421 "type": "number",
1422 "description": "The width of the parcel, in centimeters (c.m.).",
1423 "format": "double"
1424 },
1425 "height": {
1426 "type": "number",
1427 "description": "The height of the parcel, in centimeters (c.m.).",
1428 "format": "double"
1429 }
1430 }
1431 },
1432 "PickupBooking": {
1433 "type": "object",
1434 "allOf": [
1435 {
1436 "$ref": "#/definitions/NewPickupBooking"
1437 }
1438 ],
1439 "example": {
1440 "pickup_address": {
1441 "name": "John Doe",
1442 "phone_number": "+60122222222",
1443 "email": "john.doe@gmail.com",
1444 "address": {
1445 "address1": "17 Lorong Jambu 3",
1446 "address2": "",
1447 "area": "Taman Sri Delima",
1448 "city": "Simpang Ampat",
1449 "state": "Pulau Pinang",
1450 "country": "MY",
1451 "postcode": "51200"
1452 }
1453 },
1454 "pickup_service_type": "Scheduled",
1455 "pickup_service_level": "Standard",
1456 "pickup_date": "2018-01-18",
1457 "pickup_timeslot": {
1458 "start_time": "09:00",
1459 "end_time": "12:00",
1460 "timezone": "Asia/Kuala_Lumpur"
1461 },
1462 "pickup_instructions": "Pickup with care!",
1463 "pickup_approx_volume": "Less than 3 Parcels"
1464 }
1465 },
1466 "NewPickupBooking": {
1467 "type": "object",
1468 "properties": {
1469 "pickup_service_type": {
1470 "type": "string",
1471 "enum": [
1472 "Scheduled",
1473 "On-Demand"
1474 ],
1475 "default": "Scheduled",
1476 "description": "Please indicate the pickup service type that you require. Do check with your Ninja Van sales rep which pickup type(s) your account is configured for.\n\n* If you need to indicate a specific pickup date and/or timeslot, please use `Scheduled` pickups.\n* If you require an immediate pickup, do use `On-Demand`. \n \n\nWe will reject the request if your account is not configured for the specified `pickup_service_type`."
1477 },
1478 "pickup_service_level": {
1479 "type": "string",
1480 "enum": [
1481 "Standard",
1482 "Premium"
1483 ],
1484 "default": "Standard",
1485 "description": "***Note:*** Does not apply to `On-Demand` pickups.\n\nFor `Scheduled` pickups, you have the option of choosing `Standard` or `Premium` pickup service levels.\n\n`Premium` pickups have shorter pickup timeslot windows, and the cut-off rules are more relaxed. Please check with your Ninja Van sales rep to see if your account is eligible for `Premium` pickups."
1486 },
1487 "pickup_date": {
1488 "type": "string",
1489 "pattern": "^([12]\\d{3}-(0[1-9]|1[0-2])-(0[1-9]|[12]\\d|3[01]))$",
1490 "description": "Specifies the date for which the pickup will occur. Please take note that the acceptable format is `yyyy-MM-dd`.\n\nThe system will adjust the pickup date automatically to the next available working day, if the specified pickup date:\n* Is on a blocked date (e.g. public holiday or warehouse closure),\n* Does not meet the cut-off time for pickup bookings for that day.\n\nAny adjustments to pickup date will be returned in the response."
1491 },
1492 "pickup_timeslot": {
1493 "$ref": "#/definitions/TimeslotInfo"
1494 },
1495 "pickup_instructions": {
1496 "type": "string"
1497 },
1498 "pickup_approx_volume": {
1499 "type": "string",
1500 "enum": [
1501 "Full-Van Load",
1502 "Half-Van Load",
1503 "Larger than Van Load",
1504 "Less than 10 Parcels",
1505 "Less than 3 Parcels",
1506 "Trolley Required"
1507 ]
1508 },
1509 "pickup_address": {
1510 "$ref": "#/definitions/NewRecipient"
1511 },
1512 "reference": {
1513 "type": "object",
1514 "description": "Reference information. This information is returned to shipper via webhooks, and can be used as query parameters when retrieving pickup bookings from Ninja Van's API.",
1515 "properties": {
1516 "merchant_pickup_booking_number": {
1517 "type": "string",
1518 "description": "Identifier of pickup booking in shipper's systems.",
1519 "maxLength": 255
1520 }
1521 }
1522 }
1523 },
1524 "example": {
1525 "pickup_address": {
1526 "name": "John Doe",
1527 "phone_number": "+60122222222",
1528 "email": "john.doe@gmail.com",
1529 "address": {
1530 "address1": "17 Lorong Jambu 3",
1531 "address2": "",
1532 "area": "Taman Sri Delima",
1533 "city": "Simpang Ampat",
1534 "state": "Pulau Pinang",
1535 "country": "MY",
1536 "postcode": "51200"
1537 }
1538 },
1539 "pickup_service_type": "Scheduled",
1540 "pickup_service_level": "Standard",
1541 "pickup_date": "2018-01-18",
1542 "pickup_timeslot": {
1543 "start_time": "09:00",
1544 "end_time": "12:00",
1545 "timezone": "Asia/Kuala_Lumpur"
1546 },
1547 "pickup_instructions": "Pickup with care!",
1548 "pickup_approx_volume": "Less than 3 Parcels",
1549 "reference": {
1550 "merchant_pickup_booking_number": "Pickup-123456"
1551 }
1552 }
1553 },
1554 "AccessTokenGrantRequest": {
1555 "type": "object",
1556 "required": [
1557 "client_id",
1558 "client_secret",
1559 "grant_type"
1560 ],
1561 "properties": {
1562 "client_id": {
1563 "type": "string",
1564 "description": "Client ID"
1565 },
1566 "client_secret": {
1567 "type": "string",
1568 "description": "Client Secret"
1569 },
1570 "grant_type": {
1571 "type": "string",
1572 "enum": [
1573 "client_credentials"
1574 ]
1575 }
1576 }
1577 },
1578 "AccessTokenGrantResponse": {
1579 "type": "object",
1580 "required": [
1581 "access_token",
1582 "expires",
1583 "expires_in",
1584 "token_type"
1585 ],
1586 "properties": {
1587 "access_token": {
1588 "type": "string",
1589 "description": "OAuth Bearer access token to be included in the `Authorization` HTTP header for all API requests."
1590 },
1591 "expires": {
1592 "type": "integer",
1593 "format": "int32",
1594 "minimum": 1,
1595 "description": "The epoch timestamp at which the access token will expire."
1596 },
1597 "expires_in": {
1598 "type": "integer",
1599 "format": "int32",
1600 "description": "The number of seconds at which the access token will expire in.",
1601 "minimum": 300
1602 },
1603 "token_type": {
1604 "type": "string",
1605 "enum": [
1606 "bearer"
1607 ]
1608 }
1609 }
1610 },
1611 "ErrorResponse": {
1612 "type": "object",
1613 "required": [
1614 "error"
1615 ],
1616 "properties": {
1617 "error": {
1618 "$ref": "#/definitions/Error"
1619 }
1620 }
1621 },
1622 "Error": {
1623 "type": "object",
1624 "required": [
1625 "request_id"
1626 ],
1627 "properties": {
1628 "code": {
1629 "type": "string",
1630 "description": "Internal error reference Code."
1631 },
1632 "request_id": {
1633 "type": "string",
1634 "description": "Request identifier for error tracking."
1635 },
1636 "title": {
1637 "type": "string",
1638 "description": "Frontend friendly error title."
1639 },
1640 "message": {
1641 "type": "string",
1642 "description": "Frontend friendly error message."
1643 },
1644 "details": {
1645 "type": "array",
1646 "items": {
1647 "$ref": "#/definitions/ErrorDetail"
1648 }
1649 }
1650 }
1651 },
1652 "ErrorDetail": {
1653 "type": "object",
1654 "required": [
1655 "reason",
1656 "field",
1657 "message"
1658 ],
1659 "properties": {
1660 "reason": {
1661 "type": "string"
1662 },
1663 "field": {
1664 "type": "string"
1665 },
1666 "message": {
1667 "type": "string"
1668 }
1669 }
1670 },
1671 "CancelOrderResponse": {
1672 "type": "object",
1673 "properties": {
1674 "trackingId": {
1675 "type": "string",
1676 "description": "Tracking ID of the order that was cancelled."
1677 },
1678 "status": {
1679 "type": "string",
1680 "description": "Status of the order."
1681 },
1682 "updatedAt": {
1683 "type": "string",
1684 "format": "datetime",
1685 "description": "Date that the order was cancelled."
1686 }
1687 }
1688 }
1689 }
1690}