get-keys.rst (24987B)
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 // Threshold amounts beyond which wallet should 169 // trigger the KYC process of the issuing exchange. 170 // Optional option, if not given there is no limit. 171 // Currency must match ``currency``. 172 wallet_balance_limit_without_kyc?: Amount[]; 173 174 // Array of limits that apply to all accounts. 175 // All of the given limits will be hard limits. 176 // Wallets and merchants are expected to obey them 177 // and not even allow the user to cross them. 178 // @since protocol **v21**. 179 hard_limits: AccountLimit[]; 180 181 // Array of limits with a soft threshold of zero 182 // that apply to all accounts without KYC. 183 // Wallets and merchants are expected to trigger 184 // a KYC process before attempting any zero-limited 185 // operations. 186 // @since protocol **v21**. 187 zero_limits: ZeroLimitedOperation[]; 188 189 // Denominations offered by this exchange 190 denominations: DenomGroup[]; 191 192 // Compact EdDSA `signature` (binary-only) over the 193 // contatentation of all of the master_sigs (in reverse 194 // chronological order by group) in the arrays under 195 // "denominations". Signature of `TALER_ExchangeKeySetPS` 196 exchange_sig: EddsaSignature; 197 198 // Public EdDSA key of the exchange that was used to generate the signature. 199 // Should match one of the exchange's signing keys from ``signkeys``. It is given 200 // explicitly as the client might otherwise be confused by clock skew as to 201 // which signing key was used for the ``exchange_sig``. 202 exchange_pub: EddsaPublicKey; 203 204 // Denominations for which the exchange currently offers/requests recoup. 205 recoup: RecoupDenoms[]; 206 207 // Array of globally applicable fees by time range. 208 global_fees: GlobalFees[]; 209 210 // The date when the denomination keys were last updated. 211 list_issue_date: Timestamp; 212 213 // Auditors of the exchange. 214 auditors: AuditorKeys[]; 215 216 // The exchange's signing keys. 217 signkeys: SignKey[]; 218 219 } 220 221 The specification for the account object is: 222 223 .. ts:def:: ExchangeWireAccount 224 225 interface ExchangeWireAccount { 226 // Full ``payto://`` URI identifying the account and wire method 227 payto_uri: string; 228 229 // URI to convert amounts from or to the currency used by 230 // this wire account of the exchange. Missing if no 231 // conversion is applicable. 232 conversion_url?: WebURL; 233 234 // Open banking gateway base URL where wallets can 235 // initiate wire transfers to withdraw 236 // digital cash from this exchange. 237 // @since protocol **v34**. 238 open_banking_gateway?: WebURL; 239 240 // Wire transfer gateway base URL where wallets and merchants can 241 // request (short) wire transfer subjects to wire funds to this 242 // exchange without having to encode the full public key. 243 // @since protocol **v34**. 244 prepared_transfer_url?: WebURL; 245 246 // Restrictions that apply to bank accounts that would send 247 // funds to the exchange (crediting this exchange bank account). 248 // Optional, empty array for unrestricted. 249 credit_restrictions: AccountRestriction[]; 250 251 // Restrictions that apply to bank accounts that would receive 252 // funds from the exchange (debiting this exchange bank account). 253 // Optional, empty array for unrestricted. 254 debit_restrictions: AccountRestriction[]; 255 256 // Signature using the exchange's offline key over 257 // a `TALER_MasterWireDetailsPS` 258 // with purpose ``TALER_SIGNATURE_MASTER_WIRE_DETAILS``. 259 master_sig: EddsaSignature; 260 261 // Display label wallets should use to show this 262 // bank account. 263 // @since protocol **v19**. 264 bank_label?: string; 265 266 // *Signed* integer with the display priority for 267 // this bank account. Optional, 0 if missing. 268 // @since protocol **v19**. 269 priority?: Integer; 270 271 } 272 273 .. ts:def:: AccountRestriction 274 275 type AccountRestriction = 276 | RegexAccountRestriction 277 | DenyAllAccountRestriction 278 279 .. ts:def:: DenyAllAccountRestriction 280 281 // Account restriction that disables this type of 282 // account for the indicated operation categorically. 283 interface DenyAllAccountRestriction { 284 285 type: "deny"; 286 } 287 288 .. ts:def:: RegexAccountRestriction 289 290 // Accounts interacting with this type of account 291 // restriction must have a normalized payto://-URI matching 292 // the given regex. 293 interface RegexAccountRestriction { 294 295 type: "regex"; 296 297 // Regular expression that the payto://-URI of the 298 // partner account must follow. The regular expression 299 // should follow posix-egrep, but without support for character 300 // classes, GNU extensions, back-references or intervals. See 301 // https://www.gnu.org/software/findutils/manual/html_node/find_html/posix_002degrep-regular-expression-syntax.html 302 // for a description of the posix-egrep syntax. Applications 303 // may support regexes with additional features, but exchanges 304 // must not use such regexes. 305 payto_regex: string; 306 307 // Hint for a human to understand the restriction 308 // (that is hopefully easier to comprehend than the regex itself). 309 human_hint: string; 310 311 // Map from IETF BCP 47 language tags to localized 312 // human hints. 313 human_hint_i18n?: { [lang_tag: string]: string }; 314 315 } 316 317 .. ts:def:: ZeroLimitedOperation 318 319 interface ZeroLimitedOperation { 320 321 // Operation that is limited to an amount of 322 // zero until the client has passed some KYC check. 323 // Must be one of "WITHDRAW", "DEPOSIT", 324 // (p2p) "MERGE", (wallet) "BALANCE", 325 // (reserve) "CLOSE", "AGGREGATE", 326 // "TRANSACTION" or "REFUND". 327 operation_type: string; 328 329 } 330 331 332 .. ts:def:: AccountLimit 333 334 interface AccountLimit { 335 336 // Operation that is limited. 337 // Must be one of "WITHDRAW", "DEPOSIT", 338 // (p2p) "MERGE", (wallet) "BALANCE", 339 // (reserve) "CLOSE", "AGGREGATE", 340 // "TRANSACTION" or "REFUND". 341 operation_type: string; 342 343 // Timeframe during which the limit applies. 344 // Not applicable for all operation_types 345 // (but always present in this object anyway). 346 timeframe: RelativeTime; 347 348 // Maximum amount allowed during the given timeframe. 349 // Zero if the operation is simply forbidden. 350 threshold: Amount; 351 352 // True if this is a soft limit that could be raised 353 // by passing KYC checks. Clients *may* deliberately 354 // try to cross limits and trigger measures resulting 355 // in 451 responses to begin KYC processes. 356 // Clients that are aware of hard limits *should* 357 // inform users about the hard limit and prevent flows 358 // in the UI that would cause violations of hard limits. 359 // Made optional in **v21** with a default of 'false' if missing. 360 soft_limit?: boolean; 361 } 362 363 .. ts:def:: GlobalFees 364 365 interface GlobalFees { 366 367 // What date (inclusive) does these fees go into effect? 368 start_date: Timestamp; 369 370 // What date (exclusive) does this fees stop going into effect? 371 end_date: Timestamp; 372 373 // Account history fee, charged when a user wants to 374 // obtain a reserve/account history. 375 history_fee: Amount; 376 377 // Annual fee charged for having an open account at the 378 // exchange. Charged to the account. If the account 379 // balance is insufficient to cover this fee, the account 380 // is automatically deleted/closed. (Note that the exchange 381 // will keep the account history around for longer for 382 // regulatory reasons.) 383 account_fee: Amount; 384 385 // Purse fee, charged only if a purse is abandoned 386 // and was not covered by the account limit. 387 purse_fee: Amount; 388 389 // How long will the exchange preserve the account history? 390 // After an account was deleted/closed, the exchange will 391 // retain the account history for legal reasons until this time. 392 history_expiration: RelativeTime; 393 394 // Non-negative number of concurrent purses that any 395 // account holder is allowed to create without having 396 // to pay the purse_fee. 397 purse_account_limit: Integer; 398 399 // How long does an exchange keep a purse around after a purse 400 // has expired (or been successfully merged)? A 'GET' request 401 // for a purse will succeed until the purse expiration time 402 // plus this value. 403 purse_timeout: RelativeTime; 404 405 // Signature of `TALER_GlobalFeesPS`. 406 master_sig: EddsaSignature; 407 408 } 409 410 .. ts:def:: DenomGroup 411 412 type DenomGroup = 413 | DenomGroupRsa 414 | DenomGroupCs 415 | DenomGroupRsaAgeRestricted 416 | DenomGroupCsAgeRestricted; 417 418 .. ts:def:: DenomGroupRsa 419 420 interface DenomGroupRsa extends DenomGroupCommon { 421 cipher: "RSA"; 422 423 denoms: ({ 424 rsa_pub: RsaPublicKey; 425 } & DenomCommon)[]; 426 } 427 428 .. ts:def:: DenomGroupCs 429 430 interface DenomGroupCs extends DenomGroupCommon { 431 cipher: "CS"; 432 433 denoms: ({ 434 cs_pub: Cs25519Point; 435 } & DenomCommon)[]; 436 } 437 438 .. ts:def:: DenomGroupRsaAgeRestricted 439 440 interface DenomGroupRsaAgeRestricted extends DenomGroupCommon { 441 cipher: "RSA+age_restricted"; 442 age_mask: AgeMask; 443 444 denoms: ({ 445 rsa_pub: RsaPublicKey; 446 } & DenomCommon)[]; 447 } 448 449 .. ts:def:: DenomGroupCsAgeRestricted 450 451 interface DenomGroupCsAgeRestricted extends DenomGroupCommon { 452 cipher: "CS+age_restricted"; 453 age_mask: AgeMask; 454 455 denoms: ({ 456 cs_pub: Cs25519Point; 457 } & DenomCommon)[]; 458 } 459 460 .. ts:def:: DenomGroupCommon 461 462 // Common attributes for all denomination groups 463 interface DenomGroupCommon { 464 // How much are coins of this denomination worth? 465 value: Amount; 466 467 // Fee charged by the exchange for withdrawing a coin of this denomination. 468 fee_withdraw: Amount; 469 470 // Fee charged by the exchange for depositing a coin of this denomination. 471 fee_deposit: Amount; 472 473 // Fee charged by the exchange for refreshing a coin of this denomination. 474 fee_refresh: Amount; 475 476 // Fee charged by the exchange for refunding a coin of this denomination. 477 fee_refund: Amount; 478 479 } 480 481 .. ts:def:: DenomCommon 482 483 interface DenomCommon { 484 // Signature of `TALER_DenominationKeyValidityPS`. 485 master_sig: EddsaSignature; 486 487 // When does the denomination key become valid? 488 stamp_start: Timestamp; 489 490 // When is it no longer possible to withdraw coins 491 // of this denomination? Note that while this option 492 // is given per denomination, all concurrently active 493 // denominations (of the same cipher type) 494 // will have exactly the same withdraw 495 // expiration time. Thus, the wallet can be sure what 496 // is the smallest denomination being offered at any 497 // particular point in time, and not worry about the 498 // exchange having merely failed to sign the key of 499 // only the smallest denomination unit. 500 stamp_expire_withdraw: Timestamp; 501 502 // When is it no longer possible to deposit coins 503 // of this denomination? 504 stamp_expire_deposit: Timestamp; 505 506 // Timestamp indicating by when legal disputes relating to these coins must 507 // be settled, as the exchange will afterwards destroy its evidence relating to 508 // transactions involving this coin. 509 stamp_expire_legal: Timestamp; 510 511 // Set to 'true' if the exchange somehow "lost" 512 // the private key. The denomination was not 513 // necessarily revoked, but still cannot be used 514 // to withdraw coins at this time (theoretically, 515 // the private key could be recovered in the 516 // future; coins signed with the private key 517 // remain valid). 518 lost?: boolean; 519 } 520 521 Fees for any of the operations can be zero, but the fields must still be 522 present. The currency of the ``fee_deposit``, ``fee_refresh`` and ``fee_refund`` must match the 523 currency of the ``value``. Theoretically, the ``fee_withdraw`` could be in a 524 different currency, but this is not currently supported by the 525 implementation. 526 527 .. ts:def:: RecoupDenoms 528 529 interface RecoupDenoms { 530 // Hash of the public key of the denomination that is being revoked under 531 // emergency protocol (see ``/recoup``). 532 h_denom_pub: HashCode; 533 534 // We do not include any signature here, as the primary use-case for 535 // this emergency involves the exchange having lost its signing keys, 536 // so such a signature here would be pretty worthless. However, the 537 // exchange will not honor ``/recoup`` requests unless they are for 538 // denomination keys listed here. 539 } 540 541 A signing key in the ``signkeys`` list is a JSON object with the following fields: 542 543 .. ts:def:: SignKey 544 545 interface SignKey { 546 // The actual exchange's EdDSA signing public key. 547 key: EddsaPublicKey; 548 549 // Initial validity date for the signing key. 550 stamp_start: Timestamp; 551 552 // Date when the exchange will stop using the signing key, allowed to overlap 553 // slightly with the next signing key's validity to allow for clock skew. 554 stamp_expire: Timestamp; 555 556 // Date when all signatures made by the signing key expire and should 557 // henceforth no longer be considered valid in legal disputes. 558 stamp_end: Timestamp; 559 560 // Signature over ``key`` and ``stamp_expire`` by the exchange master key. 561 // Signature of `TALER_ExchangeSigningKeyValidityPS`. 562 // Must have purpose ``TALER_SIGNATURE_MASTER_SIGNING_KEY_VALIDITY``. 563 master_sig: EddsaSignature; 564 } 565 566 An entry in the ``auditors`` list is a JSON object with the following fields: 567 568 .. ts:def:: AuditorKeys 569 570 interface AuditorKeys { 571 // The auditor's EdDSA signing public key. 572 auditor_pub: EddsaPublicKey; 573 574 // The auditor's URL. 575 auditor_url: WebURL; 576 577 // The auditor's name (for humans). 578 auditor_name: string; 579 580 // An array of denomination keys the auditor affirms with its signature. 581 // Note that the message only includes the hash of the public key, while the 582 // signature is actually over the expanded information including expiration 583 // times and fees. The exact format is described below. 584 denomination_keys: AuditorDenominationKey[]; 585 } 586 587 .. ts:def:: AuditorDenominationKey 588 589 interface AuditorDenominationKey { 590 // Hash of the public RSA key used to sign coins of the respective 591 // denomination. Note that the auditor's signature covers more than just 592 // the hash, but this other information is already provided in ``denoms`` and 593 // thus not repeated here. 594 denom_pub_h: HashCode; 595 596 // Signature of `TALER_ExchangeKeyValidityPS`. 597 auditor_sig: EddsaSignature; 598 } 599 600 The same auditor may appear multiple times in the array for different subsets 601 of denomination keys, and the same denomination key hash may be listed 602 multiple times for the same or different auditors. The wallet or merchant 603 just should check that the denomination keys they use are in the set for at 604 least one of the auditors that they accept. 605 606 .. note:: 607 608 Both the individual denominations *and* the denomination list is signed, 609 allowing customers to prove that they received an inconsistent list. 610 611 Aggregate wire transfer fees representing the fees the exchange 612 charges per wire transfer to a merchant must be specified as an 613 array in all wire transfer response objects under ``fees``. The 614 respective array contains objects with the following members: 615 616 .. ts:def:: AggregateTransferFee 617 618 interface AggregateTransferFee { 619 // Per transfer wire transfer fee. 620 wire_fee: Amount; 621 622 // Per transfer closing fee. 623 closing_fee: Amount; 624 625 // What date (inclusive) does this fee go into effect? 626 // The different fees must cover the full time period in which 627 // any of the denomination keys are valid without overlap. 628 start_date: Timestamp; 629 630 // What date (exclusive) does this fee stop going into effect? 631 // The different fees must cover the full time period in which 632 // any of the denomination keys are valid without overlap. 633 end_date: Timestamp; 634 635 // Signature of `TALER_MasterWireFeePS` with 636 // purpose ``TALER_SIGNATURE_MASTER_WIRE_FEES``. 637 sig: EddsaSignature; 638 } 639 640 .. ts:def:: ExchangePartnerListEntry 641 642 interface ExchangePartnerListEntry { 643 // Base URL of the partner exchange. 644 partner_base_url: WebURL; 645 646 // Public master key of the partner exchange. 647 partner_master_pub: EddsaPublicKey; 648 649 // Per exchange-to-exchange transfer (wad) fee. 650 wad_fee: Amount; 651 652 // Exchange-to-exchange wad (wire) transfer frequency. 653 wad_frequency: RelativeTime; 654 655 // When did this partnership begin (under these conditions)? 656 start_date: Timestamp; 657 658 // How long is this partnership expected to last? 659 end_date: Timestamp; 660 661 // Signature using the exchange's offline key over 662 // `TALER_WadPartnerSignaturePS` 663 // with purpose ``TALER_SIGNATURE_MASTER_PARTNER_DETAILS``. 664 master_sig: EddsaSignature; 665 }