get-keys.rst (24018B)
1 .. http:get:: /keys 2 3 Get a list of all denomination keys offered by the exchange, 4 as well as the exchange's current online signing key. 5 6 **Request:** 7 8 :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. 9 10 **Response:** 11 12 :http:statuscode:`200 OK`: 13 The exchange responds with a `ExchangeKeysResponse` object. This request should 14 virtually always be successful. It only fails if the exchange is misconfigured or 15 has not yet been provisioned with key signatures via ``taler-exchange-offline``. 16 :http:statuscode:`400 Bad Request`: 17 A query parameter is malformed. 18 This response comes with a standard `ErrorDetail` response with 19 a code of ``TALER_EC_GENERIC_PARAMETER_MALFORMED``. 20 :http:statuscode:`502 Bad Gateway`: 21 A denomination or signing key helper is unavailable. 22 This response comes with a standard `ErrorDetail` response with 23 a code of ``TALER_EC_EXCHANGE_DENOMINATION_HELPER_UNAVAILABLE`` or 24 ``TALER_EC_EXCHANGE_SIGNKEY_HELPER_UNAVAILABLE``. 25 :http:statuscode:`500 Internal Server Error`: 26 The server experienced an internal error. 27 This response comes with a standard `ErrorDetail` response with 28 a code of ``TALER_EC_GENERIC_JSON_ALLOCATION_FAILURE``. 29 :http:statuscode:`503 Service Unavailable`: 30 The exchange has no valid denomination keys available. 31 This response comes with a standard `ErrorDetail` response with 32 a code of ``TALER_EC_EXCHANGE_GENERIC_KEYS_MISSING``. 33 34 **Details:** 35 36 .. ts:def:: ExchangeKeysResponse 37 38 interface ExchangeKeysResponse { 39 // libtool-style representation of the Exchange protocol version, see 40 // https://www.gnu.org/software/libtool/manual/html_node/Versioning.html#Versioning 41 // The format is "current:revision:age". 42 version: string; 43 44 // The exchange's base URL. 45 base_url: string; 46 47 // The exchange's currency or asset unit. 48 currency: string; 49 50 // Shopping URL where users may find shops that accept 51 // digital cash issued by this exchange. 52 // @since protocol **v21**. 53 shopping_url?: string; 54 55 // Instructs wallets to use certain bank-specific 56 // language (for buttons) and/or other UI/UX customization 57 // for compliance with the rules of that bank. 58 // The specific customizations to apply are done on a per-wallet 59 // basis as requested by the specific bank. They only 60 // apply when it is clear that the wallet is using digital 61 // cash from that bank. This is an advisory option, not 62 // all wallets must support all compliance languages. 63 // @since protocol **v24**. 64 bank_compliance_language?: string; 65 66 // How wallets should render this currency. 67 currency_specification: CurrencySpecification; 68 69 // Small(est?) amount that can likely be transferred to 70 // the exchange. Should be the default amount for KYC 71 // authentication wire transfers to this exchange. 72 // @since protocol **v21**. Mandatory since **v33**. 73 tiny_amount?: Amount; 74 75 // Absolute cost offset for the STEFAN curve used 76 // to (over) approximate fees payable by amount. 77 stefan_abs: Amount; 78 79 // Factor to multiply the logarithm of the amount 80 // with to (over) approximate fees payable by amount. 81 // Note that the total to be paid is first to be 82 // divided by the smallest denomination to obtain 83 // the value that the logarithm is to be taken of. 84 stefan_log: Amount; 85 86 // Linear cost factor for the STEFAN curve used 87 // to (over) approximate fees payable by amount. 88 // 89 // Note that this is a scalar, as it is multiplied 90 // with the actual amount. 91 stefan_lin: Float; 92 93 // Type of the asset. "fiat", "crypto", "regional" 94 // or "stock". Wallets should adjust their UI/UX 95 // based on this value. 96 asset_type: string; 97 98 // Array of wire accounts operated by the exchange for 99 // incoming wire transfers. 100 accounts: ExchangeWireAccount[]; 101 102 // Object mapping names of wire methods (i.e. "iban" or "x-taler-bank") 103 // to wire fees. 104 wire_fees: { method : AggregateTransferFee[] }; 105 106 // List of exchanges that this exchange is partnering 107 // with to enable wallet-to-wallet transfers. 108 wads: ExchangePartnerListEntry[]; 109 110 // Set to true if this exchange allows the use 111 // of reserves for rewards. 112 // @deprecated in protocol **v18**. 113 rewards_allowed: false; 114 115 // Set to true if this exchange has KYC enabled and thus 116 // requires KYC auth wire transfers prior to a first deposit. 117 // @since protocol **v24**. 118 kyc_enabled: boolean; 119 120 // Signal to the merchant backend that it should swap 121 // the terms-of-service and KYC auth authentication 122 // steps in the user experience. Optional, defaults 123 // to false if not given. 124 // @since protocol **v36**. 125 kyc_swap_tos_acceptance?: boolean; 126 127 // Set to TRUE if wallets should disable the direct deposit feature 128 // and deposits should only go via Taler merchant APIs. 129 // Mainly used for regional currency and event currency deployments 130 // where wallets are not eligible to deposit back into originating 131 // bank accounts and, because KYC is not enabled, wallets are thus 132 // likely to send money to nirvana instead of where users want it. 133 // @since protocol **v30**. 134 disable_direct_deposit: boolean; 135 136 // EdDSA master public key of the exchange, used to sign entries 137 // in ``denoms`` and ``signkeys``. 138 master_public_key: EddsaPublicKey; 139 140 // Relative duration until inactive reserves are closed; 141 // not signed (!), can change without notice. 142 reserve_closing_delay: RelativeTime; 143 144 // How long should a P2P push payment be valid by default. 145 // @since protocol **v35**. 146 default_p2p_push_expiration: RelativeTime; 147 148 // Threshold amounts beyond which wallet should 149 // trigger the KYC process of the issuing exchange. 150 // Optional option, if not given there is no limit. 151 // Currency must match ``currency``. 152 wallet_balance_limit_without_kyc?: Amount[]; 153 154 // Array of limits that apply to all accounts. 155 // All of the given limits will be hard limits. 156 // Wallets and merchants are expected to obey them 157 // and not even allow the user to cross them. 158 // @since protocol **v21**. 159 hard_limits: AccountLimit[]; 160 161 // Array of limits with a soft threshold of zero 162 // that apply to all accounts without KYC. 163 // Wallets and merchants are expected to trigger 164 // a KYC process before attempting any zero-limited 165 // operations. 166 // @since protocol **v21**. 167 zero_limits: ZeroLimitedOperation[]; 168 169 // Denominations offered by this exchange 170 denominations: DenomGroup[]; 171 172 // Compact EdDSA `signature` (binary-only) over the 173 // contatentation of all of the master_sigs (in reverse 174 // chronological order by group) in the arrays under 175 // "denominations". Signature of `TALER_ExchangeKeySetPS` 176 exchange_sig: EddsaSignature; 177 178 // Public EdDSA key of the exchange that was used to generate the signature. 179 // Should match one of the exchange's signing keys from ``signkeys``. It is given 180 // explicitly as the client might otherwise be confused by clock skew as to 181 // which signing key was used for the ``exchange_sig``. 182 exchange_pub: EddsaPublicKey; 183 184 // Denominations for which the exchange currently offers/requests recoup. 185 recoup: RecoupDenoms[]; 186 187 // Array of globally applicable fees by time range. 188 global_fees: GlobalFees[]; 189 190 // The date when the denomination keys were last updated. 191 list_issue_date: Timestamp; 192 193 // Auditors of the exchange. 194 auditors: AuditorKeys[]; 195 196 // The exchange's signing keys. 197 signkeys: SignKey[]; 198 199 // Optional field with a dictionary of (name, object) pairs defining the 200 // supported and enabled extensions, such as ``age_restriction``. 201 extensions?: { name: ExtensionManifest }; 202 203 // Signature by the exchange master key of the SHA-256 hash of the 204 // normalized JSON-object of field extensions, if it was set. 205 // The signature has purpose TALER_SIGNATURE_MASTER_EXTENSIONS. 206 extensions_sig?: EddsaSignature; 207 208 } 209 210 The specification for the account object is: 211 212 .. ts:def:: ExchangeWireAccount 213 214 interface ExchangeWireAccount { 215 // Full ``payto://`` URI identifying the account and wire method 216 payto_uri: string; 217 218 // URI to convert amounts from or to the currency used by 219 // this wire account of the exchange. Missing if no 220 // conversion is applicable. 221 conversion_url?: string; 222 223 // Open banking gateway base URL where wallets can 224 // initiate wire transfers to withdraw 225 // digital cash from this exchange. 226 // @since protocol **v34**. 227 open_banking_gateway?: string; 228 229 // Wire transfer gateway base URL where wallets and merchants can 230 // request (short) wire transfer subjects to wire funds to this 231 // exchange without having to encode the full public key. 232 // @since protocol **v34**. 233 prepared_transfer_url?: string; 234 235 // Restrictions that apply to bank accounts that would send 236 // funds to the exchange (crediting this exchange bank account). 237 // Optional, empty array for unrestricted. 238 credit_restrictions: AccountRestriction[]; 239 240 // Restrictions that apply to bank accounts that would receive 241 // funds from the exchange (debiting this exchange bank account). 242 // Optional, empty array for unrestricted. 243 debit_restrictions: AccountRestriction[]; 244 245 // Signature using the exchange's offline key over 246 // a `TALER_MasterWireDetailsPS` 247 // with purpose ``TALER_SIGNATURE_MASTER_WIRE_DETAILS``. 248 master_sig: EddsaSignature; 249 250 // Display label wallets should use to show this 251 // bank account. 252 // @since protocol **v19**. 253 bank_label?: string; 254 255 // *Signed* integer with the display priority for 256 // this bank account. Optional, 0 if missing. 257 // @since protocol **v19**. 258 priority?: Integer; 259 260 } 261 262 .. ts:def:: AccountRestriction 263 264 type AccountRestriction = 265 | RegexAccountRestriction 266 | DenyAllAccountRestriction 267 268 .. ts:def:: DenyAllAccountRestriction 269 270 // Account restriction that disables this type of 271 // account for the indicated operation categorically. 272 interface DenyAllAccountRestriction { 273 274 type: "deny"; 275 } 276 277 .. ts:def:: RegexAccountRestriction 278 279 // Accounts interacting with this type of account 280 // restriction must have a normalized payto://-URI matching 281 // the given regex. 282 interface RegexAccountRestriction { 283 284 type: "regex"; 285 286 // Regular expression that the payto://-URI of the 287 // partner account must follow. The regular expression 288 // should follow posix-egrep, but without support for character 289 // classes, GNU extensions, back-references or intervals. See 290 // https://www.gnu.org/software/findutils/manual/html_node/find_html/posix_002degrep-regular-expression-syntax.html 291 // for a description of the posix-egrep syntax. Applications 292 // may support regexes with additional features, but exchanges 293 // must not use such regexes. 294 payto_regex: string; 295 296 // Hint for a human to understand the restriction 297 // (that is hopefully easier to comprehend than the regex itself). 298 human_hint: string; 299 300 // Map from IETF BCP 47 language tags to localized 301 // human hints. 302 human_hint_i18n?: { [lang_tag: string]: string }; 303 304 } 305 306 .. ts:def:: ZeroLimitedOperation 307 308 interface ZeroLimitedOperation { 309 310 // Operation that is limited to an amount of 311 // zero until the client has passed some KYC check. 312 // Must be one of "WITHDRAW", "DEPOSIT", 313 // (p2p) "MERGE", (wallet) "BALANCE", 314 // (reserve) "CLOSE", "AGGREGATE", 315 // "TRANSACTION" or "REFUND". 316 operation_type: string; 317 318 } 319 320 321 .. ts:def:: AccountLimit 322 323 interface AccountLimit { 324 325 // Operation that is limited. 326 // Must be one of "WITHDRAW", "DEPOSIT", 327 // (p2p) "MERGE", (wallet) "BALANCE", 328 // (reserve) "CLOSE", "AGGREGATE", 329 // "TRANSACTION" or "REFUND". 330 operation_type: string; 331 332 // Timeframe during which the limit applies. 333 // Not applicable for all operation_types 334 // (but always present in this object anyway). 335 timeframe: RelativeTime; 336 337 // Maximum amount allowed during the given timeframe. 338 // Zero if the operation is simply forbidden. 339 threshold: Amount; 340 341 // True if this is a soft limit that could be raised 342 // by passing KYC checks. Clients *may* deliberately 343 // try to cross limits and trigger measures resulting 344 // in 451 responses to begin KYC processes. 345 // Clients that are aware of hard limits *should* 346 // inform users about the hard limit and prevent flows 347 // in the UI that would cause violations of hard limits. 348 // Made optional in **v21** with a default of 'false' if missing. 349 soft_limit?: boolean; 350 } 351 352 .. ts:def:: GlobalFees 353 354 interface GlobalFees { 355 356 // What date (inclusive) does these fees go into effect? 357 start_date: Timestamp; 358 359 // What date (exclusive) does this fees stop going into effect? 360 end_date: Timestamp; 361 362 // Account history fee, charged when a user wants to 363 // obtain a reserve/account history. 364 history_fee: Amount; 365 366 // Annual fee charged for having an open account at the 367 // exchange. Charged to the account. If the account 368 // balance is insufficient to cover this fee, the account 369 // is automatically deleted/closed. (Note that the exchange 370 // will keep the account history around for longer for 371 // regulatory reasons.) 372 account_fee: Amount; 373 374 // Purse fee, charged only if a purse is abandoned 375 // and was not covered by the account limit. 376 purse_fee: Amount; 377 378 // How long will the exchange preserve the account history? 379 // After an account was deleted/closed, the exchange will 380 // retain the account history for legal reasons until this time. 381 history_expiration: RelativeTime; 382 383 // Non-negative number of concurrent purses that any 384 // account holder is allowed to create without having 385 // to pay the purse_fee. 386 purse_account_limit: Integer; 387 388 // How long does an exchange keep a purse around after a purse 389 // has expired (or been successfully merged)? A 'GET' request 390 // for a purse will succeed until the purse expiration time 391 // plus this value. 392 purse_timeout: RelativeTime; 393 394 // Signature of `TALER_GlobalFeesPS`. 395 master_sig: EddsaSignature; 396 397 } 398 399 .. ts:def:: DenomGroup 400 401 type DenomGroup = 402 | DenomGroupRsa 403 | DenomGroupCs 404 | DenomGroupRsaAgeRestricted 405 | DenomGroupCsAgeRestricted; 406 407 .. ts:def:: DenomGroupRsa 408 409 interface DenomGroupRsa extends DenomGroupCommon { 410 cipher: "RSA"; 411 412 denoms: ({ 413 rsa_pub: RsaPublicKey; 414 } & DenomCommon)[]; 415 } 416 417 .. ts:def:: DenomGroupCs 418 419 interface DenomGroupCs extends DenomGroupCommon { 420 cipher: "CS"; 421 422 denoms: ({ 423 cs_pub: Cs25519Point; 424 } & DenomCommon)[]; 425 } 426 427 .. ts:def:: DenomGroupRsaAgeRestricted 428 429 interface DenomGroupRsaAgeRestricted extends DenomGroupCommon { 430 cipher: "RSA+age_restricted"; 431 age_mask: AgeMask; 432 433 denoms: ({ 434 rsa_pub: RsaPublicKey; 435 } & DenomCommon)[]; 436 } 437 438 .. ts:def:: DenomGroupCsAgeRestricted 439 440 interface DenomGroupCsAgeRestricted extends DenomGroupCommon { 441 cipher: "CS+age_restricted"; 442 age_mask: AgeMask; 443 444 denoms: ({ 445 cs_pub: Cs25519Point; 446 } & DenomCommon)[]; 447 } 448 449 .. ts:def:: DenomGroupCommon 450 451 // Common attributes for all denomination groups 452 interface DenomGroupCommon { 453 // How much are coins of this denomination worth? 454 value: Amount; 455 456 // Fee charged by the exchange for withdrawing a coin of this denomination. 457 fee_withdraw: Amount; 458 459 // Fee charged by the exchange for depositing a coin of this denomination. 460 fee_deposit: Amount; 461 462 // Fee charged by the exchange for refreshing a coin of this denomination. 463 fee_refresh: Amount; 464 465 // Fee charged by the exchange for refunding a coin of this denomination. 466 fee_refund: Amount; 467 468 } 469 470 .. ts:def:: DenomCommon 471 472 interface DenomCommon { 473 // Signature of `TALER_DenominationKeyValidityPS`. 474 master_sig: EddsaSignature; 475 476 // When does the denomination key become valid? 477 stamp_start: Timestamp; 478 479 // When is it no longer possible to withdraw coins 480 // of this denomination? Note that while this option 481 // is given per denomination, all concurrently active 482 // denominations (of the same cipher type) 483 // will have exactly the same withdraw 484 // expiration time. Thus, the wallet can be sure what 485 // is the smallest denomination being offered at any 486 // particular point in time, and not worry about the 487 // exchange having merely failed to sign the key of 488 // only the smallest denomination unit. 489 stamp_expire_withdraw: Timestamp; 490 491 // When is it no longer possible to deposit coins 492 // of this denomination? 493 stamp_expire_deposit: Timestamp; 494 495 // Timestamp indicating by when legal disputes relating to these coins must 496 // be settled, as the exchange will afterwards destroy its evidence relating to 497 // transactions involving this coin. 498 stamp_expire_legal: Timestamp; 499 500 // Set to 'true' if the exchange somehow "lost" 501 // the private key. The denomination was not 502 // necessarily revoked, but still cannot be used 503 // to withdraw coins at this time (theoretically, 504 // the private key could be recovered in the 505 // future; coins signed with the private key 506 // remain valid). 507 lost?: boolean; 508 } 509 510 Fees for any of the operations can be zero, but the fields must still be 511 present. The currency of the ``fee_deposit``, ``fee_refresh`` and ``fee_refund`` must match the 512 currency of the ``value``. Theoretically, the ``fee_withdraw`` could be in a 513 different currency, but this is not currently supported by the 514 implementation. 515 516 .. ts:def:: RecoupDenoms 517 518 interface RecoupDenoms { 519 // Hash of the public key of the denomination that is being revoked under 520 // emergency protocol (see ``/recoup``). 521 h_denom_pub: HashCode; 522 523 // We do not include any signature here, as the primary use-case for 524 // this emergency involves the exchange having lost its signing keys, 525 // so such a signature here would be pretty worthless. However, the 526 // exchange will not honor ``/recoup`` requests unless they are for 527 // denomination keys listed here. 528 } 529 530 A signing key in the ``signkeys`` list is a JSON object with the following fields: 531 532 .. ts:def:: SignKey 533 534 interface SignKey { 535 // The actual exchange's EdDSA signing public key. 536 key: EddsaPublicKey; 537 538 // Initial validity date for the signing key. 539 stamp_start: Timestamp; 540 541 // Date when the exchange will stop using the signing key, allowed to overlap 542 // slightly with the next signing key's validity to allow for clock skew. 543 stamp_expire: Timestamp; 544 545 // Date when all signatures made by the signing key expire and should 546 // henceforth no longer be considered valid in legal disputes. 547 stamp_end: Timestamp; 548 549 // Signature over ``key`` and ``stamp_expire`` by the exchange master key. 550 // Signature of `TALER_ExchangeSigningKeyValidityPS`. 551 // Must have purpose ``TALER_SIGNATURE_MASTER_SIGNING_KEY_VALIDITY``. 552 master_sig: EddsaSignature; 553 } 554 555 An entry in the ``auditors`` list is a JSON object with the following fields: 556 557 .. ts:def:: AuditorKeys 558 559 interface AuditorKeys { 560 // The auditor's EdDSA signing public key. 561 auditor_pub: EddsaPublicKey; 562 563 // The auditor's URL. 564 auditor_url: string; 565 566 // The auditor's name (for humans). 567 auditor_name: string; 568 569 // An array of denomination keys the auditor affirms with its signature. 570 // Note that the message only includes the hash of the public key, while the 571 // signature is actually over the expanded information including expiration 572 // times and fees. The exact format is described below. 573 denomination_keys: AuditorDenominationKey[]; 574 } 575 576 .. ts:def:: AuditorDenominationKey 577 578 interface AuditorDenominationKey { 579 // Hash of the public RSA key used to sign coins of the respective 580 // denomination. Note that the auditor's signature covers more than just 581 // the hash, but this other information is already provided in ``denoms`` and 582 // thus not repeated here. 583 denom_pub_h: HashCode; 584 585 // Signature of `TALER_ExchangeKeyValidityPS`. 586 auditor_sig: EddsaSignature; 587 } 588 589 The same auditor may appear multiple times in the array for different subsets 590 of denomination keys, and the same denomination key hash may be listed 591 multiple times for the same or different auditors. The wallet or merchant 592 just should check that the denomination keys they use are in the set for at 593 least one of the auditors that they accept. 594 595 .. note:: 596 597 Both the individual denominations *and* the denomination list is signed, 598 allowing customers to prove that they received an inconsistent list. 599 600 Aggregate wire transfer fees representing the fees the exchange 601 charges per wire transfer to a merchant must be specified as an 602 array in all wire transfer response objects under ``fees``. The 603 respective array contains objects with the following members: 604 605 .. ts:def:: AggregateTransferFee 606 607 interface AggregateTransferFee { 608 // Per transfer wire transfer fee. 609 wire_fee: Amount; 610 611 // Per transfer closing fee. 612 closing_fee: Amount; 613 614 // What date (inclusive) does this fee go into effect? 615 // The different fees must cover the full time period in which 616 // any of the denomination keys are valid without overlap. 617 start_date: Timestamp; 618 619 // What date (exclusive) does this fee stop going into effect? 620 // The different fees must cover the full time period in which 621 // any of the denomination keys are valid without overlap. 622 end_date: Timestamp; 623 624 // Signature of `TALER_MasterWireFeePS` with 625 // purpose ``TALER_SIGNATURE_MASTER_WIRE_FEES``. 626 sig: EddsaSignature; 627 } 628 629 .. ts:def:: ExchangePartnerListEntry 630 631 interface ExchangePartnerListEntry { 632 // Base URL of the partner exchange. 633 partner_base_url: string; 634 635 // Public master key of the partner exchange. 636 partner_master_pub: EddsaPublicKey; 637 638 // Per exchange-to-exchange transfer (wad) fee. 639 wad_fee: Amount; 640 641 // Exchange-to-exchange wad (wire) transfer frequency. 642 wad_frequency: RelativeTime; 643 644 // When did this partnership begin (under these conditions)? 645 start_date: Timestamp; 646 647 // How long is this partnership expected to last? 648 end_date: Timestamp; 649 650 // Signature using the exchange's offline key over 651 // `TALER_WadPartnerSignaturePS` 652 // with purpose ``TALER_SIGNATURE_MASTER_PARTNER_DETAILS``. 653 master_sig: EddsaSignature; 654 }