commit 25790f55e1fb520cadce8c592396ecf46135dccc
parent 29d443bd8a2868938d66618539d9ceebb3321d26
Author: Christian Grothoff <christian@grothoff.org>
Date: Tue, 3 Feb 2026 09:26:03 +0100
specify /unclaim endpoint (#9961)
Diffstat:
1 file changed, 56 insertions(+), 6 deletions(-)
diff --git a/core/api-merchant.rst b/core/api-merchant.rst
@@ -29,7 +29,7 @@ Merchant Backend RESTful API
Version History
---------------
-The current protocol version is **v25**.
+The current protocol version is **v26**.
Android PoS app is currently targeting **v20**.
@@ -44,6 +44,7 @@ Android PoS app is currently targeting **v20**.
for periodic report generation and inventory-based templates,
new long-polling for KYC and features for templates to support
session-based payments
+* ``v26``: adds unclaim endpoint
**Upcoming versions:**
@@ -582,6 +583,42 @@ claim orders (say in a case where stocks are limited).
sig: EddsaSignature;
}
+.. http:post:: [/instances/$INSTANCE]/orders/$ORDER_ID/unclaim
+
+ Wallet releases ownership over an order. By unclaiming an
+ order, it becomes possible for another wallet to claim it.
+ This is useful if a user abandons buying the order with one
+ wallet but then wants to pay with a different wallet.
+
+ @since protocol **v26**.
+
+ **Request:**
+
+ The request must be an `UnclaimRequest`.
+
+ **Response:**
+
+ :http:statuscode:`204 No content`:
+ The client has successfully unclaimed the order.
+ :http:statuscode:`403 Forbidden`:
+ The signature is invalid.
+ :http:statuscode:`404 Not found`:
+ The backend is unaware of the instance or order.
+ :http:statuscode:`409 Conflict`:
+ The order was already paid, and thus cannot be unclaimed anymore.
+
+ **Details:**
+
+ .. ts:def:: UnclaimRequest
+
+ interface UnclaimRequest {
+ // Signature using the key of the claim nonce
+ // to affirm unclaiming of the order.
+ unclaim_sig: EddsaSignature;
+
+ }
+
+
Making the payment
^^^^^^^^^^^^^^^^^^
@@ -970,7 +1007,7 @@ Querying payment status
**Request:**
:query h_contract=HASH: *Optional*. Hash of the order's contract terms (this is used to authenticate the wallet/customer in case $ORDER_ID is guessable). Required once an order was claimed.
- :query token=TOKEN: *Optional*. Authorizes the request via the claim token that was returned in the `PostOrderResponse`. Used with unclaimed orders only. Whether token authorization is required is determined by the merchant when the frontend creates the order.
+ :query token=TOKEN: *Optional*. Authorizes the request via the claim token that was returned in the `PostOrderResponse`. Used with unclaimed orders only. Whether token authorization is required is determined by the merchant when the frontend creates the order.
:query session_id=STRING: *Optional*. Session ID that the payment must be bound to. If not specified, the payment is not session-bound.
:query timeout_ms=NUMBER: *Optional.* If specified, the merchant backend will
wait up to ``timeout_ms`` milliseconds for completion of the payment before
@@ -985,14 +1022,27 @@ Querying payment status
:http:statuscode:`200 OK`:
The response is a `StatusPaidResponse`.
:http:statuscode:`202 Accepted`:
- The response is a `StatusGotoResponse`. Only returned if the content type requested was not HTML.
- The target site may allow the client to setup a fresh order (as this one has been taken) or may
+ The response is a `StatusGotoResponse`.
+ Returned only for unauthenticated (no nonce, no contract hash)
+ requests and only if the order was claimed already.
+ Only returned if the content type requested was not HTML,
+ if HTML was requested a `302 Found` will be returned instead.
+ The target site may allow the client to setup a fresh
+ order (as this one has been taken) or may
trigger repurchase detection.
+ Note that **if** the contract lacks a ``public_reorder_url``
+ the backend will instead return a `403 Forbidden` response.
:http:statuscode:`302 Found`:
The client should go to the indicated location (via HTTP "Location:" header).
- Only returned if the content type requested was HTML.
- The target site may allow the client to setup a fresh order (as this one has been taken) or may
+ Returned only for unauthenticated (no nonce, no contract hash)
+ requests and only if the order was claimed already.
+ Only returned if the content type requested was HTML
+ if HTML was not requested a `302 Accepted` will be returned instead.
+ The target site may allow the client to setup a fresh
+ order (as this one has been taken) or may
trigger repurchase detection.
+ Note that **if** the contract lacks a ``public_reorder_url``
+ the backend will instead return a `403 Forbidden` response.
:http:statuscode:`402 Payment required`:
The response is a `StatusUnpaidResponse`.
:http:statuscode:`403 Forbidden`: