← Printvine

API quickstart

From artwork to a human-approved, vendor-routed print order. Test mode simulates payments and vendors with production-identical flows — test keys can never contact a real vendor.

This deployment runs the self-contained demo profile. The key below is the shared demo workspace key; data resets when the instance recycles.

1 · Upload artwork

JPG, PNG, PDF, or TIFF. Files are validated by content, hashed, and stored immutably — every correction becomes a new version.

curl https://printvine-hqy9d6el1-bouncinsoul17s-projects.vercel.app/api/v1/files \
  -H "Authorization: Bearer pv_test_sk_demo_5UQyoyLEV2EBmYTkBoAtvahU" \
  -F file=@poster.png

2 · Run product-aware preflight

A file is only “good” for a specific product. Preflight checks trim, effective DPI, sides, bleed, and color against the variant, then produces a versioned production candidate.

curl https://printvine-hqy9d6el1-bouncinsoul17s-projects.vercel.app/api/v1/preflight_jobs \
  -H "Authorization: Bearer pv_test_sk_demo_5UQyoyLEV2EBmYTkBoAtvahU" \
  -H "Content-Type: application/json" \
  -d '{"file_id": "file_...", "variant_id": "var_poster_18x24"}'

# -> report.outcome, report.issues[], production_file_id

3 · Create a quote

Quotes price the production candidate across eligible vendors and apply your pricing policy. They expire; totals include your margin.

curl https://printvine-hqy9d6el1-bouncinsoul17s-projects.vercel.app/api/v1/quotes \
  -H "Authorization: Bearer pv_test_sk_demo_5UQyoyLEV2EBmYTkBoAtvahU" \
  -H "Content-Type: application/json" \
  -d '{
    "line_items": [{"variant_id": "var_poster_18x24", "quantity": 1,
                     "files": {"front": "file_prod_..."}}],
    "ship_to": {"name": "Sam Example", "line1": "123 Main St",
                "city": "Santa Monica", "state": "CA",
                "postal_code": "90401", "country": "US"}
  }'

curl https://printvine-hqy9d6el1-bouncinsoul17s-projects.vercel.app/api/v1/quotes/q_.../select_shipping \
  -H "Authorization: Bearer pv_test_sk_demo_5UQyoyLEV2EBmYTkBoAtvahU" -H "Content-Type: application/json" \
  -d '{"shipping_option_id": "sinalite_ground"}'

4 · Create the order & pay

Orders are idempotent — send Idempotency-Key and retries can never double-charge or double-print. Payment truth comes from the payment provider's webhook, never a redirect.

curl https://printvine-hqy9d6el1-bouncinsoul17s-projects.vercel.app/api/v1/orders \
  -H "Authorization: Bearer pv_test_sk_demo_5UQyoyLEV2EBmYTkBoAtvahU" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: order-$(uuidgen)" \
  -d '{"quote_id": "q_...", "customer_email": "sam@example.com"}'

# -> checkout.url  (simulated checkout in test mode)

5 · Human review, then production

Every paid job crosses the operations board. A reviewer approves the exact production file — the approval is fingerprinted to file hashes, quantity, address, quote, and vendor route. Then Printvine submits idempotently, tracks vendor status, and normalizes shipping events.

# your integration listens:
order.paid  →  order.review_pending  →  order.approved
→  vendor_submission.accepted  →  order.in_production
→  shipment.created  →  shipment.delivered

# or polls:
curl https://printvine-hqy9d6el1-bouncinsoul17s-projects.vercel.app/api/v1/orders/ord_... -H "Authorization: Bearer pv_test_sk_demo_5UQyoyLEV2EBmYTkBoAtvahU"
curl https://printvine-hqy9d6el1-bouncinsoul17s-projects.vercel.app/api/v1/events -H "Authorization: Bearer pv_test_sk_demo_5UQyoyLEV2EBmYTkBoAtvahU"

Webhooks

Register an HTTPS endpoint; events are signed (HMAC-SHA256), retried with backoff, and deduplicated by event id.

curl https://printvine-hqy9d6el1-bouncinsoul17s-projects.vercel.app/api/v1/webhook_endpoints \
  -H "Authorization: Bearer pv_test_sk_demo_5UQyoyLEV2EBmYTkBoAtvahU" \
  -H "Content-Type: application/json" \
  -d '{"url": "https://example.com/webhooks/printvine", "events": ["*"]}'

# verify: printvine-signature: t=<unix>,v1=HMAC_SHA256(secret, t + "." + body)

Errors

Stable envelope: type, machine-readable code, human message, offending param, and a request id for support. Common codes: PREFLIGHT_REQUIRED, QUOTE_EXPIRED, UNSUPPORTED_QUANTITY, IDEMPOTENCY_CONFLICT, APPROVAL_REVOKED, MARGIN_BELOW_FLOOR.

{
  "error": {
    "type": "preflight_error",
    "code": "PREFLIGHT_REQUIRED",
    "message": "Files must pass product-aware preflight before they can be quoted.",
    "param": "line_items[0].files.front",
    "request_id": "req_..."
  }
}

Simulator scenarios (test mode)

Trigger vendor failure paths by putting markers in ship_to.name: