# NUT-18: Payment Requests `optional` --- This NUT introduces a standardised format for payment requests, that supply a sending wallet with all information necessary to complete the transaction. This enables many use-cases where a transaction is better initiated by the receiver (e.g. point of sale). ## Flow 1. Receiver creates a payment request, encodes it and displays it to the sender 2. Sender scans the request and constructs a matching token 3. Sender sends the token according to the transport specified in the payment request 4. Receiver receives the token and finalises the transaction ## Payment Request A Payment Request is defined as follows ```json { "i": str , "a": int , "u": str , "s": bool , "m": Array[str] , "d": str , "t": Array[Transport] , "nut10": NUT10Option , } ``` Here, the fields are - `i`: Payment id to be included in the payment payload - `a`: The amount of the requested payment - `u`: The unit of the requested payment (MUST be set if `a` is set) - `s`: Whether the payment request is for single use - `m`: A set of mints from which the payment is requested - `d`: A human readable description that the sending wallet will display after scanning the request - `t`: The method of `Transport` chosen to transmit the payment (can be multiple, sorted by preference) - `nut10`: The required [NUT-10][10] locking condition ## Locking conditions The payment request can include _optional_ locking conditions the payee requires from the payer. For example, the payee might require a P2PK-locked token so that they can receive payments offline. The `nut10` field specifies the payee's requested locking condition as a `NUT10Option` object. Its elements are derived from NUT-10's [well-known secret](10.md#well-known-secret). The `NUT10Option` is defined as follows: ```json { "k": str, "d": str, "t": Array[Array[str, str]] } ``` - `k`: NUT-10 secret kind, - `d`: NUT-10 secret data, - `t`: optional NUT-10 payment tags > [!IMPORTANT] > The payee must validate the incoming tokens themselves in order to decide whether they can accept the payment. This includes checking the DLEQ proof and whether the token includes a long-enough timelock to satisfy the payee. ## Transport `Transport` specifies methods for sending the ecash to the receiver. A transport consists of a type and a target. > [!IMPORTANT] > The transport can be empty! If the transport is empty, we implicitly assume that the payment will be in-band. An example is X-Cashu where the payment is expected in the HTTP header of a request. We can only hope that the protocol you're using has a well-defined transport. ```json { "t": str, "a": str, "g": Array[Array[str, str]] } ``` - `t`: type of Transport - `a`: target of Transport - `g`: optional tags for the Transport ### Tags Tags are an optional array of `[tag, value, value, ...]` tuples that can be used to specify additional features about the transport. A single tag can have multiple values. ### Transport types The supported transport types are described below. #### Nostr - type: `nostr` - target: `` - tags: `[["n", "17"]]` The `n` tag specifies the NIPs the receiver supports. At least one tag value MUST be specified. For [NIP-17](https://github.com/nostr-protocol/nips/blob/master/17.md) direct messages, the sender sends a `PaymentRequestPayload` as the message content. #### HTTP POST - type: `post` - target: `` The execute the payment, the sender makes a `POST` request to the specified endpoint URL with the `PaymentRequestPayload` as the body. ## Payment payload If not specified otherwise, the payload sent to the receiver is a `PaymentRequestPayload` JSON serialized object as follows: ```json { "id": str , "memo": str , "mint": str, "unit": , "proofs": Array } ``` Here, `id` is the payment id (corresponding to `i` in request), `memo` is an optional memo to be sent to the receiver with the payment, `mint` is the mint URL from which the ecash is from, `unit` is the unit of the payment, and `proofs` is an array of proofs (see [NUT-00][00], can also include DLEQ proofs). ## Encoded Request The payment request is serialized using CBOR, encoded in `base64_urlsafe`, together with a prefix `creq` and a version `A`: `"creq" + "A" + base64_urlsafe(CBOR(PaymentRequest))` ### Example This is an example payment request expressed as JSON: ```json { "i": "b7a90176", "a": 10, "u": "sat", "m": ["https://nofees.testnut.cashu.space"], "t": [ { "t": "nostr", "a": "nprofile1qy28wumn8ghj7un9d3shjtnyv9kh2uewd9hsz9mhwden5te0wfjkccte9curxven9eehqctrv5hszrthwden5te0dehhxtnvdakqqgydaqy7curk439ykptkysv7udhdhu68sucm295akqefdehkf0d495cwunl5", "g": [["n", "17"]] } ] } ``` This payment request serializes to (see [here](https://cbor.nemo157.com/#type=hex&value=a3617482a261694800ffd48b8f5ecf80617081a36161016173784061636331323433356537623834383463336366313835303134393231386166393066373136613532626634613565643334376534386563633133663737333838616358210244538319de485d55bed3b29a642bee5879375ab9e7a620e11e48ba482421f3cfa261694800ad268c4d1f5826617082a3616102617378403133323364336434373037613538616432653233616461346539663166343966356135623461633762373038656230643631663733386634383330376538656561635821023456aa110d84b4ac747aebd82c3b005aca50bf457ebd5737a4414fac3ae7d94da36161016173784035366263626362623763633634303662336661356435376432313734663465666638623434303262313736393236643361353764336333646362623539643537616358210273129c5719e599379a974a626363c333c56cafc0e6d01abe46d5808280789c63616d75687474703a2f2f6c6f63616c686f73743a33333338617563736174)): ```sh creqApWF0gaNhdGVub3N0cmFheKlucHJvZmlsZTFxeTI4d3VtbjhnaGo3dW45ZDNzaGp0bnl2OWtoMnVld2Q5aHN6OW1od2RlbjV0ZTB3ZmprY2N0ZTljdXJ4dmVuOWVlaHFjdHJ2NWhzenJ0aHdkZW41dGUwZGVoaHh0bnZkYWtxcWd5ZGFxeTdjdXJrNDM5eWtwdGt5c3Y3dWRoZGh1NjhzdWNtMjk1YWtxZWZkZWhrZjBkNDk1Y3d1bmw1YWeBgmFuYjE3YWloYjdhOTAxNzZhYQphdWNzYXRhbYF4Imh0dHBzOi8vbm9mZWVzLnRlc3RudXQuY2FzaHUuc3BhY2U= ``` [00]: 00.md [10]: 10.md