Open Markets Protocol

Payments

Merchant preferences, manual and direct flows, payment requests, receipts, wallet execution, and proof verification.

Scope

Open Markets separates four concerns:

  1. An offer states a price.
  2. An order proposes a purchase.
  3. A payment request states what the merchant will accept for that order.
  4. A payment receipt carries evidence that the buyer paid.

Payment messages are private unsigned rumors transported with the envelope defined in Orders. This specification preserves Gamma's deployed wire allocation: payment requests are kind 16, type 2; payment receipts are kind 17.

Merchant preferences

A merchant MAY publish one payment_preference tag in their kind 0 profile:

["payment_preference", "manual"]
["payment_preference", "ecash"]
["payment_preference", "lud16"]
ValueMeaning
absentUse the manual flow
manualWait for a merchant-authored payment request
ecashA direct eCash flow may be offered
lud16A direct LNURL/Lightning flow may be offered
unknownDo not guess; fall back to manual

Open Gamma PR #2 proposed replacing these values with service, lightning, and bitcoin, changing the default, and moving receipts into kind 16. Open Markets incorporates its useful three-flow model but rejects those incompatible wire changes.

Before checkout, a client SHOULD automatically resolve:

  • the merchant's kind 0 payment preference;
  • merchant-authored NIP-89 kind 31989 application recommendations;
  • the referenced kind 31990 application descriptor;
  • required payment metadata such as lud16 or preferred Cashu mint information.

The merchant's signature on kind 31989 establishes a recommendation. A standalone application descriptor or client tag does not. Recommendations affect routing and UX; they do not authorize software to sign for either party.

Processing flows

Manual

Manual is the default and most compatible flow:

  1. Buyer sends a kind 16, type 1 order.
  2. Merchant MAY acknowledge it as pending.
  3. Merchant calculates the final amount and sends kind 16, type 2.
  4. Buyer validates and pays one option.
  5. Buyer sends kind 17 with payment evidence.
  6. Merchant verifies the proof independently.
  7. Merchant sends kind 16, type 3, confirmed.

Direct

Direct payment is available only when the merchant has published sufficient compatible payment information:

  1. Buyer resolves ecash or lud16 preference data.
  2. Buyer creates the order and obtains or constructs valid payment material.
  3. Buyer pays without waiting for a merchant-authored request.
  4. Buyer sends a normal kind 17 receipt.
  5. Merchant verifies payment and sends confirmed.

direct is a flow classification, not a payment_preference wire value.

Service-assisted

A merchant-recommended application MAY facilitate either flow. The service can calculate totals, construct a payment request, monitor payment, or help construct a receipt. The user remains the author of user-authored rumors unless separate explicit authority exists.

A buyer-authored type 2 rumor is permitted only as service-assisted payment initiation when the merchant has explicitly recommended the service, the kind 31990 handler declares compatible support, and the merchant can independently validate its amount and payment details. It MUST NOT be presented as a merchant-authored request.

Payment request

A payment request is normally authored by the merchant and addressed to the buyer.

Schema

TagCardinalityMeaning
pexactly 1Buyer public key
subjectexactly 1Recommended value order-payment
typeexactly 12
orderexactly 1Original order identifier
amountexactly 1Final total in integer satoshis
payment1 or moreAlternative payment option
expiration0 or 1Request expiry in Unix seconds
client0 or 1Optional NIP-89 attribution

Supported payment option shapes include:

["payment", "lightning", "<bolt11-invoice-or-lud16>"]
["payment", "bitcoin", "<bitcoin-address>"]
["payment", "ecash", "<cashu-payment-request>"]
["payment", "<medium>", "<medium-specific-request>"]

Repeated payment tags are alternatives. This protocol does not define split payment across them.

Example

{
  "id": "<rumor-id>",
  "pubkey": "<merchant-pubkey>",
  "created_at": 1786953600,
  "kind": 16,
  "tags": [
    ["p", "<buyer-pubkey>"],
    ["subject", "order-payment"],
    ["type", "2"],
    ["order", "a47e7fbb3a8f4f98a31d88b3f7703567"],
    ["amount", "21000"],
    ["payment", "lightning", "lnbc210u1..."],
    ["payment", "bitcoin", "bc1q..."],
    ["expiration", "1786954500"]
  ],
  "content": "Choose one payment option before the request expires."
}

The optional expiration tag is retained from merged Gamma PR #4. A client MUST NOT pay an expired request. When native payment material expires earlier, such as a BOLT11 invoice, the earlier expiry wins.

Request validation

Before presenting or paying a request, a client MUST:

  1. Validate the NIP-17 envelope, author, recipient, order identity, and tag cardinality.
  2. Require amount to be a non-negative base-10 integer in satoshis.
  3. Confirm that the request corresponds to an existing order between the same buyer and merchant.
  4. Display material differences between the order proposal and payment request.
  5. Validate each payment option before use.
  6. Reject expired requests.

For BOLT11, the encoded amount MUST equal amount × 1000 millisatoshis when the invoice specifies an amount. For lud16, the client MUST resolve LNURL-pay and validate the returned invoice. A Lightning address is a destination, not an amount-bound invoice.

A newer payment request does not automatically invalidate every earlier request. Clients SHOULD detect multiple valid requests for one order and require confirmation when their amount or destination differs.

Payment receipt

A receipt is a kind 17 rumor authored by the buyer and addressed to the merchant. It is a payment claim with evidence, not settlement by itself.

Schema

TagCardinalityMeaning
pexactly 1Merchant public key
subjectexactly 1Recommended value order-receipt
orderexactly 1Original order identifier
amountexactly 1Amount paid in integer satoshis
payment1 or morePayment proof
client0 or 1Optional NIP-89 attribution

Proof forms:

["payment", "lightning", "<invoice>", "<preimage>"]
["payment", "bitcoin", "<receiving-address>", "<transaction-id>"]
["payment", "ecash", "<mint-url>", "<token-or-proof>"]
["payment", "fiat", "<provider-reference>", "<provider-proof>"]
["payment", "<medium>", "<medium-reference>", "<proof>"]
{
  "id": "<rumor-id>",
  "pubkey": "<buyer-pubkey>",
  "created_at": 1786953660,
  "kind": 17,
  "tags": [
    ["p", "<merchant-pubkey>"],
    ["subject", "order-receipt"],
    ["order", "a47e7fbb3a8f4f98a31d88b3f7703567"],
    ["amount", "21000"],
    ["payment", "lightning", "lnbc210u1...", "<32-byte-preimage-hex>"]
  ],
  "content": "Lightning payment completed."
}

Receiving a syntactically valid receipt MUST NOT automatically confirm the order. The merchant confirms only after independent verification.

Proof verification

Lightning

The merchant MUST decode the invoice, verify its network and amount, calculate SHA256(preimage), and require it to equal the invoice payment hash. A preimage is stronger evidence than a screenshot or a receipt event alone.

Bitcoin

The merchant MUST verify the transaction on the intended network, destination output, amount, transaction status, and application-defined confirmation depth. A transaction ID without a matching output is insufficient.

Ecash

Cashu material is bearer value. The merchant MUST validate and redeem proofs with the intended mint and MUST prevent replay. Merely receiving an ecash string does not establish settlement.

Fiat

Open Markets defines no universal fiat proof. The merchant MUST verify the provider reference with the provider or another trusted settlement source. Opaque text and screenshots are not machine-verifiable proof.

Nostr Wallet Connect

NIP-47 controls the payer's wallet; it does not replace an Open Markets payment request or receipt.

For Lightning execution:

  1. Obtain and validate a BOLT11 invoice from the request or LNURL callback.
  2. Send NWC pay_invoice as kind 23194 using the dedicated connection key.
  3. Validate the kind 23195 response and require result_type=pay_invoice.
  4. Use the returned preimage in the buyer's kind 17 receipt.

NWC uses millisatoshis while Open Markets uses satoshis:

nwc_amount_msat == open_markets_amount_sat × 1000

Clients MUST NOT publish or include the NWC URI, connection secret, wallet authorization, or encrypted NWC payload in an order rumor.

Lightning zaps

NIP-57 MAY provide an invoice and public zap receipt when a merchant's LNURL endpoint supports it. Clients MUST validate the zap receipt signer, embedded request, description hash, amount, recipient, and LNURL.

A kind 9735 zap receipt is supplemental evidence and does not replace kind 17. NIP-57 explicitly notes that a zap receipt is not cryptographic proof that a real invoice was paid. A verified preimage remains preferable.

Client attribution

Payment requests and receipts MAY include the NIP-89 client tuple. Software SHOULD include it when attribution is enabled and MUST offer an opt-out. The tag helps debugging and deep-linking but MUST NOT be used as evidence of authorization, merchant recommendation, or payment validity.

PR #2 compatibility decisions

Open Markets incorporates every compatible intent from Gamma PR #2 while preserving deployed semantics.

PR #2 proposalOpen Markets decision
Direct, manual, and service flowsAdopted as behavioral profiles
Replace manual with serviceRejected; manual and its default remain
Add lightning and bitcoin preferencesNot added to the current enum; methods remain payment options
Move receipts into kind 16, type 2Rejected; kind 17 remains independently filterable
Rename shipping to shipping_optionRejected for order-message compatibility
Make fixed subjects mandatoryRewritten as recommended conventional subjects
Change ecash receipt tuple orderRejected; mint URL remains before proof
Improve flow explanationsAdopted throughout this page

This is a deliberate reconciliation, not an accidental partial merge. It follows the later PR discussion favoring separate business messages and receipts for retrieval, accountability, and UX.

Security requirements

  • Payment material MUST stay inside encrypted rumors.
  • Clients MUST validate authorship, recipient role, order identity, amounts, and expiration before payment.
  • Receipts MUST be deduplicated by rumor ID and proof identity.
  • A receipt, client tag, NIP-89 recommendation, or zap receipt MUST NOT be treated as settlement authority.
  • Implementations MUST prevent eCash replay and protect bearer proofs at rest.
  • Wallet operations SHOULD use connection-specific keys and least-privilege budgets.
  • Users MUST see the amount, currency conversion, payment destination, and relevant expiry before approval.

Sources