commit 7944885e71fbf970d21e0d9f4fe88dcc08146457
parent cb9f87f6db83a3db20c11276512a5906195b667b
Author: Bohdan Potuzhnyi <potub1@bfh.ch>
Date: Sun, 11 Oct 2026 15:44:31 +0000
adding public units endpoint + fixing a bit the versioning
Diffstat:
16 files changed, 69 insertions(+), 41 deletions(-)
diff --git a/core/api-merchant.rst b/core/api-merchant.rst
@@ -29,7 +29,7 @@ Merchant Backend RESTful API
Version History
---------------
-The currently implemented protocol version is **v42**.
+The currently implemented protocol version is **v44**.
* The Android PoS app is currently targeting **v20**.
* The SPA is currently targeting **vXX**.
@@ -82,16 +82,24 @@ The currently implemented protocol version is **v42**.
``/private/orders/$ORDER_ID/refund-external`` endpoint for recording
externally settled refunds, and exposes both through order status
(see :doc:`DD 96 </design-documents/096-partial-payments>`)
+* ``v43``: adds ECDSA and EdDSA challenge-based payment confirmations.
+ The OTP-device API generates signing keys and exposes the public key.
+ Order creation and template instantiation accept a ``challenge``; after
+ successful payment, the backend returns its signature in ``pos_confirmation``
+ (see :doc:`DD 97 </design-documents/097-challenge-confirmations>`).
+ Also adds token fountain management and wallet APIs for retrieving grants
+ and withdrawing blind-signed promotional tokens without creating an order
+ (see :doc:`DD 98 </design-documents/098-token-fountains>`)
+* ``v44``: adds unauthenticated :http:get:`[/instances/$INSTANCE]/units`
+ to retrieve all active measurement units for one merchant instance,
+ including built-in units with instance overrides and custom units.
+ Also adds ``limit``/``offset`` pagination to
+ :http:get:`[/instances/$INSTANCE]/private/fountains`, using the new
+ ``fountain_serial`` response field as an exclusive cursor
**Upcoming versions:**
* ``vTAXES``: adds features to manage taxes
-* ``vChallengeConfirmation``: adds challenge-signature OTP algorithms for
- payment confirmations verified by offline appliances and tags
- (see :doc:`DD 97 </design-documents/097-challenge-confirmations>`)
-* ``vTokenFountains``: adds fountains for distributing promotional
- merchant tokens
- (see :doc:`DD 98 </design-documents/098-token-fountains>`)
* ``vDonauReceipts``: returns donation receipts from ``/pay`` in the new
``donau_sigs`` field instead of inside ``token_sigs`` (breaking for orders
with a donation receipt output), answers a Donau failure after a
@@ -294,10 +302,10 @@ The following permissions exist:
* - ``donau-write``
- Adding and removing Donau charity instance links.
* - ``fountains-read``
- - Listing and inspecting token fountains. Since **vTokenFountains**.
+ - Listing and inspecting token fountains. Since **v43**.
* - ``fountains-write``
- Creating, modifying and deleting token fountains.
- Since **vTokenFountains**.
+ Since **v43**.
* - ``groups-read``
- Listing product groups.
* - ``groups-write``
@@ -788,6 +796,8 @@ Decimal quantities
Managing measurement units
^^^^^^^^^^^^^^^^^^^^^^^^^^
+.. include:: merchant/get-units.rst
+
.. include:: merchant/get-private-units.rst
.. include:: merchant/get-private-units-UNIT.rst
@@ -1341,7 +1351,7 @@ to one recipient or share it for a campaign
Wallets receive the credential as a
``taler://fountain/$MERCHANT_HOST[/$INSTANCE_PATH]/$FOUNTAIN_ID/$FOUNTAIN_SECRET``
URI. All fountain endpoints are available since protocol
-**vTokenFountains**.
+**v43**.
Managing fountains
^^^^^^^^^^^^^^^^^^
diff --git a/core/merchant/delete-private-fountains-FOUNTAIN_ID.rst b/core/merchant/delete-private-fountains-FOUNTAIN_ID.rst
@@ -4,7 +4,7 @@
Subsequent wallet requests with the fountain secret fail with
``401 Unauthorized``; tokens already withdrawn remain valid until
their issue key expires.
- This endpoint is available since protocol **vTokenFountains**.
+ This endpoint is available since protocol **v43**.
**Required permission:** ``fountains-write`` (see :ref:`Scopes <merchant-api-scopes>`)
diff --git a/core/merchant/get-fountain-info.rst b/core/merchant/get-fountain-info.rst
@@ -5,7 +5,7 @@
keys needed to prepare blinded envelopes. Wallets re-poll this
endpoint at the advertised ``poll_freq`` to learn about changed
promotional grants.
- This endpoint is available since protocol **vTokenFountains**.
+ This endpoint is available since protocol **v43**.
The fountain secret authenticates the request via the
``Authorization: Bearer $FOUNTAIN_SECRET`` header; it is
diff --git a/core/merchant/get-private-fountains-FOUNTAIN_ID.rst b/core/merchant/get-private-fountains-FOUNTAIN_ID.rst
@@ -2,7 +2,7 @@
Returns detailed information about a specific fountain.
The fountain secret is never returned.
- This endpoint is available since protocol **vTokenFountains**.
+ This endpoint is available since protocol **v43**.
**Required permission:** ``fountains-read`` (see :ref:`Scopes <merchant-api-scopes>`)
diff --git a/core/merchant/get-private-fountains.rst b/core/merchant/get-private-fountains.rst
@@ -2,7 +2,9 @@
Lists a bounded page of fountains of the instance, ordered by
``fountain_serial``.
- This endpoint is available since protocol **vTokenFountains**.
+ This endpoint is available since protocol **v43**. Pagination and the
+ ``fountain_serial`` response field are available since protocol **v44**.
+ Clients must iterate over the pages to retrieve all fountains.
**Required permission:** ``fountains-read`` (see :ref:`Scopes <merchant-api-scopes>`)
@@ -45,6 +47,7 @@
interface FountainEntry {
// Database serial number used as an exclusive pagination cursor.
+ // Since protocol **v44**.
fountain_serial: Integer;
// Identifier of the fountain.
diff --git a/core/merchant/get-private-otp-devices-DEVICE_ID.rst b/core/merchant/get-private-otp-devices-DEVICE_ID.rst
@@ -46,14 +46,14 @@
// 1: TOTP without price
// 2: TOTP with price
// 3: ECDSA signature over the order's challenge
- // (since protocol **vChallengeConfirmation**)
+ // (since protocol **v43**)
// 4: EdDSA signature over the order's challenge
- // (since protocol **vChallengeConfirmation**)
+ // (since protocol **v43**)
otp_algorithm: Integer;
// Public key of the device key pair, only present for
// challenge-signature algorithms (3 and 4).
- // Since protocol **vChallengeConfirmation**.
+ // Since protocol **v43**.
otp_device_pub?: string;
// Counter for counter-based OTP devices.
diff --git a/core/merchant/get-private-units.rst b/core/merchant/get-private-units.rst
@@ -1,6 +1,8 @@
.. http:get:: [/instances/$INSTANCE]/private/units
- Returns the list of measurement units available to an instance.
+ Returns the list of measurement units available to an instance, including
+ inactive definitions. Wallets can retrieve the active catalogue without
+ authentication using :http:get:`[/instances/$INSTANCE]/units`.
**Required permission:** ``units-read`` (see :ref:`Scopes <merchant-api-scopes>`)
diff --git a/core/merchant/patch-private-fountains-FOUNTAIN_ID.rst b/core/merchant/patch-private-fountains-FOUNTAIN_ID.rst
@@ -4,7 +4,7 @@
replacing the grants does not invalidate
the fountain secret; wallets learn about the changed grants on
their next ``GET /fountain/info`` poll.
- This endpoint is available since protocol **vTokenFountains**.
+ This endpoint is available since protocol **v43**.
**Required permission:** ``fountains-write`` (see :ref:`Scopes <merchant-api-scopes>`)
diff --git a/core/merchant/post-fountain-withdraw.rst b/core/merchant/post-fountain-withdraw.rst
@@ -5,7 +5,7 @@
structured per grant: each entry addresses one granted token
family and one key slot, and carries the envelopes to sign
against that grant's limits.
- This endpoint is available since protocol **vTokenFountains**.
+ This endpoint is available since protocol **v43**.
The fountain secret travels in the request body, never in the
URL.
diff --git a/core/merchant/post-orders-ORDER_ID-pay.rst b/core/merchant/post-orders-ORDER_ID-pay.rst
@@ -274,7 +274,7 @@
// ("ECDSA_CHALLENGE" or "EDDSA_CHALLENGE"), contains the
// Crockford Base32 encoded signature over the hash of the
// order's challenge, made with the device private key.
- // Since protocol **vChallengeConfirmation**.
+ // Since protocol **v43**.
pos_confirmation?: string;
// Signed tokens for the outputs of type ``token``. Returned in
diff --git a/core/merchant/post-private-fountains.rst b/core/merchant/post-private-fountains.rst
@@ -4,7 +4,7 @@
entitles a wallet to withdraw blind-signed promotional tokens for
a set of token families
(see :doc:`DD 98 </design-documents/098-token-fountains>`).
- This endpoint is available since protocol **vTokenFountains**.
+ This endpoint is available since protocol **v43**.
**Required permission:** ``fountains-write`` (see :ref:`Scopes <merchant-api-scopes>`)
diff --git a/core/merchant/post-private-otp-devices.rst b/core/merchant/post-private-otp-devices.rst
@@ -17,7 +17,7 @@
``otp_algorithm`` ("ECDSA_CHALLENGE" or "EDDSA_CHALLENGE"): the
backend generated the device key pair and returns a
`OtpDeviceCreateResponse` with the public key.
- Since protocol **vChallengeConfirmation**.
+ Since protocol **v43**.
:http:statuscode:`400 Bad Request`:
The request body is malformed.
:http:statuscode:`404 Not found`:
@@ -53,7 +53,7 @@
// Taler base32-crockford encoding.
// Instead it uses the RFC 3548 encoding to
// be compatible with the TOTP standard.
- // Since protocol **vChallengeConfirmation** this field is optional:
+ // Since protocol **v43** this field is optional:
// it MUST be omitted for the challenge-signature algorithms
// (3 and 4), where the backend generates the key pair itself
// and never exposes the private key.
@@ -64,9 +64,9 @@
// "TOTP_WITHOUT_PRICE" or 1: Without amounts (typical OTP device)
// "TOTP_WITH_PRICE" or 2: With amounts (special-purpose OTP device)
// "ECDSA_CHALLENGE" or 3: ECDSA signature over the order's
- // challenge, since protocol **vChallengeConfirmation**.
+ // challenge, since protocol **v43**.
// "EDDSA_CHALLENGE" or 4: EdDSA signature over the order's
- // challenge, since protocol **vChallengeConfirmation**.
+ // challenge, since protocol **v43**.
// The "string" variants are supported @since protocol **v7**.
otp_algorithm: Integer | string;
@@ -83,6 +83,6 @@
// For "ECDSA_CHALLENGE" a compressed NIST P-256 point, for
// "EDDSA_CHALLENGE" an Ed25519 public key.
// Crockford Base32 encoded.
- // Since protocol **vChallengeConfirmation**.
+ // Since protocol **v43**.
otp_device_pub: string;
}
diff --git a/core/merchant/post-templates-TEMPLATE_ID.rst b/core/merchant/post-templates-TEMPLATE_ID.rst
@@ -92,7 +92,7 @@
// meaningful -- and then mandatory -- if the template's OTP
// device uses a challenge-signature algorithm ("ECDSA_CHALLENGE"
// or "EDDSA_CHALLENGE"); rejected otherwise.
- // Since protocol **vChallengeConfirmation**.
+ // Since protocol **v43**.
challenge?: string;
}
diff --git a/design-documents/072-products-units.rst b/design-documents/072-products-units.rst
@@ -73,6 +73,13 @@ Proposed Solution
``InternationalizedString`` pattern already used across the API (maps of
BCP 47 language tags to translated strings).
+ Since merchant protocol **v44**, wallets can retrieve all active definitions
+ through the public :http:get:`[/instances/$INSTANCE]/units` endpoint without
+ credentials. It returns built-in units with the selected instance's overrides
+ and that instance's custom units in one response. The unprefixed ``/units``
+ path selects the default (``admin``) instance. Inactive units are omitted;
+ operators can still inspect them through the authenticated private endpoints.
+
.. http:get:: /private/units
Return the catalogue for the current instance.
@@ -436,10 +443,14 @@ Proposed Solution
When displaying order details or cart lines, wallet and POS front-ends
**MUST use the short unit label embedded in the public template response**
- for the referenced ``unit``. Wallets cannot call the authenticated
- ``/private/units`` endpoints. When no label is supplied, clients fall back
- to the raw ``unit`` string. Append the selected label to the numeric value with a
- non-breaking thin space (U+202F). Trailing zeros
+ for the referenced ``unit``. When no label is embedded, wallets can resolve
+ it using the merchant instance's public ``GET /units`` catalogue. Wallets
+ cannot call the authenticated ``/private/units`` endpoints. If the unit is
+ absent or the catalogue cannot be fetched and no label is otherwise
+ available, clients fall back to the raw ``unit`` string.
+
+ Append the selected label to the numeric value with a non-breaking thin space
+ (U+202F). Trailing zeros
*up to* the declared ``unit_precision_level`` **MUST be trimmed**, but the
displayed precision **MUST NOT** exceed the declared level. Examples::
diff --git a/design-documents/097-challenge-confirmations.rst b/design-documents/097-challenge-confirmations.rst
@@ -9,8 +9,8 @@ DD 97: Challenge-Signature Payment Confirmations
:Historical contributors: Bohdan Potuzhnyi
:First published: 2026-07-23
:Last substantive change: 2026-07-23
-:Implementation evidence: ``exchange`` (2026-08-01); ``merchant`` (2026-08-02, not merged into the reviewed HEAD)
-:Normative references: ``core/api-merchant.rst`` (upcoming version) and ``core/merchant/post-orders-ORDER_ID-pay.rst``
+:Implementation evidence: ``exchange`` (2026-08-01); ``merchant`` (commit ``8e1875a4``, protocol v43)
+:Normative references: ``core/api-merchant.rst`` (v43) and ``core/merchant/post-orders-ORDER_ID-pay.rst``
Summary
=======
@@ -23,8 +23,8 @@ action.
.. note::
- This design document proposes an extension for discussion. The protocol
- version name ``vChallengeConfirmation`` is a placeholder.
+ The merchant backend implements the API changes described here since
+ protocol **v43**, replacing the provisional ``vChallengeConfirmation`` name.
Motivation
==========
diff --git a/design-documents/098-token-fountains.rst b/design-documents/098-token-fountains.rst
@@ -9,7 +9,7 @@ DD 98: Token Fountains for Promotions
:Historical contributors: Bohdan Potuzhnyi
:First published: 2026-07-23
:Last substantive change: 2026-09-06
-:Normative references: ``core/api-merchant.rst`` (upcoming token-fountain API)
+:Normative references: ``core/api-merchant.rst`` (v43 token-fountain API)
Summary
=======
@@ -21,8 +21,9 @@ withdraws blind-signed tokens within limits configured by the institution.
.. note::
- This design document proposes an extension for discussion. The protocol
- version name ``vTokenFountains`` is a placeholder.
+ The merchant backend implements the fountain management and wallet APIs
+ under protocol **v43** (commit ``97439d8f``), replacing the provisional
+ ``vTokenFountains`` name.
Motivation
==========
@@ -200,8 +201,9 @@ delete fountains:
* ``POST /private/fountains``
-* ``GET /private/fountains`` (paginated listing ordered by fountain serial;
- defaults to 20 entries, with a hard cap of 100 per request)
+* ``GET /private/fountains`` (since protocol **v44**, paginated listing ordered
+ by ``fountain_serial`` with ``limit``/``offset`` parameters; defaults to 20
+ entries, with a hard cap of 100 per request)
* ``GET /private/fountains/$FOUNTAIN_ID``