parked-sketch-sandbox-printful-demo-2026-06-12
DARE.CO.UK · PARKED SKETCH · 2026-06-14
Mirrored from ~/.claude/.../memory/parked_sketch_sandbox_printful_demo_2026-06-12.md. This is a design sketch parked for future build — read for context, not as a current deliverable.
PARKED plan — sandbox.gf.cx/printful on-demand-printing demo (peelable stickers). Token in 1P exists+valid but NO store yet. Blocked on Dan creating a Manual/API store + confirming scopes. Mirrors the existing /voip + /one-pager sandbox slots.
PARKED 2026-06-12 (Dan: “lets park printful, but plan of building a sandbox.gf /printful demo”). On-demand-printing demo slot for peelable stickers via the Printful API, built like the other sandbox tier-2 slots ([[project_sandbox_one_pager_lead_capture_slot_2026-06-11]], the /voip sink).
Credentials (already done this session)
- 1P
Code Shared→ “Printful api”, token in thetokenfield →op read 'op://Code Shared/Printful api/token'(NOTcredential, which is empty). - Auth =
Authorization: Bearer <token>+X-PF-Store-Id: <id>. Verified valid (200 on/stores).
⛔ BLOCKER (why it’s parked)
- No store exists yet —
GET https://api.printful.com/stores→total:0. POD always happens inside a store. Dan must create a “Manual order platform / API” store in the Printful dashboard (NOT a Shopify/Etsy-synced one) → yields thestore_id. - Token scopes are minimal (403 on
stores_list/read). For POD, enable on the token:orders(rw),products/catalog(read),file_library(write),webhooks. (stores_listoptional — we hardcode the one store id.) - Resume trigger: Dan makes the store → re-check token, pull
store_id, confirm scopes resolve, then build.
Build plan (sandbox.gf.cx/printful — tier-2 slot)
Mirror the proven Worker pattern in ~/Code/sandbox.gf.cx/src/index.ts
(X-Sandbox-Key gate via VOIP_SANDBOX_KEY, R2 MEDIA bucket, surfaces.json
tier-2, deploy npx wrangler deploy):
- Worker endpoints:
- GET /api/printful/health — token bound? store_id set? catalog reachable?
- POST /api/printful/mockup — Printful mockup-generator
(/mockup-generator/create-task/{product_id}) → render the sticker art on a
product mockup for the demo preview.
- POST /api/printful/draft — create order with confirm:false (draft =
saved, NOT produced/charged) from {variant_id, file_url, recipient}. This is
the test-proof equivalent (like Lob test key / confirm:false).
- POST /api/printful/confirm — confirm a draft → production (the “go live”
step). X-Sandbox-Key gated.
- GET /api/printful/orders — list (gated).
- POST /api/printful/webhook — Printful order-status events (shipped,
returned, failed) → R2 sandbox/printful/orders/<date>/… — REUSE the
[[project_mowrfixr_vapi_voice_intake_2026-06-12]] voip-sink + dashboard
pattern (the /voip/calls/ dashboard is the template).
- Demo page dist/printful/: pick a sticker product → upload/choose art →
mockup preview → create draft → show proof → (gated) confirm. Plus a calls-
dashboard-style order list behind CDN, security layer, and DNS provider sitting in front of dare.co.uk." data-tip="Cloudflare — the CDN, security layer, and DNS provider sitting in front of dare.co.uk.">CF Access (home-IP bypass, same as
/voip/calls).
- CLI analog: send_sticker.mjs (Node, zero-dep) — draft → you approve →
confirm — modelled on send_postcard.mjs (the Lob sender), same
test-proof-first / live-on-approval discipline.
Test→live discipline (no separate sandbox key needed)
Printful confirm:false draft == proof (not produced, not charged); confirm ==
go live. Same approve-before-spend rule as Lob. Stickers = peelable die-cut /
kiss-cut (Printful catalog). Alt services considered: Sticker Mule (specialist
quality), Gelato (global local-print) — Printful chosen for the mature
sandbox→live dev API that maps onto our existing flow.
Related: [[reference_lob_renderer_no_flex_alignment_2026-06-12]] (sibling print-on-demand pipeline), the sandbox autovideo/one-pager slots.