medusa-plugin-printify
v0.3.1
Published
Printify print-on-demand integration plugin for Medusa v2
Maintainers
Readme
Why this plugin
- Real fulfillment, not just sync. Automatic order submission, real-time webhook status, and a Medusa Admin widget that surfaces production state on every order page.
- Type-safe, tested, CI-driven. TypeScript strict mode, Jest coverage, and OIDC-signed npm releases driven by conventional-commit PR titles.
- Decoupled and unopinionated. No storefront assumptions; works with any Medusa v2 host application.
Features
- Product sync — pull your Printify catalog into Medusa on a schedule or on-demand.
- Order fulfillment — automatically submit Medusa orders to Printify when they are placed.
- Webhook handling — real-time status updates (shipped, in-production, delivered, etc.).
- Admin UI — manage shops, browse synced products, and monitor order status from the Medusa Admin.
- Webhook auto-registration — registers all required Printify webhook topics on startup.
Screenshots
| Printify dashboard | Synced products |
|---|---|
|
| 
| Order widget | Order details |
|---|---|
|
|
|
Quick start
pnpm add medusa-plugin-printifyAdd to medusa-config.ts:
import { defineConfig } from "@medusajs/framework/utils"
export default defineConfig({
plugins: [
{
resolve: "medusa-plugin-printify",
options: {
apiKey: process.env.PRINTIFY_API_KEY,
webhookSecret: process.env.PRINTIFY_WEBHOOK_SECRET,
shopId: process.env.PRINTIFY_SHOP_ID,
webhookBaseUrl: process.env.PRINTIFY_WEBHOOK_URL,
},
},
],
})Run migrations:
pnpm medusa db:migrateDone. See Configuration for all options.
Table of contents
- Requirements
- Installation
- Configuration
- Local Development
- Production Deployment
- API Reference
- Order Fulfillment Flow
- Admin Dashboard
- Contributing
- Security
- License
Requirements
- Node.js >= 20
- Medusa >= 2.12.4
- A Printify account with a personal access token
Installation
In your Medusa application directory:
pnpm add medusa-plugin-printifyConfiguration
1. Add environment variables
cp .env.template .envAdd the following to your Medusa application's .env:
PRINTIFY_API_KEY=your_printify_personal_access_token
PRINTIFY_WEBHOOK_SECRET=your_webhook_secret
PRINTIFY_SHOP_ID=your_printify_shop_id # optional, but required for order submission
PRINTIFY_WEBHOOK_URL=https://your-domain.com # base URL for webhook registration (no trailing slash)To find your API key: go to printify.com/app/account/api and generate a personal access token.
To find your shop ID: call GET https://api.printify.com/v1/shops.json with your API key.
The webhook secret is a string you choose — Printify will use it to sign webhook payloads so you can verify they are genuine.
2. Register the plugin in medusa-config.ts
import { defineConfig } from "@medusajs/framework/utils"
export default defineConfig({
// ... other config
plugins: [
{
resolve: "medusa-plugin-printify",
options: {
apiKey: process.env.PRINTIFY_API_KEY,
webhookSecret: process.env.PRINTIFY_WEBHOOK_SECRET,
shopId: process.env.PRINTIFY_SHOP_ID,
webhookBaseUrl: process.env.PRINTIFY_WEBHOOK_URL,
},
},
],
})All available options:
| Option | Type | Required | Description |
|---|---|---|---|
| apiKey | string | Yes | Printify personal access token |
| webhookSecret | string | Yes | Secret used to verify webhook signatures |
| shopId | string | No | Printify shop ID — required for order submission and webhook registration |
| webhookBaseUrl | string | No | Base URL of your Medusa server (e.g. https://api.mystore.com) — required for webhook registration |
| enableNotifications | boolean | No | Emit Medusa notification events for Printify order status changes |
| notificationEmail | string | No | Email address to receive Printify fulfillment notifications |
3. Run database migrations
In your Medusa application directory:
pnpm medusa db:migrateThis creates the printify_shop, printify_product, and printify_order tables.
Local Development
Prerequisites
- Docker (for the local PostgreSQL instance)
- pnpm
Plugin setup
Clone this repository and install dependencies:
git clone https://github.com/greedychipmunk/medusa-plugin-printify
cd medusa-plugin-printify
pnpm installCopy the environment template and fill in your values:
cp .env.template .envStart the local PostgreSQL instance:
docker compose up -dGenerate the plugin's database migrations:
pnpm medusa plugin:db:generatePublish the plugin to the local Yalc registry so your Medusa application can install it:
pnpm medusa plugin:publishLink to a local Medusa application
In your Medusa application directory, install the locally published plugin:
pnpm medusa plugin:add medusa-plugin-printifyRun migrations in the Medusa application:
pnpm medusa db:migrateWatch for changes
In the plugin directory, start the dev watcher — changes are automatically pushed to the local Yalc registry and picked up by your Medusa application:
pnpm devRun tests
pnpm test # all tests
pnpm test -- --watch # watch modeProduction Deployment
1. Build the plugin
pnpm build2. Publish to npm
Releases are handled automatically by .github/workflows/release.yml when a PR with a conventional-commit title (feat:, fix:, or feat!:) is merged to main. There is no manual npm publish step.
3. Install in your Medusa application
pnpm add medusa-plugin-printify4. Set environment variables on your server
Ensure the following are set in your production environment:
PRINTIFY_API_KEY=...
PRINTIFY_WEBHOOK_SECRET=...
PRINTIFY_SHOP_ID=...
PRINTIFY_WEBHOOK_URL=https://api.your-production-domain.com5. Run migrations
pnpm medusa db:migrate6. Configure your reverse proxy
The plugin exposes a webhook endpoint at POST /webhooks/printify. Ensure this path is reachable from the public internet so Printify can deliver webhook events. No authentication is needed on this route — the plugin verifies the x-pfy-signature HMAC header internally.
On startup, the plugin automatically registers all required webhook topics with Printify using the webhookBaseUrl you configured.
API Reference
All admin routes require authentication. Storefront routes are public.
Admin routes
| Method | Path | Description |
|---|---|---|
| GET | /admin/printify/shops | List all synced Printify shops |
| POST | /admin/printify/shops | Trigger a shop sync from Printify |
| GET | /admin/printify/products | List synced products (supports ?shop_id= filter) |
| POST | /admin/printify/products | Trigger a product sync from Printify |
| GET | /admin/printify/orders | List Printify orders (supports ?status= and ?medusa_order_id= filters) |
| POST | /admin/printify/orders/:id/submit | Manually submit a Printify order to production |
Webhook endpoint
| Method | Path | Description |
|---|---|---|
| POST | /webhooks/printify | Receives Printify webhook events |
Handled events: order:status-changed, order:shipped, order:sent-to-production, order:shipment:delivered, product:updated, product:deleted, shop:disconnected
Order Fulfillment Flow
- A customer places an order in your Medusa storefront.
- The
order.placedsubscriber detects any line items withmetadata.printify_product_id. - A Printify order is created and submitted to production automatically.
- Printify sends webhook events as the order moves through production and shipping.
- The plugin updates the local Printify order record and emits Medusa events for each status change.
- The Printify order widget on the Medusa Admin order detail page reflects the current status.
Admin Dashboard
The plugin adds two pages and one widget to the Medusa Admin:
- Printify (sidebar) — lists synced shops with a one-click sync button.
- Printify › Products — browse all synced products with search and a sync button.
- Order detail widget — appears below the order details on any order page, showing the linked Printify order status and a manual submit button for pending orders.
Contributing
PRs welcome. See CONTRIBUTING.md for setup. PR titles must follow Conventional Commits — the release workflow uses them to bump versions automatically.
Security
See SECURITY.md for how to report vulnerabilities.
License
Licensed under the MIT License.
