Pluplus API Documentation


Introduction

The Pluplus API is a RESTful JSON service which allows simple yet powerful integration with the Pluplus service, including: The root API URL is https://api.pluplus.com/v1.4/.

Flow (more details below)

  1. Create an Estimate: This returns a price, id and a delivery window. Estimates expire 10 minutes after being created, so if you try to use it to create a Delivery and it has expired, you will get a 410 Estimate Expired
  2. Create a Delivery: Use the Estimate ID to create a Delivery. This returns a tracking code, along with other information.

Authentication and Security

All requests to the API must be made over SSL using the HTTPS protocol to ensure security.
All requests, except where stated otherwise, must be authenticated preemptively using HTTP Basic authentication as a header with the username as "api" and the password as the API key. In order to get your API key please send an email to hallo@pluplus.nl with your contact information. Please note that this key must be kept private, so don't embed it in any client side code.

Content-Types

Make sure to set the Content-Type of your requests to application/json, as this is a RESTful API and should only respond to the Content-Type you use. As this API only supports JSON, you will get an error if you make a request with a different Content-Type, or if one is not given (unless you are using GET).

Errors

In the event of the API returning an error, it will return a relevant status code (see below), along with a response containing the following information.

NameTypeExampleComments
message String "The API encountered a fatal error" The error message
kind String (one of PPException) PPFatalException The type of exception that was raised.

Example
{
  "error": {
    "message": "The API encountered a fatal error",
    "kind": "PPFatalException"
  }
}

The kind will be one of the ones given below. Check the message for more detailed information on the specific cause of the error.

Kind Meaning
PPAPIException There was a generic problem with the API. See the error message for more information.
PPAuthException Either you are not permitted to access, create or do something, or there was a problem authenticating you with the API.
PPBadWaypointException Either the given Waypoint(s) was invalid, or there was another error with fetching location information.
PPEstimateExpiredException The given Estimate has expired, and a new one must be created.
PPFatalException Something went internally wrong with the API. Please contact us if you get this error.
PPNotFoundException The requested resource could not be found
PPUndeliverableException None of the given Retailers can deliver to the customer or the Pluplus service cannot deliver it for some other reason.
PPURIException The URI the request was made to is invalid, or the incorrect method was used. Please check it is correct and try again.

HTTP Status Codes

The server will respond to each request with a relevant HTTP Status Code and description.

Successes

Errors

The request body will contain more information. Either an array of formerrors or an error object.

Basic Structures

The following structures are the foundations for the Pluplus API. If the information provided when creating them is not satisfactory, the API will return a HTTP 400 Bad Request, and the request body will contain a JSON array of formerrors.

Waypoint

Waypoints hold information about a location which includes the following: When creating a Waypoint for an Estimate, only the postcode is required. However when creating a Waypoint for a Delivery, ALL fields (with the exception of Address Line 2) are required.
NB: When routing, the Pluplus service will check to see if the given Waypoint is valid, and if not will return a 400 Invalid Waypoint, and raise a PPBadWaypointException.
Example
{
  "address":  "Elleboogsteeg 1",
  "city":     "Amsterdam",
  "postcode": "1012AM"
}

Co-ordinates

Co-ordinates are used internally for Waypoints to get accurate location points: Example
{
  "latitude":  52.375590,
  "longitude": 4.901490,
  "altitude":  null // Currently unused
}

Dimensions

Dimensions are simple structures containing the following decimal fields: Example
{
  "height": 9.0,
  "width":  15.5,
  "length": 20
}

Item

Represents a single Item in the package, containing the following information: Example
{
  "name":       "MacBook Pro",
  "quantity":   3,
  "price":      999.99,
  "sku":        "123456",
  "dimensions": {
    "height": 8.26,
    "width":  50.8,
    "length": 50.8
  },
  "weight":   3.5
}

Recipient

A Recipient is the person that the package is addressed to. It contains the following information: Please note that ALL fields are required.
Example
{
  "title":      "Mr",
  "first_name": "Peter",
  "surname":    "Jansen",
  "mobile":     "06 12345678",
  "email":      "pjansen@example.com"
}

Retailer

A Retailer is one store belonging to a business which can deliver goods to customers with Pluplus. It contains the following information

The Deliverable Region is a list of postcode prefixes (four digit numbers) to which the store can deliver to using Pluplus. This allows the Pluplus API to select the best store to deliver a package when an Estimate and delivery is created.

The pricing matrix is a set of values used to calculate the postage cost of items. Pluplus uses an algorithm to calculate prices which is based on distance, the package dimensions and weight, and the load on the Pluplus network at the given time.

The serving field is a property of the Retailer which tells the API whether or not it should respond to requests for this Retailer. It will be true if Pluplus can serve the Retailer and false if not.

Example
{
  "id": "1",
  "created_by": 1,
  "retailer_identifier": "shop001",
  "name": "Example Shop Amsterdam",
  "telephone": "00000000000",
  "location": {
      "address": "de Vlugtlaan 159",
      "address_line_2": null,
      "city": "Amsterdam",
      "postcode":" 1234 AB",
      "coordinates": {
          "longitude": 1.0000000,
          "latitude": 2.0000000,
          "altitude": null
      }
      "origin_retailer_id": null,
      "origin_retailer_identifier": null,
  },
  "deliverable_region": "1000,1111,1234,2222,3333,4444",
  "pricing_matrix": {
    "kmprice": "0.67",
    "minprice": "3.99",
    "maxprice": "9.99"
  },
  "serving": true
}

Test URI

The Pluplus API provides a test URI for your convenience when initially getting set up. To use it, simply GET /test.
If there are any errors, you will be given them, otherwise you will get the below result informing you everything went okay.

GET https://api.pluplus.com/v1.4/test HTTP/1.1
Authorization: Basic YXBpOjEyMzQ1Ng==
{
  "success": true
}

Estimates

You create Estimates to get the estimated cost for a delivery and get a delivery window.

The more information you provide, the more accurate the estimate will be, so please try and provide as much information as you can to the Estimate.

Any unroutable addresses will result in a 503 Service Unavailable response.

Delivery Windows

A delivery window is a time span of 2 hours which the package is to be delivered. It is an array of the earliest time and the latest time as DateTime objects.

Example
[
  {
    "date":	         "2014-02-15 18:01:12",
    "timezone_type": 3,
    "timezone":      "Europe/Amsterdam"
  },
  {
    "date":	         "2014-02-15 20:01:12",
    "timezone_type": 3,
    "timezone":      "Europe/Amsterdam"
  }
]

Estimates have a life of 10 minutes from the time they are created. If you try to use an expired Estimate to create a Delivery, a 410 Estimate Expired will be returned, and you will have to create a new Estimate.
In your application, displaying a countdown to the user during checkout may be a good idea.

Also, keep in mind that is is just an estimate, and the cost may fluctuate when the Delivery is created. This is why we recommend that you provide as much information as possible to the Estimate to get an accurate price.

Creating an Estimate

Perform a POST request to the Estimates endpoint, passing the required parameters (below) as the body of the request.

To communicate information about the origin and destination addresses, it is recommended to provide an array of origin_retailer_identifiers (see above) which are stocking the item. The Pluplus API will determine the best Retailer to deliver the item and give an Estimate based on the distance from that store to the customer.
In the response there will be a origin_retailer_identifier field with the chosen store to deliver the item.

POST /estimates

Creates a new Estimate Request Body:
NameTypeExampleComments
origin_retailer_identifiers Array of retailer_identifier ['shop001', 'shop002'] An array of the stores that can deliver the item.
origin_retailer_id Integer 1 A single retailer_id instead of an array of origin_retailer_identifiers (deprecated, provided for backwards compatibility.
destination Waypoint Example required
items Array of Items Example required
Returned status codes:
Example
POST https://api.pluplus.com/v1.4/estimates HTTP/1.1
Content-Type: application/json
Authorization: Basic YXBpOjEyMzQ1Ng==
{
  "origin_retailer_identifiers": [
    "shop001", "shop002", "shop003"
  ],
  "destination":  {
    "address":  "Elleboogsteeg 1",
    "city":     "Amsterdam",
    "postcode": "1012AM"
  },
  "items": [
    {
      "price":       13.99,
      "dimensions": {
        "height": 3,
        "length": 30,
        "width":  15
      },
      "name":     "Soldaat van Oranje",
      "quantity": 2,
      "sku":      "GOR004983077",
      "weight":   0.75
    },
    {
      "price":       999.99,
      "dimensions": {
        "height": 8.26,
        "length": 50.8,
        "width":  50.8
      },
      "name":       "MacBook Pro",
      "quantity":   3,
      "sku":        "123456",
      "weight":     3.5
    }
  ]
}
    
Response
HTTP/1.1 201 Created
{
  "estimate": {
    "id": 123,
    "cost": 10,
    "distance": 2,
    "created_by": 1,
    "origin_retailer_identifier": "shop002",
    "pickup_at": {
      "date":          "2014-02-16 18:00:00",
      "timezone":      "Europe/Amsterdam",
      "timezone_type": 3
    }
    "delivery_window": [
      {
        "date":          "2014-02-16 19:00:00",
        "timezone":      "Europe/Amsterdam",
        "timezone_type": 3
      },
      {
        "date":          "2014-02-16 20:00:00",
        "timezone":      "Europe/Amsterdam",
        "timezone_type": 3
      }
    ],
    "destination": {
      "address":            "Elleboogsteeg 1",
      "address_line_2":     null,
      "city":               "Amsterdam",
      "coordinates":        null,
      "origin_retailer_id": null,
      "postcode":           "1012AM"
    },
    "expiry": {
      "date":          "2014-02-16 18:10:00",
      "timezone":      "Europe/Amsterdam",
      "timezone_type": 3
    },
    "items": [
      {
        "dimensions": {
          "height": 3,
          "length": 30,
          "width":  15
        },
        "name":     "Soldaat van Oranje",
        "price":    13.99,
        "quantity": 2,
        "sku":      "GOR004983077",
        "weight":   0.75
      },
      {
        "dimensions": {
          "height": 8.26,
          "length": 50.8,
          "width":  50.8
        },
        "name":      "MacBook Pro",
        "price":     999.99,
        "quantity":  3,
        "sku":       "123456",
        "weight":    3.5
      }
    ]
  }
}

Retrieving an Estimate

GET /estimates/:id

Retrieves an Estimate by its id.
Example
GET https://api.pluplus.com/v1.4/estimates/654321 HTTP/1.1
Authorization: Basic YXBpOjEyMzQ1Ng==

The response body will be identical to the result of a POST request (see above).

Returned status codes:

Deliveries

Creating a new delivery

To create a delivery, perform a HTTP POST with the required parameters (below) in the body as JSON

You must first create an Estimate, and then reference it by its id for the estimate_id of the Delivery.

If only the postcode was provided when creating the Estimate, all the required fields for the destination Waypoint must be present when creating a Delivery.

Please note that any parameters specified below will overwrite the ones that the system currently has on file from the Estimate.

Upon creation, the API will return a tracking_code, which should be emailed to the customer upon successful checkout appended to the URL 'http://www.pluplus.com/track.php?id='. This will allow the customer to track their parcel on its way to them during transit.

Example
http://www.pluplus.com/track.php?id=PP5300fe1c40720

POST /deliveries

Create a new Delivery
Request Body:
NameTypeExampleComments
estimate_id Integer 1 Required.
origin_telephone String 020 6046048 Optional. Phone number for the retailer / sender.
origin_comments String "Use the side door" Optional. Any special instructions for the collection.
origin_signature_required Boolean true Optional. Require a signature from the person the delivery was collected from. Defaults to false.
signature_required String any_signature, leave_at_door or recipient_signatutre Optional. Require a signature from the person the delivery was collected from. Defaults to false.
destination Waypoint Example Required if a fully qualified Waypoint was not used when creating the Estimate.
destination_comments String "Leave behind bin if nobody is in" Optional. Any special instructions for the delivery.
order_number String "123456789" Required. You, the retailer's order number.
recipient Recipient Example Required.
minimum_age Integer 16 Optional. Requires the date of birth of the recipient. Not compatible with leave_at_door. Defaults to 0.
Returned status codes Example Delivery Creation
POST https://api.pluplus.com/v1.4/deliveries HTTP/1.1
Content-Type: application/json
Authorization: Basic YXBpOjEyMzQ1Ng==
{
  "estimate_id":     123,
  "origin_comments": "Use the side door",
  "recipient": {
    "title":      "Mr",
    "first_name": "Peter",
    "surname":    "Jansen",
    "mobile":     "06 12345678",
    "email":      "pjansen@example.com"
  },
  "order_number":       "8671F2",
  "minimum_age":        18,
  "signature_required": "recipient_signature"
}
Response
HTTP/1.1 201 Created
{
  "delivery": {
    "id": 1,
    "created_by": 1,
    "estimate_id":  123,
    "cancelled_at": null,
    "cost":         10,
    "weight":       4.25 // Total weight
    "order_number": "8671F2",
    "pickup_at": {
      "date":          "2014-02-16 18:06:20",
      "timezone":      "Europe/London",
      "timezone_type": 3
    },
    "deadline_at": {
      "date":          "2014-02-16 20:06:20",
      "timezone":      "Europe/Amsterdam",
      "timezone_type": 3
    },
    "delivered_at": null,
    "origin_retailer_id": 6,
    "origin_comments": "Use the side door",
    "origin_telephone": "020 6778899",
    "origin_signature_required": false,
    "destination": {
      "address": "Elleboogsteeg 1",
      "address_line_2": null,
      "city": "Amsterdam",
      "coordinates": {
        "altitude": null,
        "latitude": 52.3756307,
        "longitude": 4.9011832
      },
      "postcode": "1012AM"
    },
    "destination_comments": null,
    "signature_required": "recipient_signature",
    "minimum_age":  18,
    "items": [
      {
        "dimensions": {
          "height": 3,
          "length": 30,
          "width":  15
        },
        "name":     "Soldaat van Oranje",
        "price":    13.99,
        "quantity": 2,
        "sku":      "GOR004983077",
        "weight":   0.75
      },
      {
        "dimensions": {
          "height": 8.26,
          "length": 50.8,
          "width": 50.8
        },
        "name":     "MacBook Pro",
        "price":    999.99,
        "quantity": 3,
        "sku":      "123456",
        "weight":   3.5
      }
    ],
    "recipient": {
      "title":      "Mr",
      "first_name": "Peter",
      "surname":    "Jansen",
      "email":      "pjansen@example.com",
      "mobile":     "06 12345678"
    },
    "status":        "unassigned",
    "tracking_code": "PP5300fe1c40720",
  }
}
IMPORTANT:

Upon successfully creating a Delivery, you MUST display a Google map to the user at the end of the checkout. Your own implementation may vary, but below is an example of a Javascript map being displayed in its most simple form.
You can see this example file at http://www.pluplus.com/docs/exampleMap.html. Simply view the page source (Ctrl-U in Firefox and Chrome) to see the code used and adapt it to your needs.

Retrieving Deliveries

GET /deliveries/:tracking_code

Retrieves a Delivery by its tracking code.
Example
GET https://api.pluplus.com/v1.4/deliveries/PP5300fe1c40720 HTTP/1.1
Authorization: Basic YXBpOjEyMzQ1Ng==

The response will be the same as the response you get when you create a new Delivery, as above.

Returned status codes

Listing Deliveries

GET /deliveries

Return a list of deliveries associated with the currently authenticated account
For Example:
GET https://api.pluplus.com/v1.4/deliveries HTTP/1.1
Authorization: Basic YXBpOjEyMzQ1Ng==

Retailers

Retailers are used to create Estimates and Deliveries. They negate the need to provide the full address of the origin each time, and hold other information such as telephone numbers and exact co-ordinates. They are identified using retailer_identifiers, which you decide when you are creating them.

List Retailers

List all the retailers on your account

Example
GET https://api.pluplus.com/v1.4/retailers HTTP/1.1
Authorization: Basic YXBpOjEyMzQ1Ng==
{
  "retailers": [
    {
      "id": "6",
      "created_by": 1,
      "retailer_identifier": "shop001",
      "name":      "Henk Schoenen Winkel",
      "telephone": "020 6778899",
      "location": {
        "address":        "Ferdinand Bolstraat 110",
        "address_line_2": null,
        "city":           "Amsterdam",
        "postcode":       "1072 LR"
        "coordinates": {
          "latitude":  52.3537733,
          "longitude": 4.8906656,
          "altitude":  null
        },
        "origin_retailer_id": null,
        "deliverable_region": "1000,1111,1234,2222,3333,4444",
        "pricing_matrix": {
          "kmprice": "0.67",
          "minprice": "3.99",
          "maxprice": "9.99"
        },
        "serving": true
      }
    }
  ]
}
Returned Status Codes

Retailers are read-only. If you would like to change something about a Retailer, please contact support.

Accounts

In the responses you have seen above you will notice a created_by field in most of the responses. This is an integer representing the Account which created the item. To find out which ID your Account is, simply send a GET request to /account.
This is a read-only endpoint used for reference only.
NB: API keys are not returned for security reasons.

Example
GET https://api.pluplus.com/v1.4/account HTTP/1.1
Authorization: Basic YXBpOjEyMzQ1Ng==
{
  "account": {
    "id": "1"
    "level": "2" // This means the Account is a standard user
    "note": "Example Key"
  }
}

Getting In Touch

Should you have any queries or problems with the API, please send an email to hallo@pluplus.nl.