Manufacturers API
This documentation covers the manufacturer functionality of importing products into Papertrail. It includes authentication, adding images and uploads, adding products, and updating existing products.
Should you have any questions on the API, require clarification, or assistance, please do not hesitate to contact your Papertrail representative.
API Endpoint
The root domain of the Papertrail API is:
https://api.papertrail.io
While testing you can use the test/development API:
https://api-dev.papertrail.io
Note: Each endpoint will require a different Authorization token.
Content Negotiation
The Papertrail API uses JSON as the data transfer format for requests and responses, including errors. In order to make a valid request you should include the following header in your requests:
Content-Type: application/json
As part of the API, certain requests will require a specific Content-Type
HTTP header. Each resource that expects a specific HTTP header will be highlighted in this documentation.
Versioning
When making a request you must supply an Accept
header that contains the required version number. An example of this header would be:
Accept: application/vnd.papertrail.api+json; version=1.0
The current API version is 1.0
.
Errors
The Papertrail API aims to follow the standard semantic meaning of HTTP response codes to indicate the success or failure of a request. Generally speaking, responses in the 2xx
range indicate success, in the 4xx
range indicate a client error, and in the 5xx
range indicate an internal Papertrail error.
Each error response will include a JSON body that provides more detail of what went wrong. All errors include the status code of the response, a unique key that identifies the error, and a message description of what went wrong:
{
"code": 400,
"error": "folder_has_records",
"message": "Folder 3912ed54-073d-4827-9b98-18de57dcd265 cannot be deleted because it has existing records."
}
In the case of a validation error a data
property will be included in the response body that includes an object of properties that failed the required validation rules. Each property will have an array of messages indicating the reason why the validation failed:
{
"code": 400,
"error": "validation_error",
"message": "The request had a validation error.",
"data": {
"name": [
{
"code": "required",
"message": "The name field is required."
}
]
}
}
Pagination
When requesting a collection of results from the Papertrail API, a meta
object will be included in the response that contains pagination details:
{
"data": [...],
"meta": {
"pagination": {
"total": 322,
"count": 10,
"per_page": 10,
"current_page": 1,
"total_pages": 33,
"links": {
"next": "https://api.papertrail.io/manufacturers/imports?page=2"
}
}
}
}
By default, every collection response will return 10 results per page. You can increase this to a maximum of 1000 results per page by including a limit
parameter:
https://api.papertrail.io/manufacturers/imports?limit=50
Authentication ¶
Overview
The Papertrail Manufacturer API requires that you provide an Authorization
header that includes the token that has been provided to you from Papertrail. If you don’t have this token, please get in touch with Papertrail.
Once you have the token you will need to supply it for every request as a Authorization
header:
Authorization: Basic {token}
Uploads ¶
You can store images and uploads (such as PDFs) that can be included with each product import. If you post a different file with the same name as a previous uploaded file, the original file will be overwritten.
Note In order to include an upload in an import, you must upload the file before creating the import!
Uploads Collection ¶
Headers
Authorization: Basic 33F3C3DEE674E4A527FFB9D3836AE
Accept: application/vnd.papertrail.api+json; version=1.0
Content-Type: multipart/form-data
Body
{
"file": "..."
}
Schema
{
"type": "object",
"properties": {
"file": {
"type": "string",
"description": "The file to upload"
}
},
"$schema": "http://json-schema.org/draft-04/schema#"
}
Headers
Authorization: Basic 33F3C3DEE674E4A527FFB9D3836AE
Accept: application/vnd.papertrail.api+json; version=1.0
Content-Type: application/json
Body
{
"data": {
"url": "https://domain.com/directory/filename.jpg"
}
}
Schema
{
"$schema": "http://json-schema.org/draft-04/schema#",
"type": "object",
"properties": {
"data": {
"type": "object",
"properties": {
"url": {
"type": "string",
"description": "The url of the uploaded file"
}
}
}
}
}
POST/manufacturers/uploads
Imports ¶
An import is a list of products that you want to add to the Papertrail manufacturer’s database. You can add new or replace existing products by creating a new import.
When an import is created, the products are processed asynchronously. You will be able to check on the progress of an import by making a GET
request using the id that was provided when the import was created. If there are errors with the import, those errors will be included as part of the response.
Products have required top level attributes, as well as customisable “fields” that allow you to define the properties of the product.
The top level attributes are:
-
Name
The name of the product. This is a required attribute.
-
Description
A description of the product. This is an optional attribute.
-
Images
A list of images that should be associated with the product. This should be a list of file names of images that you have already uploaded to the manufacturers database.
-
Uploads
A list of uploads that should be associated with the product. This should be a list of file names of uploads that you have already uploaded to the manufacturers database.
-
Checklists
A list of checklist ids that should be associated with the product. You should have a list of availble ids that can be associated with a product. If you don’t already have this list, please speak to your Papertrail representative.
-
Identifier
An attribute to identify existing products to be updated. When updating existing products, you need to provide a way to identify the product(s) that should be updated. For example, if you want to update a unique product, you could pass the unique RFID number of that product. Alternatively, if you wanted to update all products with a certain model number, you could use that value as the identifier. This attribute is only required if you are updating existing products.
The customisable fields attributes are:
-
Label The label of the field. This is a required attribute where the value should be a string. For example, “Barcode”.
-
Type The type of the field. This is a required attribute. You can choose from the following options (
array
,date
,identifier
,string
,rfid
). If you require additional types, please contact your Papertrail representative. Each type has different requirements for the value that should be passed with it.- Date: A string in the format of
Y-m-d
- Identifer: A string or integer
- String: a string
- RFID: a string or integer
- Array: a list of valid types
- Date: A string in the format of
-
Value
The value of the field. This is a required attribute. The value should be appropriate for the given type of the field.
-
Unique
Determines if the field should be marked as unique. This is a required field where the value should be a boolean. For example, a unique RFID field should be marked as unique.
-
Generic
Determines if the field should be marked as generic. This is a required field where the value should be a boolean. All non-unique fields should be marked as generic. However, fields such as the date of manufacturer should be marked as not generic as that value is specific to that individual product.
-
Searchable
Determines if the field should be searchable. This is a required field where the value should be a boolean. All unique fields should be marked as searchable, plus any non-unique fields that would be appropriate for searching. If you are unsure about which fields to mark as searchable, please speak to your Papertrail representative.
-
Internal Identifier
Determines if the field should be marked as an internal identifier. This is a required field where the value should be a boolean. All unique fields should be marked as being an internal identifier, as well as any fields that you would use to identify products for updates. For example, model or part number.
-
Imports Collection ¶
Headers
Authorization: Basic 33F3C3DEE674E4A527FFB9D3836AE
Accept: application/vnd.papertrail.api+json; version=1.0
Content-Type: application/json
Body
{
"data": [
{
"id": "b532ae48-6902-40a9-bf83-a71769a2ff11",
"has_errors": false,
"completed_at": "2018-03-08T10:35:44+0000",
"segments": [
{
"id": "74f91637-6d5c-456b-872d-c6f5a3d9ed30",
"errors": [],
"completed_at": "2018-03-08T10:35:44+0000"
}
]
}
]
}
Schema
{
"$schema": "http://json-schema.org/draft-04/schema#",
"type": "object",
"properties": {
"data": {
"type": "array"
}
}
}
GET/manufacturers/imports
Headers
Authorization: Basic 33F3C3DEE674E4A527FFB9D3836AE
Accept: application/vnd.papertrail.api+json; version=1.0
Content-Type: application/json
Body
{
"products": [
{
"name": "Kayak",
"description": "A kayak is a low-to-the-water, canoe-like boat",
"images": [
"kayak.jpg"
],
"uploads": [
"instructions.pdf"
],
"checklists": [
"6a276e82-2677-46f1-bb0f-bfe360ce5459"
],
"identifier": "3992037410",
"fields": [
{
"label": "Identifier",
"type": "identifier",
"value": "3992037410",
"unique": true,
"generic": false,
"searchable": true,
"internal_identifier": true
}
]
}
]
}
Schema
{
"$schema": "http://json-schema.org/draft-04/schema#",
"type": "object",
"properties": {
"products": {
"type": "array",
"description": "An array of products to uploads"
}
}
}
Headers
Authorization: Basic 33F3C3DEE674E4A527FFB9D3836AE
Accept: application/vnd.papertrail.api+json; version=1.0
Content-Type: application/json
Body
{
"data": {
"id": "b532ae48-6902-40a9-bf83-a71769a2ff11",
"has_errors": false,
"completed_at": "2018-03-08T10:35:44+0000",
"segments": [
{
"id": "74f91637-6d5c-456b-872d-c6f5a3d9ed30",
"errors": [],
"completed_at": "2018-03-08T10:35:44+0000"
}
]
}
}
Schema
{
"$schema": "http://json-schema.org/draft-04/schema#",
"type": "object",
"properties": {
"data": {
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "The unique ID of the import"
},
"has_errors": {
"type": "boolean",
"description": "A flag that shows if the import has errors"
},
"completed_at": {
"type": "string",
"description": "Date of which the import was completed"
},
"segments": {
"type": "array"
}
}
}
}
}
POST/manufacturers/imports
Import Resource ¶
Headers
Content-Type: application/json
Body
{
"id": "b532ae48-6902-40a9-bf83-a71769a2ff11",
"has_errors": false,
"completed_at": "2018-03-08T10:35:44+0000",
"segments": [
{
"id": "74f91637-6d5c-456b-872d-c6f5a3d9ed30",
"errors": [],
"completed_at": "2018-03-08T10:35:44+0000"
}
]
}
Schema
{
"$schema": "http://json-schema.org/draft-04/schema#",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "The unique ID of the import"
},
"has_errors": {
"type": "boolean",
"description": "A flag that shows if the import has errors"
},
"completed_at": {
"type": "string",
"description": "Date of which the import was completed"
},
"segments": {
"type": "array"
}
}
}
Headers
Content-Type: application/json
Body
{
"data": {
"id": "b532ae48-6902-40a9-bf83-a71769a2ff11",
"has_errors": false,
"completed_at": "2018-03-08T10:35:44+0000",
"segments": [
{
"id": "74f91637-6d5c-456b-872d-c6f5a3d9ed30",
"errors": [],
"completed_at": "2018-03-08T10:35:44+0000"
}
]
}
}
Schema
{
"$schema": "http://json-schema.org/draft-04/schema#",
"type": "object",
"properties": {
"data": {
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "The unique ID of the import"
},
"has_errors": {
"type": "boolean",
"description": "A flag that shows if the import has errors"
},
"completed_at": {
"type": "string",
"description": "Date of which the import was completed"
},
"segments": {
"type": "array"
}
}
}
}
}
GET/manufacturers/imports/{id}
- id
string
(required) Example: 1bea346d-1828-4dff-972b-50f610dd3676The unique ID of the import
Walkthrough ¶
Making requests
In order to make requests to the Papertrail API you are going to need an access token. If you don’t already have an access token you will need to request one by speaking to your Papertrail representative. For the purposes of this tutorial we will be using the following token:
UwIlzlDTxzBRoEvEabWtS2c957Cdw9Q8WSXQ1kRerl8coz1g
In order to use the access token, you must provide it as an Authorization: Basic
header of the HTTP request:
Authorization: Basic UwIlzlDTxzBRoEvEabWtS2c957Cdw9Q8WSXQ1kRerl8coz1g
Next we need to provide an Accept
header that specifies the version of the API we would like to use. For the purposes of this tutorial we will be using the following Accept
header:
Accept: application/vnd.papertrail.api+json; version=1.0
Finally we should also provide the correct Content-Type
for the request.
For making JSON requests, you should use:
Content-Type: application/json
For uploading files, you should use:
Content-Type: multipart/form-data
Adding uploads
Before we create an import, first we have to upload any images or PDFs that will be referenced by the products.
To do that we can send a POST
request with the following command:
curl -X POST https://api.papertrail.io/manufacturers/uploads \
-F "file=@kayak.jpg" \
-H "Authorization: Basic UwIlzlDTxzBRoEvEabWtS2c957Cdw9Q8WSXQ1kRerl8coz1g" \
-H "Accept: application/vnd.papertrail.api+json; version=1.0" \
-H "Content-Type: multipart/form-data"
This will return the url of the uploaded file if the request has been successfull:
{
"data": {
"url":"https://s3-eu-west-1.amazonaws.com/pt-manufacturers-products/acme/kayak.jpg"
}
}
Each file that is uploaded must have a unique name. If you wish to modify an existing file, simply upload a new file with the same name as the existing file.
Creating imports
Once all of the uploads have been added to Papertrail a new import can be created. The data to be sent to Papertrail should look like this:
{
"products": [
{
"name": "Unisex Adult Kayak",
"description": "Unisex adult kayak",
"images": [
"kayak.jpg"
],
"uploads": [
"kayak-instructions.pdf"
],
"checklists": [
"71e23a1a-e44a-4348-ace2-603c57ec0a77"
],
"fields": [
{
"label": "RFID",
"type": "rfid",
"value": "6FkpTvWKK8mxzGM4NIVY",
"unique": true,
"generic": false,
"searchable": true,
"internal_identifier": true
},
{
"label": "Date of manufacture",
"type": "date",
"value": "2018-03-02",
"unique": false,
"generic": false,
"searchable": false,
"internal_identifier":false
},
{
"label": "Colour",
"type": "string",
"value": "Red",
"unique": false,
"generic": true,
"searchable": false,
"internal_identifier":false
},
{
"label": "Model",
"type": "string",
"value": "Aqua2000",
"unique": false,
"generic": true,
"searchable": true,
"internal_identifier": true
}
]
}
]
}
Here we have a list of products to be imported into Papertrail (in this case, just one product). Each product must have a name
. You can also optionally supply a list of images, a list of uploads, and a list of checklists to be associated with the product.
The images and uploads must refer to the same file name as the files that were uploaded in the previous step.
Each of the customisable properties of the product are included as fields. In the example above we are including the following fields:
-
A unique RFID field that will be searchable and used as an internal identifier to identify the product in the future. As this is a unique field, it cannot be a generic field.
-
The date the product was manufacturered. This is not a unique field and it is not a generic field as it is specific to this individual product. We don’t want to be able to search on date fields and we don’t want to use the manufacturer date as an internal identifier.
-
The colour is a non-unique, generic attribute of the product. We also don’t want to be able to search on the colour and we don’t want to use it as an internal identifiery because it isn’t specific to this product.
-
The model of the product is not unique but it is generic as there could be variations. We should be able to search on the model to list all of the variations, and we should use it as an internal identifier as we might want to update across the entire line of products.
curl -X POST https://api.papertrail.io/manufacturers/imports \
-d @data.json \
-H "Authorization: Basic UwIlzlDTxzBRoEvEabWtS2c957Cdw9Q8WSXQ1kRerl8coz1g" \
-H "Accept: application/vnd.papertrail.api+json; version=1.0" \
-H "Content-Type: application/json"
This will return the following response on success:
{
"data":{
"id":"ec0064f2-2b06-4750-a114-844b99c39664",
"completed_at":null,
"has_errors":false,
"new":0,
"updated":0,
"segments":{
"data":[
{
"id":"012ace5a-57a0-444c-8bd7-50428345cec0",
"completed_at":null,
"errors":[]
}
]
}
}
}
The import has now been accepted and will be processed. The import is split into segments and processed sequentially. Once all of the segments of the import have been processed the import will be marked as complete.
If any of the segments produce an error, the has_errors
property will show as true
and the relevant segment will contain details of the error.
As the segments are processed the new
and updated
totals will increment. This will show you how the import has been processed so you can ensure that existing products have been updated correctly.
Update existing products
To update existing products, you should create a new import with the new product data. In order to identify existing products you should pass an identifier
top level attribute:
For example, to update a single unique product you would use a unique internal identifier field:
{
"products": [
{
"name": "Unisex Adult Kayak",
"description": "Unisex adult kayak",
"identifier": "6FkpTvWKK8mxzGM4NIVY",
"images": ["kayak.jpg"],
"uploads": ["kayak-instructions.pdf"],
"checklists": [],
"fields": [
{
"label": "Colour",
"type": "string",
"value": "Blue",
"unique": false,
"generic": true,
"searchable": false,
"internal_identifier":false
}
]
}
]
}
Here we have a list of products to be updated (in this case, just one product). You can include a mix of new and updated products in a single import.
Monitoring for errors
Due to the fact that the import is accepted and processed separately, it’s up to you to monitor existing imports for errors. If you find that an import has errored you can correct and resend the data to try again.
To view the details of an import, you can make a GET
request using the relevant id:
curl https://api.papertrail.io/manufacturers/imports/ec0064f2-2b06-4750-a114-844b99c39664 \
-H "Authorization: Basic UwIlzlDTxzBRoEvEabWtS2c957Cdw9Q8WSXQ1kRerl8coz1g" \
-H "Accept: application/vnd.papertrail.api+json; version=1.0" \
-H "Content-Type: application/json"
This will return the import with updated totals:
{
"data":{
"id":"ec0064f2-2b06-4750-a114-844b99c39664",
"completed_at":"2018-03-27T14:04:50+0000",
"has_errors":false,
"new":1,
"updated":0,
"segments":{
"data":[
{
"id":"012ace5a-57a0-444c-8bd7-50428345cec0",
"completed_at":"2018-03-27T14:04:50+0000",
"errors":[]
}
]
}
}
}
Alternatively, you can list all the imports that have been created:
curl https://api.papertrail.io/manufacturers/imports \
-H "Authorization: Basic UwIlzlDTxzBRoEvEabWtS2c957Cdw9Q8WSXQ1kRerl8coz1g" \
-H "Accept: application/vnd.papertrail.api+json; version=1.0" \
-H "Content-Type: application/json"
Generated by aglio on 23 Jul 2019