MPP flowers
PostalForm MPP flower endpoint instructions
Use this file for MPP-paid flower letters only. A flower letter is a fresh flower arrangement delivered through Florist One with a short recipient note.
Published Jun 17, 2026 • Updated Jun 19, 2026
Catalog prep endpoints
These endpoints are not MPP-paid, but agents use them before validation:
| Purpose | Method and path |
|---|---|
| List categories | GET /api/flowers/categories |
| List products | GET /api/flowers/products?category=bs&count=18&start=1&sorttype=pa |
| List delivery dates | GET /api/flowers/delivery-dates?zipcode=32503 |
Product responses include Florist One fields such as CODE, NAME, PRICE, DESCRIPTION, SMALL, and LARGE. Treat PRICE as the arrangement price before delivery and tax. The validate endpoint is the source of truth for the final amount due.
MPP flower endpoints
| Purpose | Method and path |
|---|---|
| Validate product, ZIP, delivery date, and final quote | POST /api/machine/mpp/flower-letters/validate |
Create unpaid flower order, receive 402, and retry after MPP payment |
POST /api/machine/mpp/flower-letters |
| Poll payment and florist submission status | GET /api/machine/mpp/flower-letters/{id} |
Flow
- Choose the recipient delivery ZIP.
- List products and choose a product
CODE. - Fetch delivery dates for the recipient ZIP and choose a valid
delivery_date. - Build the flower-letter JSON body.
- Validate with
POST /api/machine/mpp/flower-letters/validate. - Show the final quote, including delivery and tax when present.
- Create the unpaid order with
POST /api/machine/mpp/flower-lettersand noAuthorizationheader. - Parse the
WWW-Authenticate: Payment ...challenges from the402response. - Pay one returned Tempo or Stripe SPT challenge.
- Retry the exact same create body and
request_idwithAuthorization: Payment <serialized-mpp-credential>. - Read
Payment-Receipt. - Poll
GET /api/machine/mpp/flower-letters/{id}untilpayment_statusispaid.
Required fields
Top-level fields:
request_id: UUID idempotency key.buyer_name: buyer or agent owner name.buyer_email: required for machine payment receipt delivery.note: recipient note, 1 to 200 characters.zipcode: recipient delivery ZIP; must matchrecipient.zipcode.product_code: selected Florist One productCODE.delivery_date: one returned by the delivery-dates endpoint.customer: sender object.recipient: delivery recipient object.allow_substitutions: optional, defaults totrue.special_instructions: optional, max 100 characters.
Address objects:
name: required.phone: required and must normalize to 10 US digits.address1: required.address2: optional.city: required.state: required two-letter state.zipcode: required ZIP.country: optional two-letter country; omit or useUS.
customer.email is optional and defaults to buyer_email.
recipient.institution is optional (max 100 characters); use it for a business, hospital, or office name at the delivery address.
Validate example
curl -sS https://postalform.com/api/machine/mpp/flower-letters/validate \
-H 'Content-Type: application/json' \
--json '{
"request_id": "0bc151ff-31a9-47a6-a0a4-2853cd75ff2a",
"buyer_name": "Agent Owner",
"buyer_email": "owner@example.com",
"note": "For your desk, your day, and the smile I hope this brings.",
"zipcode": "32503",
"product_code": "F1-509",
"delivery_date": "2026-07-03",
"customer": {
"name": "Agent Owner",
"phone": "8505550100",
"address1": "123 Sender St",
"city": "Pensacola",
"state": "FL",
"zipcode": "32503",
"country": "US"
},
"recipient": {
"name": "Recipient Example",
"phone": "8505550199",
"address1": "456 Recipient Ave",
"city": "Pensacola",
"state": "FL",
"zipcode": "32503",
"country": "US"
},
"allow_substitutions": true
}'
Expected validation shape:
{
"protocol": "mpp",
"methods": ["tempo", "stripe_spt"],
"product_type": "flower_letter",
"status": "validated_new_order",
"quote": {
"product": {
"code": "F1-509",
"priceCents": 4999
},
"total": {
"orderTotalCents": 6999,
"deliveryChargeCents": 1500,
"taxTotalCents": 500
}
}
}
For this guide, use tempo or stripe_spt.
Create and pay
Create the unpaid flower order using the same JSON body:
curl -i https://postalform.com/api/machine/mpp/flower-letters \
-H 'Content-Type: application/json' \
--json @mpp-flower-body.json
Expected unpaid response:
- HTTP status
402. X-Payment-Protocol: mpp.- One or more
WWW-Authenticate: Payment ...headers. - JSON body with payment-required details.
- Flower-specific
price_breakdownwhen final quote details are available.
Retry after paying one challenge:
curl -i https://postalform.com/api/machine/mpp/flower-letters \
-H 'Content-Type: application/json' \
-H 'Authorization: Payment <serialized-mpp-credential>' \
--json @mpp-flower-body.json
Expected paid response:
- HTTP status
200. Payment-Receiptheader.- JSON body with
order_id,payment_status,product_type: "flower_letter",payment_channel: "mpp_machine", andorder_complete_urlwhen available.
Stripe SPT requirements
For the Stripe challenge:
- Parse the Stripe challenge from
WWW-Authenticate. - Mint or obtain a buyer-approved
spt_...token for the exact amount, currency, and seller network id in the challenge. - Serialize the original challenge and
{ "spt": "..." }into an MPP credential. - Send the full serialized credential as
Authorization: Payment ....
Do not send only the bare spt_... token.
Tempo requirements
Tempo clients should parse the returned WWW-Authenticate: Payment ... challenge and retry with Authorization: Payment ....
mppx \
https://postalform.com/api/machine/mpp/flower-letters \
--account my-tempo-wallet \
--json-body "$(cat mpp-flower-body.json)" \
--include \
--verbose
Poll status
curl -sS https://postalform.com/api/machine/mpp/flower-letters/0bc151ff-31a9-47a6-a0a4-2853cd75ff2a
Status responses include:
awaiting_payment: unpaid flower order exists.settled_pending_submission: payment was accepted and florist submission is queued.paid: payment was accepted and submission processing has started.
Flower-specific rules
noteis printed with the flower delivery and must be 200 characters or fewer.zipcodemust be the recipient delivery ZIP and must matchrecipient.zipcode.- Validate final price before paying. Catalog
PRICEis not the final amount due. - PostalForm validates product, ZIP, delivery date, and total before issuing a payment challenge.
- PostalForm checks the delivery date again when submitting the paid order to Florist One.
- Machine flower totals are capped. If validation returns
amount_exceeds_limit, choose a lower-priced arrangement. - Use a fresh
request_idfor a different flower delivery.
Flower-specific errors
422 invalid_request: fix schema validation issues.422 invalid_flower_order: product, ZIP, date, address, or final quote validation failed.409 request_id_mismatch: the samerequest_idwas reused with a different flower payload.422 missing_buyer_email: add a validbuyer_email.402 payment_required: normal MPP challenge response.429 rate_limited: wait before creating more unpaid drafts.
Related MPP docs
- All MPP endpoints:
https://postalform.com/mpp.md - Mail-only MPP guide:
https://postalform.com/mpp-mail.md - OpenAPI:
https://postalform.com/openapi.json