summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/api-libeufin-bank.rst985
-rw-r--r--core/api-merchant.rst2
2 files changed, 986 insertions, 1 deletions
diff --git a/core/api-libeufin-bank.rst b/core/api-libeufin-bank.rst
new file mode 100644
index 00000000..e1482864
--- /dev/null
+++ b/core/api-libeufin-bank.rst
@@ -0,0 +1,985 @@
+..
+ This file is part of GNU TALER.
+
+ Copyright (C) 2014-2020 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
+
+.. _libeufin-bank-api:
+
+=================
+Libeufin Bank API
+=================
+
+.. contents:: Table of Contents
+
+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). The user-id must be the libeufin-bank username, and the password the
+password for the corresponding user.
+
+The ``admin`` user is a special, hard-coded username. Some requests require the
+client to authenticate as the admin.
+
+Libeufin Bank Web UI
+--------------------
+
+The web UI for the libeufin-bank is typically served under ``/``.
+
+Config
+------
+
+.. http:get:: /config
+
+ **Response:**
+
+ .. ts:def:: Config
+
+ interface Config {
+ // Name of this API, always "libeufin-bank".
+ name: string;
+
+ // API version in the form $n:$n:$n
+ version: string;
+
+ // If 'true', the server provides local currency
+ // conversion support.
+ // If missing or false, some parts of the API
+ // are not supported and return 404.
+ have_cashout?: boolean;
+
+ // Fiat currency. That is the currency in which
+ // cash-out operations ultimately wire money.
+ // Only applicable if have_cashout=true.
+ fiat_currency?: string;
+ }
+
+
+Account Management
+------------------
+
+.. _libeufin-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
+ username: string;
+
+ // Password.
+ password: string;
+
+ // Legal subject owning the account.
+ name: string;
+
+ is_public: boolean;
+
+ // 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.
+ challenge_contact_data?: ChallengeContactData;
+
+ // 'payto' address pointing a bank account
+ // external to the libeufin-bank.
+ // Payments will be sent to this bank account
+ // when the user wants to convert the local currency
+ // back to fiat currency outside libeufin-bank.
+ cashout_payto_uri?: string;
+
+ // Internal payto URI of this bank account.
+ // Used mostly for testing.
+ internal_payto_uri?: string;
+ }
+
+ .. ts:def:: ChallengeContactData
+
+ interface ChallengeContactData {
+
+ // E-Mail address
+ email?: EmailAddress;
+
+ // Phone number.
+ phone?: PhoneNumber;
+ }
+
+
+ **Response:**
+
+ :http:statuscode:`204 No content`:
+ The account was successfully created.
+ :http:statuscode:`400 Bad request`:
+ Input data was invalid. For example, the client specified a invalid
+ phone number or e-mail address.
+ :http:statuscode:`403 Forbidden`:
+ The response should indicate one of the following reasons.
+
+ * A reserved username was attempted, like ``admin`` or ``bank``.
+ * An unauthorized user tried to create the account
+
+ :http:statuscode:`409 Conflict`:
+ The internal account payto URI or username already exists.
+
+.. _delete-account:
+
+.. http:delete:: /accounts/$USERNAME
+
+ Delete the account whose username is ``$USERNAME``. The deletion
+ succeeds only if the balance is *zero*.
+
+ **Response:**
+
+ :http:statuscode:`204 No content`:
+ The account was successfully deleted.
+ :http:statuscode:`403 Forbidden`:
+ The request specified a reserved internal username, like
+ ``admin`` or ``bank``.
+ :http:statuscode:`404 Not found`:
+ The username was not found.
+ :http:statuscode:`412 Precondition failed`:
+ The 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 transactions.
+ // Currently only used for cashouts.
+ // If missing, cashouts will fail.
+ // In the future, might be used for other transactions
+ // as well.
+ challenge_data?: ChallengeData;
+
+ // 'payto' address pointing a bank account
+ // external to the libeufin-bank.
+ // Payments will be sent to this bank account
+ // when the user wants to convert the local currency
+ // back to fiat currency outside libeufin-bank.
+ cashout_address?: string;
+
+ // Legal name associated with $username.
+ // When missing, the old name is kept.
+ name?: string;
+ }
+
+ **Response:**
+
+ :http:statuscode:`204 No content`:
+ Operation successful.
+
+ :http:statuscode:`403 Forbidden`:
+ The rights to change ``$USERNAME`` are not sufficient.
+ That includes the case where a correctly authenticated
+ user tries to change their legal name. It also
+ includes the case where 'admin' tries to change its
+ own account.
+
+ :http:statuscode:`404 Not found`:
+ The account pointed by ``$USERNAME``
+ was not found.
+
+
+.. _account-password-reconfig:
+
+.. http:patch:: /accounts/$USERNAME/auth
+
+ Allows changing the account's password.
+
+ **Request:**
+
+ .. ts:def:: AccountPasswordChange
+
+ interface AccountPasswordChange {
+
+ // New password.
+ new_password: string;
+ }
+
+ **Response:**
+
+ :http:statuscode:`204 No content`:
+ Operation successful.
+
+
+.. _account-list:
+
+.. http:get:: ${BANK_API_BASE_URL}/public-accounts
+
+ Show those accounts whose histories are publicly visible. For example,
+ accounts from donation receivers. As such, this request is unauthenticated.
+
+ **Response**
+
+ **Details**
+
+ .. ts:def:: PublicAccountsResponse
+
+ interface PublicAccountsResponse {
+ public_accounts: PublicAccount[];
+ }
+
+ .. ts:def:: PublicAccount
+
+ interface PublicAccount {
+ payto_uri: string;
+
+ balance: Balance;
+
+ // The account name (=username) of the
+ // libeufin-bank account.
+ account_name: string;
+ }
+
+
+.. 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 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:`403 Forbidden`:
+ A ordinary user invoked this call.
+
+ **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
+ username: string;
+
+ // Legal subject owning the account.
+ name: string;
+
+ // current balance of the account
+ balance: Balance;
+
+ // Number indicating the max debit allowed for the requesting user.
+ debit_threshold: Amount;
+ }
+
+
+.. 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 libeufin-bank responds with an `AccountData` object.
+
+ **Details:**
+
+ .. ts:def:: AccountData
+
+ interface AccountData {
+ // Legal subject owning the account.
+ 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;
+
+ contact_data?: ContactData;
+
+ // 'payto' address pointing the 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;
+ }
+
+Transactions
+------------
+
+.. http:get:: ${BANK_API_BASE_URL}/accounts/${account_name}/transactions
+
+ Retrieve a subset of transactions related to $account_name. Without
+ query parameters, it returns the last 5 transactions.
+
+ **Request**
+
+ :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.
+ :query page: page number starting from 1. Page 1 has the latest transactions
+ and 1 is the default value.
+ :query size: how many transactions per page. It must be at least 1 and defaults to 5.
+ :query from_ms: Optional. Filters the results to transactions *from* (inclusively) this
+ timestamp in milliseconds
+ :query until_ms: Optional. Filters the results to transactions *until* (inclusively) this
+ timestamp in milliseconds
+
+ **Response**
+
+ .. ts:def:: BankAccountTransactionsResponse
+
+ interface BankAccountTransactionsResponse {
+ transactions: BankAccountTransactionInfo[];
+ }
+
+.. http:get:: ${BANK_API_BASE_URL}/accounts/${account_name}/transactions/${transaction_id}
+
+ **Response**
+
+ Retrieve the transaction whose identifier is ``transaction_id``,
+ in the following format:
+
+ .. ts:def:: BankAccountTransactionInfo
+
+ interface BankAccountTransactionInfo {
+
+ creditor_iban: string;
+ creditor_bic: string; // Optional
+ creditor_name: string;
+
+ debtor_iban: string;
+ debtor_bic: string;
+ debtor_name: string;
+
+ amount: number;
+ currency: string;
+ subject: string;
+
+ // Transaction unique ID. Matches
+ // $transaction_id from the URI.
+ uid: string;
+ direction: "DBIT" | "CRDT";
+ date: Timestamp;
+ }
+
+
+.. http:post:: ${BANK_API_BASE_URL}/accounts/${account_name}/transactions
+
+ Create a new transaction where the bank account with the label ``account_name`` is **debited**.
+
+ **Request**
+
+ .. ts:def:: BankAccountTransactionCreate
+
+ interface CreateBankAccountTransactionCreate {
+
+ // 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;
+ }
+
+ **Response**
+
+ :http:statuscode:`200 OK`:
+ the transaction has been created.
+
+ :http:statuscode:`400 Bad Request`:
+ the request was invalid or the payto://-URI used unacceptable features.
+
+
+Taler Withdrawals
+-----------------
+
+.. http:post:: ${BANK_API_BASE_URL}/accounts/${account_name}/withdrawals
+
+ Create a withdrawal operation, resulting in a ``taler://withdraw`` URI.
+
+ **Request**
+
+ .. ts:def:: BankAccountCreateWithdrawalRequest
+
+ interface BankAccountCreateWithdrawalRequest {
+ // Amount to withdraw.
+ amount: Amount;
+ }
+
+ **Response**
+
+ .. ts:def:: BankAccountCreateWithdrawalResponse
+
+ interface BankAccountCreateWithdrawalResponse {
+ // ID of the withdrawal, can be used to view/modify the withdrawal operation.
+ withdrawal_id: string;
+
+ // URI that can be passed to the wallet to initiate the withdrawal.
+ taler_withdraw_uri: string;
+ }
+
+ :http:statuscode:`403 Forbidden`:
+ The operation was rejected due to insufficient funds.
+
+.. http:get:: ${BANK_API_BASE_URL}/accounts/${account_name}/withdrawals/${withdrawal_id}
+
+ Query the status of a withdrawal operation.
+
+ **Response**
+
+ **Details**
+
+ .. ts:def:: BankAccountGetWithdrawalResponse
+
+ interface BankAccountGetWithdrawalResponse {
+ // Amount that will be withdrawn with this withdrawal operation.
+ amount: Amount;
+
+ // Was the withdrawal aborted?
+ aborted: boolean;
+
+ // Has the withdrawal been confirmed by the bank?
+ // The wire transfer for a withdrawal is only executed once
+ // both ``confirmation_done`` is ``true`` and ``selection_done`` is ``true``.
+ confirmation_done: boolean;
+
+ // Did the wallet select reserve details?
+ selection_done: boolean;
+
+ // Reserve public key selected by the exchange,
+ // only non-null if ``selection_done`` is ``true``.
+ selected_reserve_pub: string | null;
+
+ // Exchange account selected by the wallet, or by the bank
+ // (with the default exchange) in case the wallet did not provide one
+ // through the Integration API.
+ selected_exchange_account: string | null;
+ }
+
+
+.. http:post:: ${BANK_API_BASE_URL}/accounts/${account_name}/withdrawals/${withdrawal_id}/abort
+
+ Abort a withdrawal operation. Has no effect on an already aborted withdrawal operation.
+
+ :http:statuscode:`200 OK`: The withdrawal operation has been aborted. The response is an empty JSON object.
+ :http:statuscode:`409 Conflict`: The reserve operation has been confirmed previously and can't be aborted.
+
+
+.. http:post:: ${BANK_API_BASE_URL}/accounts/${account_name}/withdrawals/${withdrawal_id}/confirm
+
+ Confirm a withdrawal operation. Has no effect on an already confirmed withdrawal operation.
+ This call is responsible of wiring the funds to the exchange.
+
+ **Response**
+
+ :http:statuscode:`200 OK`:
+ The withdrawal operation has been confirmed. The response is an empty JSON object.
+ :http:statuscode:`409 Conflict`:
+ The withdrawal has been aborted previously and can't be confirmed.
+ :http:statuscode:`422 Unprocessable Entity` (New):
+ The withdraw operation cannot be confirmed because no exchange and reserve public key selection happened before.
+
+Cashouts
+--------
+
+.. _account-cashout:
+
+.. http:post:: /accounts/$USERNAME/cashouts
+
+ Initiates a conversion to fiat currency. The external
+ bank account to be
+ credited is the one specified at registration time via the
+ *cashout_address* parameter. The libeufin-bank internal account
+ is specified via ``$USERNAME``.
+ The bank sends a TAN to the customer to let them confirm the
+ operation. The request is only available to ordinary users, not
+ to the administrator.
+
+ .. note::
+
+ Consult the `cashout rates call <cashout-rates_>`_ to learn
+ about any applicable fee or exchange rate.
+
+ .. note::
+
+ FIXME: Eventually, the env variables will be replaced with
+ configuration settings.
+
+ To test this operation without relying on any SMS/E-mail provider,
+ Libeufin offers two methods: defining an environment variable called
+ ``LIBEUFIN_CASHOUT_TEST_TAN`` or specifying the value ``file`` to
+ the ``tan_channel`` field of the `request object <cashout-request_>`_.
+ Assuming ``LIBEUFIN_CASHOUT_TEST_TAN`` is set to *T*, every */confirm*
+ operation can use *T* as the TAN. Setting instead the ``tan_channel``
+ field to ``file`` will cause the server to (over)write every TAN to
+ ``/tmp/libeufin-cashout-tan.txt``. If both are used, the environment
+ variable takes the precedence.
+
+
+ **Request:**
+
+ `CashoutRequest <cashout-request_>`_
+
+ .. ts:def:: TanChannel
+
+ enum TanChannel {
+ SMS = "sms",
+ EMAIL = "email",
+ FILE = "file"
+ }
+
+ .. _cashout-request:
+
+ .. ts:def:: CashoutRequest
+
+ interface CashoutRequest {
+
+ // Optional subject to associate to the
+ // cashout operation. This data will appear
+ // as the incoming wire transfer subject in
+ // the user's external bank account.
+ subject?: string;
+
+ // That is the plain amount that the user specified
+ // to cashout. Its $currency is the (regional) currency of the
+ // libeufin-bank instance.
+ amount_debit: Amount;
+
+ // That is the amount that will effectively be
+ // transferred by the bank to the user's bank
+ // account, that is external to the regional currency.
+ // It is expressed in the fiat currency and
+ // is calculated after the cashout fee and the
+ // exchange rate. See the /cashout-rates 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;
+
+ // Which channel the TAN should be sent to. If
+ // this field is missing, it defaults to SMS.
+ // The default choice prefers to change the communication
+ // channel respect to the one used to issue this request.
+ tan_channel?: TanChannel;
+ }
+
+ **Response:**
+
+ :http:statuscode:`202 Accepted`:
+ The cashout request was correctly created and
+ the TAN authentication now is pending.
+ This returns the `CashoutPending` response.
+ :http:statuscode:`409 Conflict`:
+ The user did not share any contact data where to send the TAN,
+ the account does not have sufficient funds, or the
+ exchange rate was calculated incorrectly by the client.
+ :http:statuscode:`503 Service unavailable`:
+ The bank does not support the TAN channel for this operation.
+
+ **Details:**
+
+ .. ts:def:: CashoutPending
+
+ interface CashoutPending {
+ // ID identifying the operation being created
+ // and now waiting for the TAN confirmation.
+ cashout_id: string;
+ }
+
+
+.. _cashout-abort:
+
+.. http:post:: /accounts/$USERNAME/cashouts/$CASHOUT_ID/abort
+
+ Aborts the ``$CASHOUT_ID`` operation.
+
+ **Response:**
+
+ :http:statuscode:`204 No content`:
+ ``$CASHOUT_ID`` was found in the *pending* state
+ and got successfully aborted.
+ :http:statuscode:`404 Not found`:
+ ``$CASHOUT_ID`` is not found. Note: that happens
+ also when ``$CASHOUT_ID`` got aborted before this request.
+ :http:statuscode:`409 Conflict`:
+ ``$CASHOUT_ID`` was already confirmed.
+
+
+.. _cashout-confirm:
+
+.. http:post:: /accounts/$USERNAME/cashouts/$CASHOUT_ID/confirm
+
+ Confirms the ``$CASHOUT_ID`` operation by providing its
+ TAN. The request should still be authenticated with
+ the users credentials.
+
+ **Request:**
+
+ .. ts:def:: CashoutConfirm
+
+ interface CashoutConfirm {
+ // the TAN that confirms $CASHOUT_ID.
+ tan: string;
+ }
+
+ **Response:**
+
+ :http:statuscode:`204 No content`:
+ The request succeeded, either for the first time, or it already was
+ confirmed previously (idempotency!).
+ :http:statuscode:`403 Forbidden`:
+ Wrong TAN or bad credentials.
+ :http:statuscode:`404 Not found`:
+ ``$CASHOUT_ID`` is not found. Note: that happens
+ also when ``$CASHOUT_ID`` got aborted before this request.
+ :http:statuscode:`409 Conflict`:
+ The user changed their cash-out address between the creation and the confirmation of ``$CASHOUT_ID``.
+
+
+.. _cashout-rates:
+
+.. http:get:: /cashout-rate
+
+ This public endpoint allows clients to calculate
+ the exchange rate between the regional currency
+ and the external banking system.
+
+ This endpoint shows how the bank would apply the cash-out
+ ratio and fee to one input amount. Typically, frontends
+ ask this endpoint before creating cash-out operations.
+ At least one of the two query parameters must be provided. If both are
+ given, then the server checks their correctness. Amounts must include the
+ currency.
+
+ **Request:**
+
+ :query amount_debit: this is the amount that the user will get
+ deducted from their regional bank account.
+
+ :query amount_credit: this is the amount that the user will receive
+ in their fiat bank account.
+
+ **Response:**
+
+ .. ts:def:: CashoutConversionResponse
+
+ interface CashoutConversionResponse {
+ // Amount that the user will get deducted from their regional
+ // bank account, according to the 'amount_credit' value.
+ amount_debit: Amount;
+ // Amount that the user will receive in their fiat
+ // bank account, according to 'amount_debit'.
+ amount_credit: Amount;
+ }
+
+
+ :http:statuscode:`200 Ok`:
+ Response is a `CashoutConversionResponse`.
+ :http:statuscode:`400 Bad request`:
+ Both parameters have been provided and the calculation is not correct,
+ or none of them has been provided.
+ :http:statuscode:`404 Not found`:
+ The server does not support local currency conversion.
+
+
+.. _circuit-cashouts:
+
+.. http:get:: /accounts/$USERNAME/cashouts
+
+ Returns the list of all the (pending and confirmed) cash-out operations
+ for an account.
+
+ **Response:**
+
+ .. ts:def:: Cashouts
+
+ interface Cashouts {
+ // Every string represents a cash-out operation ID.
+ cashouts: CashoutInfo[];
+ }
+
+ .. ts:def:: CashoutInfo
+
+ interface CashoutInfo {
+ cashout_id: string;
+ status: "pending" | "confirmed";
+ }
+
+ :http:statuscode:`200 OK`:
+ At least one cash-out operation was found.
+
+ :http:statuscode:`204 No Content`:
+ No cash-out operations were found at the bank
+
+.. http:get:: /cashouts
+
+ Returns the list of all the (pending and confirmed) cash-out operations
+ for **all** accounts.
+
+ Typically can only be used by the administrators.
+
+ .. note::
+
+ We might want to add a filter in the future to only
+ query pending cashout operations.
+
+ **Response:**
+
+ .. ts:def:: GlobalCashouts
+
+ interface GlobalCashouts {
+ // Every string represents a cash-out operation ID.
+ cashouts: { cashout_id: string, username: string}[];
+ }
+
+ .. ts:def:: GlobalCashoutInfo
+
+ interface GlobalCashoutInfo {
+ cashout_id: string;
+ username: string;
+ status: "pending" | "confirmed";
+ }
+
+ :http:statuscode:`200 OK`:
+ At least one cash-out operation was found.
+
+ :http:statuscode:`204 No Content`:
+ No cash-out operations were found at the bank
+
+.. _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:**
+
+ `CashoutStatusResponse <cashout-status_>`_
+
+ .. _cashout-status:
+
+ .. ts:def:: CashoutStatus
+
+ interface CashoutStatusResponse {
+ status: "pending" | "confirmed";
+
+ // Amount debited to the internal
+ // regional currency bank account.
+ amount_debit: Amount;
+
+ // Amount credited to the external bank account.
+ amount_credit: Amount;
+
+ // Transaction subject.
+ subject: string;
+
+ // Fiat bank account that will receive the cashed out amount.
+ // Specified as a payto URI.
+ credit_payto_uri: string;
+
+ // Time when the cashout was created.
+ creation_time: Timestamp;
+
+ // Time when the cashout was confirmed via its TAN.
+ // Missing when the operation wasn't confirmed yet.
+ confirmation_time?: Timestamp;
+ }
+
+ **Response:**
+
+ :http:statuscode:`404 Not found`:
+ The cashout operation was not found.
+ Aborted cashout operations will also not be found.
+
+Taler Bank Integration API
+--------------------------
+
+Every endpoint is served under ``/integration-api``.
+See :doc:`/core/api-bank-integration`. This API handles the communication
+with Taler wallets.
+
+Taler Wire Gateway API
+----------------------
+
+Served under ``/taler-wire-gateway``. Currently,
+only the :ref:`admin/add-incoming <twg-admin-add-incoming>` endpoint
+is implemented. This endpoint allows testing, but the rest of
+this API does never involve the Sandbox.
+
+EBICS Host Management
+---------------------
+
+The libeufin-bank can be configured to serve the
+bank account transactions via the EBICS protocol.
+
+The API for this is served under ``/ebics``.
+
+.. http:post:: /ebics/request
+
+ EBICS base URL. This URL allows clients to make EBICS requests to one of
+ the configured EBICS hosts.
+
+.. http:post:: /ebics/hosts
+
+ Create a new EBICS host.
+
+ **Request:**
+
+ .. ts:def:: EbicsHostRequest
+
+ interface EbicsHostRequest {
+
+ // Ebics version.
+ host_id: string;
+
+ // Name of the host.
+ ebics_version: string;
+ }
+
+
+.. http:get:: /ebics/hosts
+
+ Shows the list of all the hosts in the system.
+
+ **Response:**
+
+ .. ts:def:: EbicsHostResponse
+
+ interface EbicsHostResponse {
+
+ // shows the host IDs that are active in the system.
+ // The Ebics version *is* missing, but it's still available
+ // via the HEV message.
+ ebics_hosts: string[];
+ }
+
+.. http:post:: /ebics/hosts/$HOST_ID/rotate-keys
+
+ Overwrite the bank's Ebics keys with random ones. This is entirely
+ meant for tests (as the Sandbox itself is) and no backup will be
+ produced along this operation.
+
+.. http:post:: /ebics/subscribers
+
+ Allows (only) the ``admin`` user create an EBICS
+ subscriber associated to a bank account.
+
+ **Request:**
+
+ .. ts:def:: SubscriberRequest
+
+ interface SubscriberRequest {
+
+ // EBICS HostID
+ host_id: string;
+
+ // EBICS UserID
+ user_id: string;
+
+ // EBICS PartnerID
+ partner_id: string;
+
+ // Optional EBICS SystemID
+ system_id?: string;
+
+ // Username of the bank account to associate with
+ // this subscriber.
+ account_username: string;
+ }
+
+
+.. http:get:: /ebics/subscribers
+
+ Shows the list of all the subscribers in the system.
+
+ **Response:**
+
+ .. ts:def:: SubscribersResponse
+
+ interface SubscribersResponse {
+
+ subscribers: Subscriber[]
+ }
+
+ .. ts:def:: Subscriber
+
+ interface Subscriber {
+
+ // userID
+ user_id: string;
+
+ // partnerID
+ partner_id: string;
+
+ // hostID
+ host_id: string;
+
+ // Label of the bank account
+ // associated with this Ebics subscriber.
+ account_username: string;
+ }
diff --git a/core/api-merchant.rst b/core/api-merchant.rst
index d542b439..38865f05 100644
--- a/core/api-merchant.rst
+++ b/core/api-merchant.rst
@@ -3061,7 +3061,7 @@ to validate that a customer made a payment.
// Counter for counter-based OTP devices.
otp_ctr?: Integer;
- }
+ }
.. http:get:: [/instances/$INSTANCE]/private/otp-devices