Manage Printful print-on-demand products, orders, shipping rates, files and webhooks through the Printful API.
Printful ships in the w6w first-party pack. It declares 25 actions, 3 health checks, and the host runs its code in a sandbox that never sees the credential.
io.w6w.printfulPrintful is a print-on-demand and dropshipping service: you upload a design, Printful prints it on a blank product (shirts, mugs, posters and so on), packs it and ships it to your customer. This app connects a workflow to the Printful v1 REST API with a private token.
A workflow can browse the product catalog (products, variants, categories, size guides), list and read the products synced into a store, create and delete synced products, add print files to the file library, and read their processing status. It can create orders as drafts or submit them for fulfillment, update, confirm and cancel them, list and read orders, estimate order costs and calculate shipping rates for a recipient. It can also set, read and disable the store’s webhook, which is how Printful pushes shipping, order and stock events out.
Printful wraps every response in a {code, result, paging} envelope and reports errors with an error.reason; this app unwraps the envelope and reports the reason. An account-level token additionally takes a Store ID. Health checks read the API component of Printful’s status page, whether the API answers, and the rate-limit headroom.
Three routes to the same 25 actions. The Workflow tab is generated from Printful's own manifest and carries its real ids, so it is copy-pasteable; the Code and CLI examples are the same call for any action on any app, so every app-specific value in them is a blank you fill in.
catalog-product-list List the Printful product catalog (the blank products you can print on), optionally by category.
catalog-variant-get Get one catalog variant (a size/colour of a product) and its parent product.
file-add Add a print file to the file library by public URL. An identical URL returns the existing file.
order-cancel Cancel a pending order or delete a draft. The charged amount is returned to the store owner.
order-confirm Approve a draft order for fulfillment. The store owner is charged when it is submitted.
order-cost-estimate Estimate the costs of an order (items, shipping, tax) without creating it.
order-create Create an order as a draft, or submit it for fulfillment at once with Confirm. Confirming charges the store owner.
order-update Replace the details of a draft order (recipient and items are required by the API); optionally confirm it.
shipping-rate-calculate List the shipping options and rates for a recipient and a set of items.
store-list List the stores the token can see (all stores for an account-level token, one for a store-level token).
sync-product-create Create a sync product together with its sync variants, each linked to a catalog variant and a print file.
sync-product-delete Delete a sync product and all of its sync variants. Orders already placed are unaffected.
sync-product-list List the products synced into the store's Printful catalog (the store's own products).
webhook-set Enable the store's webhook URL and event types. Only one URL is active per store: this replaces any existing configuration.
A workflow step names the app and the action, and the editor fills in the
connection when you pick one. This is the Step shape from the
workflow spec, carrying Printful's real ids.
{
"manifestVersion": "2",
"name": "printful-example",
"steps": [
{
"id": "catalog-product-get",
"uses": {
"app": "io.w6w.printful",
"action": "catalog-product-get",
"connection": "conn_YOUR_CONNECTION_ID"
},
"with": {
"productId": "<productId>"
}
}
]
}catalog-product-get catalog-product-list catalog-size-guide-get catalog-variant-get category-list +20 more actions available
Every app-specific value here is a blank you have to fill in. An
app action is reached through the connection that authenticates it, so the
address is a connection id, not the app id — and connections belong to your account,
so a public page cannot know yours. Create one for Printful, then fill in
the three blanks: conn_YOUR_CONNECTION_ID, the action key, and the
parameters that action declares. The call itself is real — the shape is transcribed
from the studio's own snippet builder, which prints the same kind of blanks — but
nothing in it is specific to Printful. The Workflow tab is where this app's
real ids are.
npm install @w6w/sdkyarn add @w6w/sdkpnpm add @w6w/sdkdeno add npm:@w6w/sdkimport { W6wClient, isActionRun } from "@w6w/sdk";
// Reads W6W_BASE_URL and W6W_TOKEN from the environment when omitted.
const client = new W6wClient();
const envelope = await client.run({
urn: "conn_YOUR_CONNECTION_ID",
action: "catalog-product-get",
payload: {
productId: "<value>",
},
});
if (isActionRun(envelope)) console.log(envelope.value); npm install -g @w6w/cli w6w run conn_YOUR_CONNECTION_ID --action catalog-product-get --payload '{"productId":"<value>"}' Give an AI agent Printful — without giving it Printful's credentials. One MCP endpoint exposes every app, function and workflow the caller is entitled to, as tools it can discover and run. Access is granted per team while we onboard.
One tool call{
"name": "w6w_invoke",
"arguments": {
"ref": "app:io.w6w.printful#catalog-product-get",
"input": {
"productId": "<productId>"
}
}
}
Every tool names its target with a single ref. The
app: form above doesn't name a connection at all — the
host resolves which of the caller's Printful connections to sign
with, and refuses rather than guesses when the answer is ambiguous.
The token is attached host-side, at the moment of the call. It is never a tool argument, never in the model's context, and never in a transcript — so a prompt injection has nothing to exfiltrate.
Tools are derived per end user from what that person has actually connected and is entitled to — not one shared bot identity carrying the union of everyone's access.
Multi-step work runs on the workflow engine and returns a run handle the agent can poll — retries, branching and state survive the conversation that started them.
Printful's declared health checks are on the surface too, so an agent can tell "the vendor is down" from "your credential expired" before it burns a retry on either.
The MCP surface is part of the hosted platform. Printful itself is MIT, and the runtime that executes it is source-available (FSL).
Printful declares its own checks, so its health is a property of the app rather than something the host guesses at.
The `API` component of Printful's Statuspage (www.printfulstatus.com). Unauthenticated and unsigned; the page's integration and fulfillment components are ignored.
Unauthenticated GET /stores. Printful's JSON `error` envelope (401 Unauthorized) passes: it proves the application is answering.
Calls remaining in the current 60-second window, read off the response headers.