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¶
- Receiver creates a payment request, encodes it and displays it to the sender
- Sender scans the request and constructs a matching token
- Sender sends the token according to the transport specified in the payment request
- Receiver receives the token and finalises the transaction
Payment Request¶
A Payment Request is defined as follows
{
"i": str <optional>,
"a": int <optional>,
"u": str <optional>,
"s": bool <optional>,
"m": Array[str] <optional>,
"d": str <optional>,
"t": Array[Transport]
}
Here, the fields are
i
: Payment id to be included in the payment payloada
: The amount of the requested paymentu
: The unit of the requested payment (MUST be set ifa
is set)s
: Whether the payment request is for single usem
: A set of mints from which the payment is requestedd
: A human readable description that the sending wallet will display after scanning the requestt
: The method ofTransport
chosen to transmit the payment (can be multiple, sorted by preference)
Transport¶
Transport
specifies methods for sending the ecash to the receiver. A transport consists of a type and a target.
{
"t": str,
"a": str,
"g": Array[Array[str, str]] <optional>
}
t
: type of Transporta
: target of Transportg
: 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:
<nprofile>
- tags:
[["n", "17"]]
The n
tag specifies the NIPs the receiver supports. At least one tag value MUST be specified. For NIP-17 direct messages, the sender sends a PaymentRequestPayload
as the message content.
HTTP POST¶
- type:
post
- target:
<endpoint url>
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:
{
"id": str <optional>,
"memo": str <optional>,
"mint": str,
"unit": <str_enum>,
"proofs": Array<Proof>
}
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, 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(CBOR(PaymentRequest))
Example¶
This is an example payment request expressed as 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):
creqApWF0gaNhdGVub3N0cmFheKlucHJvZmlsZTFxeTI4d3VtbjhnaGo3dW45ZDNzaGp0bnl2OWtoMnVld2Q5aHN6OW1od2RlbjV0ZTB3ZmprY2N0ZTljdXJ4dmVuOWVlaHFjdHJ2NWhzenJ0aHdkZW41dGUwZGVoaHh0bnZkYWtxcWd5ZGFxeTdjdXJrNDM5eWtwdGt5c3Y3dWRoZGh1NjhzdWNtMjk1YWtxZWZkZWhrZjBkNDk1Y3d1bmw1YWeBgmFuYjE3YWloYjdhOTAxNzZhYQphdWNzYXRhbYF4Imh0dHBzOi8vbm9mZWVzLnRlc3RudXQuY2FzaHUuc3BhY2U=