Skip to main content
POST
Buy a product from a major online retailer and ship it to a US address
Place an order using the Machine Payments Protocol (MPP) — no Zinc account required. Payment is made upfront via MPP, supporting multiple payment methods including Tempo stablecoins and Stripe.

How It Works

  1. Send Order Request - Submit an order to /agent/orders with product and shipping details
  2. Payment Challenge - If no valid payment credential is provided, the API returns HTTP 402 with payment challenges for all configured methods
  3. Submit Payment - Include a valid MPP payment credential in the Authorization header
  4. Order Processing - Once payment is confirmed, the order is queued for processing
This endpoint uses the same OrderCreate request body as the standard Create Order endpoint. The only difference is how authentication and payment are handled. The same limits apply — notably at most 10 products per order, checked before the agent is charged.

Payment is the gate

Payment — not request validation — is the gate on this endpoint. The body is parsed leniently so that an unpaid request reaches the 402 payment challenge instead of being rejected first by schema validation. This means an automated MPP discovery probe can send no body, an empty body, or a partial body and still receive the 402 challenge describing how to pay. The body is only validated strictly once a valid payment credential is present. After paying, send a complete, valid OrderCreate body — an incomplete one will then be rejected with a 422.

Payment Methods

MPP supports multiple payment methods via the HTTP 402 challenge-credential flow:
  • Stripe - Cards and wallets
  • Tempo - Stablecoins
When a request is made without a valid credential, the response includes WWW-Authenticate headers describing the available payment challenges. Your MPP client uses these to complete payment and resubmit the request.

402 Payment Required

If no valid payment credential is provided, the API returns 402 Payment Required with WWW-Authenticate headers describing the available payment methods.

Response Headers

string
One header per supported payment method with challenge parameters (per RFC 9110 §11.6.1). Your MPP client uses these to complete payment and resubmit the request.
See the MPP guide for a full walkthrough of integrating MPP with Zinc.

Headers

authorization
string | null

Query Parameters

method
string | null

Restrict the 402 to a single payment method (e.g. 'stripe', 'tempo', or 'x402'). Omit to advertise every configured method. Use this when your client can satisfy only one rail — it avoids returning multiple WWW-Authenticate challenges, which many HTTP clients mishandle.

Body

application/json

Request model for creating a new order.

products
OrderProduct · object[]
required
shipping_address
Address · object
required

Shipping address model.

Supports international addresses. The state field is optional for countries that don't use states/provinces. The country field uses ISO 3166-1 alpha-2 country codes (e.g., "US", "CA", "GB", "DE"), which are required rather than inferred — a longer spelling like "USA" is rejected with the code to use, so everything downstream can rely on seeing alpha-2.

max_price
integer
required

Maximum price (in cents) allowed for an order before it is finalized.

Required range: x >= 0
idempotency_key
string | null

Optional idempotency key to prevent duplicate orders. If not provided, one will be generated.

Maximum string length: 36
retailer_credentials_id
string | null

Optional short ID (e.g. 'zn_acct_XXXXXXXX') of one of your own saved retailer accounts to place this order on. The item is then paid for by the payment method saved on that account, and your wallet is charged the API fee only — so the balance needed to place the order is the fee, not max_price + fee. Omit it and the order is placed on a Zinc account and funded from your wallet; Zinc never substitutes one of your saved accounts, so send this field on every order that has to run on yours.

metadata
Metadata · object | null

Optional metadata to attach to the order. Can contain arbitrary key-value pairs.

po_number
string | null

Optional purchase order number for the order.

handling_days_max
integer | null

Optional ceiling on a seller's shipping and handling days. Omit or send null for no limit.

Required range: x >= 1
is_gift
boolean
default:false

Mark the order as a gift, suppressing prices on the packing slip. If the retailer's checkout offers no free gift option, the order FAILS with gift_option_unavailable rather than being placed as a normal order — a gift that arrives with prices visible to the recipient is treated as worse than no order.

gift_message
string | null

Optional note for the recipient, entered into the retailer's gift-message field at checkout. Requires is_gift to be true. Max 240 characters. Delivered where the retailer's checkout offers a gift message; the order is still placed without it where one isn't available.

Maximum string length: 240
payment
OrderPayment · object | null

Optional payment block. Omit for prepaid-wallet billing (default).

customer_notifications
CustomerNotifications · object | null

Opt in to emailing the end customer order updates (and unlock the public tracking page for this order). Adds a per-order surcharge. Omit for no customer notifications (default).

fulfillment
FulfillmentPreferences · object | null

Loosen the order's strict-by-default rules. Omit for today's behaviour: any rule that can't be met fails the order. Set a rule (gift, items, quantity) to best_effort to have the order placed anyway; anything left unset stays strict. Whatever was relaxed is reported back in fulfillment.concessions on the order. max_price is never relaxed. excluded_merchants tightens instead: merchants this order must not be bought from.

Response

Successful Response

Response model for order data.

id
string<uuid>
required
status
enum<string>
required
Available options:
pending,
in_progress,
order_placed,
order_failed,
cancelled,
cancelled_by_retailer
max_price
integer
required
attempts
integer
required
items
OrderItemResponse · object[]
required
shipping_address
Shipping Address · object
required
retailer_credentials_id
string | null
required
created_at
string<date-time>
required
updated_at
string<date-time>
required
metadata
Metadata · object
po_number
string | null
handling_days_max
integer | null
is_gift
boolean
default:false
gift_message
string | null
retailer_credentials_uuid
string | null
job_result
OrderJobResult · object | null

Fulfillment result and price breakdown for a completed or failed order; null while processing.

merchant_order_ids
string[]

The retailer's own order number(s) for this order (e.g. an Amazon 113-… ID), as recorded when it was placed. Empty while processing, or if the order never reached the retailer.

tracking_numbers
TrackingNumberResponse · object[]
created_by
string | null
user_id
integer | null
returns
ReturnRequestSummary · object[]
connect
OrderConnectInfo · object | null

Stripe Connect charge details when this order was paid via Connect; null for prepaid-wallet orders.

payment
OrderPaymentInfo · object | null

Card hold details when this order was paid by card outside the wallet and Connect; null for wallet and Connect orders.

customer_notifications
CustomerNotificationStatus · object | null

End-customer email-notification status when the order opted into the notifications add-on; null when it didn't.

fulfillment
OrderFulfillment · object

gift/items/quantity: the mode this order asked for on each rule (all null = strict). concessions: every rule that actually was relaxed, with the worker's code and the item it concerned. Empty concessions means the order was fulfilled exactly as requested.