NAV Navbar
cURL Node.JS Python PHP

Overview

This documentation describes various ways to access Printify services by using the Printify API. Each section has a detailed description as well as code examples to help you easily start creating products and fulfilling orders.

API Usage Guidelines

All integrations must comply with the Printify Terms and Printify API Terms. Please see these pages for more details:

The Printify public endpoints are powered by the same underlying technology that powers the core Printify Platform. As a result, Printify engineering closely monitors usage of the public APIs to ensure a quality experience for users of the Printify platform.

Below, you'll find the limits by which a single integration (as identified by an access token) can consume the Printify APIs. If you have any questions, please email apiteam@printify.com.

Printify has the following limits in place for API requests:

This daily limit resets at midnight based on the time zone setting of the Printify account. Customers exceeding either of those limits will receive error responses with a 429 response code.

Integrations that use Printify's API to create products and generate mockups have additional daily limits. Product creation as a result of Order creation is not limited. If your application will require heavy usage of the Product or Mockup generation functions, please contact apiteam@printify.com with more information and we will contact you shortly.

Requests resulting in an error response may not exceed 5% of your total requests.

We reserve the right to change or deprecate the APIs over time - we will provide developers ample notification in those cases. These notifications will be sent to the email provided in your API settings.

API features

REST API

Printify's REST API allows your application to manage a Printify shop on behalf of a Printify Merchant. Create products, submit orders, and more...

Check out all available methods: API Reference

Webhooks and Events

Webhooks allow you to get an instant notification after an event occurrs in a Printify shop.

Send information to accounting right after an order was placed, send tracking to end customers as soon as it's available, sync product descriptions, etc... - it's totally up to you.

More information: Webhooks

Access the Printify API

You can access the Printify API as an individual merchant or as a platform. Both of them require different types of authentication. Learn about each of them below.

Individual Accounts

Connect to a single Printify Merchant account and the shops that are a part of that account. Create products, submit artwork, create and receive orders and more. Authentication is achieved through a Personal Access Token.

See more details in Authentication.

Platforms

Connect applications that offer services to multiple merchants each with different Printify merchant accounts. Manage orders for multiple Printify Merchants, offer merchants the option to sell on your platform, and more. Authentication is achieved through OAuth 2.0

See more details in Authentication

Use cases

Create orders with user-generated content

Regardless of whether you use your own mockup generator, or you capture user generated content. Through the Printify API you can easily place those images on any products in our catalog, offer them for purchase, and fulfill.

Connect your own E-commerce channel

Don't use Etsy, Shopify, Woocommerce, or any of our other available E-commerce solutions? Connect your own with the Printify API. Enjoy the same benefits of automation that merchants using our existing integrations do.

Support existing integrations with more functionality

Already using one of our integrations such as Shopify or Woocommerce? Build any additional functionality you need and connect via Printify API to continue to get all of your sales and order data in your existing shop.

Start offering merchandise sales to your community

Do you have an application or platform with an engaged community. Connect to the Printify API and easily start monetizing your community by allowing them to sell Print on Demand merchandise through your platform.

Authentication

The Printify platform provides two ways of integrating. You can integrate with a Personal Access Token that you can use to manage a single Printify account, or you can integrate through OAuth 2.0 as a platform that will be managing multiple Printify Merchant accounts.

Unless otherwise mentioned in the documentation for a specific endpoint, all endpoints support both OAuth 2.0 and Personal Access Token.

Create a personal access token

A personal access token allows your application to connect to a single Printify Merchant account and the shops created within that account.

Step 1

Before creating your personal access token, you will first need a Printify account. If you haven't created an account yet, please do so here and complete the onboarding procedure.

Step 2

Now that you have your Printify account, navigate to My Profile, then Connections. In the Connections section you will be able to generate your Personal Access Tokens and set your Token Access Scopes.

Step 3

You will be able to generate multiple tokens. Tokens can be set to have different Access Scopes.

Please note that for security purposes, this token will only be visible immediately after generating only. Please make sure you store it in a secure location.

If you lose your access token, you will need to generate a new one.

Generate token

Step 4

Once generated, you can use that token as credentials for API requests in place of a user name and password.

All requests must also specify a User-Agent header. The value of this header should either be the type of client, such as "NodeJS" or "PHP," or the name of your application.

After you have authenticated to the API, you can send requests to the API using any programming language or program that can send HTTP requests. The base URL for all endpoints is https://api.printify.com/.

Here is an example:

curl -X GET https://api.printify.com/v1/shops.json --header "Authorization: Bearer $PRINTIFY_API_TOKEN"

Step 5

Once you’ve set the API up, go to your store by clicking on My Stores, then Add new store. You should see Shopify, Etsy, WooCommerce, and the new option, API.

Click connect to connect your store to Printify via the API.

OAuth 2.0

Using OAuth 2.0 you will be able to offer your application to the growing community of Printify Merchants.

Prerequisites

  1. Authentication for your integration starts with registering your app. This link takes you to an application form where you will answer some questions about your business, expected integration timeline and your applications functionality. If your application is approved, you will receive instructions via email for how to receive your Client ID and Client Secret, and how to set the required access scopes your application will need.
  2. You'll use the Client ID and Client Secret to initiate the OAuth handshake between Printify and your integration.

Note: Reviewing applications can take up to 1 week.

Register your app

Connecting your app to Printify

There are 4 main steps to connecting your integration to a Merchant's Printify account using OAuth:

  1. Requesting Authorization Codes The Printify merchant will be presented with a screen that allows them to grant access to your integration.
  2. After the Merchant grants access, they'll be returned to your app, with a code appended to the URL. Use that code and your Client Secret to get an access_token and refresh_token.
  3. Use that access_token to authenticate any API calls that you make for that Printify account.
  4. Once that access_token expires, use the refresh_token from Step 2 to generate a new access_token.

Requesting authorization codes

Initiating OAuth access is the first step for having merchants grant you access to their Printify account. In order to initiate OAuth access for your App, you'll first need to send a Printify Merchant to an authorization page, where that Merchant will need to grant access to your app. When your app sends a Merchant to that authorization page, you'll use the query parameters detailed below to identify your app, and to also specify the scopes that your apps requires.

Merchants must be signed into Printify to grant access, so any user that is not logged into Printify will be directed to a login screen before being directed back to the authorization page. The authorization screen will show the details for your app, and the permissions being requested (based on the scopes you include in the URL).

After the Merchant grants access, they will be redirected to the redirect_uri that you specified, with a code query parameter appended to the URL. You'll use that code to get an access token from Printify.

URL parameters

Response type REQUIRED response_type=code Defines that you should receive an OAuth code in the response.
Client ID REQUIRED client_id=x The Client ID provided to you after registering your app.
Redirect URI REQUIRED redirect_uri=x The URI that you want the visitor redirected to after granting access to your app. Please Note: For security reasons, this URI must use https in production. When testing using localhost, http can be used. Also, you must use a domain, as IP addresses are not supported.
Scope REQUIRED scope=x%20x A space separated set of scopes that your app will need access to. Scopes listed in this parameter will be treated as required for your app, and the user will see an error if they select an account that does not have access to the scope you've included. Any scopes that you have checked in your app settings will be treated as required scopes, and you'll need to include any selected scopes in this parameter or the authorization page will display an error.
State RECOMMENDED OPTIONAL state=123 The state parameter serves two functions. When the user is redirected back to your app, whatever value you include as the state will also be included in the redirect. This gives your app a chance to persist data between the user being directed to the authorization server and back again, such as using the state parameter as a session key. This may be used to indicate what action in the app to perform after authorization is complete, for example, indicating which of your app’s pages to redirect to after authorization. This also serves as a CSRF protection mechanism. When the user is redirected back to your app, double check that the state value matches what you set it to originally. This will ensure an attacker can’t intercept the authorization flow.

Authorization request

This request is made to the base URL https://printify.com/.

GET /app/oauth/authorize?{URL_parameters}
Authorization request
URL_parameters client_id=xxaabbzzxxxaabbzzxaabbzzxxaabbzz &response_type=code &scope=shops.read &state=123 &redirect_uri=https://www.example.com
Possible outcomes
If access is granted, a URL redirect will follow https://www.example.com/?code=aabbccxxeeaabbccxxeeaabbccxxee If there are any problems with the authorization, error parameters will be received instead of the code https://www.example.com/?error=error_code&error_description=Human%20readable%20description%20of%20the%20error

Converting authorization codes to access tokens

Use the code you get after a user authorizes your app to get an access token and refresh token. The access token will be used to authenticate requests that your app makes. When you will get the Access tokens you will also get expiration time for the token. When token expires you have to use Refresh token to get a new Access token.

Body parameters

Grant Type REQUIRED grant_type=authorization_code The grant type of the request, must be authorization_code for the initial request to get the access and refresh tokens.
Client Id REQUIRED client_id=x The Client ID of your app.
Client Secret REQUIRED client_secret=x The Client Secret of your app.
Redirect URI REQUIRED redirect_uri=x The redirect URI that was used when the user authorized your app. This must exactly match the redirect_uri used when initiating the OAuth 2.0 connection.
Code REQUIRED code=x The code parameter returned to your redirect URI when the user authorized your app.

Note: Printify access tokens will fluctuate in size as we change the information that is encoded in the tokens. We recommend allowing for tokens to be up to 3,000 characters to account for any changes we may make.

Conversion request

As was mentioned earlier, all requests after authentication are made to the base URL https://api.printify.com/.

POST /oauth/token
Convert authorization code to access token
Post request body grant_type=authorization_code &client_id=xxaabbzzxxxaabbzzxaabbzzxxaabbzz &client_secret=xxAabBZzEeeeDdDEEaaazzzAAAA &redirect_uri=https://www.example.com/ &code=AAAAzzzaaaEEDdDeeeEzZBbaAxx
Possible responses
If successful, a JSON response with the tokens will be received View Response

If there are any problems with the request, a 400 response will be received with an error message View Response

Refresh access token

Use a previously obtained refresh token to generate a new access token. Access tokens expire after 6 hours, so if you need offline access to data in Printify, you'll need to store the refresh token you get when initiating your OAuth integration, and use that to generate a new access token once the initial access token expires.

Body parameters

Grant Type REQUIRED grant_type=refresh_token The grant type of the request, must be refresh_token when refreshing an access token.
Client Id REQUIRED client_id=x The Client ID of your app.
Client Secret REQUIRED client_secret=x The Client Secret of your app.
Redirect URI REQUIRED redirect_uri=x The redirect URI that was used when the user authorized your app. This must exactly match the redirect_uri used when initiating the OAuth 2.0 connection.
Code REQUIRED code=x The code parameter returned to your redirect URI when the user authorized your app.

Refresh request

POST /oauth/token
Refresh access token
Post request body grant_type=refresh_token &client_id=xxaabbzzxxxaabbzzxaabbzzxxaabbzz &client_secret=xxAabBZzEeeeDdDEEaaazzzAAAA &redirect_uri=https://www.example.com/ &refresh_token={refresh-token-provided-from-above}
Possible responses
If successful, a JSON response with the tokens will be received View Response

If there are any problems with the request, a 400 response will be received with an error message View Response

Using access tokens

OAuth 2.0 access tokens are provided as a bearer token, in the Authorization http header.

The header format is: Authorization: Bearer {token}

Access scopes

Scopes are permissions that identify the scope of access your application requests from the Printify Merchant Account. Below you can see the names of access scopes that exist in Printify and their description.

Access Scope Notes
shops.read Access shops in a Merchant account
catalog.read See Products and Print Providers from the Printify Product Catalog
products.read See products created in a Merchant shop
products.write Create products in a Merchant shop
orders.read See orders created in a Merchant shop
orders.write Create orders in a Merchant shop
webhooks.read Read installed webhooks
webhooks.write Install, update and delete Webhooks
uploads.write Upload, update and delete files from Media Library

API Reference

The Printify API is organized around REST.

Our API has predictable resource-oriented URLs, accepts form-encoded request bodies, returns JSON-encoded responses, and uses standard HTTP response codes, authentication, and verbs.

API basics

Shops

All product creation and order submission in a Printify Merchant's account happens through a shop. Merchant's can have multiple shops in one Printify account. Each of these shops can be connected to different sales channels and each has independent products, orders, and analytics.

On this page:

What you can do with the shops resource

The shops resource serves one purpose, it allows you to view the list of existing shops in a Printify account.

Shop properties

id READ-ONLY "id": 12345 A unique int identifier for the shop. Each id is unique across the Printify system.
title READ-ONLY "title": "Shop's title" The name of the shop.
sales_channel READ-ONLY "sales_channel": "Sales channel name" The name of the associated sales channel. If none are connected it defaults to "disconnected".

Endpoints

Retrieve list of shops in a Printify account

GET /v1/shops.json
Retrieve a list of shops in a Printify account
GET /v1/shops.json
View Response

Catalog

Through the Catalog resource you can see all of the products, product variants, variant options and print providers available in the Printify catalog.

Products in the Printify catalog are referred to as blueprints (only after user artwork has been added, are they referred to as products).

Every blueprint in the printify catalog has multiple Print Providers that offer that blueprint. In addition to general differences between Print Providers including location and print technology employed, each Print Provider also offers different colors, sizes, print areas and prices.

Each Print Provider's blueprint has specific size and color combinations known as variants. Variants also contain information on a products available print areas and sizes.

On this page:

What you can do with the catalog resource

The Printify Public API lets you do the following with the Catalog resource:

Blueprint properties

id READ-ONLY "id": 5 A unique int identifier for the blueprint. Each id is unique across the Printify system.
title READ-ONLY "title": "Blueprint's title" The name of the blueprint.
brand READ-ONLY "brand": "Blueprint's brand" The brand of the blueprint (i.e. the name of the blank product's manufacturer).
model READ-ONLY "model": "Blueprint's brand model" The specific model of the blueprint's brand (i.e. the unique identifier of the blank product's model or style).
images READ-ONLY "images": [ "https://images.example.com/869549a1a0894a4692371b1f9928e14a.png", "https://images.example.com/878331a2b0876c9801746d2e2454f14a.png" ] Links to the title image wrappers displayed on the catalog.
id READ-ONLY "id": 3 A unique int identifier for the print provider. Each id is unique across the Printify system.
title READ-ONLY "title": "Print provider's title" The name of the print provider.
location READ-ONLY "location": { "address1": "89 Weirfield St", "address2": "", "city": "Brooklyn", "country": "US", "region": "NY", "zip": "11221-5120" } The return address of the print provider.

Variant properties

id READ-ONLY "id": 17390 A unique int identifier for the blueprint variant. Each id is unique across the Printify system.
title READ-ONLY "title": "Variant's title" The name of the variant.
options READ-ONLY "options": { "color": "Heather Grey", "size": "XS" } Options are read only values and describes blueprint variant options. There can be up to 3 options for a blueprint.
placeholders READ-ONLY "placeholders": [{ "position": "back", "height": 3995, "width": 3153 }, { "position": "front", "height": 3995, "width": 3153 }] Placeholders describe the available printable areas for a blueprint. See placeholder properties for reference.

Placeholder properties

position READ-ONLY "position": "front" Position states the available printable areas for a blueprint fulfilled by a specific print provider.
height READ-ONLY "height": 3995 Integer value for printable area height in pixels.
width READ-ONLY "width": 3153 Integer value for printable area width in pixels.

Shipping properties

handling_time READ-ONLY "handling_time": { "value":10, "unit": "day" } The standard shipping timeframe for a blueprint from a specific print provider.
profiles READ-ONLY "profiles": [ { "variant_ids": [1,2], "first_item": { "currency": "USD", "cost": 1000 }, "additional_items": { "currency": "USD", "cost": 1000 }, "countries":["US"] }, { "variant_ids": [1,2], "first_item": { "currency": "USD", "cost": 1000 }, "additional_items": { "currency": "USD", "cost": 1000 }, "countries":["REST_OF_THE_WORLD"] } ] The list of shipping locations and flat shipping costs for all variants of a blueprint from a specific print provider. See profile properties for reference.

Profile properties

variant_ids READ-ONLY "variant_ids": [ 1,2,3,4,5,6,7 ] Lists the ids of all blueprint variants the specific profile is associated to in an array.
first_item READ-ONLY "first_item": { "currency": "USD", "cost": 1000 } The currency and flat cost of shipping for a line item if identified as the first item in an order.
additional_items READ-ONLY "additional_items": { "currency": "USD", "cost": 1000 } The currency and flat cost of shipping for all other line items of the specific blueprint and print provider in the same order.
countries READ-ONLY "countries": [ US ] Lists the countries or delivery locations the shipping profile applies to.

Endpoints

Retrieve a list of available blueprints

GET /v1/catalog/blueprints.json
Retrieve a list of available blueprints
GET /v1/catalog/blueprints.json
View Response

Retrieve a specific blueprint

GET /v1/catalog/blueprints/{blueprint_id}.json
Retrieve a specific blueprint
GET /v1/catalog/blueprints/{blueprint_id}.json
View Response

Retrieve a list of all print providers that fulfill orders for a specific blueprint

GET /v1/catalog/blueprints/{blueprint_id}/print_providers.json
Retrieve a list of all print providers that fulfill orders for a specific blueprint
GET /v1/catalog/blueprints/{blueprint_id}/print_providers.json
View Response

Retrieve a list of variants of a blueprint from a specific print provider

GET /v1/catalog/blueprints/{blueprint_id}/print_providers/{print_provider_id}/variants.json
Retrieve a list of variants of a blueprint from a specific print provider
GET /v1/catalog/blueprints/{blueprint_id}/print_providers/{print_provider_id}/variants.json
View Response

Retrieve shipping information

GET /v1/catalog/blueprints/{blueprint_id}/print_providers/{print_provider_id}/shipping.json
Retrieve shipping information
GET /v1/catalog/blueprints/{blueprint_id}/print_providers/{print_provider_id}/shipping.json
View Response

Retrieve a list of available print providers

GET /v1/catalog/print_providers.json
Retrieve a list of available print providers
GET /v1/catalog/print_providers.json
View Response

Retrieve a specific print provider

GET /v1/catalog/print_providers/{print_provider_id}.json
Retrieve a specific print provider and a list of associated blueprint offerings
GET /v1/catalog/print_providers/{print_provider_id}.json
View Response

Products

The Product resource lets you list, create, update, delete and publish products to a store.

On this page:

What you can do with the product resource

The Printify Public API lets you do the following with the Product resource:

Product properties

id READ-ONLY "id": "5cb87a8cd490a2ccb256cec4" A unique string identifier for the product. Each id is unique across the Printify system.
title REQUIRED "title": "Product's title" The name of the product.
description REQUIRED "description": "Product's description" A description of the product. Supports HTML formatting.
tags OPTIONAL "tags": ["T-shirt", "Men's"] Tags are also published to sales channel.
options READ-ONLY "options": [{ "name": "Colors", "type": "color", "values": [{ "id": 751, "title": "Solid White", "colors": [ "#F9F9F9" ] }] }] Options are read only values and describes product options. There can be up to 3 options for a product.
variants REQUIRED "variants": [{ "id": 123, "price": 1000, "title": "Solid Dark Gray / S", "sku": "PRY-123", "grams": 120, "is_enabled": true, "is_default": false, "options": [751, 2] }] A list of all product variants, each representing a different version of the product. But during product creation, only the variant id and price are necessary. See variant properties for reference.
images READ-ONLY "images": [{ "src": "http://example.com/tee.jpg", "variant_ids": [123, 124], "position": "front", "is_default" : false, }] Mock-up images are read only values. The mock-up images are grouped by variants and position. See mock-up image properties for reference.
created_at READ-ONLY "created_at": "2017-04-18 13:24:28+00:00" The date and time when a product was created.
update_at READ-ONLY "update_at": "2017-04-18 13:24:28+00:00" The date and time when a product was last updated.
visible READ-ONLY "visible": true Used for publishing. Visibility in sales channel. Can be true or false, defaults to true.
blueprint_id REQUIRED READ-ONLY "blueprint_id": 5 Required when creating a product, but is read only after. See catalog for how to get blueprint_id.
print_provider_id REQUIRED READ-ONLY "print_provider_id": 5 Required when creating a product, but is read only after. See catalog for how to get print_provider_id.
user_id READ-ONLY "user_id": 5 User id that a product belongs to.
shop_id READ-ONLY "shop_id": 1 Shop id that a product belongs to.
print_areas REQUIRED "print_areas": [{ "variant_ids": [123, 124], "placeholders": [{ "position": "front", "images": [] }], }] All print area values are required. Each variant has a print area attached to it. Each print area has placeholders which represent printable areas on a product. For example the front of the t-shirt, back of the t-shirt etc. Each placeholder has images and their positions, where they need to be printed in the printable area. See placeholder properties for reference.
external CONDITIONAL "external": [{ "id": "A123abceASd", "handle": "/path/to/product" }] Updated by sales channel with publishing succeeded endpoint. Id and handle are external references in the sales channel. See publishing succeeded endpoint for more reference.
is_locked READ-ONLY "is_locked": true A product is locked during publishing. Locked products can't be updated until unlocked.
sales_channel_properties READ-ONLY "sales_channel_properties": [] Lists product properties specific to the sales channel associated with the product, if the sales channel has such custom properties, the attributes are listed in the array and may be actionable, but for all custom integrations, it will either be null or an empty array.

Variant properties

id REQUIRED READ-ONLY "id": 123 A unique int identifier for the product variant from the blueprint. Each id is unique across the Printify system. See catalog for instructions on how to get variant ids.
sku OPTIONAL "sku": "SKU-123" Optional unique string identifier for the product variant. If one is not provided, one will be generated by Printify.
price REQUIRED "price": 1000 Price in cents, integer value.
cost READ-ONLY "cost": 400 Product variant's fulfillment cost in cents, integer value.
title READ-ONLY "title": "Solid Dark Gray / S" Variant title.
grams READ-ONLY "grams": 120 Weight in grams for a product variant
is_enabled READ-ONLY "is_enabled": true Used for publishing, the value is true if one has the variant in question selected as an offering and wants it published.
in_stock READ-ONLY DEPRECATED "in_stock": true Used for publishing, out of stock items will be set to out of stock on a sales channel or skipped during publishing, depends on the particular sales channel integration. This property will be removed at a later date, use the "is_enabled" property instead.
is_default OPTIONAL "is_default": true Only one variant can be default. Used when publishing to sales channel. Default variant's image will be the title image of the product.
options READ-ONLY "options": [751, 2] Reference to options by id.

Placeholder properties

position REQUIRED "position": "front" See blueprint placeholder properties from the catalog endpoint for reference on how to get positions.
images REQUIRED "images": [] Array of images. See image properties for reference.

Image properties

id REQUIRED "id": 123 See upload images for reference on how to upload images and get all needed properties.
name READ-ONLY "name": "image.jpg" Name of an image file.
type READ-ONLY "type": "image/png" Type of an image. Valid image types are image/png, image/jpg, image/jpeg.
height READ-ONLY "height": 100 Integer value for image height in pixels. See upload images for reference on how to upload images and get all needed properties.
width READ-ONLY "width": 100 Integer value for image width in pixels. See upload images for reference on how to upload images and get all needed properties.
x REQUIRED "x": 100 Float value to position an image on the x axis. See image positioning for reference on how to position images.
y REQUIRED "y": 100 Float value to position an image on the y axis. See image positioning for reference on how to position images.
scale REQUIRED "scale": 1 Float value to scale image up or down. See image positioning for reference on how to position images.
angle REQUIRED "angle": 180 Integer value used to rotate image. See image positioning for reference on how to position images.

Mock-up image properties

src READ-ONLY "src": "https://images.printify.com/mockup/5d39b159e7c48c000728c89f/33719/145/mug-11oz.jpg" Url of a mock-up image.
variant_ids READ-ONLY "variant_ids": [ 61618, 61619, 61620, 61621, 61622 ] Array of integer ids for variants illustrated by the mock-up image.
position READ-ONLY "position": "front" Camera position of a mockup (i.e. what part of the product is being displayed).
is_default READ-ONLY "is_default": true Used by the sales channel. If set to true, The specific mockup is the title image. Can be used to decide the first image displayed when a product's page is accessed.

Publishing properties

images REQUIRED "images": true Used by the sales channel. If set to false, Images will not be published, and existing images will be used instead.
variants REQUIRED "variants": true Used by the sales channel. If set to false, product variations will not be published.
title REQUIRED "title": true Used by sales channel. If set to false, product title will not be updated.
description REQUIRED "description": true Used by sales channel. If set to false, product description will not be updated.
tags REQUIRED "tags": true Used by sales channel. If set to false, product tags will not be updated.

Endpoints

Retrieve a list of products

GET /v1/shops/{shop_id}/products.json
limit OPTIONAL
Results per page
(default: 10, maximum: 100)
page OPTIONAL Paginate through list of results
Retrieve all products
GET /v1/shops/{shop_id}/products.json
View Response
Retrieve specific page from results
GET /v1/shops/{shop_id}/products.json?page=2
View Response
Retrieve limited results
GET /v1/shops/{shop_id}/products.json?limit=1
View Response

Retrieve a product

GET /v1/shops/{shop_id}/products/{product_id}.json
Retrieve a product
GET /v1/shops/{shop_id}/products/{product_id}.json
View Response

Create a new product

POST /v1/shops/{shop_id}/products.json
Create a new product
POST /v1/shops/{shop_id}/products.json
{ "title": "Product", "description": "Good product", "blueprint_id": 384, "print_provider_id": 1, "variants": [ { "id": 45740, "price": 400 }, { "id": 45742, "price": 400 }, { "id": 45744, "price": 400 }, { "id": 45746 , "price": 400 } ], "print_areas": [ { "variant_ids": [45740,45742,45744,45746], "placeholders": [ { "position": "front", "images": [ { "id": "5d15ca551163cde90d7b2203", "x": 0.5, "y": 0.5, "scale": 1, "angle": 0 } ] } ] } ], } View Response

It is necessary to list all available variants for a blueprint in the variants array during the product creation request as failing to do so will result in an error, you can always specify which variants you don't want to offer by using the optional "is_enabled" boolean under variant properties.

Update a product

PUT /v1/shops/{shop_id}/products/{product_id}.json
Update a product
PUT /v1/shops/{shop_id}/products/{product_id}.json
{ "title": "Product" } View Response

A product can be updated partially or as a whole document. When updating variants, all variants must be present in the request.

Delete a product

DELETE /v1/shops/{shop_id}/products/{product_id}.json
Delete a product
DELETE /v1/shops/{shop_id}/products/{product_id}.json
View Response

Publish a product

POST /v1/shops/{shop_id}/products/{product_id}/publish.json
Publish a product
POST /v1/shops/{shop_id}/products/{product_id}/publish.json
{ "title": true, "description": true, "images": true, "variants": true, "tags": true } View Response

Notify that publishing has succeeded

POST /v1/shops/{shop_id}/products/{product_id}/publishing_succeeded.json
Notify that publishing has succeeded
POST /v1/shops/{shop_id}/products/{product_id}/publishing_succeeded.json
{ "external": { "id": "5941187eb8e7e37b3f0e62e5", "handle": "https://example.com/path/to/product" } } View Response

Notify that publishing has failed

POST /v1/shops/{shop_id}/products/{product_id}/publishing_failed.json
Notify that publishing has failed
POST /v1/shops/{shop_id}/products/{product_id}/publishing_failed.json
{ "reason": "Request timed out" } View Response

Image positioning

Rule of thumb: if you use artwork with width equal to print area placeholder width, set scale to 1,00 and position it at x=0,5 y=0,5 - your design will be horizontally and vertically aligned and fill all the print area fully.

Common error cases

You may receive errors when trying to create or update a product. A common error is due failing dpi validation because the image is low quality. If this happens, you will receive a detailed error message similar to the one shown here.

POST /v1/shops/{shop_id}/products.json
Common error cases
POST /v1/shops/{shop_id}/products.json
400 Image has low quality error example (See HTTP Status Codes below) View Response
PUT /v1/shops/{shop_id}/products/{product_id}.json
Common error cases
PUT /v1/shops/{shop_id}/products/{product_id}.json
400 Image has low quality error example (See HTTP Status Codes below) View Response

Orders

Printify API lets your application manage orders in a Merchants shop. You can submit orders for existing products in a merchant's shop or you can create new products with every order as in the case with merchandise created with customizable user-generated content.

Ordering existing products or creating products with orders will require different line item entries so that should be kept in mind.

On this page:

What you can do with the order resource

The Printify Public API lets you do the following with the Order resource:

Order properties

id READ-ONLY "id": "5a96f649b2439217d070f507" A unique string identifier for the order. Each id is unique across the Printify system.
address_to REQUIRED READ-ONLY "address_to": { "first_name": "John", "last_name": "Smith", "region": "", "address1": "ExampleBaan 121", "city": "Retie", "zip": "2470", "email": "example@msn.com", "phone": "0574 69 21 90", "country": "BE", "company": "MSN" } The delivery details of the order's recipient.
line_items REQUIRED READ-ONLY "line_items": [{ "product_id": "5b05842f3921c9547531758d", "quantity": 1, "variant_id": 17887, "print_provider_id": 5, "cost": 1050, "shipping_cost": 400, "status": "pending", "metadata": { "title": "18K gold plated Necklace", "price": 2200, "variant_label": "Golden indigocoin", "sku": "168699843", "country": "United States" }, "sent_to_production_at": "2017-04-18 13:24:28+00:00", "fulfilled_at": "2017-04-18 13:24:28+00:00" }] A list of all line items in the order. See line item properties for reference.
metadata READ-ONLY "metadata": { "order_type": "external", "shop_order_id": 1370762297, "shop_order_label": "1370762297", "shop_fulfilled_at": "2017-04-18 13:24:28+00:00" } Other data about the order. See metadata properties for reference.
total_price READ-ONLY "total_price": 2200 Retail price in cents, integer value.
total_shipping READ-ONLY "total_shipping": 400 Shipping price in cents, integer value.
total_tax READ-ONLY "total_tax": 0 Tax cost in cents, integer value.
status READ-ONLY "status": "pending" Production status of the entire order in string format, it can be any of the following: pending, on-hold, checking-quality, quality-declined, quality-approved, ready-for-production, sending-to-production, in-production, cancelled, fulfilled, partially-fulfilled, payment-not-received, callback-received, or has-issues.
shipping method REQUIRED READ-ONLY "shipping_method": 1 Method of shipping selected for the order, "1" is for standard shipping and "2" is for express shipping.
shipments READ-ONLY "shipments": [{ "carrier": "usps", "number": "94001116990045395649372", "url": "http://example.com/94001116990045395649372", "delivered_at": "2017-04-18 13:24:28+00:00" }] Tracking details of the order after fulfillment. See shipment properties for reference.
created_at READ-ONLY "created_at": "2017-04-18 13:24:28+00:00" The date and time the order was created in epoch seconds. It is stored as an integer.
sent_to_production_at READ-ONLY "sent_to_production_at": "2017-04-18 13:24:28+00:00" The date and time the order was sent to production in epoch seconds. It is stored as an integer.
fulfilled_at READ-ONLY "fulfilled_at": "2017-04-18 13:24:28+00:00" The date and time the order was fulfilled in epoch seconds. It is stored as an integer.

Line item properties

product_id READ-ONLY "product_id": "5b05842f3921c9547531758d" A unique string identifier for the product. Each id is unique across the Printify system.
variant_id REQUIRED READ-ONLY "variant_id": 17887 A unique int identifier for the product variant from the blueprint. Each id is unique across the Printify system.
quantity REQUIRED "quantity": 1 Describes the number of said product ordered as an integer.
print_provider_id REQUIRED READ-ONLY "print_provider_id": 5 A unique int identifier for the print provider. Each id is unique across the Printify system.
cost READ-ONLY "cost": 1050 Product variant's fulfillment cost in cents, integer value.
shipping_cost READ-ONLY "shipping_cost": 400 Product variant's shipment cost in cents, integer value.
status READ-ONLY "status": "pending" Specific line item fulfillment status, can be pending, cancelled, or fulfilled.
metadata READ-ONLY "metadata": { "title": "18K gold plated Necklace", "price": 2200, "variant_label": "Golden indigocoin", "sku": "168699843", "country": "United States" } Other details about the specific product variant. See line item metadata properties for reference.
sent_to_production_at READ-ONLY "sent_to_production_at": "2017-04-18 13:24:28+00:00" The date and time the product variant was sent to production in epoch seconds. It is stored as an integer.
fulfilled_at READ-ONLY "fulfilled_at": "2017-04-18 13:24:28+00:00" The date and time the product variant was fulfilled in epoch seconds. It is stored as an integer.

Line item metadata properties

title READ-ONLY "title": "Product's title" The name of the product.
price READ-ONLY "price": 1000 Retail price in cents, integer value.
variant_label READ-ONLY "variant_label": "Golden indigocoin" Name of the product variant.
sku READ-ONLY "sku": "168699843" A unique string identifier for the product variant.
country READ-ONLY "country": "United States" Location of print provider handling fulfillment.

Metadata properties

order_type READ-ONLY "order_type": "external" Describes the order type, can be external, manual, or sample.
shop_order_id READ-ONLY "shop_order_id": 1370762297 A unique integer identifier for the order in the external sales channel.
shop_order_label READ-ONLY "shop_order_id": "1370762297" A unique string identifier for the order in the external sales channel.
shop_fulfilled_at READ-ONLY "shop_fulfilled_at": "2017-04-18 13:24:28+00:00" The date and time the order was fulfilled in epoch seconds. It is stored as an integer.

Shipment properties

carrier READ-ONLY "carrier": "usps" Name of the shipping courier used to deliver the order to its recipient.
number READ-ONLY "number": "123" A unique string tracking number from the shipping courier used to track the status of the shipment.
url READ-ONLY "url": "http://example.com/94001116990045395649372" A unique string tracking link from the shipping courier used to track the status of the shipment.
delivered_at READ-ONLY "delivered_at": "2017-04-18 13:24:28+00:00" The date and time the order was delivered in epoch seconds. It is stored as an integer.

Order submission properties

external_id REQUIRED "external_id": "2750e210-39bb-11e9-a503-452618153e4a" A unique string identifier from the sales channel specifying the order name or id.
line_items REQUIRED "line_items": [{ "product_id": "5bfd0b66a342bcc9b5563216", "variant_id": 17887, "quantity": 1 }] Required for ordering existing products. Provide the product_id (Printify Product ID), variant_id (selected variant, e.g. 'White / XXL') and desired item quantity. If creating a product from the order is required, then additional attributes will need to be provided, specifically the blueprint_id and print_areas. "line_items": [{ "print_provider_id": 5, "blueprint_id": 9, "variant_id": 17887, "print_areas": { "front": "https://images.example.com/image.png" }, "quantity": 1 }] See product properties and variant properties for reference. Also, see print area properties for reference on print_areas for product creation during order submission. It is also possible to order existing products by providing the product variant's SKU alone. "line_items": [{ "sku": "MY-SKU", "quantity": 1 }] See variant properties for reference.
shipping_method REQUIRED "shipping_method": 1 Required to specify what method of shipping is desired, "1" means standard shipping, "2" means express shipping. It is stored as an integer.
send_shipping_notification BOOLEAN "send_shipping_notification": false A boolean for choosing whether or not to receive email notifications after an order is shipped.
address_to REQUIRED "address_to": { "first_name": "John", "last_name": "Smith", "email": "example@msn.com", "phone": "0574 69 21 90", "country": "BE", "region": "", "address1": "ExampleBaan 121", "address2": "45", "city": "Retie", "zip": "2470" } The delivery details of the order's recipient.
placeholder position and image url REQUIRED "print_areas": { "front": "https://images.example.com/image.png", "back": "https://images.example.com/image.png" } Required for creating products during order submission, See placeholder properties for reference.

Endpoints

Retrieve a list of orders

GET /v1/shops/{shop_id}/orders.json
limit OPTIONAL
Results per page
(default: 10, maximum: 10)
page OPTIONAL Paginate through list of results
status OPTIONAL Filter results by order status
Retrieve all orders
GET /v1/shops/{shop_id}/orders.json
View Response
Retrieve limited results
GET /v1/shops/{shop_id}/orders.json?limit=1
View Response
Retrieve specific page from results.
GET /v1/shops/{shop_id}/orders.json?page=2
View Response
Filter results by order status.
GET /v1/shops/{shop_id}/orders.json?status=fulfilled
View Response

Get order details by ID

GET /v1/shops/{shop_id}/orders/{order_id}.json
Get order details by ID
GET /v1/shops/{shop_id}/orders/{order_id}.json
View Response

Submit an order

POST /v1/shops/{shop_id}/orders.json
Order an existing product
POST /v1/shops/{shop_id}/orders.json
{ "external_id": "2750e210-39bb-11e9-a503-452618153e4a", "line_items": [ { "product_id": "5bfd0b66a342bcc9b5563216", "variant_id": 17887, "quantity": 1 } ], "shipping_method": 1, "send_shipping_notification": false, "address_to": { "first_name": "John", "last_name": "Smith", "email": "example@msn.com", "phone": "0574 69 21 90", "country": "BE", "region": "", "address1": "ExampleBaan 121", "address2": "45", "city": "Retie", "zip": "2470" } } View Response
Create a product with an order
POST /v1/shops/{shop_id}/orders.json
{ "external_id": "2750e210-39bb-11e9-a503-452618153e5a", "line_items": [ { "print_provider_id": 5, "blueprint_id": 9, "variant_id": 17887, "print_areas": { "front": "https://images.example.com/image.png" }, "quantity": 1 } ], "shipping_method": 1, "send_shipping_notification": false, "address_to": { "first_name": "John", "last_name": "Smith", "email": "example@msn.com", "phone": "0574 69 21 90", "country": "BE", "region": "", "address1": "ExampleBaan 121", "address2": "45", "city": "Retie", "zip": "2470" } } View Response
Order an existing product using only an SKU
POST /v1/shops/{shop_id}/orders.json
"external_id": "2750e210-39bb-11e9-a503-452618153e6a", "line_items": [ { "sku": "MY-SKU", "quantity": 1 } ], "shipping_method": 1, "send_shipping_notification": false, "address_to": { "first_name": "John", "last_name": "Smith", "email": "example@msn.com", "phone": "0574 69 21 90", "country": "BE", "region": "", "address1": "ExampleBaan 121", "address2": "45", "city": "Retie", "zip": "2470" } } View Response

Send an existing order to production

POST /v1/shops/{shop_id}/orders/{order_id}/send_to_production.json
Send an existing order to production
POST /v1/shops/{shop_id}/orders/{order_id}/send_to_production.json
View Response

Calculate the shipping cost of an order

POST /v1/shops/{shop_id}/orders/shipping.json
Calculate the shipping cost of an order
POST /v1/shops/{shop_id}/orders/shipping.json
{ "line_items": [{ "product_id": "5bfd0b66a342bcc9b5563216", "variant_id": 17887, "quantity": 1 },{ "print_provider_id": 5, "blueprint_id": 9, "variant_id": 17887, "quantity": 1 },{ "sku": "MY-SKU", "quantity": 1 }], "address_to": { "first_name": "John", // not required "last_name": "Smith", // not required "email": "example@msn.com", // not required "phone": "0574 69 21 90", // not required "country": "BE", "region": "", "address1": "ExampleBaan 121", "address2": "45", "city": "Retie", "zip": "2470" } } View Response

Common error cases

POST /v1/shops/{shop_id}/orders.json
Common error cases
POST /v1/shops/{shop_id}/orders.json
400 Invalid address validation error example (See HTTP Status Codes below) View Response

Uploads

Artwork added to a Printify Product can be saved in the Media library to be reused on additional products.

You can use this API to directly add files to the media library, and later use image IDs when creating or modifying products.

Summary:

Upload artwork to a Printify account's media library

Upload files either via image URL or image file base64-encoded contents. The file will be stored in the Merchant account Media Library.

POST /v1/uploads/images.json
Upload artwork to a Printify account's media library
POST /v1/uploads/images.json Body parameter (upload image by URL) { "file_name": "1x1-ff00007f.png", "url": "http://png-pixel.com/1x1-ff00007f.png" } Body parameter (upload image by base64-encoded contents) { "file_name": "image.png", "contents": "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8z8BQDwAEhQGAhKmMIQAAAABJRU5ErkJggg==" } View Response

Common Error cases

When uploading images to the library, you may encounter errors. These are commonly due to download errors, incorrect file formats, or your image being too large. If these are the case, you will receive messages similar to these outlined here.

POST /v1/uploads/images.json
Common error cases
POST /v1/uploads/images.json 400 Image download error example (See HTTP Status Codes below) View Response

400 Image too large error example (See HTTP Status Codes below) View Response

400 Unsupported file format error example (See HTTP Status Codes below) View Response

Events

Events are generated by some resources when certain actions are completed, such as the creation of a product, the fulfillment of an order. By requesting events, your app can know when certain actions have occurred in the shop.

On this page:

Product events

Event Description
product:deleted The product was deleted.
product:publish:started The product publishing was started.
product:publish:succeeded The product published successfully.
product:publish:failed The product publishing has failed.

Order events

Event Description
order:created The order was created.
order:updated The order was updated.
order:sent-to-production The order was sent to production.
order:shipment:created Some/all items have been fulfilled.
order:shipment:delivered Some/all items have been delivered.

Event properties

id "id": "653b6be8-2ff7-4ab5-a7a6-6889a8b3bbf5" A unique string identifier for the event. Each id is unique across the Printify system.
type "type": "order:created" The type of event that occurred. Different resources generate different types of event.
created_at "created_at": "2017-04-18 13:24:28+00:00" The date and time when the event was triggered.
resource "resource": { "id": "653b6be8-2ff7-4ab5-a7a6-6889a8b3bbf5", "type": "product", "data": { "shop_id": 1234567, "reason": "Request timed out" } } Information about the resource that triggered the event. Check Resource properties for reference.

Resource properties

id "id": "5cb87a8cd490a2ccb256cec4" A unique string identifier for the resource. Each id is unique across the Printify system.
type "type": "product" Resource type, currently valid types are product and order.
data "data": { "shop_id": 1234567, "reason": "Request timed out" } For more information see Resource data examples.

Resource data examples

Product events

product:deleted No resource data is sent.
product:publish:started The values for the action property determine the resource data payload, the values can be "create", "update", or "delete". For "create" and "update" actions, the payload is as follows: "data": { "shop_id": 1234567, "publish_details": { "title": true, "description": true, "images": true, "variants": true, "tags": true, }, "action": "create", } For the "delete" action, the payload is as follows: "data": { "action": "delete" } For reference on what other properties mean, check Publishing properties.
product:publish:succeeded "data": { "external": { "id": "123abceASd", "handle": "/path/to/product" } } For reference on what each property means, check Product properties external property.
product:publish:failed "data": { "shop_id": 1234567, "reason": "Request timed out" } Contains the reason why publishing failed.

Order events

order:created No resource data is sent with this event.
order:updated No resource data is sent with this event.
order:shipment:created "data": { "shop_id": 815256, "shipped_at": "2017-04-18 13:24:28+00:00", "carrier": { "code": "USPS", "tracking_number": "9400110200828911663274" }, "skus": [ "6220" ] }
order:shipment:delivered "data": { "shop_id": 815256, "delivered_at": "2017-04-18 13:24:28+00:00", "carrier": { "code": "USPS", "tracking_number": "9400110200828911663274" }, "skus": [ "6220" ] }
order:sent-to-production No resource data is sent with this event.

Webhooks

You can use webhook subscriptions to receive notifications about particular events in a shop. After you've subscribed to a webhook, you can let your app execute code immediately after specific events occur in shops that have your app connected, instead of having to make API calls periodically to check their status. For example, you can rely on webhooks to trigger an action in your app when a merchant creates a new product in a store. By using webhooks subscriptions you can make fewer API calls overall, which makes sure that your apps are more efficient and update quickly. For more information what actually gets sent by a webhook check Event properties and Resource data examples.

On this page:

What can you do with Webhooks

The Printify Public API lets you do the following with the Webhook resource:

Webhook properties

id READ-ONLY "id": "5cb87a8cd490a2ccb256cec4" A unique string identifier for the webhook. Each id is unique across the Printify system.
topic REQUIRED READ-ONLY "topic": "product:publish:started" Event that triggers the webhook. See Events for reference. Can't be changed.
url REQUIRED "url": "https://example.com/webhook" URI where the webhook subscription should send the POST request when the event occurs.
shop_id READ-ONLY "shop_id": 1 Id of merchant's store.
secret OPTIONAL "secret": "optional-secret-value" Secret that will be used to sign requests for webhook. See Securing your webhooks for more information.

Webhook endpoints

Retrieve a list of webhooks

GET /v1/shops/{shop_id}/webhooks.json
Retrieve a list of webhooks
GET /v1/shops/{shop_id}/webhooks.json
View Response

Retrieve a single webhook

GET /v1/shops/{shop_id}/webhooks/{webhook_id}.json
Retrieve a single webhook
GET /v1/shops/{shop_id}/webhooks/{webhook_id}.json
View Response

Create a new webhook

POST /v1/shops/{shop_id}/webhooks.json
Create a new webhook
POST /v1/shops/{shop_id}/webhooks.json
{ "topic": "order:created", "url": "https://example.com/webhooks/order/created" } View Response

Modify a webhook

PUT /v1/shops/{shop_id}/webhooks/{webhook_id}.json
Modify a webhook
PUT /v1/shops/{shop_id}/webhooks/{webhook_id}.json
{ "url": "https://example.com/callback/order/created" } View Response

Delete a webhook

DELETE /v1/shops/{shop_id}/webhooks/{webhook_id}.json
Delete a webhook
DELETE /v1/shops/{shop_id}/webhooks/{webhook_id}.json
View Response

Securing your Webhooks

Once your server is configured to receive payloads, it'll listen for any payload sent to the endpoint you configured. For security reasons, you probably want to limit requests to those coming from Printify.

There are a few ways to go about this - for example, you could opt to whitelist requests from Printify's IP address - but a far easier method is to set up a secret token and validate the information.

Summary:

Setting your shared secret with Printify

You can generate the secret by running 'openssl rand -hex 20'.

When your secret token is set, Printify will use it to create a hash signature with each payload body. Printify uses an HMAC hexdigest to compute the hash sha256 signature with your provided secret.

Secret example 7afa37fd47d7a52ea644382e04962a83c16aef62

This payload body signature is passed along with each request in the headers as X-Pfy-Signature. The signature format is: sha256={digest}.

Signature example x-pfy-signature: sha256=4260d30ec4ee2a17181ae5072c846d8dfcb5ceb195e24de055fd9a21d8c6648f

Accessing the Secret from your backend

Next, set up a SECRET_TOKEN environment variable on your server that stores this token. Never hardcode the secret into your app!

Setting the SECRET_TOKEN environment variable example $ export SECRET_TOKEN=your_token

Validating payloads from Printify

Next, compute a request body hash using your SECRET_TOKEN, and ensure that the hash from Printify matches. Printify uses an HMAC hexdigest to compute the hash. Always use "constant time" string comparisons, which renders it safe from certain timing attacks against regular equality operators.

Validation sample (python) import os import hmac def sha256hash(request): hash = hmac.new(os.environ['SECRET_TOKEN'].encode('utf-8'), request.data.encode('utf-8'), 'sha256') return 'sha256=' + hash.hexdigest() def secure_compare(a, b): return hmac.compare_digest(a, b) print('%r' % secure_compare(request.headers['x-pfy-signature'], sha256hash(request)))

HTTP Status Codes

Printify API relies heavily on standard HTTP response codes codes. Please find the brief summary of status codes used below.

Success

Code Name Description
200 OK Request completed successfully.
201 Created The request has been fulfilled and has resulted in one or more new resources being created.
202 Accepted The request has been accepted for processing, but the processing has not been completed.
204 No Content Indicates that the server has successfully fulfilled the request and that there is no content to send in the response payload body.

User error codes

These errors generally indicate a problem on the client side. If you are getting one of these, check your code and the request details.

Code Name Description
400 Bad Request The request encoding is invalid; the request can't be parsed as a valid JSON.
401 Unauthorized Accessing a protected resource without authorization or with invalid credentials.
402 Payment Required The account associated with the API key making requests hits a quota that can be increased by upgrading the Printify API account plan.
403 Forbidden Accessing a protected resource with API credentials that don't have access to that resource.
404 Not Found Route or resource is not found. This error is returned when the request hits an undefined route, or if the resource doesn't exist (e.g. has been deleted).
413 Request Entity Too Large The request exceeded the maximum allowed payload size. You shouldn't encounter this under normal use.
422 Invalid Request The request data is invalid. This includes most of the base-specific validations. You will receive a detailed error message and code pointing to the exact issue.
429 Too Many Requests Too Many Requests response status code indicates you have sent too many requests in a given amount of time ("rate limiting").

Server error codes

These errors generally represent an error on our side. In the event of a 5xx error code, detailed information about the error will be automatically recorded, and Printify's developers will be notified.

Code Name Description
500 Internal Server Error The server encountered an unexpected condition.
502 Bad Gateway Printify's servers are restarting or an unexpected outage is in progress. You should generally not receive this error, and requests are safe to retry.
503 Service Unavailable The server could not process your request in time. The server could be temporarily unavailable, or it could have timed out processing your request. You should retry the request with backoffs.

History