ShopRunBack API Documentation
Welcome on the ShopRunBack public API documentation.
ShopRunBack is the inventor of the Return As A Service solution.
This API provides all the endpoints for any e-commerce retailer to get all the features for an optimized return experience for its customers.
You can also get the swagger documentation on http://api-portal.shoprunback.com.
For feature request, use the built in form: https://dashboard.shoprunback.com/features
If you are coding in PHP, please use our PHP library.
If you got any questions, send an email to: tech_at_shoprunback.com.
Authentication
To authorize your queries, you must provide your company API Token in the HTTP Headers like this:
response = HTTParty.post(
endpoint,
body: content,
headers: {
'Content-Type' => 'application/json',
'Authorization' => "Token token=#{your_token}"
}
)
curl "<endpoint>"
-H "Authorization: Token token=<your_token>"
<?php
// Load the library
require 'path/to/lib/shoprunback-php/init.php';
// Set your token
\Shoprunback\RestClient::getClient()->setToken('your_token');
// Define the environment you want to use (Production or Sandbox)
\Shoprunback\RestClient::getClient()->useProductionEnvironment();
// Here your token is already set
// You can check if your token is correct by loading your ShopRunBack account
$account = \Shoprunback\Elements\Account::getOwn();
Replace
your_token
with your API key.
We use API keys to allow access to the API.
You can get your API key on the dashboard.
ShopRunBack expects for the API key to be included in all API requests to the server in a header that looks like the following:
Authorization: Token token=<your_token>
Products catalog
Once your account created and configured (follow the onboarding process for that), you must push your products catalog. Only products in the ShopRunBack catalog can be returned.
First, create your brands if you have any and then create your products.
Create a brand
body = {
name: "Apple",
reference: "apple"
}
HTTParty.post(
"https://dashboard.shoprunback.com/api/v1/brands",
body: body,
headers: {
'Content-Type' => 'application/json',
'Authorization' => "Token token=#{your_token}"
}
)
curl -X "POST" "https://dashboard.shoprunback.com/api/v1/brands" \
-H "Authorization: Token token=<your_token>" \
-H "Content-Type: application/json; charset=utf-8" \
-d $'{
"name": "Apple",
"reference": "apple"
}'
<?php
// Load the library
require 'path/to/lib/shoprunback-php/init.php';
// Set your token
\Shoprunback\RestClient::getClient()->setToken('your_token');
// Define the environment you want to use (Production or Sandbox)
\Shoprunback\RestClient::getClient()->useProductionEnvironment();
// Create a new blank Brand and add mandatory attributes
$brand = new \Shoprunback\Elements\Brand();
$brand->name = 'Apple';
$brand->reference = 'apple';
// Save the Brand
$brand->save();
The above command returns JSON structured like this:
{
"id": "1f27f9d9-3b5c-4152-98b7-760f56967dea",
"name": "Apple",
"reference": "apple",
"default": false
}
By default, once your retailer account is created and your company details entered, a default Brand is created. But you can add your own Brands if you have multiple Brands in your catalog.
This endpoint creates a new Brand.
HTTP Request
POST https://dashboard.shoprunback.com/api/v1/brands
Query Parameters
Parameter | Required | Description |
---|---|---|
name | yes | Name of the brand, displayed to the customer on the return process |
reference | yes | Unique reference of the brand (if you don’t have any, use the name) |
List your brands
HTTParty.get(
"https://dashboard.shoprunback.com/api/v1/brands",
headers: {
'Content-Type' => 'application/json',
'Authorization' => "Token token=#{your_token}"
}
)
curl -X "GET" "https://dashboard.shoprunback.com/api/v1/brands" \
-H "Authorization: Token token=<your_token>" \
<?php
// Load the library
require 'path/to/lib/shoprunback-php/init.php';
// Set your token
\Shoprunback\RestClient::getClient()->setToken('your_token');
// Define the environment you want to use (Production or Sandbox)
\Shoprunback\RestClient::getClient()->useProductionEnvironment();
// Get all your brands
$brands = \Shoprunback\Elements\Brand::all();
The above command returns JSON structured like this:
[
{
"id": "1f27f9d9-3b5c-4152-98b7-760f56967deb",
"name": "default",
"reference": "default",
"default": true,
},
{
"id": "1f27f9d9-3b5c-4152-98b7-760f56967dea",
"name": "Apple",
"reference": "apple",
"default": false,
},
{
"id": "1f27f9d9-3b5c-4152-98b7-760f56967dec",
"name": "Samsung",
"reference": "samsung",
"default": false,
}
]
This endpoint lists all your brands.
HTTP Request
GET https://dashboard.shoprunback.com/api/v1/brands
Add your products
body = {
"label": "Iphone 14S Blue",
"reference": "IPHONE 14S B",
"ean": "1258987561456",
"weight_grams": 200,
"brand_id": "1f27f9d9-3b5c-4152-98b7-760f56967dea",
"image_url": "http://www.apple.com/images/iphone-14s.jpg"
}
HTTParty.post(
"https://dashboard.shoprunback.com/api/v1/products",
body: body,
headers: {
'Content-Type' => 'application/json',
'Authorization' => "Token token=#{your_token}"
}
)
curl -X "POST" "https://dashboard.shoprunback.com/api/v1/products" \
-H "Authorization: Token token=<your_token>" \
-H "Content-Type: application/json; charset=utf-8" \
-d $'{
"label": "Iphone 14S Blue",
"reference": "IPHONE 14S B",
"ean": "1258987561456",
"weight_grams": 200,
"brand_id": "1f27f9d9-3b5c-4152-98b7-760f56967dea",
"picture_file_url": "http://www.apple.com/images/iphone-14s.jpg"
}'
<?php
// Load the library
require 'path/to/lib/shoprunback-php/init.php';
// Set your token
\Shoprunback\RestClient::getClient()->setToken('your_token');
// Define the environment you want to use (Production or Sandbox)
\Shoprunback\RestClient::getClient()->useProductionEnvironment();
// Create a new Product
$product = new \Shoprunback\Elements\Product();
$product->label = 'Iphone 14S Blue';
$product->reference = 'IPHONE 14S B';
$product->weight_grams = 200;
$product->brand_id = '1f27f9d9-3b5c-4152-98b7-760f56967dea';
$product->ean = '1258987561456';
$product->picture_url = 'https://s3.eu-central-1.amazonaws.com/shoprunback-dev/products/484/7b4/f4-/pictures/medium.?1505912197';
// Save the Product
$product->save();
The above command returns the same JSON object with the id of the created product:
{
"id": "1f27f9d9-3b5c-4152-98b7-760f56967dea",
"label": "Iphone 14S Blue",
"reference": "IPHONE 14S B",
"ean": "1258987561456",
"weight_grams": 200,
"picture_url": "https://s3.eu-central-1.amazonaws.com/shoprunback-dev/products/484/7b4/f4-/pictures/medium.?1505912197",
"brand": {
"id": "1f27f9d9-3b5c-4152-98b7-760f56967dea",
"name": "Apple",
"reference": "apple"
}
}
Push all your products’ catalog with this endpoint.
The image in not mandatory but the return experience of your customer will be better with it.
HTTP Request
POST https://dashboard.shoprunback.com/api/v1/products
Query Parameters
Parameter | Required | Description |
---|---|---|
label | yes | Label of the product (ie. common name) |
reference | yes | unique reference in your catalog |
weight_grams | yes | weight (grams) of the product (package included) |
ean | no | barcode |
brand_id | no | if you have created a brand and this product has this brand. Otherwise, the default brand is automaticaly used |
picture_file_url | no | public URL to the product image (JPG or PNG), to avoid imperfect cropping, use a square image |
picture_file_base64 | no | if your product’s image is not hosted on the internet, you can provide it with a base64 version of it |
Create a product with its brand
body = {
"label": "Iphone 14S Blue",
"reference": "IPHONE 14S B",
"ean": "1258987561456",
"brand": {
"name": "Apple",
"reference": "apple"
},
"image_url": "http://www.apple.com/images/iphone-14s.jpg"
}
HTTParty.post(
"https://dashboard.shoprunback.com/api/v1/products",
body: body,
headers: {
'Content-Type' => 'application/json',
'Authorization' => "Token token=#{your_token}"
}
)
curl -X "POST" "https://dashboard.shoprunback.com/api/v1/products" \
-H "Authorization: Token token=<your_token>" \
-H "Content-Type: application/json; charset=utf-8" \
-d $'{
"label": "Iphone 14S Blue",
"reference": "IPHONE 14S B",
"ean": "1258987561456",
"weight_in_grams": 200,
"brand": {
"name": "Apple",
"reference": "apple"
},
"picture_file_url": "http://www.apple.com/images/iphone-14s.jpg"
}'
<?php
// Load the library
require 'path/to/lib/shoprunback-php/init.php';
// Set your token
\Shoprunback\RestClient::getClient()->setToken('your_token');
// Define the environment you want to use (Production or Sandbox)
\Shoprunback\RestClient::getClient()->useProductionEnvironment();
// Create a Brand for your Product
$brand = new \Shoprunback\Elements\Brand();
$brand->name = 'Apple';
$brand->reference = 'apple';
// Create a new Product
$product = new \Shoprunback\Elements\Product();
$product->label = 'Iphone 14S Blue';
$product->reference = 'IPHONE 14S B';
$product->weight_grams = 200;
$product->brand = $brand;
$product->ean = '1258987561456';
$product->picture_url = 'https://s3.eu-central-1.amazonaws.com/shoprunback-dev/products/484/7b4/f4-/pictures/medium.?1505912197';
// Save the Product
$product->save();
The above command returns the same JSON object with the id of the created product:
{
"id": "1f27f9d9-3b5c-4152-98b7-760f56967dea",
"label": "Iphone 14S Blue",
"reference": "IPHONE 14S B",
"ean": "1258987561456",
"brand": {
"id": "20d0be72-a191-4eb8-af22-9dd4c3e65fe8",
"name": "Apple",
"reference": "apple"
},
"weight_grams": 200,
"picture_url": "https://s3.eu-central-1.amazonaws.com/shoprunback-dev/products/484/7b4/f4-/pictures/medium.?1505912197"
}
You can create your product directly with the brand object embedded.
The image in not mandatory but the return experience is better with it.
HTTP Request
POST https://dashboard.shoprunback.com/api/v1/products
Query Parameters
Parameter | Required | Description |
---|---|---|
label | yes | Label of the product (ie. common name) |
reference | yes | unique reference in your catalog |
weight_grams | yes | weight (grams) of the product (package included) |
ean | no | barcode |
color | no | displayed as is on the web return process (no translation) |
brand | no | the brand object with all its required attributes |
picture_file_url | no | public URL to the product image (JPG or PNG), to avoid imperfect cropping, use a square image |
picture_file_base64 | no | if your product’s image is not hosted on the internet, you can provide it with a base64 version of it |
List your products
HTTParty.get(
"https://dashboard.shoprunback.com/api/v1/products",
headers: {
'Content-Type' => 'application/json',
'Authorization' => "Token token=#{your_token}"
}
)
curl -X "GET" "https://dashboard.shoprunback.com/api/v1/products?page=1" \
-H "Authorization: Token token=<your_token>" \
-H "Content-Type: application/json; charset=utf-8" \
<?php
// Load the library
require 'path/to/lib/shoprunback-php/init.php';
// Set your token
\Shoprunback\RestClient::getClient()->setToken('your_token');
// Define the environment you want to use (Production or Sandbox)
\Shoprunback\RestClient::getClient()->useProductionEnvironment();
// Get all your products
$products = \Shoprunback\Elements\Product::all();
The above command returns JSON structured like this:
{
"pagination": {
"current_page": 1,
"first_page": 1,
"previous_page": null,
"next_page": null,
"last_page": 1,
"count": 5,
"per_page": 10
},
"products":
[
{
"id": "1f27f9d9-3b5c-4152-98b7-760f56967dea",
"label": "Iphone 14S Blue",
"reference": "IPHONE 14S B",
"ean": "1258987561456",
"brand": {
"id": "20d0be72-a191-4eb8-af22-9dd4c3e65fe8",
"name": "Apple",
"reference": "apple"
},
"picture_url": "http://s3.amazonaws/assets/iphone_14s.jpg"
},
{...},
{
"id": "1f27f9d9-3b5c-4152-98b7-760f56967dea",
"label": "Iphone 14S Red",
"reference": "IPHONE 14S B",
"ean": "1258987561456",
"brand": {
"id": "20d0be72-a191-4eb8-af22-9dd4c3e65fe8",
"name": "Apple",
"reference": "apple"
},
"picture_url": "http://s3.amazonaws/assets/iphone_14s.jpg"
}
]
}
You can list all your products on ShopRunBack with this endpoint.
The result is paginated, provide the page
parameter to get a specific page (default is page 1).
HTTP Request
GET https://dashboard.shoprunback.com/api/v1/products?page=1
Order
Once your catalog is uploaded on ShopRunBack, you can plug your e-commerce website to the ShopRunBack dashboard.
Only an existing order can be returned. You have 2 possibilities, depending on your desired return flow :
- When a user request a return on your website, you create the corresponding order on the API and initiate the corresponding return.
- You push the order on the API directly after it is processed on your website and just redirect the customer when he/she requests a return.
In both cases, you will have to create the order, sooner or later.
Create an order
body = {
"ordered_at": "2017-02-03",
"order_number": "4548-9854",
"customer": {
"first_name": "Steve",
"last_name": "Jobs",
"email": "steve@apple.com",
"phone": "555-878-456",
"address": {
"line1": "One Infinite Loop",
"line2": "Building B",
"zipcode": "95014",
"country_code": "US",
"city": "Cupertino",
"state": "California"
}
},
"items": [
{
"product_id": "1f27f9d9-3b5c-4152-98b7-760f56967dea",
},
],
"metadata": {
"foo": "bar",
"bar": "foo"
}
}
HTTParty.post(
"https://dashboard.shoprunback.com/api/v1/orders",
body: body,
headers: {
'Content-Type' => 'application/json',
'Authorization' => "Token token=#{your_token}"
}
)
curl -X "POST" "https://dashboard.shoprunback.com/api/v1/orders" \
-H "Authorization: Token token=<your_token>" \
-H "Content-Type: application/json; charset=utf-8" \
-d $'{
"ordered_at": "2017-02-03",
"order_number": "4548-9854",
"customer": {
"first_name": "Steve",
"last_name": "Jobs",
"email": "steve@apple.com",
"phone": "555-878-456",
"address": {
"line1": "One Infinite Loop",
"line2": "Building B",
"zipcode": "95014",
"country_code": "US",
"city": "Cupertino",
"state": "California"
}
},
"items":
[
{
"product_id": "1f27f9d9-3b5c-4152-98b7-760f56967dea",
},
{
"product_id": "1f27f9d9-3b5c-4152-98b7-760f56967dea",
}
],
"metadata": {
"foo": "bar",
"bar": "foo"
}
}'
<?php
// Load the library
require 'path/to/lib/shoprunback-php/init.php';
// Set your token
\Shoprunback\RestClient::getClient()->setToken('your_token');
// Define the environment you want to use (Production or Sandbox)
\Shoprunback\RestClient::getClient()->useProductionEnvironment();
// Create an Address for the Customer
$address = new \Shoprunback\Elements\Address();
$address->country_code = 'US';
$address->line2 = 'Building B';
$address->state = 'California';
$address->line1 = 'One Infinite Loop';
$address->zipcode = '95014';
$address->city = 'Cupertino';
// Create a Customer for the Order
$customer = new \Shoprunback\Elements\Customer();
$customer->email = 'steve@apple.com';
$customer->phone = '555-878-456';
$customer->first_name = 'Steve';
$customer->last_name = 'Jobs';
$customer->address = $address;
// Create an array of Items ordered by the Customer
$item = new \Shoprunback\Elements\Item();
$item->product_id = '1f27f9d9-3b5c-4152-98b7-760f56967dea';
$items = [$item];
// Create an Order
$order = new \Shoprunback\Elements\Order();
$order->order_number = '4548-9854';
$order->customer = $customer;
$order->items = $items;
$order->ordered_at = '2017-02-03';
// We save the Order
$order->save();
The above command returns the same JSON object with the id of the created order, customer and items:
{
"id": "1f27f9d9-3b5c-4152-98b7-760f56967dea",
"ordered_at": "2017-02-03",
"order_number": "4548-9854",
"customer": {
"id": "1f27f9d9-3b5c-4152-98b7-760f56967dea",
"first_name": "Steve",
"last_name": "Jobs",
"email": "steve@apple.com",
"phone": "555-878-456",
"address": {
"id": "1f27f9d9-3b5c-4152-98b7-760f56967dea",
"line1": "One Infinite Loop",
"line2": "Building B",
"zipcode": "95014",
"country_code": "US",
"city": "Cupertino",
"state": "California"
}
},
"items": [
{
"id": "1f27f9d9-3b5c-4152-98b7-760f56967dea",
"product": {
"id": "1f27f9d9-3b5c-4152-98b7-760f56967dea",
"label": "Iphone 14S Red",
"reference": "IPHONE 14S B",
"ean": "1258987561456",
"brand_id": "1f27f9d9-3b5c-4152-98b7-760f56967dea",
"brand_name": "Apple",
"picture_url": "http://s3.amazonaws/assets/iphone_14s.jpg"
}
},
{
"id": "1f27f9d9-3b5c-4152-98b7-760f56967dec",
"product": {
"id": "1f27f9d9-3b5c-4152-98b7-760f56967dea",
"label": "Iphone 14S Red",
"reference": "IPHONE 14S B",
"ean": "1258987561456",
"brand_id": "1f27f9d9-3b5c-4152-98b7-760f56967dea",
"brand_name": "Apple",
"picture_url": "http://s3.amazonaws/assets/iphone_14s.jpg"
}
}
],
"metadata": {
"foo": "bar"
}
}
An order has a order_number
, a customer and a list of items.
If you want to add extra data on the order, you can freely use the metadata
attribute (a simple key/value store).
The ShopRunBack API will always return this data without altering it.
HTTP Request
POST https://dashboard.shoprunback.com/api/v1/orders
Query Parameters
Parameter | Required | Description |
---|---|---|
ordered_at | yes | date of the order |
order_number | yes | the customer’s order number |
customer | yes | customer information (see swaggerhub documentation for details) |
items | yes | Array of items (see swaggerhub documentation for details) |
metadata | no | Anything you want to add to the order, this data will always be returned and never modified. |
List all orders
This endpoint lists all your paginated orders.
HTTP Request
GET https://dashboard.shoprunback.com/api/v1/orders?page=1
HTTParty.get(
"https://dashboard.shoprunback.com/api/v1/orders?page=1",
headers: {
'Content-Type' => 'application/json',
'Authorization' => "Token token=#{your_token}"
}
)
curl -X "GET" "https://dashboard.shoprunback.com/api/v1/orders?page=1" \
-H "Authorization: Token token=<your_token>" \
-H "Content-Type: application/json; charset=utf-8" \
<?php
// Load the library
require 'path/to/lib/shoprunback-php/init.php';
// Set your token
\Shoprunback\RestClient::getClient()->setToken('your_token');
// Define the environment you want to use (Production or Sandbox)
\Shoprunback\RestClient::getClient()->useProductionEnvironment();
// Get all your orders
$orders = \Shoprunback\Elements\Order::all();
The above command returns JSON structured like this:
{
"pagination": {
"current_page": 1,
"first_page": 1,
"previous_page": 10,
"next_page": null,
"last_page": 1,
"count": 5
},
"orders":
[
{
"id": "1f27f9d9-3b5c-4152-98b7-760f56967dea",
"ordered_at": "2017-02-03",
"order_number": "4548-9854",
"customer": {
"id": "1f27f9d9-3b5c-4152-98b7-760f56967dea",
"first_name": "Steve",
"last_name": "Jobs",
"email": "steve@apple.com",
"phone": "555-878-456",
"address": {
"id": "1f27f9d9-3b5c-4152-98b7-760f56967dea",
"line1": "One Infinite Loop",
"line2": "Building B",
"zipcode": "95014",
"country_code": "US",
"city": "Cupertino",
"state": "California"
}
},
"items": [
{
"id": "1f27f9d9-3b5c-4152-98b7-760f56967dea",
"product_id": "1f27f9d9-3b5c-4152-98b7-760f56967dea",
"product": {
"id": "1f27f9d9-3b5c-4152-98b7-760f56967dea",
"label": "Iphone 14S Red",
"reference": "IPHONE 14S B",
"ean": "1258987561456",
"brand_id": "1f27f9d9-3b5c-4152-98b7-760f56967dea",
"brand_name": "Apple",
"picture_url": "http://s3.amazonaws/assets/iphone_14s.jpg"
}
},
],
"metadata": {
"foo": "bar"
}
},
{...}
]
}
Delete an order
An order can only be deleted if no corresponding shipback is attached. So you must delete it first.
HTTP Request
DELETE https://dashboard.shoprunback.com/api/v1/orders/:order_id
Errors
{
"errors": [
{
"code": "DEPENDENT_SHIPBACK",
"message": "dependent shipback found (fee4a476-13ff-422d-85df-4ef68fa0c8d7)"
}
]
}
If you are trying to delete an order with a dependent shipback, you will receive an error with a 400
HTTP CODE.
You will also have an error message and an error code in the returned JSON.
In this case, the error code will be DEPENDENT_SHIPBACK
.
If the deletion is successful, you will receive a 200
HTTP CODE.
Return
Create the order and the return sequentially
body = {
"ordered_at": "2017-06-12",
"order_number": "1234567",
"customer": {
"first_name": "John",
"last_name": "Doe",
"email": "john@doe.com",
"phone": "1230145365",
"address": {
"line1": "651 rue de dunkerque",
"zipcode": "78010",
"country_code": "FR",
"city": "Paris"
}
},
"items": [
{
"label": "Chemise bleu",
"reference": "item 001",
"product_id": "reference1"
},
{
"label": "Casquette rouge",
"reference": "item 2",
"product_id": "reference2"
}
]
}
HTTParty.post(
"https://dashboard.shoprunback.com/api/v1/orders",
body: body,
headers: {
'Content-Type' => 'application/json',
'Authorization' => "Token token=#{your_token}"
}
)
body = {
"mode": "pickup",
"order_id": "1234567",
"items": [
{
"item_id": "item 2",
"reason_code": "doesnt_fit"
}
]
}
HTTParty.post(
"https://dashboard.shoprunback.com/api/v1/shipbacks",
body: body,
headers: {
'Content-Type' => 'application/json',
'Authorization' => "Token token=#{your_token}"
}
)
curl -X "POST" "https://dashboard.shoprunback.com/api/v1/orders" \
-H "Authorization: Token token=<your_token>" \
-H "Content-Type: application/json; charset=utf-8" \
-d $'{
"ordered_at": "2017-06-12",
"order_number": "1234567",
"customer": {
"first_name": "John",
"last_name": "Doe",
"email": "john@doe.com",
"phone": "1230145365",
"address": {
"line1": "651 rue de dunkerque",
"zipcode": "78010",
"country_code": "FR",
"city": "Paris"
}
},
"items": [
{
"label": "Chemise bleu",
"reference": "item 001",
"product_id": "reference1"
},
{
"label": "Casquette rouge",
"reference": "item 2",
"product_id": "reference2"
}
]
}'
curl -X "POST" "https://dashboard.shoprunback.com/api/v1/shipbacks" \
-H "Authorization: Token token=<your_token>" \
-H "Content-Type: application/json; charset=utf-8" \
-d $'{
"mode": "pickup",
"order_id": "1234567",
"items": [
{
"item_id": "item 2",
"reason_code": "doesnt_fit"
}
]
}'
<?php
// Load the library
require 'path/to/lib/shoprunback-php/init.php';
// Set your token
\Shoprunback\RestClient::getClient()->setToken('your_token');
// Define the environment you want to use (Production or Sandbox)
\Shoprunback\RestClient::getClient()->useProductionEnvironment();
//--------------------------------------------------------------------------
// To create a Shipback, we must first have an Order to link the Shipback to
//--------------------------------------------------------------------------
// Create an Address for the Customer
$address = new \Shoprunback\Elements\Address();
$address->country_code = 'US';
$address->line2 = 'Building B';
$address->state = 'California';
$address->line1 = 'One Infinite Loop';
$address->zipcode = '95014';
$address->city = 'Cupertino';
// Create a Customer for the Order
$customer = new \Shoprunback\Elements\Customer();
$customer->email = 'steve@apple.com';
$customer->phone = '555-878-456';
$customer->first_name = 'Steve';
$customer->last_name = 'Jobs';
$customer->address = $address;
// Create an array of Items ordered by the Customer
$item = new \Shoprunback\Elements\Item();
$item->product_id = '1f27f9d9-3b5c-4152-98b7-760f56967dea';
$items = [$item];
// Create an Order
$order = new \Shoprunback\Elements\Order();
$order->order_number = '4548-9854';
$order->customer = $customer;
$order->items = $items;
$order->ordered_at = '2017-02-03';
// We save the Order
$order->save();
//--------------------------------------------------------
// Now that we have an Order, we can link a Shipback to it
//--------------------------------------------------------
// Create a Shipback and link the Order
$shipback = new \Shoprunback\Elements\Shipback();
$shipback->order_id = $order->id;
// Optionnal: you can directly link the Items the Customer wants to return
// If you don't, the Customer will have to fill the return request's form to select them
$returnedItem = new \Shoprunback\Elements\ReturnedItem();
$returnedItem->item_id = $order->items[0]->id; // It must be the ID of an Item from the Order
$returnedItem->reason_code = 'doesnt_fit';
$shipback->items = [$returnedItem];
// We save the Shipback
$shipback->save();
You can create the order and its corresponding shipback in 2 sequential API calls without parsing the first response by using your own references.
First, create the order with an order_number and the items. You don’t have to push all the items in the initial order if you already know which items are going to be returned, just push them and not the others. You must provide item references if you want to avoid the parsing of the response. An item reference should be unique per order.
Second, create the corresponding shipback attached to your order_number by giving the item’s reference and the reason of the return.
If the customer details of the shipback are not provided, the order’s customer is copied and used for the shipback.
Delete a shipback
An shipback can only be deleted if no yet registered (the customer has not completed the whole process).
HTTP Request
DELETE https://dashboard.shoprunback.com/api/v1/shipbacks/:shipback_id
Errors
{
"errors": [
{
"code": "SHIPBACK_REGISTERED",
"message": "This shipback is already processing. You can't delete it."
}
]
}
If you are trying to delete an arlready registered shipback, you will receive an error with a 400
HTTP CODE.
You will also have an error message and an error code in the returned JSON.
In this case, the error code will be SHIPBACK_REGISTERED
.
If the deletion is successful, you will receive a 200
HTTP CODE.
Your own return process
If you don’t want to use the return process provided by ShopRunBack, you can built your own return’s funnel.
For that you have to:
1/ Create the shipback with the list of the returned items (with the associated reason code)
2/ Request the quotes (for each mode - pickup, postal and dropoff - a quote is created to compute the corresponding price of the return)
3/ Confirm the quote (select and confirm one of the available quotes)
4/ Get the label
1. Create the shipback
To create the return follow this instruction.
2. Request the quotes
HTTParty.get(
"https://dashboard.shoprunback.com/api/v1/shipbacks/00082f23-9b8c-4515-b1cd-527d56a1bef3/quotes",
body: body,
headers: {
'Content-Type' => 'application/json',
'Authorization' => "Token token=#{your_token}"
}
)
curl -X "GET" "https://dashboard.shoprunback.com/api/v1/shipbacks/00082f23-9b8c-4515-b1cd-527d56a1bef3/quotes" \
-H "Authorization: Token token=<your_token>" \
-H "Content-Type: application/json; charset=utf-8"
<?php
//The ShopRunBack library doesn't provide, at the moment, a dedicated method for that
// get cURL resource
$ch = curl_init();
// set url
curl_setopt($ch, CURLOPT_URL, 'https://dashboard.shoprunback.com/api/v1/shipbacks/00082f23-9b8c-4515-b1cd-527d56a1bef3/quotes');
// set method
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'GET');
// return the transfer as a string
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
// set headers
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Authorization: Token token=your_token',
]);
// send the request and save response to $response
$response = curl_exec($ch);
// stop if fails
if (!$response) {
die('Error: "' . curl_error($ch) . '" - Code: ' . curl_errno($ch));
}
echo 'HTTP Status Code: ' . curl_getinfo($ch, CURLINFO_HTTP_CODE) . PHP_EOL;
echo 'Response Body: ' . $response . PHP_EOL;
// close curl resource to free up system resources
curl_close($ch);
The above command returns JSON structured like this:
[
{
"id": "570f3429-25ec-4685-9229-581853d0fecc",
"state": "computing",
"mode": "postal",
"price_cents": null,
"customer_price_cents": null
},
{
"id": "dc1383df-020b-44a6-8100-69bed63c35ee",
"state": "computing",
"mode": "pickup",
"price_cents": null,
"customer_price_cents": null
},
{
"id": "d014d7c6-8f46-4c87-9d81-df91d502b1ef",
"state": "computing",
"mode": "dropoff",
"price_cents": null,
"customer_price_cents": null
}
]
The quotes are only computed on demand. So once the shipback created with the returned items inside, you have to trigger the computation of the quotes.
The computation takes some time (from 30 to 90s) to compute the 3 quotes. You can request the endpoint /api/v1/shipbacks/:id/quotes
every 20 seconds to get the state of the computation.
You can also query the quote of the mode you want to follow directly the computation of this mode only : /api/v1/shipbacks/:id/quotes/postal
for the postal mode.
Clear the quotes
HTTParty.post(
"https://dashboard.shoprunback.com/api/v1/shipbacks/00082f23-9b8c-4515-b1cd-527d56a1bef3/quotes/clear",
body: body,
headers: {
'Content-Type' => 'application/json',
'Authorization' => "Token token=#{your_token}"
}
)
curl -X "POST" "https://dashboard.shoprunback.com/api/v1/shipbacks/00082f23-9b8c-4515-b1cd-527d56a1bef3/quotes/clear" \
-H "Authorization: Token token=<your_token>" \
-H "Content-Type: application/json; charset=utf-8"
<?php
//The ShopRunBack library doesn't provide, at the moment, a dedicated method for that
// get cURL resource
$ch = curl_init();
// set url
curl_setopt($ch, CURLOPT_URL, 'https://dashboard.shoprunback.com/api/v1/shipbacks/00082f23-9b8c-4515-b1cd-527d56a1bef3/quotes/clear');
// set method
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');
// return the transfer as a string
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
// set headers
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Authorization: Token token=your_token',
]);
// send the request and save response to $response
$response = curl_exec($ch);
// stop if fails
if (!$response) {
die('Error: "' . curl_error($ch) . '" - Code: ' . curl_errno($ch));
}
echo 'HTTP Status Code: ' . curl_getinfo($ch, CURLINFO_HTTP_CODE) . PHP_EOL;
echo 'Response Body: ' . $response . PHP_EOL;
// close curl resource to free up system resources
curl_close($ch);
If you have updated the shipback or simply want to retrigger the quotes computation, you have to clear them by calling the dedicated endpoint.
3. Select the mode
HTTParty.get(
"https://dashboard.shoprunback.com/api/v1/shipbacks/00082f23-9b8c-4515-b1cd-527d56a1bef3/quotes",
body: body,
headers: {
'Content-Type' => 'application/json',
'Authorization' => "Token token=#{your_token}"
}
)
curl -X "GET" "https://dashboard.shoprunback.com/api/v1/shipbacks/00082f23-9b8c-4515-b1cd-527d56a1bef3/quotes" \
-H "Authorization: Token token=<your_token>" \
-H "Content-Type: application/json; charset=utf-8"
<?php
//The ShopRunBack library doesn't provide, at the moment, a dedicated method for that
// get cURL resource
$ch = curl_init();
// set url
curl_setopt($ch, CURLOPT_URL, 'https://dashboard.shoprunback.com/api/v1/shipbacks/00082f23-9b8c-4515-b1cd-527d56a1bef3/quotes');
// set method
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'GET');
// return the transfer as a string
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
// set headers
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Authorization: Token token=your_token',
]);
// send the request and save response to $response
$response = curl_exec($ch);
// stop if fails
if (!$response) {
die('Error: "' . curl_error($ch) . '" - Code: ' . curl_errno($ch));
}
echo 'HTTP Status Code: ' . curl_getinfo($ch, CURLINFO_HTTP_CODE) . PHP_EOL;
echo 'Response Body: ' . $response . PHP_EOL;
// close curl resource to free up system resources
curl_close($ch);
The above command returns JSON structured like this:
[
{
"id": "570f3429-25ec-4685-9229-581853d0fecc",
"state": "computing",
"mode": "postal",
"price_cents": null,
"customer_price_cents": null
},
{
"id": "dc1383df-020b-44a6-8100-69bed63c35ee",
"state": "computing",
"mode": "pickup",
"price_cents": null,
"customer_price_cents": null
},
{
"id": "d014d7c6-8f46-4c87-9d81-df91d502b1ef",
"state": "computing",
"mode": "dropoff",
"price_cents": null,
"customer_price_cents": null
}
]
To select the mode, you have to update the shipbacks and provide one of the available modes.
A mode is available if the corresponding quote is marked as available
.
Mode Dropoff
{
"dropoff_code": "O4001",
"mode": "dropoff"
}
To select the dropoff mode, you also have to provide a valid dropoff point code. This code is provided in the quotes
endpoint.
Update the shipback with the mode dropoff
and the dropoff_code
on the api/v1/shipbacks/:id
endpoint.
Mode Pickup
{
"pickup_datetime": "2018-01-18 14:00:00",
"pickup_duration": "120",
"mode": "pickup"
}
To select the pickup mode, you also have to provide a valid pickup_datetime
and pickup_duration
. These values are available in the quotes
endpoint.
Update the shipback with the mode pickup
and these 2 values on the api/v1/shipbacks/:id
endpoint.
4. Get the label
# cURL example:
curl -H "Authorization: Token token=<your_token>"
-X POST
'https://dashboard.shoprunback.com/api/v1/shipbacks/:id/free'
# Ruby example
response = HTTParty.post(
'https://dashboard.shoprunback.com/api/v1/shipbacks/#{shipback_id}/free',
headers: {
'Content-Type' => 'application/json',
'Authorization' => "Token token=#{your_token}"
}
)
To validate the selected mode and get the label, payment information needs to be
added to the shipback. In the case of a custom return process, where customer
payment isn’t supported, we need to skip the payment phase by POSTing on the
api/v1/shipbacks/:id/free
endpoint.
Once the call has been successfully performed, the voucher and the label are
being generated, you can get the corresponding label by polling the
api/v1/shipbacks/:id
endpoint.
The label generation is dependent of the carriers response time, you can expect up to 1 minute of waiting to get the label.
Overrides
Relocation
# POST on the endpoint api/v1/shipbacks/:id
{
"mode": "pickup",
"overrides": {
"relocation_warehouse_id": "E002"
}
}
The ShopRunBack’s dashboard gives you the possibility to define your rules of relocation based on the reason of the return and the country of your customer.
If the rules engine does not fit your desires, you can override the warehouse of relocation of the entire shipback while creating (or updating) the shipback on the API by providing the warehouse ID or reference.
Price paid by the customer
# POST on the endpoint api/v1/shipbacks/:id
{
"mode": "pickup",
"overrides": {
"dropoff_customer_price_cents": 300,
"postal_customer_price_cents": 450,
"pickup_customer_price_cents": 1200
}
}
You can change the price displayed and paid by the customer on the web return process depending on rules in your own system. If the amount paid is higher than the normal price of the service, the difference will be refunded to you.
These overrides are only for returns which are not free for the customer, if you want to create you policy for free return, please use the Smart Rules system.
Try at Home
# POST on the endpoint api/v1/shipbacks/:id
{
"overrides": {
"try_at_home": true
}
}
ShopRunBack provides a Try at Home feature which makes certain returns free when they are within a specified period of time after the initial order. At the time of writing, this feature needs to be enabled in your company configuration by ShopRunBack’s support.
Shipbacks leveraging this feature needs to be flagged as Try at Home returns.
This is accomplished by setting the try_at_home
override to true
, POSTing
the following json data on the shipback’s endpoint:
# cURL example:
curl -H "Authorization: Token token=<your_token>"
-X POST -d '{"overrides": {"try_at_home": true}}'
'https://dashboard.shoprunback.com/api/v1/shipbacks/:id'
# Ruby example
response = HTTParty.post(
'https://dashboard.shoprunback.com/api/v1/shipbacks/#{shipback_id}'
body: { overrides: { try_at_home: true } },
headers: {
'Content-Type' => 'application/json',
'Authorization' => "Token token=#{your_token}"
}
)
Webhooks
Every event on ShopRunBack can trigger a webhook.
Basically, a webhook is a JSON Object send by HTTP (POST) to an URL you have set on your account.
The server expect a 200 response (HTTP OK
) when posting the webhook, otherwise it is marked as not received successfully on the dashboard.
Data sent
// Example of JSON sent
{
"id": "00082f23-9b8c-4515-b1cd-527d56a1bef3",
"event": "shipback.relocated",
"created_at": "2018-02-20 16:54:22 +0100",
"data": {
"id": "fc8520bf-3ae0-46b1-8991-cacb6b03c698",
"mode": "postal"
}
}
All webhooks has the same caracteristics; this is a JSON Object with the attributes:
- the
id
: a unique identifier. You can use it to detect duplicate. - the name of the
event
with the format:<object trigerring the webhook>.<action>
- the date of the event which is also the date of creation of the webhook:
created_at
- the object triggering the webhook as a JSON in the
data
attribute.
If accurate, the webhook can be added to the platform in the next release.
Collaborator
// Example of JSON sent:
{
"id": "00082f23-9b8c-4515-b1cd-527d56a1bef3",
"event": "collaborator.invited",
"created_at": "2018-02-20 16:54:22 +0100",
"data": {
"id" : "fc8520bf-3ae0-46b1-8991-cacb6b03c698",
"email" : "tim@apple.com"
}
}
Webhook name | Trigger |
---|---|
collaborator.created | Sent when a collaborator creates its account |
collaborator.invited | Sent when a manager invite a collaborator |
Product
// Example of JSON sent:
{
"id": "00082f23-9b8c-4515-b1cd-527d56a1bef3",
"event": "product.created",
"created_at": "2018-02-20 16:54:22 +0100",
"data": {
"id" : "fc8520bf-3ae0-46b1-8991-cacb6b03c698",
"label" : "Iphone 12S - Blue",
"reference": "IPHONE-12S",
"ean": "1237492402485"
}
}
Webhook name | Trigger |
---|---|
product.created | Sent when a product is created in the catalogue |
Relocation
// Example of JSON sent:
{
"id": "00082f23-9b8c-4515-b1cd-527d56a1bef3",
"event": "relocation.created",
"created_at": "2018-02-20 16:54:22 +0100",
"data": {
"id" : "fc8520bf-3ae0-46b1-8991-cacb6b03c698",
"country_code" : "FR",
"reason_code" : "damaged",
"warehoused_id" : "fc8520bf-3ae0-46b1-8991-cacb6b03c699"
}
}
Webhook name | Trigger |
---|---|
relocation.created | Sent when a new relocation rule has been created |
Returned Item
// Example of JSON sent:
{
"id": "00082f23-9b8c-4515-b1cd-527d56a1bef3",
"event": "returneditem.relocated",
"created_at": "2018-02-20 16:54:22 +0100",
"data": {
"id" : "fc8520bf-3ae0-46b1-8991-cacb6b03c698",
"reason_code" : "damaged",
"item" : {
"id" : "fc8520bf-3ae0-46b1-8991-cacb6b03c600",
"barcode": "12149837489",
"label": "Iphone 12S - Blue",
"reference": "IPHONE-12S"
}
}
}
Webhook name | Trigger |
---|---|
returneditem.missing | Sent when a returned item is marked as missing by an operator |
returneditem.relocated | Sent when a returned item is relocated to the retailer’s warehouse |
returneditem.transiting | Sent when a returned item is transitting |
Shipback
# Example of JSON sent for shipback.registered
{
"id": "00082f23-9b8c-4515-b1cd-527d56a1bef3",
"event": "shipback.registered",
"created_at": "2018-02-20 16:54:22 +0100",
"data": {
"id" : "fc8520bf-3ae0-46b1-8991-cacb6b03c698",
"rma" : "123",
"registered_at": "2018-02-20 16:58:22 +0100",
"mode": "postal",
"weight_in_grams": "1000",
"size": "S",
"computed_weight_in_grams": "1000",
"public_url": "https://web.shoprunback.com/apple/1234",
"metadata": {},
"price_cents": "10000",
"customer_price_cents": "10000"
}
}
# Example of JSON sent for shipback.labelled
{
"id": "00082f23-9b8c-4515-b1cd-527d56a1bef3",
"event": "shipback.labelled",
"created_at": "2018-02-20 16:54:22 +0100",
"data": {
"id" : "fc8520bf-3ae0-46b1-8991-cacb6b03c698",
"rma" : "123",
"registered_at": "2018-02-20 16:58:22 +0100",
"mode": "postal",
"weight_in_grams": "1000",
"size": "S",
"computed_weight_in_grams": "1000",
"public_url": "https://web.shoprunback.com/apple/1234",
"metadata": {},
"price_cents": "10000",
"customer_price_cents": "10000",
"label_url" : "http://cdn.com/label/1234.pdf",
"tracking_number": "123456-tracking"
}
}
// Example of JSON sent for other events
{
"id": "00082f23-9b8c-4515-b1cd-527d56a1bef3",
"event": "shipback.registered",
"created_at": "2018-02-20 16:54:22 +0100",
"data": {
"id" : "fc8520bf-3ae0-46b1-8991-cacb6b03c698",
"rma" : "123",
}
}
Webhook name | Trigger |
---|---|
shipback.created | Sent when a shipback is created (via the API or via the web interface) |
shipback.registering | Sent when a customer has visited the return link |
shipback.registered | Sent when a shipback is registered (the customer has paid or validated is free return) and the customer can download its voucher and label |
shipback.labelled | Sent when the label is available |
shipback.delivering | Sent when the shipback is transiting between the customer’s location and our warehouse |
shipback.delivered | Sent when the shipback is delivered to our warehouse |
shipback.identified | Sent when the incoming parcel has been open and all returned items have been identified with a unique barcode or marked has missing (not returned) |
shipback.relocating | Sent when the shipback is transitting from our warehouse to the retailer’s warehouse |
shipback.relocated | Sent when all the returned item’s of a shipback are relocated to the retailer’s warehouse |
shipback.failed | Sent when something went wront with this shipback |
Sponsoring
// Example of JSON sent:
{
"id": "00082f23-9b8c-4515-b1cd-527d56a1bef3",
"event": "sponsoring.created",
"created_at": "2018-02-20 16:54:22 +0100",
"data": {
"id" : "fc8520bf-3ae0-46b1-8991-cacb6b03c698",
"percentage": "100",
"country_code": "FR",
"reason_code": "damaged",
"merchant_fee_min": 5,
"merchant_fee_max": 10,
"customer_fee_min": null,
"customer_fee_max": null
}
}
Webhook name | Trigger |
---|---|
sponsoring.created | Sent when a new sponsoring rule has been created |
Warehouse
// Example of JSON sent:
{
"id": "00082f23-9b8c-4515-b1cd-527d56a1bef3",
"event": "warehouse.created",
"created_at": "2018-02-20 16:54:22 +0100",
"data": {
"id" : "fc8520bf-3ae0-46b1-8991-cacb6b03c698",
"reference": "APPLE01",
"name": "Apple store Paris",
}
}
Webhook name | Trigger |
---|---|
warehouse.created | Sent when a new warehouse is added to the company |
Set the URL
# in a Rake base application controller
def webhook
# handle the webhook content with params
head 200 # HTTP OK
end
<?php
// in a PHP Framework controller
private function webhook()
{
$webhook = file_get_contents("php://input");
$webhook = json_decode($webhook); // the webhook data in an associative array
return self::returnHeaderHTTP(200); //example in Prestashop
}
?>
The ShopRunBack’s API send the webhooks on a public accessible HTTP or HTTPS endpoint (the certificate must be valid).
If you want to protect this endpoint, you can :
- setup a basic authentication and provide the login and password in the URL (
http://<login>:<password>@host.com
) - verify the value of a specific URL parameter and provide it in the webhook URL (
http://host.com?shoprunback=topsecret
) - Use the build-in HMAC signature without altering the URL (see below)
You can set your Wehbook URL on the dashboard, in the section Developers > Webhooks.
Signature
We include a signature in each webhooks sent by ShopRunBack in the Shoprunback-Signature
header.
Define your secret
You can change the secret (the default one is empty) on your dashboard: section Developers > Webhooks.
Use a random string with high entropy with, by example, the following command: ruby -rsecurerandom -e 'puts SecureRandom.hex(20)'
in your terminal.
Verify the signature
digest = OpenSSL::Digest.new('sha256')
secret = "your secret" # empty string if not set
payload = request.body.read
# signature
hmac = OpenSSL::HMAC.hexdigest(digest, secret, payload)
# verification
hmac == request.env['HTTP_SHOPRUNBACK_SIGNATURE']
<?php
$secret = "your secret"; // empty string if not set
$payload = @file_get_contents('php://input');
// signature
$hmac = hash_hmac ('sha-256', $body , $secret)
// verification
$hmac == $_SERVER['HTTP_STRIPE_SIGNATURE'];
?>
ShopRunBack generates signatures using a hash-based message authentication code (HMAC) with SHA-256.
To verify this signature:
- Get the signature in the
Shoprunback-Signature
header - Compare the header value with HMAC (SHA-256) of the request body
The two signature must be the same otherwise you can reject this webhook.
Volume
The volume of webhooks increase with the amount of shipbacks ShopRunBack will handle for you.
Please make sure your server and the application which provides the endpoint can handle all the requests.
If you don’t use the webhooks, don’t provide any webhooks URL and the platform will not send it.