Request access

Catalog API

Version 1 ยท Base URL https://app.podmf.com/api/v1

Selling from your own site or system? The Partner API reads your published products, takes orders, charges your card on file and sends signed webhooks when orders ship. Start with the 15-minute quickstart, or send your team the integration guide (owner and developer steps).

The Catalog API lets your own systems (a website, a product database, a spreadsheet sync) read the POD Mfg catalog directly: every garment, its colors, sizes, print areas, stock and your prices. It shows what you see in the Catalog page of your portal.

The API is read-only. Designing, adding products to your store and placing orders still happen in the portal.

1. Get an API key

  1. Sign in at app.podmf.com as an owner of your brand.
  2. Open Catalog API from your dashboard.
  3. Name the key after where it will be used (for example "Website sync") and click Make key.
  4. Copy the key straight away. It starts with podk_ and is shown only once.

Treat a key like a password: keep it on your server, never in a web page or app your customers can open. You can have up to 10 keys and revoke any of them from the same page; a revoked key stops working at once. A key belongs to your brand. It also stops working if the owner who made it leaves the brand or stops being an owner, if your account is paused, or while updated Terms of Service are waiting for an owner to accept them in the portal.

2. Authentication

Send your key in the Authorization header of every request:

Authorization: Bearer podk_your_key_here

X-Api-Key: podk_... is accepted too. Never put a key in a URL. All requests use HTTPS and return JSON. Money is always whole cents in US dollars: 1450 means $14.50.

3. List the catalog

GET /api/v1/catalog returns the garments you can order, featured first, a page at a time.

Query parameterMeaning
pagePage number, starting at 1. Default 1.
limitProducts per page, 1 to 100. Default 50.
categoryOnly this category, for example tees. See categories.
methodOnly garments printable by this method: dtg, dtf, sublimation or embroidery.
qSearch the name, brand and style code.
curl "https://app.podmf.com/api/v1/catalog?category=tees&limit=2" \
  -H "Authorization: Bearer $PODMF_API_KEY"
{
  "products": [ { ...product... }, { ...product... } ],
  "page": 1,
  "limit": 2,
  "has_more": true
}

To read everything, keep asking for the next page while has_more is true. The list leaves out per-variant stock; get a single product for that.

4. Get one product

GET /api/v1/catalog/{slug} returns one garment by its slug, with everything in the list plus variants: one entry per color and size, with stock.

curl "https://app.podmf.com/api/v1/catalog/gildan-5000-tee" \
  -H "Authorization: Bearer $PODMF_API_KEY"

Answers { "product": { ... } }, or 404 if there is no such garment in the catalog.

5. List categories

GET /api/v1/categories

{ "categories": [ { "category": "hoodies", "products": 6 }, { "category": "tees", "products": 14 } ] }

6. The product object

{
  "slug": "gildan-5000-tee",
  "name": "Heavy Cotton Tee",
  "brand": "Gildan",
  "style_code": "5000",
  "category": "tees",
  "description": "Classic heavyweight tee.",
  "fabric": "cotton",
  "garment_type": "tee",
  "methods": [ { "key": "dtg", "name": "Direct to garment" }, { "key": "dtf", "name": "Direct to film" } ],
  "sizes": [ "S", "M", "L", "XL", "2XL" ],
  "colors": [ { "name": "Black", "hex": "#111111" } ],
  "min_quantity": 1,
  "lead_time_days": 7,
  "availability": { "status": "available" },
  "pricing": {
    "currency": "USD",
    "printing_included": false,
    "blank_price_by_size": { "S": 800, "M": 800, "L": 800, "XL": 800, "2XL": 1200 },
    "print_areas": {
      "dtg": [
        { "area": "front", "name": "Full front", "max_width_in": 12, "max_height_in": 16,
          "default": true, "price_cents": 1000 },
        { "area": "back", "name": "Full back", "max_width_in": 12, "max_height_in": 16,
          "default": false, "price_cents": 1000 }
      ]
    },
    "default": { "method": "dtg", "areas": [ "front" ],
                 "price_by_size": { "S": 1800, "M": 1800, "L": 1800, "XL": 1800, "2XL": 2200 } }
  },
  "variants": [ { "color": "Black", "size": "S", "units_in_stock": 4210 } ]
}
  • availability.status is available, low_stock, out_of_stock or unavailable.
  • units_in_stock is null when the supplier doesn't report stock for that variant.
  • A price is null when we haven't priced it yet; ask us before quoting it.

7. How pricing works

Every price is what you pay us, the same numbers as your portal's catalog. It is never a retail price; you set your own.

  • blank_price_by_size: the garment alone, per size, before printing.
  • print_areas: for each print method, each place we can print, its largest size in inches, and what printing there adds (price_cents).
  • A product's price is the blank price for its size plus each area you print. default shows that sum for the usual choice (the first method and its default area); rounding can make it differ from your own sum by a cent.
  • When printing_included is true (cut and sew), the blank price already includes all printing.

8. Errors and limits

StatusMeaning
400A query parameter is wrong (for example an unknown method).
401No key, or the key is wrong or revoked.
403"code": "terms_required": an owner needs to accept the updated Terms of Service in the portal.
404No such product or endpoint.
429Too many requests. Each key may make 120 requests a minute; repeated wrong keys from one address are paused for a while.

Errors are JSON: { "error": "..." }. We record each key's use (when and from where) in your brand's activity log.

9. Code examples

JavaScript (Node 18 or later):

const res = await fetch("https://app.podmf.com/api/v1/catalog?page=1", {
  headers: { Authorization: `Bearer ${process.env.PODMF_API_KEY}` },
});
if (!res.ok) throw new Error(`POD Mfg API: ${res.status}`);
const { products, has_more } = await res.json();

Python:

import os, requests
r = requests.get("https://app.podmf.com/api/v1/catalog",
                 params={"page": 1},
                 headers={"Authorization": f"Bearer {os.environ['PODMF_API_KEY']}"})
r.raise_for_status()
data = r.json()

Questions about the API: privacy@podmf.com.