diff options
Diffstat (limited to 'core/api-corebank.rst')
-rw-r--r-- | core/api-corebank.rst | 1261 |
1 files changed, 1261 insertions, 0 deletions
diff --git a/core/api-corebank.rst b/core/api-corebank.rst new file mode 100644 index 00000000..4a0288a4 --- /dev/null +++ b/core/api-corebank.rst @@ -0,0 +1,1261 @@ +.. + This file is part of GNU TALER. + + Copyright (C) 2014-2024 Taler Systems SA + + TALER is free software; you can redistribute it and/or modify it under the + terms of the GNU Affero General Public License as published by the Free Software + Foundation; either version 2.1, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License along with + TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> + +.. target audience: developer, core developer + +.. _corebank-api: + +==================== +Taler Core Bank API +==================== + +.. contents:: Table of Contents + :local: + +Introduction +------------ + +The Libeufin bank provides a minimal core banking system. In addition to that, +it provides features for local/regional currencies. + +Authentication +-------------- + +Some requests require the client to authenticate via HTTP Basic auth (RFC 7617) +or using a bearer token which can be obtained or refreshed from the +``/accounts/$USERNAME/token`` endpoint. +When using Basic authentication, the user-id must be the bank +username, and the password the password for the corresponding user. + +Another way to obtain a login token is by manually configuring it for certain +endpoints. For example, the exchange could give an auditor read-only access to +the taler-wire-gateway facade via such a manually configured access token. + +The ``admin`` user is a special, hard-coded username. Some requests require the +client to authenticate as the admin. + +.. http:post:: /accounts/$USERNAME/token + + See :ref:`DD 48 token endpoint <dd48-token>`. + + +Bank Web UI +----------- + +The web UI for the bank is typically served under ``/``. + +Config +------ + +.. http:get:: /config + + Return the protocol version and configuration information about the bank. + This specification corresponds to ``current`` protocol being version **4**. + + **Response:** + + :http:statuscode:`200 OK`: + Response is a `Config`. + + **Details:** + + .. ts:def:: Config + + interface Config { + // Name of the API. + name: "taler-corebank"; + + // libtool-style representation of the Bank protocol version, see + // https://www.gnu.org/software/libtool/manual/html_node/Versioning.html#Versioning + // The format is "current:revision:age". + version: string; + + // Bank display name to be used in user interfaces. + // For consistency use "Taler Bank" if missing. + // @since v4, will become mandatory in the next version. + bank_name?: string; + + // Advertised base URL to use when you sharing an URL with another + // program. + // @since v4. + base_url?: string; + + // If 'true' the server provides local currency conversion support + // If 'false' some parts of the API are not supported and return 501 + allow_conversion: boolean; + + // If 'true' anyone can register + // If 'false' only admin can + allow_registrations: boolean; + + // If 'true' account can delete themselves + // If 'false' only admin can delete accounts + allow_deletions: boolean; + + // If 'true' anyone can edit their name + // If 'false' only admin can + allow_edit_name: boolean; + + // If 'true' anyone can edit their cashout account + // If 'false' only admin can + allow_edit_cashout_payto_uri: boolean; + + // Default debt limit for newly created accounts + default_debit_threshold: Amount; + + // Currency used by this bank. + currency: string; + + // How the bank SPA should render this currency. + currency_specification: CurrencySpecification; + + // TAN channels supported by the server + supported_tan_channels: TanChannel[]; + + // Wire transfer type supported by the bank. + // Default to 'iban' is missing + // @since v4, will become mandatory in the next version. + wire_type?: string; + } + + +Account Management +------------------ + +.. _bank-account-register: + +.. http:post:: /accounts + + Create a new bank account. Depending on the configuration, + the account creation is self-serve, or only restricted to + the administrators. + + **Request:** + + .. ts:def:: RegisterAccountRequest + + interface RegisterAccountRequest { + // Username of the account + username: string; + + // Password of the account used for authentication + password: string; + + // Legal name of the account owner + name: string; + + // Make this account visible to anyone? + // Defaults to false. + is_public?: boolean; + + // Make this account a taler exchange account? + // If true: + // - incoming transactions to the account that do not + // have a valid reserve public key are automatically + // - the account provides the taler-wire-gateway-api endpoints + // Defaults to false. + is_taler_exchange?: boolean; + + // Addresses where to send the TAN for protected operations. + contact_data?: ChallengeContactData; + + // IBAN 'payto' URI of a fiat bank account with a 'receiver-name' parameter. + // If 'receiver-name' is missing, ``name`` will be used instead. + // Payments will be sent to this bank account + // when the user wants to convert the regional currency + // back to fiat currency outside bank. + cashout_payto_uri?: string; + + // Internal payto URI of this bank account. + // Used mostly for testing, this field is ignored if the bank payment + // method is not IBAN. + payto_uri?: string; + + // If present, set the max debit allowed for this user + // Only admin can set this property. + debit_threshold?: Amount; + + // If present, enables 2FA and set the TAN channel used for challenges + // Only admin can set this property, other user can reconfig their account + // after creation. + tan_channel?: TanChannel; + } + + .. ts:def:: ChallengeContactData + + interface ChallengeContactData { + // E-Mail address + email?: EmailAddress; + + // Phone number. + phone?: PhoneNumber; + } + + + **Response:** + + :http:statuscode:`200 OK`: + Response is a `RegisterAccountResponse`. + :http:statuscode:`400 Bad request`: + Input data was invalid. For example, the client specified a invalid + phone number or e-mail address. + :http:statuscode:`401 Unauthorized`: + Invalid credentials or missing rights. + :http:statuscode:`409 Conflict`: + * ``TALER_EC_BANK_REGISTER_USERNAME_REUSE`` : username already used. + * ``TALER_EC_BANK_REGISTER_PAYTO_URI_REUSE`` : payto URI already used. + * ``TALER_EC_BANK_UNALLOWED_DEBIT`` : admin account does not have sufficient funds to grant bonus. + * ``TALER_EC_BANK_RESERVED_USERNAME_CONFLICT`` : a reserved username was attempted, like ``admin`` or ``bank`` + * ``TALER_EC_BANK_NON_ADMIN_PATCH_DEBT_LIMIT`` : a non-admin user has tried to create an account with a customer debt limit. + * ``TALER_EC_BANK_NON_ADMIN_SET_TAN_CHANNEL`` : a non-admin user has tried to create an account with 2fa. + * ``TALER_EC_BANK_TAN_CHANNEL_NOT_SUPPORTED``: ``tan_channel`` is not supported, check bank config to find supported ones. + * ``TALER_EC_BANK_MISSING_TAN_INFO``: the user did not share any contact data where to send the TAN via ``tan_channel``. + + **Details:** + + .. ts:def:: RegisterAccountResponse + + interface RegisterAccountResponse { + // Internal payto URI of this bank account. + internal_payto_uri: string; + } + +.. _delete-account: + +.. http:delete:: /accounts/$USERNAME + + Delete the account whose username is ``$USERNAME``. The deletion + succeeds only if the balance is *zero*. Typically only available to + the administrator, but can be configured to allow ordinary users too. + + **Response:** + + :http:statuscode:`202 Accepted`: + 2FA is required for this operation. This returns the `Challenge` response. + :http:statuscode:`204 No content`: + The account was successfully deleted. + :http:statuscode:`401 Unauthorized`: + Invalid credentials or missing rights. + :http:statuscode:`404 Not found`: + The account pointed by ``$USERNAME`` was not found. + :http:statuscode:`409 Conflict`: + * ``TALER_EC_BANK_RESERVED_USERNAME_CONFLICT`` : a reserved username was attempted, like ``admin`` or ``bank``. + * ``TALER_EC_BANK_ACCOUNT_BALANCE_NOT_ZERO``: the account balance was not zero. + +.. _account-reconfig: + +.. http:patch:: /accounts/$USERNAME + + Allows reconfiguring the account data of ``$USERNAME``. + + **Request:** + + .. ts:def:: AccountReconfiguration + + interface AccountReconfiguration { + // Addresses where to send the TAN for protected operations. + contact_data?: ChallengeContactData; + + // IBAN 'payto' URI of a fiat bank account with a 'receiver-name' parameter. + // If 'receiver-name' is missing, ``name`` will be used instead. + // Payments will be sent to this bank account + // when the user wants to convert the regional currency + // back to fiat currency outside bank. + // Only admin can change this property if not allowed in config + cashout_payto_uri?: string; + + // If present, change the legal name associated with $username. + // Only admin can change this property if not allowed in config + name?: string; + + // Make this account visible to anyone? + is_public?: boolean; + + // If present, change the max debit allowed for this user + // Only admin can change this property. + debit_threshold?: Amount; + + // If present, enables 2FA and set the TAN channel used for challenges + tan_channel?: TanChannel; + } + + **Response:** + + :http:statuscode:`202 Accepted`: + 2FA is required for this operation. This returns the `Challenge` response. + :http:statuscode:`204 No content`: + Operation successful. + :http:statuscode:`401 Unauthorized`: + Invalid credentials or missing rights. + :http:statuscode:`404 Not found`: + The account pointed by ``$USERNAME`` was not found. + :http:statuscode:`409 Conflict`: + * ``TALER_EC_BANK_NON_ADMIN_PATCH_LEGAL_NAME`` : a non-admin user has tried to change their legal name. + * ``TALER_EC_BANK_NON_ADMIN_PATCH_CASHOUT`` : a non-admin user has tried to change their cashout account. + * ``TALER_EC_BANK_NON_ADMIN_PATCH_DEBT_LIMIT`` : a non-admin user has tried to change their debt limit. + * ``TALER_EC_BANK_TAN_CHANNEL_NOT_SUPPORTED`` : ``tan_channel`` is not supported, check bank config to find supported ones. + * ``TALER_EC_BANK_MISSING_TAN_INFO`` : the user did not share any contact data where to send the TAN via ``tan_channel``. + + +.. _account-password-reconfig: + +.. http:patch:: /accounts/$USERNAME/auth + + Allows changing the account's password. + + + **Request:** + + .. ts:def:: AccountPasswordChange + + interface AccountPasswordChange { + // Old password. If present it need to match the current + // password before updating. + old_password?: string; + // New password. + new_password: string; + } + + **Response:** + + :http:statuscode:`202 Accepted`: + 2FA is required for this operation. This returns the `Challenge` response. + :http:statuscode:`204 No content`: + Operation successful. + :http:statuscode:`404 Not found`: + The account pointed by ``$USERNAME`` was not found. + :http:statuscode:`401 Unauthorized`: + Invalid credentials or missing rights. + :http:statuscode:`409 Conflict`: + * ``TALER_EC_BANK_NON_ADMIN_PATCH_MISSING_OLD_PASSWORD``: a non-admin user has tried to change their password whihout providing the current one. + * ``TALER_EC_BANK_PATCH_BAD_OLD_PASSWORD`` : provided old password does not match current password. + +.. _account-list: + +.. http:get:: /public-accounts + + Show those accounts whose histories are publicly visible. For example, + accounts from donation receivers. As such, this request is unauthenticated. + + + **Request:** + + :query delta: *Optional.* + Takes value of the form ``N (-N)``, so that at most ``N`` values strictly older (younger) than ``start`` are returned. Defaults to ``-20`` to return the last 20 entries. + :query start: *Optional.* + Row number threshold, see ``delta`` for its interpretation. Defaults to smallest or biggest row id possible according to ``delta`` sign. + :query filter_name: *Optional.* + Pattern to filter on the account legal name. Given + the filter 'foo', all the results will **contain** + 'foo' in their legal name. Without this option, + all the existing accounts are returned. + + **Response:** + + :http:statuscode:`200 OK`: + Response is a `PublicAccountsResponse`. + :http:statuscode:`204 No content`: + No public account. + + **Details:** + + .. ts:def:: PublicAccountsResponse + + interface PublicAccountsResponse { + public_accounts: PublicAccount[]; + } + + .. ts:def:: PublicAccount + + interface PublicAccount { + // Username of the account + username: string; + + // Internal payto URI of this bank account. + payto_uri: string; + + // Current balance of the account + balance: Balance; + + // Is this a taler exchange account? + is_taler_exchange: boolean; + + // Opaque unique ID used for pagination. + // @since v4, will become mandatory in the next version. + row_id?: Integer; + } + +.. http:get:: /accounts + + Obtains a list of the accounts registered at the bank. + It returns only the information that this API handles, without + any balance or transactions list. + This request is only available to the administrator. + + **Request:** + + :query delta: *Optional.* + Takes value of the form ``N (-N)``, so that at most ``N`` values strictly older (younger) than ``start`` are returned. Defaults to ``-20`` to return the last 20 entries. + :query start: *Optional.* + Row number threshold, see ``delta`` for its interpretation. Defaults to smallest or biggest row id possible according to ``delta`` sign. + :query filter_name: *Optional.* + Pattern to filter on the account legal name. Given + the filter 'foo', all the results will **contain** + 'foo' in their legal name. Without this option, + all the existing accounts are returned. + + **Response:** + + :http:statuscode:`200 OK`: + At least one account was found. + The server responds with a `ListBankAccountsResponse` object. + :http:statuscode:`204 No Content`: + No accounts were found for the given request. + :http:statuscode:`401 Unauthorized`: + Invalid credentials or missing rights. + + **Details:** + + .. ts:def:: ListBankAccountsResponse + + interfaces ListBankAccountsResponse { + accounts: AccountMinimalData[]; + } + + .. ts:def:: Balance + + interface Balance { + amount: Amount; + credit_debit_indicator: "credit" | "debit"; + } + + .. ts:def:: AccountMinimalData + + interface AccountMinimalData { + // Username of the account + username: string; + + // Legal name of the account owner. + name: string; + + // Internal payto URI of this bank account. + payto_uri: string; + + // Current balance of the account + balance: Balance; + + // Number indicating the max debit allowed for the requesting user. + debit_threshold: Amount; + + // Is this account visible to anyone? + is_public: boolean; + + // Is this a taler exchange account? + is_taler_exchange: boolean; + + // Opaque unique ID used for pagination. + // @since v4, will become mandatory in the next version. + row_id?: Integer; + + // Current status of the account + // active: the account can be used + // deleted: the account has been deleted but is retained for compliance + // reasons, only the administrator can access it + // Default to 'active' is missing + // @since v4, will become mandatory in the next version. + status?: "active" | "deleted"; + } + +.. _bank-account-info: + +.. http:get:: /accounts/$USERNAME + + Obtains information relative to the account owned by + ``$USERNAME``. The request is available to the administrator + and ``$USERNAME`` itself. + + **Response:** + + :http:statuscode:`200 OK`: + The bank responds with an `AccountData` object. + :http:statuscode:`401 Unauthorized`: + Invalid credentials or missing rights. + :http:statuscode:`404 Not found`: + The account pointed by ``$USERNAME`` was not found. + + **Details:** + + .. ts:def:: AccountData + + interface AccountData { + // Legal name of the account owner. + name: string; + + // Available balance on the account. + balance: Balance; + + // payto://-URI of the account. + payto_uri: string; + + // Number indicating the max debit allowed for the requesting user. + debit_threshold: Amount; + + // Addresses where to send the TAN for transactions. + // Currently only used for cashouts. + // If missing, cashouts will fail. + // In the future, might be used for other transactions + // as well. + contact_data?: ChallengeContactData; + + // IBAN 'payto' URI with a 'receiver-name' parameter of a fiat bank + // account where to send cashouts. This field is optional + // because not all the accounts are required to participate + // in the merchants' circuit. One example is the exchange: + // that never cashouts. Registering these accounts can + // be done via the access API. + cashout_payto_uri?: string; + + // Is this account visible to anyone? + is_public: boolean; + + // Is this a taler exchange account? + is_taler_exchange: boolean; + + // Is 2FA enabled and what channel is used for challenges? + tan_channel?: TanChannel; + + // Current status of the account + // active: the account can be used + // deleted: the account has been deleted but is retained for compliance + // reasons, only the administrator can access it + // Default to 'active' is missing + // @since v4, will become mandatory in the next version. + status?: "active" | "deleted"; + } + +Transactions +------------ + +.. http:get:: /accounts/$USERNAME/transactions + + Retrieve a subset of transactions related to $USERNAME. + + The list of returned transactions is determined by a row ID *starting point* + and a signed non-zero integer *delta*: + + * If *delta* is positive, return a list of up to *delta* transactions (all matching + the filter criteria) strictly **after** the starting point. The transactions are sorted + in **ascending** order of the row ID. + * If *delta* is negative, return a list of up to *-delta* transactions (all matching + the filter criteria) strictly **before** the starting point. The transactions are sorted + in **descending** order of the row ID. + + If *starting point* is not explicitly given, it defaults to: + + * A value that is **smaller** than all other row IDs if *delta* is **positive**. + * A value that is **larger** than all other row IDs if *delta* is **negative**. + + **Request:** + + :query delta: *Optional.* + Takes value of the form ``N (-N)``, so that at most ``N`` values strictly older (younger) than ``start`` are returned. Defaults to ``-20`` to return the last 20 entries. + :query start: *Optional.* + Row number threshold, see ``delta`` for its interpretation. Defaults to smallest or biggest row id possible according to ``delta`` sign. + :query long_poll_ms: Optional number to express how many milliseconds the server + should wait for at least one result to be shown. If not given, the server + responds immediately, regardless of the result. + + **Response:** + + :http:statuscode:`200 OK`: + The bank responds with an `BankAccountTransactionsResponse` object. + :http:statuscode:`204 No content`: + No transaction found. + :http:statuscode:`401 Unauthorized`: + Invalid credentials or missing rights. + :http:statuscode:`404 Not found`: + The account pointed by ``$USERNAME`` was not found. + + **Details:** + + .. ts:def:: BankAccountTransactionsResponse + + interface BankAccountTransactionsResponse { + transactions: BankAccountTransactionInfo[]; + } + +.. http:get:: /accounts/$USERNAME/transactions/$TRANSACTION_ID + + Retrieve the transaction whose identifier is ``TRANSACTION_ID``. + + **Response:** + + :http:statuscode:`200 OK`: + The bank responds with an `BankAccountTransactionInfo` object. + :http:statuscode:`401 Unauthorized`: + Invalid credentials or missing rights. + :http:statuscode:`404 Not found`: + The account pointed by ``$USERNAME`` was not found. + + **Details:** + + .. ts:def:: BankAccountTransactionInfo + + interface BankAccountTransactionInfo { + creditor_payto_uri: string; + debtor_payto_uri: string; + + amount: Amount; + direction: "debit" | "credit"; + + subject: string; + + // Transaction unique ID. Matches + // $TRANSACTION_ID from the URI. + row_id: Integer; + date: Timestamp; + } + +.. http:post:: /accounts/$USERNAME/transactions + + Create a new transaction where the bank account with the label ``USERNAME`` is **debited**. + + **Request:** + + .. ts:def:: CreateTransactionRequest + + interface CreateTransactionRequest { + // Address in the Payto format of the wire transfer receiver. + // It needs at least the 'message' query string parameter. + payto_uri: string; + + // Transaction amount (in the $currency:x.y format), optional. + // However, when not given, its value must occupy the 'amount' + // query string parameter of the 'payto' field. In case it + // is given in both places, the payto_uri's takes the precedence. + amount: string; + + // Nonce to make the request idempotent. Requests with the same + // ``request_uid`` that differ in any of the other fields + // are rejected. + // @since v4, will become mandatory in the next version. + request_uid?: ShortHashCode; + } + + **Response:** + + :http:statuscode:`200 Ok`: + The bank responds with an `CreateTransactionResponse` object. + :http:statuscode:`202 Accepted`: + 2FA is required for this operation. This returns the `Challenge` response. + :http:statuscode:`400 Bad Request`: + The request was invalid or the payto://-URI used unacceptable features. + :http:statuscode:`401 Unauthorized`: + Invalid credentials. + :http:statuscode:`404 Not found`: + The account pointed by ``$USERNAME`` was not found. + :http:statuscode:`409 Conflict`: + * ``TALER_EC_BANK_SAME_ACCOUNT`` : creditor account is the same than ``USERNAME``. + * ``TALER_EC_BANK_UNKNOWN_CREDITOR`` : creditor account was not found. + * ``TALER_EC_BANK_UNALLOWED_DEBIT`` : the account does not have sufficient funds. + * ``TALER_EC_BANK_TRANSFER_REQUEST_UID_REUSED``: an operation with the same ``request_uid`` but different details has been submitted before. + + **Details:** + + .. ts:def:: CreateTransactionResponse + + interface CreateTransactionResponse { + // ID identifying the transaction being created + row_id: Integer; + } + +Account withdrawals +------------------- + +.. http:post:: /accounts/$USERNAME/withdrawals + + Create a withdrawal operation, resulting in a ``taler://withdraw`` URI. + + **Request:** + + The request must be a `BankAccountCreateWithdrawalRequest`. + + **Response:** + + :http:statuscode:`200 Ok`: + The bank responds with an `BankAccountCreateWithdrawalResponse` object. + :http:statuscode:`404 Not found`: + The account pointed by ``$USERNAME`` was not found. + :http:statuscode:`409 Conflict`: + The account does not have sufficient funds. + + **Details:** + + .. ts:def:: BankAccountCreateWithdrawalRequest + + interface BankAccountCreateWithdrawalRequest { + + // Amount to withdraw. If given, the wallet + // cannot change the amount. + // Optional since **vC2EC**. + amount?: Amount; + + // Suggested amount to withdraw. The wallet can + // still change the suggestion. + // @since **vC2EC** + suggested_amount?: Amount; + + // The non-Taler card fees the customer will have + // to pay to the account owner, bank and/or + // payment service provider + // they are using to make this withdrawal. + // @since **vC2EC** + card_fees?: Amount; + } + + .. ts:def:: BankAccountCreateWithdrawalResponse + + interface BankAccountCreateWithdrawalResponse { + // ID identifying the operation being created + withdrawal_id: string; + + // URI that can be passed to the wallet to initiate the withdrawal + taler_withdraw_uri: string; + } + +.. http:post:: /accounts/$USERNAME/withdrawals/$WITHDRAWAL_ID/confirm + + Confirms ``WITHDRAWAL_ID`` operation. Has no effect on an already confirmed + withdrawal operation. This call is responsible for wiring the funds to the + exchange. + + **Response:** + + :http:statuscode:`202 Accepted`: + 2FA is required for this operation. This returns the `Challenge` response. + :http:statuscode:`204 No content`: + The withdrawal operation has been confirmed. + :http:statuscode:`404 Not found`: + The operation was not found. + :http:statuscode:`409 Conflict`: + * ``TALER_EC_BANK_CONFIRM_ABORT_CONFLICT`` : the withdrawal has been aborted previously and can't be confirmed. + * ``TALER_EC_BANK_CONFIRM_INCOMPLETE`` : the withdraw operation cannot be confirmed because no exchange and reserve public key selection happened before. + * ``TALER_EC_BANK_UNALLOWED_DEBIT`` : the account does not have sufficient funds. + +.. http:post:: /accounts/$USERNAME/withdrawals/$WITHDRAWAL_ID/abort + + Aborts ``WITHDRAWAL_ID`` operation. Has no effect on an already aborted + operation. + + **Response:** + + :http:statuscode:`204 No content`: + The withdrawal operation has been aborted. + :http:statuscode:`404 Not found`: + The withdrawal operation was not found. + :http:statuscode:`409 Conflict`: + The withdrawal operation has been confirmed previously and can't be aborted. + +.. http:get:: /withdrawals/$WITHDRAWAL_ID + + Retrieve public information about ``WITHDRAWAL_ID`` withdrawal operation. + Does not require further authentication as knowledge of ``WITHDRAWAL_ID`` + serves as an authenticator. + + **Request:** + + :query long_poll_ms: + *Optional.* If specified, the bank will wait up to ``long_poll_ms`` + milliseconds for operationt state to be different from ``old_state`` before sending the HTTP + response. A client must never rely on this behavior, as the bank may + return a response immediately. + :query old_state: + *Optional.* Default to "pending". + + **Response:** + + :http:statuscode:`200 Ok`: + The bank responds with an `WithdrawalPublicInfo` object. + :http:statuscode:`404 Not found`: + The operation was not found. + + **Details:** + + .. ts:def:: WithdrawalPublicInfo + + interface WithdrawalPublicInfo { + // Current status of the operation + // pending: the operation is pending parameters selection (exchange and reserve public key) + // selected: the operations has been selected and is pending confirmation + // aborted: the operation has been aborted + // confirmed: the transfer has been confirmed and registered by the bank + status: "pending" | "selected" | "aborted" | "confirmed"; + + // Amount that will be withdrawn with this operation + // (raw amount without fee considerations). + amount: Amount; + + // Account username + username: string; + + // Reserve public key selected by the exchange, + // only non-null if ``status`` is ``selected`` or ``confirmed``. + selected_reserve_pub?: string; + + // Exchange account selected by the wallet + // only non-null if ``status`` is ``selected`` or ``confirmed``. + selected_exchange_account?: string; + } + +Cashouts +-------- + +.. _account-cashout: + +.. http:post:: /accounts/$USERNAME/cashouts + + Initiates a conversion to fiat currency. The fiat + bank account to be + credited is the one specified at registration time via the + *cashout_payto_uri* parameter. The regional bank account + is specified via ``$USERNAME``. + + .. note:: + + Consult the `cashout rates call <cashout-rates_>`_ to learn + about any applicable fee or exchange rate. + + + **Request:** + + .. ts:def:: CashoutRequest + + interface CashoutRequest { + // Nonce to make the request idempotent. Requests with the same + // ``request_uid`` that differ in any of the other fields + // are rejected. + request_uid: ShortHashCode; + + // Optional subject to associate to the + // cashout operation. This data will appear + // as the incoming wire transfer subject in + // the user's fiat bank account. + subject?: string; + + // That is the plain amount that the user specified + // to cashout. Its $currency is the (regional) currency of the + // bank instance. + amount_debit: Amount; + + // That is the amount that will effectively be + // transferred by the bank to the user's fiat bank + // account. + // It is expressed in the fiat currency and + // is calculated after the cashout fee and the + // exchange rate. See the /cashout-rate call. + // The client needs to calculate this amount + // correctly based on the amount_debit and the cashout rate, + // otherwise the request will fail. + amount_credit: Amount; + } + + **Response:** + + :http:statuscode:`200 OK`: + The cashout request was correctly created. + This returns the `CashoutResponse` response. + :http:statuscode:`202 Accepted`: + 2FA is required for this operation. This returns the `Challenge` response. + :http:statuscode:`404 Not found`: + The account pointed by ``$USERNAME`` was not found. + :http:statuscode:`409 Conflict`: + * ``TALER_EC_BANK_TRANSFER_REQUEST_UID_REUSED``: an operation with the same ``request_uid`` but different details has been submitted before. + * ``TALER_EC_BANK_BAD_CONVERSION`` : exchange rate was calculated incorrectly by the client. + * ``TALER_EC_BANK_UNALLOWED_DEBIT`` : the account does not have sufficient funds. + * ``TALER_EC_BANK_CONFIRM_INCOMPLETE`` : the user did not share any cashout payto to uri where to wire funds. + :http:statuscode:`501 Not Implemented`: + * ``TALER_EC_BANK_TAN_CHANNEL_NOT_SUPPORTED``: the chosen ``tan_channel`` is not currently supported. + * This server does not support conversion, client should check config response. + + **Details:** + + .. ts:def:: CashoutResponse + + interface CashoutResponse { + // ID identifying the operation being created + cashout_id: Integer; + } + +.. _circuit-cashout-details: + +.. http:get:: /accounts/$USERNAME/cashouts/$CASHOUT_ID + + Returns information about the status of the ``$CASHOUT_ID`` operation. + The request is available to the administrator and the account owner. + + **Response:** + + :http:statuscode:`200 OK`: + Response is a `CashoutStatusResponse`. + :http:statuscode:`404 Not found`: + The cashout operation was not found. + :http:statuscode:`501 Not implemented`: + This server does not support conversion, client should check config response. + + **Details:** + + .. ts:def:: CashoutStatusResponse + + interface CashoutStatusResponse { + // Amount debited to the regional bank account. + amount_debit: Amount; + + // Amount credited to the fiat bank account. + amount_credit: Amount; + + // Transaction subject. + subject: string; + + // Time when the cashout was created. + creation_time: Timestamp; + } + +.. _circuit-cashouts: + +.. http:get:: /accounts/$USERNAME/cashouts + + Returns the list of all cash-out operations for an account. + + **Request:** + + :query delta: *Optional.* + Takes value of the form ``N (-N)``, so that at most ``N`` values strictly older (younger) than ``start`` are returned. Defaults to ``-20`` to return the last 20 entries. + :query start: *Optional.* + Row number threshold, see ``delta`` for its interpretation. Defaults to smallest or biggest row id possible according to ``delta`` sign. + + **Response:** + + :http:statuscode:`200 OK`: + Response is a `Cashouts`. + :http:statuscode:`204 No Content`: + No cash-out operations were found. + :http:statuscode:`501 Not implemented`: + This server does not support conversion, client should check config response. + + **Details:** + + .. ts:def:: Cashouts + + interface Cashouts { + // Every string represents a cash-out operation ID. + cashouts: CashoutInfo[]; + } + + .. ts:def:: CashoutInfo + + interface CashoutInfo { + cashout_id: Integer; + } + +.. http:get:: /cashouts + + Returns the list of all cash-out operations for **all** accounts. + + Can only be used by the administrators. + + **Request:** + + :query delta: *Optional.* + Takes value of the form ``N (-N)``, so that at most ``N`` values strictly older (younger) than ``start`` are returned. Defaults to ``-20`` to return the last 20 entries. + :query start: *Optional.* + Row number threshold, see ``delta`` for its interpretation. Defaults to smallest or biggest row id possible according to ``delta`` sign. + + .. note:: + + We might want to add a filter in the future to only + query pending cashout operations. + + **Response:** + + :http:statuscode:`200 OK`: + Response is a `GlobalCashouts`. + :http:statuscode:`204 No Content`: + No cash-out operations were found. + :http:statuscode:`501 Not implemented`: + This server does not support conversion, client should check config response. + + **Details:** + + .. ts:def:: GlobalCashouts + + interface GlobalCashouts { + cashouts: GlobalCashoutInfo[]; + } + + .. ts:def:: GlobalCashoutInfo + + interface GlobalCashoutInfo { + cashout_id: Integer; + username: string; + } + +.. _cashout-rates: + +2FA +--- + +.. http:post:: /accounts/$USERNAME/challenge/$CHALLENGE_ID + + Send TAN code for the ``CHALLENGE_ID`` challenge. + + This request can be posted several times to trigger TAN retransmission when the current code has expired or too many confirmation attempts have been made. + + **Response:** + + :http:statuscode:`200 OK`: + The TAN code have been sent. This returns `TanTransmission` response. + :http:statuscode:`401 Unauthorized`: + Invalid credentials or missing rights. + :http:statuscode:`404 Not Found`: + The challenge was not found. + :http:statuscode:`502 Bad Gateway`: + * ``TALER_EC_BANK_TAN_CHANNEL_SCRIPT_FAILED``: TAN transmition via ``tan_channel`` failed. + + **Details:** + + .. ts:def:: TanTransmission + + interface TanTransmission { + // Channel of the last successful transmission of the TAN challenge. + tan_channel: TanChannel; + + // Info of the last successful transmission of the TAN challenge. + tan_info: string; + } + + .. ts:def:: Challenge + + interface Challenge { + // Unique identifier of the challenge to solve to run this protected + // operation. + challenge_id: string; + } + + .. ts:def:: TanChannel + + enum TanChannel { + SMS = "sms", + EMAIL = "email" + } + + +.. http:post:: /accounts/$USERNAME/challenge/$CHALLENGE_ID/confirm + + Solves the ``CHALLENGE_ID`` challenge and allows performing the protected operation. + + When the challenge is confirmed, you can call the protected endpoint again with ``CHALLENGE_ID`` in the ``X-Challenge-Id`` HTTP header and an empty request body. + + **Request:** + + .. ts:def:: ChallengeSolve + + interface ChallengeSolve { + // The TAN code that solves $CHALLENGE_ID + tan: string; + } + + **Response:** + + :http:statuscode:`204 No Content`: + The challenge is confirmed. + :http:statuscode:`401 Unauthorized`: + Invalid credentials or missing rights. + :http:statuscode:`404 Not Found`: + The challenge was not found. + :http:statuscode:`409 Conflict`: + * ``TALER_EC_BANK_TAN_CHALLENGE_FAILED`` : wrong TAN. + * ``TALER_EC_BANK_TAN_CHALLENGE_EXPIRED`` : expired TAN. + :http:statuscode:`429 Too many requests`: + Too many failed confirmation attempts, a new TAN must be requested. + + +Monitor +------- + +.. http:get:: /monitor + + When the bank provides conversion between the local currency and an + external one, this call lets the bank administrator monitor the cashin + and cashout operations that were made from and to the external currency. + It shows as well figures related to internal payments made by a Taler + exchange component to internal bank accounts. Timeframes are in UTC. + + **Request:** + + :query timeframe: *Optional*. + This parameter admits one of the following values. Defaults to 'hour'. + + * hour + * day + * month + * year + + :query date_s: *Optional*. + Non-negative date in seconds after the UNIX Epoch. Default to current time. + @since v4 + + :query which: *Optional*. + This parameter points at a particular element of the *timeframe* parameter. + Following are the admitted values for each one. + Default to the last snapshot taken of the *timeframe* parameter. + @deprecated since v4 + + * hour: from 00 to 23 + * day: from 1 to the last day of the current month. + * month: from 1 to 12 + * year: Gregorian year in the YYYY format. + + **Response:** + + :http:statuscode:`200 OK`: + The bank responds with `MonitorResponse`. + :http:statuscode:`400 Bad Request`: + This error may indicate that the *which* parameter is not appropriate for the selected *timeframe*. For example, timeframe=month and which=20 would result in this error. + + **Details:** + + .. note:: + + API consumers may combine the values in the response with other + factors to serve different views to their users. + + .. ts:def:: MonitorResponse + + // Union discriminated by the "type" field. + type MonitorResponse = + | MonitorNoConversion + | MonitorWithConversion; + + .. ts:def:: MonitorNoConversion + + // Monitoring stats when conversion is not supported + interface MonitorNoConversion { + type: "no-conversions"; + + // How many payments were made to a Taler exchange by another + // bank account. + talerInCount: Integer; + + // Overall volume that has been paid to a Taler + // exchange by another bank account. + talerInVolume: Amount; + + // How many payments were made by a Taler exchange to another + // bank account. + talerOutCount: Integer; + + // Overall volume that has been paid by a Taler + // exchange to another bank account. + talerOutVolume: Amount; + } + + .. ts:def:: MonitorWithConversion + + // Monitoring stats when conversion is supported + interface MonitorWithConversion { + type: "with-conversions"; + + // How many cashin operations were confirmed by a + // wallet owner. Note: wallet owners + // are NOT required to be customers of the libeufin-bank. + cashinCount: Integer; + + // Overall regional currency that has been paid by the regional admin account + // to regional bank accounts to fulfill all the confirmed cashin operations. + cashinRegionalVolume: Amount; + + // Overall fiat currency that has been paid to the fiat admin account + // by fiat bank accounts to fulfill all the confirmed cashin operations. + cashinFiatVolume: Amount; + + // How many cashout operations were confirmed. + cashoutCount: Integer; + + // Overall regional currency that has been paid to the regional admin account + // by fiat bank accounts to fulfill all the confirmed cashout operations. + cashoutRegionalVolume: Amount; + + // Overall fiat currency that has been paid by the fiat admin account + // to fiat bank accounts to fulfill all the confirmed cashout operations. + cashoutFiatVolume: Amount; + + // How many payments were made to a Taler exchange by another + // bank account. + talerInCount: Integer; + + // Overall volume that has been paid to a Taler + // exchange by another bank account. + talerInVolume: Amount; + + // How many payments were made by a Taler exchange to another + // bank account. + talerOutCount: Integer; + + // Overall volume that has been paid by a Taler + // exchange to another bank account. + talerOutVolume: Amount; + } + + +Endpoints for Integrated Sub-APIs +--------------------------------- + +.. http:any:: /taler-integration/* + + All endpoints under this prefix are specified by the. + :doc:`GNU Taler bank integration API </core/api-bank-integration>`. + This API handles the communication with Taler wallets. + + +.. http:any:: /accounts/$USERNAME/taler-wire-gateway/* + + All endpoints under this prefix are specified + by the :doc:`GNU Taler wire gateway API </core/api-bank-wire>`. + + The endpoints are only available for accounts configured with ``is_taler_exchange=true``. + + +.. http:any:: /accounts/$USERNAME/taler-revenue/* + + All endpoints under this prefix are specified + by the :doc:`GNU Taler Revenue API </core/api-bank-revenue>`. + + +.. http:any:: /conversion-info/* + + All endpoints under this prefix are specified + by the :doc:`GNU Taler Conversion Info API </core/api-bank-conversion-info>`. + + +.. http:post:: /ebicshost + + EBICS base URL. This URL allows clients to make EBICS requests to one of + the configured EBICS hosts. + + The Taler bank can be configured to serve bank account transactions and + allow payment initiations via the EBICS protocol. + + This is an optional feature, not all implementations of the API support it. |