---
title: PostalForm MPP flower endpoint instructions
description: 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.
seotitle: PostalForm MPP flower endpoint instructions
seo-description: Agent instructions for using PostalForm MPP flower-letter endpoints to validate, pay for, and track florist delivery with a recipient note.
group: resources
indexable: true
llms: true
nav: false
schema: webpage
eyebrow: MPP flowers
published: 2026-06-17T00:00:00+00:00
updated: 2026-06-19T00:00:00+00:00
path: /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.

## 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
1. Choose the recipient delivery ZIP.
2. List products and choose a product `CODE`.
3. Fetch delivery dates for the recipient ZIP and choose a valid `delivery_date`.
4. Build the flower-letter JSON body.
5. Validate with `POST /api/machine/mpp/flower-letters/validate`.
6. Show the final quote, including delivery and tax when present.
7. Create the unpaid order with `POST /api/machine/mpp/flower-letters` and no `Authorization` header.
8. Parse the `WWW-Authenticate: Payment ...` challenges from the `402` response.
9. Pay one returned Tempo or Stripe SPT challenge.
10. Retry the exact same create body and `request_id` with `Authorization: Payment <serialized-mpp-credential>`.
11. Read `Payment-Receipt`.
12. Poll `GET /api/machine/mpp/flower-letters/{id}` until `payment_status` is `paid`.

## 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 match `recipient.zipcode`.
- `product_code`: selected Florist One product `CODE`.
- `delivery_date`: one returned by the delivery-dates endpoint.
- `customer`: sender object.
- `recipient`: delivery recipient object.
- `allow_substitutions`: optional, defaults to `true`.
- `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 use `US`.

`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
```bash
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:

```json
{
  "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:

```bash
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_breakdown` when final quote details are available.

Retry after paying one challenge:

```bash
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-Receipt` header.
- JSON body with `order_id`, `payment_status`, `product_type: "flower_letter"`, `payment_channel: "mpp_machine"`, and `order_complete_url` when available.

## Stripe SPT requirements
For the Stripe challenge:

1. Parse the Stripe challenge from `WWW-Authenticate`.
2. Mint or obtain a buyer-approved `spt_...` token for the exact amount, currency, and seller network id in the challenge.
3. Serialize the original challenge and `{ "spt": "..." }` into an MPP credential.
4. 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 ...`.

```bash
mppx \
  https://postalform.com/api/machine/mpp/flower-letters \
  --account my-tempo-wallet \
  --json-body "$(cat mpp-flower-body.json)" \
  --include \
  --verbose
```

## Poll status
```bash
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
- `note` is printed with the flower delivery and must be 200 characters or fewer.
- `zipcode` must be the recipient delivery ZIP and must match `recipient.zipcode`.
- Validate final price before paying. Catalog `PRICE` is 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_id` for 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 same `request_id` was reused with a different flower payload.
- `422 missing_buyer_email`: add a valid `buyer_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`
