taler-docs

Documentation for GNU Taler components, APIs and protocols
Log | Files | Refs | README | LICENSE

api-exchange.rst (231426B)


      1 ..
      2   This file is part of GNU TALER.
      3   Copyright (C) 2014-2025 Taler Systems SA
      4 
      5   TALER is free software; you can redistribute it and/or modify it under the
      6   terms of the GNU Affero General Public License as published by the Free Software
      7   Foundation; either version 2.1, or (at your option) any later version.
      8 
      9   TALER is distributed in the hope that it will be useful, but WITHOUT ANY
     10   WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
     11   A PARTICULAR PURPOSE.  See the GNU Affero General Public License for more details.
     12 
     13   You should have received a copy of the GNU Affero General Public License along with
     14   TALER; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
     15 
     16   @author Christian Grothoff
     17   @author Özgür Kesim
     18 
     19 ========================
     20 The Exchange RESTful API
     21 ========================
     22 
     23 The API specified here follows the :ref:`general conventions <http-common>`
     24 for all details not specified in the individual requests.
     25 The `glossary <https://docs.taler.net/taler-developer-manual.html#developer-glossary>`_
     26 defines all specific terms used in this section.
     27 
     28 .. include:: tos.rst
     29 
     30 .. _keys:
     31 
     32 ---------------------------
     33 Exchange status information
     34 ---------------------------
     35 
     36 This API is used by wallets and merchants to obtain global information about
     37 the exchange, such as online signing keys, available denominations and the fee
     38 structure.  This is typically the first call any exchange client makes, as it
     39 returns information required to process all of the other interactions with the
     40 exchange.  The returned information is secured by (1) signature(s) from the exchange,
     41 especially the long-term offline signing key of the exchange, which clients should
     42 cache; (2) signature(s) from auditors, and the auditor keys should be
     43 hard-coded into the wallet as they are the trust anchors for Taler; (3)
     44 possibly by using HTTPS.
     45 
     46 
     47 .. http:get:: /seed
     48 
     49   Return an entropy seed. The exchange will return a high-entropy
     50   value that will differ for every call.  The response is NOT in
     51   JSON, but simply high-entropy binary data in the HTTP body.
     52   This API should be used by wallets to guard themselves against
     53   running on low-entropy (bad PRNG) hardware. Naturally, the entropy
     54   returned MUST be mixed with locally generated entropy.
     55 
     56 
     57 .. http:get:: /config
     58 
     59   Return the protocol version and currency supported by this exchange backend,
     60   as well as the list of possible KYC requirements.  This endpoint is largely
     61   for the SPA for AML officers. Merchants should use ``/keys`` which also
     62   contains the protocol version and currency.
     63   This specification corresponds to ``current`` protocol being **v31**.
     64 
     65   **Response:**
     66 
     67   :http:statuscode:`200 OK`:
     68     The body is a `VersionResponse`.
     69 
     70   .. ts:def:: ExchangeVersionResponse
     71 
     72     interface ExchangeVersionResponse {
     73       // libtool-style representation of the Exchange protocol version, see
     74       // https://www.gnu.org/software/libtool/manual/html_node/Versioning.html#Versioning
     75       // The format is "current:revision:age".
     76       version: string;
     77 
     78       // Name of the protocol.
     79       name: "taler-exchange";
     80 
     81       // URN of the implementation (needed to interpret 'revision' in version).
     82       // @since protocol **v18**, may become mandatory in the future.
     83       implementation?: string;
     84 
     85       // Currency supported by this exchange, given
     86       // as a currency code ("USD" or "EUR").
     87       currency: string;
     88 
     89       // Shopping URL where users may find shops that accept
     90       // digital cash issued by this exchange.
     91       // @since protocol **v21**.
     92       shopping_url?: string;
     93 
     94       // Open banking gateway base URL where wallets can
     95       // initiate wire transfers to withdraw
     96       // digital cash from this exchange.
     97       // @since protocol **v30**.
     98       open_banking_gateway?: string;
     99 
    100       // How wallets should render this currency.
    101       currency_specification: CurrencySpecification;
    102 
    103       // Names of supported KYC requirements.
    104       // @deprected in **v24**.
    105       supported_kyc_requirements: string[];
    106 
    107       // Bank-specific dialect for the AML SPA. Determines
    108       // which set of forms is available as well as statistics
    109       // to show and sets of properties/events to trigger in
    110       // AML decisions.
    111       // @since protocol **v24**.
    112       aml_spa_dialect?: string;
    113 
    114     }
    115 
    116   .. ts:def:: CurrencySpecification
    117 
    118     interface CurrencySpecification {
    119       // Name of the currency. Like "US Dollar".
    120       name: string;
    121 
    122       // Code of the currency.
    123       // @deprecated in protocol **v18** for the exchange, and
    124       // @deprecated in protocol **v6** for the merchant.
    125       currency: string;
    126 
    127       // how many digits the user may enter after the decimal_separator
    128       num_fractional_input_digits: Integer;
    129 
    130       // Number of fractional digits to render in normal font and size.
    131       num_fractional_normal_digits: Integer;
    132 
    133       // Number of fractional digits to render always, if needed by
    134       // padding with zeros.
    135       num_fractional_trailing_zero_digits: Integer;
    136 
    137       // map of powers of 10 to alternative currency names / symbols, must
    138       // always have an entry under "0" that defines the base name,
    139       // e.g.  "0 => €" or "3 => k€". For BTC, would be "0 => BTC, -3 => mBTC".
    140       // Communicates the currency symbol to be used.
    141       alt_unit_names: { log10 : string };
    142 
    143       // An array of common amounts that should be turned into
    144       // display buttons in dialogs where the user might like
    145       // a short-cut.  The array should have four entries, but
    146       // may have fewer or more entries. Wallets may omit
    147       // later entries in the array.
    148       // @since protocol **v30** (rev 2)
    149       common_amounts: Amount[];
    150 
    151     }
    152 
    153 
    154 .. http:get:: /keys
    155 
    156   Get a list of all denomination keys offered by the exchange,
    157   as well as the exchange's current online signing key.
    158 
    159   **Request:**
    160 
    161   :query last_issue_date: Optional argument specifying the maximum value of any of the ``stamp_start`` members of the denomination keys of a ``/keys`` response that is already known to the client. Allows the exchange to only return keys that have changed since that timestamp.  The given value must be an unsigned 64-bit integer representing seconds after 1970.  If the timestamp does not exactly match the ``stamp_start`` of one of the denomination keys, all keys are returned.
    162 
    163   **Response:**
    164 
    165   :http:statuscode:`200 OK`:
    166     The exchange responds with a `ExchangeKeysResponse` object. This request should
    167     virtually always be successful. It only fails if the exchange is misconfigured or
    168     has not yet been provisioned with key signatures via ``taler-exchange-offline``.
    169 
    170   **Details:**
    171 
    172   .. ts:def:: ExchangeKeysResponse
    173 
    174     interface ExchangeKeysResponse {
    175       // libtool-style representation of the Exchange protocol version, see
    176       // https://www.gnu.org/software/libtool/manual/html_node/Versioning.html#Versioning
    177       // The format is "current:revision:age".
    178       version: string;
    179 
    180       // The exchange's base URL.
    181       base_url: string;
    182 
    183       // The exchange's currency or asset unit.
    184       currency: string;
    185 
    186       // Shopping URL where users may find shops that accept
    187       // digital cash issued by this exchange.
    188       // @since protocol **v21**.
    189       shopping_url?: string;
    190 
    191       // Open banking gateway base URL where wallets can
    192       // initiate wire transfers to withdraw
    193       // digital cash from this exchange.
    194       // @since protocol **v30**.
    195       open_banking_gateway?: string;
    196 
    197       // Instructs wallets to use certain bank-specific
    198       // language (for buttons) and/or other UI/UX customization
    199       // for compliance with the rules of that bank.
    200       // The specific customizations to apply are done on a per-wallet
    201       // basis as requested by the specific bank. They only
    202       // apply when it is clear that the wallet is using digital
    203       // cash from that bank.  This is an advisory option, not
    204       // all wallets must support all compliance languages.
    205       // @since protocol **v24**.
    206       bank_compliance_language?: string;
    207 
    208       // How wallets should render this currency.
    209       currency_specification: CurrencySpecification;
    210 
    211       // Small(est?) amount that can likely be transferred to
    212       // the exchange. Should be the default amount for KYC
    213       // authentication wire transfers to this exchange.
    214       // Optional, not present if not known or not configured.
    215       // @since protocol **v21**.
    216       tiny_amount?: Amount;
    217 
    218       // Absolute cost offset for the STEFAN curve used
    219       // to (over) approximate fees payable by amount.
    220       stefan_abs: Amount;
    221 
    222       // Factor to multiply the logarithm of the amount
    223       // with to (over) approximate fees payable by amount.
    224       // Note that the total to be paid is first to be
    225       // divided by the smallest denomination to obtain
    226       // the value that the logarithm is to be taken of.
    227       stefan_log: Amount;
    228 
    229       // Linear cost factor for the STEFAN curve used
    230       // to (over) approximate fees payable by amount.
    231       //
    232       // Note that this is a scalar, as it is multiplied
    233       // with the actual amount.
    234       stefan_lin: Float;
    235 
    236       // Type of the asset. "fiat", "crypto", "regional"
    237       // or "stock".  Wallets should adjust their UI/UX
    238       // based on this value.
    239       asset_type: string;
    240 
    241       // Array of wire accounts operated by the exchange for
    242       // incoming wire transfers.
    243       accounts: ExchangeWireAccount[];
    244 
    245       // Object mapping names of wire methods (i.e. "iban" or "x-taler-bank")
    246       // to wire fees.
    247       wire_fees: { method : AggregateTransferFee[] };
    248 
    249       // List of exchanges that this exchange is partnering
    250       // with to enable wallet-to-wallet transfers.
    251       wads: ExchangePartnerListEntry[];
    252 
    253       // Set to true if this exchange allows the use
    254       // of reserves for rewards.
    255       // @deprecated in protocol **v18**.
    256       rewards_allowed: false;
    257 
    258       // Set to true if this exchange has KYC enabled and thus
    259       // requires KYC auth wire transfers prior to a first deposit.
    260       // @since in protocol **v24**.
    261       kyc_enabled: boolean;
    262 
    263       // Set to TRUE if wallets should disable the direct deposit feature
    264       // and deposits should only go via Taler merchant APIs.
    265       // Mainly used for regional currency and event currency deployments
    266       // where wallets are not eligible to deposit back into originating
    267       // bank accounts and, because KYC is not enabled, wallets are thus
    268       // likely to send money to nirvana instead of where users want it.
    269       // @since in protocol **v30**.
    270       disable_direct_deposit: boolean;
    271 
    272       // EdDSA master public key of the exchange, used to sign entries
    273       // in ``denoms`` and ``signkeys``.
    274       master_public_key: EddsaPublicKey;
    275 
    276       // Relative duration until inactive reserves are closed;
    277       // not signed (!), can change without notice.
    278       reserve_closing_delay: RelativeTime;
    279 
    280       // Threshold amounts beyond which wallet should
    281       // trigger the KYC process of the issuing exchange.
    282       // Optional option, if not given there is no limit.
    283       // Currency must match ``currency``.
    284       wallet_balance_limit_without_kyc?: Amount[];
    285 
    286       // Array of limits that apply to all accounts.
    287       // All of the given limits will be hard limits.
    288       // Wallets and merchants are expected to obey them
    289       // and not even allow the user to cross them.
    290       // @since protocol **v21**.
    291       hard_limits: AccountLimit[];
    292 
    293       // Array of limits with a soft threshold of zero
    294       // that apply to all accounts without KYC.
    295       // Wallets and merchants are expected to trigger
    296       // a KYC process before attempting any zero-limited
    297       // operations.
    298       // @since protocol **v21**.
    299       zero_limits: ZeroLimitedOperation[];
    300 
    301       // Denominations offered by this exchange
    302       denominations: DenomGroup[];
    303 
    304       // Compact EdDSA `signature` (binary-only) over the
    305       // contatentation of all of the master_sigs (in reverse
    306       // chronological order by group) in the arrays under
    307       // "denominations".  Signature of `TALER_ExchangeKeySetPS`
    308       exchange_sig: EddsaSignature;
    309 
    310       // Public EdDSA key of the exchange that was used to generate the signature.
    311       // Should match one of the exchange's signing keys from ``signkeys``.  It is given
    312       // explicitly as the client might otherwise be confused by clock skew as to
    313       // which signing key was used for the ``exchange_sig``.
    314       exchange_pub: EddsaPublicKey;
    315 
    316       // Denominations for which the exchange currently offers/requests recoup.
    317       recoup: RecoupDenoms[];
    318 
    319       // Array of globally applicable fees by time range.
    320       global_fees: GlobalFees[];
    321 
    322       // The date when the denomination keys were last updated.
    323       list_issue_date: Timestamp;
    324 
    325       // Auditors of the exchange.
    326       auditors: AuditorKeys[];
    327 
    328       // The exchange's signing keys.
    329       signkeys: SignKey[];
    330 
    331       // Optional field with a dictionary of (name, object) pairs defining the
    332       // supported and enabled extensions, such as ``age_restriction``.
    333       extensions?: { name: ExtensionManifest };
    334 
    335       // Signature by the exchange master key of the SHA-256 hash of the
    336       // normalized JSON-object of field extensions, if it was set.
    337       // The signature has purpose TALER_SIGNATURE_MASTER_EXTENSIONS.
    338       extensions_sig?: EddsaSignature;
    339 
    340     }
    341 
    342   The specification for the account object is:
    343 
    344   .. ts:def:: ExchangeWireAccount
    345 
    346     interface ExchangeWireAccount {
    347       // Full ``payto://`` URI identifying the account and wire method
    348       payto_uri: string;
    349 
    350       // URI to convert amounts from or to the currency used by
    351       // this wire account of the exchange. Missing if no
    352       // conversion is applicable.
    353       conversion_url?: string;
    354 
    355       // Restrictions that apply to bank accounts that would send
    356       // funds to the exchange (crediting this exchange bank account).
    357       // Optional, empty array for unrestricted.
    358       credit_restrictions: AccountRestriction[];
    359 
    360       // Restrictions that apply to bank accounts that would receive
    361       // funds from the exchange (debiting this exchange bank account).
    362       // Optional, empty array for unrestricted.
    363       debit_restrictions: AccountRestriction[];
    364 
    365       // Signature using the exchange's offline key over
    366       // a `TALER_MasterWireDetailsPS`
    367       // with purpose ``TALER_SIGNATURE_MASTER_WIRE_DETAILS``.
    368       master_sig: EddsaSignature;
    369 
    370       // Display label wallets should use to show this
    371       // bank account.
    372       // @since protocol **v19**.
    373       bank_label?: string;
    374 
    375       // *Signed* integer with the display priority for
    376       // this bank account. Optional, 0 if missing.
    377       // @since protocol **v19**.
    378       priority?: Integer;
    379 
    380     }
    381 
    382   .. ts:def:: AccountRestriction
    383 
    384     type AccountRestriction =
    385       | RegexAccountRestriction
    386       | DenyAllAccountRestriction
    387 
    388   .. ts:def:: DenyAllAccountRestriction
    389 
    390     // Account restriction that disables this type of
    391     // account for the indicated operation categorically.
    392     interface DenyAllAccountRestriction {
    393 
    394       type: "deny";
    395     }
    396 
    397   .. ts:def:: RegexAccountRestriction
    398 
    399     // Accounts interacting with this type of account
    400     // restriction must have a normalized payto://-URI matching
    401     // the given regex.
    402     interface RegexAccountRestriction {
    403 
    404       type: "regex";
    405 
    406       // Regular expression that the payto://-URI of the
    407       // partner account must follow.  The regular expression
    408       // should follow posix-egrep, but without support for character
    409       // classes, GNU extensions, back-references or intervals. See
    410       // https://www.gnu.org/software/findutils/manual/html_node/find_html/posix_002degrep-regular-expression-syntax.html
    411       // for a description of the posix-egrep syntax. Applications
    412       // may support regexes with additional features, but exchanges
    413       // must not use such regexes.
    414       payto_regex: string;
    415 
    416       // Hint for a human to understand the restriction
    417       // (that is hopefully easier to comprehend than the regex itself).
    418       human_hint: string;
    419 
    420       // Map from IETF BCP 47 language tags to localized
    421       // human hints.
    422       human_hint_i18n?: { [lang_tag: string]: string };
    423 
    424     }
    425 
    426   .. ts:def:: ZeroLimitedOperation
    427 
    428     interface ZeroLimitedOperation {
    429 
    430       // Operation that is limited to an amount of
    431       // zero until the client has passed some KYC check.
    432       // Must be one of "WITHDRAW", "DEPOSIT",
    433       // (p2p) "MERGE", (wallet) "BALANCE",
    434       // (reserve) "CLOSE", "AGGREGATE",
    435       // "TRANSACTION" or "REFUND".
    436       operation_type: string;
    437 
    438     }
    439 
    440 
    441   .. ts:def:: AccountLimit
    442 
    443     interface AccountLimit {
    444 
    445       // Operation that is limited.
    446       // Must be one of "WITHDRAW", "DEPOSIT",
    447       // (p2p) "MERGE", (wallet) "BALANCE",
    448       // (reserve) "CLOSE", "AGGREGATE",
    449       // "TRANSACTION" or "REFUND".
    450       operation_type: string;
    451 
    452       // Timeframe during which the limit applies.
    453       // Not applicable for all operation_types
    454       // (but always present in this object anyway).
    455       timeframe: RelativeTime;
    456 
    457       // Maximum amount allowed during the given timeframe.
    458       // Zero if the operation is simply forbidden.
    459       threshold: Amount;
    460 
    461       // True if this is a soft limit that could be raised
    462       // by passing KYC checks.  Clients *may* deliberately
    463       // try to cross limits and trigger measures resulting
    464       // in 451 responses to begin KYC processes.
    465       // Clients that are aware of hard limits *should*
    466       // inform users about the hard limit and prevent flows
    467       // in the UI that would cause violations of hard limits.
    468       // Made optional in **v21** with a default of 'false' if missing.
    469       soft_limit?: boolean;
    470     }
    471 
    472   .. ts:def:: GlobalFees
    473 
    474     interface GlobalFees {
    475 
    476       // What date (inclusive) does these fees go into effect?
    477       start_date: Timestamp;
    478 
    479       // What date (exclusive) does this fees stop going into effect?
    480       end_date: Timestamp;
    481 
    482       // Account history fee, charged when a user wants to
    483       // obtain a reserve/account history.
    484       history_fee: Amount;
    485 
    486       // Annual fee charged for having an open account at the
    487       // exchange.  Charged to the account.  If the account
    488       // balance is insufficient to cover this fee, the account
    489       // is automatically deleted/closed. (Note that the exchange
    490       // will keep the account history around for longer for
    491       // regulatory reasons.)
    492       account_fee: Amount;
    493 
    494       // Purse fee, charged only if a purse is abandoned
    495       // and was not covered by the account limit.
    496       purse_fee: Amount;
    497 
    498       // How long will the exchange preserve the account history?
    499       // After an account was deleted/closed, the exchange will
    500       // retain the account history for legal reasons until this time.
    501       history_expiration: RelativeTime;
    502 
    503       // Non-negative number of concurrent purses that any
    504       // account holder is allowed to create without having
    505       // to pay the purse_fee.
    506       purse_account_limit: Integer;
    507 
    508       // How long does an exchange keep a purse around after a purse
    509       // has expired (or been successfully merged)?  A 'GET' request
    510       // for a purse will succeed until the purse expiration time
    511       // plus this value.
    512       purse_timeout: RelativeTime;
    513 
    514       // Signature of `TALER_GlobalFeesPS`.
    515       master_sig: EddsaSignature;
    516 
    517     }
    518 
    519   .. ts:def:: DenomGroup
    520 
    521     type DenomGroup =
    522       | DenomGroupRsa
    523       | DenomGroupCs
    524       | DenomGroupRsaAgeRestricted
    525       | DenomGroupCsAgeRestricted;
    526 
    527   .. ts:def:: DenomGroupRsa
    528 
    529     interface DenomGroupRsa extends DenomGroupCommon {
    530       cipher: "RSA";
    531 
    532       denoms: ({
    533         rsa_pub: RsaPublicKey;
    534       } & DenomCommon)[];
    535     }
    536 
    537   .. ts:def:: DenomGroupCs
    538 
    539     interface DenomGroupCs extends DenomGroupCommon {
    540       cipher: "CS";
    541 
    542       denoms: ({
    543         cs_pub: Cs25519Point;
    544       } & DenomCommon)[];
    545     }
    546 
    547   .. ts:def:: DenomGroupRsaAgeRestricted
    548 
    549     interface DenomGroupRsaAgeRestricted extends DenomGroupCommon {
    550       cipher: "RSA+age_restricted";
    551       age_mask: AgeMask;
    552 
    553       denoms: ({
    554         rsa_pub: RsaPublicKey;
    555       } & DenomCommon)[];
    556     }
    557 
    558   .. ts:def:: DenomGroupCsAgeRestricted
    559 
    560     interface DenomGroupCsAgeRestricted extends DenomGroupCommon {
    561       cipher: "CS+age_restricted";
    562       age_mask: AgeMask;
    563 
    564       denoms: ({
    565         cs_pub: Cs25519Point;
    566       } & DenomCommon)[];
    567     }
    568 
    569   .. ts:def:: DenomGroupCommon
    570 
    571     // Common attributes for all denomination groups
    572     interface DenomGroupCommon {
    573       // How much are coins of this denomination worth?
    574       value: Amount;
    575 
    576       // Fee charged by the exchange for withdrawing a coin of this denomination.
    577       fee_withdraw: Amount;
    578 
    579       // Fee charged by the exchange for depositing a coin of this denomination.
    580       fee_deposit: Amount;
    581 
    582       // Fee charged by the exchange for refreshing a coin of this denomination.
    583       fee_refresh: Amount;
    584 
    585       // Fee charged by the exchange for refunding a coin of this denomination.
    586       fee_refund: Amount;
    587 
    588     }
    589 
    590   .. ts:def:: DenomCommon
    591 
    592     interface DenomCommon {
    593       // Signature of `TALER_DenominationKeyValidityPS`.
    594       master_sig: EddsaSignature;
    595 
    596       // When does the denomination key become valid?
    597       stamp_start: Timestamp;
    598 
    599       // When is it no longer possible to withdraw coins
    600       // of this denomination?
    601       stamp_expire_withdraw: Timestamp;
    602 
    603       // When is it no longer possible to deposit coins
    604       // of this denomination?
    605       stamp_expire_deposit: Timestamp;
    606 
    607       // Timestamp indicating by when legal disputes relating to these coins must
    608       // be settled, as the exchange will afterwards destroy its evidence relating to
    609       // transactions involving this coin.
    610       stamp_expire_legal: Timestamp;
    611 
    612       // Set to 'true' if the exchange somehow "lost"
    613       // the private key. The denomination was not
    614       // necessarily revoked, but still cannot be used
    615       // to withdraw coins at this time (theoretically,
    616       // the private key could be recovered in the
    617       // future; coins signed with the private key
    618       // remain valid).
    619       lost?: boolean;
    620     }
    621 
    622   Fees for any of the operations can be zero, but the fields must still be
    623   present. The currency of the ``fee_deposit``, ``fee_refresh`` and ``fee_refund`` must match the
    624   currency of the ``value``.  Theoretically, the ``fee_withdraw`` could be in a
    625   different currency, but this is not currently supported by the
    626   implementation.
    627 
    628   .. ts:def:: RecoupDenoms
    629 
    630     interface RecoupDenoms {
    631       // Hash of the public key of the denomination that is being revoked under
    632       // emergency protocol (see ``/recoup``).
    633       h_denom_pub: HashCode;
    634 
    635       // We do not include any signature here, as the primary use-case for
    636       // this emergency involves the exchange having lost its signing keys,
    637       // so such a signature here would be pretty worthless.  However, the
    638       // exchange will not honor ``/recoup`` requests unless they are for
    639       // denomination keys listed here.
    640     }
    641 
    642   A signing key in the ``signkeys`` list is a JSON object with the following fields:
    643 
    644   .. ts:def:: SignKey
    645 
    646     interface SignKey {
    647       // The actual exchange's EdDSA signing public key.
    648       key: EddsaPublicKey;
    649 
    650       // Initial validity date for the signing key.
    651       stamp_start: Timestamp;
    652 
    653       // Date when the exchange will stop using the signing key, allowed to overlap
    654       // slightly with the next signing key's validity to allow for clock skew.
    655       stamp_expire: Timestamp;
    656 
    657       // Date when all signatures made by the signing key expire and should
    658       // henceforth no longer be considered valid in legal disputes.
    659       stamp_end: Timestamp;
    660 
    661       // Signature over ``key`` and ``stamp_expire`` by the exchange master key.
    662       // Signature of `TALER_ExchangeSigningKeyValidityPS`.
    663       // Must have purpose ``TALER_SIGNATURE_MASTER_SIGNING_KEY_VALIDITY``.
    664       master_sig: EddsaSignature;
    665     }
    666 
    667   An entry in the ``auditors`` list is a JSON object with the following fields:
    668 
    669   .. ts:def:: AuditorKeys
    670 
    671     interface AuditorKeys {
    672       // The auditor's EdDSA signing public key.
    673       auditor_pub: EddsaPublicKey;
    674 
    675       // The auditor's URL.
    676       auditor_url: string;
    677 
    678       // The auditor's name (for humans).
    679       auditor_name: string;
    680 
    681       // An array of denomination keys the auditor affirms with its signature.
    682       // Note that the message only includes the hash of the public key, while the
    683       // signature is actually over the expanded information including expiration
    684       // times and fees.  The exact format is described below.
    685       denomination_keys: AuditorDenominationKey[];
    686     }
    687 
    688   .. ts:def:: AuditorDenominationKey
    689 
    690     interface AuditorDenominationKey {
    691       // Hash of the public RSA key used to sign coins of the respective
    692       // denomination.  Note that the auditor's signature covers more than just
    693       // the hash, but this other information is already provided in ``denoms`` and
    694       // thus not repeated here.
    695       denom_pub_h: HashCode;
    696 
    697       // Signature of `TALER_ExchangeKeyValidityPS`.
    698       auditor_sig: EddsaSignature;
    699     }
    700 
    701   The same auditor may appear multiple times in the array for different subsets
    702   of denomination keys, and the same denomination key hash may be listed
    703   multiple times for the same or different auditors.  The wallet or merchant
    704   just should check that the denomination keys they use are in the set for at
    705   least one of the auditors that they accept.
    706 
    707   .. note::
    708 
    709     Both the individual denominations *and* the denomination list is signed,
    710     allowing customers to prove that they received an inconsistent list.
    711 
    712   Aggregate wire transfer fees representing the fees the exchange
    713   charges per wire transfer to a merchant must be specified as an
    714   array in all wire transfer response objects under ``fees``.  The
    715   respective array contains objects with the following members:
    716 
    717   .. ts:def:: AggregateTransferFee
    718 
    719     interface AggregateTransferFee {
    720       // Per transfer wire transfer fee.
    721       wire_fee: Amount;
    722 
    723       // Per transfer closing fee.
    724       closing_fee: Amount;
    725 
    726       // What date (inclusive) does this fee go into effect?
    727       // The different fees must cover the full time period in which
    728       // any of the denomination keys are valid without overlap.
    729       start_date: Timestamp;
    730 
    731       // What date (exclusive) does this fee stop going into effect?
    732       // The different fees must cover the full time period in which
    733       // any of the denomination keys are valid without overlap.
    734       end_date: Timestamp;
    735 
    736       // Signature of `TALER_MasterWireFeePS` with
    737       // purpose ``TALER_SIGNATURE_MASTER_WIRE_FEES``.
    738       sig: EddsaSignature;
    739     }
    740 
    741   .. ts:def:: ExchangePartnerListEntry
    742 
    743     interface ExchangePartnerListEntry {
    744       // Base URL of the partner exchange.
    745       partner_base_url: string;
    746 
    747       // Public master key of the partner exchange.
    748       partner_master_pub: EddsaPublicKey;
    749 
    750       // Per exchange-to-exchange transfer (wad) fee.
    751       wad_fee: Amount;
    752 
    753       // Exchange-to-exchange wad (wire) transfer frequency.
    754       wad_frequency: RelativeTime;
    755 
    756       // When did this partnership begin (under these conditions)?
    757       start_date: Timestamp;
    758 
    759       // How long is this partnership expected to last?
    760       end_date: Timestamp;
    761 
    762       // Signature using the exchange's offline key over
    763       // `TALER_WadPartnerSignaturePS`
    764       // with purpose ``TALER_SIGNATURE_MASTER_PARTNER_DETAILS``.
    765       master_sig: EddsaSignature;
    766     }
    767 
    768 
    769 
    770 
    771 ----------------------------------------------
    772 Management operations authorized by master key
    773 ----------------------------------------------
    774 
    775 .. http:get:: /management/keys
    776 
    777   Get a list of future public keys to be used by the exchange.  Only to be
    778   used by the exchange's offline key management team. Not useful for anyone
    779   else (but also not secret, so access is public).
    780 
    781   **Response:**
    782 
    783   :http:statuscode:`200 OK`:
    784     The exchange responds with a `FutureKeysResponse` object. This request should
    785     virtually always be successful.
    786 
    787   **Details:**
    788 
    789   .. ts:def:: FutureKeysResponse
    790 
    791     interface FutureKeysResponse {
    792 
    793       // Future denominations to be offered by this exchange
    794       // (only those lacking a master signature).
    795       future_denoms: FutureDenom[];
    796 
    797       // The exchange's future signing keys (only those lacking a master signature).
    798       future_signkeys: FutureSignKey[];
    799 
    800       // Master public key expected by this exchange (provided so that the
    801       // offline signing tool can check that it has the right key).
    802       master_pub: EddsaPublicKey;
    803 
    804       // Public key of the denomination security module.
    805       denom_secmod_public_key: EddsaPublicKey;
    806 
    807       // Public key of the signkey security module.
    808       signkey_secmod_public_key: EddsaPublicKey;
    809 
    810     }
    811 
    812   .. ts:def:: FutureDenom
    813 
    814     interface FutureDenom {
    815       // Name in the configuration file that defines this denomination.
    816       section_name: string;
    817 
    818       // How much are coins of this denomination worth?
    819       value: Amount;
    820 
    821       // When does the denomination key become valid?
    822       stamp_start: Timestamp;
    823 
    824       // When is it no longer possible to withdraw coins
    825       // of this denomination?
    826       stamp_expire_withdraw: Timestamp;
    827 
    828       // When is it no longer possible to deposit coins
    829       // of this denomination?
    830       stamp_expire_deposit: Timestamp;
    831 
    832       // Timestamp indicating by when legal disputes relating to these coins must
    833       // be settled, as the exchange will afterwards destroy its evidence relating to
    834       // transactions involving this coin.
    835       stamp_expire_legal: Timestamp;
    836 
    837       // Public key for the denomination.
    838       denom_pub: DenominationKey;
    839 
    840       // Fee charged by the exchange for withdrawing a coin of this denomination.
    841       fee_withdraw: Amount;
    842 
    843       // Fee charged by the exchange for depositing a coin of this denomination.
    844       fee_deposit: Amount;
    845 
    846       // Fee charged by the exchange for refreshing a coin of this denomination.
    847       fee_refresh: Amount;
    848 
    849       // Fee charged by the exchange for refunding a coin of this denomination.
    850       fee_refund: Amount;
    851 
    852       // Signature by the denomination security module
    853       // over `TALER_DenominationKeyAnnouncementPS`
    854       // for this denomination with purpose
    855       // ``TALER_SIGNATURE_SM_DENOMINATION_KEY``.
    856       denom_secmod_sig: EddsaSignature;
    857 
    858     }
    859 
    860   .. ts:def:: DenominationKey
    861 
    862     type DenominationKey =
    863       | RsaDenominationKey
    864       | CSDenominationKey;
    865 
    866   .. ts:def:: RsaDenominationKey
    867 
    868     interface RsaDenominationKey {
    869       cipher: "RSA";
    870 
    871       // 32-bit age mask.
    872       age_mask: Integer;
    873 
    874       // RSA public key
    875       rsa_pub: RsaPublicKey;
    876     }
    877 
    878   .. ts:def:: CSDenominationKey
    879 
    880     interface CSDenominationKey {
    881       cipher: "CS";
    882 
    883       // 32-bit age mask.
    884       age_mask: Integer;
    885 
    886       // Public key of the denomination.
    887       cs_pub: Cs25519Point;
    888 
    889     }
    890 
    891   .. ts:def:: FutureSignKey
    892 
    893     interface FutureSignKey {
    894       // The actual exchange's EdDSA signing public key.
    895       key: EddsaPublicKey;
    896 
    897       // Initial validity date for the signing key.
    898       stamp_start: Timestamp;
    899 
    900       // Date when the exchange will stop using the signing key, allowed to overlap
    901       // slightly with the next signing key's validity to allow for clock skew.
    902       stamp_expire: Timestamp;
    903 
    904       // Date when all signatures made by the signing key expire and should
    905       // henceforth no longer be considered valid in legal disputes.
    906       stamp_end: Timestamp;
    907 
    908       // Signature over `TALER_SigningKeyAnnouncementPS`
    909       // for this signing key by the signkey security
    910       // module using purpose ``TALER_SIGNATURE_SM_SIGNING_KEY``.
    911       signkey_secmod_sig: EddsaSignature;
    912     }
    913 
    914 
    915 .. http:post:: /management/keys
    916 
    917   Provide master signatures for future public keys to be used by the exchange.
    918   Only to be used by the exchange's offline key management team. Not useful
    919   for anyone else.
    920 
    921   **Request:**
    922 
    923   The request body must be a `MasterSignatures` object.
    924 
    925   **Response:**
    926 
    927   :http:statuscode:`204 No content`:
    928     The request was successfully processed.
    929   :http:statuscode:`403 Forbidden`:
    930     A provided signature is invalid.
    931   :http:statuscode:`404 Not found`:
    932     One of the keys for which a signature was provided is unknown to the exchange.
    933 
    934   **Details:**
    935 
    936   .. ts:def:: MasterSignatures
    937 
    938     interface MasterSignatures {
    939 
    940       // Provided master signatures for future denomination keys.
    941       denom_sigs: DenomSignature[];
    942 
    943       // Provided master signatures for future online signing keys.
    944       signkey_sigs: SignKeySignature[];
    945 
    946     }
    947 
    948   .. ts:def:: DenomSignature
    949 
    950     interface DenomSignature {
    951 
    952       // Hash of the public key of the denomination.
    953       h_denom_pub: HashCode;
    954 
    955       // Signature over `TALER_DenominationKeyValidityPS`.
    956       // Must have purpose ``TALER_SIGNATURE_MASTER_DENOMINATION_KEY_VALIDITY``
    957       master_sig: EddsaSignature;
    958 
    959     }
    960 
    961   .. ts:def:: SignKeySignature
    962 
    963     interface SignKeySignature {
    964       // The actual exchange's EdDSA signing public key.
    965       key: EddsaPublicKey;
    966 
    967       // Signature by the exchange master key over
    968       // `TALER_ExchangeSigningKeyValidityPS`.
    969       // Must have purpose ``TALER_SIGNATURE_MASTER_SIGNING_KEY_VALIDITY``.
    970       master_sig: EddsaSignature;
    971 
    972     }
    973 
    974 
    975 .. http:post:: /management/denominations/$H_DENOM_PUB/revoke
    976 
    977   Revoke denomination key, preventing further use by the exchange.
    978   Only to be used by the exchange's offline key management team. Not useful
    979   for anyone else.
    980 
    981   **Request:**
    982 
    983   The request body must be a `DenomRevocationSignature` object.
    984 
    985   **Response:**
    986 
    987   :http:statuscode:`204 No content`:
    988     The request was successfully processed.
    989   :http:statuscode:`403 Forbidden`:
    990     The provided signature is invalid.
    991 
    992   **Details:**
    993 
    994   .. ts:def:: DenomRevocationSignature
    995 
    996     interface DenomRevocationSignature {
    997 
    998       // Signature by the exchange master key over a
    999       // `TALER_MasterDenominationKeyRevocationPS`.
   1000       // Must have purpose ``TALER_SIGNATURE_MASTER_DENOMINATION_KEY_REVOKED``.
   1001       master_sig: EddsaSignature;
   1002 
   1003     }
   1004 
   1005 .. http:post:: /management/signkeys/$EXCHANGE_PUB/revoke
   1006 
   1007   Revoke exchange online signing key, preventing further use by the exchange.
   1008   Only to be used by the exchange's offline key management team. Not useful
   1009   for anyone else.
   1010 
   1011   **Request:**
   1012 
   1013   The request body must be a `SignkeyRevocationSignature` object.
   1014 
   1015   **Response:**
   1016 
   1017   :http:statuscode:`204 No content`:
   1018     The request was successfully processed.
   1019   :http:statuscode:`403 Forbidden`:
   1020     The provided signature is invalid.
   1021 
   1022   **Details:**
   1023 
   1024   .. ts:def:: SignkeyRevocationSignature
   1025 
   1026     interface SignkeyRevocationSignature {
   1027 
   1028       // Signature by the exchange master key over a
   1029       // `TALER_MasterSigningKeyRevocationPS`.
   1030       // Must have purpose ``TALER_SIGNATURE_MASTER_SIGN_KEY_REVOKED``.
   1031       master_sig: EddsaSignature;
   1032 
   1033     }
   1034 
   1035 
   1036 .. http:post:: /management/auditors
   1037 
   1038   This request will be used to enable an auditor.
   1039 
   1040   **Request:**
   1041 
   1042   The request must be a `AuditorSetupMessage`.
   1043 
   1044   **Response:**
   1045 
   1046   :http:statuscode:`204 No content`:
   1047     The auditor was successfully enabled.
   1048   :http:statuscode:`403 Forbidden`:
   1049     The master signature is invalid.
   1050   :http:statuscode:`409 Conflict`:
   1051     The exchange has a more recent request related to this auditor key (replay detected).
   1052 
   1053   **Details:**
   1054 
   1055   .. ts:def:: AuditorSetupMessage
   1056 
   1057     interface AuditorSetupMessage {
   1058 
   1059       // Base URL of the auditor.
   1060       auditor_url: string;
   1061 
   1062       // Human-readable name of the auditor.
   1063       auditor_name: string;
   1064 
   1065       // The auditor's EdDSA signing public key.
   1066       auditor_pub: EddsaPublicKey;
   1067 
   1068       // Signature by the exchange master ke yover a
   1069       // `TALER_MasterAddAuditorPS`.
   1070       // Must have purpose ``TALER_SIGNATURE_MASTER_ADD_AUDITOR``.
   1071       master_sig: EddsaSignature;
   1072 
   1073       // When does the auditor become active?
   1074       // Should be the time when the signature was created,
   1075       // using the (monotonic!) local time of the system
   1076       // with the offline master public key. Note that
   1077       // even if the time is in the future, the auditor will
   1078       // become active immediately! Used ONLY to detect replay attacks.
   1079       validity_start: Timestamp;
   1080 
   1081     }
   1082 
   1083 .. http:post:: /management/auditors/$AUDITOR_PUB/disable
   1084 
   1085   This request will be used to disable the use of the given auditor.
   1086   We use POST instead of DELETE because the exchange will retain state
   1087   about the auditor (specifically the end date) to prevent replay
   1088   attacks abusing the `AuditorSetupMessage`.  Also, DELETE would not
   1089   support a body, which is needed to provide the signature authorizing
   1090   the operation.
   1091 
   1092   **Request:**
   1093 
   1094   The request must be a `AuditorTeardownMessage`.
   1095 
   1096   **Response**
   1097 
   1098   :http:statuscode:`204 No content`:
   1099     The auditor has successfully disabled the auditor. The body is empty.
   1100   :http:statuscode:`403 Forbidden`:
   1101     The signature is invalid.
   1102   :http:statuscode:`404 Not found`:
   1103     The auditor is unknown to the exchange.
   1104   :http:statuscode:`409 Conflict`:
   1105     The exchange has a more recent request related to this auditor key (replay detected).
   1106 
   1107   **Details:**
   1108 
   1109   .. ts:def:: AuditorTeardownMessage
   1110 
   1111     interface AuditorTeardownMessage {
   1112 
   1113       // Signature by the exchange master key over a
   1114       // `TALER_MasterDelAuditorPS`.
   1115       // Must have purpose ``TALER_SIGNATURE_MASTER_AUDITOR_DEL``.
   1116       master_sig: EddsaSignature;
   1117 
   1118       // When does the auditor become inactive?
   1119       // Should be the time when the signature was created,
   1120       // using the (monotonic!) local time of the system
   1121       // with the offline master public key.  Note that
   1122       // even if the time is in the future, the auditor will
   1123       // become inactive immediately! Used ONLY to detect replay attacks.
   1124       validity_end: Timestamp;
   1125 
   1126     }
   1127 
   1128 
   1129 .. http:post:: /management/wire-fee
   1130 
   1131   This request is used to configure wire fees.
   1132 
   1133   **Request:**
   1134 
   1135   The request must be a `WireFeeSetupMessage`.
   1136 
   1137   **Response:**
   1138 
   1139   :http:statuscode:`204 No content`:
   1140     The wire fee was successfully configured.
   1141   :http:statuscode:`403 Forbidden`:
   1142     The master signature is invalid.
   1143   :http:statuscode:`409 Conflict`:
   1144     The exchange has a conflicting wire fee already set up.
   1145 
   1146   **Details:**
   1147 
   1148   .. ts:def:: WireFeeSetupMessage
   1149 
   1150     interface WireFeeSetupMessage {
   1151 
   1152       // Wire method the fee applies to.
   1153       wire_method: string;
   1154 
   1155       // Signature using the exchange's offline key
   1156       // with purpose ``TALER_SIGNATURE_MASTER_WIRE_FEES``.
   1157       master_sig_wire: EddsaSignature;
   1158 
   1159       // When does the wire fee validity period start?
   1160       fee_start: Timestamp;
   1161 
   1162       // When does the wire fee validity period end (exclusive).
   1163       fee_end: Timestamp;
   1164 
   1165       // Closing fee to charge during that time period for this wire method.
   1166       closing_fee: Amount;
   1167 
   1168       // Wire fee to charge during that time period for this wire method.
   1169       wire_fee: Amount;
   1170 
   1171     }
   1172 
   1173 .. http:post:: /management/global-fees
   1174 
   1175   Provides global fee configuration for a timeframe.
   1176 
   1177   **Request:**
   1178 
   1179   The request must be a `GlobalFees` message.
   1180 
   1181   **Response:**
   1182 
   1183   :http:statuscode:`204 No content`:
   1184     The configuration update has been processed successfully. The body is empty.
   1185   :http:statuscode:`403 Forbidden`:
   1186     The signature is invalid.
   1187   :http:statuscode:`409 Conflict`:
   1188     The exchange has previously received a conflicting configuration message.
   1189 
   1190 
   1191 
   1192 .. http:post:: /management/wire
   1193 
   1194   This request will be used to enable a wire method (exchange bank account).
   1195 
   1196   **Request:**
   1197 
   1198   The request must be a `WireSetupMessage`.
   1199 
   1200   **Response:**
   1201 
   1202   :http:statuscode:`204 No content`:
   1203     The wire method was successfully enabled.
   1204   :http:statuscode:`403 Forbidden`:
   1205     The master signature is invalid.
   1206   :http:statuscode:`409 Conflict`:
   1207     The exchange has a more recent request related to this wire method (replay detected).
   1208 
   1209   **Details:**
   1210 
   1211   .. ts:def:: WireSetupMessage
   1212 
   1213     interface WireSetupMessage {
   1214 
   1215       // Full ``payto://`` URL identifying the account and wire method
   1216       payto_uri: string;
   1217 
   1218       // Signature using the exchange's offline key
   1219       // over a `TALER_MasterWireDetailsPS`
   1220       // with purpose ``TALER_SIGNATURE_MASTER_WIRE_DETAILS``.
   1221       master_sig_wire: EddsaSignature;
   1222 
   1223       // Signature using the exchange's offline key over a
   1224       // `TALER_MasterAddWirePS`
   1225       // with purpose ``TALER_SIGNATURE_MASTER_WIRE_ADD``.
   1226       master_sig_add: EddsaSignature;
   1227 
   1228       // When does the wire method become active?
   1229       // Should be the time when the signature was created,
   1230       // using the (monotonic!) local time of the system
   1231       // with the offline master public key. Note that
   1232       // even if the time is in the future, the wire method will
   1233       // become active immediately! Used ONLY to detect replay attacks.
   1234       validity_start: Timestamp;
   1235 
   1236       // Display label wallets should use to show this
   1237       // bank account.
   1238       // @since protocol **v19**.
   1239       bank_label?: string;
   1240 
   1241       // *Signed* integer with the display priority for
   1242       // this bank account.
   1243       // @since protocol **v19**.
   1244       priority?: Integer;
   1245 
   1246     }
   1247 
   1248 .. http:post:: /management/wire/disable
   1249 
   1250   This request will be used to disable the use of the given wire method.
   1251   We use POST instead of DELETE because the exchange will retain state
   1252   about the wire method (specifically the end date) to prevent replay
   1253   attacks abusing the `WireSetupMessage`.  Also, DELETE would not
   1254   support a body, which is needed to provide the signature authorizing
   1255   the operation.
   1256 
   1257   **Request:**
   1258 
   1259   The request must be a `WireTeardownMessage`.
   1260 
   1261   **Response:**
   1262 
   1263   :http:statuscode:`204 No content`:
   1264     The auditor has successfully disabled the wire method. The body is empty.
   1265   :http:statuscode:`403 Forbidden`:
   1266     The signature is invalid.
   1267   :http:statuscode:`404 Not found`:
   1268     The wire method is unknown to the exchange.
   1269   :http:statuscode:`409 Conflict`:
   1270     The exchange has a more recent request related to this wire method (replay detected).
   1271 
   1272   **Details:**
   1273 
   1274   .. ts:def:: WireTeardownMessage
   1275 
   1276     interface WireTeardownMessage {
   1277 
   1278       // Full ``payto://`` URL identifying the account and wire method
   1279       payto_uri: string;
   1280 
   1281       // Signature using the exchange's offline key over a
   1282       // `TALER_MasterDelWirePS`.
   1283       // with purpose ``TALER_SIGNATURE_MASTER_WIRE_DEL``.
   1284       master_sig_del: EddsaSignature;
   1285 
   1286       // Should be the time when the signature was created,
   1287       // using the (monotonic!) local time of the system
   1288       // with the offline master public key.  Note that
   1289       // even if the time is in the future, the wire method will
   1290       // become inactive immediately! Used ONLY to detect replay attacks.
   1291       validity_end: Timestamp;
   1292 
   1293     }
   1294 
   1295 
   1296 .. http:post:: /management/drain
   1297 
   1298   This request is used to drain profits from the
   1299   exchange's escrow account to another regular
   1300   bank account of the exchange.  The actual drain
   1301   requires running the ``taler-exchange-drain`` tool.
   1302 
   1303   **Request:**
   1304 
   1305   The request must be a `DrainProfitsMessage`.
   1306 
   1307   **Response:**
   1308 
   1309   :http:statuscode:`204 No content`:
   1310     The profit drain was scheduled.
   1311   :http:statuscode:`403 Forbidden`:
   1312     The master signature is invalid.
   1313 
   1314   **Details:**
   1315 
   1316   .. ts:def:: DrainProfitsMessage
   1317 
   1318     interface DrainProfitsMessage {
   1319 
   1320       // Configuration section of the account to debit.
   1321       debit_account_section: string;
   1322 
   1323       // Full payto URI of the account to credit.
   1324       credit_payto_uri: string;
   1325 
   1326       // Wire transfer identifier to use.
   1327       wtid: Base32;
   1328 
   1329       // Signature by the exchange master key over a
   1330       // `TALER_MasterDrainProfitPS`.
   1331       // Must have purpose ``TALER_SIGNATURE_MASTER_DRAIN_PROFITS``.
   1332       master_sig: EddsaSignature;
   1333 
   1334       // When was the message created.
   1335       date: Timestamp;
   1336 
   1337       // Amount to be drained.
   1338       amount: Amount;
   1339 
   1340     }
   1341 
   1342 
   1343 .. http:post:: /management/aml-officers
   1344 
   1345   Update settings for an AML Officer status.
   1346 
   1347   **Request:**
   1348 
   1349   The request must be an `AmlOfficerSetup` message.
   1350 
   1351   **Response:**
   1352 
   1353   :http:statuscode:`204 No content`:
   1354     The officer settings have been updated successfully.
   1355   :http:statuscode:`403 Forbidden`:
   1356     The signature is invalid.
   1357   :http:statuscode:`409 Conflict`:
   1358     The exchange has previously received a conflicting configuration message.
   1359 
   1360   **Details:**
   1361 
   1362   .. ts:def:: AmlOfficerSetup
   1363 
   1364     interface AmlOfficerSetup {
   1365 
   1366       // Public key of the AML officer
   1367       officer_pub: EddsaPublicKey;
   1368 
   1369       // Legal full name of the AML officer
   1370       officer_name: string;
   1371 
   1372       // Is the account active?
   1373       is_active: boolean;
   1374 
   1375       // Is the account read-only?
   1376       read_only: boolean;
   1377 
   1378       // Signature by the exchange master key over a
   1379       // `TALER_MasterAmlOfficerStatusPS`.
   1380       // Must have purpose ``TALER_SIGNATURE_MASTER_AML_KEY``.
   1381       master_sig: EddsaSignature;
   1382 
   1383       // When will the change take effect?
   1384       change_date: Timestamp;
   1385 
   1386     }
   1387 
   1388 
   1389   .. http:post:: /management/partners
   1390 
   1391     Enables a partner exchange for wad transfers.
   1392 
   1393   **Request:**
   1394 
   1395   The request must be an `ExchangePartnerSetupRequest` message.
   1396 
   1397   **Response:**
   1398 
   1399   :http:statuscode:`204 No content`:
   1400     The partner has been added successfully.
   1401   :http:statuscode:`403 Forbidden`:
   1402     The signature is invalid.
   1403   :http:statuscode:`409 Conflict`:
   1404     The exchange has previously received a conflicting configuration message.
   1405 
   1406   **Details:**
   1407 
   1408   .. ts:def:: ExchangePartnerSetupRequest
   1409 
   1410     interface ExchangePartnerSetupRequest {
   1411 
   1412       // Base URL of the partner exchange
   1413       partner_base_url: string;
   1414 
   1415       // Master (offline) public key of the partner exchange.
   1416       partner_pub: EddsaPublicKey;
   1417 
   1418       // How frequently will wad transfers be made
   1419       wad_frequency: RelativeTime;
   1420 
   1421       // Signature by the exchange master key over a
   1422       // `TALER_PartnerConfigurationPS`.
   1423       // Must have purpose ``TALER_SIGNATURE_MASTER_PARTNER_DETAILS``.
   1424       master_sig: EddsaSignature;
   1425 
   1426       // When will the partner relationship start (inclusive).
   1427       start_date: Timestamp;
   1428 
   1429       // When will the partner relationship end (exclusive).
   1430       end_date: Timestamp;
   1431 
   1432       // Wad fee to be charged (to customers).
   1433       wad_fee: Amount;
   1434 
   1435     }
   1436 
   1437 ---------------
   1438 Auditor actions
   1439 ---------------
   1440 
   1441 .. _auditor_action:
   1442 
   1443 This part of the API is for the use by auditors interacting with the exchange.
   1444 
   1445 
   1446 .. http:post:: /auditors/$AUDITOR_PUB/$H_DENOM_PUB
   1447 
   1448   This is used to add an auditor signature to the ``/keys`` response. It
   1449   affirms to wallets and merchants that this auditor is indeed auditing
   1450   the coins issued by the respective denomination.  There is no "delete"
   1451   operation for this, as auditors can only stop auditing a denomination
   1452   when it expires.
   1453 
   1454   **Request:**
   1455 
   1456   The request must be a `AuditorSignatureAddMessage`.
   1457 
   1458   **Response:**
   1459 
   1460   :http:statuscode:`204 No content`:
   1461     The backend has successfully stored the auditor signature.
   1462   :http:statuscode:`403 Forbidden`:
   1463     The auditor signature is invalid.
   1464   :http:statuscode:`404 Not found`:
   1465     The denomination key for which the auditor is providing a signature is unknown.
   1466     The response will be a `DenominationUnknownMessage`.
   1467   :http:statuscode:`410 Gone`:
   1468     This auditor is no longer supported by the exchange.
   1469   :http:statuscode:`412 Precondition failed`:
   1470     This auditor is not yet known to the exchange.
   1471 
   1472   **Details:**
   1473 
   1474   .. ts:def:: DenominationUnknownMessage
   1475 
   1476     interface DenominationUnknownMessage {
   1477 
   1478       // Taler error code
   1479       // ``TALER_EC_EXCHANGE_GENERIC_DENOMINATION_KEY_UNKNOWN``
   1480       code: Integer;
   1481 
   1482       // Signature by the exchange over a
   1483       // `TALER_DenominationUnknownAffirmationPS`.
   1484       // Must have purpose ``TALER_SIGNATURE_EXCHANGE_AFFIRM_DENOM_UNKNOWN``.
   1485       exchange_sig: EddsaSignature;
   1486 
   1487       // Public key of the exchange used to create
   1488       // the 'exchange_sig.
   1489       exchange_pub: EddsaPublicKey;
   1490 
   1491       // Hash of the denomination public key that is unknown.
   1492       h_denom_pub: HashCode;
   1493 
   1494       // When was the signature created.
   1495       timestamp: Timestamp;
   1496 
   1497     }
   1498 
   1499   .. ts:def:: AuditorSignatureAddMessage
   1500 
   1501     interface AuditorSignatureAddMessage {
   1502 
   1503       // Signature by the auditor over a
   1504       // `TALER_ExchangeKeyValidityPS`.
   1505       // Must have purpose ``TALER_SIGNATURE_AUDITOR_EXCHANGE_KEYS``.
   1506       auditor_sig: EddsaSignature;
   1507 
   1508     }
   1509 
   1510 
   1511 ----------------
   1512 Blinding Prepare
   1513 ----------------
   1514 
   1515 Certain denomination cipher types, such as Clause-Schnorr, require input values
   1516 from the exchange-side as preparation for the blinding of the coins.  See the
   1517 Bachelor thesis of Gian Demarmels and Lucien Heuzeveldt,
   1518 `Adding Schnorr’s Blind Signature in Taler <https://www.taler.net/papers/cs-thesis.pdf>`_,
   1519 for details.
   1520 
   1521 .. http:post:: /blinding-prepare
   1522 
   1523   Obtain exchange-side input values in preparation for a
   1524   blinding step of multiple coins for certain denomination
   1525   cipher types, specifically at this point for Clause-Schnorr
   1526   blind signatures.
   1527 
   1528   **Request:**
   1529 
   1530   The request body must be a `BlindingPrepareRequest` object.
   1531 
   1532   **Response:**
   1533 
   1534   :http:statuscode:`200 OK`:
   1535     The request was successful, and the response is a
   1536     `BlindingPrepareResponse`.  Note that repeating exactly the same request
   1537     will again yield the same response (assuming none of the denominations is
   1538     expired).
   1539   :http:statuscode:`404 Not found`:
   1540     A denomination key is not known to the exchange.
   1541     The response is a `DenominationUnknownMessage`.
   1542   :http:statuscode:`410 Gone`:
   1543     A requested denomination key is not yet or no longer valid.
   1544     It either before the validity start, past the expiration or was revoked.
   1545     The response is a `DenominationGoneMessage`.
   1546     Clients must evaluate the error code provided to understand
   1547     which of the cases this is and handle it accordingly.
   1548 
   1549   **Details:**
   1550 
   1551 
   1552   .. ts:def:: BlindingPrepareRequest
   1553 
   1554     type BlindingPrepareRequest = BlindingPrepareRequestCS;
   1555 
   1556 
   1557   .. ts:def:: BlindingPrepareRequestCS
   1558 
   1559     interface BlindingPrepareRequestCS {
   1560       // Cipher type
   1561       cipher: "CS";
   1562 
   1563       // The type of operation this blinding is for.
   1564       operation: "withdraw" | "melt";
   1565 
   1566       // Master seed for the Clause-Schnorr R-value creation.
   1567       // MUST not have been used in any prior request of this type.
   1568       seed: BlindingMasterSeed;
   1569 
   1570       // Array of denominations and coin offsets for
   1571       // each of the fresh coins with a CS-cipher
   1572       // denomination.
   1573       // The coin_offset values MUST be strongly increasing.
   1574       nks: BlindingInputParameter[];
   1575 
   1576     }
   1577 
   1578   .. ts:def:: BlindingInputParameter
   1579 
   1580     interface BlindingInputParameter {
   1581 
   1582       // Offset of this coin in the list of
   1583       // fresh coins. May not match the array offset
   1584       // as the fresh coins may include non-CS
   1585       // denominations as well.
   1586       coin_offset: Integer;
   1587 
   1588       // Hash of the public key of the denomination the
   1589       // request relates to. Must be a CS denomination type.
   1590       denom_pub_hash: HashCode;
   1591     }
   1592 
   1593 
   1594 
   1595   .. ts:def:: BlindingPrepareResponse
   1596 
   1597     type BlindingPrepareResponse = BlindingPrepareResponseCS;
   1598 
   1599 
   1600   .. ts:def:: BlindingPrepareResponseCS
   1601 
   1602     interface BlindingPrepareResponseCS {
   1603       cipher: "CS";
   1604 
   1605       // Array of pairs of CS values, one pair per input
   1606       r_pubs: CSRPublicPair[];
   1607     }
   1608 
   1609 
   1610   .. ts:def:: CSRPublicPair
   1611 
   1612     // Pair of points (of type `CSRPublic`) on the curve Curve25519,
   1613     // one of which is randomly selected in the Clause-Schnorr
   1614     // signature scheme.
   1615     type CSRPublicPair = [CSRPublic, CSRPublic];
   1616 
   1617 
   1618 
   1619 .. _exchange-withdrawal:
   1620 
   1621 ----------
   1622 Withdrawal
   1623 ----------
   1624 
   1625 This API is used by the wallet to obtain digital coins.
   1626 
   1627 When transferring money to the exchange such as via SEPA transfers, the exchange creates
   1628 a *reserve*, which keeps the money from the customer.  The customer must
   1629 specify an EdDSA reserve public key as part of the transfer, and can then
   1630 withdraw digital coins using the corresponding private key.  All incoming and
   1631 outgoing transactions are recorded under the corresponding public key by the
   1632 exchange.
   1633 
   1634 .. note::
   1635 
   1636    Eventually the exchange will need to advertise a policy for how long it will
   1637    keep transaction histories for inactive or even fully drained reserves.  We
   1638    will therefore need some additional handler similar to ``/keys`` to
   1639    advertise those terms of service.
   1640 
   1641 
   1642 .. http:get:: /reserves/$RESERVE_PUB
   1643 
   1644   Request summary information about a reserve.
   1645 
   1646   **Request:**
   1647 
   1648   :query timeout_ms=MILLISECONDS: *Optional.*  If specified, the exchange will wait up to MILLISECONDS for incoming funds before returning a 404 if the reserve does not yet exist.
   1649 
   1650   **Response:**
   1651 
   1652   :http:statuscode:`200 OK`:
   1653     The exchange responds with a `ReserveSummary` object; the reserve was known to the exchange.
   1654   :http:statuscode:`404 Not found`:
   1655     The reserve key does not belong to a reserve known to the exchange.
   1656 
   1657   **Details:**
   1658 
   1659   .. ts:def:: ReserveSummary
   1660 
   1661     interface ReserveSummary {
   1662       // Balance left in the reserve.
   1663       balance: Amount;
   1664 
   1665       // Full payto URI of the bank account that
   1666       // (most recently) funded this reserve.
   1667       // Useful as a hint for deposit operations for wallets.
   1668       // Missing if this reserve was only filled via P2P merges.
   1669       // @since protocol **v23**.
   1670       last_origin?: string;
   1671 
   1672       // The expiration date of the reserve.
   1673       // Any residual value of in the reserve after this date
   1674       // will be returned to the ``last_origin``, if present.
   1675       // @since protocol **vRECOUP**.
   1676       reserve_expiration: Timestamp;
   1677 
   1678       // If set, proof of age restriction is required and age restriction needs
   1679       // to be set for each coin to this value during the withdrawal from this reserve.
   1680       // The client then MUST use a denomination with support for age restriction enabled
   1681       // for the withdrawal and MUST set an appropriate value for ``max_age``
   1682       // The value represents a valid age group from the list of permissible
   1683       // age groups as defined by the exchange's output to /keys.
   1684       maximum_age_group?: Integer;
   1685     }
   1686 
   1687 
   1688 
   1689 .. _withdraw:
   1690 .. http:post:: /withdraw
   1691 
   1692   Withdraw multiple coins from the same reserve.  Note that the client should
   1693   commit all of the request details, including the private key of the coins and
   1694   the blinding factors, to disk *before* issuing this request, so that it can
   1695   recover the information if necessary in case of transient failures, like
   1696   power outage, network outage, etc.
   1697 
   1698   **Request:**
   1699 
   1700   The request body must be a `WithdrawRequest` object.
   1701 
   1702   **Response:**
   1703 
   1704   :http:statuscode:`200 OK`:
   1705     The request was successful, and ``max_age`` was not set.
   1706     The response is a `WithdrawResponse`.
   1707     Note that repeating exactly the same request will again yield the same
   1708     response, so if the network goes down during the transaction or before the
   1709     client can commit the coins signature to disk, the coins are not lost.
   1710   :http:statuscode:`201 Created`:
   1711     The request was successful, and ``max_age`` was set.
   1712     The response is a `AgeWithdrawResponse`.  The client is expected
   1713     to call ``/reveal-withdraw`` next.
   1714     Note that repeating exactly the same request will again yield the same
   1715     response, so if the network goes down during the transaction or before the
   1716     client can commit the coins signature to disk, the coins are not lost.
   1717   :http:statuscode:`403 Forbidden`:
   1718     A signature is invalid. This is usually the reserve signature.
   1719     This response comes with a standard `ErrorDetail` response with
   1720     a code of ``TALER_EC_EXCHANGE_WITHDRAW_RESERVE_SIGNATURE_INVALID``.
   1721   :http:statuscode:`404 Not found`:
   1722     One of the following reasons occured:
   1723 
   1724     1. The reserve is unknown. The response comes with a standard
   1725        `ErrorDetail` response with error-code
   1726        ``TALER_EC_EXCHANGE_GENERIC_RESERVE_UNKNOWN``.
   1727        If the reserve is unknown, the wallet should not report a
   1728        hard error, but instead long-poll for the reserve status to wait
   1729        for the wire transfer to complete.
   1730        Once the wire transfer has arrived,
   1731        the wallet should repeat the exact same request later again,
   1732        possibly using exactly the same blinded coins.
   1733     2. A denomination keyis not known to the exchange.
   1734        The response comes with a standard
   1735        `ErrorDetail` response with error-code
   1736        ``TALER_EC_EXCHANGE_GENERIC_DENOMINATION_KEY_UNKNOWN``.
   1737        This suggests the wallet has outdated ``/keys`` and
   1738        should fetch the latest ``/keys``.
   1739   :http:statuscode:`409 Conflict`:
   1740     One of the following reasons occured:
   1741 
   1742     1. The balance of the reserve is not sufficient to withdraw the
   1743        coins of the indicated denominations.
   1744        The response is `WithdrawError` object with an error code of
   1745        ``TALER_EC_EXCHANGE_WITHDRAW_INSUFFICIENT_FUNDS``.  An operation
   1746        withdrawing less money should succeed.
   1747     2. The reserve has a birthday set and requires the request to
   1748        provide a ``max_age``  value.
   1749        The response comes with a standard `ErrorDetail` response with
   1750        an error-code of
   1751        ``TALER_EC_EXCHANGE_RESERVES_AGE_RESTRICTION_REQUIRED``
   1752        and an additional field ``maximum_allowed_age`` for the
   1753        maximum age (in years)
   1754        that the client can commit to in a call to ``/withdraw``, this time
   1755        with ``max_age`` set accordingly and ``coin_evs`` being an array
   1756        of ``n*kappa`` elements of type `CoinEnvelope`.
   1757     3. The provided value for ``max_age`` is higher than the allowed value
   1758        according to the reserve's birthday. The response comes with a
   1759        standard `ErrorDetail` response with error-code
   1760        ``TALER_EC_EXCHANGE_AGE_WITHDRAW_MAXIMUM_AGE_TOO_LARGE``
   1761        and an additional field ``maximum_allowed_age`` for the maximum
   1762        age (in years) that the client can commit to in a call
   1763        to ``/withdraw``.
   1764     4. The request uses a nonce value that was previously seen by
   1765        the exchange for a different request. As nonces must be unique,
   1766        the request is rejected. This can only happen with some cipher
   1767        types that use nonces.
   1768   :http:statuscode:`410 Gone`:
   1769     A requested denomination key is no longer valid. There are two cases:
   1770 
   1771     1. The denomination key is past its expiration.
   1772        The response is a `DenominationGoneMessage` with a code of
   1773        ``TALER_EC_EXCHANGE_GENERIC_DENOMINATION_EXPIRED``.
   1774     2. The denominatoin key was revoked. The response is a
   1775        plain `ErrorDetail` with a code of ``TALER_EC_EXCHANGE_GENERIC_DENOMINATION_REVOKED``.
   1776   :http:statuscode:`412 Precondition Failed`:
   1777     A requested denomination key is not yet valid.
   1778     It is before the validity start time.
   1779     The response is a `DenominationGoneMessage` with
   1780     ``TALER_EC_EXCHANGE_GENERIC_DENOMINATION_VALIDITY_IN_FUTURE``.
   1781     A common case might be a difference in the current time between
   1782     wallet and exchange. The wallet could probably just wait a bit and
   1783     retry. Checking the server's ``Date:`` header should allow the
   1784     wallet to figure out how long to wait. Alternatively, the wallet
   1785     could try with an the previous denomination key generation.
   1786     Note: this is a bit of an abuse of the HTTP status code.
   1787   :http:statuscode:`451 Unavailable for Legal Reasons`:
   1788     This reserve has received funds from a purse or the amount withdrawn
   1789     exceeds another legal threshold and thus the reserve must
   1790     be upgraded to an account (with KYC) before the withdraw can
   1791     complete.  Note that this response does NOT affirm that the
   1792     withdraw will ultimately complete with the requested amount.
   1793     The user should be redirected to the provided location to perform
   1794     the required KYC checks to open the account before withdrawing.
   1795     Afterwards, the request should be repeated.
   1796     The response will be an `LegitimizationNeededResponse` object.
   1797 
   1798     Implementation note: internally, we need to
   1799     distinguish between upgrading the reserve to an
   1800     account (due to P2P payment) and identifying the
   1801     owner of the origin bank account (due to exceeding
   1802     the withdraw amount threshold), as we need to create
   1803     a different payto://-URI for the KYC check depending
   1804     on the case.
   1805   :http:statuscode:`501 Not implemented`:
   1806     The client has provided a cipher that is not supported.
   1807   :http:statuscode:`502 Bad gateway`:
   1808     This indicates the exchange could not communicate with an
   1809     external process. This usually means the exchange could
   1810     not talk to one of its secmod helpers.
   1811     Here, a standard error message with a code of
   1812     ``TALER_EC_EXCHANGE_SIGNKEY_HELPER_UNAVAILABLE``
   1813     is returned.
   1814     Wallets should retry the requests (with some delays) at
   1815     a later time.
   1816   :http:statuscode:`503 Service Unavailable`:
   1817     This primarily happens when the exchange currently has no
   1818     denomination signing keys at all, for example because the
   1819     offline signature did not yet happen. In this case, a standard
   1820     error message with a code of
   1821     ``TALER_EC_EXCHANGE_GENERIC_KEYS_MISSING`` is returned.
   1822 
   1823   **Details:**
   1824 
   1825 
   1826 .. ts:def:: WithdrawRequest
   1827 
   1828   interface WithdrawRequest {
   1829     // Cipher that is used for the rerserve's signatures.
   1830     // For now, only ed25519 signatures are applicable,
   1831     // but this might change in future versions.
   1832     cipher: "ED25519";
   1833 
   1834     // The reserve's public key, for the the cipher ED25519,
   1835     // to verify the signature ``reserve_sig``.
   1836     reserve_pub: EddsaPublicKey;
   1837 
   1838     // Array of ``n`` hash codes of denomination public keys to order.
   1839     // The sum of all denomination's values and fees MUST be
   1840     // at most the balance of the reserve. The balance of
   1841     // the reserve will be immediatley reduced by that amount.
   1842     // If ``max_age`` is set, these denominations MUST support
   1843     // age restriction as defined in the output to /keys.
   1844     denoms_h: HashCode[];
   1845 
   1846     // If set, the maximum age to commit to. This implies:
   1847     // 1.) it MUST be the same value as the maximum age
   1848     //     of the reserve.
   1849     // 2.) ``coin_evs`` MUST be an array of ``n*kappa``
   1850     // 3.) the denominations in ``denoms_h`` MUST support
   1851     //      age restriction.
   1852     max_age?: Integer;
   1853 
   1854     // Master seed for the Clause-Schnorr R-value creation.
   1855     // MUST match the /blinding-prepare request.
   1856     // MUST NOT have been used in any prior withdraw request.
   1857     // MUST be present if one of the fresh coin's
   1858     // denomination is of type Clause-Schnorr.
   1859     blinding_seed?: BlindingMasterSeed;
   1860 
   1861     // Array of blinded coin envelopes of type `CoinEnvelope`.
   1862     // If ``max_age`` is not set, MUST be n entries.
   1863     // If ``max_age`` is set, MUST be ``n*kappa`` entries,
   1864     // arranged in [0..n)..[0..n), with the first n entries
   1865     // belonging to kappa=0 etc.
   1866     // In case of age restriction, the exchange will
   1867     // respond with an index ``gamma``, which is the index
   1868     // that shall remain undisclosed during the subsequent
   1869     // reveal phase.
   1870     // This hash value along with the reserve's public key
   1871     // will also be used for recoup operations, if needed.
   1872     coin_evs:  CoinEnvelope[];
   1873 
   1874     // Signature of `TALER_WithdrawRequestPS` created with
   1875     // the `reserves's private key <reserve-priv>`.
   1876     reserve_sig: EddsaSignature;
   1877   }
   1878 
   1879 .. ts:def:: WithdrawResponse
   1880 
   1881   interface WithdrawResponse {
   1882     // Array of blinded signatures over each ``coin_evs``,
   1883     // in the same order as was given in the request.
   1884     // The blinded signatures affirm the coin's validity
   1885     // after unblinding.
   1886     ev_sigs: BlindedDenominationSignature[];
   1887 
   1888   }
   1889 
   1890 
   1891 .. ts:def:: AgeWithdrawResponse
   1892 
   1893   interface AgeWithdrawResponse {
   1894     // index of the commitments that the client doesn't
   1895     // have to disclose in the subsequent call to
   1896     // ``/reveal-withdraw``.
   1897     noreveal_index: Integer;
   1898 
   1899     // Signature of `TALER_WithdrawConfirmationPS` whereby
   1900     // the exchange confirms the ``noreveal_index``.
   1901     exchange_sig: EddsaSignature;
   1902 
   1903     // `Public EdDSA key <sign-key-pub>` of the exchange that was used to
   1904     // generate the signature.  Should match one of the exchange's signing
   1905     // keys from ``/keys``.  Again given explicitly as the client might
   1906     // otherwise be confused by clock skew as to which signing key was used.
   1907     exchange_pub: EddsaPublicKey;
   1908 
   1909   }
   1910 
   1911 .. ts:def:: DenominationGoneMessage
   1912 
   1913   interface DenominationGoneMessage {
   1914 
   1915     // Taler error code.  Note that beyond
   1916     // expiration this message format is also
   1917     // used if the key is not yet valid, or
   1918     // has been revoked. May be one of
   1919     // - ``TALER_EC_EXCHANGE_GENERIC_DENOMINATION_VALIDITY_IN_FUTURE``
   1920     // - ``TALER_EC_EXCHANGE_GENERIC_DENOMINATION_EXPIRED``
   1921     // - ``TALER_EC_EXCHANGE_GENERIC_DENOMINATION_REVOKED``
   1922     code: Integer;
   1923 
   1924     // Signature by the exchange over a
   1925     // `TALER_DenominationExpiredAffirmationPS`.
   1926     // Must have purpose ``TALER_SIGNATURE_EXCHANGE_AFFIRM_DENOM_EXPIRED``.
   1927     exchange_sig: EddsaSignature;
   1928 
   1929     // Public key of the exchange used to create
   1930     // the 'exchange_sig.
   1931     exchange_pub: EddsaPublicKey;
   1932 
   1933     // Hash of the denomination public key that is unknown.
   1934     h_denom_pub: HashCode;
   1935 
   1936     // When was the signature created.
   1937     timestamp: Timestamp;
   1938 
   1939     // What kind of operation was requested that now
   1940     // failed?
   1941     oper: string;
   1942 
   1943   }
   1944 
   1945 
   1946 .. ts:def:: WithdrawError
   1947 
   1948   interface SingleWithdrawError {
   1949     // Text describing the error.
   1950     hint: string;
   1951 
   1952     // Detailed error code.
   1953     code: Integer;
   1954 
   1955     // Amount left in the reserve.
   1956     balance: Amount;
   1957 
   1958   }
   1959 
   1960 
   1961 
   1962 ------------------
   1963 
   1964 
   1965 .. _reveal-withdraw:
   1966 
   1967 **Reveal-Withdraw**
   1968 
   1969 This endpoint is called by the client after a call to `withdraw`_,
   1970 *if* the original request had ``max_age`` set and
   1971 the response was of type `AgeWithdrawResponse`.
   1972 Now the client has to disclose for each coin all but one of the κ secrets
   1973 that went into creating the blinded coin's planchets,
   1974 including the commitment to age restriction,
   1975 and prove that the age restriction was set correctly.
   1976 
   1977 .. http:post:: /reveal-withdraw
   1978 
   1979   Reveal previously committed values to the exchange, except for the values
   1980   corresponding to the ``noreveal_index`` returned by the ``/withdraw`` step.
   1981 
   1982   The base URL for ``/reveal-withdraw``-request may differ from the main base URL of
   1983   the exchange. Clients SHOULD respect the ``reveal_base_url`` returned for the
   1984   coin during melt operations. The exchange MUST return a
   1985   307 or 308 redirection to the correct base URL if the client failed to
   1986   respect the ``reveal_base_url`` or if the allocation has changed.
   1987 
   1988   The request body is a `RevealWithdrawRequest`.
   1989 
   1990   This endpoint was introduced in this form in protocol **vDOLDPLUS**.
   1991 
   1992   :http:statuscode:`200 OK`:
   1993     The coin's' secret material matched the commitment and the original request was well-formed.
   1994     The response body is a `RevealResponse`.
   1995   :http:statuscode:`404 Not found`:
   1996     The provided commitment $RCH is unknown.
   1997   :http:statuscode:`409 Conflict`:
   1998     There is a problem between the original commitment and the revealed secret data.
   1999     The returned information is proof of the mismatch,
   2000     and therefore rather verbose, as it includes most of the original /withdraw request,
   2001     but of course expected to be primarily used for diagnostics.
   2002 
   2003     The response body is a `RevealConflictResponse`.
   2004 
   2005     The following specific error codes can be returned:
   2006 
   2007     - An age commitment for at least one of the coins did not fulfill the
   2008       required maximum age requirement of the corresponding reserve.
   2009       Error code:
   2010       ``TALER_EC_EXCHANGE_GENERIC_COIN_AGE_REQUIREMENT_FAILURE``.
   2011     - The computation of the hash of the commitment with provided input does
   2012       result in the value of field ``h_commitment``.
   2013       Error code:
   2014       ``TALER_EC_EXCHANGE_AGE_WITHDRAW_REVEAL_INVALID_HASH``
   2015 
   2016   **Details:**
   2017 
   2018   Request body for a ``reveal-withdraw`` request
   2019   contains a JSON object with the following fields:
   2020 
   2021   .. ts:def:: RevealWithdrawRequest
   2022 
   2023     interface RevealWithdrawRequest {
   2024       // The reserve's public key from the previous call to /withdraw.
   2025       reserve_pub: string;
   2026 
   2027       // This is the h_planchets running hash of all blinded planchets
   2028       // from the previous call to /withdraw.
   2029       h_planchets: string;
   2030 
   2031       // Array of ``(kappa - 1)`` disclosed batch secrets,
   2032       // from which for each of the n coins in a batch
   2033       // their coin master secret is derived,
   2034       // from which in turn their private key,
   2035       // blinding, nonce (for Clause-Schnorr) and
   2036       // age-restriction is calculated.
   2037       disclosed_batch_seeds: AgeRestrictedPlanchetSeed[];
   2038 
   2039     }
   2040 
   2041   .. ts:def:: AgeRestrictedPlanchetSeed
   2042 
   2043     // The master seed material from which for n coins in a batch,
   2044     // each the coins' private key ``coin_priv``,  blinding ``beta``
   2045     // and nonce ``nonce`` (for Clause-Schnorr) itself are
   2046     // derived as usually in wallet-core.  Given a coin's master key material,
   2047     // the age commitment for the coin MUST be derived from this private key as
   2048     // follows:
   2049     //
   2050     // Let m ∈  {1,...,M} be the maximum age group as defined in the reserve
   2051     // that the wallet can commit to.
   2052     //
   2053     // For age group $AG ∈  {1,...m}, set
   2054     //     seed = HDKF(coin_secret, "age-commitment", $AG)
   2055     //   p[$AG] = Edx25519_generate_private(seed)
   2056     // and calculate the corresponding Edx25519PublicKey as
   2057     //   q[$AG] = Edx25519_public_from_private(p[$AG])
   2058     //
   2059     // For age groups $AG ∈  {m+1,...,M}, set
   2060     //   f[$AG] = HDKF(coin_secret, "age-factor", $AG)
   2061     // and calculate the corresponding Edx25519PublicKey as
   2062     //   q[$AG] = Edx25519_derive_public(`PublishedAgeRestrictionBaseKey`, f[$AG])
   2063     //
   2064     type AgeRestrictedPlanchetSeed = string;
   2065 
   2066   .. ts:def:: PublishedAgeRestrictionBaseKey
   2067 
   2068     // The value for ``PublishedAgeRestrictionBaseKey`` is a randomly chosen
   2069     // `Edx25519PublicKey` for which the private key is not known to the clients.  It is
   2070     // used during the age-withdraw protocol so that clients can prove that they
   2071     // derived all public keys to age groups higher than their allowed maximum
   2072     // from this particular value.
   2073     const PublishedAgeRestrictionBaseKey =
   2074         new Edx25519PublicKey("CH0VKFDZ2GWRWHQBBGEK9MWV5YDQVJ0RXEE0KYT3NMB69F0R96TG");
   2075 
   2076 
   2077 
   2078 ----------
   2079 Refreshing
   2080 ----------
   2081 
   2082 Refreshing creates ``n`` new coins from ``m`` old coins, where the sum of
   2083 denominations of the new coins must be smaller than the sum of the old coins'
   2084 denominations plus melting (refresh) and withdrawal fees charged by the exchange.
   2085 The refreshing API can be used by wallets to melt partially spent coins, making
   2086 transactions with the freshly exchangeed coins unlinkabe to previous transactions
   2087 by anyone except the wallet itself.
   2088 
   2089 Refreshing is a two step process, consisting of
   2090 
   2091 1. the **melting** of the old coin, together with ``kappa`` batches
   2092    of blinded planchets candidates,
   2093 2. the **reveal** of ``kappa-1`` secrets to prove the proper construction
   2094    of the (revealed) batches of blinded planchets candidates.
   2095 
   2096 
   2097 ^^^^
   2098 Melt
   2099 ^^^^
   2100 
   2101 .. _melt:
   2102 .. http:post:: /melt
   2103 
   2104   "Melts" a coin.  Invalidates the coins and prepares for exchanging of fresh
   2105   coins.  Taler uses a global parameter ``kappa`` for the cut-and-choose
   2106   component of the protocol, for which this request is the commitment.  Thus,
   2107   various arguments are given ``kappa``-times in this step.  At present ``kappa``
   2108   is always 3.
   2109 
   2110   The base URL for ``/melt/``-requests may differ from the main base URL of the
   2111   exchange. The exchange MUST return a 307 or 308 redirection to the correct
   2112   base URL if this is the case.
   2113 
   2114   This endpoint was introduced in this form in protocol **vDOLDPLUS**.
   2115 
   2116   :http:statuscode:`200 OK`:
   2117     The request was successful.  The response body is `MeltResponse` in this case.
   2118   :http:statuscode:`403 Forbidden`:
   2119     One of the signatures is invalid.
   2120   :http:statuscode:`404 Not found`:
   2121     The exchange does not recognize the denomination key as belonging to the exchange,
   2122     or it has expired.
   2123     If the denomination key is unknown, the response will be
   2124     a `DenominationUnknownMessage`.
   2125   :http:statuscode:`409 Conflict`:
   2126     The operation is not allowed as the coin has insufficient
   2127     residual value, or because the same public key of the coin has been
   2128     previously used with a different denomination.  Which case it is
   2129     can be decided by looking at the error code
   2130     (``TALER_EC_EXCHANGE_GENERIC_INSUFFICIENT_FUNDS`` or
   2131     ``TALER_EC_EXCHANGE_GENERIC_COIN_CONFLICTING_DENOMINATION_KEY``).
   2132     The response is `MeltForbiddenResponse` in both cases.
   2133   :http:statuscode:`410 Gone`:
   2134     The requested denomination key is not yet or no longer valid.
   2135     It either before the validity start, past the expiration or was revoked. The response is a
   2136     `DenominationGoneMessage`. Clients must evaluate
   2137     the error code provided to understand which of the
   2138     cases this is and handle it accordingly.
   2139 
   2140   **Details:**
   2141 
   2142   .. ts:def:: MeltRequest
   2143 
   2144     interface MeltRequest {
   2145        // The old coin's public key
   2146        old_coin_pub: CoinPublicKey;
   2147 
   2148        // Hash of the denomination public key of the old coin,
   2149        // to determine total coin value.
   2150        old_denom_pub_h: HashCode;
   2151 
   2152        // The hash of the age-commitment for the old coin. Only present
   2153        // if the denomination has support for age restriction.
   2154        old_age_commitment_h?: AgeCommitmentHash;
   2155 
   2156        // Signature over the old `coin public key <eddsa-coin-pub>` by the denomination.
   2157        old_denom_sig: DenominationSignature;
   2158 
   2159        // Amount of the value of the old coin that should be melted as part of
   2160        // this refresh operation, including melting fee.  I.e.:
   2161        //        melting fee of the old coin
   2162        //      + sum over all values of fresh coins
   2163        //      + sum over all withdraw fees for the fresh coins
   2164        value_with_fee: Amount;
   2165 
   2166        // @since v27
   2167        // @deprecated vDOLDPLUS
   2168        // Seed from which the nonces for the n*κ coin candidates are derived from.
   2169        //
   2170        // @since vDOLDPLUS
   2171        // The ``refresh_seed`` is an opaque value to the exchange.
   2172        // It is provided by the client and is verified with the ``coin_sig`` below.
   2173        // Its purpose is to ensure that the honest owner of the old coin
   2174        // can replay a /melt request from data in the coin history,
   2175        // provided by the exchange and including this value, in case a wallet
   2176        // was restored into a state prior to the refresh operation.
   2177        //
   2178        // The honest owner of the old coin SHOULD use this value
   2179        // and the old coin's private key to derive kappa many
   2180        // batch seeds (one for each cut-and-choose candidate)
   2181        // like this:
   2182        //
   2183        //   ``bs[] = HKDF(kappa*sizeof(HashCode),``
   2184        //               ``"refresh-batch-seeds",``
   2185        //               ``old_coin_priv,``
   2186        //               ``refresh_seed)``
   2187        //
   2188        // These batch seeds (however constructed) are relevant in the
   2189        // subsequent reveal step of the cut-and-chose.  Each of the
   2190        // revealed seeds is expanded to a batch of ``n`` transfer private keys
   2191        // via HKDF:
   2192        //
   2193        //   ``tp[k][] = HKDF(n*sizeof(HashCode),``
   2194        //                  ``"refresh-transfer-private-keys",``
   2195        //                  ``bs[k])``
   2196        //
   2197        // An individual coin's transfer private key at kappa-index k and
   2198        // coin index i in the batch is then ``tp[k][i]``.  The corresponding
   2199        // transfer _public_ keys are given in the field ``transfer_pubs``.
   2200        refresh_seed: HashCode;
   2201 
   2202        // Master seed for the Clause-Schnorr R-value
   2203        // creation. Must match the /blinding-prepare request.
   2204        // Must not have been used in any prior melt request.
   2205        // Must be present if one of the fresh coin's
   2206        // denominations is of type Clause-Schnorr.
   2207        blinding_seed?: BlindingMasterSeed;
   2208 
   2209        // Array of ``n`` new hash codes of denomination public keys
   2210        // for the new coins to order.
   2211        denoms_h: HashCode[];
   2212 
   2213        // ``kappa`` arrays of ``n`` entries for blinded coin candidates,
   2214        // each matching the respective entries in ``denoms_h``.
   2215        coin_evs: CoinEnvelope[kappa][];
   2216 
   2217        // @since vDOLDPLUS
   2218        // ``kappa`` arrays of ``n`` entries of transfer public keys each.
   2219        // These are ephemeral ECDHE keys that allow the owner of a coin
   2220        // to (re-)obtain the derived coins from a refresh operation, f.e. should
   2221        // the wallet state be restored from a backup, prior to the refresh operation.
   2222        transfer_pubs: EddsaPublicKey[kappa][];
   2223 
   2224        // Signature by the `coin <coin-priv>` over `TALER_RefreshMeltCoinAffirmationPS`.
   2225        confirm_sig: EddsaSignature;
   2226 
   2227     }
   2228 
   2229   For details about the HKDF used to derive the new coin private keys and
   2230   the blinding factors from ECDHE between the transfer public keys and
   2231   the private key of the melted coin, please refer to the
   2232   implementation in ``libtalerutil``.
   2233 
   2234   .. ts:def:: MeltResponse
   2235 
   2236     interface MeltResponse {
   2237       // Which of the ``kappa`` indices does the client not have to reveal
   2238       // by calling the ``/reveal-melt`` endpoint.
   2239       noreveal_index: Integer;
   2240 
   2241       // Signature of `TALER_RefreshMeltConfirmationPS` whereby the exchange
   2242       // affirms the successful melt and confirming the ``noreveal_index``.
   2243       exchange_sig: EddsaSignature;
   2244 
   2245       // `Public EdDSA key <sign-key-pub>` of the exchange that was used to generate the signature.
   2246       // Should match one of the exchange's signing keys from ``/keys``.  Again given
   2247       // explicitly as the client might otherwise be confused by clock skew as to
   2248       // which signing key was used.
   2249       exchange_pub: EddsaPublicKey;
   2250 
   2251       // Base URL to use for operations on the refresh context
   2252       // (so the reveal operation).  If not given,
   2253       // the base URL is the same as the one used for this request.
   2254       // Can be used if the base URL for ``/reveal-melt/`` differs from that
   2255       // for ``/melt/``, i.e. for load balancing.  Clients SHOULD
   2256       // respect the reveal_base_url if provided.  Any HTTP server
   2257       // belonging to an exchange MUST generate a 307 or 308 redirection
   2258       // to the correct base URL should a client uses the wrong base
   2259       // URL, or if the base URL has changed since the melt.
   2260       //
   2261       // When melting the same coin twice (technically allowed
   2262       // as the response might have been lost on the network),
   2263       // the exchange may return different values for the ``reveal_base_url``.
   2264       reveal_base_url?: string;
   2265 
   2266     }
   2267 
   2268   .. ts:def:: MeltForbiddenResponse
   2269 
   2270     interface MeltForbiddenResponse {
   2271 
   2272       // Must be TALER_EC_EXCHANGE_GENERIC_INSUFFICIENT_FUNDS
   2273       // or TALER_EC_EXCHANGE_GENERIC_COIN_CONFLICTING_DENOMINATION_KEY
   2274       code: Integer;
   2275 
   2276       // A string explaining that the user tried to
   2277       // double-spend.
   2278       hint: string;
   2279 
   2280       // EdDSA public key of a coin being double-spent.
   2281       coin_pub: EddsaPublicKey;
   2282 
   2283       // Hash of the public key of the denomination of the coin.
   2284       h_denom_pub: HashCode;
   2285 
   2286     }
   2287 
   2288 ^^^^^^^^^^^
   2289 Reveal-Melt
   2290 ^^^^^^^^^^^
   2291 
   2292 This endpoint is called by the client after a call to `melt`_.
   2293 Now the client has to disclose --for each coin--
   2294 all but one of the κ secrets that went into creating the blinded coin's planchets,
   2295 the transfer public keys (linking the ownership of the old and new coin),
   2296 and the commitment to age restriction,
   2297 as proof that the age restriction was set correctly (if applicable).
   2298 
   2299 .. http:post:: /reveal-melt
   2300 
   2301   Reveal previously committed values to the exchange, except for the values
   2302   corresponding to the ``noreveal_index`` returned by the ``/melt`` step.
   2303 
   2304   The base URL for ``/reveal-melt``-request may differ from the main base URL of
   2305   the exchange. Clients SHOULD respect the ``reveal_base_url`` returned for the
   2306   coin during melt operations. The exchange MUST return a
   2307   307 or 308 redirection to the correct base URL if the client failed to
   2308   respect the ``reveal_base_url`` or if the allocation has changed.
   2309 
   2310   The request body is a `RevealMeltRequest`.
   2311 
   2312   This endpoint was introduced in this form in protocol **vDOLDPLUS**.
   2313 
   2314   :http:statuscode:`200 OK`:
   2315     The coin's' secret material matched the commitment and the original request was well-formed.
   2316     The response body is a `RevealResponse`.
   2317   :http:statuscode:`403 Forbidden`:
   2318     One of the signatures is invalid.
   2319     This response comes with a standard `ErrorDetail` response.
   2320   :http:statuscode:`404 Not found`:
   2321     The provided commitment is unknown.
   2322   :http:statuscode:`409 Conflict`:
   2323     There is a problem between the original commitment and the revealed secret data.
   2324     The returned information is proof of the mismatch,
   2325     and therefore rather verbose, as it includes most of the original /melt request,
   2326     but of course expected to be primarily used for diagnostics.
   2327 
   2328     The response body is a `RevealConflictResponse`.
   2329 
   2330   **Details:**
   2331 
   2332   Request body for a ``reveal-melt`` request
   2333   contains a JSON object with the following fields:
   2334 
   2335   .. ts:def:: RevealMeltRequest
   2336 
   2337     interface RevealMeltRequest {
   2338       // The refresh commitment from the ``/melt/`` step,
   2339       // see `TALER_RefreshCommitmentP`.
   2340       rc: HashCode;
   2341 
   2342       // @since v27
   2343       // @deprecated vDOLDPLUS
   2344       // The disclosed kappa-1 signatures by the old coin's private key,
   2345       // over Hash1a("Refresh", Cp, r, i), where Cp is the melted coin's public key,
   2346       // r is the public refresh nonce from the metling step and i runs over the
   2347       // _disclosed_ kappa-1 indices.
   2348       signatures: CoinSignature[kappa-1];
   2349 
   2350       // @since vDOLDPLUS
   2351       // The batch seeds for the transfer private keys to reveal,
   2352       // as they were generated for the previous `MeltRequest`.
   2353       // That is, assuming an honest client who had generated
   2354       // kappa many batch seeds via HKDF like this:
   2355       //
   2356       //   ``bs[] = HKDF(kappa*sizeof(HashCode),``
   2357       //               ``"refresh-batch-seeds",``
   2358       //               ``old_coin_priv,``
   2359       //               ``refresh_seed)``,
   2360       //
   2361       // this field contains the entries in ``bs[]`` for all the indeces
   2362       // *except* the ``noreveal_index``.
   2363       batch_seeds: HashCode[kappa-1];
   2364 
   2365       // IFF the denomination of the old coin had support for age restriction,
   2366       // the client MUST provide the original age commitment, i. e. the
   2367       // vector of public keys, or omitted otherwise.
   2368       // The size of the vector MUST be the number of age groups as defined by the
   2369       // Exchange in the field ``.age_groups`` of the extension ``age_restriction``.
   2370       age_commitment?: Edx25519PublicKey[];
   2371 
   2372     }
   2373 
   2374   .. ts:def:: RevealResponse
   2375 
   2376     type RevealResponse = WithdrawResponse;
   2377 
   2378 
   2379   .. ts:def:: RevealConflictResponse
   2380 
   2381     interface RevealConflictResponse {
   2382       // Text describing the error.
   2383       hint: string;
   2384 
   2385       // Detailed error code.
   2386       code: Integer;
   2387 
   2388       // Commitment as calculated by the exchange from the revealed data.
   2389       rc_expected: HashCode;
   2390 
   2391     }
   2392 
   2393 
   2394 .. _deposit-par:
   2395 
   2396 -------
   2397 Deposit
   2398 -------
   2399 
   2400 Deposit operations are requested f.e. by a merchant during a transaction or a
   2401 bidder during an auction.
   2402 
   2403 For the deposit operation during purchase, the merchant has to obtain the
   2404 deposit permission for a coin from their customer who owns the coin.  When
   2405 depositing a coin, the merchant is credited an amount specified in the deposit
   2406 permission, possibly a fraction of the total coin's value, minus the deposit
   2407 fee as specified by the coin's denomination.
   2408 
   2409 For auctions, a bidder performs an deposit operation and provides all relevant
   2410 information for the auction policy (such as timeout and public key as bidder)
   2411 and can use the ``exchange_sig`` field from the `DepositSuccess` message as a
   2412 proof to the seller for the escrow of sufficient fund.
   2413 
   2414 
   2415 .. _deposit:
   2416 
   2417 .. http:post:: /batch-deposit
   2418 
   2419   Deposit multiple coins and ask the exchange to transfer the given :ref:`amount`
   2420   into the merchant's bank account.  This API is used by the merchant to redeem
   2421   the digital coins.
   2422 
   2423   **Request:**
   2424 
   2425   The request body must be a `BatchDepositRequest` object.
   2426 
   2427   **Response:**
   2428 
   2429   :http:statuscode:`200 OK`:
   2430     The operation succeeded, the exchange confirms that no double-spending took
   2431     place.  The response will include a `DepositSuccess` object.
   2432   :http:statuscode:`403 Forbidden`:
   2433     One of the signatures is invalid.
   2434     This response comes with a standard `ErrorDetail` response.
   2435   :http:statuscode:`404 Not found`:
   2436     Either one of the denomination keys is not recognized (expired or invalid),
   2437     or the wire type is not recognized.
   2438     If a denomination key is unknown, the response will be
   2439     a `DenominationUnknownMessage`.
   2440   :http:statuscode:`409 Conflict`:
   2441     The deposit operation has either failed because a coin has insufficient
   2442     residual value, or because the same public key of a coin has been
   2443     previously used with a different denomination.
   2444     Which case it is can be decided by looking at the error code:
   2445 
   2446     1. ``TALER_EC_EXCHANGE_DEPOSIT_CONFLICTING_CONTRACT`` (same coin used in different ways),
   2447     2. ``TALER_EC_EXCHANGE_GENERIC_INSUFFICIENT_FUNDS`` (balance insufficient),
   2448     3. ``TALER_EC_EXCHANGE_GENERIC_COIN_CONFLICTING_DENOMINATION_KEY`` (same coin public key, but different denomination).
   2449     4. ``TALER_EC_EXCHANGE_GENERIC_COIN_CONFLICTING_AGE_HASH`` (same coin public key, but different age commitment).
   2450 
   2451     The request should not be repeated again with this coin.  Instead, the client
   2452     can get from the exchange via the ``/coin/$COIN_PUB/history`` endpoint the record
   2453     of the transactions known for this coin's public key.
   2454   :http:statuscode:`410 Gone`:
   2455     The requested denomination key is not yet or no longer valid.
   2456     It either before the validity start, past the expiration or was revoked. The response is a
   2457     `DenominationGoneMessage`. Clients must evaluate
   2458     the error code provided to understand which of the
   2459     cases this is and handle it accordingly.
   2460   :http:statuscode:`451 Unavailable For Legal Reasons`:
   2461     This merchant has not yet passed the KYC checks.
   2462     The client must pass KYC checks before proceeding with the deposit.
   2463     The response will be an `LegitimizationNeededResponse` object.
   2464     @since protocol **v21**.
   2465 
   2466   **Details:**
   2467 
   2468   .. ts:def:: BatchDepositRequest
   2469 
   2470     interface BatchDepositRequest {
   2471 
   2472       // The merchant's account details as a full payto URI.
   2473       merchant_payto_uri: string;
   2474 
   2475       // The salt is used to hide the ``payto_uri`` from customers
   2476       // when computing the ``h_wire`` of the merchant.
   2477       wire_salt: WireSalt;
   2478 
   2479       // SHA-512 hash of the contract of the merchant with the customer.  Further
   2480       // details are never disclosed to the exchange.
   2481       h_contract_terms: HashCode;
   2482 
   2483       // Merchant's signature over the h_contract_terms.
   2484       // @since protocol **v22**
   2485       merchant_sig: EddsaSignature;
   2486 
   2487       // The list of coins that are going to be deposited with this Request.
   2488       coins: BatchDepositRequestCoin[];
   2489 
   2490       // Timestamp when the contract was finalized.
   2491       timestamp: Timestamp;
   2492 
   2493       // Indicative time by which the exchange undertakes to transfer the funds to
   2494       // the merchant, in case of successful payment. A wire transfer deadline of 'never'
   2495       // is not allowed.
   2496       wire_transfer_deadline: Timestamp;
   2497 
   2498       // EdDSA `public key of the merchant <merchant-pub>`, so that the client can identify the
   2499       // merchant for refund requests.
   2500       merchant_pub: EddsaPublicKey;
   2501 
   2502       // Date until which the merchant can issue a refund to the customer via the
   2503       // exchange, to be omitted if refunds are not allowed.
   2504       //
   2505       // THIS FIELD WILL BE DEPRICATED, once the refund mechanism becomes a
   2506       // policy via extension.
   2507       refund_deadline?: Timestamp;
   2508 
   2509       // CAVEAT: THIS IS WORK IN PROGRESS
   2510       // (Optional) policy for the batch-deposit.
   2511       // This might be a refund, auction or escrow policy.
   2512       policy?: DepositPolicy;
   2513     }
   2514 
   2515   .. ts:def:: BatchDepositRequestCoin
   2516 
   2517     interface BatchDepositRequestCoin {
   2518       // EdDSA public key of the coin being deposited.
   2519       coin_pub: EddsaPublicKey;
   2520 
   2521       // Hash of denomination RSA key with which the coin is signed.
   2522       denom_pub_hash: HashCode;
   2523 
   2524       // Exchange's unblinded RSA signature of the coin.
   2525       ub_sig: DenominationSignature;
   2526 
   2527       // Amount to be deposited, can be a fraction of the
   2528       // coin's total value.
   2529       contribution: Amount;
   2530 
   2531       // Signature over `TALER_DepositRequestPS`, made by the customer with the
   2532       // `coin's private key <coin-priv>`.
   2533       coin_sig: EddsaSignature;
   2534     }
   2535 
   2536   .. ts:def:: DenominationSignature
   2537 
   2538     type DenominationSignature = DenomCipher & (
   2539       | RsaDenominationSignature
   2540       | CSDenominationSignature
   2541     );
   2542 
   2543   .. ts:def:: RsaDenominationSignature
   2544 
   2545     interface RsaDenominationSignature extends DenomCipher {
   2546       cipher: "RSA";
   2547 
   2548       // RSA signature
   2549       rsa_signature: RsaSignature;
   2550     }
   2551 
   2552   .. ts:def:: CSDenominationSignature
   2553 
   2554     interface CSDenominationSignature extends DenomCipher {
   2555       cipher: "CS";
   2556 
   2557       // R value component of the signature.
   2558       cs_signature_r: Cs25519Point;
   2559 
   2560       // s value component of the signature.
   2561       cs_signature_s: Cs25519Scalar;
   2562 
   2563     }
   2564 
   2565   .. ts:def:: DepositPolicy
   2566 
   2567     type DepositPolicy =
   2568     | PolicyMerchantRefund
   2569     | PolicyBrandtVickreyAuction
   2570     | PolicyEscrowedPayment;
   2571 
   2572   .. ts:def:: PolicyMerchantRefund
   2573 
   2574     // CAVEAT: THIS IS STILL WORK IN PROGRESS.
   2575     // This policy is optional and might not be supported by the exchange.
   2576     // If it does, the exchange MUST show support for this policy in the
   2577     // ``extensions`` field in the response to ``/keys``.
   2578     interface PolicyMerchantRefund {
   2579       type: "merchant_refund";
   2580 
   2581       // EdDSA `public key of the merchant <merchant-pub>`, so that the client
   2582       // can identify the merchant for refund requests.
   2583       merchant_pub: EddsaPublicKey;
   2584 
   2585       // Date until which the merchant can issue a refund to the customer via
   2586       // the ``/extensions/policy_refund``-endpoint of the exchange.
   2587       deadline: Timestamp;
   2588     }
   2589 
   2590   .. ts:def:: PolicyBrandtVickreyAuction
   2591 
   2592     // CAVEAT: THIS IS STILL WORK IN PROGRESS.
   2593     // This policy is optional and might not be supported by the exchange.
   2594     // If it does, the exchange MUST show support for this policy in the
   2595     // ``extensions`` field in the response to ``/keys``.
   2596     interface PolicyBrandtVickreyAuction {
   2597       type: "brandt_vickrey_auction";
   2598 
   2599       // Public key of this bidder.
   2600       //
   2601       // The bidder uses this key to sign the auction information and
   2602       // the messages it sends to the seller during the auction.
   2603       bidder_pub: EddsaPublicKey;
   2604 
   2605       // Hash of the auction terms
   2606       //
   2607       // The hash should be taken over a normalized JSON object of type
   2608       // `BrandtVickreyAuction`.
   2609       h_auction: HashCode;
   2610 
   2611       // The amount that this bidder commits to for this auction
   2612       //
   2613       // This amount can be larger than the contribution of a single coin.
   2614       // The bidder can increase funding of this auction policy by using
   2615       // sufficiently many coins during the deposit operation (single or batch)
   2616       // with the same policy.
   2617       commitment: Amount;
   2618 
   2619       // Date until the auction must have been successfully executed and
   2620       // a valid transcript provided to the
   2621       // ``/extensions/policy_brandt_vickrey_auction``-endpoint of the
   2622       // exchange.
   2623       //
   2624       // [If the auction has not been executed by then] OR [has been executed
   2625       // before then, but this bidder did not win], the coin's value doesn't
   2626       // change and the owner can refresh the coin.
   2627       //
   2628       // If this bidder won the auction, the winning price/amount from the
   2629       // outcome will be substracted from the coin and transfered to the
   2630       // merchant's ``payout_uri`` from the deposit request (minus a potential
   2631       // auction fee).  For any remaining value, the bidder can refresh the
   2632       // coin to retrieve change.
   2633       deadline: Timestamp;
   2634     }
   2635 
   2636   .. ts:def:: BrandtVickreyAuction
   2637 
   2638     // CAVEAT: THIS IS STILL WORK IN PROGRESS.
   2639     // This structure defines an auction of Brandt-Vickory kind.
   2640     // It is used for the `PolicyBrandtVickreyAuction`.
   2641     interface BrandtVickreyAuction {
   2642       // Start date of the auction
   2643       time_start: Timestamp;
   2644 
   2645       // Maximum duration per round.  There are four rounds in an auction of
   2646       // Brandt-Vickrey kind.
   2647       time_round: RelativeTime;
   2648 
   2649       // This integer m refers to the (m+1)-type of the Brandt-Vickrey-auction.
   2650       // - Type 0 refers to an auction with one highest-price winner,
   2651       // - Type 1 refers to an auction with one winner, paying the second
   2652       //   highest price,
   2653       // - Type 2 refers to an auction with two winners, paying
   2654       //   the third-highest price,
   2655       // - etc.
   2656       auction_type: Integer;
   2657 
   2658       // The vector of prices for the Brandt-Vickrey auction.  The values MUST
   2659       // be in strictly increasing order.
   2660       prices: Amount[];
   2661 
   2662       // The type of outcome of the auction.
   2663       // In case the auction is declared public, each bidder can calculate the
   2664       // winning price.  This field is not relevant for the replay of a
   2665       // transcript, as the transcript must be provided by the seller who sees
   2666       // the winner(s) and winning price of the auction.
   2667       outcome_public: boolean;
   2668 
   2669       // The public key of the seller.
   2670       pubkey: EddsaPublicKey;
   2671 
   2672       // The seller's account details as a full payto URI.
   2673       payto_uri: string;
   2674     }
   2675 
   2676 
   2677   .. ts:def:: PolicyEscrowedPayment
   2678 
   2679     // CAVEAT: THIS IS STILL WORK IN PROGRESS
   2680     // This policy is optional and might not be supported by the exchange.
   2681     // If it does, the exchange MUST show support for this policy in the
   2682     // ``extensions`` field in the response to ``/keys``.
   2683     interface PolicyEscrowedPayment {
   2684       type: "escrowed_payment";
   2685 
   2686       // Public key of this trustor, the owner of the coins.
   2687       //
   2688       // To claim the deposit, the merchant must provide the valid signature
   2689       // of the ``h_contract_terms`` field from the deposit, signed by _this_
   2690       // key, to the ``/extensions/policy_escrow``-endpoint of the exchange,
   2691       // after the date specified in ``not_before`` and before the date
   2692       // specified in ``not_after``.
   2693       trustor_pub: EddsaPublicKey;
   2694 
   2695       // Latest date by which the deposit must be claimed.  If the deposit
   2696       // has not been claimed by that date, the deposited coins can be
   2697       // refreshed by the (still) owner.
   2698       deadline: Timestamp;
   2699     }
   2700 
   2701   The deposit operation succeeds if the coin is valid for making a deposit and
   2702   has enough residual value that has not already been deposited or melted.
   2703 
   2704   .. ts:def:: DepositSuccess
   2705 
   2706      interface DepositSuccess {
   2707       // Optional base URL of the exchange for looking up wire transfers
   2708       // associated with this transaction.  If not given,
   2709       // the base URL is the same as the one used for this request.
   2710       // Can be used if the base URL for ``/transactions/`` differs from that
   2711       // for ``/coins/``, i.e. for load balancing.  Clients SHOULD
   2712       // respect the ``transaction_base_url`` if provided.  Any HTTP server
   2713       // belonging to an exchange MUST generate a 307 or 308 redirection
   2714       // to the correct base URL should a client uses the wrong base
   2715       // URL, or if the base URL has changed since the deposit.
   2716       transaction_base_url?: string;
   2717 
   2718       // Timestamp when the deposit was received by the exchange.
   2719       exchange_timestamp: Timestamp;
   2720 
   2721       // `Public EdDSA key of the exchange <sign-key-pub>` that was used to
   2722       // generate the signature.
   2723       // Should match one of the exchange's signing keys from ``/keys``.  It is given
   2724       // explicitly as the client might otherwise be confused by clock skew as to
   2725       // which signing key was used.
   2726       exchange_pub: EddsaPublicKey;
   2727 
   2728       // Deposit confirmation signature from the exchange.
   2729       // The EdDSA signature of `TALER_DepositConfirmationPS` using a current
   2730       // `signing key of the exchange <sign-key-priv>` affirming the successful
   2731       // deposit and that the exchange will transfer the funds after the refund
   2732       // deadline, or as soon as possible if the refund deadline is zero.
   2733       exchange_sig: EddsaSignature;
   2734     }
   2735 
   2736   .. ts:def:: DepositDoubleSpendError
   2737 
   2738     interface DepositDoubleSpendError {
   2739 
   2740       // Must be TALER_EC_EXCHANGE_GENERIC_INSUFFICIENT_FUNDS
   2741       // or TALER_EC_EXCHANGE_GENERIC_COIN_CONFLICTING_DENOMINATION_KEY
   2742       code: Integer;
   2743 
   2744       // A string explaining that the user tried to
   2745       // double-spend.
   2746       hint: string;
   2747 
   2748       // EdDSA public key of a coin being double-spent.
   2749       coin_pub: EddsaPublicKey;
   2750 
   2751       // Hash of the public key of the denomination of the coin.
   2752       h_denom_pub: HashCode;
   2753 
   2754     }
   2755 
   2756 
   2757 
   2758 ------
   2759 Recoup
   2760 ------
   2761 
   2762 The purpose of this API is to allow coins to be cashed back in,
   2763 in certain exceptional situations.
   2764 This API is only used if the exchange is either about to go out of
   2765 business or has had its private signing keys compromised (so in
   2766 either case, the protocol is only used in **abnormal**
   2767 situations).  In the above cases, the exchange signals to the
   2768 wallets that the emergency cash back protocol has been activated
   2769 by putting the affected denomination keys into the cash-back
   2770 part of the ``/keys`` response.  If and only if this has happened,
   2771 coins that were signed with those denomination keys can be cashed
   2772 in using this API.
   2773 
   2774 For a recoup, a coin has to provide the necessary information to
   2775 identify the original transaction (either a withdraw or a refresh) it
   2776 became minted, and proof ownership of the coin itself.
   2777 
   2778 
   2779 .. http:post:: /recoup-withdraw
   2780 
   2781   Demand that a batch of coins be refunded to the reserve,
   2782   from which the coins were originally withdrawn.
   2783   The coins must have been originated from the same call to withdraw, and be
   2784   a subset of that original batch.
   2785   The remaining amount on the coin will be credited to the reserve
   2786   that the coins were withdrawn from, in the same withdraw request.
   2787 
   2788   Note that the original withdrawal fees will **not** be recouped.
   2789 
   2790   .. note:: This endpoint still Work-in-Progress.  It will be implemented in **vRECOUP**, sometime after **vDOLDPLUS**.
   2791 
   2792   **Request:**
   2793 
   2794   The request body must be a `RecoupWithdrawRequest` object.
   2795 
   2796   It provides sufficient information to
   2797   a) identify the originating withdraw request
   2798   b) proof that the coins to be recouped were part of that withdraw request
   2799   c) proof ownership of all coins requested to be recouped.
   2800 
   2801   **Response:**
   2802 
   2803   :http:statuscode:`200 OK`:
   2804     The request was successful, and the response is a `ReserveSummary`.
   2805   :http:statuscode:`403 Forbidden`:
   2806     A coin's signature is invalid.
   2807     This response comes with a standard `ErrorDetail` response.
   2808   :http:statuscode:`404 Not found`:
   2809     A denomination key is unknown,
   2810     the withdraw commitment is unknown
   2811     or a blinded coin is not known to have been withdrawn.
   2812     If a denomination key is unknown, the response will be
   2813     a `DenominationUnknownMessage`.
   2814   :http:statuscode:`409 Conflict`:
   2815     The operation is not allowed
   2816     as a coin has insufficient residual value,
   2817     or because the same public key of a coin
   2818     has been previously used with a different denomination.
   2819     Which case it is can be decided by looking at the error code
   2820     (usually ``TALER_EC_EXCHANGE_GENERIC_INSUFFICIENT_FUNDS``).
   2821     The response is a `DepositDoubleSpendError`.
   2822   :http:statuscode:`410 Gone`:
   2823     A requested denomination key is not yet or no longer valid.
   2824     It either before the validity start, past the expiration or was not yet revoked.
   2825     The response is a `DenominationGoneMessage`.
   2826     Clients must evaluate the error code provided
   2827     to understand which of the cases this is and handle it accordingly.
   2828 
   2829   **Details:**
   2830 
   2831   .. ts:def:: RecoupWithdrawRequest
   2832 
   2833     interface RecoupWithdrawRequest {
   2834       // Public key of the reserve that will receive the recoup.
   2835       // MUST be the same as the one from the original withdraw.
   2836       reserve_pub: EddsaPublicKey;
   2837 
   2838       // The details about the coins:
   2839       // An array of either
   2840       // a) the hash code of a blinded coin envelope (not to be recouped)
   2841       // b) the disclosed coin details, in order to recoup it.
   2842       // From these, the hash of all coin envelopes
   2843       // from the original withdraw can be reconstructed.
   2844       coin_data: RecoupCoinData[];
   2845     }
   2846 
   2847   .. ts:def:: RecoupCoinData
   2848 
   2849     // This is either
   2850     // a) the hash code of a blinded coin envelope (not to be recouped)
   2851     // b) the disclosed coin details, in order to recoup it.
   2852     type RecoupCoinData =
   2853        | NonRecoupedCoin
   2854        | RecoupDisclosedCoinDetails;
   2855 
   2856   .. ts:def:: NonRecoupedCoin
   2857 
   2858     interface  NonRecoupedCoin {
   2859       type: "non_recouped_coin";
   2860 
   2861       // This is the SHA512 hash code of a blinded coin envelope,
   2862       // including the corresponding denomination's hash.
   2863       // It is the output of the TALER_coin_ev_hash function
   2864       // from libtalerutil.
   2865       coin_ev: BlindedCoinEnvelopeHash;
   2866     };
   2867 
   2868   .. ts:def:: BlindedCoinEnvelopeHash
   2869 
   2870     // The hash value of a blinded coin envelope,
   2871     // as it its generated by the function TALER_coin_ev_hash
   2872     // in libtalerutil.
   2873     type BlindedCoinEnvelopeHash = HashCode;
   2874 
   2875   .. ts:def:: RecoupDisclosedCoinDetails
   2876 
   2877     // This object provides all necessary coin data
   2878     // in order to call TALER_denom_blind and retrieve
   2879     // a blinded coin planchet, from which we can
   2880     // calculate the blinded coin envelope hash.
   2881     // It also contains the denomination's signature
   2882     // for the (unblinded) coin's public key,
   2883     // and the coin's signature to authorize the recoup request.
   2884     interface RecoupDisclosedCoinDetails {
   2885       type: "recoup_coin_details";
   2886 
   2887       // The coin's public key
   2888       coin_pub: CoinPublicKey;
   2889 
   2890       // The blinding secret for this coin
   2891       // that was used during withdraw
   2892       coin_blinding_key_secret: DenominationBlindingKeySecret;
   2893 
   2894       // The coin's commitment for age restriction,
   2895       // if the denomination had age restriction support.
   2896       age_commitment_h?: AgeCommitmentHash;
   2897 
   2898       // The blinding nonce that went into this coin's
   2899       // blinded envelope
   2900       cs_session_nonce?: HashCode;
   2901 
   2902       // In case of Clause-Schnorr denomination,
   2903       // the blinding values that were provided
   2904       // for this coin, by the exchange, as response
   2905       // to a call to /blinding-prepare.
   2906       cs_r_pubs?: CSRPublicPair;
   2907 
   2908       // Unblinded signature of the coins' public key,
   2909       // signed by the denomination key.
   2910       denom_pub_sig: DenominationSignature;
   2911 
   2912       // The denomination public key.
   2913       // This denomination MUST be eligible for recoup,
   2914       // i.e. being listed in the "recoup" section of /config.
   2915       denom_pub_h: HashCode;
   2916 
   2917       // Signature of `TALER_RecoupRequestPS`,
   2918       // created by this coin's private key.
   2919       coin_sig: EddsaSignature;
   2920     }
   2921 
   2922 
   2923 .. http:post:: /recoup-refresh
   2924 
   2925   Demand that a batch of coins be refunded to the original coin,
   2926   from which the coins were originally refreshed.
   2927   The coins must have been originated from the same call to refresh, and be
   2928   a subset of that original batch.
   2929   The remaining amount on the coin will be credited to the original coin
   2930   that the coins were refreshed from, in the same refresh request.
   2931 
   2932   The base URL for coin related requests may differ from the main base URL of the
   2933   exchange. The exchange MUST return a 307 or 308 redirection to the correct
   2934   base URL if this is the case.
   2935 
   2936   Note that the original refresh fees will **not** be recouped.
   2937 
   2938   .. note:: This endpoint still Work-in-Progress.  It will be implemented in **vRECOUP**, sometime after **vDOLDPLUS**.
   2939 
   2940   **Request:**
   2941 
   2942   The request body must be a `RecoupRefreshRequest` object.
   2943 
   2944   **Response:**
   2945 
   2946   :http:statuscode:`200 OK`:
   2947     The request was successful, and the response is a `RecoupRefreshConfirmation`.
   2948     Note that repeating exactly the same request
   2949     will again yield the same response, so if the network goes down during the
   2950     transaction or before the client can commit the coin signature to disk, the
   2951     coin is not lost.
   2952   :http:statuscode:`403 Forbidden`:
   2953     The coin's signature is invalid.
   2954     This response comes with a standard `ErrorDetail` response.
   2955   :http:statuscode:`404 Not found`:
   2956     The denomination key is unknown, or the blinded
   2957     coin is not known to have been withdrawn.
   2958     If the denomination key is unknown, the response will be
   2959     a `DenominationUnknownMessage`.
   2960   :http:statuscode:`409 Conflict`:
   2961     The operation is not allowed as the coin has insufficient
   2962     residual value, or because the same public key of the coin has been
   2963     previously used with a different denomination.  Which case it is
   2964     can be decided by looking at the error code
   2965     (usually ``TALER_EC_EXCHANGE_GENERIC_INSUFFICIENT_BALANCE``).
   2966     The response is a `DepositDoubleSpendError`.
   2967   :http:statuscode:`410 Gone`:
   2968     The requested denomination key is not yet or no longer valid.
   2969     It either before the validity start, past the expiration or was not yet revoked. The response is a
   2970     `DenominationGoneMessage`. Clients must evaluate
   2971     the error code provided to understand which of the
   2972     cases this is and handle it accordingly.
   2973 
   2974   **Details:**
   2975 
   2976   .. ts:def:: RecoupRefreshRequest
   2977 
   2978     interface RecoupRefreshRequest {
   2979       // Public key of the original coin that will receive the recoup.
   2980       // MUST be the same as the one from the original refresh request.
   2981       old_coin_pub: EddsaPublicKey;
   2982 
   2983       // The details about the coins:
   2984       // An array of either
   2985       // a) the hash code of a blinded coin envelope (not to be recouped)
   2986       // b) the disclosed coin details, in order to recoup it.
   2987       // From these, the hash of all coin envelopes
   2988       // from the original refresh can be reconstructed.
   2989       coin_data: RecoupCoinData[];
   2990     }
   2991 
   2992 
   2993   .. ts:def:: RecoupRefreshConfirmation
   2994 
   2995     interface RecoupRefreshConfirmation {
   2996       // Public key of the old coin that will receive the recoup.
   2997       old_coin_pub: EddsaPublicKey;
   2998 
   2999       // The new balance of the old coin, after it has absorved
   3000       // the residual values of the coins from the request.
   3001       balance: Amount;
   3002     }
   3003 
   3004 
   3005 
   3006 .. _exchange_refund:
   3007 
   3008 -------
   3009 Refunds
   3010 -------
   3011 
   3012 .. http:post:: /coins/$COIN_PUB/refund
   3013 
   3014   Undo deposit of the given coin, restoring its value.
   3015 
   3016   **Request:**
   3017 
   3018   The request body must be a `RefundRequest` object.
   3019 
   3020   **Response:**
   3021 
   3022   :http:statuscode:`200 OK`:
   3023     The operation succeeded, the exchange confirms that the coin can now be refreshed.  The response will include a `RefundSuccess` object.
   3024   :http:statuscode:`403 Forbidden`:
   3025     Merchant signature is invalid.
   3026     This response comes with a standard `ErrorDetail` response.
   3027   :http:statuscode:`404 Not found`:
   3028     The refund operation failed as we could not find a matching deposit operation (coin, contract, transaction ID and merchant public key must all match).
   3029     This response comes with a standard `ErrorDetail` response.
   3030   :http:statuscode:`409 Conflict`:
   3031     The exchange has previously received a refund request for the same coin, merchant and contract, but specifying a different amount for the same refund transaction ID.  The response will be a `RefundFailure` object.
   3032   :http:statuscode:`410 Gone`:
   3033     It is too late for a refund by the exchange, the money was already sent to the merchant.
   3034     This response comes with a standard `ErrorDetail` response.
   3035   :http:statuscode:`412 Precondition failed`:
   3036     The request transaction ID is identical to a previous refund request by the same
   3037     merchant for the same coin and contract, but the refund amount differs. (The
   3038     failed precondition is that the ``rtransaction_id`` is not unique.)
   3039     The response will be a `RefundFailure` object with the conflicting refund request.
   3040 
   3041   **Details:**
   3042 
   3043   .. ts:def:: RefundRequest
   3044 
   3045      interface RefundRequest {
   3046 
   3047       // Amount to be refunded, can be a fraction of the
   3048       // coin's total deposit value (including deposit fee);
   3049       // must be larger than the refund fee.
   3050       refund_amount: Amount;
   3051 
   3052       // SHA-512 hash of the contact of the merchant with the customer.
   3053       h_contract_terms: HashCode;
   3054 
   3055       // 64-bit transaction id of the refund transaction between merchant and customer.
   3056       rtransaction_id: Integer;
   3057 
   3058       // EdDSA public key of the merchant.
   3059       merchant_pub: EddsaPublicKey;
   3060 
   3061       // EdDSA signature of the merchant over a
   3062       // `TALER_RefundRequestPS` with purpose
   3063       // ``TALER_SIGNATURE_MERCHANT_REFUND``
   3064       // affirming the refund.
   3065       merchant_sig: EddsaPublicKey;
   3066 
   3067     }
   3068 
   3069   .. ts:def:: RefundSuccess
   3070 
   3071     interface RefundSuccess {
   3072 
   3073       // The EdDSA :ref:`signature` (binary-only) with purpose
   3074       // ``TALER_SIGNATURE_EXCHANGE_CONFIRM_REFUND`` over
   3075       // a `TALER_RecoupRefreshConfirmationPS`
   3076       // using a current signing key of the
   3077       // exchange affirming the successful refund.
   3078       exchange_sig: EddsaSignature;
   3079 
   3080       // Public EdDSA key of the exchange that was used to generate the signature.
   3081       // Should match one of the exchange's signing keys from ``/keys``.  It is given
   3082       // explicitly as the client might otherwise be confused by clock skew as to
   3083       // which signing key was used.
   3084       exchange_pub: EddsaPublicKey;
   3085    }
   3086 
   3087   .. ts:def:: RefundFailure
   3088 
   3089     interface RefundFailure {
   3090 
   3091       // Numeric error code unique to the condition, which can be either
   3092       // related to the deposit value being insufficient for the requested
   3093       // refund(s), or the requested refund conflicting due to refund
   3094       // transaction number re-use (with different amounts).
   3095       code: Integer;
   3096 
   3097       // Human-readable description of the error message.
   3098       hint: string;
   3099 
   3100       // Information about the conflicting refund request(s).
   3101       // This will not be the full history of the coin, but only
   3102       // the relevant subset of the transactions.
   3103       history: CoinSpendHistoryItem[];
   3104     }
   3105 
   3106 
   3107 .. _reserve-history:
   3108 
   3109 ---------------
   3110 Reserve History
   3111 ---------------
   3112 
   3113 .. http:get:: /reserves/$RESERVE_PUB/history
   3114 
   3115   Request information about the full history of
   3116   a reserve or an account.
   3117 
   3118   **Request:**
   3119 
   3120   The GET request should come with the following HTTP headers:
   3121 
   3122   *If-None-Match*:
   3123     The client MAY provide an ``If-None-Match`` header with an
   3124     Etag.  In that case, the server MUST additionally respond with an ``304``
   3125     status code in case the reserve history matches the provided Etag.
   3126 
   3127   *Taler-Reserve-History-Signature*:
   3128     The client MUST provide Base-32 encoded
   3129     EdDSA signature over a ``TALER_SIGNATURE_RESERVE_HISTORY_REQUEST`` made with
   3130     the respective ``$RESERVE_PRIV``, affirming desire to download the current
   3131     reserve transaction history.
   3132 
   3133   :query start=OFFSET: *Optional.* Only return reserve history entries with
   3134                        offsets above the given OFFSET. Allows clients to not
   3135                        retrieve history entries they already have.
   3136 
   3137   **Response:**
   3138 
   3139   :http:statuscode:`200 OK`:
   3140     The exchange responds with a `ReserveHistory` object; the reserve was known to the exchange.
   3141   :http:statuscode:`204 No content`:
   3142     The reserve history is known, but at this point from the given starting point it is empty. Can only happen if OFFSET was positive.
   3143   :http:statuscode:`304 Not modified`:
   3144     The reserve history matches the one identified by the "If-none-match" HTTP header of the request.
   3145   :http:statuscode:`403 Forbidden`:
   3146     The *TALER_SIGNATURE_RESERVE_HISTORY_REQUEST* is invalid.
   3147     This response comes with a standard `ErrorDetail` response.
   3148   :http:statuscode:`404 Not found`:
   3149     The reserve key does not belong to a reserve known to the exchange.
   3150 
   3151   **Details:**
   3152 
   3153   .. ts:def:: ReserveHistory
   3154 
   3155     interface ReserveHistory {
   3156       // Balance left in the reserve.
   3157       balance: Amount;
   3158 
   3159       // If set, gives the maximum age group that the client is required to set
   3160       // during withdrawal.
   3161       maximum_age_group: Integer;
   3162 
   3163       // Transaction history for this reserve.
   3164       // May be partial (!).
   3165       history: TransactionHistoryItem[];
   3166     }
   3167 
   3168   Objects in the transaction history have the following format:
   3169 
   3170   .. ts:def:: TransactionHistoryItem
   3171 
   3172     // Union discriminated by the "type" field.
   3173     type TransactionHistoryItem =
   3174       | AccountSetupTransaction
   3175       | ReserveWithdrawTransaction
   3176       | ReserveCreditTransaction
   3177       | ReserveClosingTransaction
   3178       | ReserveOpenRequestTransaction
   3179       | ReserveCloseRequestTransaction
   3180       | PurseMergeTransaction;
   3181 
   3182   .. ts:def:: AccountSetupTransaction
   3183 
   3184     interface AccountSetupTransaction {
   3185       type: "SETUP";
   3186 
   3187       // Offset of this entry in the reserve history.
   3188       // Useful to request incremental histories via
   3189       // the "start" query parameter.
   3190       history_offset: Integer;
   3191 
   3192       // KYC fee agreed to by the reserve owner.
   3193       kyc_fee: Amount;
   3194 
   3195       // Time when the KYC was triggered.
   3196       kyc_timestamp: Timestamp;
   3197 
   3198       // Hash of the wire details of the account.
   3199       // Note that this hash is unsalted and potentially
   3200       // private (as it could be inverted), hence access
   3201       // to this endpoint must be authorized using the
   3202       // private key of the reserve.
   3203       h_wire: HashCode;
   3204 
   3205       // Signature created with the reserve's private key.
   3206       // Must be of purpose ``TALER_SIGNATURE_ACCOUNT_SETUP_REQUEST`` over
   3207       // a ``TALER_AccountSetupRequestSignaturePS``.
   3208       reserve_sig: EddsaSignature;
   3209 
   3210     }
   3211 
   3212   .. ts:def:: ReserveWithdrawTransaction
   3213 
   3214     interface ReserveWithdrawTransaction {
   3215       type: "WITHDRAW";
   3216 
   3217       // Offset of this entry in the reserve history.
   3218       // Useful to request incremental histories via
   3219       // the "start" query parameter.
   3220       history_offset: Integer;
   3221 
   3222       // Amount withdrawn.
   3223       amount: Amount;
   3224 
   3225       // Total fee that is charged for withdraw.
   3226       withdraw_fee: Amount;
   3227 
   3228       // Total number of coins in the withdraw request
   3229       num_coins: Integer;
   3230 
   3231       // Signature over a `TALER_WithdrawRequestPS`
   3232       // with purpose ``TALER_SIGNATURE_WALLET_RESERVE_WITHDRAW``
   3233       // created with the reserve's private key.
   3234       reserve_sig: EddsaSignature;
   3235 
   3236       // The hash of the all the planchets that were provided during the
   3237       // call to /withdraw.
   3238       h_planchets: HashCode;
   3239 
   3240       // The blinding seed that was provided. It will be NULL if
   3241       // no denominations of cipher type Clause-Schnorr were invovled
   3242       blinding_seed?: BlindingMasterSeed;
   3243 
   3244       // The array of hashes of public key of denominations for the coins.
   3245       denom_pub_hashes: HashCode[];
   3246 
   3247       // The maximum age committed to, if the withdraw request
   3248       // required age-restriction
   3249       max_age?: Integer;
   3250 
   3251       // The noreveal index that was returned as part
   3252       // of a age-restricted withdraw, if applicable
   3253       noreveal_index?: Integer;
   3254 
   3255      }
   3256 
   3257 
   3258   .. ts:def:: ReserveCreditTransaction
   3259 
   3260     interface ReserveCreditTransaction {
   3261       type: "CREDIT";
   3262 
   3263       // Offset of this entry in the reserve history.
   3264       // Useful to request incremental histories via
   3265       // the "start" query parameter.
   3266       history_offset: Integer;
   3267 
   3268       // Amount deposited.
   3269       amount: Amount;
   3270 
   3271       // Sender account full payto:// URI.
   3272       sender_account_url: string;
   3273 
   3274       // Opaque identifier internal to the exchange that
   3275       // uniquely identifies the wire transfer that credited the reserve.
   3276       wire_reference: Integer;
   3277 
   3278       // Timestamp of the incoming wire transfer.
   3279       timestamp: Timestamp;
   3280     }
   3281 
   3282 
   3283   .. ts:def:: ReserveClosingTransaction
   3284 
   3285     interface ReserveClosingTransaction {
   3286       type: "CLOSING";
   3287 
   3288       // Offset of this entry in the reserve history.
   3289       // Useful to request incremental histories via
   3290       // the "start" query parameter.
   3291       history_offset: Integer;
   3292 
   3293       // Closing balance.
   3294       amount: Amount;
   3295 
   3296       // Closing fee charged by the exchange.
   3297       closing_fee: Amount;
   3298 
   3299       // Wire transfer subject.
   3300       wtid: Base32;
   3301 
   3302       // Full payto URI of the wire account into which the funds were returned to.
   3303       receiver_account_details: string;
   3304 
   3305       // This is a signature over a
   3306       // struct `TALER_ReserveCloseConfirmationPS` with purpose
   3307       // ``TALER_SIGNATURE_EXCHANGE_RESERVE_CLOSED``.
   3308       exchange_sig: EddsaSignature;
   3309 
   3310       // Public key used to create 'exchange_sig'.
   3311       exchange_pub: EddsaPublicKey;
   3312 
   3313       // Time when the reserve was closed.
   3314       timestamp: Timestamp;
   3315     }
   3316 
   3317 
   3318   .. ts:def:: ReserveOpenRequestTransaction
   3319 
   3320     interface ReserveOpenRequestTransaction {
   3321       type: "OPEN";
   3322 
   3323       // Offset of this entry in the reserve history.
   3324       // Useful to request incremental histories via
   3325       // the "start" query parameter.
   3326       history_offset: Integer;
   3327 
   3328       // Open fee paid from the reserve.
   3329       open_fee: Amount;
   3330 
   3331       // This is a signature over
   3332       // a struct `TALER_ReserveOpenPS` with purpose
   3333       // ``TALER_SIGNATURE_WALLET_RESERVE_OPEN``.
   3334       reserve_sig: EddsaSignature;
   3335 
   3336       // Timestamp of the open request.
   3337       request_timestamp: Timestamp;
   3338 
   3339       // Requested expiration.
   3340       requested_expiration: Timestamp;
   3341 
   3342       // Requested number of free open purses.
   3343       requested_min_purses: Integer;
   3344 
   3345     }
   3346 
   3347   .. ts:def:: ReserveCloseRequestTransaction
   3348 
   3349     interface ReserveCloseRequestTransaction {
   3350       type: "CLOSE";
   3351 
   3352       // Offset of this entry in the reserve history.
   3353       // Useful to request incremental histories via
   3354       // the "start" query parameter.
   3355       history_offset: Integer;
   3356 
   3357       // This is a signature over
   3358       // a struct `TALER_ReserveClosePS` with purpose
   3359       // ``TALER_SIGNATURE_WALLET_RESERVE_CLOSE``.
   3360       reserve_sig: EddsaSignature;
   3361 
   3362       // Hash over the full payto URI of the target account.
   3363       h_payto?: FullPaytoHash;
   3364 
   3365       // Timestamp of the close request.
   3366       request_timestamp: Timestamp;
   3367     }
   3368 
   3369   .. ts:def:: PurseMergeTransaction
   3370 
   3371     interface PurseMergeTransaction {
   3372       type: "MERGE";
   3373 
   3374       // Offset of this entry in the reserve history.
   3375       // Useful to request incremental histories via
   3376       // the "start" query parameter.
   3377       history_offset: Integer;
   3378 
   3379       // SHA-512 hash of the contact of the purse.
   3380       h_contract_terms: HashCode;
   3381 
   3382       // EdDSA public key used to approve merges of this purse.
   3383       merge_pub: EddsaPublicKey;
   3384 
   3385       // Minimum age required for all coins deposited into the purse.
   3386       min_age: Integer;
   3387 
   3388       // Number that identifies who created the purse
   3389       // and how it was paid for.
   3390       flags: Integer;
   3391 
   3392       // Purse public key.
   3393       purse_pub: EddsaPublicKey;
   3394 
   3395       // EdDSA signature of the account/reserve affirming the merge
   3396       // over a `TALER_AccountMergeSignaturePS`.
   3397       // Must be of purpose ``TALER_SIGNATURE_ACCOUNT_MERGE``
   3398       reserve_sig: EddsaSignature;
   3399 
   3400       // Client-side timestamp of when the merge request was made.
   3401       merge_timestamp: Timestamp;
   3402 
   3403       // Indicative time by which the purse should expire
   3404       // if it has not been merged into an account. At this
   3405       // point, all of the deposits made should be
   3406       // auto-refunded.
   3407       purse_expiration: Timestamp;
   3408 
   3409       // Purse fee the reserve owner paid for the purse creation.
   3410       purse_fee: Amount;
   3411 
   3412       // Total amount merged into the reserve.
   3413       // (excludes fees).
   3414       amount: Amount;
   3415 
   3416       // True if the purse was actually merged.
   3417       // If false, only the purse_fee has an impact
   3418       // on the reserve balance!
   3419       merged: boolean;
   3420     }
   3421 
   3422 
   3423 
   3424 .. _coin-history:
   3425 
   3426 ------------
   3427 Coin History
   3428 ------------
   3429 
   3430 .. http:get:: /coins/$COIN_PUB/history
   3431 
   3432 Obtain the transaction history of a coin.  Used only in special cases, like
   3433 when the exchange claims a double-spending error and the wallet does not
   3434 believe it. Usually, the wallet knows the transaction history of each coin
   3435 and thus has no need to inquire.
   3436 
   3437 **Request:**
   3438 
   3439 The GET request should come with the following HTTP headers:
   3440 
   3441 *If-None-Match*:
   3442   The client MAY provide an ``If-None-Match`` header with an
   3443   Etag.  In that case, the server MUST additionally respond with an ``304``
   3444   status code in case the coin history matches the provided Etag.
   3445 
   3446 *Taler-Coin-History-Signature*:
   3447   The client MUST provide Base-32 encoded EdDSA signature over a
   3448   ``TALER_SIGNATURE_COIN_HISTORY_REQUEST`` made with the respective
   3449   ``$COIN_PRIV``, affirming desire to download the current coin
   3450   transaction history.
   3451 
   3452 :query start=OFFSET: *Optional.* Only return coin history entries with
   3453                      offsets above the given OFFSET. Allows clients to not
   3454                      retrieve history entries they already have.
   3455 
   3456 **Response:**
   3457 
   3458 :http:statuscode:`200 OK`:
   3459   The operation succeeded, the exchange confirms that no double-spending took
   3460   place.  The response will include a `CoinHistoryResponse` object.
   3461 :http:statuscode:`204 No content`:
   3462   The reserve history is known, but at this point from the given starting point it is empty. Can only happen if OFFSET was positive.
   3463 :http:statuscode:`304 Not modified`:
   3464   The coin history has not changed since the previous query (detected via Etag
   3465   in "If-none-match" header).
   3466 :http:statuscode:`403 Forbidden`:
   3467   The *TALER_SIGNATURE_COIN_HISTORY_REQUEST* is invalid.
   3468   This response comes with a standard `ErrorDetail` response.
   3469 :http:statuscode:`404 Not found`:
   3470   The coin public key is not (yet) known to the exchange.
   3471 
   3472 **Details:**
   3473 
   3474 .. ts:def:: CoinHistoryResponse
   3475 
   3476   interface CoinHistoryResponse {
   3477     // Current balance of the coin.
   3478     balance: Amount;
   3479 
   3480     // Hash of the coin's denomination.
   3481     h_denom_pub: HashCode;
   3482 
   3483     // Transaction history for the coin.
   3484     history: CoinSpendHistoryItem[];
   3485   }
   3486 
   3487 .. ts:def:: CoinSpendHistoryItem
   3488 
   3489   // Union discriminated by the "type" field.
   3490   type CoinSpendHistoryItem =
   3491     | CoinDepositTransaction
   3492     | CoinMeltTransaction
   3493     | CoinRefundTransaction
   3494     | CoinRecoupWithdrawTransaction
   3495     | CoinRecoupRefreshTransaction
   3496     | CoinRecoupRefreshReceiverTransaction
   3497     | CoinPurseDepositTransaction
   3498     | CoinPurseRefundTransaction
   3499     | CoinReserveOpenDepositTransaction;
   3500 
   3501 .. ts:def:: CoinDepositTransaction
   3502 
   3503   interface CoinDepositTransaction {
   3504     type: "DEPOSIT";
   3505 
   3506     // Offset of this entry in the reserve history.
   3507     // Useful to request incremental histories via
   3508     // the "start" query parameter.
   3509     history_offset: Integer;
   3510 
   3511     // The total amount of the coin's value absorbed (or restored in the
   3512     // case of a refund) by this transaction.
   3513     // The amount given includes
   3514     // the deposit fee. The current coin value can thus be computed by
   3515     // subtracting this amount.
   3516     amount: Amount;
   3517 
   3518     // Deposit fee.
   3519     deposit_fee: Amount;
   3520 
   3521     // Public key of the merchant.
   3522     merchant_pub: EddsaPublicKey;
   3523 
   3524     // Date when the operation was made.
   3525     timestamp: Timestamp;
   3526 
   3527     // Date until which the merchant can issue a refund to the customer via the
   3528     // exchange, possibly zero if refunds are not allowed.
   3529     refund_deadline?: Timestamp;
   3530 
   3531     // Hash over the proposal data of the contract that
   3532     // is being paid.
   3533     h_contract_terms: HashCode;
   3534 
   3535     // Hash of the bank account from where we received the funds.
   3536     h_wire: HashCode;
   3537 
   3538     // Hash of the public denomination key used to sign the coin.
   3539     // Needed because 'coin_sig' signs over this, and
   3540     // that is important to fix the coin's denomination.
   3541     h_denom_pub: HashCode;
   3542 
   3543     // Hash over the deposit policy extension. Optional.
   3544     h_policy?: HashCode;
   3545 
   3546     // Hash over auxiliary wallet data provided by the wallet
   3547     // to complete the contract. Optional.
   3548     wallet_data_hash?: HashCode;
   3549 
   3550     // Hash over the age commitment of the coin. Optional.
   3551     h_age_commitment?: HashCode;
   3552 
   3553     // Signature over `TALER_DepositRequestPS`, made by the customer with the
   3554     // `coin's private key <coin-priv>`.
   3555     coin_sig: EddsaSignature;
   3556 
   3557   }
   3558 
   3559 .. ts:def:: CoinMeltTransaction
   3560 
   3561   interface CoinMeltTransaction {
   3562     type: "MELT";
   3563 
   3564     // Offset of this entry in the reserve history.
   3565     // Useful to request incremental histories via
   3566     // the "start" query parameter.
   3567     history_offset: Integer;
   3568 
   3569     // The total amount of the coin's value absorbed by this transaction.
   3570     // Note that for melt this means the amount given includes
   3571     // the melt fee. The current coin value can thus be computed by
   3572     // subtracting the amounts.
   3573     amount: Amount;
   3574 
   3575     // Melt fee.
   3576     melt_fee: Amount;
   3577 
   3578     // Commitment from the melt operation, see `TALER_RefreshCommitmentP`
   3579     rc: HashCode;
   3580 
   3581     // Hash of the public denomination key used to sign the old coin.
   3582     // Needed because 'coin_sig' signs over this, and
   3583     // that is important to fix the coin's denomination.
   3584     old_denom_pub_h: HashCode;
   3585 
   3586     // Hash over the age commitment of the coin. Optional.
   3587     old_age_commitment_h?: AgeCommitmentHash;
   3588 
   3589     // @since vDOLDPLUS
   3590     // This value is opaque to the exchange.  It was provided by the client
   3591     // as part of the original refresh request, and was therefore verified
   3592     // with the confirm_sig below.
   3593     // If the reveal step was not performed yet by the old coin owner,
   3594     // they can use this value and the old coin's private key to derive
   3595     // all indivual seeds for the n*κ coin candidates for the original
   3596     // refresh request and replay it
   3597     refresh_seed: HashCode;
   3598 
   3599     // @since vDOLDPLUS
   3600     // The kappa*n list of transfer public keys that were provided by the
   3601     // old coin owner during the melt request.
   3602     transfer_pubs: EddsaPublicKey[kappa][];
   3603 
   3604     // @since vDOLDPLUS
   3605     // The n denomination public keys for the fresh coins
   3606     // that the coin owner had requested.
   3607     denoms_h: HashCode[];
   3608 
   3609     // @since vDOLDPLUS
   3610     // The ``noreveal_index`` value that was returned by the exchange as response
   3611     // to the melt request.
   3612     noreveal_index: Integer;
   3613 
   3614     // @since vDOLDPLUS
   3615     // If the reveal step was successfully peformed by the coin owner,
   3616     // this field contains the blind coin signatures that were returned
   3617     // by the exchange for the chosen batch of coins.
   3618     ev_sigs?: BlindedDenominationSignature[];
   3619 
   3620     // Master seed for the Clause-Schnorr R-value
   3621     // Present if one of the fresh coin's
   3622     // denominations is of type Clause-Schnorr.
   3623     blinding_seed?: BlindingMasterSeed;
   3624 
   3625     // Signature by the coin over a
   3626     // `TALER_RefreshMeltCoinAffirmationPS` of
   3627     // purpose ``TALER_SIGNATURE_WALLET_COIN_MELT``.
   3628     confirm_sig: EddsaSignature;
   3629 
   3630   }
   3631 
   3632 .. ts:def:: CoinRefundTransaction
   3633 
   3634   interface CoinRefundTransaction {
   3635     type: "REFUND";
   3636 
   3637     // Offset of this entry in the reserve history.
   3638     // Useful to request incremental histories via
   3639     // the "start" query parameter.
   3640     history_offset: Integer;
   3641 
   3642     // The total amount of the coin's value restored
   3643     // by this transaction.
   3644     // The amount given excludes the transaction fee.
   3645     // The current coin value can thus be computed by
   3646     // adding the amounts to the coin's denomination value.
   3647     amount: Amount;
   3648 
   3649     // Refund fee.
   3650     refund_fee: Amount;
   3651 
   3652     // Hash over the proposal data of the contract that
   3653     // is being refunded.
   3654     h_contract_terms: HashCode;
   3655 
   3656     // Public key of the merchant.
   3657     merchant_pub: EddsaPublicKey;
   3658 
   3659     // Refund transaction ID.
   3660     rtransaction_id: Integer;
   3661 
   3662     // `EdDSA Signature <eddsa-sig>` authorizing the REFUND over a
   3663     // `TALER_MerchantRefundConfirmationPS` with
   3664     // purpose ``TALER_SIGNATURE_MERCHANT_REFUND_OK``. Made with
   3665     // the `public key of the merchant <merchant-pub>`.
   3666     merchant_sig: EddsaSignature;
   3667 
   3668   }
   3669 
   3670 
   3671 .. note::
   3672 
   3673    The `CoinRecoupWithdrawTransaction` interface defintion is WIP.
   3674    It will be fully specified and implemented with **vRECOUP**.
   3675 
   3676 .. ts:def:: CoinRecoupWithdrawTransaction
   3677 
   3678   // This represents a transaction of a call to /recoup-withdraw
   3679   // where the coin's residual value has been credited to the
   3680   // original reserve, from which this coin was withdrawn.
   3681   interface CoinRecoupWithdrawTransaction {
   3682     type: "RECOUP-WITHDRAW";
   3683 
   3684     // Offset of this entry in the reserve history.
   3685     // Useful to request incremental histories via
   3686     // the "start" query parameter.
   3687     history_offset: Integer;
   3688 
   3689     // The total amount of the coin's value absorbed
   3690     // by this transaction.
   3691     // The current coin value can thus be computed by
   3692     // subtracting the amount from
   3693     // the coin's denomination value.
   3694     amount: Amount;
   3695 
   3696     // Signature by the exchange over a
   3697     // `TALER_RecoupConfirmationPS`, must be
   3698     // of purpose ``TALER_SIGNATURE_EXCHANGE_CONFIRM_RECOUP``.
   3699     exchange_sig: EddsaSignature;
   3700 
   3701     // Public key of the private key used to create 'exchange_sig'.
   3702     exchange_pub: EddsaPublicKey;
   3703 
   3704     // Signature by the coin over a
   3705     // `TALER_RecoupRequestPS` with purpose
   3706     // ``TALER_SIGNATURE_WALLET_COIN_RECOUP``.
   3707     coin_sig: EddsaSignature;
   3708 
   3709     // Hash of the public denomination key used to sign the coin.
   3710     // Needed because 'coin_sig' signs over this, and
   3711     // that is important to fix the coin's denomination.
   3712     h_denom_pub: HashCode;
   3713 
   3714     // Coin blinding key that was used in the original withdraw request.
   3715     coin_blind: DenominationBlindingKeyP;
   3716 
   3717     // The hash of the withdraw commitment of the original withdraw
   3718     // request that this coin was part of
   3719     h_commitment: HashCode;
   3720 
   3721     // Coin's index in the original withdraw request, starting at 0
   3722     coin_index: Integer;
   3723 
   3724     // Reserve receiving the recoup.
   3725     reserve_pub: EddsaPublicKey;
   3726 
   3727     // Date when the operation was made.
   3728     timestamp: Timestamp;
   3729 
   3730   }
   3731 
   3732 
   3733 .. note::
   3734 
   3735    The `CoinRecoupRefreshTransaction` interface defintion is WIP.
   3736    It will be fully specified and implemented with **vRECOUP**.
   3737 
   3738 .. ts:def:: CoinRecoupRefreshTransaction
   3739 
   3740   // This represents a transaction of a call to /recoup-refresh
   3741   // where this coin was _part_ of the batch of coins whose
   3742   // residual values were credited to the original coin, from
   3743   // which also this coin was refresh from.
   3744   interface CoinRecoupRefreshTransaction {
   3745     type: "RECOUP-REFRESH";
   3746 
   3747     // Offset of this entry in the reserve history.
   3748     // Useful to request incremental histories via
   3749     // the "start" query parameter.
   3750     history_offset: Integer;
   3751 
   3752     // The total amount of the coin's value absorbed
   3753     // by this transaction.
   3754     // The current coin value can thus be computed by
   3755     // subtracting this amounts from
   3756     // the coin's denomination value.
   3757     amount: Amount;
   3758 
   3759     // Signature by the exchange over a
   3760     // `TALER_RecoupRefreshConfirmationPS`
   3761     // of purpose ``TALER_SIGNATURE_EXCHANGE_CONFIRM_RECOUP_REFRESH``.
   3762     exchange_sig: EddsaSignature;
   3763 
   3764     // Public key used to sign 'exchange_sig'.
   3765     exchange_pub: EddsaPublicKey;
   3766 
   3767     // The original coin, from which this coin was derived from
   3768     // in a call to /refresh, and which was then credited with
   3769     // the residual value of this coin in a call to /recoup-refresh.
   3770     old_coin_pub: EddsaPublicKey;
   3771 
   3772     // Signature by the coin over a `TALER_RecoupRequestPS`
   3773     // with purpose ``TALER_SIGNATURE_WALLET_COIN_RECOUP``.
   3774     coin_sig: EddsaSignature;
   3775 
   3776     // Hash of the public denomination key used to sign the coin.
   3777     // Needed because 'coin_sig' signs over this, and
   3778     // that is important to fix the coin's denomination.
   3779     h_denom_pub: HashCode;
   3780 
   3781     // Coin blinding key that was used in the original refresh request.
   3782     coin_blind: DenominationBlindingKeyP;
   3783 
   3784     // The hash of the refresh commitment of the original refresh
   3785     // request that this coin was derived from.
   3786     h_commitment: HashCode;
   3787 
   3788     // Coin's index in the original refresh request, starting at 0
   3789     coin_index: Integer;
   3790 
   3791     // Blinding factor of the revoked new coin.
   3792     new_coin_blinding_secret: DenominationBlindingKeySecret;
   3793 
   3794     // Blinded public key of the revoked new coin.
   3795     new_coin_ev: DenominationBlindingKeySecret;
   3796 
   3797     // Date when the operation was made.
   3798     timestamp: Timestamp;
   3799 
   3800   }
   3801 
   3802 
   3803 .. note::
   3804 
   3805    The `CoinRecoupRefreshReceiverTransaction` interface defintion is WIP.
   3806    It will be fully specified and implemented with **vRECOUP**.
   3807 
   3808 .. ts:def:: CoinRecoupRefreshReceiverTransaction
   3809 
   3810   // This represents a transaction of a call to /recoup-refresh
   3811   // where this coin was the _receiver_ of the residual values
   3812   // from coins, that originated from a call to /refresh of this coin.
   3813   interface CoinRecoupRefreshReceiverTransaction {
   3814     type: "RECOUP-REFRESH-RECEIVER";
   3815 
   3816     // Offset of this entry in the reserve history.
   3817     // Useful to request incremental histories via
   3818     // the "start" query parameter.
   3819     history_offset: Integer;
   3820 
   3821     // The total amount of the coin's value restored
   3822     // by this transaction.
   3823     // The current coin value can thus be computed by
   3824     // adding the amount to the coin's denomination value.
   3825     amount: Amount;
   3826 
   3827     // Date when the operation was made.
   3828     timestamp: Timestamp;
   3829 
   3830     // Signature by the exchange over a
   3831     // `TALER_RecoupRefreshConfirmationPS`
   3832     // of purpose ``TALER_SIGNATURE_EXCHANGE_CONFIRM_RECOUP_REFRESH``.
   3833     exchange_sig: EddsaSignature;
   3834 
   3835     // Public key of the private key used to create 'exchange_sig'.
   3836     exchange_pub: EddsaPublicKey;
   3837 
   3838   }
   3839 
   3840 .. ts:def:: CoinPurseDepositTransaction
   3841 
   3842   interface CoinPurseDepositTransaction {
   3843     type: "PURSE-DEPOSIT";
   3844 
   3845     // Offset of this entry in the reserve history.
   3846     // Useful to request incremental histories via
   3847     // the "start" query parameter.
   3848     history_offset: Integer;
   3849 
   3850     // The total amount of the coin's value absorbed
   3851     // by this transaction.
   3852     // Note that this means the amount given includes
   3853     // the deposit fee. The current coin value can thus be computed by
   3854     // subtracting the amount from
   3855     // the coin's denomination value.
   3856     amount: Amount;
   3857 
   3858     // Base URL of the exchange the purse lives at.
   3859     exchange_base_url: string;
   3860 
   3861     // The hash of the age-commitment for the coin. Only present
   3862     // if the denomination has support for age restriction.
   3863     h_age_commitment?: AgeCommitmentHash;
   3864 
   3865     // Deposit fee.
   3866     deposit_fee: Amount;
   3867 
   3868     // Public key of the purse.
   3869     purse_pub: EddsaPublicKey;
   3870 
   3871     // True if the deposit was refunded for any reason.
   3872     refunded: boolean;
   3873 
   3874     // Signature by the coin over a
   3875     // `TALER_PurseDepositSignaturePS` of
   3876     // purpose ``TALER_SIGNATURE_PURSE_DEPOSIT``.
   3877     coin_sig: EddsaSignature;
   3878 
   3879     // Hash of the public denomination key used to sign the coin.
   3880     // Needed because 'coin_sig' signs over this, and
   3881     // that is important to fix the coin's denomination.
   3882     h_denom_pub: HashCode;
   3883 
   3884   }
   3885 
   3886 .. ts:def:: CoinPurseRefundTransaction
   3887 
   3888   interface CoinPurseRefundTransaction {
   3889     type: "PURSE-REFUND";
   3890 
   3891     // Offset of this entry in the reserve history.
   3892     // Useful to request incremental histories via
   3893     // the "start" query parameter.
   3894     history_offset: Integer;
   3895 
   3896     // The total amount of the coin's value restored
   3897     // by this transaction.
   3898     // The amount given excludes the refund fee.
   3899     // The current coin value can thus be computed by
   3900     // adding the amount to the coin's denomination value.
   3901     amount: Amount;
   3902 
   3903     // Refund fee (of the coin's denomination). The deposit
   3904     // fee will be waived.
   3905     refund_fee: Amount;
   3906 
   3907     // Signature by the exchange over a
   3908     // ``TALER_CoinPurseRefundConfirmationPS``
   3909     // of purpose ``TALER_SIGNATURE_EXCHANGE_CONFIRM_PURSE_REFUND``.
   3910     exchange_sig: EddsaSignature;
   3911 
   3912     // Public key used to sign 'exchange_sig'.
   3913     exchange_pub: EddsaPublicKey;
   3914 
   3915     // Public key of the purse that expired.
   3916     purse_pub: EddsaPublicKey;
   3917 
   3918   }
   3919 
   3920 .. ts:def:: CoinReserveOpenDepositTransaction
   3921 
   3922   interface CoinReserveOpenDepositTransaction {
   3923     type: "RESERVE-OPEN-DEPOSIT";
   3924 
   3925     // Offset of this entry in the reserve history.
   3926     // Useful to request incremental histories via
   3927     // the "start" query parameter.
   3928     history_offset: Integer;
   3929 
   3930     // The total amount of the coin's value absorbed
   3931     // by this transaction.
   3932     // Note that this means the amount given includes
   3933     // the deposit fee.
   3934     coin_contribution: Amount;
   3935 
   3936     // Signature of the reserve open operation being paid for.
   3937     reserve_sig: EddsaSignature;
   3938 
   3939     // Signature by the coin over a
   3940     // `TALER_ReserveOpenDepositSignaturePS` of
   3941     // purpose ``TALER_SIGNATURE_RESERVE_OPEN_DEPOSIT``.
   3942     coin_sig: EddsaSignature;
   3943 
   3944   }
   3945 
   3946 
   3947 -----------------------
   3948 Tracking wire transfers
   3949 -----------------------
   3950 
   3951 This API is used by merchants that need to find out which wire
   3952 transfers (from the exchange to the merchant) correspond to which deposit
   3953 operations.  Typically, a merchant will receive a wire transfer with a
   3954 **wire transfer identifier** and want to know the set of deposit
   3955 operations that correspond to this wire transfer.  This is the
   3956 preferred query that merchants should make for each wire transfer they
   3957 receive.  If a merchant needs to investigate a specific deposit
   3958 operation (i.e. because it seems that it was not paid), then the
   3959 merchant can also request the wire transfer identifier for a deposit
   3960 operation.
   3961 
   3962 Sufficient information is returned to verify that the coin signatures
   3963 are correct. This also allows governments to use this API when doing
   3964 a tax audit on merchants.
   3965 
   3966 Naturally, the returned information may be sensitive for the merchant.
   3967 We do not require the merchant to sign the request, as the same requests
   3968 may also be performed by the government auditing a merchant.
   3969 However, wire transfer identifiers should have sufficient entropy to
   3970 ensure that obtaining a successful reply by brute-force is not practical.
   3971 Nevertheless, the merchant should protect the wire transfer identifiers
   3972 from his bank statements against unauthorized access, lest his income
   3973 situation is revealed to an adversary. (This is not a major issue, as
   3974 an adversary that has access to the line-items of bank statements can
   3975 typically also view the balance.)
   3976 
   3977 
   3978 .. http:get:: /transfers/$WTID
   3979 
   3980   Provides deposits associated with a given wire transfer.  The
   3981   wire transfer identifier (WTID) and the base URL for tracking
   3982   the wire transfer are both given in the wire transfer subject.
   3983 
   3984   **Request:**
   3985 
   3986   **Response:**
   3987 
   3988   :http:statuscode:`200 OK`:
   3989     The wire transfer is known to the exchange, details about it follow in the body.
   3990     The body of the response is a `TrackTransferResponse`.
   3991   :http:statuscode:`404 Not found`:
   3992     The wire transfer identifier is unknown to the exchange.
   3993 
   3994   .. ts:def:: TrackTransferResponse
   3995 
   3996     interface TrackTransferResponse {
   3997       // Actual amount of the wire transfer, excluding the wire fee.
   3998       total: Amount;
   3999 
   4000       // Applicable wire fee that was charged.
   4001       wire_fee: Amount;
   4002 
   4003       // Public key of the merchant (identical for all deposits).
   4004       merchant_pub: EddsaPublicKey;
   4005 
   4006       // Hash of the payto:// account URI (identical for all deposits).
   4007       h_payto: FullPaytoHash;
   4008 
   4009       // Time of the execution of the wire transfer by the exchange.
   4010       execution_time: Timestamp;
   4011 
   4012       // Details about the deposits.
   4013       deposits: TrackTransferDetail[];
   4014 
   4015       // Signature from the exchange made with purpose
   4016       // ``TALER_SIGNATURE_EXCHANGE_CONFIRM_WIRE_DEPOSIT``
   4017       // over a `TALER_WireDepositDataPS`.
   4018       exchange_sig: EddsaSignature;
   4019 
   4020       // Public EdDSA key of the exchange that was used to generate the signature.
   4021       // Should match one of the exchange's signing keys from ``/keys``.  Again given
   4022       // explicitly as the client might otherwise be confused by clock skew as to
   4023       // which signing key was used.
   4024       exchange_pub: EddsaSignature;
   4025     }
   4026 
   4027   .. ts:def:: TrackTransferDetail
   4028 
   4029     interface TrackTransferDetail {
   4030       // SHA-512 hash of the contact of the merchant with the customer.
   4031       h_contract_terms: HashCode;
   4032 
   4033       // Coin's public key, both ECDHE and EdDSA.
   4034       coin_pub: CoinPublicKey;
   4035 
   4036       // The total amount the original deposit was worth,
   4037       // including fees and after applicable refunds.
   4038       deposit_value: Amount;
   4039 
   4040       // Applicable fees for the deposit, possibly
   4041       // reduced or waived due to refunds.
   4042       deposit_fee: Amount;
   4043 
   4044       // Refunds that were applied to the value of
   4045       // this coin. Optional.
   4046       // @since protocol **v19**.  Before, refunds were
   4047       // incorrectly still included in the
   4048       // ``deposit_value`` (!).
   4049       refund_total?: Amount;
   4050 
   4051     }
   4052 
   4053 .. http:get:: /deposits/$H_WIRE/$MERCHANT_PUB/$H_CONTRACT_TERMS/$COIN_PUB
   4054 
   4055   Provide the wire transfer identifier associated with an (existing) deposit operation.
   4056   The arguments are the hash of the merchant's payment details (H_WIRE), the
   4057   merchant's public key (EdDSA), the hash of the contract terms that were paid
   4058   (H_CONTRACT_TERMS) and the public key of the coin used for the payment (COIN_PUB).
   4059 
   4060   **Request:**
   4061 
   4062   :query merchant_sig: EdDSA signature of the merchant made with purpose
   4063     ``TALER_SIGNATURE_MERCHANT_TRACK_TRANSACTION`` over a
   4064     ``TALER_DepositTrackPS``, affirming that it is really the merchant who
   4065     requires obtaining the wire transfer identifier.
   4066   :query timeout_ms=NUMBER: *Optional.* If specified, the exchange will wait
   4067     up to ``NUMBER`` milliseconds for completion of a deposit operation before
   4068     sending the HTTP response.
   4069   :query lpt=TARGET: *Optional*.
   4070     Specifies what status change we are long-polling for.
   4071     Use 1 to wait for the a 202 state where ``kyc_ok`` is false *or* a 200 OK response.
   4072     2 to wait exclusively for a 200 OK response.
   4073     @since protocol **v21**.
   4074 
   4075   **Response:**
   4076 
   4077   :http:statuscode:`200 OK`:
   4078     The deposit has been executed by the exchange and we have a wire transfer identifier.
   4079     The response body is a `TrackTransactionResponse` object.
   4080   :http:statuscode:`202 Accepted`:
   4081     The deposit request has been accepted for processing, but was not yet
   4082     executed.  Hence the exchange does not yet have a wire transfer identifier.  The
   4083     merchant should come back later and ask again.
   4084     The response body is a `TrackTransactionAcceptedResponse`.
   4085   :http:statuscode:`403 Forbidden`:
   4086     A signature is invalid.
   4087     This response comes with a standard `ErrorDetail` response.
   4088   :http:statuscode:`404 Not found`:
   4089     The deposit operation is unknown to the exchange.
   4090 
   4091   **Details:**
   4092 
   4093   .. ts:def:: TrackTransactionResponse
   4094 
   4095     interface TrackTransactionResponse {
   4096 
   4097       // Raw wire transfer identifier of the deposit.
   4098       wtid: Base32;
   4099 
   4100       // When was the wire transfer given to the bank.
   4101       execution_time: Timestamp;
   4102 
   4103       // The contribution of this coin to the total (without fees)
   4104       coin_contribution: Amount;
   4105 
   4106       // Binary-only Signature_ with purpose ``TALER_SIGNATURE_EXCHANGE_CONFIRM_WIRE``
   4107       // over a `TALER_ConfirmWirePS`
   4108       // whereby the exchange affirms the successful wire transfer.
   4109       exchange_sig: EddsaSignature;
   4110 
   4111       // Public EdDSA key of the exchange that was used to generate the signature.
   4112       // Should match one of the exchange's signing keys from /keys.  Again given
   4113       // explicitly as the client might otherwise be confused by clock skew as to
   4114       // which signing key was used.
   4115       exchange_pub: EddsaPublicKey;
   4116     }
   4117 
   4118   .. ts:def:: TrackTransactionAcceptedResponse
   4119 
   4120     interface TrackTransactionAcceptedResponse {
   4121 
   4122       // Legitimization row. Largely useless, except
   4123       // not present if the deposit has not
   4124       // yet been aggregated to the point that a KYC
   4125       // requirement has been evaluated.
   4126       requirement_row?: Integer;
   4127 
   4128       // True if the KYC check for the merchant has been
   4129       // satisfied.  False does not mean that KYC
   4130       // is strictly needed, unless also a
   4131       // legitimization_uuid is provided.
   4132       kyc_ok: boolean;
   4133 
   4134       // Time by which the exchange currently thinks the deposit will be executed.
   4135       // Actual execution may be later if the KYC check is not satisfied by then.
   4136       execution_time: Timestamp;
   4137 
   4138       // Public key associated with the account. The client must sign
   4139       // the initial request for the KYC status using the corresponding
   4140       // private key.  Will be the merchant (instance) public key.
   4141       //
   4142       // This is ONLY given if the merchant did a KYC auth wire transfer.
   4143       // It is not given if the deposit was made to a reserve public key.
   4144       // The wallet would already know the reserve public key, plus there
   4145       // could be various reserve public keys (which do not change), while
   4146       // there is only the *latest* KYC auth wire transfer public key.
   4147       //
   4148       // Absent if no public key is currently associated
   4149       // with the account and the client MUST thus first
   4150       // credit the exchange via an inbound wire transfer
   4151       // to associate a public key with the debited account.
   4152       // Note that absence does *not* imply a need for a KYC auth
   4153       // transfer if the deposit was made to a reserve public key
   4154       // that was also used for the deposit.
   4155       //
   4156       // @since protocol **v20**.
   4157       account_pub?: EddsaPublicKey;
   4158 
   4159     }
   4160 
   4161 
   4162 .. _exchange_w2w:
   4163 
   4164 --------------------------
   4165 Wallet-to-wallet transfers
   4166 --------------------------
   4167 
   4168 .. http:get:: /purses/$PURSE_PUB/merge
   4169 .. http:get:: /purses/$PURSE_PUB/deposit
   4170 
   4171   Obtain information about a purse.  Depending on the suffix,
   4172   the long-polling (if any) will wait for either a merge or
   4173   a deposit event.
   4174 
   4175   **Request:**
   4176 
   4177   :query timeout_ms=NUMBER: *Optional.*  If specified,
   4178     the exchange
   4179     will wait up to ``NUMBER`` milliseconds for completion
   4180     of a merge operation before sending the HTTP response.
   4181   :query deposit_timeout_ms=NUMBER: *Optional.*  If specified,
   4182     the exchange
   4183     will wait up to ``NUMBER`` milliseconds for completion
   4184     of a deposit operation before sending the HTTP response.
   4185 
   4186   **Response:**
   4187 
   4188   :http:statuscode:`200 OK`:
   4189     The operation succeeded, the exchange provides details
   4190     about the purse.
   4191     The response will include a `PurseStatus` object.
   4192   :http:statuscode:`404 Not found`:
   4193     The purse is unknown to the exchange.
   4194   :http:statuscode:`410 Gone`:
   4195     The purse expired before the deposit or merge was completed.
   4196 
   4197   **Details:**
   4198 
   4199   .. ts:def:: PurseStatus
   4200 
   4201      interface PurseStatus {
   4202 
   4203       // Total amount deposited into the purse so far.
   4204       // If 'total_deposit_amount' minus 'deposit_fees'
   4205       // exceeds 'merge_value_after_fees', and a
   4206       // 'merge_request' exists for the purse, then the
   4207       // purse will (have been) merged with the account.
   4208       balance: Amount;
   4209 
   4210       // Time of the merge, missing if "never".
   4211       merge_timestamp?: Timestamp;
   4212 
   4213       // Time of the deposits being complete, missing if "never".
   4214       // Note that this time may not be "stable": once sufficient
   4215       // deposits have been made, is "now" before the purse
   4216       // expiration, and otherwise set to the purse expiration.
   4217       // However, this should also not be relied upon. The key
   4218       // property is that it is either "never" or in the past.
   4219       deposit_timestamp?: Timestamp;
   4220 
   4221       // Time when the purse expires and
   4222       // funds that were not merged are refunded
   4223       // on the deposited coins.
   4224       // FIXME: Document the exchange protocol version
   4225       //        in which this field became available.
   4226       purse_expiration: Timestamp;
   4227 
   4228       // EdDSA signature of the exchange over a
   4229       // `TALER_PurseStatusResponseSignaturePS`
   4230       // with purpose ``TALER_SIGNATURE_PURSE_STATUS_RESPONSE``
   4231       // affirming the purse status.
   4232       exchange_sig: EddsaSignature;
   4233 
   4234       // EdDSA public key exchange used for 'exchange_sig'.
   4235       exchange_pub: EddsaPublicKey;
   4236 
   4237     }
   4238 
   4239 
   4240 
   4241 .. http:post:: /purses/$PURSE_PUB/create
   4242 
   4243   Create a purse by depositing money into it. First step of a PUSH payment.
   4244 
   4245   **Request:**
   4246 
   4247   The request body must be a `PurseCreate` object.
   4248 
   4249   **Response:**
   4250 
   4251   :http:statuscode:`200 OK`:
   4252     The operation succeeded, the exchange confirms that all
   4253     coins were deposited into the purse.
   4254     The response will include a `PurseCreateSuccessResponse` object.
   4255   :http:statuscode:`403 Forbidden`:
   4256     A coin, denomination or contract signature is invalid.
   4257     This response comes with a standard `ErrorDetail` response.
   4258   :http:statuscode:`404 Not Found`:
   4259     The denomination of one of the coins is unknown to the exchange.
   4260   :http:statuscode:`409 Conflict`:
   4261     The deposit operation has either failed because a coin has insufficient
   4262     residual value, or because the same public key of the coin has been
   4263     previously used with a different denomination, or because a purse with
   4264     the same public key but different meta data was created previously.
   4265     Which case it is
   4266     can be decided by looking at the error code
   4267     (``TALER_EC_EXCHANGE_GENERIC_INSUFFICIENT_FUNDS`` or
   4268     ``TALER_EC_EXCHANGE_GENERIC_COIN_CONFLICTING_DENOMINATION_KEY`` or
   4269     ``TALER_EC_EXCHANGE_PURSE_CREATE_CONFLICTING_META_DATA`` or
   4270     ``TALER_EC_EXCHANGE_PURSE_DEPOSIT_CONFLICTING_META_DATA`` or
   4271     ``TALER_EC_EXCHANGE_PURSE_ECONTRACT_CONFLICTING_META_DATA``).
   4272     The specific fields of the response depend on the error code
   4273     and include the signatures (and what was signed over) proving the
   4274     conflict.
   4275   :http:statuscode:`425 Too Early`:
   4276     This response type is used if the given purse expiration time
   4277     is too far in the future (at least from the perspective
   4278     of the exchange). Thus, retrying at a later time may
   4279     succeed. The client should look at the ``Date:`` header
   4280     of the response to see if a minor time difference is to
   4281     blame and possibly adjust the request accordingly.
   4282     (Note: this status code is not yet used.)
   4283 
   4284 
   4285   **Details:**
   4286 
   4287   .. ts:def:: PurseCreate
   4288 
   4289     interface PurseCreate {
   4290 
   4291       // Total value of the purse, excluding fees.
   4292       amount: Amount;
   4293 
   4294       // Minimum age required for all coins deposited into the purse.
   4295       min_age: Integer;
   4296 
   4297       // Optional encrypted contract, in case the buyer is
   4298       // proposing the contract and thus establishing the
   4299       // purse with the payment.
   4300       econtract?: EncryptedContract;
   4301 
   4302       // EdDSA public key used to approve merges of this purse.
   4303       merge_pub: EddsaPublicKey;
   4304 
   4305       // EdDSA signature of the purse over a
   4306       // `TALER_PurseRequestSignaturePS`
   4307       // of purpose ``TALER_SIGNATURE_WALLET_PURSE_CREATE``
   4308       // confirming the key
   4309       // invariants associated with the purse.
   4310       // (amount, h_contract_terms, expiration).
   4311       purse_sig: EddsaSignature;
   4312 
   4313       // SHA-512 hash of the contact of the purse.
   4314       h_contract_terms: HashCode;
   4315 
   4316       // Array of coins being deposited into the purse.
   4317       // Maximum length is 128.
   4318       deposits: PurseDeposit[];
   4319 
   4320       // Indicative time by which the purse should expire
   4321       // if it has not been merged into an account. At this
   4322       // point, all of the deposits made will be auto-refunded.
   4323       purse_expiration: Timestamp;
   4324 
   4325     }
   4326 
   4327   .. ts:def:: EncryptedContract
   4328 
   4329     interface EncryptedContract {
   4330 
   4331       // Encrypted contract.
   4332       econtract: string;
   4333 
   4334       // Signature over the (encrypted) contract.
   4335       econtract_sig: EddsaSignature;
   4336 
   4337       // Ephemeral public key for the DH operation to decrypt the encrypted contract.
   4338       contract_pub: EddsaPublicKey;
   4339 
   4340     }
   4341 
   4342   .. ts:def:: PurseCreateSuccessResponse
   4343 
   4344      interface PurseCreateSuccessResponse {
   4345 
   4346       // Total amount deposited into the purse so far (without fees).
   4347       total_deposited: Amount;
   4348 
   4349       // Time at the exchange.
   4350       exchange_timestamp: Timestamp;
   4351 
   4352       // EdDSA signature of the exchange affirming the payment,
   4353       // of purpose ``TALER_SIGNATURE_PURSE_DEPOSIT_CONFIRMED``
   4354       // over a `TALER_PurseDepositConfirmedSignaturePS`.
   4355       // Signs over the above and the purse public key and
   4356       // the hash of the contract terms.
   4357       exchange_sig: EddsaSignature;
   4358 
   4359       // public key used to create the signature.
   4360       exchange_pub: EddsaPublicKey;
   4361 
   4362     }
   4363 
   4364   .. ts:def:: PurseConflict
   4365 
   4366     // Union discriminated by the "code" field.
   4367     type PurseConflict =
   4368     | DepositDoubleSpendError
   4369     | PurseCreateConflict
   4370     | PurseDepositConflict
   4371     | PurseContractConflict;
   4372 
   4373   .. ts:def:: PurseCreateConflict
   4374 
   4375     interface PurseCreateConflict {
   4376       // Must be equal to TALER_EC_EXCHANGE_PURSE_CREATE_CONFLICTING_META_DATA
   4377       code: Integer;
   4378 
   4379       // Total amount to be merged into the reserve.
   4380       // (excludes fees).
   4381       amount: Amount;
   4382 
   4383       // Minimum age required for all coins deposited into the purse.
   4384       min_age: Integer;
   4385 
   4386       // Indicative time by which the purse should expire
   4387       // if it has not been merged into an account. At this
   4388       // point, all of the deposits made should be
   4389       // auto-refunded.
   4390       purse_expiration: Timestamp;
   4391 
   4392       // EdDSA signature of the purse over
   4393       // `TALER_PurseMergeSignaturePS` of
   4394       // purpose ``TALER_SIGNATURE_WALLET_PURSE_MERGE``
   4395       // confirming that the
   4396       // above details hold for this purse.
   4397       purse_sig: EddsaSignature;
   4398 
   4399       // SHA-512 hash of the contact of the purse.
   4400       h_contract_terms: HashCode;
   4401 
   4402       // EdDSA public key used to approve merges of this purse.
   4403       merge_pub: EddsaPublicKey;
   4404     }
   4405 
   4406   .. ts:def:: PurseDepositConflict
   4407 
   4408     interface PurseDepositConflict {
   4409       // Must be equal to TALER_EC_EXCHANGE_PURSE_DEPOSIT_CONFLICTING_META_DATA
   4410       code: Integer;
   4411 
   4412       // Public key of the coin being deposited into the purse.
   4413       coin_pub: EddsaPublicKey;
   4414 
   4415       // Signature over `TALER_PurseDepositSignaturePS`
   4416       // of purpose ``TALER_SIGNATURE_WALLET_PURSE_DEPOSIT``
   4417       // made by the customer with the
   4418       // `coin's private key <coin-priv>`.
   4419       coin_sig: EddsaSignature;
   4420 
   4421       // Target exchange URL for the purse. Not present for the
   4422       // same exchange.
   4423       partner_url?: string;
   4424 
   4425       // Amount to be contributed to the purse by this coin.
   4426       amount: Amount;
   4427 
   4428     }
   4429 
   4430   .. ts:def:: PurseContractConflict
   4431 
   4432     interface PurseContractConflict {
   4433       // Must be equal to TALER_EC_EXCHANGE_PURSE_ECONTRACT_CONFLICTING_META_DATA
   4434       code: Integer;
   4435 
   4436       // Hash of the encrypted contract.
   4437       h_econtract: HashCode;
   4438 
   4439       // Signature over the contract.
   4440       econtract_sig: EddsaSignature;
   4441 
   4442       // Ephemeral public key for the DH operation to decrypt the contract.
   4443       contract_pub: EddsaPublicKey;
   4444 
   4445     }
   4446 
   4447 
   4448 .. http:delete:: /purses/$PURSE_PUB
   4449 
   4450   Delete a purse that is unmerged and not yet expired. Refunds any money that
   4451   is already in the purse.
   4452 
   4453   **Request:**
   4454 
   4455   The request body must be empty, as recommended for HTTP delete in general.
   4456 
   4457   To authorize the request, the header must contain the following HTTP header:
   4458 
   4459   *Taler-Purse-Signature*:
   4460     $PURSE_SIG`` where ``$PURSE_SIG`` is the Crockford base32-encoded EdDSA
   4461     signature of purpose TALER_SIGNATURE_WALLET_PURSE_DELETE.
   4462 
   4463   **Response:**
   4464 
   4465   :http:statuscode:`204 No Content`:
   4466     The operation succeeded, the exchange confirms that the purse
   4467     was deleted.
   4468   :http:statuscode:`403 Forbidden`:
   4469     The signature is invalid.
   4470     This response comes with a standard `ErrorDetail` response.
   4471   :http:statuscode:`404 Not Found`:
   4472     The purse is not known. Might have already been deleted previously.
   4473   :http:statuscode:`409 Conflict`:
   4474     It is too late to delete the purse, its fate (merge or expiration)
   4475     was already decided.
   4476 
   4477 
   4478 .. http:post:: /purses/$PURSE_PUB/merge
   4479 
   4480   Merge purse with account, adding the value of the purse into
   4481   the account.  Endpoint to be used by the receiver of a PUSH payment.
   4482 
   4483   **Request:**
   4484 
   4485   The request body must be a `MergeRequest` object.
   4486 
   4487   **Response:**
   4488 
   4489   :http:statuscode:`200 OK`:
   4490     The operation succeeded, the exchange confirms that the
   4491     funds were merged into the account.
   4492     The response will include a `MergeSuccess` object.
   4493   :http:statuscode:`402 Payment Required`:
   4494     The purse is not yet full and more money needs to be deposited
   4495     before the merge can be made.
   4496   :http:statuscode:`403 Forbidden`:
   4497     The signature of the merge request or the reserve was invalid.
   4498     This response comes with a standard `ErrorDetail` response.
   4499   :http:statuscode:`404 Not found`:
   4500     The merge operation failed as we could not find the purse
   4501     or the partner exchange.
   4502     This response comes with a standard `ErrorDetail` response.
   4503   :http:statuscode:`409 Conflict`:
   4504     The purse was already merged into a different reserve.
   4505     The response will include a `MergeConflict` object.
   4506   :http:statuscode:`410 Gone`:
   4507     The purse has already expired and thus can no longer be merged.
   4508     This response comes with a standard `ErrorDetail` response.
   4509   :http:statuscode:`451 Unavailable For Legal Reasons`:
   4510     This account has not yet passed the KYC checks.
   4511     The client must pass KYC checks before proceeding with the merge.
   4512     The response will be an `LegitimizationNeededResponse` object.
   4513 
   4514   **Details:**
   4515 
   4516   .. ts:def:: MergeRequest
   4517 
   4518     interface MergeRequest {
   4519 
   4520       // Normalized payto URI of the account the purse is to be merged into.
   4521       // Must be of the form: 'payto://taler/$EXCHANGE_URL/$RESERVE_PUB'.
   4522       payto_uri: string;
   4523 
   4524       // EdDSA signature of the account/reserve affirming the merge
   4525       // over a `TALER_AccountMergeSignaturePS`.
   4526       // Must be of purpose ``TALER_SIGNATURE_ACCOUNT_MERGE``
   4527       reserve_sig: EddsaSignature;
   4528 
   4529       // EdDSA signature of the merge private key affirming the merge
   4530       // over a `TALER_PurseMergeSignaturePS`.
   4531       // Must be of purpose ``TALER_SIGNATURE_PURSE_MERGE``.
   4532       merge_sig: EddsaSignature;
   4533 
   4534       // Client-side timestamp of when the merge request was made.
   4535       merge_timestamp: Timestamp;
   4536 
   4537     }
   4538 
   4539   .. ts:def:: MergeSuccess
   4540 
   4541      interface MergeSuccess {
   4542 
   4543       // Amount merged (excluding deposit fees).
   4544       merge_amount: Amount;
   4545 
   4546       // Time at which the merge came into effect.
   4547       // Maximum of the "payment_timestamp" and the
   4548       // "merge_timestamp".
   4549       exchange_timestamp: Timestamp;
   4550 
   4551       // EdDSA signature of the exchange affirming the merge of
   4552       // purpose ``TALER_SIGNATURE_PURSE_MERGE_SUCCESS``
   4553       // over `TALER_PurseMergeSuccessSignaturePS`.
   4554       // Signs over the above and the account public key.
   4555       exchange_sig: EddsaSignature;
   4556 
   4557       // public key used to create the signature.
   4558       exchange_pub: EddsaPublicKey;
   4559 
   4560     }
   4561 
   4562   .. ts:def:: MergeConflict
   4563 
   4564     interface MergeConflict {
   4565 
   4566       // Client-side timestamp of when the merge request was made.
   4567       merge_timestamp: Timestamp;
   4568 
   4569       // EdDSA signature of the purse private key affirming the merge
   4570       // over a `TALER_PurseMergeSignaturePS`.
   4571       // Must be of purpose ``TALER_SIGNATURE_PURSE_MERGE``.
   4572       merge_sig: EddsaSignature;
   4573 
   4574       // Base URL of the exchange receiving the payment, only present
   4575       // if the exchange hosting the reserve is not this exchange.
   4576       partner_url?: string;
   4577 
   4578       // Public key of the reserve that the purse was merged into.
   4579       reserve_pub: EddsaPublicKey;
   4580     }
   4581 
   4582 
   4583 
   4584 .. http:post:: /reserves/$RESERVE_PUB/purse
   4585 
   4586   Create purse for an account.  First step of a PULL payment.
   4587 
   4588   **Request:**
   4589 
   4590   The request body must be a `ReservePurseRequest` object.
   4591 
   4592   **Response:**
   4593 
   4594   :http:statuscode:`200 OK`:
   4595     The operation succeeded, the exchange confirms that the
   4596     purse was allocated.
   4597     The response will include a `PurseCreateSuccessResponse` object.
   4598   :http:statuscode:`402 Payment Required`:
   4599     The account needs to contain more funding to create more purses.
   4600     This response comes with a standard `ErrorDetail` response.
   4601   :http:statuscode:`403 Forbidden`:
   4602     Account or contract signature is invalid.
   4603     This response comes with a standard `ErrorDetail` response.
   4604   :http:statuscode:`404 Not found`:
   4605     The purse creation operation failed as we could not find the reserve.
   4606     This response comes with a standard `ErrorDetail` response.
   4607   :http:statuscode:`409 Conflict`:
   4608     The purse creation failed because a purse with
   4609     the same public key but different meta data was
   4610     created previously.  Which specific conflict it is
   4611     can be decided by looking at the error code
   4612     (``TALER_EC_EXCHANGE_PURSE_CREATE_CONFLICTING_META_DATA`` or
   4613     ``TALER_EC_EXCHANGE_PURSE_DEPOSIT_CONFLICTING_META_DATA`` or
   4614     ``TALER_EC_EXCHANGE_PURSE_ECONTRACT_CONFLICTING_META_DATA``).
   4615     The specific fields of the response depend on the error code
   4616     and include the signatures (and what was signed over) proving the
   4617     conflict.
   4618     The response will be a `PurseConflict` response
   4619     (but not a `DepositDoubleSpendError`).
   4620   :http:statuscode:`451 Unavailable For Legal Reasons`:
   4621     This account has not yet passed the KYC checks.
   4622     The client must pass KYC checks before proceeding with the merge.
   4623     The response will be an `LegitimizationNeededResponse` object.
   4624 
   4625   **Details:**
   4626 
   4627   .. ts:def:: ReservePurseRequest
   4628 
   4629     interface ReservePurseRequest {
   4630 
   4631       // Minimum amount that must be credited to the reserve, that is
   4632       // the total value of the purse minus the deposit fees.
   4633       // If the deposit fees are lower, the contribution to the
   4634       // reserve can be higher!
   4635       purse_value: Amount;
   4636 
   4637       // Minimum age required for all coins deposited into the purse.
   4638       min_age: Integer;
   4639 
   4640       // Purse fee the reserve owner is willing to pay
   4641       // for the purse creation. Optional, if not present
   4642       // the purse is to be created from the purse quota
   4643       // of the reserve.
   4644       purse_fee: Amount;
   4645 
   4646       // Optional encrypted contract, in case the buyer is
   4647       // proposing the contract and thus establishing the
   4648       // purse with the payment.
   4649       econtract?: EncryptedContract;
   4650 
   4651       // EdDSA public key used to approve merges of this purse.
   4652       merge_pub: EddsaPublicKey;
   4653 
   4654       // EdDSA signature of the purse private key affirming the merge
   4655       // over a `TALER_PurseMergeSignaturePS`.
   4656       // Must be of purpose ``TALER_SIGNATURE_PURSE_MERGE``.
   4657       merge_sig: EddsaSignature;
   4658 
   4659       // EdDSA signature of the account/reserve affirming the merge.
   4660       // Must be of purpose ``TALER_SIGNATURE_WALLET_ACCOUNT_MERGE``
   4661       reserve_sig: EddsaSignature;
   4662 
   4663       // Purse public key.
   4664       purse_pub: EddsaPublicKey;
   4665 
   4666       // EdDSA signature of the purse over
   4667       // `TALER_PurseRequestSignaturePS` of
   4668       // purpose ``TALER_SIGNATURE_PURSE_REQUEST``
   4669       // confirming that the
   4670       // above details hold for this purse.
   4671       purse_sig: EddsaSignature;
   4672 
   4673       // SHA-512 hash of the contact of the purse.
   4674       h_contract_terms: HashCode;
   4675 
   4676       // Client-side timestamp of when the merge request was made.
   4677       merge_timestamp: Timestamp;
   4678 
   4679       // Indicative time by which the purse should expire
   4680       // if it has not been paid.
   4681       purse_expiration: Timestamp;
   4682 
   4683     }
   4684 
   4685 .. http:get:: /contracts/$CONTRACT_PUB
   4686 
   4687   Obtain P2P contract associated with the given contract public key.
   4688 
   4689   **Response:**
   4690 
   4691   :http:statuscode:`200 Ok`:
   4692     The contract is being returned using a `ExchangeContractResponse`.
   4693   :http:statuscode:`404 Not found`:
   4694     The contract is unknown.
   4695     This response comes with a standard `ErrorDetail` response.
   4696 
   4697   **Details:**
   4698 
   4699    .. ts:def:: ExchangeContractResponse
   4700 
   4701     interface ExchangeContractResponse {
   4702 
   4703       // Public key of the purse into which payments must be
   4704       // made for this contract.
   4705       purse_pub: PursePublicKey;
   4706 
   4707       // Signature over the contract
   4708       econtract_sig: PurseContractSignature;
   4709 
   4710       // Encrypted contract.
   4711       econtract: EncryptedContract;
   4712     }
   4713 
   4714 
   4715 .. http:post:: /purses/$PURSE_PUB/deposit
   4716 
   4717   Deposit money into a purse. Used by the buyer for a PULL payment.
   4718 
   4719   **Request:**
   4720 
   4721   The request body must be a `PurseDeposits` object.
   4722 
   4723   **Response:**
   4724 
   4725   :http:statuscode:`200 OK`:
   4726     The operation succeeded, the exchange confirms that all
   4727     coins were deposited into the purse.
   4728     The response will include a `PurseDepositSuccessResponse` object.
   4729   :http:statuscode:`403 Forbidden`:
   4730     A coin or denomination signature is invalid.
   4731     This response comes with a standard `ErrorDetail` response.
   4732   :http:statuscode:`404 Not found`:
   4733     The purse is unknown.
   4734     This response comes with a standard `ErrorDetail` response.
   4735   :http:statuscode:`409 Conflict`:
   4736     The deposit operation has either failed because a coin has insufficient
   4737     residual value, or because the same public key of the coin has been
   4738     previously used with a different denomination.  Which case it is
   4739     can be decided by looking at the error code
   4740     (``TALER_EC_EXCHANGE_GENERIC_INSUFFICIENT_FUNDS`` or
   4741     ``TALER_EC_EXCHANGE_GENERIC_COIN_CONFLICTING_DENOMINATION_KEY`` or
   4742     ``TALER_EC_EXCHANGE_PURSE_DEPOSIT_CONFLICTING_META_DATA``).
   4743     This response comes with a standard `PurseConflict` response
   4744     (alas some cases are impossible).
   4745   :http:statuscode:`410 Gone`:
   4746     The purse has expired.
   4747 
   4748 
   4749   **Details:**
   4750 
   4751    .. ts:def:: PurseDeposits
   4752 
   4753     interface PurseDeposits {
   4754 
   4755       // Array of coins to deposit into the purse.
   4756       deposits: PurseDeposit[];
   4757     }
   4758 
   4759   .. ts:def:: PurseDeposit
   4760 
   4761     interface PurseDeposit {
   4762 
   4763       // Amount to be deposited, can be a fraction of the
   4764       // coin's total value.
   4765       amount: Amount;
   4766 
   4767       // Hash of denomination RSA key with which the coin is signed.
   4768       denom_pub_hash: HashCode;
   4769 
   4770       // Exchange's unblinded RSA signature of the coin.
   4771       ub_sig: DenominationSignature;
   4772 
   4773       // Age commitment for the coin, if the denomination is age-restricted.
   4774       age_commitment?: AgeCommitment;
   4775 
   4776       // Attestation for the minimum age, if the denomination is age-restricted.
   4777       attest?: Attestation;
   4778 
   4779       // Signature over `TALER_PurseDepositSignaturePS`
   4780       // of purpose ``TALER_SIGNATURE_WALLET_PURSE_DEPOSIT``
   4781       // made by the customer with the
   4782       // `coin's private key <coin-priv>`.
   4783       coin_sig: EddsaSignature;
   4784 
   4785       // Public key of the coin being deposited into the purse.
   4786       coin_pub: EddsaPublicKey;
   4787 
   4788     }
   4789 
   4790   .. ts:def:: PurseDepositSuccessResponse
   4791 
   4792      interface PurseDepositSuccessResponse {
   4793 
   4794       // Total amount paid into the purse.
   4795       total_deposited: Amount;
   4796 
   4797       // Total amount expected in the purse.
   4798       purse_value_after_fees: Amount;
   4799 
   4800       // Time at which the deposit came into effect.
   4801       exchange_timestamp: Timestamp;
   4802 
   4803       // Indicative time by which the purse should expire
   4804       // if it has not been merged into an account. At this
   4805       // point, all of the deposits made will be auto-refunded.
   4806       purse_expiration: Timestamp;
   4807 
   4808       // SHA-512 hash of the contact of the purse.
   4809       h_contract_terms: HashCode;
   4810 
   4811       // EdDSA signature of the exchange affirming the payment,
   4812       // of purpose ``TALER_SIGNATURE_PURSE_DEPOSIT_CONFIRMED``
   4813       // over a `TALER_PurseDepositConfirmedSignaturePS`.
   4814       // Signs over the above and the purse public key and
   4815       // the hash of the contract terms.
   4816       exchange_sig: EddsaSignature;
   4817 
   4818       // public key used to create the signature.
   4819       exchange_pub: EddsaPublicKey;
   4820 
   4821     }
   4822 
   4823   .. ts:def:: AgeCommitment
   4824 
   4825      // AgeCommitment is an array of public keys, one for each age group of the
   4826      // age-restricted denomination.
   4827      type AgeCommitment = Edx25519PublicKey[];
   4828 
   4829   .. ts:def:: Attestation
   4830 
   4831      // An attestation for a minimum age is an Edx25519 signature of the age
   4832      // with purpose ``TALER_SIGNATURE_WALLET_AGE_ATTESTATION``.
   4833      type Attestation = string;
   4834 
   4835 .. _exchange_wads:
   4836 
   4837 
   4838 ----
   4839 Wads
   4840 ----
   4841 
   4842   .. note::
   4843 
   4844      This is a draft API that is not yet implemented.
   4845 
   4846 
   4847 These endpoints are used to manage exchange-to-exchange payments in support of
   4848 wallet-to-wallet payments.  Only another exchange should access this endpoint.
   4849 
   4850 
   4851 .. http:get:: /wads/$WAD_ID
   4852 
   4853   Obtain information about a wad.
   4854 
   4855   **Request:**
   4856 
   4857   **Response:**
   4858 
   4859   :http:statuscode:`200 OK`:
   4860     The operation succeeded, the exchange provides details
   4861     about the wad.
   4862     The response will include a `WadDetails` object.
   4863   :http:statuscode:`404 Not found`:
   4864     The wad is unknown to the exchange.
   4865 
   4866   **Details:**
   4867 
   4868   .. ts:def:: WadDetails
   4869 
   4870      interface WadDetails {
   4871 
   4872       // Total transfer amount claimed by the exchange.
   4873       total: Amount;
   4874 
   4875       // Indicative time by which the wad was given to the
   4876       // bank to execute the wire transfer.
   4877       wad_execution_time: Timestamp;
   4878 
   4879       // Transfers aggregated in the wad.
   4880       items: WadItem[];
   4881 
   4882       // EdDSA signature of the exchange affirming the wad
   4883       // data is correct, must be over `TALER_WadDataSignaturePS`
   4884       // and of purpose ``TALER_SIGNATURE_WAD_DATA``.
   4885       exchange_sig: EddsaSignature;
   4886 
   4887       // public key used to create the signature.
   4888       exchange_pub: EddsaPublicKey;
   4889      }
   4890 
   4891   Objects in the wad item list have the following format:
   4892 
   4893   .. ts:def:: WadItem
   4894 
   4895     interface WadItem {
   4896 
   4897       // Amount in the purse.
   4898       amount: Amount;
   4899 
   4900       // Normalized payto URI of the account the purse is to be merged into.
   4901       // Must be of the form: 'payto://taler/EXCHANGE_URL/RESERVE_PUB'.
   4902       payto_uri: string;
   4903 
   4904       // Purse public key.
   4905       purse_pub: EddsaPublicKey;
   4906 
   4907       // Hash of the contract.
   4908       h_contract: HashCode;
   4909 
   4910       // Indicative time by which the purse should expire
   4911       // if it has not been paid.
   4912       purse_expiration: Timestamp;
   4913 
   4914       // Client-side timestamp of when the merge request was made.
   4915       merge_timestamp: Timestamp;
   4916 
   4917       // Signature created with the reserve's private key.
   4918       // Must be of purpose ``TALER_SIGNATURE_ACCOUNT_MERGE``
   4919       // and over `TALER_AccountMergeSignaturePS`.
   4920       reserve_sig: EddsaSignature;
   4921 
   4922       // Signature created with the purse's private key.
   4923       // Must be of purpose ``TALER_SIGNATURE_PURSE_MERGE``
   4924       // and over `TALER_PurseMergeSignaturePS`.
   4925       purse_sig: EddsaSignature;
   4926 
   4927       // Deposit fees that were charged to the purse.
   4928       deposit_fees: Amount;
   4929 
   4930       // Wad fees that was charged to the purse.
   4931       wad_fees: Amount;
   4932     }
   4933 
   4934 
   4935 ------------------
   4936 KYC status updates
   4937 ------------------
   4938 
   4939 This section describes endpoints used to set up, complete and
   4940 inquire about KYC operations performed by an exchange for
   4941 regulatory compliance.
   4942 
   4943 .. http:post:: /kyc-wallet
   4944 
   4945   The ``/kyc-wallet`` POST endpoint allows a wallet to notify an exchange if
   4946   it will cross a balance threshold.  Here, the ``balance`` specified should be
   4947   the threshold (from the ``wallet_balance_limit_without_kyc`` array) that the
   4948   wallet would cross, and *not* the *exact* balance of the wallet.  The exchange
   4949   will respond with a wire target UUID. The wallet can then use this UUID to
   4950   being the KYC process at ``/kyc-check/``. The wallet must only proceed to
   4951   obtain funds exceeding the threshold after the KYC process has concluded.
   4952   While wallets could be "hacked" to bypass this measure (we cannot
   4953   cryptographically enforce this), such modifications are a terms of service
   4954   violation which may have legal consequences for the user.
   4955 
   4956   Setup KYC identification for a wallet.  Returns the KYC UUID.
   4957   This endpoint is used by compliant Taler wallets when they
   4958   are about to hit the balance threshold and thus need to have
   4959   the customer provide their personal details to the exchange.
   4960   The wallet is identified by its long-lived reserve public key
   4961   (which is used for P2P payments, not for withdrawals).
   4962 
   4963   **Request:**
   4964 
   4965   The request body must be a `WalletKycRequest` object.
   4966 
   4967   **Response:**
   4968 
   4969   :http:statuscode:`200 Ok`:
   4970     The balance
   4971     is below the threshold that requires KYC, or this
   4972     wallet already satisfied the KYC check for the
   4973     given balance. The `WalletKycCheckResponse` body
   4974     give details about the next applicable KYC check
   4975     requirements.
   4976   :http:statuscode:`204 No Content`:
   4977     KYC is disabled at this exchange.
   4978   :http:statuscode:`403 Forbidden`:
   4979     The provided signature is invalid.
   4980     This response comes with a standard `ErrorDetail` response.
   4981   :http:statuscode:`451 Unavailable for Legal Reasons`:
   4982     The wallet must undergo a KYC check. A KYC ID was created.
   4983     The response will be a `LegitimizationNeededResponse` object.
   4984 
   4985   **Details:**
   4986 
   4987   .. ts:def:: WalletKycRequest
   4988 
   4989      interface WalletKycRequest {
   4990 
   4991       // Balance threshold (not necessarily exact balance)
   4992       // to be crossed by the wallet that (may) trigger
   4993       // additional KYC requirements.
   4994       balance: Amount;
   4995 
   4996       // EdDSA signature of the wallet affirming the
   4997       // request, must be of purpose
   4998       // ``TALER_SIGNATURE_WALLET_ACCOUNT_SETUP``
   4999       reserve_sig: EddsaSignature;
   5000 
   5001       // long-term wallet reserve-account
   5002       // public key used to create the signature.
   5003       reserve_pub: EddsaPublicKey;
   5004     }
   5005 
   5006   .. ts:def:: WalletKycCheckResponse
   5007 
   5008      interface WalletKycCheckResponse {
   5009 
   5010        // Next balance limit above which a KYC check
   5011        // may be required. Optional, not given if no
   5012        // threshold exists (assume infinity).
   5013        next_threshold?: Amount;
   5014 
   5015        // When does the current set of AML/KYC rules
   5016        // expire and the wallet needs to check again
   5017        // for updated thresholds.
   5018        expiration_time: Timestamp;
   5019 
   5020      }
   5021 
   5022 
   5023 .. http:get:: /kyc-check/$H_NORMALIZED_PAYTO
   5024 
   5025   Checks the KYC status of a particular payment target.  That information
   5026   allows the customer to choose the next KYC measure to satisfy, if any.
   5027   This endpoint is typically used by wallets or merchants that
   5028   have been told that a transaction is not happening because it triggered
   5029   some KYC/AML measure and now want to check how the KYC/AML
   5030   requirement could be fulfilled (or whether it already has been
   5031   statisfied and the operation can now proceed).  Long-polling may be used
   5032   to instantly observe a change in the KYC requirement status.
   5033 
   5034   Given a valid pair of a normalized payto hash and account owner signature, the
   5035   ``/kyc-check/`` endpoint returns either just the KYC status or redirects the
   5036   client (202) to the next required stage of the KYC process.  The redirection
   5037   must be for an HTTP(S) endpoint to be triggered via a simple HTTP GET.  It
   5038   must always be the same endpoint for the same client, as the wallet/merchant
   5039   backend are not required to check for changes to this endpoint.  Clients
   5040   that received a 202 status code may repeat the request and use long-polling
   5041   to detect a change of the HTTP status.
   5042 
   5043   This endpoint exists in this specific form only since protocol **v21**.
   5044 
   5045   **Request:**
   5046 
   5047   *Account-Owner-Signature*:
   5048     The client must provide Base-32 encoded EdDSA signature with
   5049     ``$ACCOUNT_PRIV``, affirming the desire to obtain KYC data.  Note that
   5050     this is merely a simple authentication mechanism, the details of the
   5051     request are not protected by the signature.  The ``$ACCOUNT_PRIV`` is
   5052     either the (wallet long-term) reserve private key or the merchant instance
   5053     private key.
   5054 
   5055   *Account-Owner-Pub*:
   5056     The client should provide the Base-32 encoded EdDSA public key of
   5057     ``$ACCOUNT_PUB``, enabling the exchange to easily locate the correct
   5058     public key used for the signature in case multiple wire transfers
   5059     were made to the account in the past.
   5060 
   5061   :query lpt=TARGET: *Optional*.
   5062     Specifies what status change we are long-polling for.
   5063     Use 1 to wait for the KYC auth transfer (access token available),
   5064     2 to wait for an AML investigation to be done,
   5065     and 3 to wait for the KYC status to be OK.
   5066     @since protocol **v21**.
   5067   :query min_rule=NUMBER: *Optional*.
   5068     Specifies the ``rule_num`` of the previous ``kyc-check``
   5069     already known to the client.  When long-polling, the server
   5070     should always respond when it has a more recent rule.
   5071     @since protocol **v26**.
   5072   :query timeout_ms=NUMBER: *Optional.*  If specified, the exchange will
   5073     wait up to ``timeout_ms`` milliseconds if the requirement continues
   5074     to be mandatory provisioning of KYC data by the client.
   5075     Ignored if the HTTP status code is already ``200 Ok``.  Note that
   5076     clients cannot long-poll for AML staff actions, so status information
   5077     about an account being under AML review needs to be requested
   5078     periodically.
   5079 
   5080   **Response:**
   5081 
   5082   :http:statuscode:`200 Ok`:
   5083     No mandatory KYC actions are required by the client at this time.
   5084     The client *may* still visit the KYC URL to initiate voluntary checks.
   5085     The response will be an `AccountKycStatus` object which specifies
   5086     restrictions that currently apply to the account. If the
   5087     client attempts to exceed *soft* limits, the status may change
   5088     to a ``202 Accepted``.  Hard limits cannot be lifted by passing KYC checks.
   5089   :http:statuscode:`202 Accepted`:
   5090     The account holder performed an operation that would have crossed
   5091     limits (hard or soft) and must be redirected to the provided location to perform
   5092     the required KYC checks to satisfy the legal requirements. Afterwards, the
   5093     ``/kyc-check/`` request should be repeated to check whether the
   5094     user has completed the process.
   5095     The response will be an `AccountKycStatus` object.
   5096   :http:statuscode:`204 No content`:
   5097     The exchange is not configured to perform KYC and thus
   5098     the legal requirements are already satisfied.
   5099   :http:statuscode:`403 Forbidden`:
   5100     The provided signature is not acceptable for the given account.  The response will be an `KycCheckAccountExpectedResponse` object which specifies the expected account public key.
   5101   :http:statuscode:`404 Not found`:
   5102     The account identified by the normalized payto hash is unknown.
   5103   :http:statuscode:`409 Conflict`:
   5104     The bank account is not (yet) associated with a public key. The account owner must do a wire transfer to the exchange with the account public key in the wire transfer subject to enable authentication.
   5105 
   5106   **Details:**
   5107 
   5108   .. ts:def:: KycCheckAccountExpectedResponse
   5109 
   5110     interface KycCheckAccountExpectedResponse {
   5111 
   5112       // Public key for which the signature must be
   5113       // valid to authorize this request.
   5114       expected_account_pub: EddsaPublicKey;
   5115     }
   5116 
   5117   .. ts:def:: AccountKycStatus
   5118 
   5119     interface AccountKycStatus {
   5120 
   5121       // Current AML state for the target account.  True if
   5122       // operations are not happening due to staff processing
   5123       // paperwork *or* due to legal requirements (so the
   5124       // client cannot do anything but wait).
   5125       //
   5126       // Note that not every AML staff action may be legally
   5127       // exposed to the client, so this is merely a hint that
   5128       // a client should be told that AML staff is currently
   5129       // reviewing the account.  AML staff *may* review
   5130       // accounts without this flag being set!
   5131       aml_review: boolean;
   5132 
   5133       // Monotonically increasing number identifying the decision.
   5134       // 0 if no decision was taken for this account. Useful for
   5135       // long-polling via ``min_rule`` to long-poll for any change
   5136       // to the rules or limits.
   5137       rule_gen: Integer;
   5138 
   5139       // Access token needed to construct the ``/kyc-spa/``
   5140       // URL that the user should open in a browser to
   5141       // proceed with the KYC process (optional if the status
   5142       // type is ``200 Ok``, mandatory if the HTTP status
   5143       // is ``202 Accepted``).
   5144       access_token: AccountAccessToken;
   5145 
   5146       // Array with limitations that currently apply to this
   5147       // account and that may be increased or lifted if the
   5148       // KYC check is passed.
   5149       // Note that additional limits *may* exist and not be
   5150       // communicated to the client. If such limits are
   5151       // reached, this *may* be indicated by the account
   5152       // going into ``aml_review`` state. However, it is
   5153       // also possible that the exchange may legally have
   5154       // to deny operations without being allowed to provide
   5155       // any justification.
   5156       // The limits should be used by the client to
   5157       // possibly structure their operations (e.g. withdraw
   5158       // what is possible below the limit, ask the user to
   5159       // pass KYC checks or withdraw the rest after the time
   5160       // limit is passed, warn the user to not withdraw too
   5161       // much or even prevent the user from generating a
   5162       // request that would cause it to exceed hard limits).
   5163       limits?: AccountLimit[];
   5164 
   5165     }
   5166 
   5167 .. http:get:: /kyc-spa/$ACCESS_TOKEN
   5168 .. http:get:: /kyc-spa/$FILENAME
   5169 
   5170   A set of ``/kyc-spa/$ACCESS_TOKEN`` GET endpoints is created per account
   5171   hash that serves the KYC SPA.  This is where the ``/kyc-check/`` endpoint
   5172   will in principle redirect clients.  The KYC SPA will use the
   5173   ``$ACCESS_TOKEN`` of its URL to initialize itself via the
   5174   ``/kyc-info/$ACCESS_TOKEN`` endpoint family.  The KYC SPA may download
   5175   additional resources via ``/kyc-spa/$FILENAME``. The filenames must not
   5176   match base32-encoded 256-bit values.
   5177 
   5178   This endpoint was introduced in protocol **v20**.
   5179 
   5180 
   5181 .. http:get:: /kyc-info/$ACCESS_TOKEN
   5182 
   5183   The ``/kyc-info/$ACCESS_TOKEN`` endpoints are created per client
   5184   account hash (but access controlled via a unique target token)
   5185   to return information about the state of the KYC or AML process
   5186   to the KYC SPA.  The SPA uses this information to show the user an
   5187   appropriate dialog. The SPA should also long-poll this endpoint for changes
   5188   to the AML/KYC state. Note that this is a client-facing endpoint, so it will
   5189   only provide a restricted amount of information to the customer (as some
   5190   laws may forbid us to inform particular customers about their true status).
   5191   The endpoint will typically inform the SPA about possible choices to
   5192   proceed, such as directly uploading files, contacting AML staff, or
   5193   proceeding with a particular KYC process at an external provider (such as
   5194   Challenger).  If the user chooses to initate a KYC process at an external
   5195   provider, the SPA must request the respective process to be set-up by the
   5196   exchange via the ``/kyc-start/`` endpoint.
   5197 
   5198   This endpoint was introduced in protocol **v20**.
   5199 
   5200   **Request:**
   5201 
   5202   *If-None-Match*:
   5203     The client MAY provide an ``If-None-Match`` header with an ETag.
   5204 
   5205   :query timeout_ms=MILLISECONDS:
   5206     *Optional.* If specified, the exchange will wait up to MILLISECONDS for
   5207     a change to a more recent legitimization measure before returning a 304
   5208     Not Modified status.
   5209 
   5210   **Response:**
   5211 
   5212   *Etag*: Will be set to the serial ID of the measure. Used for long-polling (only for 200 OK responses).
   5213 
   5214   :http:statuscode:`200 OK`:
   5215     The body is a `KycProcessClientInformation`.
   5216   :http:statuscode:`202 Accepted`:
   5217     The exchange is currently processing the KYC status. The request should be
   5218     repeated later again.
   5219   :http:statuscode:`204 No Content`:
   5220     There are no open KYC requirements or possible voluntary checks
   5221     the client might perform.
   5222   :http:statuscode:`304 Not Modified`:
   5223     The KYC requirements did not change.
   5224 
   5225 
   5226   **Details:**
   5227 
   5228   .. ts:def:: KycProcessClientInformation
   5229 
   5230     interface KycProcessClientInformation {
   5231 
   5232       // Array of requirements.
   5233       requirements: KycRequirementInformation[];
   5234 
   5235       // True if the client is expected to eventually satisfy all requirements.
   5236       // Default (if missing) is false.
   5237       is_and_combinator?: boolean
   5238 
   5239       // List of available voluntary checks the client could undertake.
   5240       // @since protocol **vATTEST**.
   5241       voluntary_measures?: KycRequirementInformation[];
   5242     }
   5243 
   5244   .. ts:def:: KycRequirementInformation
   5245 
   5246     interface KycRequirementInformation {
   5247 
   5248       // Which form should be used? Common values include "INFO"
   5249       // (to just show the descriptions but allow no action),
   5250       // "LINK" (to enable the user to obtain a link via
   5251       // ``/kyc-start/``) or any build-in form name supported
   5252       // by the SPA.
   5253       form: string;
   5254 
   5255       // Object with arbitrary additional context, completely depends on
   5256       // the specific form.
   5257       context?: Object;
   5258 
   5259       // English description of the requirement.
   5260       description: string;
   5261 
   5262       // Map from IETF BCP 47 language tags to localized
   5263       // description texts.
   5264       description_i18n ?: { [lang_tag: string]: string };
   5265 
   5266       // ID of the requirement, useful to construct the
   5267       // ``/kyc-upload/$ID`` or ``/kyc-start/$ID`` endpoint URLs.
   5268       // Present if and only if "form" is not "INFO".  The
   5269       // ``$ID`` value may itself contain ``/`` or ``?`` and
   5270       // basically encode any URL path (and optional arguments).
   5271       id?: string;
   5272 
   5273     }
   5274 
   5275 .. http:post:: /kyc-upload/$ID
   5276 
   5277   The ``/kyc-upload/$ID`` POST endpoint allows the SPA to upload
   5278   client-provided evidence.  The ``$ID`` will be provided as part of the
   5279   ``/kyc-info`` body.  This is for checks of type ``FORM``.  In practice,
   5280   ``$ID`` will encode the ``$ACCESS_TOKEN``, legitimization measure serial ID
   5281   (to disambiguate) and the index of the selected measure (but these details
   5282   should be irrelevant for the client).
   5283 
   5284   This endpoint was introduced in protocol **v20**.
   5285 
   5286   **Request:**
   5287 
   5288   JSON body with data depending on the form being submitted.
   5289   Details will thus completely depend on the form, but it
   5290   MUST include a form ID and be generally of type
   5291   `CustomerKycAttributes`.
   5292 
   5293   **Response:**
   5294 
   5295   :http:statuscode:`204 No Content`:
   5296     The information was successfully uploaded. The SPA should fetch
   5297     an updated ``/kyc-info/``.
   5298   :http:statuscode:`404 Not Found`:
   5299     The ``$ID`` is unknown to the exchange.
   5300   :http:statuscode:`409 Conflict`:
   5301     The upload conflicts with a previous upload.
   5302   :http:statuscode:`413 Request Entity Too Large`:
   5303     The body is too large.
   5304 
   5305 .. http:post:: /kyc-start/$ID
   5306 
   5307   The ``/kyc-start/$ID`` POST endpoint allows the SPA to set up a new external
   5308   KYC process. It will return the URL that the client must GET to begin the
   5309   KYC process. The SPA should probably open this URL in a new window or tab.
   5310   The ``$ID`` will be provided as part of the ``/kyc-info`` body.  In
   5311   practice, ``$ID`` will encode the ``$ACCESS_TOKEN``, legitimization measure
   5312   serial ID (to disambiguate) and the index of the selected measure (but these
   5313   details should be irrelevant for the client).
   5314 
   5315   **Request:**
   5316 
   5317   Use empty JSON body for now.
   5318 
   5319   **Response:**
   5320 
   5321   :http:statuscode:`200 Ok`:
   5322     The KYC process was successfully initiated. The URL is in a
   5323     `KycProcessStartInformation` object.
   5324   :http:statuscode:`404 Not Found`:
   5325     The ``$ID`` is unknown to the exchange.
   5326 
   5327   **Details:**
   5328 
   5329   .. ts:def:: KycProcessStartInformation
   5330 
   5331     interface KycProcessStartInformation {
   5332 
   5333       // URL to open.
   5334       redirect_url: string;
   5335     }
   5336 
   5337   .. note::
   5338 
   5339     As this endpoint is involved in every KYC check at the beginning, this
   5340     is also the place where we could integrate the payment process for the KYC fee
   5341     in the future (since protocol **vATTEST**).
   5342 
   5343 .. http:get:: /kyc-proof/$PROVIDER_NAME?state=$H_NORMALIZED_PAYTO
   5344 
   5345   Upon completion of the process at the external KYC provider, the provider
   5346   must redirect the client (browser) to trigger a GET request to a new
   5347   ``/kyc-proof/$H_NORMALIZED_PAYTO/$PROVIDER_NAME`` endpoint.  Once this endpoint is
   5348   triggered, the exchange will pass the received arguments to the respective
   5349   logic plugin.  The logic plugin will then (asynchronously) update the KYC
   5350   status of the user.  The logic plugin should redirect the user to the KYC
   5351   SPA. This endpoint deliberately does not use the ``$ACCESS_TOKEN`` as the
   5352   external KYC provider should not learn that token.
   5353 
   5354   This endpoint is thus accessed from the user's browser at the *end* of a
   5355   KYC process, possibly providing the exchange with additional
   5356   credentials to obtain the results of the KYC process.
   5357   Specifically, the URL arguments should provide
   5358   information to the exchange that allows it to verify that the
   5359   user has completed the KYC process. The details depend on
   5360   the logic, which is selected by the "$PROVIDER_NAME".
   5361 
   5362   While this is a GET (and thus safe, and idempotent), the operation
   5363   may actually trigger significant changes in the exchange's state.
   5364   In particular, it may update the KYC status of a particular
   5365   payment target.
   5366 
   5367   **Request:**
   5368 
   5369   Details on the request depend on the specific KYC logic
   5370   that was used.
   5371 
   5372   If the KYC plugin logic is OAuth 2.0, the query parameters are:
   5373 
   5374   :query code=CODE:
   5375      OAuth 2.0 code argument.
   5376   :query state=STATE:
   5377      OAuth 2.0 state argument with the H_NORMALIZED_PAYTO.
   5378 
   5379   .. note::
   5380 
   5381     Depending on the OAuth variant used, additional
   5382     query parameters may need to be passed here.
   5383 
   5384   **Response:**
   5385 
   5386   Given that the response is returned to a user using a browser and **not** to
   5387   a Taler wallet, the response format is in human-readable HTML and not in
   5388   machine-readable JSON.
   5389 
   5390   :http:statuscode:`302 Found`:
   5391     The KYC operation succeeded and the
   5392     payment target is now authorized to transact.
   5393     The browser is redirected to a human-readable
   5394     page configured by the exchange operator.
   5395   :http:statuscode:`401 Unauthorized`:
   5396     The provided authorization token is invalid.
   5397   :http:statuscode:`404 Not found`:
   5398     The payment target is unknown.
   5399   :http:statuscode:`502 Bad Gateway`:
   5400     The exchange received an invalid reply from the
   5401     legitimization service.
   5402   :http:statuscode:`504 Gateway Timeout`:
   5403     The exchange did not receive a reply from the legitimization
   5404     service within a reasonable time period.
   5405 
   5406 
   5407 .. http:get:: /kyc-webhook/$PROVIDER_NAME/*
   5408 .. http:post:: /kyc-webhook/$PROVIDER_NAME/*
   5409 .. http:get:: /kyc-webhook/$LOGIC/*
   5410 .. http:post:: /kyc-webhook/$LOGIC/*
   5411 
   5412   All of the above endpoints can be used to update KYC status of a particular
   5413   payment target. They provide information to the KYC logic of the exchange
   5414   that allows it to verify that the user has completed the KYC process.  May
   5415   be a GET or a POST request, depending on the specific "$LOGIC" and/or the
   5416   "$PROVIDER_NAME".
   5417 
   5418   **Request:**
   5419 
   5420   Details on the request depend on the specific KYC logic
   5421   that was used.
   5422 
   5423   **Response:**
   5424 
   5425   :http:statuscode:`204 No content`:
   5426     The operation succeeded.
   5427   :http:statuscode:`404 Not found`:
   5428     The specified logic is unknown.
   5429 
   5430 
   5431 --------------
   5432 AML operations
   5433 --------------
   5434 
   5435 This API is only for designated AML officers. It is used
   5436 to allow exchange staff to monitor suspicious transactions
   5437 and freeze or unfreeze accounts suspected of money laundering.
   5438 
   5439 
   5440 .. http:get:: /aml/$OFFICER_PUB/measures
   5441 
   5442   To enable the AML staff SPA to give AML staff a choice of possible measures, a
   5443   new endpoint ``/aml/$OFFICER_PUB/measures`` is added that allows the AML SPA
   5444   to dynamically GET the list of available measures.  It returns a list of known
   5445   KYC checks (by name) with their descriptions and a list of AML programs with
   5446   information about the required context.
   5447 
   5448   This endpoint was introduced in protocol **v20**.
   5449 
   5450   **Request:**
   5451 
   5452   *Taler-AML-Officer-Signature*:
   5453     The client must provide Base-32 encoded EdDSA signature with
   5454     ``$OFFICER_PRIV``, affirming the desire to obtain AML data.  Note that
   5455     this is merely a simple authentication mechanism, the details of the
   5456     request are not protected by the signature.
   5457 
   5458   **Response:**
   5459 
   5460   :http:statuscode:`200 Ok`:
   5461     Information about possible measures is returned in a
   5462     `AvailableMeasureSummary` object.
   5463 
   5464   **Details:**
   5465 
   5466   .. ts:def:: AvailableMeasureSummary
   5467 
   5468     interface AvailableMeasureSummary {
   5469 
   5470       // Available original measures that can be
   5471       // triggered directly by default rules.
   5472       roots: { "$measure_name" : MeasureInformation; };
   5473 
   5474       // Available AML programs.
   5475       programs: { "$prog_name" : AmlProgramRequirement; };
   5476 
   5477       // Available KYC checks.
   5478       checks: { "$check_name" : KycCheckInformation; };
   5479 
   5480       // Default KYC rules. This is the set of KYC rules that
   5481       // applies by default to new "accounts".  Note that some
   5482       // rules only apply to wallets, while others only apply to
   5483       // bank accounts. The returned array is the union of all
   5484       // possible rules, applications should consider the
   5485       // ``operation_type`` to filter for rules that actually
   5486       // apply to a specific situation.
   5487       // @since protocol **v28**.
   5488       default_rules: KycRule[];
   5489 
   5490     }
   5491 
   5492   .. ts:def:: MeasureInformation
   5493 
   5494     interface MeasureInformation {
   5495 
   5496       // Name of a KYC check.
   5497       check_name: string;
   5498 
   5499       // Name of an AML program.
   5500       // Optional @since protocol **v30**.
   5501       prog_name?: string;
   5502 
   5503       // Context for the check. Optional.
   5504       context?: Object;
   5505 
   5506       // Operation that this measure relates to.
   5507       // NULL if unknown. Useful as a hint to the
   5508       // user if there are many (voluntary) measures
   5509       // and some related to unlocking certain operations.
   5510       // (and due to zero-amount thresholds, no measure
   5511       // was actually specifically triggered).
   5512       //
   5513       // Must be one of "WITHDRAW", "DEPOSIT",
   5514       // (p2p) "MERGE", (wallet) "BALANCE",
   5515       // (reserve) "CLOSE", "AGGREGATE",
   5516       // "TRANSACTION" or "REFUND".
   5517       // @since protocol **v21**.
   5518       operation_type?: string;
   5519 
   5520       // Can this measure be undertaken voluntarily?
   5521       // Optional, default is false.
   5522       // @since protocol **vATTEST**.
   5523       voluntary?: boolean;
   5524 
   5525     }
   5526 
   5527   .. ts:def:: AmlProgramRequirement
   5528 
   5529     interface AmlProgramRequirement {
   5530 
   5531       // Description of what the AML program does.
   5532       description: string;
   5533 
   5534       // List of required field names in the context to run this
   5535       // AML program. SPA must check that the AML staff is providing
   5536       // adequate CONTEXT when defining a measure using this program.
   5537       context: string[];
   5538 
   5539       // List of required attribute names in the
   5540       // input of this AML program.  These attributes
   5541       // are the minimum that the check must produce
   5542       // (it may produce more).
   5543       inputs: string[];
   5544 
   5545     }
   5546 
   5547   .. ts:def:: KycCheckInformation
   5548 
   5549     interface KycCheckInformation {
   5550 
   5551       // Description of the KYC check.  Should be shown
   5552       // to the AML staff but will also be shown to the
   5553       // client when they initiate the check in the KYC SPA.
   5554       description: string;
   5555 
   5556       // Map from IETF BCP 47 language tags to localized
   5557       // description texts.
   5558       description_i18n ?: { [lang_tag: string]: string};
   5559 
   5560       // Names of the fields that the CONTEXT must provide
   5561       // as inputs to this check.
   5562       // SPA must check that the AML staff is providing
   5563       // adequate CONTEXT when defining a measure using
   5564       // this check.
   5565       requires: string[];
   5566 
   5567       // Names of the attributes the check will output.
   5568       // SPA must check that the outputs match the
   5569       // required inputs when combining a KYC check
   5570       // with an AML program into a measure.
   5571       outputs: string[];
   5572 
   5573       // Name of a root measure taken when this check fails.
   5574       fallback: string;
   5575     }
   5576 
   5577 .. http:get:: /aml/$OFFICER_PUB/kyc-statistics/$NAMES
   5578 
   5579   Returns the number of KYC events matching the space-separated (!)
   5580   list of given event types ``$NAMES`` in
   5581   the specified time range.  Note that this query can be slow as the
   5582   statistics are computed on-demand. (This is OK as such requests should be
   5583   rare.)
   5584 
   5585   This endpoint was introduced in protocol **v20**. It was
   5586   modified in **v30** revision 1 to accept a space-separated
   5587   list of names instead of a single name and to return an array
   5588   of results.
   5589 
   5590   **Request:**
   5591 
   5592   *Taler-AML-Officer-Signature*:
   5593     The client must provide Base-32 encoded EdDSA signature with
   5594     ``$OFFICER_PRIV``, affirming the desire to obtain AML data.  Note that this
   5595     is merely a simple authentication mechanism, the details of the request are
   5596     not protected by the signature.
   5597 
   5598   :query start_date=TIMESTAMP:
   5599     *Optional*. Specifies the date when to
   5600     start looking (inclusive). If not given, the start time of the
   5601     exchange operation is used.  The TIMESTAMP is given
   5602     in seconds since the UNIX epoch.
   5603   :query end_date=TIMESTAMP:
   5604     *Optional*. Specifies the date when to
   5605     stop looking (exclusive). If not given, the current date is used.  The TIMESTAMP is given
   5606     in seconds since the UNIX epoch.
   5607 
   5608   **Response:**
   5609 
   5610   :http:statuscode:`200 OK`:
   5611     The responds will be an `AmlStatisticsResponse` message.
   5612   :http:statuscode:`204 No content`:
   5613     All the event counters are zero.
   5614 
   5615   **Details:**
   5616 
   5617   .. ts:def:: AmlStatisticsResponse
   5618 
   5619     interface AmlStatisticsResponse {
   5620       // Statistics that were found.
   5621       statistics: EventCounter[];
   5622     }
   5623 
   5624 
   5625   .. ts:def:: EventCounter
   5626 
   5627     interface EventCounter {
   5628       // Name of the statistic that is being returned.
   5629       name: string;
   5630 
   5631       // Number of events of the specified type in
   5632       // the given range.
   5633       counter: Integer;
   5634 
   5635     }
   5636 
   5637 
   5638 .. http:get:: /aml/$OFFICER_PUB/decisions
   5639 
   5640   **Request:**
   5641 
   5642   *Taler-AML-Officer-Signature*:
   5643     The client must provide Base-32 encoded EdDSA signature with
   5644     ``$OFFICER_PRIV``, affirming the desire to obtain AML data.  Note that
   5645     this is merely a simple authentication mechanism, the details of the
   5646     request are not protected by the signature.
   5647 
   5648     This endpoint was introduced in this form in protocol **v20**.
   5649 
   5650   :query limit:
   5651     *Optional*. takes value of the form ``N (-N)``, so that at
   5652     most ``N`` values strictly older (younger) than ``start`` are returned.
   5653     Defaults to ``-20`` to return the last 20 entries (before ``start``).
   5654   :query offset:
   5655     *Optional*. Row number threshold, see ``delta`` for its
   5656     interpretation.  Defaults to ``INT64_MAX``, namely the biggest row id
   5657     possible in the database.
   5658   :query h_payto:
   5659     *Optional*. Account selector using the *normalized* payto URI.
   5660     All matching accounts are returned if this
   5661     filter is absent, otherwise only decisions for this account.
   5662   :query active:
   5663     *Optional*. If set to yes, only return active decisions, if no only
   5664     decisions that have been superseded. Do not give (or use "all") to
   5665     see all decisions regardless of activity status.
   5666   :query investigation:
   5667     *Optional*. If set to yes, only return accounts that are under
   5668     AML investigation, if no only accounts that are not under investigation.
   5669     Do not give (or use "all") to see all accounts regardless of
   5670     investigation status.
   5671 
   5672   **Response:**
   5673 
   5674   :http:statuscode:`200 OK`:
   5675     The response will be an `AmlDecisionsResponse` message.
   5676   :http:statuscode:`204 No content`:
   5677     There are no matching AML records.
   5678   :http:statuscode:`403 Forbidden`:
   5679     The signature is invalid.
   5680   :http:statuscode:`404 Not found`:
   5681     The designated AML account is not known.
   5682   :http:statuscode:`409 Conflict`:
   5683     The designated AML account is not enabled.
   5684 
   5685   **Details:**
   5686 
   5687   .. ts:def:: AmlDecisionsResponse
   5688 
   5689     interface AmlDecisionsResponse {
   5690 
   5691       // Array of AML decisions matching the query.
   5692       records: AmlDecision[];
   5693     }
   5694 
   5695   .. ts:def:: AmlDecision
   5696 
   5697     interface AmlDecision {
   5698 
   5699       // Which payto-address is this record about.
   5700       // Identifies a GNU Taler wallet or an affected bank account.
   5701       h_payto: NormalizedPaytoHash;
   5702 
   5703       // Full payto URL of the account that the decision is
   5704       // about. Since protocol **v30** (rev 1).
   5705       full_payto: string;
   5706 
   5707       // True if the underlying payto://-URI is for a wallet
   5708       // Since protocol **v25**.
   5709       is_wallet: boolean;
   5710 
   5711       // Row ID of the record.  Used to filter by offset.
   5712       rowid: Integer;
   5713 
   5714       // Justification for the decision. NULL if none
   5715       // is available.
   5716       justification?: string;
   5717 
   5718       // When was the decision made?
   5719       decision_time: Timestamp;
   5720 
   5721       // Free-form properties about the account.
   5722       // Can be used to store properties such as PEP,
   5723       // risk category, type of business, hits on
   5724       // sanctions lists, etc.
   5725       //
   5726       // Passing a properties object overrides all
   5727       // of the current properties for the AML account.
   5728       properties?: AccountProperties;
   5729 
   5730       // What are the new rules?
   5731       limits: LegitimizationRuleSet;
   5732 
   5733       // True if the account is under investigation by AML staff
   5734       // after this decision.
   5735       to_investigate: boolean;
   5736 
   5737       // True if this is the active decision for the
   5738       // account.
   5739       is_active: boolean;
   5740 
   5741     }
   5742 
   5743   .. ts:def:: AccountProperties
   5744 
   5745     // All fields in this object are optional. The actual
   5746     // properties collected depend fully on the discretion
   5747     // of the exchange operator;
   5748     // however, some common fields are standardized
   5749     // and thus described here.
   5750     interface AccountProperties {
   5751 
   5752       // True if this is a politically exposed account.
   5753       // Rules for classifying accounts as politically
   5754       // exposed are country-dependent.
   5755       pep?: boolean;
   5756 
   5757       // True if this is a sanctioned account.
   5758       // Rules for classifying accounts as sanctioned
   5759       // are country-dependent.
   5760       sanctioned?: boolean;
   5761 
   5762       // True if this is a high-risk account.
   5763       // Rules for classifying accounts as at-risk
   5764       // are exchange operator-dependent.
   5765       high_risk?: boolean;
   5766 
   5767       // Business domain of the account owner.
   5768       // The list of possible business domains is
   5769       // operator- or country-dependent.
   5770       business_domain?: string;
   5771 
   5772       // Is the client's account currently frozen?
   5773       is_frozen?: boolean;
   5774 
   5775       // Was the client's account reported to the authorities?
   5776       was_reported?: boolean;
   5777 
   5778     }
   5779 
   5780   .. ts:def:: LegitimizationRuleSet
   5781 
   5782     interface LegitimizationRuleSet {
   5783 
   5784       // When does this set of rules expire and
   5785       // we automatically transition to the successor
   5786       // measure?
   5787       expiration_time: Timestamp;
   5788 
   5789       // Name of the measure to apply when the expiration time is
   5790       // reached.  If not set, we refer to the default
   5791       // set of rules (and the default account state).
   5792       successor_measure?: string;
   5793 
   5794       // Legitimization rules that are to be applied
   5795       // to this account.
   5796       rules: KycRule[];
   5797 
   5798       // Custom measures that KYC rules and the
   5799       // ``successor_measure`` may refer to.
   5800       custom_measures: { "$measure_name" : MeasureInformation; };
   5801 
   5802     }
   5803 
   5804   .. ts:def:: KycRule
   5805 
   5806     interface KycRule {
   5807 
   5808       // Type of operation to which the rule applies.
   5809       //
   5810       // Must be one of "WITHDRAW", "DEPOSIT",
   5811       // (p2p) "MERGE", (wallet) "BALANCE",
   5812       // (reserve) "CLOSE", "AGGREGATE",
   5813       // "TRANSACTION" or "REFUND".
   5814       operation_type: string;
   5815 
   5816       // Name of the configuration section this rule
   5817       // originates from. Not available for all rules.
   5818       // Primarily informational, but also useful to
   5819       // explicitly manipulate rules by-name in AML programs.
   5820       rule_name?: string;
   5821 
   5822       // The measures will be taken if the given
   5823       // threshold is crossed over the given timeframe.
   5824       threshold: Amount;
   5825 
   5826       // Over which duration should the ``threshold`` be
   5827       // computed.  All amounts of the respective
   5828       // ``operation_type`` will be added up for this
   5829       // duration and the sum compared to the ``threshold``.
   5830       timeframe: RelativeTime;
   5831 
   5832       // Array of names of measures to apply.
   5833       // Names listed can be original measures or
   5834       // custom measures from the `AmlOutcome`.
   5835       // A special measure "verboten" is used if the
   5836       // threshold may never be crossed.
   5837       measures: string[];
   5838 
   5839       // If multiple rules apply to the same account
   5840       // at the same time, the number with the highest
   5841       // rule determines which set of measures will
   5842       // be activated and thus become visible for the
   5843       // user.
   5844       display_priority: Integer;
   5845 
   5846       // True if the rule (specifically, operation_type,
   5847       // threshold, timeframe) and the general nature of
   5848       // the measures (verboten or approval required)
   5849       // should be exposed to the client.
   5850       // Defaults to "false" if not set.
   5851       exposed?: boolean;
   5852 
   5853       // True if all the measures will eventually need to
   5854       // be satisfied, false if any of the measures should
   5855       // do.  Primarily used by the SPA to indicate how
   5856       // the measures apply when showing them to the user;
   5857       // in the end, AML programs will decide after each
   5858       // measure what to do next.
   5859       // Default (if missing) is false.
   5860       is_and_combinator?: boolean;
   5861 
   5862     }
   5863 
   5864 
   5865 .. http:get:: /aml/$OFFICER_PUB/legitimizations
   5866 
   5867   Enables AML staff to see which legitimizations are pending
   5868   or have been completed.
   5869   returns a list of active or finished legitimization
   5870   measures (by account).
   5871 
   5872   This endpoint was introduced in protocol **v23**.
   5873 
   5874   **Request:**
   5875 
   5876   *Taler-AML-Officer-Signature*:
   5877     The client must provide Base-32 encoded EdDSA signature with
   5878     ``$OFFICER_PRIV``, affirming the desire to obtain AML data.  Note that
   5879     this is merely a simple authentication mechanism, the details of the
   5880     request are not protected by the signature.
   5881 
   5882   :query limit:
   5883     *Optional*. takes value of the form ``N (-N)``, so that at
   5884     most ``N`` values strictly older (younger) than ``start`` are returned.
   5885     Defaults to ``-20`` to return the last 20 entries (before ``start``).
   5886   :query offset:
   5887     *Optional*. Row number threshold, see ``limit`` for its
   5888     interpretation.  Defaults to ``INT64_MAX``, namely the biggest row id
   5889     possible in the database.
   5890   :query h_payto:
   5891     *Optional*. Account selector using the *normalized* payto URI.
   5892     All matching accounts are returned if this
   5893     filter is absent, otherwise only decisions for this account.
   5894   :query active:
   5895     *Optional*. If set to yes, only return active decisions, if no only
   5896     decisions that have been superseded. Do not give (or use "all") to
   5897     see all decisions regardless of activity status.
   5898 
   5899   **Response:**
   5900 
   5901   :http:statuscode:`200 Ok`:
   5902     Information about possible measures is returned in a
   5903     `LegitimizationMeasuresList` object.
   5904 
   5905   **Details:**
   5906 
   5907   .. ts:def:: LegitimizationMeasuresList
   5908 
   5909     interface LegitimizationMeasuresList {
   5910 
   5911       // Legitimization measures.
   5912       measures: LegitimizationMeasureDetails[];
   5913 
   5914     }
   5915 
   5916   .. ts:def:: LegitimizationMeasureDetails
   5917 
   5918     interface LegitimizationMeasureDetails {
   5919 
   5920       // Hash of the normalized payto:// URI of the account the
   5921       // measure applies to.
   5922       h_payto: HashCode;
   5923 
   5924       // Row of the measure in the exchange database.
   5925       rowid: Integer;
   5926 
   5927       // When was the measure started?
   5928       start_time: Timestamp;
   5929 
   5930       // The the actual measures.
   5931       measures: LegitimizationMeasures;
   5932 
   5933       // Was this measure finished by the customer?
   5934       is_finished: boolean;
   5935 
   5936     }
   5937 
   5938 
   5939 .. http:get:: /aml/$OFFICER_PUB/accounts
   5940 
   5941   **Request:**
   5942 
   5943   *Accept*:
   5944     The client may specify the desired MIME-type for the result.
   5945     Supported are the usual "application/json", but also
   5946     "text/csv" (RFC 4180)
   5947     and "application/vnd.ms-excel" (XML of Excel 2003).
   5948 
   5949   *Taler-AML-Officer-Signature*:
   5950     The client must provide Base-32 encoded EdDSA signature with
   5951     ``$OFFICER_PRIV``, affirming the desire to obtain AML data.  Note that
   5952     this is merely a simple authentication mechanism, the details of the
   5953     request are not protected by the signature.
   5954 
   5955     This endpoint was introduced in this form in protocol **v31**.
   5956 
   5957   :query limit:
   5958     *Optional*. takes value of the form ``N (-N)``, so that at
   5959     most ``N`` values strictly older (younger) than ``start`` are returned.
   5960     Defaults to ``-20`` to return the last 20 entries (before ``start``).
   5961   :query offset:
   5962     *Optional*. Row number threshold, see ``delta`` for its
   5963     interpretation.  Defaults to ``INT64_MAX``, namely the biggest row id
   5964     possible in the database.
   5965   :query investigation:
   5966     *Optional*. If set to yes, only return accounts that are under
   5967     AML investigation, if no only accounts that are not under investigation.
   5968     Do not give (or use "all") to see all accounts regardless of
   5969     investigation status.
   5970   :query open:
   5971     *Optional*. If set to yes, only return accounts that are open,
   5972     which means they crossed some initial limit and now have custom rules.
   5973     Do not give (or use "all") to see all accounts regardless of
   5974     open status.
   5975   :query high_risk:
   5976     *Optional*. If set to yes, only return accounts that were flagged
   5977     as high risk.
   5978     Do not give (or use "all") to see all accounts regardless of
   5979     risk status.
   5980 
   5981   **Response:**
   5982 
   5983   :http:statuscode:`200 OK`:
   5984     The response will be an `AmlAccountsResponse` message (if the
   5985     client's header "Accept" was "application/json"). Other encodings
   5986     may differ in the exact returned data and format.
   5987   :http:statuscode:`204 No content`:
   5988     There are no accounts at all (within the specified constraints).
   5989   :http:statuscode:`403 Forbidden`:
   5990     The signature is invalid.
   5991   :http:statuscode:`404 Not found`:
   5992     The designated AML account is not known.
   5993   :http:statuscode:`409 Conflict`:
   5994     The designated AML account is not enabled.
   5995 
   5996   **Details:**
   5997 
   5998   .. ts:def:: AmlAccountsResponse
   5999 
   6000     interface AmlAccountsResponse {
   6001 
   6002       // Array of customer accounts matching the query.
   6003       accounts: CustomerAccountSummary[];
   6004     }
   6005 
   6006   .. ts:def:: CustomerAccountSummary
   6007 
   6008     interface CustomerAccountSummary {
   6009 
   6010       // Which payto-address is this record about.
   6011       // Identifies a GNU Taler wallet or an affected bank account.
   6012       h_payto: NormalizedPaytoHash;
   6013 
   6014       // Full payto URL of the account that the decision is
   6015       // about.
   6016       full_payto: string;
   6017 
   6018       // True if the account was assessed as being high risk.
   6019       high_risk: boolean;
   6020 
   6021       // Latest comments about the account (if any).
   6022       comments?: string;
   6023 
   6024       // Row of the account in the exchange tables. Useful to filter
   6025       // by offset.
   6026       rowid: Integer;
   6027 
   6028       // When was the account opened? "never" if it was never opened.
   6029       open_time: Timestamp;
   6030 
   6031       // When was the account opened? "never" if it was never closed.
   6032       close_time: Timestamp;
   6033 
   6034       // True if the account is under investigation by AML staff
   6035       // after this decision.
   6036       to_investigate: boolean;
   6037 
   6038     }
   6039 
   6040   .. ts:def:: AccountProperties
   6041 
   6042     // All fields in this object are optional. The actual
   6043     // properties collected depend fully on the discretion
   6044     // of the exchange operator;
   6045     // however, some common fields are standardized
   6046     // and thus described here.
   6047     interface AccountProperties {
   6048 
   6049       // True if this is a politically exposed account.
   6050       // Rules for classifying accounts as politically
   6051       // exposed are country-dependent.
   6052       pep?: boolean;
   6053 
   6054       // True if this is a sanctioned account.
   6055       // Rules for classifying accounts as sanctioned
   6056       // are country-dependent.
   6057       sanctioned?: boolean;
   6058 
   6059       // True if this is a high-risk account.
   6060       // Rules for classifying accounts as at-risk
   6061       // are exchange operator-dependent.
   6062       high_risk?: boolean;
   6063 
   6064       // Business domain of the account owner.
   6065       // The list of possible business domains is
   6066       // operator- or country-dependent.
   6067       business_domain?: string;
   6068 
   6069       // Is the client's account currently frozen?
   6070       is_frozen?: boolean;
   6071 
   6072       // Was the client's account reported to the authorities?
   6073       was_reported?: boolean;
   6074 
   6075     }
   6076 
   6077 
   6078 
   6079 .. http:get:: /aml/$OFFICER_PUB/attributes/$H_NORMALIZED_PAYTO
   6080 
   6081   Obtain attributes obtained as part of AML/KYC processes for a
   6082   given account.
   6083 
   6084   This endpoint was introduced in protocol **v20**.
   6085 
   6086   **Request:**
   6087 
   6088   *Accept*:
   6089     The client may specify the desired MIME-type for the result.
   6090     Supported are the usual "application/json", but also
   6091     "application/pdf".
   6092 
   6093   *Taler-AML-Officer-Signature*:
   6094     The client must provide Base-32 encoded EdDSA signature with
   6095     ``$OFFICER_PRIV``, affirming the desire to obtain AML data.  Note that
   6096     this is merely a simple authentication mechanism, the details of the
   6097     request are not protected by the signature.
   6098 
   6099   :query limit:
   6100     *Optional*. takes value of the form ``N (-N)``, so that at
   6101     most ``N`` values strictly older (younger) than ``start`` are returned.
   6102     Defaults to ``-20`` to return the last 20 entries (before ``start``).
   6103   :query offset:
   6104     *Optional*. Row number threshold, see ``delta`` for its
   6105     interpretation.  Defaults to ``INT64_MAX``, namely the biggest row id
   6106     possible in the database.
   6107 
   6108   **Response:**
   6109 
   6110   :http:statuscode:`200 OK`:
   6111     The responds will be an `KycAttributes` message.
   6112   :http:statuscode:`204 No content`:
   6113     There are no matching KYC attributes.
   6114   :http:statuscode:`403 Forbidden`:
   6115     The signature is invalid.
   6116   :http:statuscode:`404 Not found`:
   6117     The designated AML account is not known.
   6118   :http:statuscode:`409 Conflict`:
   6119     The designated AML account is not enabled.
   6120 
   6121   .. ts:def:: KycAttributes
   6122 
   6123     interface KycAttributes {
   6124 
   6125       // Matching KYC attribute history of the account.
   6126       details: KycAttributeCollectionEvent[];
   6127 
   6128     }
   6129 
   6130   .. ts:def:: KycAttributeCollectionEvent
   6131 
   6132     interface KycAttributeCollectionEvent {
   6133 
   6134       // Row ID of the record.  Used to filter by offset.
   6135       rowid: Integer;
   6136 
   6137       // True if the attributes were filed by an AML officer,
   6138       // otherwise they were provided directly by the customer.
   6139       by_aml_officer: boolean;
   6140 
   6141       // The collected KYC data.  NULL if the attribute data could not
   6142       // be decrypted (internal error of the exchange, likely the
   6143       // attribute key was changed).
   6144       attributes?: CustomerKycAttributes;
   6145 
   6146       // Time when the KYC data was collected
   6147       collection_time: Timestamp;
   6148 
   6149     }
   6150 
   6151   .. ts:def:: CustomerKycAttributes
   6152 
   6153     interface CustomerKycAttributes {
   6154 
   6155       // ID of the Form that was used to submit the attributes and/or
   6156       // that should be used to *render* the attributes.
   6157       // Mandatory since **v31**.
   6158       FORM_ID: String;
   6159 
   6160       // Version of the form completed by the user.
   6161       FORM_VERSION?: Number;
   6162 
   6163       // High entropy value used in forms where hash is going to be stored in
   6164       // plain text.
   6165       FORM?_SALT: String;
   6166 
   6167       // Attributes can have basically arbitrary additional
   6168       // Key-value pairs. See the
   6169       // gnu-taler-form-attributes registry in GANA
   6170       // for possible keys!
   6171 
   6172     }
   6173 
   6174 
   6175 .. http:post:: /aml/$OFFICER_PUB/decision
   6176 
   6177   Make an AML decision. Triggers the respective action and
   6178   records the justification.
   6179 
   6180   **Request:**
   6181 
   6182   The request must be an `AmlDecisionRequest` message.
   6183 
   6184   **Response**
   6185 
   6186   :http:statuscode:`204 No content`:
   6187     The AML decision has been executed and recorded successfully.
   6188   :http:statuscode:`403 Forbidden`:
   6189     The signature is invalid (or the AML officer not known).
   6190   :http:statuscode:`404 Not found`:
   6191     The normalized payto-address the decision was made for is unknown to the exchange.
   6192   :http:statuscode:`409 Conflict`:
   6193     The designated AML account is not enabled or a more recent
   6194     decision was already submitted.
   6195 
   6196   **Details:**
   6197 
   6198   .. ts:def:: AmlDecisionRequest
   6199 
   6200     interface AmlDecisionRequest {
   6201 
   6202       // Human-readable justification for the decision.
   6203       justification: string;
   6204 
   6205       // Hash of normalized payto-address of the account the decision is about.
   6206       // Identifies a GNU Taler wallet or an affected bank account.
   6207       h_payto: NormalizedPaytoHash;
   6208 
   6209       // Full payto address of the account the decision is about.
   6210       // Optional. Must be given if the account is not yet
   6211       // known to the exchange. If given, must match ``h_payto``
   6212       // (when normalized and then hashed).
   6213       // @since protocol **v21**.
   6214       payto_uri?: string;
   6215 
   6216       // What are the new rules?
   6217       // New since protocol **v20**.
   6218       new_rules: LegitimizationRuleSet;
   6219 
   6220       // What are the new account properties?
   6221       // New since protocol **v20**.
   6222       properties: AccountProperties;
   6223 
   6224       // Array of AML/KYC events to trigger for statistics.
   6225       // Note that this information is not covered by the signature
   6226       // (which is OK as events are just for statistics).
   6227       // New since protocol **v24**.
   6228       events?: string[];
   6229 
   6230       // Space-separated list of measures to trigger
   6231       // immediately on the account.
   6232       // Prefixed with a "+" to indicate that the
   6233       // measures should be ANDed.
   6234       // Should typically be used to give the user some
   6235       // information or request additional information.
   6236       //
   6237       // At most one measure with a SKIP check may be specified.
   6238       //
   6239       // @since protocol **v21**.
   6240       new_measures?: string;
   6241 
   6242       // True if the account should remain under investigation by AML staff.
   6243       // @since protocol **v20**.
   6244       keep_investigating: boolean;
   6245 
   6246       // Signature by the AML officer over a `TALER_AmlDecisionPS`.
   6247       // Must have purpose ``TALER_SIGNATURE_MASTER_AML_KEY``.
   6248       officer_sig: EddsaSignature;
   6249 
   6250       // When was the decision made?
   6251       decision_time: Timestamp;
   6252 
   6253       // KYC attributes uploaded by the AML officer
   6254       // The object *must* contain high-entropy salt,
   6255       // as the hash of the attributes will be
   6256       // stored in plain text.
   6257       attributes?: CustomerKycAttributes;
   6258 
   6259       // Expiration timestamp of the attributes.
   6260       // Mandatory if attributes are present.
   6261       attributes_expiration?: Timestamp;
   6262 
   6263     }
   6264 
   6265 
   6266 .. http:get:: /aml/$OFFICER_PUB/transfers-credit
   6267 .. http:get:: /aml/$OFFICER_PUB/transfers-debit
   6268 .. http:get:: /aml/$OFFICER_PUB/transfers-kycauth
   6269 
   6270   Obtain exchange's bank account wire transfer history data. Shows effective
   6271   incoming wire transfers (credit), incoming wire transfers for KYC
   6272   authorization (kycauth), or effective outgoing (aggregated, closed)
   6273   wire transfers (debit).  Note that bounced incoming
   6274   wire transfers and drain outgoing wire transfers requests are excluded (as
   6275   they are not relevant for AML processes and would just distract). The
   6276   wire transfer subject is also not given as in all cases it will just
   6277   be some cryptographic data that is meaningless for humans.
   6278 
   6279   The first two endpoints were introduced in protocol **v25**.
   6280   ``transfers-kycauth`` was added in protocol **v29**.
   6281 
   6282   **Request:**
   6283 
   6284   *Taler-AML-Officer-Signature*:
   6285     The client must provide Base-32 encoded EdDSA signature with
   6286     ``$OFFICER_PRIV``, affirming the desire to obtain AML data.  Note that
   6287     this is merely a simple authentication mechanism, the details of the
   6288     request are not protected by the signature.
   6289 
   6290   :query threshold:
   6291     *Optional*. minimum amount ("CURRENCY:VAL.FRAC") to return. All amounts
   6292     below the given threshold will be filtered.
   6293   :query limit:
   6294     *Optional*. takes value of the form ``N (-N)``, so that at
   6295     most ``N`` values strictly older (younger) than ``start`` are returned.
   6296     Defaults to ``-20`` to return the last 20 entries (before ``start``).
   6297   :query offset:
   6298     *Optional*. Row number threshold, see ``delta`` for its
   6299     interpretation.  Defaults to ``INT64_MAX``, namely the biggest row id
   6300     possible in the database.
   6301   :query h_payto:
   6302     *Optional*. Account selector using the *normalized* payto URI.
   6303     Information for all accounts is returned if this
   6304     filter is absent, otherwise only transactions for this account.
   6305     @since protocol **v29**.
   6306 
   6307   **Response:**
   6308 
   6309   :http:statuscode:`200 OK`:
   6310     The responds will be an `ExchangeTransferList` message.
   6311   :http:statuscode:`204 No content`:
   6312     There are no matching transactions.
   6313   :http:statuscode:`403 Forbidden`:
   6314     The signature is invalid.
   6315   :http:statuscode:`404 Not found`:
   6316     The designated AML account is not known.
   6317   :http:statuscode:`409 Conflict`:
   6318     The designated AML account is not enabled.
   6319 
   6320   .. ts:def:: ExchangeTransferList
   6321 
   6322     interface ExchangeTransferList {
   6323 
   6324       // Matching transaction of the exchange
   6325       transfers: ExchangeTransferListEntry[];
   6326 
   6327     }
   6328 
   6329   .. ts:def:: ExchangeTransferListEntry
   6330 
   6331     interface ExchangeTransferListEntry {
   6332 
   6333       // Row ID of the record.  Used to filter by offset.
   6334       rowid: Integer;
   6335 
   6336       // payto://-URI of the other account.
   6337       payto_uri: string;
   6338 
   6339       // The amount involved.
   6340       amount: Amount;
   6341 
   6342       // Time when the transfer was made
   6343       execution_time: Timestamp;
   6344 
   6345     }
   6346 
   6347 
   6348 
   6349 
   6350 ---------------
   6351 Reserve control
   6352 ---------------
   6353 
   6354 This section describes the reserve control API which can be used to (1)
   6355 prevent a reserve from expiring, to (2) pay an annual fee to allow a number of
   6356 purses to be created for the respective reserve without paying a purse fee
   6357 each time, to (3) obtain KYC information associated with a reserve to prove
   6358 the identity of the person sending an invoice to the payer, and to (4) close a
   6359 reserve before it would naturally expire and possibly (5) wire the funds to a
   6360 designated account.
   6361 
   6362   .. note::
   6363 
   6364      This section is about a proposed API. It is not implemented. See also DD 31.
   6365 
   6366 .. http:post:: /reserves/$RESERVE_PUB/open
   6367 
   6368   Request keeping a reserve open for invoicing.
   6369 
   6370   **Request:**
   6371 
   6372   The request body must be a `ReserveOpenRequest` object.
   6373 
   6374   **Response:**
   6375 
   6376   :http:statuscode:`200 OK`:
   6377     The exchange responds with a `ReserveOpenResponse` object.
   6378   :http:statuscode:`402 Payment Required`:
   6379     The exchange responds with a `ReserveOpenFailure` object when
   6380     the payment offered is insufficient for the requested operation.
   6381   :http:statuscode:`403 Forbidden`:
   6382     The *TALER_SIGNATURE_WALLET_RESERVE_OPEN* signature is invalid.
   6383     This response comes with a standard `ErrorDetail` response.
   6384   :http:statuscode:`404 Not found`:
   6385     The reserve key does not belong to a reserve known to the exchange.
   6386   :http:statuscode:`409 Conflict`:
   6387     The balance of the reserve or of a coin was insufficient.
   6388     Which case it is can be decided by looking at the error code
   6389     (``TALER_EC_EXCHANGE_GENERIC_INSUFFICIENT_FUNDS`` or
   6390     ``TALER_EC_EXCHANGE_GENERIC_COIN_CONFLICTING_DENOMINATION_KEY`` or
   6391     ``TALER_EC_EXCHANGE_OPEN_INSUFFICIENT_FUNDS``).
   6392     The specific fields of the response depend on the error code
   6393     and include the signatures (and what was signed over) proving the
   6394     conflict.
   6395     The response is `WithdrawError` object or a `DepositDoubleSpendError`
   6396     depending on the error type.
   6397   :http:statuscode:`451 Unavailable For Legal Reasons`:
   6398     This account has not yet passed the KYC checks.
   6399     The client must pass KYC checks before the reserve can be opened.
   6400     The response will be an `LegitimizationNeededResponse` object.
   6401 
   6402   **Details:**
   6403 
   6404   .. ts:def:: ReserveOpenRequest
   6405 
   6406     interface ReserveOpenRequest {
   6407       // Signature of purpose
   6408       // ``TALER_SIGNATURE_WALLET_RESERVE_OPEN`` over
   6409       // a `TALER_ReserveOpenPS`.
   6410       reserve_sig: EddsaSignature;
   6411 
   6412       // Array of payments made towards the cost of the
   6413       // operation.
   6414       payments: OpenPaymentDetail[];
   6415 
   6416       // Amount to be paid from the reserve for this
   6417       // operation.
   6418       reserve_payment: Amount;
   6419 
   6420       // Time when the client made the request.
   6421       // Timestamp must be reasonably close to the time of
   6422       // the exchange, otherwise the exchange may reject
   6423       // the request (with a status code of 400).
   6424       request_timestamp: Timestamp;
   6425 
   6426       // Desired new expiration time for the reserve.
   6427       // If the reserve would expire before this time,
   6428       // the exchange will charge account fees (and
   6429       // possibly KYC fees) until the expiration time
   6430       // exceeds this timestamp. Note that the exchange
   6431       // will refuse requests (with a status code of 400)
   6432       // if the time is so far in the future that the
   6433       // fees are not yet known (see /keys).
   6434       reserve_expiration: Timestamp;
   6435 
   6436       // Desired open purse limit. Can be used to pay the
   6437       // annual account fee more than once to get a larger
   6438       // purse limit.
   6439       purse_limit: Integer;
   6440 
   6441     }
   6442 
   6443   .. ts:def:: ReserveOpenResponse
   6444 
   6445     interface ReserveOpenResponse {
   6446       // Transaction cost for extending the expiration time.
   6447       // Excludes KYC fees.
   6448       open_cost: Amount;
   6449 
   6450       // Current expiration time for the reserve.
   6451       reserve_expiration: Timestamp;
   6452     }
   6453 
   6454   .. ts:def:: ReserveOpenFailure
   6455 
   6456     interface ReserveOpenFailure {
   6457       // Transaction cost that should have been paid
   6458       // to extending the reserve as requested.
   6459       // Excludes KYC fees.
   6460       open_cost: Amount;
   6461 
   6462       // Remaining expiration time for the reserve.
   6463       reserve_expiration: Timestamp;
   6464     }
   6465 
   6466   .. ts:def:: OpenPaymentDetail
   6467 
   6468     interface OpenPaymentDetail {
   6469 
   6470       // Contribution of this coin to the overall amount.
   6471       // Can be a fraciton of the coin's total value.
   6472       amount: Amount;
   6473 
   6474       // Hash of denomination RSA key with which the coin is signed.
   6475       denom_pub_hash: HashCode;
   6476 
   6477       // Exchange's unblinded RSA signature of the coin.
   6478       ub_sig: DenominationSignature;
   6479 
   6480       // Age commitment for the coin, if the denomination is age-restricted.
   6481       age_commitment?: AgeCommitment;
   6482 
   6483       // Signature over `TALER_ReserveOpenDepositSignaturePS`
   6484       // of purpose ``TALER_SIGNATURE_WALLET_RESERVE_OPEN_DEPOSIT``
   6485       // made by the customer with the
   6486       // `coin's private key <coin-priv>`.
   6487       coin_sig: EddsaSignature;
   6488 
   6489       // Public key of the coin being used to pay for
   6490       // opening the reserve.
   6491       coin_pub: EddsaPublicKey;
   6492 
   6493     }
   6494 
   6495 
   6496 .. http:get:: /reserves-attest/$RESERVE_PUB
   6497 
   6498   Request list of available KYC attributes about the owner of a reserve.
   6499   Used as a preliminary step to find out which subsets of attributes the
   6500   exchange could provide signatures over.
   6501 
   6502   **Response:**
   6503 
   6504   :http:statuscode:`200 OK`:
   6505     The exchange responds with a `ReserveKycAttributes` object.
   6506   :http:statuscode:`404 Not found`:
   6507     The reserve key does not belong to a reserve known to the exchange.
   6508   :http:statuscode:`409 Conflict`:
   6509     The exchange does not have the requested KYC information.
   6510 
   6511   **Details:**
   6512 
   6513   .. ts:def:: ReserveKycAttributes
   6514 
   6515     interface ReserveKycAttributes {
   6516       // Array of KYC attributes available.  The attribute names
   6517       // listed are expected to be from the respective GANA
   6518       // registry.
   6519       details: string[];
   6520     }
   6521 
   6522 
   6523 .. http:post:: /reserves-attest/$RESERVE_PUB
   6524 
   6525   Request signed KYC information about the owner of a reserve.
   6526   This can be used by a reserve owner to include a proof
   6527   of their identity in invoices.
   6528 
   6529   **Request:**
   6530 
   6531   The request body must be a `ReserveAttestRequest` object.
   6532 
   6533   **Response:**
   6534 
   6535   :http:statuscode:`200 OK`:
   6536     The exchange responds with a `ReserveAttestResponse` object.
   6537   :http:statuscode:`403 Forbidden`:
   6538     The *TALER_SIGNATURE_WALLET_KYC_DETAILS* signature is invalid.
   6539     This response comes with a standard `ErrorDetail` response.
   6540   :http:statuscode:`404 Not found`:
   6541     The reserve key does not belong to a reserve known to the exchange.
   6542   :http:statuscode:`409 Conflict`:
   6543     The exchange does not have the requested KYC information.
   6544 
   6545   **Details:**
   6546 
   6547   .. ts:def:: ReserveAttestRequest
   6548 
   6549     interface ReserveAttestRequest {
   6550       // Signature of purpose
   6551       // ``TALER_SIGNATURE_WALLET_ATTEST_DETAILS`` over
   6552       // a `TALER_WalletReserveAttestRequestSignaturePS`.
   6553       reserve_sig: EddsaSignature;
   6554 
   6555       // Client's time for the request.
   6556       request_timestamp: Timestamp;
   6557 
   6558       // Array of KYC attributes requested.
   6559       details: string[];
   6560     }
   6561 
   6562   .. ts:def:: ReserveAttestResponse
   6563 
   6564     interface ReserveAttestResponse {
   6565       // Signature of purpose
   6566       // ``TALER_SIGNATURE_EXCHANGE_RESERVE_ATTEST_DETAILS`` over
   6567       // a `TALER_ExchangeAttestPS`.
   6568       exchange_sig: EddsaSignature;
   6569 
   6570       // Exchange public key used to create the
   6571       // signature.
   6572       exchange_pub: EddsaPublicKey;
   6573 
   6574       // Time when the exchange created the signature.
   6575       exchange_timestamp: Timestamp;
   6576 
   6577       // Expiration time for the provided information.
   6578       expiration_time: Timestamp;
   6579 
   6580       // KYC details (key-value pairs) as requested.
   6581       // The keys will match the elements of the
   6582       // ``details`` array from the request.
   6583       attributes: CustomerKycAttributes;
   6584     }
   6585 
   6586 
   6587 .. http:post:: /reserves/$RESERVE_PUB/close
   6588 
   6589   Force immediate closure of a reserve. Does not actually
   6590   delete the reserve or the KYC data, but merely forces
   6591   the reserve's current balance to be wired back to the
   6592   account where it originated from, or another account of
   6593   the user's choosing if they performed the required KYC
   6594   check and designated another target account.
   6595 
   6596   **Request:**
   6597 
   6598   The request body must be a `ReserveCloseRequest` object.
   6599 
   6600   **Response:**
   6601 
   6602   :http:statuscode:`200 OK`:
   6603     The exchange responds with a `ReserveCloseResponse` object.
   6604   :http:statuscode:`403 Forbidden`:
   6605     The *TALER_SIGNATURE_WALLET_RESERVE_CLOSE* signature is invalid.
   6606     This response comes with a standard `ErrorDetail` response.
   6607   :http:statuscode:`404 Not found`:
   6608     The reserve key does not belong to a reserve known to the exchange.
   6609   :http:statuscode:`409 Conflict`:
   6610     No target account was given, and the exchange does not know an
   6611     origin account for this reserve.
   6612   :http:statuscode:`451 Unavailable For Legal Reasons`:
   6613     This account has not yet passed the KYC checks, hence wiring
   6614     funds to a non-origin account is not allowed.
   6615     The client must pass KYC checks before the reserve can be opened.
   6616     The response will be an `LegitimizationNeededResponse` object.
   6617 
   6618   **Details:**
   6619 
   6620   .. ts:def:: ReserveCloseRequest
   6621 
   6622     interface ReserveCloseRequest {
   6623       // Signature of purpose
   6624       // ``TALER_SIGNATURE_WALLET_RESERVE_CLOSE`` over
   6625       // a `TALER_ReserveCloseRequestSignaturePS`.
   6626       reserve_sig: EddsaSignature;
   6627 
   6628       // Time when the client made the request.
   6629       // Timestamp must be reasonably close to the time of
   6630       // the exchange, otherwise the exchange may reject
   6631       // the request (with a status code of 400).
   6632       request_timestamp: Timestamp;
   6633 
   6634       // Full payto://-URI of the account the reserve balance is to be
   6635       // wired to.  Must be of the form: 'payto://$METHOD' for a
   6636       // wire method supported by this exchange (if the
   6637       // method is not supported, this is a bad request (400)).
   6638       // If not given, the reserve's origin account
   6639       // will be used. If no origin account is known for the
   6640       // reserve and not given, this is a conflict (409).
   6641       payto_uri?: string;
   6642 
   6643     }
   6644 
   6645   .. ts:def:: ReserveCloseResponse
   6646 
   6647     interface ReserveCloseResponse {
   6648 
   6649       // Actual amount that will be wired (excludes closing fee).
   6650       wire_amount: Amount;
   6651 
   6652     }
   6653 
   6654 
   6655 .. _delete-reserve:
   6656 
   6657 .. http:DELETE:: /reserves/$RESERVE_PUB
   6658 
   6659   Forcefully closes a reserve.
   6660   The request header must contain an *Account-Request-Signature*.
   6661   Note: this endpoint is not currently implemented!
   6662 
   6663   **Request:**
   6664 
   6665   *Account-Request-Signature*:
   6666     The client must provide Base-32 encoded EdDSA signature made with
   6667     ``$ACCOUNT_PRIV``, affirming its authorization to delete the account.
   6668     The purpose used MUST be ``TALER_SIGNATURE_RESERVE_CLOSE``.
   6669 
   6670   :query force=BOOLEAN: *Optional.*  If set to 'true' specified, the exchange
   6671     will delete the account even if there is a balance remaining.
   6672 
   6673   **Response:**
   6674 
   6675   :http:statuscode:`200 OK`:
   6676     The operation succeeded, the exchange provides details
   6677     about the account deletion.
   6678     The response will include a `ReserveDeletedResponse` object.
   6679   :http:statuscode:`403 Forbidden`:
   6680     The *Account-Request-Signature* is invalid.
   6681     This response comes with a standard `ErrorDetail` response.
   6682   :http:statuscode:`404 Not found`:
   6683     The account is unknown to the exchange.
   6684   :http:statuscode:`409 Conflict`:
   6685     The account is still has digital cash in it, the associated
   6686     wire method is ``void`` and the *force* option was not provided.
   6687     This response comes with a standard `ErrorDetail` response.
   6688 
   6689   **Details:**
   6690 
   6691   .. ts:def:: ReserveDeletedResponse
   6692 
   6693      interface ReserveDeletedResponse {
   6694 
   6695       // Final balance of the account.
   6696       closing_amount: Amount;
   6697 
   6698       // Current time of the exchange, used as part of
   6699       // what the exchange signs over.
   6700       close_time: Timestamp;
   6701 
   6702       // Hash of the full payto URI of the wire account
   6703       // into which the remaining balance will be transferred.
   6704       // Note: may be the hash over ``payto://void/`,
   6705       // in which case the balance is forfeit
   6706       // to the profit of the exchange.
   6707       h_wire: FullPaytoHash;
   6708 
   6709       // This is a signature over a
   6710       // struct ``TALER_AccountDeleteConfirmationPS`` with purpose
   6711       // ``TALER_SIGNATURE_EXCHANGE_RESERVE_DELETED``.
   6712       exchange_sig: EddsaSignature;
   6713 
   6714     }