summaryrefslogtreecommitdiff
path: root/core/api-corebank.rst
diff options
context:
space:
mode:
Diffstat (limited to 'core/api-corebank.rst')
-rw-r--r--core/api-corebank.rst1261
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.