Skip to content
From the farm floor

Order Completion Webhooks for Printie Partners

Implement Printie's order.completed webhook safely with the current payload, durable intake, idempotency, testing, and failure monitoring.
Tyler Reece

By Tyler Reece · Published November 20, 2025 · Updated July 22, 2026 · 6 min read

Printie's order-completion webhook sends a JSON POST after a fulfillment record is written. It gives a partner system the completed order identity, shipment and tracking data, totals, SKU lines, assigned design files, and included-item details without requiring polling.

The important operating detail is delivery behavior: Printie waits up to 10 seconds, does not automatically retry, and never rolls back physical fulfillment because a partner endpoint failed. Your receiver should therefore validate quickly, store the event durably, return a successful HTTP response, and process downstream work asynchronously.

This feature appears in the Advanced section of Account Settings only for accounts with partner API access. It is separate from the Shippo or ShipStation connection used for storefront order intake.

Configure and test the endpoint

In Account Settings → Advanced → Order completion webhook, save an HTTP or HTTPS URL. Production receivers should use HTTPS. A blank value disables delivery. URLs are limited to 2,000 characters, and Printie rejects malformed URLs, unsupported protocols, literal private-network targets, loopback hosts, and internal hostnames.

Use Send test before the first live fulfillment. The test invokes the same outbound delivery path with representative order, tracking, totals, selected-filament, and included-item data. A failed destination response is returned as a structured result such as a timeout or HTTP status instead of turning the test request into an unrelated server failure.

Testing should prove more than “the route returned 200.” Confirm that:

  1. the receiver stores the raw body and arrival time;
  2. the event can be identified more than once without duplicating side effects;
  3. unknown optional fields do not break parsing;
  4. sensitive customer fields do not leak into unrestricted logs;
  5. downstream jobs can be replayed from the stored event;
  6. an intentional receiver failure appears in your alerting.

Current payload contract

The event name is order.completed and the current payload version is 2026-07-06. Treat the version as a schema identifier, not as the date an individual order was completed.

Here is a shortened but structurally accurate example:

{
  "event": "order.completed",
  "version": "2026-07-06",
  "fulfillmentId": "account-123_order-456",
  "completedAt": "2026-07-22T18:45:00.000Z",
  "order": {
    "orderId": "order-456",
    "orderNumber": "A-456",
    "status": "Completed",
    "customer": {
      "name": "Example Customer",
      "email": "customer@example.com"
    },
    "shippingAddress": {
      "name": "Example Customer",
      "addressLine1": "123 Main St",
      "addressLine2": null,
      "city": "Boston",
      "state": "MA",
      "postalCode": "02118",
      "country": "United States"
    },
    "shipping": {
      "carrier": "ups",
      "trackingNumber": "1Z999",
      "trackingUrl": "https://example.com/tracking/1Z999",
      "labelUrl": "https://example.com/labels/label.pdf",
      "cost": 10
    },
    "totals": {
      "totalQuantity": 1,
      "totalCost": 25.5,
      "productionCost": 15,
      "shippingCost": 10,
      "includedItemsPickFee": 0.5
    },
    "items": [
      {
        "sku": "STORE-SKU-1",
        "title": "Desk Stand",
        "quantity": 1,
        "unitPrice": 0,
        "includedItems": [
          {
            "itemId": "thank-you-card",
            "name": "Thank You Card",
            "quantityPerUnit": 1,
            "usage": "include",
            "instructions": "Place on top of the print"
          }
        ],
        "designFiles": [
          {
            "designId": "design-123",
            "designName": "Desk Stand v2",
            "quantity": 1,
            "filamentType": "PLA",
            "selectedFilaments": [],
            "notes": null,
            "printProfile": null,
            "costData": {
              "totalCost": 15
            }
          }
        ]
      }
    ]
  },
  "metadata": {
    "partner": null
  }
}

Authorized Printie partners can open the machine-readable contract in the gated /api-docs reference after an API key is enabled. Contact Printie if your account needs partner API access. Generate types or fixtures from that contract when possible, but keep your parser tolerant of additional fields. A new optional property should not make a previously valid completion event unreadable.

Design the receiver as an inbox

The safest receiver is a small inbox rather than a large workflow:

  1. Accept the POST.
  2. Enforce a reasonable body-size limit.
  3. Parse JSON and require the expected event name.
  4. Derive an idempotency key.
  5. Insert the event and key into durable storage in one transaction.
  6. Return a 2xx response.
  7. Let a background worker update the CRM, ERP, analytics, or customer system.

Use fulfillmentId + event + version as a practical event key. If your business permits multiple completion records for the same source order, do not deduplicate on orderNumber alone. Order numbers can collide across stores, and a human-readable number is not necessarily the stable record identity.

An idempotent consumer is still necessary even though Printie does not currently retry automatically. Operators can send test events repeatedly, reverse proxies can retry requests, and future delivery behavior can evolve. Shippo's own tracking documentation explicitly notes that its tracking webhooks are not idempotent, which illustrates the broader rule: webhook consumers should assume duplicate delivery is possible.

Return success only after durable acceptance

Do not return 200 before the event is stored. If the process exits between the response and the database write, there is no automatic Printie retry to recover that completion.

Do not perform a slow sequence of external API calls before responding either. Printie's request timeout is 10 seconds. A CRM outage or spreadsheet API delay should not turn ingestion into a timeout. Store first, acknowledge, then retry your own downstream jobs under your own policy.

The HTTP specification defines successful responses as the 2xx class; see RFC 9110, section 15.3. Use a clear 2xx response once the inbox owns the event. Reserve 4xx for an event you intentionally reject and 5xx for a receiver failure, knowing that the current sender will report the failure but will not schedule another attempt.

Handle totals deliberately

Do not assume every cost field means storefront revenue.

  • totalCost represents fulfillment cost in the completion record.
  • productionCost represents charged production amounts when available.
  • shippingCost can be null on legacy records.
  • includedItemsPickFee covers applicable picked customer-supplied items.
  • unitPrice is not a promise of the buyer's retail price.

If the webhook feeds accounting, preserve the original payload and map each field explicitly into your ledger. Do not silently substitute zero for null: “not available” and “no cost” are different facts.

The items array carries the SKU-level quantity and assigned production details. A designFiles quantity is the quantity of that design per sold line configuration; the line's own quantity still matters. Test a multi-quantity order before using these fields for inventory or unit economics.

Protect customer and fulfillment data

The payload can contain a name, email, full shipping address, label URL, tracking number, and internal cost information. Apply the same access controls and retention policy you use for orders.

  • Keep raw bodies out of public error trackers.
  • Redact addresses and label URLs from routine logs.
  • Use a dedicated secret endpoint path or gateway controls.
  • Restrict database access by service role.
  • Rotate any URL token that is exposed.
  • Validate outbound actions; never treat notes or titles as executable instructions.

If your gateway supports request signing of your own, that does not prove Printie generated the body unless both systems share a verification contract. Do not invent a signature header that the current webhook does not send. Use network controls and a secret endpoint as compensating controls, then contact Printie if your integration requires a stronger authentication arrangement.

Monitor the two halves separately

Create one dashboard for intake and another for downstream processing:

Signal
Question it answers
Received eventsDid the endpoint accept completions?
Duplicate-key countAre events being delivered or replayed more than once?
Receiver response timeIs ingestion safely below the timeout?
Queue ageAre accepted events waiting too long?
Permanent processing failuresWhich system or mapping needs intervention?
Order reconciliation gapWhich Printie completions are absent downstream?

Because delivery is best-effort, schedule a periodic reconciliation against your authoritative Printie fulfillment data when the integration is business-critical. The webhook reduces latency; reconciliation closes gaps.

Production-readiness checklist

  • Partner API access exposes the Advanced settings.
  • The endpoint is HTTPS and publicly reachable.
  • The Send test payload is stored and processed.
  • Parsing accepts version 2026-07-06 and ignores unknown optional fields.
  • fulfillmentId-based idempotency is enforced in durable storage.
  • A 2xx response happens only after the event is committed.
  • Background processing has retries and a dead-letter path.
  • Logs redact customer, address, label, and cost data.
  • Multi-SKU and multi-quantity totals have been tested.
  • Monitoring catches both delivery failures and stuck downstream jobs.
  • Reconciliation can identify a completion missing from the partner system.

For the upstream order path, read the automated fulfillment blueprint. To understand the production and shipping stages that precede this event, see How Printie works and review current pricing.

Run it on Printie

Put your fulfillment on autopilot.

Discover how Printie automates made-to-order production. Explore the full workflow and flexible pricing to match your store's scale.

Keep reading

More on this topic

June 22, 2026 · 8 min read

Top 5 Fulfillment Automation Platforms for 3D Print Sellers

A top-5 comparison of fulfillment automation platforms for selling 3D printed products online, including Printie, Teleport, 3DQue, Shop3D, and FlowQ.

May 27, 2026 · 5 min read

Which 3D Print Fulfillment Services Integrate Best with Amazon?

A practical Amazon fulfillment integration comparison for 3D print sellers, including Printie, FBM, FBA, and Seller Fulfilled Prime tradeoffs.

May 27, 2026 · 5 min read

Which 3D Print Fulfillment Services Integrate Best with Etsy?

A practical Etsy integration comparison for 3D print sellers, including Printie, Printify-style POD, and in-house workflows.

May 27, 2026 · 5 min read

Which 3D Print Fulfillment Services Integrate Best with TikTok Shop?

A practical TikTok Shop integration comparison for 3D print sellers, including Printie, Seller Shipping, FBT, and custom workflows.

May 27, 2026 · 7 min read

How to Connect Walmart Marketplace to 3D Print Fulfillment

The exact Walmart-to-Printie order path through ShipStation or Shippo, plus SKU mapping, test-order, tracking, and WFS decisions for 3D print sellers.

May 27, 2026 · 4 min read

Which 3D Print Fulfillment Services Integrate Best with WooCommerce?

A practical WooCommerce integration comparison for 3D print sellers, including Printie, plugin-based workflows, and custom routing paths.