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