Skip to contentPostalForm

MPP shipping labels

PostalForm MPP shipping-label endpoint instructions

Use this guide for MPP-paid domestic parcel shipping labels. PostalForm returns a carrier-generated 4-by-6 PDF label; it does not package or hand the parcel to the carrier.

Published Aug 27, 2026

Shipping labels are MPP-only. Do not send this payload through the letter, postcard, flower, x402, hosted-checkout, or MCP draft endpoints.

Base URL: https://postalform.com

Endpoints

Purpose Method and path
Validate addresses and parcel measurements and receive live rates POST /api/machine/mpp/shipping-labels/validate
Create an unpaid order, receive 402, and retry after MPP payment POST /api/machine/mpp/shipping-labels
Poll payment, purchase, tracking, and download status GET /api/machine/mpp/shipping-labels/{id}

Request body

Top-level fields:

  • request_id: UUID idempotency key.
  • buyer_name and buyer_email: required for payment and label delivery.
  • from and to: U.S. sender and recipient address objects.
  • parcel: measured weight and exterior dimensions.
  • carrier: optional carrier name returned by validation.
  • service: optional carrier service returned by validation.

Each address requires name, street1, city, two-letter state, five- or nine-digit zip, and phone. Optional fields are company, street2, and email. country may be omitted or set to US.

The parcel requires:

  • weight_oz: actual packaged weight in ounces, greater than zero and no more than 2,400.
  • length_in, width_in, and height_in: actual exterior inches, each greater than zero and no more than 108.

PostalForm rounds measurements up to one decimal place before requesting carrier rates. Carrier-specific weight, dimension, address, and service limits can be lower than the API schema limit. A live validation result is the source of truth for current eligibility.

Validate and choose a rate

curl -sS https://postalform.com/api/machine/mpp/shipping-labels/validate \
  -H 'Content-Type: application/json' \
  --json '{
    "request_id": "8ad35df9-466f-4a65-8c4b-4580332f76c6",
    "buyer_name": "Agent Owner",
    "buyer_email": "owner@example.com",
    "from": {
      "name": "Agent Owner",
      "street1": "123 Sender St",
      "city": "Springfield",
      "state": "IL",
      "zip": "62701",
      "country": "US",
      "phone": "2175550100"
    },
    "to": {
      "name": "Recipient Example",
      "street1": "456 Recipient Ave",
      "city": "Chicago",
      "state": "IL",
      "zip": "60601",
      "country": "US",
      "phone": "3125550199"
    },
    "parcel": {
      "weight_oz": 24,
      "length_in": 10,
      "width_in": 7,
      "height_in": 4
    }
  }'

The validation response includes a selected quote, available_rates, and quote expiry. Each rate includes:

  • carrier and service.
  • total_cents: the all-in customer price.
  • delivery estimates when the carrier supplies them.

If carrier and service are omitted, PostalForm selects the lowest returned total. To select another result, copy its exact carrier and service into a new request and use a fresh request_id.

Rates and supported carriers are dynamic: PostalForm offers the rates returned by the carriers enabled on its EasyPost account for that parcel and route. Do not assume a static carrier list or promise a service that is absent from available_rates.

Create, pay, and receive the PDF

Create the unpaid order using the same body:

curl -i https://postalform.com/api/machine/mpp/shipping-labels \
  -H 'Content-Type: application/json' \
  --json @shipping-label-body.json

The unpaid call returns HTTP 402, one or more WWW-Authenticate: Payment ... challenges, and the persisted quote. Pay one Tempo, Stripe SPT, or configured card-MPP challenge, then retry the exact same body and request_id:

curl -i https://postalform.com/api/machine/mpp/shipping-labels \
  -H 'Content-Type: application/json' \
  -H 'Authorization: Payment <serialized-mpp-credential>' \
  --json @shipping-label-body.json

When payment and carrier purchase finish immediately, the response is HTTP 200 with Payment-Receipt, tracking_code, label_download_url, label_download_expires_at, and order_complete_url. If payment or carrier purchase is still finalizing, the response is HTTP 202; poll the returned status URL and do not pay again.

PostalForm also emails the PDF as an attachment plus a signed download link to buyer_email, and the order completion page exposes a download button. Download links expire. Polling the status endpoint or revisiting the completion page issues a fresh signed link while the label remains available.

Pricing and adjustments

PostalForm calculates the customer total internally from the selected live carrier rate, a configurable EasyPost/platform-fee reserve, a configured service margin, and an estimated payment-processing fee. The payment challenge uses the same persisted total shown by validation. Wholesale carrier cost and margin fields are stored for reconciliation but are not disclosed in the public MPP response.

Accurate packaged weight and dimensions are required. Carriers can audit a parcel after acceptance and assess a correction for inaccurate measurements, packaging, address details, or service eligibility. That later carrier adjustment cannot be guaranteed at quote time and may reduce the expected margin.

Status and errors

Status responses distinguish payment from fulfillment. Common fulfillment values are quoted, purchasing, label_ready, and purchase_failed.

  • 422 invalid_request: fix schema errors.
  • 422 invalid_shipping_label_order: fix address, parcel, or service validation.
  • 422 shipping_service_unavailable: select a returned carrier/service pair.
  • 422 amount_exceeds_limit: the total exceeds the configured MPP limit.
  • 409 request_id_mismatch: the same request_id was reused with a different payload.
  • 409 shipping_label_quote_expired: create a new order with a fresh request_id so the payment challenge and carrier rate stay aligned.
  • 402 payment_required: normal MPP challenge response.
  • 502 carrier_quote_failed: the carrier-rate provider could not quote the shipment.
  • 503 shipping_labels_unavailable: the shipping-label product is disabled or not configured.
  • 429 rate_limited: wait before creating more unpaid orders.

Related docs

  • All MPP endpoints: https://postalform.com/mpp.md
  • Mail-only MPP guide: https://postalform.com/mpp-mail.md
  • Flower-only MPP guide: https://postalform.com/mpp-flowers.md
  • OpenAPI: https://postalform.com/openapi.json