summaryrefslogtreecommitdiff
path: root/core/api-bank-wire.rst
diff options
context:
space:
mode:
Diffstat (limited to 'core/api-bank-wire.rst')
-rw-r--r--core/api-bank-wire.rst434
1 files changed, 434 insertions, 0 deletions
diff --git a/core/api-bank-wire.rst b/core/api-bank-wire.rst
new file mode 100644
index 00000000..a76f5195
--- /dev/null
+++ b/core/api-bank-wire.rst
@@ -0,0 +1,434 @@
+..
+ This file is part of GNU TALER.
+ Copyright (C) 2019-2023 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/>
+
+.. _taler-wire-gateway-http-api:
+
+===========================
+Taler Wire Gateway HTTP API
+===========================
+
+This section describes the API offered by the Taler wire gateway. The API is
+used by the exchange to trigger transactions and query incoming transactions, as
+well as by the auditor to query incoming and outgoing transactions.
+
+This API is currently implemented by the Taler Demo Bank, as well as by
+LibEuFin (work in progress).
+
+.. http:get:: /config
+
+ Return the protocol version and configuration information about the bank.
+ This specification corresponds to ``current`` protocol being version **0**.
+
+ **Response:**
+
+ :http:statuscode:`200 OK`:
+ The exchange responds with a `WireConfig` object. This request should
+ virtually always be successful.
+
+ **Details:**
+
+ .. ts:def:: WireConfig
+
+ interface WireConfig {
+ // Name of the API.
+ name: "taler-wire-gateway";
+
+ // 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;
+
+ // Currency used by this gateway.
+ currency: string;
+
+ // URN of the implementation (needed to interpret 'revision' in version).
+ // @since v0, may become mandatory in the future.
+ implementation?: string;
+ }
+
+--------------
+Authentication
+--------------
+
+The bank library authenticates requests to the wire gateway via
+`HTTP basic auth <https://tools.ietf.org/html/rfc7617>`_.
+
+-------------------
+Making Transactions
+-------------------
+
+.. http:post:: /transfer
+
+ This API allows the exchange to make a transaction, typically to a merchant. The bank account
+ of the exchange is not included in the request, but instead derived from the user name in the
+ authentication header and/or the request base URL.
+
+ To make the API idempotent, the client must include a nonce. Requests with the same nonce
+ are rejected unless the request is the same.
+
+ **Request:**
+
+ .. ts:def:: TransferRequest
+
+ interface TransferRequest {
+ // Nonce to make the request idempotent. Requests with the same
+ // ``request_uid`` that differ in any of the other fields
+ // are rejected.
+ request_uid: HashCode;
+
+ // Amount to transfer.
+ amount: Amount;
+
+ // Base URL of the exchange. Shall be included by the bank gateway
+ // in the appropriate section of the wire transfer details.
+ exchange_base_url: string;
+
+ // Wire transfer identifier chosen by the exchange,
+ // used by the merchant to identify the Taler order(s)
+ // associated with this wire transfer.
+ wtid: ShortHashCode;
+
+ // The recipient's account identifier as a payto URI.
+ credit_account: string;
+ }
+
+ **Response:**
+
+ :http:statuscode:`200 OK`:
+ The request has been correctly handled, so the funds have been transferred to
+ the recipient's account. The body is a `TransferResponse`.
+ :http:statuscode:`400 Bad request`:
+ Request malformed. The bank replies with an `ErrorDetail` object.
+ :http:statuscode:`401 Unauthorized`:
+ Authentication failed, likely the credentials are wrong.
+ :http:statuscode:`404 Not found`:
+ The endpoint is wrong or the user name is unknown. The bank replies with an `ErrorDetail` object.
+ :http:statuscode:`409 Conflict`:
+ A transaction with the same ``request_uid`` but different transaction details
+ has been submitted before.
+
+ **Details:**
+
+ .. ts:def:: TransferResponse
+
+ interface TransferResponse {
+ // Timestamp that indicates when the wire transfer will be executed.
+ // In cases where the wire transfer gateway is unable to know when
+ // the wire transfer will be executed, the time at which the request
+ // has been received and stored will be returned.
+ // The purpose of this field is for debugging (humans trying to find
+ // the transaction) as well as for taxation (determining which
+ // time period a transaction belongs to).
+ timestamp: Timestamp;
+
+ // Opaque ID of the transaction that the bank has made.
+ row_id: SafeUint64;
+ }
+
+
+--------------------------------
+Querying the transaction history
+--------------------------------
+
+
+.. http:get:: /history/incoming
+
+ Return a list of transactions made from or to the exchange.
+
+ Incoming transactions must contain a valid reserve public key. If a bank
+ transaction does not conform to the right syntax, the wire gateway must not
+ report it to the exchange, and send funds back to the sender if possible.
+
+ The bank account of the exchange is determined via the base URL and/or the
+ user name in the ``Authorization`` header. In fact the transaction history
+ might come from a "virtual" account, where multiple real bank accounts are
+ merged into one history.
+
+ Transactions are identified by an opaque numeric identifier, referred to here
+ as *row ID*. The semantics of the row ID (including its sorting order) are
+ determined by the bank server and completely opaque to the client.
+
+ 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 start: *Optional.*
+ Row identifier to explicitly set the *starting point* of the query.
+ :query delta:
+ The *delta* value that determines the range of the query.
+ :query long_poll_ms: *Optional.* If this parameter is specified and the
+ result of the query would be empty, the bank will wait up to ``long_poll_ms``
+ milliseconds for new transactions that match the query to arrive and only
+ then send the HTTP response. A client must never rely on this behavior, as
+ the bank may return a response immediately or after waiting only a fraction
+ of ``long_poll_ms``.
+
+ **Response:**
+
+ :http:statuscode:`200 OK`:
+ JSON object of type `IncomingHistory`.
+ :http:statuscode:`204 No content`:
+ There are not transactions to report (under the given filter).
+ :http:statuscode:`400 Bad request`:
+ Request malformed. The bank replies with an `ErrorDetail` object.
+ :http:statuscode:`401 Unauthorized`:
+ Authentication failed, likely the credentials are wrong.
+ :http:statuscode:`404 Not found`:
+ The endpoint is wrong or the user name is unknown. The bank replies with an `ErrorDetail` object.
+
+ **Details:**
+
+ .. ts:def:: IncomingHistory
+
+ interface IncomingHistory {
+ // Array of incoming transactions.
+ incoming_transactions : IncomingBankTransaction[];
+
+ // Payto URI to identify the receiver of funds.
+ // This must be one of the exchange's bank accounts.
+ // Credit account is shared by all incoming transactions
+ // as per the nature of the request.
+ credit_account: string;
+
+ }
+
+ .. ts:def:: IncomingBankTransaction
+
+ // Union discriminated by the "type" field.
+ type IncomingBankTransaction =
+ | IncomingReserveTransaction
+ | IncomingWadTransaction;
+
+ .. ts:def:: IncomingReserveTransaction
+
+ interface IncomingReserveTransaction {
+ type: "RESERVE";
+
+ // Opaque identifier of the returned record.
+ row_id: SafeUint64;
+
+ // Date of the transaction.
+ date: Timestamp;
+
+ // Amount transferred.
+ amount: Amount;
+
+ // Payto URI to identify the sender of funds.
+ debit_account: string;
+
+ // The reserve public key extracted from the transaction details.
+ reserve_pub: EddsaPublicKey;
+
+ }
+
+ .. ts:def:: IncomingWadTransaction
+
+ interface IncomingWadTransaction {
+ type: "WAD";
+
+ // Opaque identifier of the returned record.
+ row_id: SafeUint64;
+
+ // Date of the transaction.
+ date: Timestamp;
+
+ // Amount transferred.
+ amount: Amount;
+
+ // Payto URI to identify the receiver of funds.
+ // This must be one of the exchange's bank accounts.
+ credit_account: string;
+
+ // Payto URI to identify the sender of funds.
+ debit_account: string;
+
+ // Base URL of the exchange that originated the wad.
+ origin_exchange_url: string;
+
+ // The reserve public key extracted from the transaction details.
+ wad_id: WadId;
+ }
+
+
+.. http:get:: /history/outgoing
+
+ Return a list of transactions made by the exchange, typically to a merchant.
+
+ The bank account of the exchange is determined via the base URL and/or the
+ user name in the ``Authorization`` header. In fact the transaction history
+ might come from a "virtual" account, where multiple real bank accounts are
+ merged into one history.
+
+ Transactions are identified by an opaque integer, referred to here as *row
+ ID*. The semantics of the row ID (including its sorting order) are
+ determined by the bank server and completely opaque to the client.
+
+ 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 start: *Optional.*
+ Row identifier to explicitly set the *starting point* of the query.
+ :query delta:
+ The *delta* value that determines the range of the query.
+ :query long_poll_ms: *Optional.* If this parameter is specified and the
+ result of the query would be empty, the bank will wait up to ``long_poll_ms``
+ milliseconds for new transactions that match the query to arrive and only
+ then send the HTTP response. A client must never rely on this behavior, as
+ the bank may return a response immediately or after waiting only a fraction
+ of ``long_poll_ms``.
+
+ **Response:**
+
+ :http:statuscode:`200 OK`:
+ JSON object of type `OutgoingHistory`.
+ :http:statuscode:`204 No content`:
+ There are not transactions to report (under the given filter).
+ :http:statuscode:`400 Bad request`:
+ Request malformed. The bank replies with an `ErrorDetail` object.
+ :http:statuscode:`401 Unauthorized`:
+ Authentication failed, likely the credentials are wrong.
+ :http:statuscode:`404 Not found`:
+ The endpoint is wrong or the user name is unknown. The bank replies with an `ErrorDetail` object.
+
+ **Details:**
+
+ .. ts:def:: OutgoingHistory
+
+ interface OutgoingHistory {
+ // Array of outgoing transactions.
+ outgoing_transactions : OutgoingBankTransaction[];
+
+ // Payto URI to identify the sender of funds.
+ // This must be one of the exchange's bank accounts.
+ // Credit account is shared by all incoming transactions
+ // as per the nature of the request.
+ debit_account: string;
+
+ }
+
+ .. ts:def:: OutgoingBankTransaction
+
+ interface OutgoingBankTransaction {
+ // Opaque identifier of the returned record.
+ row_id: SafeUint64;
+
+ // Date of the transaction.
+ date: Timestamp;
+
+ // Amount transferred.
+ amount: Amount;
+
+ // Payto URI to identify the receiver of funds.
+ credit_account: string;
+
+ // The wire transfer ID in the outgoing transaction.
+ wtid: ShortHashCode;
+
+ // Base URL of the exchange.
+ exchange_base_url: string;
+ }
+
+
+-----------------------
+Wire Transfer Test APIs
+-----------------------
+
+Endpoints in this section are only used for integration tests and never
+exposed by bank gateways in production.
+
+.. _twg-admin-add-incoming:
+
+.. http:post:: /admin/add-incoming
+
+ Simulate a transfer from a customer to the exchange. This API is *not*
+ idempotent since it's only used in testing.
+
+ **Request:**
+
+ .. ts:def:: AddIncomingRequest
+
+ interface AddIncomingRequest {
+ // Amount to transfer.
+ amount: Amount;
+
+ // Reserve public key that is included in the wire transfer details
+ // to identify the reserve that is being topped up.
+ reserve_pub: EddsaPublicKey;
+
+ // Account (as payto URI) that makes the wire transfer to the exchange.
+ // Usually this account must be created by the test harness before this API is
+ // used. An exception is the "exchange-fakebank", where any debit account can be
+ // specified, as it is automatically created.
+ debit_account: string;
+ }
+
+ **Response:**
+
+ :http:statuscode:`200 OK`:
+ The request has been correctly handled, so the funds have been transferred to
+ the recipient's account. The body is a `AddIncomingResponse`.
+ :http:statuscode:`400 Bad request`:
+ The request is malformed. The bank replies with an `ErrorDetail` object.
+ :http:statuscode:`401 Unauthorized`:
+ Authentication failed, likely the credentials are wrong.
+ :http:statuscode:`404 Not found`:
+ The endpoint is wrong or the user name is unknown. The bank replies with an `ErrorDetail` object.
+ :http:statuscode:`409 Conflict`:
+ The 'reserve_pub' argument was used previously in another transfer, and the specification mandates that reserve public keys must not be reused.
+
+ **Details:**
+
+ .. ts:def:: AddIncomingResponse
+
+ interface AddIncomingResponse {
+ // Timestamp that indicates when the wire transfer will be executed.
+ // In cases where the wire transfer gateway is unable to know when
+ // the wire transfer will be executed, the time at which the request
+ // has been received and stored will be returned.
+ // The purpose of this field is for debugging (humans trying to find
+ // the transaction) as well as for taxation (determining which
+ // time period a transaction belongs to).
+ timestamp: Timestamp;
+
+ // Opaque ID of the transaction that the bank has made.
+ row_id: SafeUint64;
+ }