Introduction
Welcome to the Sendle API!
You can use our Application Programming Interface (API) to book Sendle parcels, manage shipping, and oversee past and present orders any way you like!
example of a Sendle API call using Curl:
curl 'https://api.sendle.com/api/quote?pickup_suburb=Wonglepong&pickup_postcode=4275&delivery_suburb=Foul%20Bay&pickup_country=AU&delivery_postcode=5577&delivery_country=AU&weight_value=2.0&weight_units=kg&volume_value=0.01&volume_units=m3'
-H 'Content-Type: application/json'
Sendle API uses JSON. You can view code examples in the rightmost column.
For all examples in this guide, we will be using cURL from the command line, but you are encouraged to make requests in whichever method you are most comfortable with.
API Endpoints
The Sendle API services different tasks which can be accessed through GET, POST, or DELETE requests through specific urls.
endpoint | request | task |
---|---|---|
/api/ping | GET | Connection Test |
/api/quote | GET | Quoting |
/api/orders | POST | Booking Orders |
/api/orders/{id} | GET | View Order {id} |
/api/{label_url} | GET | View a Label |
/api/tracking/{ref} | GET | Track a Parcel |
/dashboard/prepare_form | - | Prepare Form URL |
Getting Started
Requests should be made with the following headers:
Content-Type: application/json
Accept: application/json
cURL authorization looks like:
-U "sendleAPI:42RRTjYz5Z4hZrm8XY3t4Vxt"
Before anything else, you will need to have a Sendle Account
From the Sendle Dashboard visit the Settings
tab from the sidebar. Visit your Integrations tab to get your Sendle ID
and your API Key
.
Requests to the API require the use of HTTP Basic Authentication using your account’s Sendle ID
as the user name and your API key
as the password.
Be sure to use Sendle’s sandbox environment for testing first! (See below for more)
Sandbox Server
Sendle provides access to a sandbox server at https://sandbox.sendle.com. You will need to create a new account for the sandbox server – just like you did for Sendle and set up a sandbox credit card.
Any orders created on the sandbox server will be created in the test mode, they will not result in actual consignments that can be used to send a parcel. Using a valid credit card in Sandbox will not work, so please review Stripe’s test credit card numbers (below).
Create an Account
Response Without Email Confirmation
{
"error": "precondition_failed",
"error_description": "The account associated with this API key has not yet had the email confirmed. Please check your email and confirm the account, or visit your Sendle Dashboard to resend the confirmation email."
}
Response Without Dangerous Goods Terms Accepted
{
"error": "precondition_failed",
"error_description": "The account associated with this API key has not accepted the dangerous goods terms. Please visit your Account Settings in your Sendle Dashboard to view and accept these terms."
}
To create orders with the Sendle API you must make sure you have confirmed your email address. To do this, check your inbox for the email and click the confirmation link.
You must also accept the dangerous goods terms in your Pickup Settings.
Set Up Payments
Response Without Payment Details
{
"error": "payment_required",
"error_description": "The account associated with this API key has no method of payment. Please go to your Account Settings in your Sendle Dashboard and add a payment method."
}
To use the Sendle API you need to attach a credit card in the currency you are going to be creating orders for to your Sendle account for invoicing. You can do this on the Billing page of your Sendle Dashboard.
If you are creating orders in Australia, you will need to have an AUD Credit Card set up, or if you are creating orders in the US you will need to have a USD Credit Card set up in your billing account to create an order in the relevant currency.
Ping Server
GET /api/ping
[ GET /api/ping ]
Status 200:
{
"ping": "pong",
"timestamp": "2018-04-05T15:52:48+10:00"
}
The ping endpoint has been specifically created so that you can test out some of the more administrative aspects of our API’s functionality, without any risk of creating live orders on our system.
You can use it to test:
Other endpoints can be quite complex, and it is easier to determine what kind of error has occurred if the test-endpoint doesn’t do much. Thus, ping returns a very simple response.
It returns a simple ping/pong key-pair, and a timestamp showing when the response was generated on our system.
Testing Account settings
If you have not yet confirmed the email on your account, set up payment settings or accepted the dangerous goods terms, the ping-response will give the relevant errors. This is as opposed to other ‘public’ endpoints such as the quote-request endpoint.
Thus, ping can be useful for testing whether your settings are valid before trying out the order-creation endpoint.
See Getting started for more details on these settings and the relevant error messages.
Testing Authentication
All API interactions will require your Sendle ID and your API Key as username and password for HTTP Basic Authentication (Make sure to replace sendleID and APIKey with your Sendle ID & API key.)
curl 'https://api.sendle.com/api/ping'
-u sendleID:APIKey
-H "Content-Type: application/json"
-H "Accept: application/json"
Sendle uses your Sendle ID together with your own API Key to grant access to the server. Together this allows you to access the API so that you may book and follow up with orders, as well as view past orders you have sent or received.
You must include your credentials in every request, or you will be denied. If you only you include your Sendle ID
, you will be prompted to enter your API key (password).
Status 200:
{
"ping": "pong",
"timestamp": "2018-04-05T15:52:48+10:00"
}
When the api receives a request with a Sendle ID
and an API Key
the server responds with a JSON
string containing the relevant details.
Without credentials
curl 'https://api.sendle.com/api/ping'
Response:
HTTP Basic: Access denied.
Response With incorrect Credentials:
{
"error": "unauthorised",
"error_description": "The authorisation details are not valid. Either the Sendle ID or API key are incorrect."
}
Testing Idempotency keys
Repeating a request without idempotency
curl 'https://api.sendle.com/api/ping'
-u sendleID:APIKey
-H "Content-Type: application/json"
-H "Accept: application/json"
Responses will all be different:
{"ping": "pong","timestamp": "2018-04-05T15:52:48+10:00"}
{"ping": "pong","timestamp": "2018-04-05T15:52:50+10:00"}
{"ping": "pong","timestamp": "2018-04-05T15:52:51+10:00"}
{"ping": "pong","timestamp": "2018-04-05T15:52:52+10:00"}
Repeating a request with the same idempotency-key
curl 'https://api.sendle.com/api/ping'
-u sendleID:APIKey
-H "Content-Type: application/json"
-H "Accept: application/json"
-H "Idempotency-Key: 6f4aba46-91d4-6ef3-af23-f523375ed5f6"
Responses will all be the same:
{"ping": "pong","timestamp": "2018-04-05T15:52:48+10:00"}
{"ping": "pong","timestamp": "2018-04-05T15:52:48+10:00"}
{"ping": "pong","timestamp": "2018-04-05T15:52:48+10:00"}
{"ping": "pong","timestamp": "2018-04-05T15:52:48+10:00"}
The ping endpoint contains a timestamp in the response so that you can test idempotency and check that it is working.
You will know that the idempotency-key is successfully working because if you keep requesting with the same key, you will get the same timestamp back.
Getting Quotes
GET /api/quote
[GET /api/quote]
Empty Request
curl 'https://api.sendle.com/api/quote'
Response
{
"messages": {
"pickup_suburb": ["can't be blank"],
"pickup_postcode": ["can't be blank"],
"delivery_suburb": ["can't be blank"],
"delivery_postcode": ["can't be blank"],
"weight": {
"value": ["is not a number"],
"units": ["can't be blank"]
}
},
"error": "unprocessable_entity",
"error_description": "The data you supplied is invalid. Error messages are in the messages section. Please fix those fields and try again."
}
Authenticated Request (recommended)
curl 'https://api.sendle.com/api/quote?pickup_suburb=Camberwell%20North&pickup_postcode=3124&pickup_country=AU&delivery_suburb=Barangaroo&delivery_postcode=2000&delivery_country=AU&weight_value=2.0&weight_units=kg&volume_value=0.01&volume_units=m3' \
-u "sendleID:APIKey"
-H 'Content-Type: application/json' \
-H 'Accept: application/json'
200 Response
[
{
"quote": {
"gross": {
"amount": 13.95,
"currency": "AUD"
},
"net": {
"amount": 12.68,
"currency": "AUD"
},
"tax": {
"amount": 1.27,
"currency": "AUD"
}
},
"plan_name": "Premium",
"eta": {
"days_range": [0, 4],
"date_range": ["2018-02-13", "2018-02-19"],
"for_pickup_date": "2018-02-13"
}
}
]
Request with
plan_name
(deprecated)
curl 'https://api.sendle.com/api/quote?pickup_suburb=Camberwell%20North&pickup_postcode=3124&pickup_country=AU&delivery_suburb=Barangaroo&delivery_postcode=2000&delivery_country=AU&weight_value=2.0&weight_units=kg&volume_value=0.01&volume_units=m3&plan_name=Premium' \
-H 'Content-Type: application/json'
200 Response
[
{
"quote": {
"gross": {
"amount": 13.95,
"currency": "AUD"
},
"net": {
"amount": 12.68,
"currency": "AUD"
},
"tax": {
"amount": 1.27,
"currency": "AUD"
}
},
"plan_name": "Premium",
"eta": {
"days_range": [0, 4],
"date_range": ["2018-02-13", "2018-02-19"],
"for_pickup_date": "2018-02-13"
}
}
]
The quoting API operates in three modes, two of which are deprecated:
- (Recommended) Requesting a quote with your Sendle ID and API key will return the quote for the relevant account’s plan only.
- (Deprecated) Requesting a quote without providing your Sendle ID and API key will return all quotes for all publicly available plans.
- (Deprecated) Requesting a quote without providing your Sendle ID and API key, but providing a
plan_name
will return a quote for just that plan.
Modes 2 and 3 are deprecated and will be removed in a future version. All new integrations should make authenticated quote requests (mode 1), as this ensures the API always returns the right quote for the account, even if the plan changes.
The ?
after the quote endpoint initiates the query. Be sure to separate terms using <name>=<value>
pairs in your request and use percent-encoding for all spaces or special characters in your query string like the example (right). If you need more information on GET & POST requests, the Treehouse blog has a nice summary.
For specific information about weight limits and parcel sizing, visit the Weights and Dimensions section.
The response also returns an approximate eta. The eta assumes the parcel is being picked up or dropped off on the next available business day. The eta section contains the approximate number of business days the parcel is likely to arrive, and the dates this corresponds to, as well as the assumed pickup/dropoff date.
The currency returned will be the relevant currency for the origin of the quote. When sending from Australia this will be AUD
and when sending from the US this will be USD
. This is the currency you will be charged in.
Parcels can be ‘picked up’ from a home or business address, or they can be 'dropped off’ at a Hubbed location (in Australia) or a USPS store (in the US). The availability of both varies on location, but generally we offer both services in Australia, and just drop off for now in the United States.
Fields in a successful response
Field | Description |
---|---|
quote | Section: contains all the pricing of the quote. |
gross | Pricing including taxes (if applicable). |
net | Pricing exclusive of taxes (if applicable). |
tax | Any applicable taxes. |
plan_name | The name of the plan for which this is the price. |
eta | Section: contains eta-relevant data |
days_range | How long delivery is likely to take expressed as a range. Always returned as an array. If there are two values, these are the min and max estimated days it will take. If only one number - it’s estimated to take about this long. |
date_range | Actual business dates that the eta days_range match, if pickup occurs on the given pickup_date . |
for_pickup_date | All etas are relevant to a given pickup-date. Sendle assumes the next available business day - and this is the pickup-date we are estimating based off. |
Domestic Parcel Quote Requirements
Domestic request with authentication credentials
curl 'https://api.sendle.com/api/quote?pickup_suburb=Camberwell%20North&pickup_postcode=3124&pickup_country=AU&delivery_suburb=Barangaroo&delivery_postcode=2000&delivery_country=AU&weight_value=2.0&weight_units=kg&volume_value=0.01&volume_units=m3&first_mile_option=drop%20off'
-u 'sendleID:APIKey'
-H 'Content-Type: application/json'
200 Response
[
{
"quote": {
"gross": {
"amount": 14.95,
"currency": "AUD"
},
"net": {
"amount": 13.59,
"currency": "AUD"
},
"tax": {
"amount": 1.36,
"currency": "AUD"
}
},
"plan_name": "Standard",
"eta": {
"days_range": [1, 4],
"date_range": ["2018-02-14", "2018-02-19"],
"for_pickup_date": "2018-02-13"
}
}
]
Query-parameters
Parameter | Description |
---|---|
pickup_address_line1 optional |
First line of the street address for the pickup location. |
pickup_address_line2 optional |
Second line of the street address for the pickup location. |
pickup_suburb | Suburb must be real and match pickup postcode. |
pickup_postcode | Post code for the pickup address. |
pickup_country optional |
ISO 3166 country code. Sendle currently supports AU for Australia and US for United States. If no pickup_country is provided this will default to AU . |
delivery_address_line1 optional |
First line of the street address for the delivery location. |
delivery_address_line2 optional |
Second line of the street address for the delivery location. |
delivery_suburb | Suburb must be real and match delivery postcode. |
delivery_postcode | Post code for the delivery address. |
delivery_country optional |
ISO 3166 country code. Sendle currently supports AU for Australia and US for United States. If no delivery_country is provided this will default to AU . |
weight_value | Decimal string value of the weight. Max weight is 25 kilograms for Australia and 70lb for United States. |
weight_units | The unit of measurement. Most be one of kg (kilograms), g (grams), lb (pounds) or oz (ounces). |
volume_value optional |
Decimal string value of the volume. |
volume_units optional |
The unit of measurement for the volume. Most be one of l (litres), m3 (cubic metres), in3 (cubic inches) or ft3 (cubic feet). |
first_mile_option | Whether the parcel will be picked up or dropped off. pickup for parcels that are being picked up, or drop off for drop off (or US) parcels. |
plan_name deprecated |
Without authenticating, the API will give quotes for all publicly available plans by default. If plan_name is specified, the API will respond with a quote for just the given plan. For authenticated requests, the API always returns the quote for the account’s current plan and ignores plan_name. |
kilogram_weight deprecated |
Must be a decimal-value above 0 and less than weight limits. Max weight is 25 kilograms for Australia and 70lb for United States. Sendle recommends using the weight_value and weight_units parameters above instead. |
cubic_metre_volume optional, deprecated |
Must be decimal-value between 0 and 1. To determine this measurement multiply length x width x depth of the parcel in metres. Sendle recommends using the volume_value and volume_units parameters above instead. |
International Parcel Quote Requirements
International request with authentication credentials
curl 'https://api.sendle.com/api/quote?pickup_suburb=Sydney&pickup_postcode=2000&delivery_country=New%20Zealand&weight_value=5&weight_units=kg'
-u 'sendleID:APIKey'
-H 'Content-Type: application/json'
200 Response
[
{
"quote": {
"gross": {
"amount": 116.2,
"currency": "AUD"
},
"net": {
"amount": 116.2,
"currency": "AUD"
},
"tax": {
"amount": 0.0,
"currency": "AUD"
}
},
"plan_name": "Standard",
"eta": {
"days_range": [4, 11],
"date_range": ["2018-02-19", "2018-02-28"],
"for_pickup_date": "2018-02-13"
}
}
]
name | Attributes |
---|---|
pickup_suburb | Suburb must be real and match pickup postcode. |
pickup_postcode | Four-digit post code for the pickup address. |
delivery_country | Full name or ISO Alpha 2 code of the country the parcel is being delivered to. |
weight_value | Decimal string value of the weight. Max weight is 25 kilograms for Australia and 70lb for United States. |
weight_units | The unit of measurement. Most be one of kg (kilograms), g (grams), lb (pounds) or oz (ounces). |
volume_value optional |
Decimal string value of the volume. |
volume_units optional |
The unit of measurement for the volume. Most be one of l (litres), m3 (cubic metres), in3 (cubic inches) or ft3 (cubic feet). |
plan_name deprecated |
Without authenticating, the API will give quotes for all publicly available plans by default. If plan_name is specified, the API will respond with a quote for just the given plan. For authenticated requests, the API always returns the quote for the account’s current plan and ignores plan_name. |
kilogram_weight deprecated |
Must be a decimal-value above 0 and less than weight limits. Max weight is 25 kilograms for Australia and 70lb for United States. It is preferable to use weight_value and weight_units as this attribute will be removed in the future. |
cubic_metre_volume optional, deprecated |
Must be decimal-value between 0 and 1. To determine this measurement multiply length x width x depth of the parcel in metres.. It is preferable to use volume_value and volume_units as this attribute will be removed in the future. |
Creating Orders
POST /api/orders
[ POST /api/orders ]
To create an order, submit order data via POST command. The order will be rejected if the data fails validation and the API will respond with an HTTP error.
Identification matching the sender name on the label must be provided for the first three pickups of international parcels.
You can prevent duplicate orders by using an Idempotency Key header with this endpoint. Find out more about Idempotency Keys here
Your account will require a card for the currency you will be creating orders for.
If you are creating orders in Australia, you will need to have an AUD Credit Card set up, or if you are creating orders in the US you will need to have a USD Credit Card set up in your billing account to create an order in the relevant currency.
If you do not have the correct currency enabled for your card you will receive an error in the response.
Example Booking JSON
Example Booking
curl "https://api.sendle.com/api/orders"
-X POST
-u "sendleID:APIKey"
-H "Content-Type: application/json"
-H "Accept: application/json"
-H "Idempotency-Key: 6f4aba46-91d4-6ef3-af23-f523375ed5f6"
-d '{
"pickup_date": "2015-11-24",
"first_mile_option": "pickup",
"description": "Kryptonite",
"weight": {"value": "1", "units": "kg"},
"volume": {"value": "0.01", "units": "m3"},
"customer_reference": "SupBdayPressie",
"metadata": {
"your_data": "XYZ123"
},
"sender": {
"contact": {
"name": "Lex Luthor",
"phone": "0412 345 678",
"company": "LexCorp"
},
"address": {
"address_line1": "123 Gotham Ln",
"suburb": "Sydney",
"state_name": "NSW",
"postcode": "2000",
"country": "Australia"
},
"instructions": "Knock loudly"
},
"receiver": {
"contact": {
"name": "Clark Kent",
"email": "clarkissuper@dailyplanet.xyz",
"company": "Daily Planet"
},
"address": {
"address_line1": "80 Wentworth Park Road",
"suburb": "Glebe",
"state_name": "NSW",
"postcode": "2037",
"country": "Australia"
},
"instructions": "Give directly to Clark"
}
}'
Each collection within the example booking JSON is described in detail in the sections below.
Section | Attributes |
---|---|
Parcel details | Pickup date, a parcel description, weight, volume, and a customer reference for the shipment |
Sender details | Sender contact details, origin address, and pickup instructions |
Sender address | Origin Address Details |
Receiver details | Recipient contact details, destination address, and delivery instructions |
Receiver address | Destination Address Details |
Weight | Information about how heavy the package is |
Volume | Information about the volume of the package |
API response | JSON object returned with a valid booking |
Labels | Getting Shipping Labels |
Parcel Details
Parcel details for a pickup
{
"pickup_date": "2015-11-24",
"first_mile_option": "pickup",
"description": "Kryptonite",
"weight": {
"value": "1",
"units": "kg"
},
"volume": {
"value": "0.01",
"units": "m3"
},
"customer_reference": "SupBdayPressie",
"metadata": {
"your_data": "XYZ123"
},
"hide_pickup_address": false
}
Parcel details for a drop off
{
"first_mile_option": "drop off",
"description": "Kryptonite",
"weight": {
"value": "1",
"units": "kg"
},
"volume": {
"value": "0.01",
"units": "m3"
},
"customer_reference": "SupBdayPressie",
"metadata": {
"your_data": "XYZ123"
},
"hide_pickup_address": false
}
Data Field | Attributes |
---|---|
pickup_date “yyyy-mm-dd” |
If you choose drop off as your first_mile_option , please omit pickup_date . Otherwise, if provided, the date must be at least one non-holiday, business day in the future. If pickup date is omitted it will be set to the first available pickup date option and returned in the order payload on subsequent requests. |
first_mile_option | Use pickup to get your parcel picked up (when available) or drop off to drop it off at the nearest drop off location in Australia or United States. In the US, only drop off is available. If first_mile_option is not specified, a default value of pickup will be used. |
description | Description is used by the customer to track the parcel on Sendle Dashboard. It does not show up on a label. It must be under 255 characters in length. |
weight | Object detailing how much the parcel weighs. See weight for full information about the weight object. |
volume optional |
Object detailing the volume of the parcel. See volume for full information about the volume object. |
customer_reference optional |
Reference will appear on the label for parcel identification. It must be under 255 characters in length. |
metadata optional |
Up to 1MB of JSON key/value pairs which will be stored for this order. These are included when Viewing an Order and in some bulk reports available from the system. |
hide_pickup_address optional |
For Australian domestic orders only. Can be used to omit the street address of the sender from a label. Overrides accounts preferences if passed in, account preferences will be respected if omitted. Ignored for export orders, or orders originating outside of Australia. |
kilogram_weight deprecated |
Must be a decimal value greater than 0 and less than the maximum allowed weight of 25kg. This option has been deprecated, Sendle recommends that you use the weight object instead. |
cubic_metre_volume deprecated, optional |
Must be a decimal value between 0 and 1. When included, value will be length x width x depth of parcel in metres. This option has been deprecated, Sendle recommends that you use the volume object instead. If both kilogram_weight AND the weight object is passed, weight will take precedence. |
Sender Details
{
"sender": {
"instructions": "Pick up from reception",
"contact": {
"name": "Lex Luthor",
"phone": "0412 345 678",
"email": "me@lexluthor.com",
"company": "LexCorp"
}
}
}
sender object |
A collection of parcel origin details. |
instructions optional |
Short message used as pickup instructions for courier. It must be under 200 chars in length, but is recommended to be under 40 chars due to label-size limitations. |
contact object |
A collection of sender contact details. |
name | It must be under 255 characters in length. |
email optional |
Leave this empty - it will be populated with your email based on your account. |
phone optional |
Used to coordinate pickup if the courier is outside attempting delivery. It must be a valid Australian phone number (including area code), or fully qualified international number. Examples: (02) 1234 1234, +1 519 123 1234, +61 (0)4 1234 1234. |
company optional |
Business name for the Sender |
Sender Address
{
"address": {
"address_line1": "123 Gotham Ln",
"address_line2": null,
"suburb": "Sydney",
"state_name": "NSW",
"postcode": "2000",
"country": "Australia"
}
}
address object |
A collection of origin address details. |
address_line1 | The street address where the parcel will be picked up. Addresses can be split over two lines using address_line1 and address_line2 . Only address_line1 is mandatory. line2 will be displayed below line1 on the parcel label. Do not include postcode, state, or suburb in this field. It must be under 255 char in length, but best practice to keep under 40 chars due to label-size limitations. |
address_line2 optional |
Second line of the street address for the pickup location. It must be under 255 char in length, but best practice to keep under 40 chars due to label-size limitations. |
suburb | Suburb or town where the parcel is to be picked up. If Sendle cannot service this location, response will be a validation error stating that the suburb is not serviceable. Postcode and suburb must match. If they do not match, Sendle will return a set of alternates to choose from. If receiving an unserviceable error, you may want to check if the location is also listed under a different suburb name. |
postcode | Postcode or ZIP code of pickup location. It must be a four or five digit string for a valid location. If we cannot pick up parcels from the area, the response will be a validation error stating the location is unserviceable. |
state_name | Must be the origin location’s state or territory. For Australia these are: ACT, NSW, NT, QLD, SA, TAS, VIC, WA, with the long-form (i.e. “Northern Territory”) also accepted. For United States these are the states 2 letter representation such as CA, NY. |
country optional |
Sendle only works within Australia & the United States. If absent, Sendle assumes orders are in Australia. String value under 255 characters in length. If included, must read “Australia” or “United States”. |
Receiver Details
{
"receiver": {
"instructions": "ATL but knock loudly",
"contact": {
"name": "Clark Kent",
"email": "clarkissuper@dailyplanet.xyz",
"phone": "0287654321",
"company": "Daily Planet"
}
}
}
receiver object |
A collection of parcel recipient details. |
instructions | Short message used as delivery instructions for courier. It must be under 200 chars, but is recommended to be under 40 chars due to label-size limitations. Note: “Signature on Delivery” is always ignored for satchels sent within Australia, even if entered here. |
contact object |
A collection of receiver details. |
name | It must be under 255 characters in length. |
email optional |
Recipient email allows Sendle to send parcel updates to the recipient. |
phone optional |
Used to coordinate pickup if the courier is outside attempting delivery. It must be a valid Australian/US phone number (including area code), or fully qualified international number. Examples: (02) 1234 1234, +1 519 123 1234, +61 (0)4 1234 1234. |
company optional |
Business name for the Receiver |
Receiver Address
{
"address": {
"address_line1": "80 Wentworth Park Road",
"suburb": "Glebe",
"state_name": "NSW",
"postcode": "2037",
"country": "Australia"
}
}
address object |
A collection of destination address details. |
address_line1 | The street address where the parcel will be delivered. Addresses can be split over two lines using address_line1 and address_line2 . Only address_line1 is mandatory. line2 will be displayed below line1 on the parcel label. Do not include postcode, state, or suburb in this field. It must be under 255 chars in length, but best practice to keep under 40 chars due to label-size limitations. |
address_line2 optional |
Second line of the street address for the pickup location. It must be under 255 chars in length, but best practice to keep under 40 chars due to label-size limitations. |
suburb | Suburb or town where the parcel is to be delivered. If Sendle cannot service this location, the response will be a validation error stating that the suburb is not serviceable. Postcode and suburb must match if within Australia. If they do not match, Sendle will return a set of alternatives to choose from. |
postcode | Postcode or ZIP code of destination location. If we cannot deliver parcels to the area, the response will be a validation error stating the location is unserviceable. |
state_name | Must be the destination location’s state or territory. For Australia these are: ACT, NSW, NT, QLD, SA, TAS, VIC, WA, with the long-form (i.e. “Northern Territory”) also accepted. For United States these are the states 2 letter representation such as CA, NY. |
country optional |
If absent, Sendle assumes orders are in Australia. String value under 255 characters in length. If included, must read “Australia” or “United States”. Sendle only supports international parcels sent from Australia. |
Weight
{
"weight": {
"value": "1",
"units": "kg"
}
}
Contains information pertaining to the weight of the package. Either a weight
object or kilogram_weight
is required.
If both kilogram_weight
AND the weight
object is passed, weight
will take precedence.
weight object |
A collection detailing the package weight. |
value | A string value detailing how heavy the parcel is. |
units | The unit of measurement for the weight. Most be one of kg (kilograms), g (grams), lb (pounds) or oz (ounces). |
Volume
{
"volume": {
"value": "0.01",
"units": "m3"
}
}
Contains information pertaining to the volume of the package. Either a volume
object or cubic_metre_volume
is required.
If both a cubic_metre_volume
value AND the volume
object is passed, the volume
will take precedence.
volume object |
A collection detailing the package volume. |
value | A string value detailing the volume of the parcel is. |
units | The unit of measurement for the volume. Most be one of l (litres), m3 (cubic metres), in3 (cubic inches) or ft3 (cubic feet). |
API Response
201 Response
{
"order_id": "f5233746-71d4-4b05-bf63-56f4abaed5f6",
"state": "Payment",
"order_url": "https://api.sendle.com/api/orders/f5233746-71d4-4b05-bf63-56f4abaed5f6",
"sendle_reference": "S3ND73",
"tracking_url": "https://track.sendle.com/tracking?ref=S3ND73",
"hide_pickup_address": false,
"labels": null,
"scheduling": {
"is_cancellable": true,
"pickup_date": "2015-11-24",
"picked_up_on": null,
"delivered_on": null,
"estimated_delivery_date_minimum": "2015-11-26",
"estimated_delivery_date_maximum": "2015-11-27"
},
"description": "Kryptonite",
"kilogram_weight": "1.0",
"weight": {
"units": "kg",
"value": "1.0"
},
"volume": {
"units": "m3",
"value": "0.0"
},
"cubic_metre_volume": "0.01",
"customer_reference": "SupBdayPressie",
"metadata": {
"your_data": "XYZ123"
},
"sender": {
"contact": {
"name": "Lex Luthor",
"phone": "0412 345 678",
"email": "me@lexluthor.com",
"company": "LexCorp"
},
"address": {
"address_line1": "123 Gotham Ln",
"address_line2": null,
"suburb": "Sydney",
"state_name": "NSW",
"postcode": "2000",
"country": "Australia"
},
"instructions": "Knock loudly"
},
"receiver": {
"contact": {
"name": "Clark Kent",
"phone": null,
"email": "clarkissuper@dailyplanet.xyz",
"company": "Daily Planet"
},
"address": {
"address_line1": "80 Wentworth Park Road",
"address_line2": null,
"suburb": "Glebe",
"state_name": "NSW",
"postcode": "2037",
"country": "Australia"
},
"instructions": "Give directly to Clark"
},
"route": {
"description": "Sydney to Sydney",
"type": "same-city",
"delivery_guarantee_status": "eligible"
},
"price": {
"tax": {
"currency": "AUD",
"amount": 0.81
},
"net": {
"currency": "AUD",
"amount": 8.14
},
"gross": {
"currency": "AUD",
"amount": 8.95
}
}
}
A successful response will be a full version of an Order object. Many of the fields sent in a booking response are confirmation of the details sent in a booking request and are covered in detail in the View an Order section. In addition to the booking details, information about the current State of the order, URLs for order details, and scheduling information is included.
The currency returned will be the relevant currency for the origin of the order. When sending from Australia this will be AUD
and when sending from the US this will be USD
. This is the currency you will be charged in.
Field | Description |
---|---|
order_id | The order’s individual identification in Sendle’s system. |
state | Identifies the current state of the order. Visit Check for Status Updates for more information. |
order_url | Specific url for order queries. After booking, this url becomes the point to check for updated information (state changes), labels and any other information related to the order. |
sendle_reference | Reference ID for a Sendle Order. References begin with an “S” and are an alphanumeric string six or more characters in length. |
tracking_url | The order’s public tracking page. Tracking page updates as the parcel progresses from sender to receiver. The url can be shared and viewed without a Sendle Account and contains no personal information about either party. |
labels | Covered in detail in the label section. Contains URLs to retrieve labels in different formats. |
scheduling | Information regarding the order’s delivery status and whether an order can be cancelled. picked_up_on and delivered_on will return null . |
pickup_date is the date the courier has been requested to pick up the parcel. picked_up_on represents the date an order is collected by a courier. |
|
estimated_delivery_date_minimum and estimated_delivery_date_maximum can change depending on courier conditions. |
|
route | Information about the route. |
description is a human readable description of the route. |
|
type is a machine readable version of the route type. One of same-city , national , remote , or export |
|
delivery_guarantee_status only present when the account has enrolled in our 2-Day Delivery Guarantee. Values can be eligible or ineligible . |
|
price | The amount charged for this order. |
Creating International Orders
POST /api/orders
[ POST /api/orders ]
To create an international order (an order that is sent from one country another, such as Australia to the United States), submit order data via POST command. The order will be rejected if the data fails validation and the API will respond with an HTTP error.
All strings must be provided using Latin character sets, find out more about Latin and non-Latin character sets
Example Booking JSON
Example Booking
curl "https://api.sendle.com/api/orders"
-X POST
-u "sendleID:APIKey"
-H "Content-Type: application/json"
-H "Accept: application/json"
-d '{
"pickup_date": "2015-11-24",
"description": "Kryptonite",
"weight": {"value": "1", "units": "kg"},
"volume": {"value": "0.01", "units": "m3"},
"customer_reference": "SupBdayPressie",
"metadata": {
"your_data": "XYZ123"
},
"sender": {
"contact": {
"name": "Lex Luthor",
"phone": "0412 345 678"
},
"address": {
"address_line1": "123 Gotham Ln",
"suburb": "Sydney",
"state_name": "NSW",
"postcode": "2000",
"country": "Australia"
},
"instructions": "Knock loudly"
},
"receiver": {
"contact": {
"name": "Clark Kent",
"email": "clarkissuper@dailyplanet.xyz"
},
"address": {
"address_line1": "445 Mount Eden Road",
"suburb": "Auckland",
"postcode": "2025",
"country": "New Zealand"
},
"instructions": "Give directly to Clark"
},
"parcel_contents": [
{
"description": "T-shirt",
"value": "20.00",
"country_of_origin": "China"
}
]
}'
Each collection within the example booking JSON is described in detail in the sections below.
Section | Attributes |
---|---|
Parcel details | Pickup date, a parcel description, weight, volume, and a customer reference for the shipment |
Sender details | Sender contact details, origin address, and pickup instructions |
Sender address | Origin Address Details |
Receiver details | Recipient contact details, destination address, and delivery instructions |
Receiver address | Destination Address Details |
API response | JSON object returned with a valid booking |
Labels | Getting Shipping Labels |
International Parcel Details
{
"pickup_date": "2015-11-24",
"description": "Kryptonite",
"kilogram_weight": "1",
"cubic_metre_volume": "0.01",
"customer_reference": "SupBdayPressie",
"metadata": {
"your_data": "XYZ123"
},
"parcel_contents": [
{
"description": "T-shirt",
"value": "20.00",
"country_of_origin": "China"
}
]
}
Data Field | Attributes |
---|---|
pickup_date “yyyy-mm-dd” |
If provided the date must be at least one non-holiday, business day in the future. If pickup date is omitted it will be set to the first available pickup date option and returned in the order payload on subsequent requests. |
description | Description is used by the customer to track the parcel on Sendle Dashboard. It does not show up on a label. It must be under 255 characters in length. |
kilogram_weight | Must be a decimal value greater than 0 and less than the maximum allowed weight of 25kg. |
cubic_metre_volume optional |
Must be a decimal value between 0 and 1. When included, value will be length x width x depth of parcel in metres. |
customer_reference optional |
Reference will appear on the label for parcel identification. It must be under 255 characters in length. |
metadata optional |
Up to 1MB of JSON key/value pairs which will be stored for this order. These are included when Viewing an Order and in some bulk reports available from the system. |
contents object |
(Deprecated) Details about the parcel contents |
parcel_contents array |
A collection of details about the parcel contents |
description | Detailed description of the parcel contents for customs purposes. Must be between 3 and 300 characters in length. Examples: Shoes, hat, sunglasses |
country_of_origin | The country in which the goods where manufactured. This can be either the country name or ISO Alpha 2 code. Country names can vary between systems so it is recommended to use ISO country codes where possible. |
value | The total value of the parcel contents in $AUD, the total value of the parcel cannot exceed $2,000AUD |
International Sender Details
{
"sender": {
"instructions": "Pick up from reception",
"contact": {
"name": "Lex Luthor",
"phone": "0412 345 678",
"email": "me@lexluthor.com"
}
}
}
sender object |
A collection of parcel origin details. |
instructions optional |
Short message used as pickup instructions for courier. It must be under 200 chars, but is recommended to be under 40 chars due to label-size limitations. |
contact object |
A collection of sender contact details. |
name | It must be under 255 characters in length. |
email optional |
Leave this empty - it will be populated with your email based on your account. |
phone optional |
Used to coordinate pickup if the courier is outside attempting delivery. It must be a valid Australian phone number (including area code), or fully qualified international number. Examples: (02) 1234 1234, +1 519 123 1234, +61 (0)4 1234 1234. |
International Sender Address
{
"address": {
"address_line1": "123 Gotham Ln",
"address_line2": null,
"suburb": "Sydney",
"state_name": "NSW",
"postcode": "2000",
"country": "Australia"
}
}
address object |
A collection of origin address details. |
address_line1 | The street address where the parcel will be picked up. Addresses can be split over two lines using address_line1 and address_line2 . Only address_line1 is mandatory. line2 will be displayed below line1 on the parcel label. Do not include postcode, state, or suburb in this field It must be under 255 char in length, but best practice to keep under 40 chars due to label-size limitations. |
address_line2 optional |
Second line of the street address for the pickup location. |
suburb | Suburb or town where the parcel is to be picked up. If Sendle cannot service this location, response will be a validation error stating that the suburb is not serviceable. Postcode and suburb must match. If they do not match, Sendle will return a set of alternates to choose from. If receiving an unserviceable error, you may want to check if the location is also listed under a different suburb name. |
postcode | Postcode of pickup location. It must be a four digit string for a valid location. If the area cannot be picked up from, response will be a validation error stating the location is unserviceable. |
state_name | Must be the pickup location’s state or territory. Valid options include: ACT, NSW, NT, QLD, SA, TAS, VIC, WA. Long-form (i.e. “Northern Territory”) is also accepted. |
country optional |
If absent, Sendle assumes orders are in Australia. String value under 255 characters in length. If included, must read “Australia” or “AU” |
International Receiver Details
{
"receiver": {
"instructions": "ATL but knock loudly",
"contact": {
"name": "Clark Kent",
"email": "clarkissuper@dailyplanet.xyz",
"phone": "0287654321"
}
}
}
receiver object |
A collection of parcel recipient details. |
instructions | Short message used as delivery instructions for courier. It must be under 200 chars, but is recommended to be under 40 chars due to label-size limitations. Note: “Signature on Delivery” is always ignored for satchels sent within Australia, even if entered here. |
contact object |
A collection of receiver details. |
name | It must be under 255 characters in length. |
email optional |
Recipient email allows Sendle to send parcel updates to the recipient. |
phone optional |
Used to coordinate pickup if the courier is outside attempting delivery. It must be a valid Australian phone number (including area code), or fully qualified international number. Examples: (02) 1234 1234, +1 519 123 1234, +61 (0)4 1234 1234. |
International Receiver Address
{
"address": {
"address_line1": "80 Wentworth Park Road",
"suburb": "Glebe",
"state_name": "NSW",
"postcode": "2037",
"country": "Australia"
}
}
address object |
A collection of destination address details. |
address_line1 | The street address where the parcel will be delivered. Addresses can be split over two lines using address_line1 and address_line2 . Only address_line1 is mandatory. line2 will be displayed below line1 on the parcel label. Do not include postcode, state, or suburb in this field. It must be under 255 char in length, but best practice to keep under 40 chars due to label-size limitations. |
address_line2 optional |
Second line of the street address for the destination location. |
suburb | Suburb or town where the parcel is to be delivered. |
postcode | optional Postcode of destination location. |
state_name | optional The destination location’s state or territory. |
country | A string of the destination location’s country. This can be either the country name or ISO Alpha 2 code. The list of countries that Sendle delivers to and their codes can be found here, the country name must match exactly so it is recommended to use the ISO country code where possible. |
Merchant tax ID for EU parcels
{
"sender": {
"tax_ids": { "ioss": "IM0123456789" }
}
}
sender object |
A collection of parcel origin details. |
tax_ids object |
A collection of tax information. |
ioss optional |
The IOSS tax ID for the parcel’s sender, for VAT collection purposes. This field is optional for personal items, but should be provided by commercial senders. Failure to do so may result in transit delays, or the receiver needing to pay unpaid VAT and administration fees. Must have the prefix IM followed by 10 digits. |
Detailed parcel contents information
{
"parcel_contents": [
{
"description": "Printed cotton t-shirt",
"hs_code": "5210.21",
"value": "20.00",
"currency": "AUD",
"quantity": 3,
"country_of_origin": "china"
},
{
"description": "Clear plastic umbrella",
"hs_code": "6601.10",
"value": "20.00",
"currency": "AUD",
"quantity": 1,
"country_of_origin": "india"
}
]
}
parcel_contents array |
A collection of details about the parcel contents |
description | Detailed description of the parcel contents for customs purposes. Must be between 3 and 300 characters in length. |
country_of_origin | The country in which the goods where manufactured. This can be either the country name or ISO Alpha 2 code. Country names can vary between systems so it is recommended to use ISO country codes where possible. |
value | The value of one unit of this item. Total value of the parcel for all items can not exceed $2,000AUD. |
quantity default: 1 |
The number of units of this item which are contained in the parcel. |
currency default: AUD |
The currency in which value is expressed. |
hs_code optional |
A Harmonized System code for this item which is appropriate for the destination country. Single HS tariff code only. Must only contain 6-10 digits with separating dots. |
Deprecated format of parcel contents
{
"contents": {
"description": "T-shirt",
"value": "20.00",
"country_of_origin": "China",
"currency": "AUD"
}
}
For clients that do not yet support parcel_contents
, the deprecated form of providing contents
remains supported:
International API Response
201 Response
{
"order_id": "f5233746-71d4-4b05-bf63-56f4abaed5f6",
"state": "Payment",
"order_url": "https://api.sendle.com/api/orders/f5233746-71d4-4b05-bf63-56f4abaed5f6",
"sendle_reference": "S3ND73",
"tracking_url": "https://track.sendle.com/tracking?ref=S3ND73",
"labels": null,
"scheduling": {
"is_cancellable": true,
"pickup_date": "2015-11-24"
},
"description": "Kryptonite",
"kilogram_weight": "1.0",
"cubic_metre_volume": "0.01",
"customer_reference": "SupBdayPressie",
"metadata": {
"your_data": "XYZ123"
},
"sender": {
"contact": {
"name": "Lex Luthor",
"phone": "0412 345 678",
"email": "me@lexluthor.com"
},
"address": {
"address_line1": "123 Gotham Ln",
"address_line2": null,
"suburb": "Sydney",
"state_name": "NSW",
"postcode": "2000",
"country": "Australia"
},
"instructions": "Knock loudly"
},
"receiver": {
"contact": {
"name": "Clark Kent",
"phone": null,
"email": "clarkissuper@dailyplanet.xyz"
},
"address": {
"address_line1": "445 Mount Eden Road",
"address_line2": null,
"suburb": "Auckland",
"postcode": "2025",
"state_name": null,
"country": "New Zealand"
},
"instructions": "Give directly to Clark"
},
"contents": {
"description": "T-shirt",
"value": "20.00",
"country_of_origin": "China",
"currency": "AUD"
},
"parcel_contents": [
{
"description": "T-shirt",
"value": "20.00",
"country_of_origin": "China",
"quantity": 1,
"currency": "AUD",
"hs_code": null
}
]
}
A successful response will be a full version of an Order object. Many of the fields sent in a booking response are confirmation of the details sent in a booking request and are covered in detail in the View an Order section. In addition to the booking details, information about the current State of the order, URLs for order details, and scheduling information is included.
Field | Description |
---|---|
order_id | The order’s individual identification in Sendle’s system. |
state | Identifies the current state of the order. Visit Check for Status Updates for more information. |
order_url | Specific url for order queries. After booking, this url becomes the point to check for updated information (state changes), labels and any other information related to the order. |
sendle_reference | Reference ID for a Sendle Order. References begin with an “S” and are an alphanumeric string six or more characters in length. |
tracking_url | The order’s public tracking page. Tracking page updates as the parcel progresses from sender to receiver. The url can be shared and viewed without a Sendle Account and contains no personal information about either party. |
labels | Covered in detail in the label section. Contains URLs to retrieve labels in different formats. |
scheduling | Information regarding the order’s pickup date and whether an order can be cancelled |
contents | Legacy format of parcel contents, only included when parcel_contents has a single item. Clients should disregard this field in favour of parcel_contents . |
Weights and Dimensions
A 20cm cube weighing 500g
{
"weight": {"value": "0.5", "units": "kg"},
"volume": {"value": "0.008", "units": "m3"}
}
Sendle uses weight and volume together to determine the size of your parcel.
Sendle will choose the parcel size that can accommodate the weight and volume of your request. If either unit is over, Sendle will select the next size for your parcel.
Note that as per our Terms and Conditions, parcels may be weighed and scanned during transit. If a parcel is found to be under-declared (either weight or volume), we may raise an adjustment charge to reflect the difference between the booked dimensions and the actual dimensions.
Weight
weight
(required) when creating an order must be an object containing a unit
and a value
. The value
must be a decimal value greater than 0 and less than or equal to the category/max weight allowed for that unit.
- 25kg max for Australian Domestic, 20kg max for Australian International
- 70lb max for United States Domestic
Volume
volume
(optional) when creating an order must be an object containing aunit
and avalue
.
When using m3
, the value
must be a decimal value above zero and less than one.
To get the value
, multiply length x width x depth of parcel in your unit
(for example meters or in3).
We recommend that you always provide a weight, but the volume is optional. Items booked at a lower price due to insufficient information or underquoting may be refused at collection, or may attract adjustment charges.
The Sendle Dashboard uses several weight tiers to allow users to select dimensions, however the API allows any combination of weight and volume. This allows quoting and booking for both Domestic and International parcels.
Australian Domestic Parcels
A satchel
{
"weight": {"value": "0.4", "units": "kg"},
"volume": {"value": "0.001", "units": "m3"}
}
A shoebox
{
"weight": {"value": "1.0", "units": "kg"},
"volume": {"value": "0.01", "units": "m3"}
}
A Carry-on
{
"weight": {"value": "5.2", "units": "kg"},
"volume": {"value": "0.05", "units": "m3"}
}
Note that the
weight
when using akg
unit
(5.2) has bumped the parcel to the carry-on size despite the relatively smallvolume
.
Sendle uses five standard sizes for parcel delivery:
Size | Weight – kg (Max) | Volume – m3 (Max) |
---|---|---|
Satchel | 0.5kg | 0.002 |
Shoebox | 2kg | 0.008 |
Briefcase | 5kg | 0.02 |
Carry-on | 10kg | 0.04 |
Luggage | 25kg | 0.1 |
Australian Domestic Satchel Specifics
Satchels sent from are special pouch-only mailers, and are available only for Domestic parcels. If delivery instructions are not provided it will be Authority To Leave (ATL) by default.
Requirements:
Satchels must be packaged in an A4 satchel.
receiver.instructions
Short message used as delivery instructions for courier. It must be under 200 chars, but is recommended to be under 40 chars due to label-size limitations.weight
is less than or equal to 0.5volume
is less than or equal to 0.002.
Australian International Parcels
When sending from Australia, International parcels can be up to 20kg. There are three main International zones, and pricing is calculated based on those zones, weight and volume.
United States Domestic Parcels
Micro
{
"weight": {"value": "0.5", "units": "lb"},
"volume": {"value": "0.001", "units": "m3"}
}
Mini
{
"weight": {"value": "1.0", "units": "lb"},
"volume": {"value": "0.01", "units": "m3"}
}
Small
{
"weight": {"value": "5", "units": "lb"},
"volume": {"value": "173", "units": "in3"}
}
Medium
{
"weight": {"value": "10", "units": "lb"},
"volume": {"value": "518", "units": "in3"}
}
Large
{
"weight": {"value": "20", "units": "lb"},
"volume": {"value": "864", "units": "in3"}
}
Sendle uses five standard sizes for parcel delivery in the US:
Size | Weight – lb (Max) | Volume – in3 (Max) |
---|---|---|
Micro | 0.5lb | 0.002 |
Mini | 1lb | 0.008 |
Small | 5lb | 173 |
Medium | 10lb | 518 |
Large | 20lb | 864 |
Size Calculator
If you are ever unsure about your parcel size, the Dashboard Size Calculator will convert your parcel’s length, width, and height measurements together with the weight to display the litre volume and select the correct parcel size.
Deprecated Kilogram Weight / Cubic Metre Volume
Previously Sendle used a kilogram_weight
key for detailing and a cubic_metre_volume
key for detailing the volume of the package. As of January 2020 this has been deprecated, but will continue to be supported for the forseeable future.
You can still pass kilogram_weight
and cubic_metre_volume
in lieu of the volume
and weight
objects, but Sendle recommends using the weight
and volume
properties.
View an Order
GET /api/orders/{id}
[ GET /api/orders/{id} ]
curl "https://api.sendle.com/api/orders/f5233746-71d4-4b05-bf63-56f4abaed5f6"
-u "sendleID:APIKey"
-H "Content-Type: application/json"
200 Response
{
"order_id": "f5233746-71d4-4b05-bf63-56f4abaed5f6",
"state": "Pickup",
"status": {
"description": "Pickup Scheduled",
"last_changed_at": "2015-11-23"
},
"order_url": "https://api.sendle.com/api/orders/f5233746-71d4-4b05-bf63-56f4abaed5f6",
"sendle_reference": "S3ND73",
"tracking_url": "https://track.sendle.com/tracking?ref=S3ND73",
"metadata": {
"your_data": "XYZ123"
},
"labels": [
{
"format": "pdf",
"size": "a4",
"url": "https://api.sendle.com/api/orders/f5233746-71d4-4b05-bf63-56f4abaed5f6/labels/a4.pdf"
},
{
"format": "pdf",
"size": "cropped",
"url": "https://api.sendle.com/api/orders/f5233746-71d4-4b05-bf63-56f4abaed5f6/labels/cropped.pdf"
}
],
"scheduling": {
"is_cancellable": true,
"pickup_date": "2015-11-24",
"picked_up_on": null,
"delivered_on": null,
"estimated_delivery_date_minimum": "2015-11-26",
"estimated_delivery_date_maximum": "2015-11-27"
},
"description": "Kryptonite",
"kilogram_weight": "1.0",
"weight": {
"value": "1",
"units": "kg"
},
"cubic_metre_volume": "0.01",
"volume": {
"value": "0.01",
"units": "m3"
},
"customer_reference": "SupBdayPressie",
"sender": {
"contact": {
"name": "Lex Luthor",
"phone": "0412 345 678",
"email": "lluthor@gmail.com",
"sendle_id": "sendleID",
"company": "LexCorp"
},
"address": {
"address_line1": "123 Gotham Ln",
"address_line2": null,
"suburb": "Sydney",
"state_name": "NSW",
"postcode": "2000",
"country": "Australia"
},
"instructions": "Knock loudly"
},
"receiver": {
"contact": {
"name": "Clark Kent",
"phone": null,
"email": "clarkissuper@dailyplanet.xyz",
"company": "Daily Planet"
},
"address": {
"address_line1": "80 Wentworth Park Road",
"address_line2": null,
"suburb": "Glebe",
"state_name": "NSW",
"postcode": "2037",
"country": "Australia"
},
"instructions": "Give directly to Clark"
},
"route": {
"description": "Sydney to Sydney",
"type": "same-city",
"delivery_guarantee_status": "eligible"
},
"price": {
"tax": {
"currency": "AUD",
"amount": 0.81
},
"net": {
"currency": "AUD",
"amount": 8.14
},
"gross": {
"currency": "AUD",
"amount": 8.95
}
}
}
Viewing an order will give you all the details associated with an existing Sendle Booking. Important details in an order include:
Field | Description |
---|---|
order_id | The order’s individual identification in Sendle’s system. |
state | Identifies the current state of the order. Visit Order states for more information. |
status | Extra information about order state: a user-friendly description , and last_changed_at is the date that the order changed to the current state |
order_url | Specific url for order queries. After booking, this url becomes the point to check for updated information (state changes), labels and any other information related to the order. |
sendle_reference | Reference ID for a Sendle Order. References begin with an “S” and are an alphanumeric string six or more characters in length. |
tracking_url | The order’s public tracking page. Tracking page updates as the parcel progresses from sender to receiver. The url can be shared and viewed without a Sendle Account and contains no personal information about either party. |
labels | Covered in detail in the label section. Contains URLs to retrieve labels in different formats. |
scheduling | Information regarding the order’s delivery status and whether an order can be cancelled. Some fields return null depending on the state of the order. |
pickup_date is the date the courier has been requested to pick up the parcel. picked_up_on is the date the parcel was actually picked up. |
|
estimated_delivery_date_minimum and estimated_delivery_date_maximum can change depending on courier conditions. |
|
route | Information about the route. |
description is a human readable description of the route. |
|
type is a machine readable version of the route type. One of same-city , national , remote , or export |
|
delivery_guarantee_status only present when the account has enrolled in our 2-Day Delivery Guarantee. Values can be eligible or ineligible . |
|
price | The amount charged for this order. |
Getting Labels
GET {label_url}
[ GET {label_url} ]
curl "https://api.sendle.com/api/orders/f5233746-71d4-4b05-bf63-56f4abaed5f6/labels/a4.pdf"
-u "sendleID:APIKey"
-o "local_label_filename.pdf"
-L
A4/cropped label data within AU order response
{
"labels": [
{
"format": "pdf",
"size": "a4",
"url": "https://api.sendle.com/api/orders/f5233746-71d4-4b05-bf63-56f4abaed5f6/labels/a4.pdf"
},
{
"format": "pdf",
"size": "cropped",
"url": "https://api.sendle.com/api/orders/f5233746-71d4-4b05-bf63-56f4abaed5f6/labels/cropped.pdf"
}
]
}
Letter/cropped label data within US order response
{
"labels": [
{
"format": "pdf",
"size": "letter",
"url": "https://api.sendle.com/api/orders/b152ecca-35a2-4da4-884d-c892bc912b82/labels/letter.pdf"
},
{
"format": "pdf",
"size": "cropped",
"url": "https://api.sendle.com/api/orders/b152ecca-35a2-4da4-884d-c892bc912b82/labels/cropped.pdf"
}
]
}
Sendle currently has two labels to choose from:
- A cropped label and
- An A4-sized (AU) or letter (US) sheet with a single label.
Both labels are formatted as PDFs. Labels are stored within the order hash as an array (see example on right). Each label is a hash with a format
, size
, and url
.
Using our order response, we can download the label by using cURL and our preferred label’s url
. The label url will redirect you to a private PDF, do not cache this redirect URL as the access permissions expire after 1 minute.
Because of the redirect, special handling is needed. Adding the -L
flag will follow the redirect to the label from within Sendle. If you are using cURL you can add the -O
(Open) option to save the label with the remote file name, or -o <filename>
to specify a file name locally.
This option is only valid once an order has been booked with a courier.
Track a Parcel
GET /api/tracking/{ref}
[ GET /api/tracking/{ref} ]
curl "https://api.sendle.com/api/tracking/S3ND73"
200 Response
{
"state": "Delivered",
"tracking_events":
[
{
"event_type": "Pickup Attempted",
"scan_time": "2015-11-23T01:04:00Z",
"description": "We attempted to pick up the parcel but were unsuccessful",
"reason": "Parcel not ready"
},
{
"event_type": "Pickup",
"scan_time": "2015-11-24T20:31:00Z",
"description": "Parcel picked up"
},
{
"event_type": "Info",
"scan_time": "2015-11-25T01:04:00Z",
"description": "In transit between locations"
},
{
"event_type": "In Transit",
"scan_time": "2015-11-25T01:14:00Z",
"description": "In transit",
"origin_location": "Sydney",
"destination_location": "Brisbane"
},
{
"event_type": "Info",
"scan_time": "2015-11-26T19:46:00Z",
"description": "Arrived at the depot for processing"
},
{
"event_type": "Info",
"scan_time": "2015-11-26T23:00:00Z",
"description": "Parcel is loaded for delivery"
},
{
"event_type": "Delivered",
"scan_time": "2015-11-27T23:46:00Z",
"description": "Parcel delivered"
},
{
"event_type": "Info",
"scan_time": "2015-11-27T23:47:00Z",
"description": "Your parcel was signed for by JIMMY"
},
],
"origin": {"country": "AU"},
"destination": {"country": "AU"},
"scheduling": {
"pickup_date": "2015-11-24",
"picked_up_on": null,
"delivered_on": null,
"estimated_delivery_date_minimum": "2015-11-26",
"estimated_delivery_date_maximum": "2015-11-27"
}
}
Order tracking gives the public details associated with a Sendle order based on the order’s Sendle Reference as a search key (as ref
above). The API response returns two sections as described below.
Order tracking does not contain personal location information.
Field | Description |
---|---|
state | The current state of the order |
tracking_events | The set of tracking scans from pickup to delivery (if any). See table below for description of fields |
origin | The origin of the parcel, this currently only shows the country. If there is no origin, this might be blank. |
destination | The destination of the parcel, this currently only shows the country. If there is no destination yet, this might be blank. |
scheduling | Information regarding the order’s delivery status. Some fields return null depending on the state of the order. |
pickup_date is the date the courier has been requested to pick up the parcel. picked_up_on is the date the parcel was actually picked up. |
|
estimated_delivery_date_minimum and estimated_delivery_date_maximum can change depending on courier conditions. |
Tracking events
Each tracking event may include any of the following fields:
Field | Description |
---|---|
event_type | Type of scan event. Options usually are Pickup , Info , or Delivered , though there are many tracking event types explained on the table below. |
scan_time | Timestamp marker for a tracking event scan. Scans are set in the UTC time zone. |
description | A short description for the tracking event. |
origin_location | Marks the departure location of a parcel from a physical hub within an order’s transit. |
destination_location | Marks the arrival location of a parcel to a physical hub in the courier network. |
location | City, state, and country information from the tracking event (eg “SYDNEY, NSW, Australia”). |
reason | Some event types have a reason recorded (eg an attempted delivery will often record the reason why the parcel was not able to be picked up). |
requester | Some event types have a requester (eg if the customer has contacted us with an issue). |
Event Type | Description |
---|---|
Pickup | Parcel successfully picked up. |
Info | Information received from courier. |
In Transit | Parcel in transit between courier hub locations. |
Delivered | Parcel successfully delivered. |
Delivery Attempted | Parcel delivery attempted, but unsuccessful. |
Card Left | Parcel delivery attempted, card left for receiver to arrange collection or re-delivery where available. |
Left with Agent | Parcel left with agent, this will be a parcel connect location, POPStation, or similar. |
Delivery Failed | Delivery failed. |
Origin / Destination Address
Currently this only shows the country of the origin/destination as an ISO 3166-1 alpha-2 country code. For example “AU” for Australia, “US” for United States.
Field | Description |
---|---|
country | ISO 3166-1 alpha-2 country code. For example “AU” for Australia, “US” for United States. This might be blank if there is no origin/destination address yet. |
Cancelling Orders
DELETE /api/orders/{id}
[ DELETE /api/orders/{id} ]
curl "https://api.sendle.com/api/orders/f5233746-71d4-4b05-bf63-56f4abaed5f6"
-X DELETE
-u "sendleID:APIKey"
-H "Content-Type: application/json"
-H "Accept: application/json"
200 Response
{
"order_id": "f5233746-71d4-4b05-bf63-56f4abaed5f6",
"state": "Cancelled",
"order_url": "https://api.sendle.com/api/orders/f5233746-71d4-4b05-bf63-56f4abaed5f6",
"sendle_reference": "S3ND73",
"tracking_url": "https://track.sendle.com/tracking?ref=S3ND73",
"customer_reference": "SupBdayPressie",
"cancelled_at": "2015-10-15 00:56:51 UTC",
"cancellation_message": "Cancelled by S6LRX64PV8MABbBbzu6DoBHD during picking up"
}
As long as an order has not been collected by the courier, an order is cancellable. The value to review is:
is_cancellable | If true , the order can be cancelled. |
If a booking has already been collected by the courier, a failure response (422) will be returned. is_cancellable
is found in the scheduling
section of the JSON
along with delivery estimates. For an example of where is_cancellable
can be seen, check the View an Order section.
Note: the order is not deleted from the system and should still be viewable on your dashboard in the “cancelled” state.
Order states
A part of viewing an order
{
"state": "Pickup",
"status": {
"description": "Pickup Scheduled",
"last_changed_at": "2015-11-23"
}
}
States
Sendle uses a handful of terms to describe an order’s state within the shipment process. These are similar to the states used in Sendle Dashboard to describe tracking progress, but are not an exact match.
Orders start in BOOKING
, and typically proceed through each of the states until they either reach DELIVERED
or end in one of the failure states (eg LOST
).
The state workflow of a successful delivery looks like this:
BOOKING
-> PICKUP
-> IN_TRANSIT
-> DELIVERED
All other states represent either deliberate cancellation of the order, or some kind of failure during the above process.
State | Description |
---|---|
Booking | Order is still being created and has not yet been scheduled for delivery. |
Pickup | Booking has been consigned and Courier is scheduled to pick up the parcel. |
Pickup Attempted | An unsuccessful parcel pickup was attempted. |
Transit | Parcel is in transit. |
Delivered | Parcel has been successfully delivered. |
Cancelled | A cancelled order. |
Unable to Book | An order which cannot be booked. |
Lost | An order marked as missing or lost. |
Return to Sender | An order which is being returned to the sender. |
Status
The status
section gives a bit more information about the current state of the order.
It currently contains two fields:
description
is a user-friendly description of the order-statelast_changed_at
this is the date at which the order changed to this state
Prepare Form URL
https://www.sendle.com/dashboard/prepare_form
[ https://www.sendle.com/dashboard/prepare_form ]
The Prepare Form URL pre-fills a Send Parcel Form with pickup and delivery details.
This service requires a valid Sendle account with a confirmed email address.
Parcel Pickup Details
There are two ways to provide parcel pickup details for the Prepare Form URL.
The recommended approach is to use the customer’s default Sendle pickup details. To do this, make sure that none of the pickup_address_*
or sender_*
parameters are provided.
The other approach is to provide the full set of pickup_address_*
and sender_*
fields. In this case, the users’ defaults are ignored. The form is filled with only the parameters provided. This means any missing or blank parameters need to be manually completed by the user. For example, if only sender_name
and sender_contact_number
are provided, the user will need to fill in pickup address and instructions on the form before sending.
Therefore, if providing any of these parameters we recommend populating the complete set. This will reduce the manual entry required by the user.
If the parcel is being dropped off, the pickup_address_ fields will be ignored.
The available sender fields are:
sender_name
sender_contact_number
sender_email
pickup_instructions
pickup_address_line1
pickup_address_line2
pickup_address_suburb
pickup_address_postcode
pickup_address_state
URL Parameters Details
https://www.sendle.com/dashboard/prepare_form?pickup_date=2017%2D04%2D03&customer_reference=Flower+Delivery&kilogram_weight=1&cubic_metre_volume=0.001&receiver_name=Oscar+Wilde&delivery_address_line1=2+Smith+Lane&delivery_address_suburb=Sydney&delivery_address_state=NSW&delivery_address_postcode=2000
Data Field | Attributes |
---|---|
PARCEL DETAILS | Details about the parcel. |
pickup_date yyyy-mm-dd optional |
If provided the date must be at least one non-holiday, business day in the future. If pickup date is omitted it will be set to the first available pickup date option. |
description | Description is used by the customer to track the parcel on Sendle Dashboard. It does not show up on a label. It must be under 255 characters in length. |
kilogram_weight optional |
Must be a decimal value greater than 0 and less than the maximum allowed weight of 25kg. |
parcel_weight_value optional |
Must be one of kg , g , oz or lb . Takes precedence over kilogram_weight . Required if parcel_weight_units is provided. |
parcel_weight_units optional |
Parcel weight in format specified in parcel_weight_value Takes precedence over kilogram_weight . Required if parcel_weight_value is provided. |
cubic_metre_volume optional |
Must be a value between 0 and 0.1 (m³). When included, value will be length x width x depth of parcel in metres. |
parcel_size_units optional |
Must be one of m3 , in3 or ft . Takes precedence over cubic_metre_volume . Required if other parcel_size_* values are provided. |
parcel_size_length optional |
Parcel length as specified in parcel_size_units . Takes precedence over cubic_metre_volume . Required if other parcel_size_* values are provided. |
parcel_size_width optional |
Parcel height as specified in parcel_size_units . Takes precedence over cubic_metre_volume . Required if other parcel_size_* values are provided. |
parcel_size_height optional |
Parcel height as specified in parcel_size_units . Takes precedence over cubic_metre_volume . Required if other parcel_size_* values are provided. |
customer_reference optional |
Reference will appear on the label for parcel identification. It must be under 255 characters in length. |
RECEIVER DETAILS | Details about the receiver. |
delivery_instructions optional |
Short message used as delivery instructions for courier. It must be under 255 chars, but is recommended to be under 40 chars due to label-size limitations. |
receiver_name optional |
It must be under 255 characters in length. |
receiver_email optional |
Allows Sendle to send parcel updates to the recipient. |
receiver_contact_number optional |
Used to coordinate pickup if the courier is outside attempting delivery. It must be a valid Australian phone number (including area code), or fully qualified international number. Examples: (02) 1234 1234, +1 519 123 1234, +61 (0)4 1234 1234. |
delivery_address_line1 optional |
The street address where the parcel will be delivered. Addresses can be split over two lines using delivery_address_line1 and delivery_address_line2 . delivery_address_line2 will be displayed below delivery_address_line1 on the parcel label. Do not include postcode, state, or suburb in this field. It must be under 255 char in length, but best practice to keep under 40 chars due to label-size limitations. |
delivery_address_line2 optional |
Second line of the street address for the delivery location. |
delivery_address_suburb optional |
Suburb or town where the parcel is to be delivered. |
delivery_address_postcode optional |
Postcode of destination location. It must be a four digits. |
delivery_address_state optional |
Must be the destination location’s state or territory. Valid options include: ACT, NSW, NT, QLD, SA, TAS, VIC, WA. Long-form (i.e. “Northern Territory”) is also accepted. |
SENDER DETAILS | We recommend omitting these. If you provide one, provide all. See Parcel Pickup for details. |
sender_name optional |
It must be under 255 characters in length. |
sender_email optional |
Allows Sendle to send parcel updates to the sender. |
sender_contact_number optional |
Used to coordinate pickup if the courier is outside attempting delivery. It must be a valid Australian phone number (including area code), or fully qualified international number. Examples: (02) 1234 1234, +1 519 123 1234, +61 (0)4 1234 1234. |
pickup_instructions optional |
Short message used as pickup instructions for courier. It must be under 255 chars, but is recommended to be under 40 chars due to label-size limitations. |
pickup_address_line1 optional |
The street address where the parcel will be picked up. Addresses can be split over two lines using pickup_address_line1 and pickup_address_line2 . pickup_address_line2 will be displayed below pickup_address_line1 on the parcel label. Do not include postcode, state, or suburb in this field It must be under 255 char in length, but best practice to keep under 40 chars due to label-size limitations. |
pickup_address_line2 optional |
Second line of the street address for the pickup location. |
pickup_address_suburb optional |
Suburb or town where the parcel is to be picked up. |
pickup_address_postcode optional |
Postcode of pickup location. It must be a four digits. |
pickup_address_state optional |
Must be the pickup location’s state or territory. Valid options include: ACT, NSW, NT, QLD, SA, TAS, VIC, WA. Long-form (i.e. “Northern Territory”) is also accepted. |
Validation Errors
Example response - single error
{
"messages": {
"pickup_date": [
"must be a business day and at least one business day in the future."
]
},
"error": "unprocessable_entity",
"error_description": "The data you supplied is invalid. Error messages are in the messages section. Please fix those fields and try again."
}
Example response - multiple errors
{
"messages": {
"pickup_date": [
"must be a business day and at least one business day in the future."
],
"cubic_metre_volume": [
"must be less than or equal to 0.5"
],
"description": [
"is too long (maximum is 255 characters)"
],
"sender": [
{
"contact": [
{
"phone": [
"must be a valid phone number. 13, 1300, and 1800 numbers are not allowed."
]
}
],
"intructions": [
"is too long (maximum is 200 characters)"
]
},
],
"receiver": [
{
"contact": [
{
"email": [
"must be a valid email address"
],
"name": [
"is too long (maximum is 200 characters)"
]
}
]
}
]
},
"error": "unprocessable_entity",
"error_description": "The data you supplied is invalid. Error messages are in the messages section. Please fix those fields and try again."
}
The following validations will apply during order creation. Each has an example of the error that is returned if the validation fails.
Each of these will be returned with a 422 HTTP error code. See also HTTP Error codes for other kinds of errors that can occur.
The "messages"
, "error"
and "error_description"
sections use the same structure for all error responses. In the examples that detail individual errors (on your right), I will omit the error
/error_description
sections so as not to continually repeat them. I will only show the contents of the messages
section.
Required fields
Minimum mandatory field list
description
kilogram_weight OR cubic_metre_volume
sender
contact
name
address
address_line1
suburb
postcode
state_name
country
receiver
contact
name
address
address_line1
suburb
postcode
state_name
country
instructions
Example with minimum mandatory fields
curl "https://api.sendle.com/api/orders"
-X POST
-u "sendleID:APIKey"
-H "Content-Type: application/json"
-H "Accept: application/json"
-d '{
"description": "Kryptonite",
"kilogram_weight": 1,
"sender": {
"contact": {
"name": "Lex Luthor"
},
"address": {
"address_line1": "123 Gotham Ln",
"suburb": "Sydney",
"state_code": "NSW",
"postcode": "2000"
}
},
"receiver": {
"contact": {
"name": "Clark Kent"
},
"address": {
"address_line1": "80 Wentworth Park Road",
"suburb": "Foul Bay",
"state_name": "South Australia",
"postcode": "5577"
},
"instructions": "receiver instructions"
}
}'
Required fields errors
{
"messages": {
"description": ["can't be blank"],
"kilogram_weight": ["can't be blank"],
"sender": [
{
"contact": [
{
"name": ["can't be blank"]
}
],
"address": [
{
"suburb": ["can't be blank"],
"postcode": ["can't be blank"],
"state_code": ["can't be blank"],
"address_line1": ["can't be blank"],
"state_name": ["can't be blank"]
}
]
}
],
"receiver": [
{
"contact": [
{
"name": ["can't be blank"]
}
],
"address": [
{
"suburb": ["can't be blank"],
"postcode": ["can't be blank"],
"state_code": ["can't be blank"],
"address_line1": ["can't be blank"],
"state_name": ["can't be blank"]
}
],
"instructions": ["can't be blank"]
}
]
}
}
Many fields are mandatory in order to book an order for pickup. At right is outlined the minimum-necessary set of fields required for an order and an example cURL script using them.
Note: Sendle will automatically populate the pickup-date with the next business day.
Parcel details
description
is missing
{
"messages": {
"description": ["can't be blank"]
}
}
description
is too long
{
"messages": {
"description": ["is too long (maximum is 255 characters)"]
}
}
pickup_date
is not a business date in the future
{
"messages": {
"pickup_date": [
"must be a business day and at least one business day in the future."
]
}
}
weight/volume too much
{
"messages": {
"kilogram_weight": ["must be less than or equal to 25.0"],
"cubic_metre_volume": ["must be less than or equal to 0.1"]
}
}
weight/volume negative
{
"messages": {
"kilogram_weight": ["must be greater than or equal to 0"],
"cubic_metre_volume": ["must be greater than or equal to 0"]
}
}
neither weight nor volume supplied
{
"messages": {
"kilogram_weight": ["can't be blank"]
}
}
customer_reference
too long
{
"messages": {
"customer_reference": ["is too long (maximum is 255 characters)"]
}
}
metadata
not JSON
{
"messages": {
"metadata": ["must be a JSON object"]
}
}
metadata
too long
{
"messages": {
"metadata": ["must be less than 1MB"]
}
}
Description
There must be a description. It must be under 255 characters in length.
Pickup date
The Pickup Date must either be valid (a business day in the future), or be left blank (which will be auto-populated with the Next Business Day) for parcels being picked up.
Weight and volume
The weight and volume must be greater than 0, and within range (25kg for weight, 0.1m^3 for volume).
Either kilogram_weight
or cubic_metre_volume
must be supplied
Customer Reference
The customer_reference
must be under 255 characters in length.
Metadata
metadata
must be a valid JSON object that is less that 1MB in size
Sender/Receiver details
Instructions too long
{
"messages": {
"sender": [
{
"instructions": ["is too long (maximum is 200 characters)"]
}
],
"receiver": [
{
"instructions": ["is too long (maximum is 200 characters)"]
}
]
}
}
Non-satchel and receiver instructions absent
{
"messages": {
"receiver": [
{
"instructions": ["can't be blank"]
}
]
}
}
Satchel and receiver instructions present
{
"messages": {
"receiver": [
{
"instructions": [
"No delivery instructions are allowed when booking at satchel rates - all satchels are 'Authority to Leave'"
]
}
]
}
}
Instructions
Instructions (both sender and receiver) must be under 200 characters in length.
Receiver instructions
Receiver instructions must be populated if the order is not a satchel
Receiver instructions must be blank if the order will be a satchel - ie the weight is less than or equal to 500gm AND the volume less than or equal to 8 litres
Contact details
Name absent
{
"messages": {
"receiver": [
{
"contact": [
{
"name": ["can't be blank"]
}
]
}
],
"sender": [
{
"contact": [
{
"name": ["can't be blank"]
}
]
}
]
}
}
Name too long
{
"messages": {
"receiver": [
{
"contact": [
{
"name": ["is too long (maximum is 255 characters)"]
}
]
}
],
"sender": [
{
"contact": [
{
"name": ["is too long (maximum is 255 characters)"]
}
]
}
]
}
}
Phone format invalid or 1300
{
"messages": {
"receiver": [
{
"contact": [
{
"phone": [
"must be a valid phone number. 13, 1300, and 1800 numbers are not allowed."
]
}
]
}
],
"sender": [
{
"contact": [
{
"phone": [
"must be a valid phone number. 13, 1300, and 1800 numbers are not allowed."
]
}
]
}
]
}
}
Email/Sendle ID not valid
{
"messages": {
"receiver": [
{
"contact": [
{
"email": ["must be a valid email address"],
"sendle_id": ["doesn't exist"]
}
]
}
]
}
}
Name
There must be a Sender and a Receiver name. They must be under 255 characters in length.
Phone
Any provided phone must be a valid Australian number. (eg. “(02) 2222 2222” or “0411 111 111” or “+61 4 1111 1111”). 1300 and 1800 numbers are not permitted.
Email / Sendle ID
Any email provided must be valid email (see format) Any provided Sendle ID must be correct for a valid account on the server you are using.
Addresses
Country must be Australia
{
"messages": {
"receiver": [
{
"address": [
{
"postal_code_lookup": ["- country must be Australia"],
"state_name": ["New South Wales does not match any of our known states for your given country."]
}
]
}
]
}
}
Address details must be provided
{
"messages": {
"receiver": [
{
"address": [
{
"suburb": ["can't be blank"],
"state_code": ["can't be blank"],
"state_name": ["can't be blank"],
"postcode": ["can't be blank"]
}
]
}
]
}
}
Address lines must not be too long
{
"messages": {
"receiver": [
{
"address": [
{
"address_line1": [
"is too long (maximum is 255 characters)"
],
"address_line2": [
"is too long (maximum is 255 characters)"
]
}
]
}
]
}
}
Suburb doesn’t match postcode - single match
{
"messages": {
"sender": [
{
"address": [
{
"suburb": [
"Leura does not match the postcode: 2782. Perhaps try: Wentworth Falls"
],
"postcode": [
"2782 does not match the suburb: Leura. Perhaps try: 2780"
]
}
]
}
]
}
}
Suburb doesn’t match postcode - multiple matches
{
"messages": {
"sender": [
{
"address": [
{
"suburb": [
"Sydney does not match the postcode: 2780. Perhaps try: Katoomba, Katoomba DC, Leura, and Medlow Bath"
],
"postcode": [
"2780 does not match the suburb: Sydney. Perhaps try: 1001, 1002, 1003, 1004, 1005, 1006, 1007, 1008, 1009, 1010, 2000, and 2001"
]
}
]
}
]
}
}
Address details don’t match state
{
"messages": {
"sender": [
{
"address": [
{
"state_name": [
"We found your postcode and suburb, but they aren't in the state you gave: VIC instead they are in: QLD, perhaps you could change the state to match?"
]
}
]
}
]
}
}
Address is not serviceable by Sendle (eg a GPO)
{
"messages": {
"sender": [
{
"address": ["is not yet serviced by Sendle"]
}
]
}
}
Address doesn’t exist in Australia
{
"messages": {
"sender": [
{
"address": [
{
"postal_code_lookup": ["- country must be Australia"],
"state_name": [
"Berkshire does not match any of our known states for your given country."
],
"suburb": ["Slough does not match any of our known suburbs."],
"postcode": ["9999 does not match any of our known postcodes."]
},
"is not yet serviced by Sendle"
]
}
]
}
}
Country
country
(if given) must be a valid country that we service. Currently we only service Australia.
Address lines 1 and 2
Must be under 255 characters in length.
Suburb, postcode, and state
Of suburb, postcode, state - all three must be present. You can provide
either the state_name
or state_code
field (see descriptions in order creation )
For US orders, a ZIP code can be used as the value for postcode
.
Due to our postal-code-lookup there may be errors on fields that you are not required to enter (eg state_code
and postal_code_lookup
) - fix the main fields and these will be resolved.
We usually refer to the combination of suburb+postcode+state as a location.
These fields must all match an existing location in Australia or the United States. We use the freely available Geonames database for validating, and we encourage integrations to use that same dataset.
Note that if the suburb/postcode/state are found but don’t match, the error message will try to suggest alternatives. This is sometimes useful if the state has been entered incorrectly (see the examples at right).
Servicability
The pickup and delivery addresses must be serviceable by Sendle. Check Sendle’s US and AU locations and coverage. An example of an unserviceable location would be a GPO or PO box.
HTTP Error Codes
The Sendle API uses the following error codes:
Error Code | Meaning |
---|---|
400 | Bad Request – The data provided by the client (typically in the body) is invalid or incorrectly structured. |
401 | Unauthorized – The authorisation details are invalid. Either the Sendle ID, the API key (or both) are incorrect and should be fixed. |
402 | Payment Required – The client does not yet have a payment-method set up on their account, and cannot create orders. |
404 | Not Found – The requested resource/URI was not found. |
422 | Unprocessable Entity – The server was unable to complete the request due to the data itself. For example, validations within the data may fail, or an upstream request may not be able to be fulfilled with the data. This is different to 400 Bad Request as 422 Unprocessable Entity suggests that the request sent by the client was structurally valid, and the request was attempted. |
500 | Internal Error – An unhandled error has occured with the Sendle API. Contact support@sendle.com if the problem persists. |
503 | Not Available – The server is currently unavailable, due to maintenance or upgrades. |
400 Bad request
curl -i "https://api.sendle.com/api/orders"
-X POST
-u "sendleID:APIKey"
-H "Content-Type: application/json"
-d ']'
400 Response Header information:
HTTP/1.1 400 Bad Request
Content-Type: text/html; charset=utf-8
Content-Length: 0
Invalid request format
When an invalid request is sent to the API, there is no visible response. This will include mostly formatting errors.
401 Unauthorised
401 Response after request without/incorrect Sendle ID or API Key
{
"error": "unauthorised",
"error_description": "The authorisation details are not valid. Either the Sendle ID or API key are incorrect."
}
Invalid sendle_id or api_key
If you have entered your Sendle ID or API Key incorrectly, you may want to double check your account details.
402 Payment Required
402 Response after POST valid order
{
"error": "payment_required",
"error_description": "The account associated with this API key has no method of payment. Please go to your Account Settings in your Sendle Dashboard and add a payment method."
}
Payment details not found
Without a credit card on file, booking orders will respond with a 402
error.
Non-booking queries will continue to work without payment and will not receive an error.
404 Not Found
404 Response when entering incorrect Order ID
{
"error": "not_found",
"error_description": "The resource you requested was not found. Please check the URI and try again."
}
Incorrect URI
If an Order ID or label url is incorrectly entered, a 404
error will be returned. Double-check the ID or url before continuing.
412 Precondition Failed
412 Response after POST valid order
{
"error": "precondition_failed",
"error_description": "The account associated with this API key has not accepted the dangerous goods terms. Please visit your Account Settings in your Sendle Dashboard to view and accept these terms."
}
Dangerous goods terms have not been accepted
Without accepting dangerous goods terms, booking orders will respond with a 412
error.
Non-booking queries will continue to work without accepting dangerous goods terms and will not receive an error.
422 Unprocessable Entity
Request with unallowable errors:
curl "https://api.sendle.com/api/orders"
-u "sendleID:APIKey"
-H "Content-Type: application/json"
-X POST
-d '{
"pickup_date": "2012-12-25",
"description": "Showing 400 Error",
"kilogram_weight": "1",
"cubic_metre_volume": "1.1",
"customer_reference": "Four hundred twenty two",
"sender": {
"contact": {
"name": "Sendle API",
"sendle_id": "sendleAPI",
"phone": "1300 345 678"
},
"address": {
"address_line1": "123 Test Ave",
"suburb": "Acton",
"state_name": "ACT",
"postcode": "2601",
"country": "Australia"
},
"instructions": "Just a test."
},
"receiver": {
"contact": {
"name": "Jim",
"email": "emailaddress.com"
},
"address": {
"address_line1": "80 Wentworth Park Road",
"suburb": "Glebe",
"state_name": "NSW",
"postcode": "2037",
"country": "Australia"
},
"instructions": "Please leave inside the door."
}
}'
422 Response
{
"messages": {
"pickup_date": [
"must be a business day and at least one business day in the future."
],
"cubic_metre_volume": [
"must be less than or equal to 0.5"
],
"sender": [
{
"contact": [
{
"phone": [
"must be a valid phone number. 13, 1300, and 1800 numbers are not allowed."
]
}
]
}
],
"receiver": [
{
"contact": [
{
"email": [
"must be a valid email address"
]
}
]
}
]
},
"error": "unprocessable_entity",
"error_description": "The data you supplied is invalid. Error messages are in the messages section. Please fix those fields and try again."
}
Data format was correct but contained unprocessable information
422
errors occur most commonly as users become more familiar with the API. These errors occur when the server receives your request, it is properly formatted, but the information can not be processed as is.
This error-code most often occurs when POSTing data to the API (eg when creating an order) and some of the sent data are invalid (eg a pickup date is in the past or the receiver address was missing). See the validation errors section for more detail.
Be sure to check the error messages as the server response will explain why the request could not be processed and often give suggestions.
503 Not Available
From time to time we might require a short outage to carry out maintenance or upgrades. In most cases the API will return a HTTP 503 error response.
503 Response
{
"error":"service_unavailable",
"error_description":"Service is temporarily unavailable. Please check back soon."
}
Idempotency keys
What are they and why do I want one?
Example ping request with idempotency
curl 'https://api.sendle.com/api/ping'
-u sendleID:APIKey
-H "Content-Type: application/json"
-H "Accept: application/json"
-H "Idempotency-Key: 6f4aba46-91d4-6ef3-af23-f523375ed5f6"
Example order-creation request with idempotency
curl "https://api.sendle.com/api/orders"
-X POST
-u "sendleID:APIKey"
-H "Content-Type: application/json"
-H "Accept: application/json"
-H "Idempotency-Key: 6f4aba46-91d4-6ef3-af23-f523375ed5f6"
-d '{
"pickup_date": "2015-11-24",
"description": "Kryptonite",
"kilogram_weight": "1",
"cubic_metre_volume": "0.01",
"customer_reference": "SupBdayPressie",
"metadata": {
"your_data": "XYZ123"
},
"sender": {
"contact": {
"name": "Lex Luthor",
"phone": "0412 345 678"
},
"address": {
"address_line1": "123 Gotham Ln",
"suburb": "Sydney",
"state_name": "NSW",
"postcode": "2000",
"country": "Australia"
},
"instructions": "Knock loudly"
},
"receiver": {
"contact": {
"name": "Clark Kent",
"email": "clarkissuper@dailyplanet.xyz"
},
"address": {
"address_line1": "80 Wentworth Park Road",
"suburb": "Glebe",
"state_name": "NSW",
"postcode": "2037",
"country": "Australia"
},
"instructions": "Give directly to Clark"
}
}'
Idempotency keys are used to prevent duplicate actions occurring when you did not intend for them to be duplicates.
Let me outline two example order-creation scenarios you might use these for:
1) you have a web-form for people to enter order-details that are then submitted to us. Somebody accidentally manages to double-click on the “submit order” button, but you want to make sure that only one order is created.
2) you submit an order to us, but there’s a glitch in the internet and you don’t get a response back from us… how do you tell whether the order was successfully created or not? If you resend the order-create details, will it create a duplicate order?
Customers sometimes make mistakes, and the internet is sometimes flakey… but we want things to run smoothly anyway, if at all possible.
Idempotency keys help reduce these problems by giving us a little more surety that we don’t accidentally duplicate “mutating actions” (ie actions that have consequences).
They work as follows (we’ll use order-creation as the example):
- You create a unique string that serves as the key for this transaction - eg a UUID
- You send this key with your order-creation params, to identify that this set of params is intended to be a given order.
- If we receive this key, we will store it and the params you sent, and try creating the order.
- Any response we would normally send to you, we will also store against this key.
- If we see this key again we won’t try to create a new order, but just return the existing response.
In essence, it works a little like caching.
Also note that a “response” can include 4XX
error responses, not just successful order creation. Any validation errors, for example, would be cached alongside the params that cause them, when using a given key.
5XX
error responses are not cached and requests can be safely replayed using the same idempotency key.
Here is what happens in the two scenarios outlined above:
Scenario 1 (double-submit):
- You generate an idempotency key and add it to the web form as a hidden field.
- You submit the key to us in the headers, together with the rest of the fields.
- The first click comes through to us with the key and we create an order and store it against that key.
- The second click comes through to us with the same key and we retrieve and return the same order to you instead of creating a new one.
Scenario 2 (super flakey internet connection):
- You generate an idempotency key and send it through to us with the order submission.
- You receive no response within your timeout period, because we never received the request in the first place (there’s a flakey server in between us randomly dropping packets)
- Knowing that no duplicate will be created, you can poll us every so often, resending the same key+params until you receive a response
- Maybe once more, the request gets lost along the way, but eventually one gets through to us.
- We create the order and try sending it back… but now the response gets lost.
- We eventually receive your request again - and retrieve the order-response we stored against that key…
- and this time the response gets through to you too! success at last!
Which endpoints are they available on?
Idempotency is only really required for “mutating” endpoints - ie endpoints where something permanent changes each time you hit it… the best example is order-creation, of course. Each time you send params to order-creation, you, in theory, want a new order created.
Contrast this with order-cancellation. If you re-send a cancel to an order… we won’t double-cancel the order. It’ll still be just as cancelled at the end, whether it’s the first time or the thousandth time (though please don’t cancel a 1000 times :D), so it doesn’t need idempotency to protect it.
Right now the keys are available for order-creation, and we also have it on the ping-endpoint - not because it needs it, but to make it easier for you to test using idempotency keys. See examples of each of these to the right.
In the future, we will add them to any mutating endpoint that is not already idempotent-by-nature. As in the example above, order-cancellation is naturally idempotent and does not need idempotency-keys added. Likewise any GET request is naturally idempotent. If we were to implement an order-update endpoint, or any other create-endpoint, we would add idempotency to it.
How do I use them?
First you need to generate a unique string to serve as the idempotency key.
Keys cannot be reused for another transaction (eg if you change params), so it’s preferable not to use something like a customer number or an order-id, so we recommend something that is guaranteed unique such as a UUID or a hash of the order-id, customer-id and requested params.
You will pass the key to us in a special header called Idempotency-Key
.
There are some examples to the right, and there are also examples given for the ping-endpoint which exists to help you to test Idempotency Keys
You then just need to periodically poll the endpoint (preferably with random backoff) until you receive a response from us.
Key validity, expiry etc
When you send a key to a different endpoint
{
"error": "conflict",
"error_description": "The idempotency key you have requested already exists with different endpoint"
}
When you send a key with different params
{
"error": "conflict",
"error_description": "The idempotency key you have requested already exists with different params"
}
You can technically use any string-value as your idempotency key, but keep in mind there are two constraints about how they will be used.
1) Your idempotency key must be unique for your account.
If you reuse a key, we will assume you are trying to do the same transaction again, not use a key in a different context. So for each transaction that you want to be unique, you must use a new key.
Thankfully, keys (and their stored responses) are destroyed after 72 hours - after which you can reuse them.
2) Once used, you cannot reuse the same key even if you change endpoint or params
We thought about how best to make this key-system have a fast response-time, and remain simple and clear. The best way to do that is to be zealous in ensuring that you cannot change endpoint or params once they have been associated with a key. This makes it easier to send you back the relevant response quickly.
This means that if your user enters invalid order-creation params, and receives an error telling them which fields to update… Then you will need to generate a new key to send with any updated params.
If you do try to send the same key with different params, (or to a different endpoint) then you will receive a conflict response (see example responses to the right).
Because of these constraints… we recommend using a new UUID every time you make a new submission, but it is also possible to use a hash-value of all of the relevant submission data (eg request-params, endpoint and the order-id+customer-id at your end) to provide a unique id.
Keys are stripped of whitespace before storage, so “ abc123 ” is the same as “abc123”. Likewise, you will receive an error if you try to submit a blank key.
I’m a multi-tenant site, what do I need to be aware of?
Keys need to be unique per Sendle-customer… ie you, not your customers. If two of your customers try to create an order with the exact same details (unlikely as that might be), then you need a way to make the idempotency-key for each of these two orders unique.
We always recommend using a UUID as it’s practically guaranteed to be unique, but if you instead want to hash relevant data, then we recommend adding the relevant customer-id into the hash just to add some uniqueness.
We definitely recommend using a long, randomised key. Shorter, meaningful-valued keys are not as secure. That is why we prefer a UUID.
Note that we check that parameters are the same for any given idempotency-key we see. In part this is for the safety of our multi-tenant customers as it makes it harder for any given malicious user to randomly spoof an idempotency-key and thus use it as a back-channel for gaining access to order-data. The malicious user would have to know not only the idempotency key, but also all the params that were sent with the original request that was made with that key.
Credits
This example API documentation page was created with Slate.