Manufacturers API

API Endpoint

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

POST /manufacturers/uploads
Requestsexample 1
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#"
}
Responses200
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
    • 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

GET /manufacturers/imports
Responses200
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


POST /manufacturers/imports
Requestsexample 1
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"
    }
  }
}
Responses200
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

GET /manufacturers/imports/1bea346d-1828-4dff-972b-50f610dd3676
Requestsexample 1
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"
    }
  }
}
Responses200
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}

URI Parameters
HideShow
id
string (required) Example: 1bea346d-1828-4dff-972b-50f610dd3676

The 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