# Ordering custom apparel from Customnia by API

Step-by-step instructions for an AI agent (or a developer) that orders printed T-shirts, hoodies, hats and bags from
Customnia for a person, without the website. Customnia prints in New York and Los Angeles and ships in the US.
Every step ends with a check. The same steps work through the MCP server at https://api.customnia.com/mcp
(tool names in brackets).

Reference: https://api.customnia.com/docs/order (the guide), https://api.customnia.com/docs/openapi.yaml (every
field and error).

## Rules for the agent

- Money is in US cents (`2280` = $22.80). Show the person dollars.
- Never place a live order the person has not agreed to. Show the quote total, wait for a clear yes, then send that
  total as `expected_total`. If the price changed, the API answers 409 `price_changed` and charges nothing: show the
  new total and ask again.
- Keep the keys secret. Do not print them back to the person or put them in files that others can read.
- The person does three things themselves, once: reads the email code, reads the SMS code, saves a card on a Stripe
  page. Ask for the codes; give them the page link. Never ask for a card number: it is entered only on Stripe's page.
- Try the whole flow with the test key first (`cn_test_…`): test orders are priced like real ones and never printed
  or charged.

## Step 1. Sign up

```bash
curl -s https://api.customnia.com/v1/signup -H "Content-Type: application/json" -d '{"email": "ann@example.com"}'
```

[Through MCP without a key: `start_signup`, then `verify_signup`; then reconnect with the test key.]

The person gets a 6-digit code by email. Then:

```bash
curl -s https://api.customnia.com/v1/signup/verify -H "Content-Type: application/json" \
  -d '{"email": "ann@example.com", "code": "123456", "name": "Ann Lee"}'
```

The answer holds `api_key` (`cn_live_…`) and `test_key` (`cn_test_…`), shown once. Signing up again with the same
email gives new keys and turns the old ones off.

Check: `GET /v1/account` with the test key answers `"kind": "buyer"` [`get_account`].

## Step 2. Confirm a phone (live orders only)

A US mobile number, confirmed by SMS, once per account. Virtual, landline and toll-free numbers are refused.

```bash
curl -s https://api.customnia.com/v1/account/phone -H "Authorization: Bearer $CUSTOMNIA_KEY" \
  -H "Content-Type: application/json" -d '{"phone": "+1 212 555 0123"}'
curl -s https://api.customnia.com/v1/account/phone/verify -H "Authorization: Bearer $CUSTOMNIA_KEY" \
  -H "Content-Type: application/json" -d '{"code": "654321"}'
```

[Through MCP: `setup_payments` gives a Customnia page (`setup_url`) where the person confirms the phone and saves a card
in a browser. Never ask for SMS codes or card numbers in the chat.]

Check: `GET /v1/account` shows `"phone": {"verified": true}`.

## Step 3. Save a card (live orders only)

```bash
curl -s -X POST https://api.customnia.com/v1/account/card -H "Authorization: Bearer $CUSTOMNIA_KEY"
```

Give the person the `url`: a Stripe page where they save a card. [Through MCP: the same `setup_payments` page.]

Check: `GET /v1/account` shows `card` with `brand` and `last4` once it is saved. From then on, orders are charged to
it without a browser.

## Step 4. Pick a blank

```bash
curl -s "https://api.customnia.com/v1/catalog?category=TSHIRT" -H "Authorization: Bearer $CUSTOMNIA_KEY"
```

[`search_catalog`, `get_blank`] Each blank has `colors` (with `id`, name and price per size in `prices`) and `sizes`
(with `id`). Note the `moq` of a color: the fewest pieces of that blank and color an order can have. The answer's
`shipping.methods` lists ways to ship from each location.

Check: you have a `blank_id`, a `color_id` and a `size_id` for each line.

## Step 5. Make the design

From a PNG (at least 600 × 600 px; a transparent background prints best):

```bash
curl -s https://api.customnia.com/v1/designs -H "Authorization: Bearer $CUSTOMNIA_KEY" \
  -F blank_id=4 -F file=@art.png
```

[`create_design` takes `front_png_url`, a public link to the PNG.]

No picture? Words work: `text` (`\n` between lines), `font` from `GET /v1/fonts` [`list_fonts`], `text_color` (hex; white
on dark garments), `bold`, `italic`, `text_side`. A photo or a picture on a background: add `remove_background: true`.

Show the person the mockup:
`GET /v1/designs/{id}/mockups/{color_id}.jpg` [`get_mockup`].

Check: the design answers `"ready": true` and the person likes the mockup.

## Step 6. Quote

```bash
curl -s https://api.customnia.com/v1/quotes -H "Authorization: Bearer $CUSTOMNIA_KEY" -H "Content-Type: application/json" \
  -d '{"items": [{"design_id": 101, "color_id": 1, "size_id": 3, "quantity": 12}],
       "speed": "REGULAR", "shipping_method": "UPS GROUND", "shipping_address": {"state": "NY"}}'
```

[`quote_order`] The answer gives each line's `unit_price`, `discount` (more pieces of a blank cost less), `tax`, then
`totals` and `ready_by` — when the order is printed (shipping time comes on top).

- `speed`: `REGULAR` (default), `TWO_BUSINESS_DAYS` or `SAME_DAY` where the blank and color allow it; faster costs more
  per piece.
- `shipping_method`: one of the catalog's `shipping.methods`; `UPS GROUND` by default.
- The state picks the print location: western states print in Los Angeles, the rest in New York.

Ask the person what customnia.com asks at payment, and quote again with the answers:

- `review_design: true` — a Customnia designer checks the artwork before printing (price in the quote's
  `options.design_check.price`, $9 today).
- `print_as_is: true` — print exactly as sent, no improving, no background removal.
- `tip` — a tip for the print team in cents; suggest $1, $3, $5, $10 or $20.
- `promo_code` — if they have one.

Check: show the person the lines, `totals.total` in dollars and `ready_by`, and get a yes.

## Step 7. Order

```bash
curl -s https://api.customnia.com/v1/orders -H "Authorization: Bearer $CUSTOMNIA_KEY" -H "Content-Type: application/json" \
  -d '{"reference": "ann-2026-001", "expected_total": 26380,
       "items": [{"design_id": 101, "color_id": 1, "size_id": 3, "quantity": 12}], "speed": "REGULAR",
       "shipping_address": {"first_name": "Ann", "last_name": "Lee", "address1": "1 Main St", "city": "Brooklyn",
                            "state": "NY", "zip": "11201", "phone": "+12125550123"}}'
```

`expected_total` is `totals.total` from Step 6, the total the person agreed to; send the same options as that quote. [`place_order`] `reference` is your own id for the order: sending the same reference again returns the same order and
never charges twice, so retry freely after a timeout.

| Answer | What to do |
|---|---|
| 201 | Placed and paid. Tell the person the order `id` and `ready_by`. |
| 409 `price_changed` | Show `quote.totals.total`, ask again, send the new total. |
| 402 `card_required` | Step 3. |
| 402 `card_declined` | Tell the person; they save another card (Step 3). |
| 402 `authentication_required` | The bank wants the person to confirm: give them `action_url`, then send the same order again. |
| 403 `phone_required` | Step 2. |
| 403 `order_limit` / `daily_limit` | A limit the person set (`PATCH /v1/account`). |
| 422 | `errors` names each bad field (for example a quantity under `moq`). |
| 429 | Too many attempts; wait a minute. |

Check: `GET /v1/orders/{id}` [`get_order`] answers `"status": "received"`.

## Step 8. Follow and change

- Status: `received` → `printing` → `ready` → `shipped` (with tracking) → `delivered`. Check with `GET /v1/orders/{id}`
  or `GET /v1/orders?updated_since=…` [`list_orders`], or have them pushed: `PATCH /v1/account {"webhook_url":
  "https://…"}` answers a `webhook_secret` (shown once) that signs every `order.updated` webhook.
- Until printing starts: `POST /v1/orders/{id}/cancel` refunds the card in full [`cancel_order`];
  `PATCH /v1/orders/{id}/address` changes where it goes [`change_order_address`].
- With the test key, `POST /v1/orders/{id}/simulate {"status": "shipped"}` moves a test order on [`simulate_order`].

## Limits the person can set for you

`PATCH /v1/account {"limits": {"order": 20000, "daily": 50000}}` caps one order and one day, in cents. Customnia sets
no cap of its own.

Questions: hello@customnia.com.
