1.11.7. Terminal API

1.11.7.1. Introduction

Terminals are devices where users can withdraw digital cash.

This API is offered by a payment service backend and is used by such terminals. It enables imposing limits on withdrawals per unique user ID (and communicating such limits to the terminals) as well as setting up and triggering withdrawal operations.

Implementations of this API typically interact with a terminal-specific payment service (or a bank) to realize the service.

1.11.7.2. Authentication

Terminals must authenticate against all terminal API using basic auth according to HTTP basic auth.

1.11.7.3. Config

GET /config

Return the protocol version and configuration information about the bank. This specification corresponds to current protocol being version 0.

Response:

200 OK:

Response is a TerminalConfig.

Details:

interface TerminalConfig {
  // Name of the API.
  name: "taler-terminal";

  // 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;

  // Terminal provider display name to be used in user interfaces.
  provider_name: string;

  // The currency supported by this Terminal-API
  // must be the same as the currency specified
  // in the currency field of the wire gateway config
  currency: string;

  // Wire transfer type supported by the terminal.
  // FIXME: needed?
  wire_type: string;
}
GET /quotas/$UUID

Obtain the current transaction limit for the given $UUID. The UUID should be an encoding of a unique identifier of the user.

Response:

200 OK:

Response is a WithdrawLimit.

Details:

interface WithdrawLimit {
  // Maximum amount that can be withdrawn now.
  limit: Amount;

  // Time when the limit may increase.
  expiration: Timestamp;
}
POST /quotas/$UUID/lock

This endpoint allows a terminal to reserve a given amount from the user’s quota, ensuring that a subsequent operation will not fail due to a quota violation.

Request:

The request should be a WithdrawLimitLock.

Response:

204 No content:

The change was accepted.

409 Conflict:

The proposed lock would push the user above the limit.

Details:

interface WithdrawLimitLock {

  // Amount that should be reserved from the quota.
  limit: Amount;

  // ID for the lock.  FIXME: could also be 32-byte nonce?
  lock: string;

  // How long should the lock be held?
  expiration: Timestamp;
}
DELETE /quotas/$UUID/lock/$LOCK

This endpoint allows the terminal to clear a lock it may have previously created.

Response:

204 No content:

The lock was cleared.

404 Not found:

The lock is unknown.

409 Conflict:

The lock was already used in a withdrawal operation.

POST /withdrawals

This endpoint allows the terminal to set up a new withdrawal operation.

Request:

The request should be a TerminalWithdrawalSetup.

Response:

200 Ok:

The operation was created. The response will be a TerminalWithdrawalSetupResponse.

404 Not found:

A lock was specified but the lock is not known for the given user.

409 Conflict:

A conflicting withdrawal operation already exists or the amount would violate the quota for the specified user.

Details:

interface TerminalWithdrawalSetup {

  // Amount to withdraw.  If given, the wallet
  // cannot change the amount!
  amount?: Amount;

  // Suggested amount to withdraw. If given, the wallet can
  // still change the suggestion.
  suggested_amount?: Amount;

  // A provider-specific transaction identifier.
  // This identifier may be used to attest the
  // payment at the provider's backend. Optional,
  // as we may not know it at this time.
  provider_transaction_id?: string;

  // The non-Taler fees the customer will have
  // to pay to the service provider
  // they are using to make this withdrawal.
  // If the fees cannot be precalculated,
  // they can be specified in the /withdrawals/$WITHDRAWAL_ID/check
  // request after the transaction was executed.
  terminal_fees?: Amount;

  // Unique request ID to make retried requests idempotent.
  request_uid: string;

  // Unique user ID of the user.  Optional
  // in case a user Id is not (yet) known.
  user_uuid?: string;

  // ID identifying a lock on the quota that the client
  // may wish to use in this operation.  May only be
  // present if user_uuid is also given.
  lock?: string;
}
interface TerminalWithdrawalSetupResponse {

  // ID identifying the withdrawal operation being created.
  withdrawal_id: string;
}
POST /withdrawals/$WITHDRAWAL_ID/check

Endpoint for providers to notify the terminal backend about a payment having happened. This will cause the bank to validate the transaction and allow the withdrawal to proceed. The API is idempotent, meaning sending a payment notification for the same WITHDRAWAL_ID return successfuly but not change anything. This endpoint is always optional: the bank, exchange and wallet should all eventually notice the wire transfer with or without this endpoint being called. However, by calling this endpoint checks that might otherwise only happen periodically can be triggered immediately.

The endpoint may also be used to associate a user ID at a very late stage with the withdrawal — and still get an immediate failure if we are above the quota.

Note

The backend shall never just accept this claim that the payment was confirmed, but instead needs to internally attest that the payment was successful using provider-specific transaction validation logic! The point of this endpoint is merely to trigger this validation now.

Request:

The body of the request must be a TerminalWithdrawalConfirmationRequest.

Response:

204 No content:

The payment notification was processed successfully.

404 Not found:

The withdrawal operation was not found.

409 Conflict:

The withdrawal operation has been previously aborted and cannot be confirmed anymore.

451 Unavailable for Legal Reasons:

The withdrawal operation cannot be confirmed because it would put the user above the legal limit. The payment service will eventually bounce the transfer (if it were to become effective), but the user should already be shown an error.

Details:

interface TerminalWithdrawalConfirmationRequest {

  // A provider-specific transaction identifier.
  // This identifier may be used to facilitate the
  // backend to check that the credit was confirmed.
  provider_transaction_id?: string;

  // The fees which the customer had to pay to the
  // provider
  terminal_fees?: Amount;

  // A user-specific identifier for quota checks.
  user_uuid?: string;

  // ID identifying a lock on the quota that the client
  // may wish to use in this operation.  May only be
  // present if user_uuid is also given.
  lock?: string;
}
GET /withdrawals/$WITHDRAWAL_ID

Query information about a withdrawal, identified by the WITHDRAWAL_ID.

Request:

Query Parameters:
  • long_poll_msOptional. 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.

  • old_stateOptional. Default to “pending”.

Response:

200 OK:

The withdrawal operation is known to the bank, and details are given in the BankWithdrawalOperationStatus response body.

404 Not found:

The operation was not found.

DELETE /withdrawals/$WITHDRAWAL_ID/abort

Aborts WITHDRAWAL_ID operation. Has no effect on an already aborted operation. This endpoint can be used by the terminal if the terminal aborts the transaction, ensuring that the operation is also aborted at the bank.

Request:

The request body is empty.

Response:

204 No content:

The withdrawal operation has been aborted.

404 Not found:

The withdrawal operation was not found.

409 Conflict:

The withdrawal operation has been confirmed previously and can’t be aborted.

1.11.7.4. Endpoints for Integrated Sub-APIs

ANY /taler-integration/*

All endpoints under this prefix are specified by the. GNU Taler bank integration API. This API handles the communication with Taler wallets.

ANY /taler-wire-gateway/*

All endpoints under this prefix are specified by the GNU Taler wire gateway API.

The endpoints are only available for accounts configured with is_taler_exchange=true.