api-exchange.rst (19006B)
1 .. 2 This file is part of GNU TALER. 3 Copyright (C) 2014-2026 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 3.0, 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 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 29 --------------- 30 Version History 31 --------------- 32 33 The currently implemented protocol version is **v38**. 34 35 * Wallet-core is currently targeting **vXX**. 36 * The merchant is currently targeting **v34**. 37 * The AML SPA is currently targeting **v31**. 38 * The KYC SPA is currently targeting **v30**. 39 40 **Version history:** 41 42 * ``v29``: AML reporting on KYC auth transfers 43 * ``v30``: various minor feature additions 44 * ``v31``: improvements for AML reporting 45 * ``v32``: support for extra_wire_subject_metadata 46 * ``v33``: addition of accumulated_total_without_fee in :http:post:`/batch-deposit </batch-deposit>` 47 * ``v34``: new offline signature; support for open_banking_gateway and 48 prepared_transfer_url per wire account in :http:get:`/keys </keys>` 49 * ``v35``: adds ``default_p2p_push_expiration`` to :http:get:`/keys </keys>` 50 * ``v36``: adds ``kyc_swap_tos_acceptance`` to :http:get:`/keys </keys>` 51 * ``v37``: adds :http:get:`/aml/$OFFICER_PUB/wallet-credit </aml/$OFFICER_PUB/wallet-credit>` endpoint 52 * ``v38``: adds ``build_version`` to :http:get:`/config </config>` 53 54 **Upcoming versions:** 55 56 * ``vIMPORT``: external KYC/KYB data import 57 * ``vRECOUP``: improved recoup protocol 58 * ``vATTEST``: KYC attestation support 59 60 **Ideas for future version:** 61 62 * ``vXXX``: marker for features not yet targeted for release 63 64 .. include:: tos.rst 65 66 .. _keys: 67 68 --------------------------- 69 Exchange status information 70 --------------------------- 71 72 This API is used by wallets and merchants to obtain global information about 73 the exchange, such as online signing keys, available denominations and the fee 74 structure. This is typically the first call any exchange client makes, as it 75 returns information required to process all of the other interactions with the 76 exchange. The returned information is secured by (1) signature(s) from the exchange, 77 especially the long-term offline signing key of the exchange, which clients should 78 cache; (2) signature(s) from auditors, and the auditor keys should be 79 hard-coded into the wallet as they are the trust anchors for Taler; (3) 80 possibly by using HTTPS. 81 82 83 .. include:: exchange/get-seed.rst 84 85 .. include:: exchange/get-config.rst 86 87 .. include:: exchange/get-keys.rst 88 89 90 ---------------------------------------------- 91 Management operations authorized by master key 92 ---------------------------------------------- 93 94 .. include:: exchange/get-management-keys.rst 95 96 .. include:: exchange/post-management-keys.rst 97 98 .. include:: exchange/post-management-denominations-H_DENOM_PUB-revoke.rst 99 100 .. include:: exchange/post-management-signkeys-EXCHANGE_PUB-revoke.rst 101 102 .. include:: exchange/post-management-auditors.rst 103 104 .. include:: exchange/post-management-auditors-AUDITOR_PUB-disable.rst 105 106 .. include:: exchange/post-management-wire-fee.rst 107 108 .. include:: exchange/post-management-global-fees.rst 109 110 .. include:: exchange/post-management-wire.rst 111 112 .. include:: exchange/post-management-wire-disable.rst 113 114 .. include:: exchange/post-management-drain.rst 115 116 .. include:: exchange/post-management-aml-officers.rst 117 118 .. include:: exchange/post-management-partners.rst 119 120 --------------- 121 Auditor actions 122 --------------- 123 124 .. _auditor_action: 125 126 This part of the API is for the use by auditors interacting with the exchange. 127 128 .. include:: exchange/post-auditors-AUDITOR_PUB-H_DENOM_PUB.rst 129 130 131 ---------------- 132 Blinding Prepare 133 ---------------- 134 135 Certain denomination cipher types, such as Clause-Schnorr, require input values 136 from the exchange-side as preparation for the blinding of the coins. See the 137 Bachelor thesis of Gian Demarmels and Lucien Heuzeveldt, 138 `Adding Schnorr’s Blind Signature in Taler <https://www.taler.net/papers/cs-thesis.pdf>`_, 139 for details. 140 141 .. include:: exchange/post-blinding-prepare.rst 142 143 144 .. _exchange-withdrawal: 145 146 ---------- 147 Withdrawal 148 ---------- 149 150 This API is used by the wallet to obtain digital coins. 151 152 When transferring money to the exchange such as via SEPA transfers, the exchange creates 153 a *reserve*, which keeps the money from the customer. The customer must 154 specify an EdDSA reserve public key as part of the transfer, and can then 155 withdraw digital coins using the corresponding private key. All incoming and 156 outgoing transactions are recorded under the corresponding public key by the 157 exchange. 158 159 .. note:: 160 161 Eventually the exchange will need to advertise a policy for how long it will 162 keep transaction histories for inactive or even fully drained reserves. We 163 will therefore need some additional handler similar to :http:get:`/keys </keys>` to 164 advertise those terms of service. 165 166 167 .. include:: exchange/get-reserves-RESERVE_PUB.rst 168 169 .. _withdraw: 170 .. include:: exchange/post-withdraw.rst 171 172 173 .. ts:def:: WithdrawRequest 174 175 interface WithdrawRequest { 176 // Cipher that is used for the rerserve's signatures. 177 // For now, only ed25519 signatures are applicable, 178 // but this might change in future versions. 179 cipher: "ED25519"; 180 181 // The reserve's public key, for the the cipher ED25519, 182 // to verify the signature ``reserve_sig``. 183 reserve_pub: EddsaPublicKey; 184 185 // Array of ``n`` hash codes of denomination public keys to order. 186 // The sum of all denomination's values and fees MUST be 187 // at most the balance of the reserve. The balance of 188 // the reserve will be immediatley reduced by that amount. 189 // If ``max_age`` is set, these denominations MUST support 190 // age restriction as defined in the output to /keys. 191 denoms_h: HashCode[]; 192 193 // If set, the maximum age to commit to. This implies: 194 // 1.) it MUST be the same value as the maximum age 195 // of the reserve. 196 // 2.) ``coin_evs`` MUST be an array of ``n*kappa`` 197 // 3.) the denominations in ``denoms_h`` MUST support 198 // age restriction. 199 max_age?: Integer; 200 201 // Master seed for the Clause-Schnorr R-value creation. 202 // MUST match the /blinding-prepare request. 203 // MUST NOT have been used in any prior withdraw request. 204 // MUST be present if one of the fresh coin's 205 // denomination is of type Clause-Schnorr. 206 blinding_seed?: BlindingMasterSeed; 207 208 // Array of blinded coin envelopes of type `CoinEnvelope`. 209 // If ``max_age`` is not set, MUST be n entries. 210 // If ``max_age`` is set, MUST be ``n*kappa`` entries, 211 // arranged in [0..n)..[0..n), with the first n entries 212 // belonging to kappa=0 etc. 213 // In case of age restriction, the exchange will 214 // respond with an index ``gamma``, which is the index 215 // that shall remain undisclosed during the subsequent 216 // reveal phase. 217 // This hash value along with the reserve's public key 218 // will also be used for recoup operations, if needed. 219 coin_evs: CoinEnvelope[]; 220 221 // Signature of `TALER_WithdrawRequestPS` created with 222 // the `reserves's private key <reserve-priv>`. 223 reserve_sig: EddsaSignature; 224 } 225 226 .. ts:def:: WithdrawResponse 227 228 interface WithdrawResponse { 229 // Array of blinded signatures over each ``coin_evs``, 230 // in the same order as was given in the request. 231 // The blinded signatures affirm the coin's validity 232 // after unblinding. 233 ev_sigs: BlindedDenominationSignature[]; 234 235 } 236 237 238 .. ts:def:: AgeWithdrawResponse 239 240 interface AgeWithdrawResponse { 241 // index of the commitments that the client doesn't 242 // have to disclose in the subsequent call to 243 // ``/reveal-withdraw``. 244 noreveal_index: Integer; 245 246 // Signature of `TALER_WithdrawConfirmationPS` whereby 247 // the exchange confirms the ``noreveal_index``. 248 exchange_sig: EddsaSignature; 249 250 // `Public EdDSA key <sign-key-pub>` of the exchange that was used to 251 // generate the signature. Should match one of the exchange's signing 252 // keys from ``/keys``. Again given explicitly as the client might 253 // otherwise be confused by clock skew as to which signing key was used. 254 exchange_pub: EddsaPublicKey; 255 256 } 257 258 .. ts:def:: DenominationGoneMessage 259 260 interface DenominationGoneMessage { 261 262 // Taler error code. Note that beyond 263 // expiration this message format is also 264 // used if the key is not yet valid, or 265 // has been revoked. May be one of 266 // - ``TALER_EC_EXCHANGE_GENERIC_DENOMINATION_VALIDITY_IN_FUTURE`` 267 // - ``TALER_EC_EXCHANGE_GENERIC_DENOMINATION_EXPIRED`` 268 // - ``TALER_EC_EXCHANGE_GENERIC_DENOMINATION_REVOKED`` 269 code: Integer; 270 271 // Signature by the exchange over a 272 // `TALER_DenominationExpiredAffirmationPS`. 273 // Must have purpose ``TALER_SIGNATURE_EXCHANGE_AFFIRM_DENOM_EXPIRED``. 274 exchange_sig: EddsaSignature; 275 276 // Public key of the exchange used to create 277 // the 'exchange_sig. 278 exchange_pub: EddsaPublicKey; 279 280 // Hash of the denomination public key that is unknown. 281 h_denom_pub: HashCode; 282 283 // When was the signature created. 284 timestamp: Timestamp; 285 286 // What kind of operation was requested that now 287 // failed? 288 oper: string; 289 290 } 291 292 293 .. ts:def:: WithdrawError 294 295 interface SingleWithdrawError { 296 // Text describing the error. 297 hint: string; 298 299 // Detailed error code. 300 code: Integer; 301 302 // Amount left in the reserve. 303 balance: Amount; 304 305 } 306 307 308 309 ------------------ 310 311 312 .. _reveal-withdraw: 313 314 **Reveal-Withdraw** 315 316 This endpoint is called by the client after a call to `withdraw`_, 317 *if* the original request had ``max_age`` set and 318 the response was of type `AgeWithdrawResponse`. 319 Now the client has to disclose for each coin all but one of the κ secrets 320 that went into creating the blinded coin's planchets, 321 including the commitment to age restriction, 322 and prove that the age restriction was set correctly. 323 324 .. include:: exchange/post-reveal-withdraw.rst 325 326 327 ---------- 328 Refreshing 329 ---------- 330 331 Refreshing exchanges one old coin against ``n`` new coins, where the sum of 332 denominations of the new coins must be smaller than the old coin's 333 denomination plus melting (refresh) and withdrawal fees charged by the exchange. 334 The refreshing API can be used by wallets to melt partially spent coins, making 335 transactions with the freshly exchanged coins unlinkable to previous transactions 336 by anyone except the wallet itself. 337 338 Refreshing is a two-step process, consisting of 339 340 1. the **melting** of the old coin, together with ``kappa`` batches 341 of blinded planchets candidates, 342 2. the **reveal** of ``kappa-1`` secrets to prove the proper construction 343 of the (revealed) batches of blinded planchets candidates. 344 345 346 ^^^^ 347 Melt 348 ^^^^ 349 350 .. _melt: 351 .. include:: exchange/post-melt.rst 352 353 ^^^^^^^^^^^ 354 Reveal-Melt 355 ^^^^^^^^^^^ 356 357 This endpoint is called by the client after a call to `melt`_. 358 Now the client has to disclose --for each coin-- 359 all but one of the κ secrets that went into creating the blinded coin's planchets, 360 the transfer public keys (linking the ownership of the old and new coin), 361 and the commitment to age restriction, 362 as proof that the age restriction was set correctly (if applicable). 363 364 .. include:: exchange/post-reveal-melt.rst 365 366 367 .. _deposit-par: 368 369 ------- 370 Deposit 371 ------- 372 373 Deposit operations are requested f.e. by a merchant during a transaction or a 374 bidder during an auction. 375 376 For the deposit operation during purchase, the merchant has to obtain the 377 deposit permission for a coin from their customer who owns the coin. When 378 depositing a coin, the merchant is credited an amount specified in the deposit 379 permission, possibly a fraction of the total coin's value, minus the deposit 380 fee as specified by the coin's denomination. 381 382 For auctions, a bidder performs a deposit operation and provides all relevant 383 information for the auction policy (such as timeout and public key as bidder) 384 and can use the ``exchange_sig`` field from the `DepositSuccessResponse` 385 message as a proof to the seller for the escrow of sufficient fund. 386 387 388 .. _deposit: 389 390 .. include:: exchange/post-batch-deposit.rst 391 392 393 ------ 394 Recoup 395 ------ 396 397 The purpose of this API is to allow coins to be cashed back in, 398 in certain exceptional situations. 399 This API is only used if the exchange is either about to go out of 400 business or has had its private signing keys compromised (so in 401 either case, the protocol is only used in **abnormal** 402 situations). In the above cases, the exchange signals to the 403 wallets that the emergency cash back protocol has been activated 404 by putting the affected denomination keys into the cash-back 405 part of the :http:get:`/keys </keys>` response. If and only if this has happened, 406 coins that were signed with those denomination keys can be cashed 407 in using this API. 408 409 For a recoup, a coin has to provide the necessary information to 410 identify the original transaction (either a withdraw or a refresh) it 411 became minted, and prove ownership of the coin itself. 412 413 414 .. include:: exchange/post-recoup-withdraw.rst 415 416 .. include:: exchange/post-recoup-refresh.rst 417 418 419 .. _exchange_refund: 420 421 ------- 422 Refunds 423 ------- 424 425 .. include:: exchange/post-coins-COIN_PUB-refund.rst 426 427 .. _reserve-history: 428 429 --------------- 430 Reserve History 431 --------------- 432 433 .. include:: exchange/get-reserves-RESERVE_PUB-history.rst 434 435 436 .. _coin-history: 437 438 ------------ 439 Coin History 440 ------------ 441 442 .. include:: exchange/get-coins-COIN_PUB-history.rst 443 444 ----------------------- 445 Tracking wire transfers 446 ----------------------- 447 448 This API is used by merchants that need to find out which wire 449 transfers (from the exchange to the merchant) correspond to which deposit 450 operations. Typically, a merchant will receive a wire transfer with a 451 **wire transfer identifier** and want to know the set of deposit 452 operations that correspond to this wire transfer. This is the 453 preferred query that merchants should make for each wire transfer they 454 receive. If a merchant needs to investigate a specific deposit 455 operation (i.e. because it seems that it was not paid), then the 456 merchant can also request the wire transfer identifier for a deposit 457 operation. 458 459 Sufficient information is returned to verify that the coin signatures 460 are correct. This also allows governments to use this API when doing 461 a tax audit on merchants. 462 463 Naturally, the returned information may be sensitive for the merchant. 464 We do not require the merchant to sign the request, as the same requests 465 may also be performed by the government auditing a merchant. 466 However, wire transfer identifiers should have sufficient entropy to 467 ensure that obtaining a successful reply by brute-force is not practical. 468 Nevertheless, the merchant should protect the wire transfer identifiers 469 from his bank statements against unauthorized access, lest his income 470 situation is revealed to an adversary. (This is not a major issue, as 471 an adversary that has access to the line-items of bank statements can 472 typically also view the balance.) 473 474 475 .. include:: exchange/get-transfers-WTID.rst 476 477 .. include:: exchange/get-deposits-H_WIRE-MERCHANT_PUB-H_CONTRACT_TERMS-COIN_PUB.rst 478 479 480 .. _exchange_w2w: 481 482 -------------------------- 483 Wallet-to-wallet transfers 484 -------------------------- 485 486 .. include:: exchange/get-purses-PURSE_PUB-merge.rst 487 488 .. include:: exchange/post-purses-PURSE_PUB-create.rst 489 490 .. include:: exchange/delete-purses-PURSE_PUB.rst 491 492 .. include:: exchange/post-purses-PURSE_PUB-merge.rst 493 494 .. include:: exchange/post-reserves-RESERVE_PUB-purse.rst 495 496 .. include:: exchange/get-contracts-CONTRACT_PUB.rst 497 498 .. include:: exchange/post-purses-PURSE_PUB-deposit.rst 499 500 501 .. _exchange_wads: 502 503 ---- 504 Wads 505 ---- 506 507 .. note:: 508 509 This is a draft API that is not yet implemented. 510 511 512 These endpoints are used to manage exchange-to-exchange payments in support of 513 wallet-to-wallet payments. Only another exchange should access this endpoint. 514 515 516 .. include:: exchange/get-wads-WAD_ID.rst 517 518 519 ------------------ 520 KYC status updates 521 ------------------ 522 523 This section describes endpoints used to set up, complete and 524 inquire about KYC operations performed by an exchange for 525 regulatory compliance. 526 527 .. include:: exchange/post-kyc-wallet.rst 528 529 .. include:: exchange/get-kyc-check-H_NORMALIZED_PAYTO.rst 530 531 .. include:: exchange/get-kyc-spa-ACCESS_TOKEN.rst 532 533 .. include:: exchange/get-kyc-info-ACCESS_TOKEN.rst 534 535 .. include:: exchange/post-kyc-upload-ID.rst 536 537 .. include:: exchange/post-kyc-start-ID.rst 538 539 .. include:: exchange/post-kyc-import-EXTERN_PUB.rst 540 541 .. include:: exchange/post-kyc-bulk-EXTERN_PUB.rst 542 543 .. include:: exchange/get-kyc-proof-PROVIDER_NAME.rst 544 545 .. include:: exchange/get-kyc-webhook-PROVIDER_NAME-star.rst 546 547 548 -------------- 549 AML operations 550 -------------- 551 552 This API is only for designated AML officers. It is used 553 to allow exchange staff to monitor suspicious transactions 554 and freeze or unfreeze accounts suspected of money laundering. 555 556 .. include:: exchange/get-aml-OFFICER_PUB-measures.rst 557 558 .. include:: exchange/get-aml-OFFICER_PUB-kyc-statistics-NAMES.rst 559 560 .. include:: exchange/get-aml-OFFICER_PUB-decisions.rst 561 562 .. include:: exchange/get-aml-OFFICER_PUB-legitimizations.rst 563 564 .. include:: exchange/get-aml-OFFICER_PUB-accounts.rst 565 566 .. include:: exchange/get-aml-OFFICER_PUB-attributes-H_NORMALIZED_PAYTO.rst 567 568 .. include:: exchange/post-aml-OFFICER_PUB-decision.rst 569 570 .. include:: exchange/get-aml-OFFICER_PUB-transfers-credit.rst 571 572 .. include:: exchange/get-aml-OFFICER_PUB-wallet-credit.rst 573 574 --------------- 575 Reserve control 576 --------------- 577 578 This section describes the reserve control API which can be used to (1) 579 prevent a reserve from expiring, to (2) pay an annual fee to allow a number of 580 purses to be created for the respective reserve without paying a purse fee 581 each time, to (3) obtain KYC information associated with a reserve to prove 582 the identity of the person sending an invoice to the payer, and to (4) close a 583 reserve before it would naturally expire and possibly (5) wire the funds to a 584 designated account. 585 586 .. note:: 587 588 This section is about a proposed API. It is not implemented. See also DD 31. 589 590 .. include:: exchange/post-reserves-RESERVE_PUB-open.rst 591 592 .. include:: exchange/get-reserves-RESERVE_PUB-attest.rst 593 594 .. include:: exchange/post-reserves-RESERVE_PUB-attest.rst 595 596 .. include:: exchange/post-reserves-RESERVE_PUB-close.rst 597 598 .. _delete-reserve: 599 600 .. include:: exchange/delete-reserves-RESERVE_PUB.rst