Skip to main content
POST
Create Mpp Order
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.

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").

max_price
integer
required

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

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 specific retailer credentials to use for this order. If not provided, credentials will be selected automatically.

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).

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.

customer_notifications
CustomerNotificationStatus · object | null

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