API Documentation | Printful (1.0)

Download OpenAPI specification:Download

About the Printful API

The Printful API is a RESTful API, that uses an HTTP protocol for communication. HTTP GET, POST, PUT and DELETE methods are used to access the API resources.

Requests and responses

Request endpoint

All API requests have to be sent to this URL:

https://api.printful.com/

If you are using a proxy, make sure that all requests have host header set to api.printful.com.

Request parameters

Some mandatory parameters (like object identifiers) must be included in the request URL path

GET /orders/123

Additional parameters can be passed as GET variables:

GET /orders?offset=10&limit=5

For POST and PUT requests, a more complex data structure can be passed as JSON encoded data in the request body:

POST /orders

{"recipient":{...},"items":[...]}

Response body

The response body is always a JSON object that contains a response status code (identical to the HTTP status code) and the result of the action. If the status code is 200, then the action was successful.

{
   "code": 200, //Response status code
   "result":{
      //API method return data
      //...
   }
}

Sometimes the response includes paging information to allow to browse larger result sets by adding offset and limit GET parameters to the request URL.

{
   "code": 200, //Response status code
   "result":[
       {
          //Item 11
       },
       {
          //Item 12
       }
   ]
   "paging": {
      "total": 12,  //Total items available
      "offset": 10, //Items skipped from the beginning
      "limit": 20   //Number of items per page
   }
}

Error response

If the API call is not successful, then the response code is not in the 2xx range and the result attribute contains an error description.

{
    "code": 404,
    "result": "Not Found",
    "error": {
        "reason": "NotFound",
        "message": "Not Found"
    }
}

In general, response codes in the 4xx range indicate an error that resulted from the provided information (e.g. a required parameter was missing, etc.), and codes in the 5xx range indicate an error with Printful's servers.

Timestamps

All timestamps from the API are returned as integers in UNIX timestamp format.

Rate Limits

Printful API has a general rate limit of 120 API calls per minute. Additionally, endpoints that perform resource intensive operations (such as mockup generator) have a lower allowed request limit.

Localisation

Some of the resources returned by the API are translated into several languages. By default, they are returned in English in the API responses.

If you want to get a response with texts in another language, you can use the X-PF-Language HTTP header. Its value should be the long version of the locale to use (e.g. es_ES for Spanish).

Example

Product details (GET https://api.printful.com/products/71) response with default locale (en_US):

{
    "code": 200,
    "result": {
        "product": {
            "type_name": "T-Shirt",
            "title": "Unisex Staple T-Shirt | Bella + Canvas 3001",
            ...
        }
    }
}

Product details response with Spanish locale (X-PF-Language: es_ES):

{
    "code": 200,
    "result": {
        "product": {
            ...
            "type_name": "Camiseta",
            "title": "Camiseta esencial unisex | Bella + Canvas 3001",
            ...
        }
    }
}

Authorization

Private tokens and public apps

There are two different ways of using Printful OAuth - Private token and Public App. If you are developing an API solution for your personal store, you should choose Private Token. But if you are building an Public App that will be used by a wider audience, you should be choosing Public App.

Client types

There are two different client types - Store and Account. Store access level client is only able to access the specific store. For Private tokens this store is specified when the token is created, but for Public apps this store is specified when the app is installed. Account level tokens on the other hand can manage all the stores associated with the account. For the endpoints that require specific store context, requests should contain X-PF-Store-Id header. Account level access currently is only available for Private tokens.

Scopes

Scopes are used to limit access to specific resources and their methods. Scopes are defined in the developer portal when creating a Private Token or Public App. Customers on Public App installation grant screen will see all requested permissions, so be thoughtful about which scopes to request.

List of currently available scopes

Scope Client type Description
orders Store & Account Read and Write access to Orders
orders/read Store & Account Read access to Orders
sync_products Store & Account Read and Write access to SyncProducts
sync_products/read Store & Account Read access to SyncProducts
file_library Store & Account Read and Write access access to File library
file_library/read Store & Account Read access to File library
webhooks Store & Account Read and Write access to Webhooks
webhooks/read Store & Account Read access to Webhooks
product_templates Account Read and Write access to Product templates
product_templates/read Account Read access to Product templates

Developer Portal

Developer Portal is specifically designed for developers that want to interact with the Printful API. In the Developer Portal, it's possible to create and manage your Public Apps and Private tokens.

Acquiring Private Tokens

Private OAuth tokens can be generated in the Developer Portal's Token page. These tokens do not require refreshing and are valid until they expire or are deleted manually. Usage of these tokens is described below.

Acquiring OAuth tokens for Public Apps

For public apps to make requests on behalf of the customer, they must first acquire access tokens. In order to acquire these tokens, developers must follow these steps:

  • create an app in Apps page of developer portals
  • generate app-specific installation URL with Client id, Client secret, and other parameters
  • redirect the user to app installation url
  • once the users returns to redirect_url, use code parameter to acquire OAuth tokens

Public App authorization

Public App installation flow

Public App installation starts with a user redirection to an app-specific installation URL. Installation URL has to be generated in the following format:

https://www.printful.com/oauth/authorize?client_id={clientId}&state={stateValue}&redirect_url={redirectUrl}

Parameter Description
client_id the Client id of your app
state use the optional state parameter to help keep track of the customer throughout the installation process
redirect_url URL to where the customer should be taken after the authorization step. This URL must be registered in the app

In this URL, the customer is asked to register or log in to an existing account. After authorization, the customer is redirected to the OAuth grant screen. This screen shows information about your app, and the customer is asked to accept the requested scopes. If the customer rejects the app installation, he is redirected back to your provided redirect_url with success=0 parameter. If the customer accepts app installation, he is redirected to your redirect_url with state={stateValue}&code={authorizationCode}&success=1 parameters.

Parameter Description
state state parameter that was provided when installation flow was initialized
code authorization code that will be used to request access and refresh tokens
success flag indicating that authorization flow was successful

After receiving authorization code, apps should request access and refresh tokens. To request these tokens, the app should make a POST request to https://www.printful.com/oauth/token page with the following parameters:

  • grant_type=authorization_code
  • client_id={clientId}
  • client_secret={clientSecret}
  • code={authorizationCode}

If the request is successful the following response is returned:

{
  "access_token": "smk_GN0I1Os3OdfqzjJnTOWn1wlbqqq2Y2Pc10TS",
  "expires_at": "1562157895",
  "token_type": "bearer",
  "refresh_token": "902LmW0sWNlY-mbrLhb6AgexkI6K4OFo3Hknak8HDhTy_ifB5SdoLH1QgV9"
}
Field Description
access_token this token should be used to make authorized API calls
expires_at timestamp for the date when the access_token will expire
token_type type of the token. Currently only bearer. Use it together with the access_token in authorized requests headers
refresh_token a token that can be used to refresh the access_token once it expires

Refreshing tokens

The access_token will expire in one hour. When access_token expires you must refresh it with the refresh_token. After refreshing tokens, you will receive a new set of access_token and refresh_token. If tokens are not refreshed within 90 days, refresh_token will expire, and the app will have to ask the user to reauthorize it. To refresh tokens you must make a POST request to https://www.printful.com/oauth/token with the parameters:

  • grant_type=refresh_token
  • client_id={clientId}
  • client_secret={clientSecret}
  • refresh_token={refreshToken}

The successful refresh request will result in a similar response that you received previously:

{
  "access_token": "smk_GN0I1Os3OdfqzjJnTOWn1wlbqqq2Y2Pc10TS",
  "expires_at": "1562157895",
  "token_type": "bearer",
  "refresh_token": "902LmW0sWNlY-mbrLhb6AgexkI6K4OFo3Hknak8HDhTy_ifB5SdoLH1QgV9"
}

OAuth API

OAuth API allows receiving data for token

Get scopes for token

Returns a list of scopes associated with the token

Authorizations:
OAuth

Responses

Response Schema: application/json
code
integer

Response status code 200

object

Request samples

curl --location --request GET 'https://api.printful.com/oauth/scopes' --header 'Authorization: Bearer {oauth_token}'

Response samples

Content type
application/json
{
  • "code": 200,
  • "result": {
    }
}

Catalog API

Printful has a substantial catalog of blank Products and Variants. A Product can describe a specific type, model and manufacturer of the item, while the Variant specifies the more detailed attributes of the product like the exact size/color of a T-shirt or the dimensions of a poster. Moreover, each item in the Printful Catalog has a unique Variant ID. When managing Sync Products or orders, you will need to specify the Variant ID of the specific blank item, hence you can use this API resource to find the needed Variant ID.

It is critically important to always refer to the Variant IDs (NOT Product IDs) when creating products or orders. Mixing up and using the Product ID instead of the Variant ID can lead to an entirely different product created or item ordered. The Product entity is only meant to allow of easier browsing of what Printful offers.

You can also use this API resource to find out the types of print files a product can be configured for as well as the additional price each print file would cost (e.g. the back print or inside label print for T-shirts). Moreover, some product types allow for additional options (e.g. embroidery type and thread colors) - these options are listed in the responses as well.

Please note that the current Catalog API does not reflect the discounted pricing available in the Printful subscription plans.

Important: Jewelry products are not supported via API.

Rate limiting: For unauthenticated usages, up to 30 requests per 60 seconds. A 60 seconds lockout is applied if request count is exceeded.

Size guides

The Get Product Size Guide endpoint will return size guide data for the selected product.

There are three types of size tables available, as described by the following table:

Table type API name Description
Measure yourself measure_yourself Measurements of the product to measure the body provided by the supplier.
Product measurements product_measure Measurements of the product provided by the supplier.
International size conversion international International size conversion – e.g. US, EU or UK sizes corresponding to the product sizes.

Not each table type might be available for the selected product.

See examples

Get Products

Returns list of Products available in the Printful

query Parameters
category_id
string

A comma-separated list of Category IDs of the Products that are to be returned

Responses

Response Schema: application/json
code
integer

Response status code 200

Array of objects (Product)

Request samples

curl --location --request GET 'https://api.printful.com/products'

Response samples

Content type
application/json
{
  • "code": 200,
  • "result": [
    ]
}

Get Variant

Returns information about a specific Variant and its Product

path Parameters
id
required
integer

Variant id

Responses

Response Schema: application/json
code
integer

Response status code 200

object (VariantInfo)

Request samples

curl --location --request GET 'https://api.printful.com/products/variant/4018'

Response samples

Content type
application/json
{
  • "code": 200,
  • "result": {
    }
}

Get Product

Returns information about a specific product and a list of variants for this product.

path Parameters
id
required
integer

Product ID.

Responses

Response Schema: application/json
code
integer

Response status code 200

object (ProductInfo)

Request samples

curl --location --request GET 'https://api.printful.com/products/71'

Response samples

Content type
application/json
{
  • "code": 200,
  • "result": {
    }
}

Get Product Size Guide

Returns information about the size guide for a specific product.

path Parameters
id
required
integer

Product ID.

query Parameters
unit
string
Example: unit=inches,cm

A comma-separated list of measurement unit in which size tables are to be returned (inches or cm). The default value is determined based on the locale country. The inches are used for United States, Liberia and Myanmar, for other countries the unit defaults to centimeters.

Responses

Response Schema: application/json
code
integer

Response status code 200

object (ProductSizeGuide)

Size Guide information for the Product

Request samples

curl --location --request GET 'https://api.printful.com/products/71/sizes'

Response samples

Content type
application/json
{
  • "code": 200,
  • "result": {
    }
}

Get Categories

Returns list of Catalog Categories available in the Printful

Responses

Response Schema: application/json
code
integer

Response status code 200

Array of objects (Category)

Request samples

curl --location --request GET 'https://api.printful.com/categories'

Response samples

Content type
application/json
{}

Get Category

Returns information about a specific category.

path Parameters
id
required
integer

Category ID

Responses

Response Schema: application/json
code
integer

Response status code 200

object (Category)

Information about the Category

Request samples

curl --location --request GET 'https://api.printful.com/categories/24'

Response samples

Content type
application/json
{}

Products API

The Products API resource lets you create, modify and delete products in a Printful store based on the Manual orders / API platform (you can create such store by going to the Stores section at your Printful dashboard.)

Important: Jewelry products are not supported via API.

To configure products and variants at a Printful store based on Shopify, WooCommerce or another supported integration platform, please see Ecommerce Platform Sync API.

To manage Warehouse products, please see Warehouse Products API.

The basics

Each product in your Printful store must contain one or multiple variants (imagine multiple sizes or colors of the same t-shirt design). Furthermore, for each variant, you have to specify both a blank product variant from our Printful Catalog and a print file. These two properties together with price and External ID (more on that later) will allow the variant to be purchasable. Please, see the following sections for more details. Finally, please note that for technical reasons a product in your Printful store is called a Sync Product and a variant of that product is called a Sync Variant. The maximum supported amount of Sync Variants a Sync Product can have is 100.

Assigning a blank product variant

Printful has a substantial catalog of blank products and variants, where each variant (e.g. size and color combination of a particular product) has a unique ID, which we call variant_id. You can browse through the catalog via Catalog API to find a specific variant_id. Moreover, when creating a Sync Product at your Printful store, each of its Sync Variants must be associated with a variant_id from the Printful Catalog. Furthermore, to assign a specific variant_id to a specific Sync Variant, simply add it to the HTTP request body (see examples at the specific endpoint).

Assigning a single print file

There are two ways to assign a print file to a Sync Variant. One is to specify the File ID if the file already exists in the File library of the authorized store;

Limitations

Important: The Products API is not intended and will never support creating and managing products in external platforms such as Shopify, WooCommerce and others. For managing your products from external platforms please refer to Ecommerce Platform Sync API

{
    ...
    "files": [
        {
            "id": 12345
        }
    ],
    ...
}

The second and most convenient method is to specify the file URL. If a file with the same URL already exists, it will be reused.

{
    ...
    "files": [
        {
            "url": "http://example.com/t-shirts/123/front.pdf"
        }
    ],
    ...
}

Moreover, each Sync Variant has to be linked with one or multiple print files. The available file types for each product are available from the Printful Catalogue API. You can add one file for each type by specifying the type attribute. For the default type, this attribute can be skipped.

...
"files":[
    {
        "type": "default",
        "url": "http://example.com/t-shirts/123/front.pdf"
    },
    {
        "type": "back"
        "url": "http://example.com/t-shirts/123/back.pdf"
    }
],
...

Remember that using additional files can increase the price of the item.

External ID

When creating a Sync Product and/or Sync Variant you can specify an External ID, which you can then use as a reference when managing or even ordering the specific Sync Product or Sync Variant. In particular, when requesting a specific Sync Product and Sync Variant, you can use either the internal Printful ID or your External ID (prefixed with an @ symbol) at the request URL.

Native inside label

Printful previously allowed customers to upload a fully customized inside label. Since these labels had to contain specific information about fabric composition, manufacturing, etc. to meet the legal requirements, users usually encountered issues to get their labels printed.

Inside labels are printed on the inside of the garment and require the removal of the original manufacturer's tag. They're only available for apparel with tear-away labels. An inside label must include the country of manufacturing origin, original garment size, and material information. To use our native label template you only need to upload a graphic (such as your brand's logo). The mandatory content will be generated and placed automatically.

...
"files":[
        {
            "type": "label_inside",
            "url": "http://example.com/logo/123/image.jpg",
            "options": [{
                "id": "template_type",
                "value": "native"
            }]
        },
],
...

Printful previously supported fully customized inside labels. These have now been deprecated. The ability to create orders with fully customized inside labels has been limited to only users who were actively using them in their stores before April 2020. This feature is no longer accessible to new users.

See examples

Get Sync Products

Returns a list of Sync Product objects from your custom Printful store.

Authorizations:
OAuth
query Parameters
status
string
Enum: "all" "synced" "unsynced" "ignored" "imported" "discontinued" "out_of_stock"

Parameter used to filter results by status/group of Sync Products

category_id
string

A comma-separated list of Category IDs of the Products that are to be returned

header Parameters
X-PF-Store-Id
string

Use this to specify which store you want to use (required only for account level token).

The store IDs can be retrieved with the Get basic information about stores endpoint.

Responses

Response Schema: application/json
code
integer

Response status code 200

object (Paging)

Paging information

Array of objects (SyncProduct)

Array of SyncProduct

Request samples

curl --location --request GET 'https://api.printful.com/store/products' \
--header 'Authorization: Bearer {oauth_token}'

Response samples

Content type
application/json
{
  • "code": 200,
  • "paging": {
    },
  • "result": [
    ]
}

Create a new Sync Product

Creates a new Sync Product together with its Sync Variants (See examples).

Authorizations:
OAuth
header Parameters
X-PF-Store-Id
string

Use this to specify which store you want to use (required only for account level token).

The store IDs can be retrieved with the Get basic information about stores endpoint.

Request Body schema: application/json
required

POST request body

required
object (SyncProduct)

Information about the SyncProduct

required
Array of objects (SyncVariant)

Information about the Sync Variants

Responses

Response Schema: application/json
code
integer

Response status code 200

object (SyncProduct)

Information about the SyncProduct

Request samples

Content type
application/json
{
  • "sync_product": {
    },
  • "sync_variants": [
    ]
}

Response samples

Content type
application/json
{
  • "code": 200,
  • "result": {
    }
}

Get a Sync Product

Get information about a single Sync Product and its Sync Variants.

Authorizations:
OAuth
path Parameters
required
integer or string

Sync Product ID (integer) or External ID (if prefixed with @)

header Parameters
X-PF-Store-Id
string

Use this to specify which store you want to use (required only for account level token).

The store IDs can be retrieved with the Get basic information about stores endpoint.

Responses

Response Schema: application/json
code
integer

Response status code 200

object (SyncProductInfo)

Request samples

curl --location --request GET 'https://api.printful.com/store/products/{sync_product_id}' \
--header 'Authorization: Bearer {oauth_token}'

Response samples

Content type
application/json
{
  • "code": 200,
  • "result": {
    }
}

Delete a Sync Product

Deletes a Sync Product with all of its Sync Variants

Authorizations:
OAuth
path Parameters
required
integer or string

Sync Product ID (integer) or External ID (if prefixed with @)

header Parameters
X-PF-Store-Id
string

Use this to specify which store you want to use (required only for account level token).

The store IDs can be retrieved with the Get basic information about stores endpoint.

Responses

Response Schema: application/json
code
integer

Response status code 200

object (SyncProductInfo)

Request samples

curl --location --request DELETE 'https://api.printful.com/store/products/161636638' \
--header 'Authorization: Bearer {oauth_token}'

Response samples

Content type
application/json
{
  • "code": 200,
  • "result": {
    }
}

Modify a Sync Product

Modifies an existing Sync Product with its Sync Variants.

Please note that in the request body you only need to specify the fields that need to be changed. Furthermore, if you want to update existing sync variants, then in the sync variants array you must specify the IDs of all existing sync variants. All omitted existing sync variants will be deleted. All new sync variants without an ID will be created. See examples for more insights.

Rate limiting: Up to 10 requests per 60 seconds. A 60 seconds lockout is applied if request count is exceeded.

See examples

Authorizations:
OAuth
path Parameters
required
integer or string

Sync Product ID (integer) or External ID (if prefixed with @)

header Parameters
X-PF-Store-Id
string

Use this to specify which store you want to use (required only for account level token).

The store IDs can be retrieved with the Get basic information about stores endpoint.

Request Body schema: application/json
required

PUT request body

object (SyncProduct)

Information about the SyncProduct

Array of SyncVariant (object) or SyncVariant (object) (SyncVariant)

Information about the Sync Variants

Responses

Response Schema: application/json
code
integer

Response status code 200

object (SyncProduct)

Information about the SyncProduct

Request samples

Content type
application/json
{
  • "sync_product": {
    },
  • "sync_variants": [
    ]
}

Response samples

Content type
application/json
{
  • "code": 200,
  • "result": {
    }
}

Get a Sync Variant

Get information about a single Sync Variant.

Authorizations:
OAuth
path Parameters
required
integer or string

Sync Variant ID (integer) or External ID (if prefixed with @)

header Parameters
X-PF-Store-Id
string

Use this to specify which store you want to use (required only for account level token).

The store IDs can be retrieved with the Get basic information about stores endpoint.

Responses

Response Schema: application/json
code
integer

Response status code 200

object (SyncVariant)

Information about the SyncVariant

Response samples

Content type
application/json
{
  • "code": 200,
  • "result": {
    }
}

Delete a Sync Variant

Deletes a single Sync Variant.

Authorizations:
OAuth
path Parameters
required
integer or string

Sync Variant ID (integer) or External ID (if prefixed with @)

header Parameters
X-PF-Store-Id
string

Use this to specify which store you want to use (required only for account level token).

The store IDs can be retrieved with the Get basic information about stores endpoint.

Responses

Response Schema: application/json
code
integer

Response status code 200

result
Array of arrays = 0 items

Request samples

curl --location --request DELETE 'https://api.printful.com/store/variants/1781126754' \
--header 'Authorization: Bearer {oauth_token}'

Response samples

Content type
application/json
{
  • "code": 200,
  • "result": [ ]
}

Modify a Sync Variant

Modifies an existing Sync Variant.

Please note that in the request body you only need to specify the fields that need to be changed. See examples for more insights.

See examples

Authorizations:
OAuth
path Parameters
required
integer or string

Sync Variant ID (integer) or External ID (if prefixed with @)

header Parameters
X-PF-Store-Id
string

Use this to specify which store you want to use (required only for account level token).

The store IDs can be retrieved with the Get basic information about stores endpoint.

Request Body schema: application/json
required

POST request body

id
integer

Sync Variant ID. Please specify the IDs of all Sync Variants you wish to keep.

external_id
string

Variant ID from the Ecommerce platform

variant_id
integer

Printful Variant ID that this Sync Variant is synced to

retail_price
string

Retail price that this item is sold for

is_ignored
boolean

Indicates if this Sync Variant is ignored

sku
string or null

SKU of this Sync Variant

Array of objects (SyncVariantFile)

Array of attached printfiles / preview images

Array of objects (SyncVariantOption)

Array of additional options for the configured product/variant See examples

availability_status
string
Enum: "active" "discontinued" "out_of_stock" "temporary_out_of_stock"

Indicates the status of the Sync Variant.

Responses

Response Schema: application/json
code
integer

Response status code 200

object (SyncVariant)

Information about the SyncVariant

Request samples

Content type
application/json
{
  • "id": 10,
  • "external_id": "12312414",
  • "variant_id": 3001,
  • "retail_price": "29.99",
  • "is_ignored": true,
  • "sku": "SKU1234",
  • "files": [
    ],
  • "options": [
    ],
  • "availability_status": "active"
}

Response samples

Content type
application/json
{
  • "code": 200,
  • "result": {
    }
}

Create a new Sync Variant

Creates a new Sync Variant for an existing Sync Product (See examples).

Authorizations:
OAuth
path Parameters
required
integer or string

Sync Product ID (integer) or External ID (if prefixed with @)

header Parameters
X-PF-Store-Id
string

Use this to specify which store you want to use (required only for account level token).

The store IDs can be retrieved with the Get basic information about stores endpoint.

Request Body schema: application/json
required

POST request body

external_id
string

Variant ID from the Ecommerce platform

variant_id
required
integer

Printful Variant ID that this Sync Variant is synced to

retail_price
string

Retail price that this item is sold for

is_ignored
boolean

Indicates if this Sync Variant is ignored

sku
string or null

SKU of this Sync Variant

required
Array of objects (SyncVariantFile)

Array of attached printfiles / preview images

Array of objects (SyncVariantOption)

Array of additional options for the configured product/variant See examples

availability_status
string
Enum: "active" "discontinued" "out_of_stock" "temporary_out_of_stock"

Indicates the status of the Sync Variant.

Responses

Response Schema: application/json
code
integer

Response status code 200

object (SyncVariant)

Information about the SyncVariant

Request samples

Content type
application/json
{
  • "external_id": "12312414",
  • "variant_id": 3001,
  • "retail_price": "29.99",
  • "is_ignored": true,
  • "sku": "SKU1234",
  • "files": [
    ],
  • "options": [
    ],
  • "availability_status": "active"
}

Response samples

Content type
application/json
{
  • "code": 200,
  • "result": {
    }
}

Product Templates API

The Product Templates API resource lets you retrieve the product templates information.

External Product ID

In case of a single template retrieval it is possible to get it by the External Product ID. In order to do this, the ID needs to be prepended with the '@' character. Here are the examples of how to get the template data by the Template ID and by the External Product ID.

GET /product-templates/11001  - reference by Printful Template ID
GET /product-templates/@988123  - reference by External ID

See examples

Get product template list

Returns a list of templates.

Authorizations:
OAuth
query Parameters
offset
integer

Result set offset

limit
integer

Number of items per page (max 100)

Responses

Response Schema: application/json
code
integer

Response status code 200

object (Product template)

Information about the template

object (Paging)

Paging information

Request samples

curl --location --request GET 'https://api.printful.com/product-templates' \
--header 'Authorization: Bearer {oauth_token}'

Response samples

Content type
application/json
{
  • "code": 200,
  • "result": {
    },
  • "paging": {
    }
}

Get product template

Get information about a single product template

Authorizations:
OAuth
path Parameters
required
integer or string

Template ID (integer) or External Product ID (if prefixed with @)

Responses

Response Schema: application/json
code
integer

Response status code 200

object (Product template)

Information about the template

Request samples

curl --location --request GET 'https://api.printful.com/product-templates/{template_id}' \
--header 'Authorization: Bearer {oauth_token}'

Response samples

Content type
application/json
{
  • "code": 200,
  • "result": {
    }
}

Delete product template

Delete product template by ID or External Product ID

Authorizations:
OAuth
path Parameters
required
integer or string

Template ID (integer) or External Product ID (if prefixed with @)

Responses

Response Schema: application/json
code
integer

Response status code 200

object

Request samples

curl --location --request DELETE 'https://api.printful.com/product-templates/{template_id}' \
--header 'Authorization: Bearer {oauth_token}'

Response samples

Content type
application/json
{
  • "code": 200,
  • "result": {
    }
}

Orders API

The Orders API is the most important part of the Printful API - it allows you to create new orders and confirm them for fulfillment.

Important: Jewelry products are not supported via API.

Order life cycle and statuses

Each order will go through different states while being processed. The following order status types indicate those states:

draft The order is created but is not yet submitted for fulfillment. You still can edit it and confirm later.
pending The order has been submitted for fulfillment, but is not yet accepted for fulfillment. You can still cancel the order if you need.
failed Order was submitted for fulfillment but was returned for review because of an error (problem with address, missing printfiles, charging has failed, etc.).
canceled The order has been canceled and can no longer be processed. If the order was charged then the amount has been returned to your credit card.
inprocess The order is being fulfilled and can no longer be cancelled or modified. Contact customer support if there are any issues with the order at this point.
onhold The order has encountered a problem during the fulfillment that needs to be resolved together with Printful customer service before fulfillment can continue.
partial The order is partially fulfilled (some items are shipped already, the rest will follow)
fulfilled All items have been shipped successfully
archived The order has been archived and hidden from the UI

To sum up, the API allows you to create orders with status draft and then move them to state pending (both steps can be done with a single action). You are only charged for orders that have been confirmed. If the order encounters a problem after it has been submitted, then it is moved to the failed state so that the problem can be fixed and the order can be resubmitted.

Asynchronous order cost calculation

Most of the times, when you submit an order, we'll perform the cost calculation and return it in the response.

However, we might not be able to calculate all the costs immediately, for example if the order contains a new advanced embroidery design. If that's the case, we'll automatically put your order on hold, calculate the order costs once it's possible, and then remove the order from hold.

Such an order will return to a draft status (even if it was created with the auto-confirm option) and will need to be confirmed.

You can subscribe to the order_remove_hold event (see Webhook API) to be notified when the order is removed from hold.

External ID

External ID is an optional feature that allows you to link your Printful order with the Order ID from your system without the need to store additional data on your side. External ID can be up to 32 characters long and contain digits, Latin alphabet letters, dashes and underscores, however it is recommended to use integer numbers. Each order's External ID must be unique within the store.

To use the External ID feature, you just add the external_id attribute when creating the order. Later, when you need to access the order through the API, you can reference it by both the Order ID and by External ID (if you prefix it with the @ symbol).

GET /orders/11001  - reference by Printful Order ID
GET /orders/@988123  - reference by External ID
GET /orders/@AA123123  - reference by External ID

You can assign the external_id attribute to line items as well. In this case they have to be unique per order.

Specifying products

There are three general ways to specify a product’s variant when creating, updating or estimating an order:

(A) Using an existing product variant (sync variant) in your Printful store or warehouse. To specify the existing product please use its sync_variant_id or external_variant_id, or warehouse_product_variant_id.

Example using Sync Variant ID Example using External Variant ID

(B) Using a Catalog API variant without adding a product to the store. This method can be used when a Printful store has no products in it. To construct a variant on-the-fly retrieve a specific variant_id from the Catalog API together with print files and an additional options.

Example

(C) Using an existing template ID. This method can be used when a Printful store has assigned templates without the need to create products. To create an order please use the product_template_id and variant_id that will be added to the order.

Example

Adding print files

There are two ways to assign a print file to the item. One is to specify the File ID if the file already exists in the file library of the authorized store:

...
"files": [
    {
        "id": 12345
    },
],
...

The second and the most convenient method is to specify the file URL. If a file with the same URL already exists, it will be reused.

...
"files": [
    {
        "url": "http://example.com/t-shirts/123/front.pdf"
    },
],
...

Specifying file position

You can specify the image position inside the print area by providing a position object.

Important

  • Each print area has specific dimensions, by default Orders API will assume that your file has to stick to those limitations and not exceed them. In some cases you would want to position your file outside the print area - to be able to do so use the limit_to_print_area and set it to: false.
  • limit_to_print_area determines if the image can cross the print area border. If limit_to_print_area is set to true then the request will result in 400 Bad Request with "Invalid position" in error.message once the image crosses the print area borders. If limit_to_print_area is set to false then it will be possible to place image partially or fully outside the print area.
  • The (0,0) point is always located in top left corner of the print area.

Steps
1.Retrieve printfile dimensions Printfiles

...
"printfiles":
    [
        {
            "printfile_id": 1,
            "width": 1800,
            "height": 2400,
            "dpi": 150,
            "fill_mode": "fit",
            "can_rotate": false
        }
    ],
...

2.Specify file position for specific print placement while creating an order. Use items -> files -> position object as in the example:

...
"items": [
    {
        "variant_id":4011,
        "quantity":"1",
        "files": [
            {
                "type": "front",
                "url": "http://example.com/t-shirts/123/front.pdf",
                "position": {
                    "area_width": 1800,
                    "area_height": 2400,
                    "width": 1800,
                    "height": 1800,
                    "top": 300,
                    "left": 0,
                    "limit_to_print_area": true
                }
            }
        ]
    }
]
...

Example of positioning the 450x450 image on the front placement

Position Mockup Payload
Top left Top left mockup
  "position": {
  "area_width": 1800,
  "area_height": 2400,
  "width": 450,
  "height": 450,
  "top": 0,
  "left": 0,
  "limit_to_print_area": true
  }
Top middle Top left mockup
"position": {
"area_width": 1800,
"area_height": 2400,
"width": 450,
"height": 450,
"top": 0,
"left": 675,
"limit_to_print_area": true
}
Top right Top left mockup
"position": {
"area_width": 1800,
"area_height": 2400,
"width": 450,
"height": 450,
"top": 0,
"left": 1350,
"limit_to_print_area": true
}
Middle Top left mockup
"position": {
"area_width": 1800,
"area_height": 2400,
"width": 450,
"height": 450,
"top": 975,
"left": 675,
"limit_to_print_area": true
}
Bottom left Top left mockup
"position": {
"area_width": 1800,
"area_height": 2400,
"width": 450,
"height": 450,
"top": 1950,
"left": 0,
"limit_to_print_area": true
}
Bottom middle Top left mockup
"position": {
"area_width": 1800,
"area_height": 2400,
"width": 450,
"height": 450,
"top": 1950,
"left": 675,
"limit_to_print_area": true
}
Bottom right Top left mockup
"position": {
"area_width": 1800,
"area_height": 2400,
"width": 450,
"height": 450,
"top": 1950,
"left": 1350,
"limit_to_print_area": true
}

Specifying multiple files per item

Each item in the order has to be linked with one or multiple files. The available file types for each product are available from the Catalog API.

You can add one file for each type by specifying the type attribute. For the default type, this attribute can be skipped.

...
"files":[
    {
        "type": "default",
        "url": "http://example.com/t-shirts/123/front.pdf"
    },
    {
        "type": "back"
        "url": "http://example.com/t-shirts/123/back.pdf"
    },
    {
        "type": "preview"
        "url": "http://example.com/t-shirts/123/preview.png"
    }
],
...

Remember that using additional files can increase the price of the item.

Creating orders from a template

Orders API allows also creating orders based on the product template created in the Printful account without the need to add the product to the Printful store.

To retrieve available templates for your account please use the Products Templates API.

To create an order from a template you need to specify a variant or variants that will be added to the order. It is possible to use multiple templates with different variants in one request. To achieve that please use the items object below:

    ...
    "items": [
        {
            "variant_id": 4012,
            "quantity": 1,
            "product_template_id": 123456789
        },
        {
            "variant_id": 1,
            "quantity": 2,
            "product_template_id": 11235813
        },
    ]
    ...

Important note: you can only create orders from templates for variant IDs from the Catalog API.

More examples are available here.

Retail costs

Printful allows you to specify your retail costs for the order so that the packing slip for international orders can contain your correct retail prices. To enable retail costs, each item in the order has to contain the retail_price attribute. You can also specify a custom discount sum, shipping costs and taxes in the retail_costs object when creating the order. If the retail costs are missing, the packing slip will contain the Printful prices instead.

Native inside label

Printful previously allowed customers to upload a fully customized inside label. Since these labels had to contain specific information about fabric composition, manufacturing, etc. to meet the legal requirements, users usually encountered issues to get their labels printed.

Inside labels are printed on the inside of the garment and require the removal of the original manufacturer's tag. They're only available for apparel with tear-away labels. An inside label must include the country of manufacturing origin, original garment size, and material information. To use our native label template you only need to upload a graphic (such as your brand's logo). The mandatory content will be generated and placed automatically.

...
"files":[
        {
            "type": "label_inside",
            "url": "http://example.com/logo/123/image.jpg",
            "options": [{
                "id": "template_type",
                "value": "native"
            }]
        },
],
...

Printful previously supported fully customized inside labels. These have now been deprecated. The ability to create orders with fully customized inside labels has been limited to only users who were actively using them in their stores before April 2020. This feature is no longer accessible to new users.

Ordering embroidery products

Embroidery is a technique which uses colored threads, sewn into a product, to recreate provided design. In order to use embroidery technique you first need to check if selected product support embroidery technique.

In order to do that you need to use Catalog API to determine if the selected product or variant contains EMBROIDERY technique.

"techniques": [
                {
                    "key": "EMBROIDERY",
                    "display_name": "Embroidery",
                    "is_default": true
                }
            ]

After that you need to also get list of available embroidery placements. Those are listed under file property with embroidery_ prefix. You can get list of all available placements in Placements.

Example of file property
"files": [
                {
                    "id": "default",
                    "type": "embroidery_front",
                    "title": "Front",
                    "additional_price": null
                },
                {
                    "id": "back",
                    "type": "embroidery_back",
                    "title": "Back",
                    "additional_price": "3.75"
                },
                {
                    "id": "left",
                    "type": "embroidery_left",
                    "title": "Left side",
                    "additional_price": "3.75"
                },
                {
                    "id": "right",
                    "type": "embroidery_right",
                    "title": "Right side",
                    "additional_price": "3.75"
                },
                {
                    "id": "preview",
                    "type": "mockup",
                    "title": "Mockup",
                    "additional_price": null
                }
            ]

To create an order using embroidery technique you can:

Finally, you can make an order using embroidery technique See example. Depending on the placement that you've used you need to specify the correct thread color option.

Packing slip

The packing slip fields can be configured at the store level and overridden for a specific order.

The packing slip settings can be found in Dashboard at Settings > Stores > Branding > Packing slip section.

To override the packing slip settings for the order, you can use packing_slip or gift fields.

Below you can find an example or a packing slip for a shipment with explained fields.

packing slip

Field annotations:

  • (1) Barcode unique for the shipment.
  • (2) Store logo defined in the store settings or overridded using packing_slip.logo_url field.
  • (3) The date of the shipment.
  • (4) Packing slip number consisting of order and shipment IDs in Printful database, divided with a hyphen.
  • (5) The country from which the shipment is made. If the recipient is in the United States, this field will be absent.
  • (6) Recipient address with phone, without email address.
  • (7) Store name. This can be overridden using packing_slip.store_name.
  • (8) The address to which the shipment should be returned. By default it will be a Printful’s return address, but you can set your own address in the store settings (Settings > Stores > Returns > Return address section).
  • (9) The customer service phone number defined in the store settings or overridden using packing_slip.phone field.
  • (10) The customer service email address defined in the store settings or overridden using packing_slip.email field.
  • (11) Gift message. This is only present if the gift field was provided in the order request.
  • (12) The order creation date.
  • (13) Printful Order ID which can be overridden using packing_slip.custom_order_id field.
  • (14) The list of order items with quantities. The items’ display names are localized, using the recipient’s country and include variant information such as color and size e.g. „Unisex Staple T-Shirt | Bella + Canvas 3001 ( Lilac / M)”.
  • (15) The packing slip message defined in the store settings or overridden using packing_slip.message field.

More Orders API examples

See the examples section for more sample requests on how Orders API can be used in different scenarios.

Custom border color option

Stickers can have a different border color which can be set by using the thread_colors_outline option. This option is available in options for stickers. To showcase the usage we will use the order flow which will create order with a sticker that will have a red border color:

Endpoint POST https://api.printful.com/orders

Request body
{
    "shipping": "STANDARD",
    "recipient": {
        "name": "John Smith",
        "address1": "19749 Dearborn St",
        "city": "Chatsworth",
        "country_code": "US",
        "state_code": "CA",
        "zip": "91311"
    },
    "items": [
        {
            "variant_id": 10163,
            "files": [
                {
                    "type": "default",
                    "url": "https://www.printful.com/static/images/layout/printful-logo.png"
                }
            ],
            "options": [
                {
                    "id": "custom_border_color",
                    "value": "#FF0000"
                }
            ]
        }
    ]
}

Get list of orders

Returns list of order objects from your store

Authorizations:
OAuth
query Parameters
status
string

Filter by order status

offset
integer

Result set offset

limit
integer

Number of items per page (max 100)

Responses

Response Schema: application/json
code
integer

Response status code 200

object (Paging)

Paging information

Array of objects (Order)

Request samples

curl --location --request GET 'https://api.printful.com/orders' \
--header 'Authorization: Bearer {oauth_token}'

Response samples

Content type
application/json
{
  • "code": 200,
  • "paging": {
    },
  • "result": [
    ]
}

Create a new order

Creates a new order and optionally submits it for fulfillment (See examples)

Authorizations:
OAuth
query Parameters
confirm
boolean

Automatically submit the newly created order for fulfillment (skip the Draft phase)

update_existing
boolean

Try to update existing order if an order with the specified external_id already exists

header Parameters
X-PF-Store-Id
string

Use this to specify which store you want to use (required only for account level token).

The store IDs can be retrieved with the Get basic information about stores endpoint.

Request Body schema: application/json
required

POST request body

external_id
string or null

Order ID from the external system

shipping
string

Shipping method. Defaults to 'STANDARD'

required
object (Address)

Information about the address

required
Array of objects (Item)

Array of items in the order

object (OrderRetailCosts)

Retail costs that are to be displayed on the packing slip for international shipments. Retail costs are used only if every item in order contains the retail_price attribute.

object (OrderGift)

Optional gift message for the packing slip

OrderPackingSlip (object) or OrderPackingSlip (object) or OrderPackingSlip (object) or OrderPackingSlip (object) (OrderPackingSlip)

Custom packing slip for this order. Example of a packing slip with explained fields can be found here.

Responses

Response Schema: application/json
code
integer

Response status code 200

object (Order)

Information about the Order

Request samples

Content type
application/json
{
  • "external_id": "4235234213",
  • "shipping": "STANDARD",
  • "recipient": {
    },
  • "items": [
    ],
  • "retail_costs": {
    },
  • "gift": {
    },
  • "packing_slip": {
    }
}

Response samples

Content type
application/json
{
  • "code": 200,
  • "result": {
    }
}

Get order data

Returns order data by ID or External ID.

Authorizations:
OAuth
path Parameters
required
string or integer

Order ID (integer) or External ID (if prefixed with @)

header Parameters
X-PF-Store-Id
string

Use this to specify which store you want to use (required only for account level token).

The store IDs can be retrieved with the Get basic information about stores endpoint.

Responses

Response Schema: application/json
code
integer

Response status code 200

object (Order)

Information about the Order

Request samples

curl --location --request GET 'https://api.printful.com/orders/{order_id}' \
--header 'Authorization: Bearer {oauth_token}'

Response samples

Content type
application/json
{
  • "code": 200,
  • "result": {
    }
}

Cancel an order

Cancels pending order or draft. Charged amount is returned to the store owner's credit card.

Authorizations:
OAuth
path Parameters
required
string or integer

Order ID (integer) or External ID (if prefixed with @)

header Parameters
X-PF-Store-Id
string

Use this to specify which store you want to use (required only for account level token).

The store IDs can be retrieved with the Get basic information about stores endpoint.

Responses

Response Schema: application/json
code
integer

Response status code 200

object (Order)

Information about the Order

Request samples

curl --location --request DELETE 'https://api.printful.com/orders/{order_id}' \
--header 'Authorization: Bearer {oauth_token}'

Response samples

Content type
application/json
{
  • "code": 200,
  • "result": {
    }
}

Update order data

Updates unsubmitted order and optionally submits it for the fulfillment.

Note that you need to post only the fields that need to be changed, not all required fields.

If items array is given in the update data, the items will be:

a) updated, if the update data contains the item id or external_id parameter that alreay exists

b) deleted, if the request doesn't contain the item with previously existing id

c) created as new if the id is not given or does not already exist

Authorizations:
OAuth
path Parameters
required
string or integer

Order ID (integer) or External ID (if prefixed with @)

query Parameters
confirm
boolean

Automatically submit the newly created order for fulfillment (skip the Draft phase)

header Parameters
X-PF-Store-Id
string

Use this to specify which store you want to use (required only for account level token).

The store IDs can be retrieved with the Get basic information about stores endpoint.

Request Body schema: application/json
required

POST request body

external_id
string or null

Order ID from the external system

shipping
string

Shipping method. Defaults to 'STANDARD'

required
object (Address)

Information about the address

required
Array of objects (Item)

Array of items in the order

object (OrderRetailCosts)

Retail costs that are to be displayed on the packing slip for international shipments. Retail costs are used only if every item in order contains the retail_price attribute.

object (OrderGift)

Optional gift message for the packing slip

OrderPackingSlip (object) or OrderPackingSlip (object) or OrderPackingSlip (object) or OrderPackingSlip (object) (OrderPackingSlip)

Custom packing slip for this order. Example of a packing slip with explained fields can be found here.

Responses

Response Schema: application/json
code
integer

Response status code 200

object (Order)

Information about the Order

Request samples

Content type
application/json
{
  • "external_id": "4235234213",
  • "shipping": "STANDARD",
  • "recipient": {
    },
  • "items": [
    ],
  • "retail_costs": {
    },
  • "gift": {
    },
  • "packing_slip": {
    }
}

Response samples

Content type
application/json
{
  • "code": 200,
  • "result": {
    }
}

Confirm draft for fulfillment

Approves for fulfillment an order that was saved as a draft. Store owner's credit card is charged when the order is submitted for fulfillment.

Authorizations:
OAuth
path Parameters
required
string or integer

Order ID (integer) or External ID (if prefixed with @)

header Parameters
X-PF-Store-Id
string

Use this to specify which store you want to use (required only for account level token).

The store IDs can be retrieved with the Get basic information about stores endpoint.

Responses

Response Schema: application/json
code
integer

Response status code 200

object (Order)

Information about the Order

Request samples

curl --location --request POST 'https://api.printful.com/orders/{order_id}/confirm' \
--header 'Authorization: Bearer {oauth_token}'

Response samples

Content type
application/json
{
  • "code": 200,
  • "result": {
    }
}

Estimate order costs

Calculates the estimated order costs including item costs, print costs (back prints, inside labels etc.), shipping and taxes

Authorizations:
OAuth
header Parameters
X-PF-Store-Id
string

Use this to specify which store you want to use (required only for account level token).

The store IDs can be retrieved with the Get basic information about stores endpoint.

Request Body schema: application/json
required

POST request body

external_id
string or null

Order ID from the external system

shipping
string

Shipping method. Defaults to 'STANDARD'

required
object (Address)

Information about the address

required
Array of objects (Item)

Array of items in the order

object (OrderRetailCosts)

Retail costs that are to be displayed on the packing slip for international shipments. Retail costs are used only if every item in order contains the retail_price attribute.

object (OrderGift)

Optional gift message for the packing slip

OrderPackingSlip (object) or OrderPackingSlip (object) or OrderPackingSlip (object) or OrderPackingSlip (object) (OrderPackingSlip)

Custom packing slip for this order. Example of a packing slip with explained fields can be found here.

Responses

Response Schema: application/json
code
integer

Response status code 200

object

Request samples

Content type
application/json
{
  • "external_id": "4235234213",
  • "shipping": "STANDARD",
  • "recipient": {