XEP-xxxx: Payment Required

Abstract
This specification defines an XMPP protocol extension that enables services to require payment before granting access to a resource. It provides a payment-system neutral invoice format supporting multiple concurrent payment options, including bank transfers (SEPA, IBAN, UPI) and instant-settlement networks (Lightning Network), and integrates with the existing CAPTCHA challenge mechanism defined in XEP-0158.
Author
JC Brand
Copyright
© 2026 – 2026 XMPP Standards Foundation. SEE LEGAL NOTICES.
Status

ProtoXEP

WARNING: This document has not yet been accepted for consideration or approved in any official manner by the XMPP Standards Foundation, and this document is not yet an XMPP Extension Protocol (XEP). If this document is accepted as a XEP by the XMPP Council, it will be published at <https://xmpp.org/extensions/> and announced on the <standards@xmpp.org> mailing list.
Type
Standards Track
Version
0.0.1 (2026-04-23)
Document Lifecycle
  1. Experimental
  2. Proposed
  3. Stable
  4. Final

1. Introduction

This XEP provides a mechanism for XMPP services to require payment before access to their resources or functionality is granted. Use cases include charging for account registration or hosting, compensating operators of AI agents or bots for compute costs, monetizing file hosting services per upload or download, requiring an entry fee for access to a Multi-User Chat (XEP-0045) [1] room, and requiring a small payment from users not already in a contact's roster as a proof-of-intent mechanism to deter unsolicited messages.

Existing XMPP anti-spam work (CAPTCHA Forms (XEP-0158) [2]) defines robot challenges using either image/audio CAPTCHAs or hashcash proof-of-work tokens. This specification extends that concept by adding a payment-required challenge type that follows the same challenge-retry flow, while independently defining a richer invoice format suitable for both human and automated payers.

Protocols such as Publish-Subscribe (XEP-0060) [3] already acknowledge that services may require payment for operations (e.g., node subscriptions or item retrieval) but leave the payment mechanism out-of-band. This specification provides the in-band protocol to fulfill that need.

The design is informed by analogous protocols in the HTTP ecosystem: the long-reserved HTTP 402 Payment Required status code; the L402 protocol published by Lightning Labs, in which a client receives a WWW-Authenticate header containing a macaroon token and a Lightning invoice and presents a token-preimage credential after payment; and the x402 protocol published by Coinbase et al., in which a client receives an HTTP 402 response with a PAYMENT-REQUIRED header listing accepted payment schemes and retries with a PAYMENT-SIGNATURE header; and the Machine Payments Protocol (MPP) published by Stripe and Tempo, an IETF-tracked open standard for machine-to-machine payments that similarly uses HTTP 402 challenges with multi-method selection, machine-readable error codes, payment receipts, and cryptographic challenge binding.

The conceptual parallels shared by all four are:

  1. a service declines a request and presents payment instructions in-band;
  2. the client completes payment and retries, optionally supplying a proof-of-payment token;
  3. multiple simultaneously valid payment options MAY be presented so that the client can choose the most suitable scheme.

This specification is payment-system agnostic. A service MAY require payment exclusively via bank transfer, exclusively via an instant-settlement network, or via any combination thereof. No payment scheme is privileged over any other at the protocol level.

2. Requirements

This specification was designed with the following requirements in mind:

3. Glossary

Payer
The XMPP entity that receives a payment-required error and is expected to fulfill the payment. Typically this is the originating client.
Payee / Service
The XMPP entity that requires payment before granting access to a resource. This may be a server component, a MUC service, a bot, or any other XMPP service.
Invoice
A structured XML element, defined in this specification, that conveys one or more payment options to a payer.
Payment Option
A single, self-contained description of one method by which payment may be made (e.g., a SEPA bank transfer, a UPI payment request, a Lightning Network invoice).
Proof of Payment
A token supplied by the payer on retry to demonstrate that a payment has been made. The format depends on the payment scheme used (e.g., a Lightning Network payment preimage, a bank transaction reference number).
Payment Session
A short-lived, service-generated identifier that correlates a payment-required error with the subsequent retry stanza, analogous to a session identifier in Ad-Hoc Commands (XEP-0050) [5].

4. Use Cases

4.1 Paid MUC Room Entry with Multiple Payment Options

Juliet operates a premium conference room on conference.shakespeare.lit that charges an entry fee. Romeo attempts to join but is declined and presented with invoice options spanning both traditional banking and an instant-settlement network.

Example 1. Romeo attempts to join a paid MUC room
<presence from='romeo@shakespeare.lit/orchard'
          to='upperroom@conference.shakespeare.lit/Romeo'>
  <x xmlns='http://jabber.org/protocol/muc'/>
</presence>
Example 2. The MUC service declines with a payment-required error
<presence from='upperroom@conference.shakespeare.lit'
          to='romeo@shakespeare.lit/orchard'
          type='error'>
  <error type='auth'>
    <payment-required xmlns='urn:xmpp:payment:0'/>
    <text xml:lang='en'
          xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'>
      An entry fee of EUR 5.00 is required to join this room.
    </text>
    <invoice expires='2026-04-19T14:00:00Z'
             purpose='Premium room monthly entry'
             session='c4a1f902-7d3b-4e8c-a510-2f9b0e6d3178'
             xmlns='urn:xmpp:payment:0'>
      <description>
        Pay once per calendar month. Include your JID as the payment
        reference so your access can be confirmed promptly.
      </description>
      <option amount='EUR:5.00'
              label='Bank transfer (SEPA)'
              scheme='payto'>payto://iban/DE02200400300200270112?amount=EUR:5.00&amp;message=upperroom-c4a1f902&amp;receiver-name=Capulet+Hosting</option>
      <option amount='INR:450'
              label='UPI'
              scheme='payto'>payto://upi/capulethosting@examplebank?amount=INR:450&amp;message=upperroom-c4a1f902&amp;receiver-name=Capulet+Hosting
        <display-amount>&#x20B9; 450</display-amount>
      </option>
      <option amount='EUR:5.00'
              label='Lightning Network (instant)'
              scheme='lightning-bolt11'>lnbc50n1pn2s4czpp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypq
        <display-amount>EUR 5.00 via Lightning</display-amount>
      </option>
    </invoice>
  </error>
</presence>
Example 3. Romeo retries after paying by SEPA bank transfer
<presence from='romeo@shakespeare.lit/orchard'
          to='upperroom@conference.shakespeare.lit/Romeo'>
  <x xmlns='http://jabber.org/protocol/muc'/>
  <payment scheme='payto'
           session='c4a1f902-7d3b-4e8c-a510-2f9b0e6d3178'
           xmlns='urn:xmpp:payment:0'>
    <proof type='reference'>NOTPROVIDED20260419DE02</proof>
  </payment>
</presence>
Example 4. Romeo alternatively retries after paying via Lightning
<presence from='romeo@shakespeare.lit/orchard'
          to='upperroom@conference.shakespeare.lit/Romeo'>
  <x xmlns='http://jabber.org/protocol/muc'/>
  <payment scheme='lightning-bolt11'
           session='c4a1f902-7d3b-4e8c-a510-2f9b0e6d3178'
           xmlns='urn:xmpp:payment:0'>
    <proof type='lightning-preimage'>a8f3e1d2b4c9078564fae012cc3d99a1b5e7d0f3a2c81496057832bd7e4f0c1a</proof>
  </payment>
</presence>

Because SEPA bank transfers may take time to settle, the service SHOULD set a generous session expiry for bank-transfer options and MAY grant access provisionally upon receiving the retry stanza, subsequently revoking it if reconciliation fails.

4.2 Per-Message Fee for an AI Agent Bot

Balthasar operates a news-summary bot that charges per query. Because the amounts are small and latency matters, only instant-settlement options are offered. This is a service-level policy decision, not a protocol constraint.

Example 5. Romeo sends a message to the bot
<message from='romeo@shakespeare.lit/orchard'
         id='msg-001'
         to='newssummary@bots.shakespeare.lit'
         type='chat'>
  <body>Summarize today's news from Verona.</body>
</message>
Example 6. The bot declines with a payment-required error
<message from='newssummary@bots.shakespeare.lit'
         id='msg-001'
         to='romeo@shakespeare.lit/orchard'
         type='error'>
  <body>Summarize today's news from Verona.</body>
  <error type='auth'>
    <payment-required xmlns='urn:xmpp:payment:0'/>
    <text xml:lang='en'
      xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'>
      A payment of 10 sats is required per query.
    </text>
    <invoice expires='2026-03-19T14:20:00Z'
             purpose='Per-query fee'
             session='a3f7c291-84d0-4b2e-9b1a-0f3e2d1c5678'
             xmlns='urn:xmpp:payment:0'>
      <option amount='SAT:10'
          label='Lightning (instant, automated)'
          scheme='lightning-bolt11'>lnbc100n1pn2s3dzpp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypq
        <display-amount>10 sats</display-amount>
      </option>
      <option amount='SAT:10'
              label='BOLT 12 offer'
              scheme='lightning-bolt12'>lno1qgsyz4uzesxqcyq5rqwzqfqpqdynf
        <display-amount>10 sats</display-amount>
      </option>
    </invoice>
  </error>
</message>
Example 7. Romeo retries after paying via Lightning
<message from='romeo@shakespeare.lit/orchard'
         id='msg-002'
         to='newssummary@bots.shakespeare.lit'
         type='chat'>
  <body>Summarize today's news from Verona.</body>
  <payment scheme='lightning-bolt11'
           session='a3f7c291-84d0-4b2e-9b1a-0f3e2d1c5678'
           xmlns='urn:xmpp:payment:0'>
    <proof type='lightning-preimage'>a8f3e1d2b4c9078564fae012cc3d99a1b5e7d0f3a2c81496057832bd7e4f0c1a</proof>
  </payment>
</message>
Example 8. The bot fulfills the request and returns a payment receipt
<message from='newssummary@bots.shakespeare.lit'
         id='msg-003'
         to='romeo@shakespeare.lit/orchard'
         type='chat'>
  <body>Today in Verona: the Montagues and Capulets have agreed to a temporary truce...</body>
  <receipt reference='a8f3e1d2b4c9078564fae012cc3d99a1b5e7d0f3a2c81496057832bd7e4f0c1a'
           scheme='lightning-bolt11'
           session='a3f7c291-84d0-4b2e-9b1a-0f3e2d1c5678'
           settled='2026-03-20T09:01:14Z'
           xmlns='urn:xmpp:payment:0'/>
</message>

4.3 Anti-Spam Deposit for Non-Roster Contacts

Juliet's server requires a small deposit from senders not present in her roster, as a proof-of-intent mechanism to deter unsolicited messages. Instant-settlement options are used because slow bank transfers would allow queuing before verification.

Example 9. An unknown sender is declined pending a deposit
<message from='juliet@shakespeare.lit'
         id='spam-001'
         to='stranger@othello.lit/mobile'
         type='error'>
  <body>Buy cheap goblets!</body>
  <error type='auth'>
    <payment-required xmlns='urn:xmpp:payment:0'/>
    <text xml:lang='en'
          xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'>
      A small deposit is required to message this user for the first time.
      The deposit will be refunded if the recipient accepts your contact request.
    </text>
    <invoice expires='2026-03-19T16:01:00Z'
             purpose='First-contact anti-spam deposit'
             session='f1c3d9e2-7a04-4b8f-a629-3e0d15b7c412'
             xmlns='urn:xmpp:payment:0'>
      <option amount='SAT:10'
              label='Lightning deposit'
              scheme='lightning-bolt11'>lnbc100n1pn2s5azpp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypq
        <display-amount>10 sats</display-amount>
      </option>
    </invoice>
  </error>
</message>

4.4 Proactive Invoice Request

A client MAY proactively request an invoice from a service before sending the gated stanza. This is useful when the client wishes to present payment options to the user before committing to an action. Before sending a proactive invoice request, the client SHOULD discover whether the service supports this feature by querying for the 'urn:xmpp:payment:0#invoice-request' feature via Service Discovery (XEP-0030) [4].

Example 10. Romeo requests an invoice before attempting to join
<iq from='romeo@shakespeare.lit/orchard'
    id='inv-001'
    to='conference.shakespeare.lit'
    type='get'>
  <get-invoice service='muc-entry'
               target='upperroom@conference.shakespeare.lit'
               xmlns='urn:xmpp:payment:0'/>
</iq>
Example 11. The service returns an invoice
<iq from='conference.shakespeare.lit'
    id='inv-001'
    to='romeo@shakespeare.lit/orchard'
    type='result'>
  <invoice expires='2026-04-19T14:00:00Z'
           purpose='Premium room monthly entry'
           session='3c91b2e4-6f07-4a2d-b839-5e0f17d9c823'
           xmlns='urn:xmpp:payment:0'>
    <option amount='EUR:5.00'
            label='Bank transfer (SEPA)'
            scheme='payto'>payto://iban/DE02200400300200270112?amount=EUR:5.00&amp;message=3c91b2e4&amp;receiver-name=Capulet+Hosting</option>
    <option amount='EUR:5.00'
            label='Lightning (instant)'
            scheme='lightning-bolt11'>lnbc50n1pn2s4czpp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypq
      <display-amount>EUR 5.00</display-amount>
    </option>
  </invoice>
</iq>

If the service does not support proactive invoice requests, it SHOULD return a <feature-not-implemented/> error of type "cancel".

4.5 Payment Challenge as Alternative to CAPTCHA

This specification extends CAPTCHA Forms (XEP-0158) [2] by defining a new challenge field type that carries a payment invoice, allowing a service to offer payment as an alternative to solving a CAPTCHA.

To embed a payment invoice within a CAPTCHA Forms (XEP-0158) [2] challenge, the challenger SHOULD include a field with var='urn:xmpp:payment:0' inside the Data Form. The invoice is transmitted as a sibling element to the <x/> element in the same stanza.

Example 12. A service offers payment as an alternative to a CAPTCHA
<message from='security.shakespeare.lit'
         id='challenge-001'
         to='romeo@shakespeare.lit/orchard'>
  <x type='form' xmlns='jabber:x:data'>
    <title>Verify your intent</title>
    <field type='hidden' var='FORM_TYPE'>
      <value>urn:xmpp:captcha</value>
    </field>
    <field type='hidden' var='challenge'>
      <value>challenge-abc-123</value>
    </field>
    <field label='Enter the text you see:'
           type='text-single'
           var='ocr'>
      <media xmlns='urn:xmpp:media-element'>
        <uri type='image/jpeg'>https://security.shakespeare.lit/captcha/abc123.jpg</uri>
      </media>
      <required/>
    </field>
    <field label='Or pay the verification fee (enter session ID after payment):'
           type='text-single'
           var='urn:xmpp:payment:0'/>
  </x>
  <invoice expires='2026-03-19T14:30:00Z'
           purpose='Account verification fee'
           session='9d4e2c01-5b8f-4a3e-b796-0f1e28d7c589'
           xmlns='urn:xmpp:payment:0'>
    <option amount='EUR:0.01'
            label='Bank transfer (SEPA)'
            scheme='payto'>payto://iban/DE02200400300200270112?amount=EUR:0.01&amp;message=9d4e2c01
      <display-amount>EUR 0.01</display-amount>
    </option>
    <option amount='EUR:0.01'
            label='Lightning'
            scheme='lightning-bolt11'>lnbc10p1pn2s6azpp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypq
      <display-amount>EUR 0.01</display-amount>
    </option>
  </invoice>
</message>

5. Protocol

5.1 Namespace

This specification uses the namespace 'urn:xmpp:payment:0'. (see Namespace Versioning regarding the possibility of incrementing the version number)

5.2 Elements

The following elements are defined in the 'urn:xmpp:payment:0' namespace.

5.2.1 The invoice Element

The <invoice/> element is the container for all payment options associated with a single payment event. It MUST contain at least one <option/> child element and MAY contain a <description/> child element whose character data provides additional human-readable context.

The <invoice/> element possesses the following attributes:

5.2.2 The option Element

Each <option/> element describes one complete, self-contained payment method. The payer MUST use exactly one option to fulfill the invoice.

The character data of the <option/> element is the scheme-specific payment payload string (see Payment Schemes Registry).

The <option/> element possesses the following attributes:

The <option/> element MAY contain a <display-amount/> child element. This element contains a locale-appropriate human-readable string representing the amount for the option, making no assumption about which currency or payment system is primary. Examples: "EUR 5.00", "₹ 450", "R 18.50", "USD 0.001", "1 000 sat". Services SHOULD include <display-amount/> when the amount is not self-evident from the payload string.

5.2.3 The payment Element

The <payment/> element is added by the payer as an extension to the retried stanza to indicate that a payment has been made for the referenced session.

The <payment/> element possesses the following attributes:

The <payment/> element MAY contain a <proof/> child element. The <proof/> element possesses a required 'type' attribute identifying the proof format (see Proof Types Registry), and its character data is the proof token.

5.2.4 The payment-required Element

The <payment-required/> element is an application-specific stanza error condition. It is used as a child of the <error/> element to indicate that the requested action requires payment before it can be fulfilled.

The <payment-required/> element possesses one OPTIONAL attribute:

Table 1: Registered reason Codes
Value Meaning
payment-required No <payment/> element was present. The resource requires payment before access is granted.
invalid-session The 'session' value is unknown, has already been consumed, or does not match the HMAC verification check.
payment-expired The invoice has passed its 'expires' time and may no longer be honored. The payer SHOULD request a fresh invoice.
verification-failed A <proof/> element was present but the proof could not be verified as valid for the referenced payment.
payment-insufficient The payment amount detected was less than the required amount.
scheme-unsupported The 'scheme' value in the <payment/> element is not accepted by this service.

5.2.5 The receipt Element

The <receipt/> element MAY be included by a service in the successful response to a retried stanza to provide the payer with a machine-readable record of the settled payment. It is an OPTIONAL protocol element; its absence does not indicate that payment failed.

The <receipt/> element possesses the following attributes:

A service that supports emitting receipts SHOULD advertise the feature 'urn:xmpp:payment:0#receipt' via Service Discovery (XEP-0030) [4].

5.2.6 The get-invoice Element

The <get-invoice/> element is the payload of a proactive invoice request. It is sent as the child of an IQ-get stanza and possesses the following attributes:

5.3 Error Flow

When a service requires payment for an action, it MUST respond to the triggering stanza with an error of type "auth" containing the <payment-required/> application condition element qualified by 'urn:xmpp:payment:0', and MUST include an <invoice/> element as a sibling of the error condition element within the <error/> element.

The "auth" error type is appropriate because the payer has not yet demonstrated authorization (via payment) to access the resource. The <payment-required/> application condition distinguishes this case from <not-authorized/> and <registration-required/>.

If the requesting entity is not authenticated at all (e.g., it has not completed SASL authentication with its own server, or its JID cannot be verified), the service SHOULD return a <not-authorized/> error rather than a <payment-required/> error. Payment challenges SHOULD only be issued to entities whose identity can be established, to prevent anonymous entities from exploiting the payment flow to probe service behavior.

The service SHOULD include a human-readable <text/> child within the <error/> element describing the reason for the payment requirement.

When a <payment/> element is present on a retried stanza but verification fails, the service SHOULD return a <not-acceptable/> error of type "modify" containing a <payment-required/> element with an appropriate 'reason' attribute (see The payment-required Element), and MAY include a new <invoice/> element to allow the payer to retry with a fresh payment. Using a machine-readable 'reason' value allows automated agents to distinguish between a recoverable failure (e.g., 'payment-expired', which warrants requesting a new invoice) and a non-recoverable one (e.g., 'verification-failed', which warrants escalating to the user).

5.4 Verification

The mechanism by which a service verifies that a payment has been made is outside the scope of this specification. The following non-normative guidance is provided for implementors.

For bank transfers (SEPA, IBAN, UPI, PIX, SWIFT, etc.), the service typically cannot verify payment in real time. The service SHOULD encode the session identifier as the payment reference in the payto URI (the 'message' or 'instruction' query parameter) and reconcile incoming payments against outstanding sessions via its bank's API or statement-import mechanism. Because bank transfers can take from seconds (SEPA Instant) to days (SWIFT) to settle, bank transfer options are best suited to one-time access grants such as account registration or monthly subscriptions rather than per-message micropayments.

For Lightning Network payments, the service MAY verify payment by stateless preimage verification: if the payment hash is encoded in the session identifier, the service verifies that SHA-256(preimage) matches the payment hash without querying external state. Alternatively, the service MAY query its own Lightning node for a settled invoice.

A facilitator service MAY issue an opaque bearer token after verifying payment. The token can be used across multiple retried stanzas within its validity period, enabling a "pay once, use many times" pattern. The format and lifecycle of such tokens is outside the scope of this specification.

A service MUST NOT accept the same session identifier more than once. Once a session is consumed, the service MUST invalidate it. A service MUST NOT honor a session after the time specified in the 'expires' attribute.

6. Business Rules

The following rules apply to implementations of this specification.

6.1 Service Behavior

6.2 Client Behavior

7. Implementation Notes

The 'payto' URI scheme (RFC 8905) is the RECOMMENDED primary URI scheme for this specification because it covers the widest range of payment networks within a single IETF-standardized format. Examples of valid payto URIs include:

Implementations MAY also use the European Payments Council (EPC) QR code format for SEPA Credit Transfers (the 'epc-qr' scheme) as an alternative for European users, particularly in countries where this format is already widely deployed (Austria, Belgium, Finland, Germany, Netherlands).

When generating Lightning Network invoices for inclusion in an <option/> element, the service SHOULD encode the payment hash in a way that allows stateless preimage verification (see Verification), avoiding the need to query the Lightning node on every retry.

8. Accessibility Considerations

Clients MUST NOT present a payment interface as the sole means of completing an action where an accessibility-equivalent alternative exists. Where a service also offers a CAPTCHA Forms (XEP-0158) [2] CAPTCHA challenge, the payment option and the CAPTCHA option SHOULD be presented with equal prominence.

When rendering URI-based payment options as QR codes, clients SHOULD also present the underlying URI as selectable text so that users of screen readers or other assistive technologies can copy and use it directly.

9. Internationalization Considerations

The 'purpose' attribute of <invoice/> and the 'label' attribute of <option/> are human-readable strings. Services SHOULD provide these in the language of the recipient where known. Multiple language variants MAY be provided using the standard 'xml:lang' attribute on any element containing character data.

The 'amount' attribute uses machine-readable RFC 8905 notation (currency:unit.fraction) rather than locale-formatted strings to avoid locale-dependent parsing errors. Human-formatted amounts SHOULD be derived by the client from the machine-readable value. The <display-amount/> element MAY carry a pre-formatted string if the service wishes to control presentation, but clients SHOULD treat this as advisory only.

ISO 4217 currency codes MUST be used for all standard currencies. Non-ISO identifiers (e.g., BTC, msat) MAY be used for assets not covered by ISO 4217.

10. Security Considerations

The following security considerations apply to implementations of this specification.

10.1 Replay Attacks

Session identifiers MUST be unique and single-use. A service MUST maintain a record of consumed session identifiers for at least as long as the invoice expiry window to prevent replay attacks. Reusing a session identifier to obtain multiple access grants MUST be rejected.

10.2 Session Binding

Because XMPP servers routinely mutate stanzas in transit — adding elements such as <delay/>, rewriting the 'from' attribute, injecting stream management acknowledgements, and normalizing namespace prefixes — it is not possible for a service to cryptographically bind an invoice to the byte content of the stanza it declined. Body-level hashing, as used by HTTP-based payment protocols, is therefore not applicable in XMPP.

Instead, services SHOULD bind the 'session' attribute value to the parameters of the invoice itself using a keyed hash (HMAC). The RECOMMENDED input to the HMAC is the concatenation of: the service's JID, the 'purpose' value, the 'expires' value, and the total amount per scheme. Where the invoice was issued in response to a proactive <get-invoice/> request whose 'target' attribute identifies a specific resource (e.g., a content hash, a file identifier, or a room JID), the 'target' value SHOULD also be included as an HMAC input. This binds the session to the specific resource being purchased, so that a client cannot present a session identifier paid for resource A to obtain access to resource B.

Upon receiving a retried stanza, the service SHOULD recompute the HMAC over the same inputs and compare it against the received 'session' value. A session value that does not match MUST be rejected. This mechanism does not depend on any property of the client-supplied stanza, and therefore survives any server-side stanza mutation in transit.

10.3 Invoice Tampering

An intermediary XMPP server could modify <invoice/> contents in transit, redirecting payment destinations to attacker-controlled accounts. Implementations SHOULD use end-to-end encryption (e.g., OMEMO Encryption (XEP-0384) [7]) when the integrity of invoice contents is critical. For Lightning Network options, stateless preimage verification protects the service from granting access without payment: because the session identifier is bound to the payment hash (see Session Binding), a tampered invoice would yield a preimage that fails verification. This does not protect the payer, who may still send funds to an attacker; end-to-end encryption is required for that.

For traditional bank transfer options, no equivalent cryptographic binding between the invoice and the beneficiary account exists. Users SHOULD independently verify beneficiary account details before initiating a bank transfer, particularly when communicating with a service for the first time.

10.4 Financial Safety

Clients MUST NOT automatically pay an invoice above a configurable amount threshold without explicit user confirmation. Implementations SHOULD default this threshold to zero (i.e., all payments require explicit user approval) and SHOULD allow the user to raise it. Automated agents operating within a pre-authorized budget MAY raise this threshold programmatically for their specific use case, but MUST NOT do so without the knowledge and consent of the account holder.

11. Privacy Considerations

Services MUST NOT include information in invoice metadata that would allow correlation of payments to real-world identities beyond what is required for the service function.

Lightning Network payment hashes are pseudonymous. However, a service that retains proof-of-payment preimages alongside session records can link a payment to the payer's JID. Services SHOULD minimize the identity information stored alongside consumed session records and SHOULD delete such records once the access grant has expired.

Traditional bank transfer options inherently reveal the payer's real name and account details to the payee, as this is a property of the underlying banking system. Clients SHOULD inform the user of this before initiating a bank transfer to a party the user has not previously transacted with.

The 'session' value SHOULD NOT encode any information about the payer's identity or behavior.

12. IANA Considerations

This document requires no interaction with the Internet Assigned Numbers Authority (IANA).

13. XMPP Registrar Considerations

13.1 Protocol Namespaces

The XMPP Registrar [8] shall include 'urn:xmpp:payment:0' in its registry of protocol namespaces.

If the protocol defined in this specification undergoes a revision that is not fully backwards-compatible with an older version, the XMPP Registrar shall increment the protocol version number found at the end of the XML namespaces defined herein, as described in Section 4 of XEP-0053.

13.2 Service Discovery Features

The XMPP Registrar [8] shall include the following features in its registry of service discovery features (see <https://xmpp.org/registrar/disco-features.html>):

An entity that supports the error-flow portion of this protocol MUST advertise the feature 'urn:xmpp:payment:0'. An entity that additionally supports the proactive IQ-based invoice request MUST advertise 'urn:xmpp:payment:0#invoice-request'. An entity that supports emitting <receipt/> elements upon successful payment MUST advertise 'urn:xmpp:payment:0#receipt'.

13.3 Payment Schemes Registry

The XMPP Registrar [8] shall maintain a registry of payment scheme identifiers for use in the 'scheme' attribute of the <option/> element. The RECOMMENDED process for registering a new scheme is to define it in a Standards Track XEP or in a published specification and submit a registration request to the XMPP Registrar [8].

Each registration MUST specify all of the following:

  1. Scheme identifier — A unique lowercase ASCII string used as the value of the 'scheme' attribute (e.g., payto, lightning-bolt11).
  2. Payload format — The syntax and semantics of the character data of the <option/> element when this scheme is used (e.g., a payto URI per RFC 8905, a BOLT 11 invoice string).
  3. Proof format — The proof type(s) that MAY accompany a <payment/> element for this scheme, and the syntax of the proof token (or explicitly "none" if no machine-verifiable proof exists for this scheme).
  4. Verification procedure — A description of how a service can verify that a payment was made, including any constraints on timing, idempotency, and the handling of asynchronous settlement.

The initial contents of this registry are as follows.

Table 2: Initial Payment Scheme Registry
Scheme Description Reference
payto A 'payto' URI as defined by RFC 8905. This payment-system-neutral scheme covers IBAN/SEPA bank transfers, UPI, PIX, Bitcoin, and other payment target types within a single standardized format. RECOMMENDED as the primary URI scheme for this specification. Example: payto://iban/DE75512108001245126199?amount=EUR:200.00&message=ref RFC 8905
lightning-bolt11 A Lightning Network BOLT 11 invoice string (e.g., beginning with lnbc, lntbs, or another network prefix). BOLT 11
lightning-bolt12 A Lightning Network BOLT 12 offer or invoice string (e.g., beginning with lno or lni). BOLT 12
epc-qr A European Payments Council QR code payload for SEPA Credit Transfers. Plain-text, newline-delimited format as defined by the EPC (EPC069-12). Commonly used in Austria, Belgium, Finland, Germany, and the Netherlands. EPC069-12

Implementors MAY define private or experimental schemes using reverse-domain-name notation (e.g., com.example.custompay) without XMPP Registrar [8] registration. Public schemes intended for interoperability MUST be registered.

13.4 Proof Types Registry

The XMPP Registrar [8] shall maintain a registry of proof type identifiers for use in the 'type' attribute of the <proof/> element. The initial contents of this registry are as follows.

Table 3: Initial Proof Types Registry
Type Description Payload Format
lightning-preimage A 32-byte Lightning Network payment preimage, serving as cryptographic proof that the corresponding BOLT 11 or BOLT 12 invoice was paid. 64-character lowercase hexadecimal string
reference A payment reference or transaction identifier provided by the payer's bank or payment network after completing a transfer. Examples include a SEPA end-to-end identifier, a UPI transaction ID, and a PIX end-to-end identifier (E2EID). Alphanumeric string; format is network-dependent
txid An on-chain blockchain transaction identifier (e.g., a Bitcoin transaction ID). Transaction ID string; format is network-dependent
token An opaque bearer token issued by a facilitator service following verified payment. Enables a "pay once, use many times" pattern within the token's validity period. Opaque string; format is implementation-defined

13.5 Invoice Request Service Registry

The XMPP Registrar [8] shall maintain a registry of service type identifiers for use in the 'service' attribute of the <get-invoice/> element. The initial contents of this registry are as follows.

Table 4: Initial Invoice Request Service Registry
Value Description
muc-entry Entry fee for a Multi-User Chat (XEP-0045) [1] room.
file-upload Fee for a file upload service (e.g., HTTP File Upload (XEP-0363) [9]).
message Per-message fee, e.g., for a bot service or an anti-spam deposit.
registration Account registration or hosting fee.

14. Design Considerations

Several alternative designs were considered during the development of this specification.

14.1 Using Data Forms for the Invoice

Data Forms (XEP-0004) [10] Data Forms were considered as the vehicle for invoice delivery, since CAPTCHA Forms (XEP-0158) [2] already uses them for challenges. Data Forms were rejected for the primary invoice format because the structured multi-element nature of an invoice (multiple <option/> children, each with a payload string and a display annotation) does not map naturally onto flat form fields, and because a dedicated element is more self-describing and easier to parse for automated agents. Data Forms are retained only for the CAPTCHA Forms (XEP-0158) [2] integration use case, where the payment option appears as a single field alongside other challenge fields.

14.2 Choosing auth as the Error Type

The "auth" error type was chosen for the payment-required error rather than, say, "cancel" or a new type, because the payer genuinely lacks authorization to perform the requested action until payment is made. This mirrors the semantics of HTTP 402 and is consistent with the existing use of "auth" for <registration-required/> in RFC 6120 [11].

14.3 Streaming Payment Sessions

This specification defines only single-payment ("charge") semantics: one invoice, one payment, one grant. For high-frequency use cases such as per-query AI agent bots, this model requires a new invoice round-trip for every request, which introduces latency and overhead.

A future companion specification MAY define streaming payment session semantics, analogous to the session intent in the Machine Payments Protocol (MPP). In such a model, an agent would open a payment channel by pre-funding it, and subsequent requests within the same channel would be settled using off-chain cryptographic vouchers without requiring a new invoice or an on-chain transaction per query. Such a specification would advertise support via a new feature (e.g., 'urn:xmpp:payment:0#session') and is outside the scope of this document.

15. XML Schema

XML Schema for urn:xmpp:payment:0
<?xml version='1.0' encoding='UTF-8'?>
<xs:schema
    xmlns:xs='http://www.w3.org/2001/XMLSchema'
    elementFormDefault='qualified'
    targetNamespace='urn:xmpp:payment:0'
    xmlns='urn:xmpp:payment:0'>

  <!-- invoice: emitted by services in error stanzas and IQ results -->
  <xs:element name='invoice'>
    <xs:complexType>
      <xs:sequence>
        <xs:element maxOccurs='1'
                    minOccurs='0'
                    ref='description'/>
        <xs:element maxOccurs='unbounded'
                    minOccurs='1'
                    ref='option'/>
      </xs:sequence>
      <xs:attribute name='expires'
                    type='xs:dateTime'
                    use='optional'/>
      <xs:attribute name='purpose'
                    type='xs:string'
                    use='optional'/>
      <xs:attribute name='session'
                    type='xs:string'
                    use='required'/>
    </xs:complexType>
  </xs:element>

  <xs:element name='description' type='xs:string'/>

  <!-- option: one payment scheme within an invoice -->
  <xs:element name='option'>
    <xs:complexType mixed='true'>
      <xs:sequence>
        <xs:element maxOccurs='1'
                    minOccurs='0'
                    ref='display-amount'/>
      </xs:sequence>
      <xs:attribute name='amount'
                    type='xs:string'
                    use='optional'/>
      <xs:attribute name='label'
                    type='xs:string'
                    use='optional'/>
      <xs:attribute name='scheme'
                    type='xs:string'
                    use='required'/>
    </xs:complexType>
  </xs:element>

  <!-- display-amount: locale-appropriate human-readable amount string -->
  <xs:element name='display-amount' type='xs:string'/>

  <!-- payment: added to retried stanzas by the payer -->
  <xs:element name='payment'>
    <xs:complexType>
      <xs:sequence>
        <xs:element maxOccurs='1'
                    minOccurs='0'
                    ref='proof'/>
      </xs:sequence>
      <xs:attribute name='scheme'
                    type='xs:string'
                    use='optional'/>
      <xs:attribute name='session'
                    type='xs:string'
                    use='required'/>
    </xs:complexType>
  </xs:element>

  <xs:element name='proof'>
    <xs:complexType mixed='true'>
      <xs:attribute name='type'
                    type='xs:string'
                    use='required'/>
    </xs:complexType>
  </xs:element>

  <!-- payment-required: application-specific stanza error condition -->
  <xs:element name='payment-required'>
    <xs:complexType>
      <xs:attribute name='reason'
                    type='xs:string'
                    use='optional'/>
    </xs:complexType>
  </xs:element>

  <!-- receipt: optional element returned by the service upon successful settlement -->
  <xs:element name='receipt'>
    <xs:complexType>
      <xs:attribute name='reference'
                    type='xs:string'
                    use='optional'/>
      <xs:attribute name='scheme'
                    type='xs:string'
                    use='required'/>
      <xs:attribute name='session'
                    type='xs:string'
                    use='required'/>
      <xs:attribute name='settled'
                    type='xs:dateTime'
                    use='optional'/>
    </xs:complexType>
  </xs:element>

  <!-- get-invoice: IQ-get payload for proactive invoice request -->
  <xs:element name='get-invoice'>
    <xs:complexType>
      <xs:attribute name='service'
                    type='xs:string'
                    use='required'/>
      <xs:attribute name='target'
                    type='xs:string'
                    use='optional'/>
    </xs:complexType>
  </xs:element>

</xs:schema>

Appendices

Appendix A: Document Information

Series
XEP
Number
xxxx
Publisher
XMPP Standards Foundation
Status
ProtoXEP
Type
Standards Track
Version
0.0.1
Last Updated
2026-04-23
Approving Body
XMPP Council
Dependencies
XMPP Core, XMPP IM, XEP-0004, XEP-0030, XEP-0082, XEP-0158, RFC 8905
Supersedes
None
Superseded By
None
Short Name
NOT_YET_ASSIGNED

This document in other formats: XML  PDF

Appendix B: Author Information

JC Brand
Email
jc@opkode.com
JabberID
jc@opkode.com

Copyright

This XMPP Extension Protocol is copyright © 1999 – 2024 by the XMPP Standards Foundation (XSF).

Permissions

Permission is hereby granted, free of charge, to any person obtaining a copy of this specification (the "Specification"), to make use of the Specification without restriction, including without limitation the rights to implement the Specification in a software program, deploy the Specification in a network service, and copy, modify, merge, publish, translate, distribute, sublicense, or sell copies of the Specification, and to permit persons to whom the Specification is furnished to do so, subject to the condition that the foregoing copyright notice and this permission notice shall be included in all copies or substantial portions of the Specification. Unless separate permission is granted, modified works that are redistributed shall not contain misleading information regarding the authors, title, number, or publisher of the Specification, and shall not claim endorsement of the modified works by the authors, any organization or project to which the authors belong, or the XMPP Standards Foundation.

Disclaimer of Warranty

## NOTE WELL: This Specification is provided on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. ##

Limitation of Liability

In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall the XMPP Standards Foundation or any author of this Specification be liable for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising from, out of, or in connection with the Specification or the implementation, deployment, or other use of the Specification (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if the XMPP Standards Foundation or such author has been advised of the possibility of such damages.

IPR Conformance

This XMPP Extension Protocol has been contributed in full conformance with the XSF's Intellectual Property Rights Policy (a copy of which can be found at <https://xmpp.org/about/xsf/ipr-policy> or obtained by writing to XMPP Standards Foundation, P.O. Box 787, Parker, CO 80134 USA).

Visual Presentation

The HTML representation (you are looking at) is maintained by the XSF. It is based on the YAML CSS Framework, which is licensed under the terms of the CC-BY-SA 2.0 license.

Appendix D: Relation to XMPP

The Extensible Messaging and Presence Protocol (XMPP) is defined in the XMPP Core (RFC 6120) and XMPP IM (RFC 6121) specifications contributed by the XMPP Standards Foundation to the Internet Standards Process, which is managed by the Internet Engineering Task Force in accordance with RFC 2026. Any protocol defined in this document has been developed outside the Internet Standards Process and is to be understood as an extension to XMPP rather than as an evolution, development, or modification of XMPP itself.

Appendix E: Discussion Venue

The primary venue for discussion of XMPP Extension Protocols is the <standards@xmpp.org> discussion list.

Discussion on other xmpp.org discussion lists might also be appropriate; see <https://xmpp.org/community/> for a complete list.

Given that this XMPP Extension Protocol normatively references IETF technologies, discussion on the <xsf-ietf@xmpp.org> list might also be appropriate.

Errata can be sent to <editor@xmpp.org>.

Appendix F: Requirements Conformance

The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in BCP 14 [RFC2119] [RFC8174] when, and only when, they appear in all capitals, as shown here.

Appendix G: Notes

1. XEP-0045: Multi-User Chat <https://xmpp.org/extensions/xep-0045.html>.

2. XEP-0158: CAPTCHA Forms <https://xmpp.org/extensions/xep-0158.html>.

3. XEP-0060: Publish-Subscribe <https://xmpp.org/extensions/xep-0060.html>.

4. XEP-0030: Service Discovery <https://xmpp.org/extensions/xep-0030.html>.

5. XEP-0050: Ad-Hoc Commands <https://xmpp.org/extensions/xep-0050.html>.

6. XEP-0082: XMPP Date and Time Profiles <https://xmpp.org/extensions/xep-0082.html>.

7. XEP-0384: OMEMO Encryption <https://xmpp.org/extensions/xep-0384.html>.

8. The XMPP Registrar maintains a list of reserved protocol namespaces as well as registries of parameters used in the context of XMPP extension protocols approved by the XMPP Standards Foundation. For further information, see <https://xmpp.org/registrar/>.

9. XEP-0363: HTTP File Upload <https://xmpp.org/extensions/xep-0363.html>.

10. XEP-0004: Data Forms <https://xmpp.org/extensions/xep-0004.html>.

11. RFC 6120: Extensible Messaging and Presence Protocol (XMPP): Core <http://tools.ietf.org/html/rfc6120>.

Appendix H: Revision History

Note: Older versions of this specification might be available at https://xmpp.org/extensions/attic/

  1. Version 0.0.1 (2026-04-23)

    First draft.

    jcb

Appendix I: Bib(La)TeX Entry

@report{brand2026xepxxxx,
  title = {Payment Required},
  author = {Brand, JC},
  type = {XEP},
  number = {xxxx},
  version = {0.0.1},
  institution = {XMPP Standards Foundation},
  url = {https://xmpp.org/extensions/xep-xxxx.html},
  date = {2026-04-23/2026-04-23},
}

END