NAV

Introduction

Welcome to the Cubyn API! This API is organized around REST over HTTPS.

Get your API Application Key in your cubyn account settings app.cubyn.com. If you need help implementing the Cubyn API on your website, do not hesitate to shoot us an email at api@cubyn.com!

We also provide a Sandbox environment where you will be able to test drive your integration before going live. See Using Cubyn Sandbox

All our endpoints speak JSON fluently.

2 simple steps

Step Description API METHOD
STEP 1 Create as many parcels as you want POST /parcels
STEP 2 Create a collect POST /collects

Then Cubyn does the magic!

Authentication

Try this with your applicationKey

curl https://api.cubyn.com/v2 \
    -H 'X-Application: my-api-key'

RESPONSE

{
  "version": "0.0.3",
  "name": "cubyn.api",
  "description": "Please visit developers.cubyn.com for further information on this API.",
  "auth": {
    "application": {
      "name": "Mathieu Lemaire",
      "createdAt": "2015-08-19T10:18:13.000Z",
      "updatedAt": "2015-08-19T10:18:14.000Z"
    },
    "user": {
      "id": 706293859,
      "firstName": "Mathieu",
      "lastName": "Lemaire",
      "phone": "0664543537",
      "createdAt": "2015-08-19T10:18:13.000Z",
      "updatedAt": "2015-08-19T10:18:13.000Z",
      "email": "mathieu@cubyn.com"
    }
  }
}

All endpoints except GET /v2 require a proper authentication. Your API credentials will consist of an applicationKey. Authentication is done simply by adding an X-Application header containing your API Key.

Beware: this key carries many privileges - so keep it secret!

Step 1: Create parcels

REQUEST (curl)

curl https://api.cubyn.com/v2/parcels \
    -H 'X-Application: my-app-key' \
    -H 'Content-Type: application/json' \
    --data '{"firstName":"Sophie","lastName":"Martin","address":{"line1":"3 place de la Republique","zip":"69002","city":"Lyon","country":"France","additionalInformation":"code 9898"},"objectCount":2}'

RESPONSE

{
  "id": 673847167,
  "status": "CREATED",
  "address": {
    "line1": "3 place de la Republique",
    "zip": "69002",
    "city": "Lyon",
    "country": "France",
    "additionalInformation": "code 9898"
  },
  "firstName": "Sophie",
  "lastName": "Martin",
  "deliveryMode": "standard",
  "deliverySigned": false,
  "objectCount": 2,
  "insurance": 250,
  "applcationId": "92390180134",
  "shipperId": "2932983427982",
  "collectId": null,
  "barcode": null,
  "qrCode": null,
  "createdAt": "2015-08-18T16:26:08.000Z",
  "updatedAt": "2015-08-18T16:26:08.000Z"
}

Once we have come to collect all your PREPARED parcels, their statuses are changed to PICKED after which they cannot be updated nor deleted.

POST /v2/parcels

Field Type Details
address * <Address> defines the recipient address (see format)
items [<Item>] array of items contained in this parcel (see format)
firstName string (of recipient)
lastName string (of recipient)
organizationName string Company / Organisation name One of firstName, lastName and organizationName has to be defined
deliveryMode Enum<string> shipping mode allowed: standard, express or relay
deliverySigned boolean should shipment be handed against signature
relayPickupRef string pickup point identifier (only if deliveryMode is relay) (see handling relay)
objectCount number how many objects will be shipped to that recipient within the same parcel default: 1
phone string (of recipient)
email string (of recipient)
value number overall value of parcel
insurance number all parcels are insured up to €250 by default, you can choose to insure a parcel above that amount example: 300.00
orderRef string your own reference (such as prestashop order id) you can use to track shipping within your own workflows

Step 2: Create a collect

REQUEST (curl)

curl https://api.cubyn.com/v2/collects \
    -H 'X-Application: my-app-key' \
    -H 'Content-Type: application/json' \
    --data '{ \
        "address":{"line1":"27 rue du Chemin Vert","zip":"75011","city":"Paris","country":"France"}, \
        "pickupAt":"2015-08-19T08:00:00.000Z", \
        "volumeCategory":"STANDARD" \
    }'

RESPONSE

{
  "id": 634207757,
  "status": "CREATED",
  "address": {
    "line1": "27 rue du Chemin Vert",
    "line2": "2nd floor",
    "zip": "75011",
    "city": "Paris",
    "country": "France"
  },
  "pickupAt": "2015-08-19T08:00:00.000Z",
  "volumeCategory": "STANDARD",
  "shipperId": "293427561",
  "applicationId": "84935791",
  "createdAt": "2015-08-18T12:49:30.000Z",
  "updatedAt": "2015-08-18T12:49:30.000Z"
}

A collect is both an event and an entity:

When a user creates a collect, it notifies us that we must come to collect that user’s parcels. When the status of a collect passes from CREATED to CONFIRMED, it means the we have assigned a messenger to that collect for the specified pickupAt parameter.

POST /v2/collects

Field Type Details
volumeCategory * Enum<string> depends on the size / volume of the objects allowed: SMALL, STANDARD, LARGE
contactName * String who will be receiving our courier
contactPhone * String mobile phone number of the local contact
pickupAt IsoDate Has to be during working hours. (see Timeslots) default: the first slot available
address <Address> where to pickup the objects (see format) default: shipper’s address

Timeslots

REQUEST (curl)

curl https://api.cubyn.com/v2/timeslots \
    -H 'X-Application: my-app-key'

REPONSE (the collect)

[
    {
        "asap": true,
        "date": "2015-07-21T07:00:00.563Z",
        "duration": 120
    },
    {
        "asap": false,
        "date": "2015-07-21T08:00:00.563Z",
        "duration": 120
    },
    {
        "asap": false,
        "date": "2015-07-21T09:00:00.563Z",
        "duration": 120
    },
    {
        "asap": false,
        "date": "2015-07-22T07:00:00.563Z",
        "duration": 120
    }
]

This will list the next 2-hour slots available for pick-up in France timezone. The results can be used to suggest collecting hours to the end user.

In case the collect can happen as soon as submitted (within the next 2 hours), the asap property is set to true.

GET /v2/timeslots

API Reference

Find here all API endpoints available.

Addresses

This is the address model used in Shipper, Collect and Parcel objects.

Field Type Details
line1 * string (max length: 35 chars.)
line2 string (max length: 35 chars.)
zip * string city’s zip code
city * string city’s name
state string required for US
country * string
additionalInformation string any detail (floor, code, …) needed by the carrier to deliver / messenger to pick. (max length: 35 chars.)

Items

This is the item model used in to specify an object contained in a Parcel.

Field Type Details
name * string
count * string
reference string sku
value * string unit price
width string (in meters)
height string (in meters)
depth string (in meters)
weight string weight (in g)

Users

Method Path Description
GET /v2/users Get user currently connected
GET /v2/users/:id Read user details Response will include collects sub-documents
PUT /v2/users/:id Edit a user

Collects

Method Path Description
GET /v2/timeslots List next timeslots available for pick-up
GET /v2/collects List all your collects
POST /v2/collects Create a new collect
GET /v2/collects/:id Read details of this collect Response will include shipper and may include parcels sub-documents
PUT /v2/collects/:id Update this collect will fail if not in the CREATED status
DELETE /v2/collects/:id Delete this collect will fail if not in the CREATED status

Parcels

Method Path Description
GET /v2/parcels List all your parcels
POST /v2/parcels Create a new Parcel
GET /v2/parcels/:id Read details of this parcel Response will include collect sub-document
PUT /v2/parcels/:id Edit a parcel will fail if the collect is not in CREATED or PREPARED status
DELETE /v2/parcels/:id Delete a parcel will fail if the collect is not in the CREATED status

Attachments

Method Path Body Description
GET /v2/attachments List all your attachments
GET /v2//attachments?filters[parcelId]=:id List all attachments of this parcel
POST /v2//attachments { “parcelId”: “:id” } Upload a new attachment on this parcel
GET /v2/attachments/:id Read details of this attachment
DELETE /v2/attachments/:id Delete this attachment

Guides

Understanding Cubyn statuses

Collects, Parcels and their Attachments all have a status field.

Collect statuses

Status Description
CREATED Collect has been created and is still editable (draft mode)
CONFIRMED Collect is automatically confirmed at the beginning of the chosen timeslot
PICKED Collect has been collected by a messenger

Parcel statuses

Status Stakeholder Description
CREATED Shipper Parcel has been created and is still editable (draft mode)
PREPARED Shipper / Cubyn A QrCode has been associated to this parcel. Parcel is now ready to be collected
PICKED Cubyn Parcel has been collected by a Cubyn messenger
SHIPPED Cubyn Parcel is now in carrier hands
CARRIER_IN_TRANSIT Carrier Parcel is on the way, transitting within carrier network
CARRIER_OUT_FOR_DELIVERY Carrier Carrier is ready to deliver the parcel
CARRIER_FAILED_ATTEMPT Carrier Carrier attempted to deliver the parcel but will try again
CARRIER_DELIVERED Carrier (final status) Parcel delivered successfully
CARRIER_EXCEPTION Carrier (final status) Parcel not delivered / returned to shipper

Attachment statuses

Status Description
IN_PROGRESS Attachment is being downloaded or processed by our servers
SUCCESS Attachment is ready to be printed
PRINTED Attachment has been printed and packed in your parcel

Parcel attachments

REQUEST (curl)

curl https://api.cubyn.com/v2/attachments \
    -H 'X-Application: my-app-key' \
    -F name=my-file.pdf \
    -F parcelId=983264786 \
    -F 'file=@/path/to/my-file.pdf'

RESPONSE

{
    "id":923743672,
    "type":"OTHER",
    "status":"SUCCESS",
    "name":"my-file.pdf",
    "file": {
        "url": "https://attachment.domain/path/to"
    },
    "pageCount":1,
    "fileSize":24218,
    "createdAt":"2016-08-23T15:27:54.000Z",
    "updatedAt":"2016-08-23T15:27:54.000Z"
}

Parcel attachments are a convenient way to have Cubyn print and pack documents in your parcels. e.g. Invoices, User guides, Ads, … Parcel attachments have to be uploaded before you create the Collect object.

Maximum allowed size: 2Mo. Only PDF files are supported.

You can also list and delete attachments as described in API Reference.

Endpoint

POST /v2/attachments

Tracking page

Cubyn offers a unified tracking page that is common to every carrier we support. We highly recommend using it:

To do so:

1. Build your Cubyn tracking number

CUB{{your parcel id}}

2. Build your Cubyn tracking page

http://track.cubyn.com/{{your tracking number}}

Notifications via webhooks

Use webhooks to subscribe to events related to parcels you created.

By providing us with a webhook, you will be notified everytime a parcel sees its status change. This allows you to take the appropriate action in the shortest delay, such as informing your customers that their product has been shipped.

Enabling webhooks

To activate webhooks for your account, please shoot us an email at api@cubyn.com with:

Webhook event types

A webhook call will be triggered in each of those events:

Event Description
parcel:deleted parcel has been deleted
parcel:picked parcel goes from being PREPARED to being PICKED.
parcel:carrier-status:changed parcel transits within the carrier network.

Securing your webhook

A webhook creates a potential backdoor on your system, we thus recommend:

Backoff webhook attempts

If your server responds with a HTTP 500 status, our servers will attempt to replay the request up to 3 times: 1, 2, 4 minutes later.

Webhook request

A JSON payload POSTed to your webhook

{
    "event": "parcel:picked",
    "key": "my-app-key",
    "parcel": {
      "id": 673847167,
      "label": "iPhone 7",
      "status": "PICKED",
      "address": {
        "line1": "3 place de la Republique",
        "zip": "69002",
        "city": "Lyon",
        "country": "France",
        "additionalInformation": "code 9898"
      },
      "firstName": "Sophie",
      "lastName": "Martin",
      "deliveryMode": "standard",
      "objectCount": 2,
      "insurance": 250,
      "createdAt": "2015-08-18T16:26:08.000Z",
      "updatedAt": "2015-08-18T16:26:08.000Z"
    }
}

Our systems will issue POST requests to your Webhook URL with these 3 fields in the request body:

Testing your webhooks

Simply use these simple curl commands to try your webhooks -›


// parcel:deleted
curl https://<URL_WEBHOOK> -H 'Content-Type: application/json' \
--data '{ \
    "key":"<API_KEY>", \
    "event":"parcel:deleted", \
    "parcel":{"id":"<CUBYN_ID>","orderRef":"<ORDER_REFERENCE>","status":"CREATED"} \
}'

// parcel:picked
curl https://<URL_WEBHOOK> -H 'Content-Type: application/json' \
--data '{ \
    "key":"<API_KEY>", \
    "event":"parcel:picked", \
    "parcel":{"id":"<CUBYN_ID>","orderRef":"<ORDER_REFERENCE>","status":"PICKED"} \
}'

// parcel:carrier-status:changed
curl https://<URL_WEBHOOK> -H 'Content-Type: application/json' \
--data '{ \
    "key":"<API_KEY>", \
    "event":"parcel:carrier-status:changed", \
    "parcel":{"id":"<CUBYN_ID>","orderRef":"<ORDER_REFERENCE>","status":"CARRIER_DELIVERED"} \
}'

Handling Cubyn relay

Cubyn supports relay as a third delivery mode which requires a valid relayPickupRef to be set on the parcel. We recommend using our iframe to facilitate the Relay integration into your own systems.

If you do not want to integrate our iframe, please be aware that our relay offer is currently routed on Mondial Relay’s network, so relayPickupRef needs to be a valid Mondial Relay pickup point ID. Check Mondial Relay Widget to have a map of pickup points.

Important note: we only support french pickup points.

https://app.cubyn.com/tools/relay-iframe/index.html?address=[...]&callback=[...]

Field Type Details
address * string Remember to URL encode this value Address must be formatted as follows: [line1] [line2] [zip] [city] [country]
callback * string Remember to URL encode this value That URL will be given query parameters telling which pickup point the user has selected.
Field Type Details
id string This is the one and only ID you need to set on parcel.relayPickupRef.
name string Name of the pickup point
image string
openinghours string Example: MON.0700.1830-TUE.0700.1830-WED.0700.1830...
street string
city string
zip string

No page reload

shop.com/cart

<!-- This is your main checkout tunnel page. -->

<!-- You can include that iframe inside a popup for instance-->
<iframe src="https://app.cubyn.com/tools/relay-iframe/index.html?address=[...]&callback=http%3A%2F%2Fshop.com%2Fcallback">
</iframe>

<script type="text/javascript">
    window.setRelay = function(info) {
        console.log('Yeay — relay selected:', info);
    }
</script>

shop.com/callback

<!-- Once the relay is selected, the iframe will redirect to this page. -->

<script type="text/javascript">
    // call parent (out of iframe, but on same domain so that works)
    window.parent.setRelay(parseGetParams());

    function parseGetParams() {
        var vars = window.location.search.substring(1).split('&');
        var getPrms = {};
        for (var i = 0; i < vars.length; i++) {
            var pair = vars[i].split('=');
            getPrms[decodeURIComponent(pair[0])] = decodeURIComponent(pair[1]);
        }
        return getPrms;
    }
</script>

Our iframe relies on a http redirect to give you back results, thus (re)loading a new page. You can avoid this redirect by loading the map inside an iframe (in a popup for instance). Beware that cross domain scripting is not allowed. Here is a simple scenario to illustrate how to overcome this:

Using Cubyn Sandbox

Cubyn provides a Sandbox environment where you will be able to test drive your integration before going live. Ask us for a sandbox account here api@cubyn.com.

Endpoint

https://apisandbox.cubyn.com/v2

Cubyn customer interface URL

https://appsandbox.cubyn.com

Parcel recipient returns

Given a parcel, you can generate a return parcel and download its label.

Endpoint 1: create a RECIPIENT_RETURN parcel

POST /v2/parcels/:id/recipient-returns

Without any body. Replace :id by the Cubyn ID of the parcel you want to return. This will create a second parcel of type RECIPIENT_RETURN.

Endpoint 2: download its label

GET /v2/attachments?filters[type]=LABEL&filters[parcelId]=:return-id&includes[]=attachment.file

Replace :return-id by the id of the parcel returned by endpoint 1.

Notes

  1. You can only generate one return for a given parcel
  2. Returns are currently supported from France FR only parcels
  3. You cannot generate a return from a return

Handling errors

When PUTing or POSTing - in case of a validation error, our API will describe each erroneous field. Here is an example:

 

REQUEST (curl)

curl https://api.cubyn.com/v2/users/124288383 \
    -X PUT \
    -H 'X-Application: my-app-key' \
    -H 'Content-Type: application/json' \
    --data '{"email":"wrongemail.com","password":"mypassword"}'

RESPONSE

{
    "errors": [
        {
            "field": "email",
            "message": "Validation isEmail failed"
        }
    ],
    "message": "Validation error: Validation isEmail failed",
    "type": "ValidationError"
}
Code Type Description
400 BadRequestError Often missing a required parameter
400 ValidationError Some field is badly formatted or has validation errors
404 ResourceNotFoundError The requested resource does not exist
403 ForbiddenError You cannot perform that action on this resource
413 TooBigFileError The file you uploaded is too big
50X ServerError Oops - that’s for us.