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 }