taler-docs

Documentation for GNU Taler components, APIs and protocols
Log | Files | Refs | README | LICENSE

get-keys.rst (23590B)


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