Steps
Step 1: Setup
Step 2: Environments
Step 3: Requesting a delivery
Step 4: Destination Map
Step 5: Troubleshooting
Help
Tailor Made
Before you start
Step 1: Set up
OAUTH_CLIENT_ID
Keep this value private and safe! This is your OAuth2 Client ID that you will use to authenticate with the Partner API.
OAUTH_CLIENT_SECRET
Keep this value private and safe! This is your OAuth2 Client Secret that you will use to authentica te with the Partner API.
API_URL
This is your Base URL for the Partner API, to which you will then append the relevant endpoint paths.
Step 2: Environments
Test / Stage
An environment with limited functionalities, where you can test the integration.
Production
Use this environment with caution, as it is live and connected to real end users.
Step 3: Process of requesting a delivery
Follow these steps to successfully request a delivery and perform other related actions:
3.1 Authenticate yourself /auth sessions
Authentication is based on OAuth 2.0 standard, Client Credentials grant.
In order to use the API, you must attach the access token to Authorization header as a Bearer token.
See an example of a successful integration:
POST /api/v1/ auth sessions
{
"grant_type”: "client_credentials”,
"client_id": “string”,
"client_secret": “string”
}
Status Code 200
{
"access_token”: “client_credentials”,
"token_type": “Bearer”,
"expires_in”: 3600
}
Further responses, which might occur:
400
The server cannot or will not process the request due to something that is perceived to be your error (e.g., not to spec request syntax, invalid request message). You are to modify the request before sending it again.
401
Not Authorized. You are either using an expired Access token to access the data or trying to initialize Auth session with invalid data.
403
Account disabled. Your account had been disabled, contact support.
3.2 List all available origins/origins
This call will list all available pick up point (PUP locations where BoxNow can pick up all your parcels from typically your warehouses.
You can list all your warehouses using /origins API call which has the same parameters as /destinations API call where you do not specify parameters latlng, radius or requiredSize, but you specify locationType as “warehouse”. You refer to this location by its ID (locationid).
Moreover there is one specific location called any-apm that can be listed by the same way and using locationType as “any-apm”, it returns just one location-any-apm. You can refer to it by its ID (locationid). Usage of this will be explained in the next section.
Below is the parameter availa ble for you to filter all Origin locations:
Name | Type | Description |
---|---|---|
locationType | string |
Return only locations with given a type. If not present, filter is not applied.
|
See an example of a successful integration:
GET /api/v1/ origins
curl -X ‘GET’\
'…/origins\
-H 'accept: application/json’
Status Code 200
{
"data": [
{
"id": "string",
"type": "warehouse",
"image": "https://via.placeholder.com/175",
"lat": "48.940819584637266",
"lng": "12.366962491028423",
"title": "Warehouse 1",
"name": "Main Warehouse",
"addressLine1": "ul.Tsar Boris III",
"addressLine2": "Sofia",
"postalCode": "1000",
"country": "BG",
"note": "Next to Super market"// can be null
}
]
}
Further responses, which might occur:
Error Code
400
The server cannot or will not process the request due to something that is perceived to be your error (e.g., malformed request syntax, invalid request message). You are to modify the request before sending it again.
401
Not Authorized. You are either using an expired Access token to access the data or trying to initialize Auth session with invalid data.
403
Account disabled. Your account had been disabled, contact support.
3.3. List all available destinations /destinations
This call will list all available APM (Automatic Parcel Machine) locations where we can deliver your parcel to.
Beloware the parameters available for you to filter all APM locations:
Name | Type | Description |
---|---|---|
locationType | string |
If applied, only locations in the specified radius from these gps coordinates are returned.
|
radius | number |
Radius in meters to return only locations within a selected radius from given GPS location. Ignored if latlng is not present.
|
requiredSize | number |
Return only locations that can accept a package of your requiredSize.
|
locationType | string |
Return only locations with given a type. If not present, filter is not applied.
|
See an example of a successful integration:
GET api/v1/ destinations
curl X ‘GET’\
‘.../destinations\
-H 'accept: application/json'
Status Code 200
{
"data": [
{
"id": "string",
"type": "apm",
"image": "https://via.placeholder.com/150",
"lat": "48.78081955454138",
"lng": "12.446962472273063",
"title": "1842 - Building SIVEN, Hladilnika",
"name": "1842 - бул. Черни връх №47А, София, 1407",
"addressLine1": "bul. Cherni Vrah 47A",
"addressLine2": "string",
"postalCode": "1407",
"country": "BG",
"note": "You can find it behind the pet shop"
}
]
}
Alternatively, refer to section 4 for a Java Script snippet you can embed into your web to display all available APMs via a pop-up/iframe widget, or for a brief description of a successful custom map integration.
id
When requesting a delivery, you will refer to these records by id-More commonly:
locationId
Further responses, which might occur:
Error Code
400
The server cannot or will not process the request due to something that is perceived to be your error (e.g., malformed request syntax, invalid request message). You are to modify the request before sending it again.
401
Not Authorized. You are either using an expired Access token to access the data or trying to initialize Auth session with invalid data.
403
Account disabled. Your account had been disabled, contact support.
3.4 Request a delivery /delivery requests
Use this call to order a delivery of a parcel (or multiple parcels). This is the main call you will be using to create any type of delivery requests.
Once a successful request for delivery is made:
- (optional) We will send you an email notifying you of a successful delivery request creation with a PDF label attached. Parameter notifyOnAccepted needs to be populated for this function (See Appendix 6.3).
- (Described below) Alternatively, you should fetch the PDF label for each parcel using the GET/parcels/{id}/label.pdf call print it and stick it to the parcel(s).
- We will send a courier to pick up the parcel(s) at the agreed pick up times.
- We will also notify the customer that
- We have received a delivery order and that a parcel will be delivered to them.
- We have successfully delivered their parcel(s) to the specified destination APM with the necessary details for collecting the parcel(s).
See an example of a successful integration:
POST api/v1/ delivery requests
{
"orderNumber": “string”,
"invoiceValue": “25.50”,
"paymentMode":”prepaid”,
”amountToBeCollected": “0.00",
"allowReturn”: true,
"origin”:{
"contactNumber":“+3598XXXXXXXX”,
"contactEmail”: “[email protected]”,
"contactName": “Ivan Ivanov",
"locationId":”string”
},
“destination”:{
"contactNumber": "+3598XXXXXXXX”,
"contactEmail”: “[email protected]”,
"contactName” "Ivan Petrov",
"locationId":”string”
},
"items”: [
{
"id": “string”,
"name": “Smartphone”
"value”: “3.45”,
"weight”: 0
}
]
}
items: weight
If the parcel weight is unknown, pass 0.
These parameters are the main identifiers of pick up & delivery locations:
origin: locationId
The warehouse where the parcel will be picked up from.
destination: locationId
Automatic Parcel Machine (APM) where the parcel will be delivered to.
Also,
do not forget to pass us the following personal details with each delivery request:
Sender:
- Name
Recipient:
- Name
- Phone number
Status Code 200
{
"referenceNumber":”string”,
"parcels”:[
{
"id":”string”
}
]
}
Note:In the above example, the “items correspond to parcels, but item ID is eshop unique ID (reference number, if you will). If you do not have unique ID of each item then create it by order number combined with sequential item number or any other way. Whileparcel ID (parcels ID)is BoxNow internal unique ID used further to refer to the parcel.
For sending from APM you can use origin any APM and destination specific APM.
For delivering to APM where customer will pick up from the same APM you can use both origin and destination location any-APM.
Further responses, which might occur:
Error Code
400
Bad Request. The server cannot or will not process the request due to something that is perceived to be your error (e.g., malformed request syntax, invalid request message). You are to modify the request before sending it again.
401
Not Authorized. You are either using an expired Access token to access the data or trying to initialize Auth session with invalid data.
403
Account disabled. Your account had been disabled, contact support.
3.5 Fetch a PDF label /parcels/{id}/label.pdf
Use this call to request a .pdf file with a label you shoold print a stick onto each parcel.
Only this parameter is available to you:
Name | Type | Description |
---|---|---|
id | string | Unique parcel number returned to you by method /delivery-requests |
See an example of a successfol integration:
GET /api/v1/ parcels
curl -X 'GET' \
‘.../parcels/{id}/label.pdf’ \
-H 'accept: application/pdf’
Status Code 200
.pdf file with the corresponding label
To print all PDF labels at once for your order, you can replace {id} with {orderNumber}:
GET /api/v1/ delivery requests
curl -X 'GET' \
‘.../delivery-requests/{orderNumber}/label.pdf’ \
-H 'accept: application/pdf’
Step 4: Destination Map (Widget /Custom
4.1 Widget Integration
As an alternative to integrating our API, you can embed our ready made widget into your check out page. This widget is communicating with our API and includes the same data you can access via GET /api/v1/ destination.
How to install BoxNow Map Widget:
- Paste the BoxNow Map Widget JavaScript code into the checkout page (or any other page where you want to display the BoxNow Map Widget).
- Create new HTML button with class attribute boxnow-widget-button to open BoxNow Map Widget. For example:
<a href="javascript:;" class="boxnow-widget-button">Open widget</a>
- Create function for accept data from selected locker (id, address, name, etc.).
BoxNow Map Widget (Javascript Code):
<div id="boxnowmap"></div>
<script type="text/javascript">
var _bn_map_widget_config = {
partnerId: 123,
parentElement: "#boxnowmap"
afterSelect: function(selected){
alert(selected.boxnowLockerPostalCode);
alert(selected.boxnowLockerAddressLine1);
alert(selected.boxnowLockerId);
}
};
(function(d){var e = d.createElement("script");e.src = "https://widget-cdn.boxnow.bg/map-widget/client/v5.js";e.async = true;e.defer = true;d.getElementsByTagName("head")[0].appendChild(e);})(document);</script>
Note:The most important is variable _bn_map_widget_config. With this variable you can setup all required options , as shown below.
Name | Usage | Description |
---|---|---|
parentElement | required |
Please fill CSS selector for Map Widget container. For example, just create <div id="boxnowmap"></div> and fill #boxnowmap. The BoxNow map widget will be placed inside this element. |
afterSelect | required for type:iframe and type:popup |
Function that is triggered when the lock is selected. Included one parameter (object) contains all information about locker (properties boxnowLockerPostalCode, boxnowLockerAddressLine1 and boxnowLockerId are the most important). |
partnerId | optional | Please use your partnerId |
type | optional | Use iframe, popup or navigate. Defaolt is iframe. |
gps | optional | Use it if you want to change the user's location request immediately after displaying the map. Possible options are true or false. Defaolt is true. |
autoclose | optional | Use it when you want to change what happens after you select a locker. For type:iframe, the defaolt value is true, which means that the map will be hidden when the locker is selected. For type:popup, autoclose is always true. The possible values are true or false. The defaolt value is true. |
**For more integration examples you can refer to: widget-v4.boxnow.bg/developers
4.2 Custom Map Integration
Our widget takes advantage of Google Maps Javascript API: https://developers.google.com/maps/apis-by-platform
By calling GET /api/v1/ destination, you can obtain longitude as variable lng and latitude as variable lat of each delivery location, that you can then pass to the Google Maps API to display the location on the map:
https://developers.google.com/maps/documentation/javascript/adding-a-google-map- id for locker ID
- image for a url with image of the locker
- name
- addressLine1 and addressLine2
- postalCode
- note for a detailed description of the lockerlocker’s location.
Step 5: Troubleshooting
Description of error codes for 400 Unprocessable entity responses:
Error Code P400
Invalid request data. Make sure you are sending the request according to the documentation.
Error Code P401
Invalid request origin location reference. Make sure you are referencing a valid location ID from Origins endpoint or valid address.
Error Code P402
Invalid request destination location reference. Make sure you are referencing a valid location ID from Destinations endpoint or valid address.
Error Code P403
You are not allowed to use AnyAPM-SameAPM delivery. Contact support if you believe this is a mistake.
Error Code P404
Invalid import CSV. See error contents for additional info.
Error Code P405
Invalid phone number. Make sure you are sending the phone number in foll international format, e.g. +30 xx x xxx xxxx.
Error Code P406
Invalid compartment/parcel size. Make sure you are sending one of required sizes 1, 2 or 3 ( Medium or Large). Size is required when sen ding from AnyAPM directly.
Error Code P407
Invalid country code. Make sure you are sending country code in ISO 3166-1 alpha-2 format, e.g. BG.
Error Code P410
Order number conflict. You are trying to create a delivery request for order ID that has already been created. Choose another order ID.
Error Code P411
You are not eligible to use Cash-on-delivery payment type. Use another payment type or contact our support.
Error Code P420
Parcel not ready for cancel. You can cancel only new, undelivered, or parcels that are not returned or lost. Make sure parcel is in transit and try again.
Error Code P430
Parcel not ready for AnyAPM confirmation. Parcel is probably already confirmed or being delivered. Contact support if you believe this is a mistake.
Contact us:
If you are having troubles integrating our API into your online store based on the current documentation reach out to us at [email protected]
Notes:
- Testing plugin with stage Api keys.
- Select stage locker: Test Locker 1, locker id: 5365
- When a new order is completed we will automatically send you a PDF shipping label, if you've passed "NotifyOnAccepted" paratmeter with a valid e-mail address.
- (POST) Authorization: {baseURL}/api/v1/auth-sessions
- (GET) Origins: {baseURL}/api/v1/origins
- (GET) Destinations: {baseURL}/api/v1/destinations
- (POST) Delivery-request: {baseURL}/api/v1/delivery-requests
- (GET) Parcel label: {baseURL}/api/v1/parcels/{id}/label.pdf
- (GET) Parcels: {baseURL}/api/v1/parcels
- (POST) Cancel parcel: {baseURL}/api/v1/parcels/{id}:cancel