api-terminal.rst (11319B)
1 .. 2 This file is part of GNU TALER. 3 4 Copyright (C) 2024 Taler Systems SA 5 6 TALER is free software; you can redistribute it and/or modify it under the 7 terms of the GNU Affero General Public License as published by the Free Software 8 Foundation; either version 2.1, or (at your option) any later version. 9 10 TALER is distributed in the hope that it will be useful, but WITHOUT ANY 11 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 12 A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. 13 14 You should have received a copy of the GNU Affero General Public License along with 15 TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> 16 17 .. target audience: developer, core developer 18 19 .. _terminal-api: 20 21 ============ 22 Terminal API 23 ============ 24 25 26 Introduction 27 ------------ 28 29 Terminals are devices where users can withdraw digital cash. 30 31 This API is offered by a payment service backend and is used by such 32 terminals. It enables imposing limits on withdrawals per unique user ID (and 33 communicating such limits to the terminals) as well as setting up and 34 triggering withdrawal operations. 35 36 Implementations of this API typically interact with a terminal-specific 37 payment service (or a bank) to realize the service. 38 39 40 --------------- 41 Version History 42 --------------- 43 44 The current protocol version is **v0**. 45 46 * cash2ecash is currently targeting protocol version **v0**. 47 * cashless2ecash is currently targeting protocol version **v0**. 48 49 **Version history:** 50 51 * ``v0``: Initial version. 52 53 **Upcoming versions:** 54 55 * None anticipated. 56 57 **Ideas for future version:** 58 59 * ``vXXX``: marker for features not yet targeted for release 60 61 62 63 64 Authentication 65 -------------- 66 67 Terminals must authenticate against all terminal API using basic auth according to `HTTP basic auth <https://tools.ietf.org/html/rfc7617>`_. 68 69 70 Config 71 ------ 72 73 .. http:get:: /config 74 75 Return the protocol version and configuration information about the bank. 76 This specification corresponds to ``current`` protocol being version **0**. 77 78 **Response:** 79 80 :http:statuscode:`200 OK`: 81 Response is a `TerminalConfig`. 82 83 **Details:** 84 85 .. ts:def:: TerminalConfig 86 87 interface TerminalConfig { 88 // Name of the API. 89 name: "taler-terminal"; 90 91 // libtool-style representation of the Bank protocol version, see 92 // https://www.gnu.org/software/libtool/manual/html_node/Versioning.html#Versioning 93 // The format is "current:revision:age". 94 version: string; 95 96 // Terminal provider display name to be used in user interfaces. 97 provider_name: string; 98 99 // The currency supported by this Terminal-API 100 // must be the same as the currency specified 101 // in the currency field of the wire gateway config 102 currency: string; 103 104 // The withdrawal fees which of this Terminals API endpoint. 105 // If the Exchange chooses to charge no fees, then just configure 106 // the zero amount. 107 withdrawal_fees: Amount; 108 109 // Wire transfer type supported by the terminal. 110 // FIXME: needed? 111 wire_type: string; 112 } 113 114 115 .. http:get:: /quotas/$UUID 116 117 Obtain the current transaction limit for the given $UUID. 118 The UUID should be an encoding of a unique identifier of 119 the user. 120 121 **Response:** 122 123 :http:statuscode:`200 OK`: 124 Response is a `WithdrawLimit`. 125 126 **Details:** 127 128 .. ts:def:: WithdrawLimit 129 130 interface WithdrawLimit { 131 // Maximum amount that can be withdrawn now. 132 limit: Amount; 133 134 // Time when the limit may increase. 135 expiration: Timestamp; 136 } 137 138 139 .. http:post:: /quotas/$UUID/lock 140 141 This endpoint allows a terminal to reserve a given amount 142 from the user's quota, ensuring that a subsequent operation 143 will not fail due to a quota violation. 144 145 **Request:** 146 147 The request should be a `WithdrawLimitLock`. 148 149 **Response:** 150 151 :http:statuscode:`204 No content`: 152 The change was accepted. 153 :http:statuscode:`409 Conflict`: 154 The proposed lock would push the user above the limit. 155 156 **Details:** 157 158 .. ts:def:: WithdrawLimitLock 159 160 interface WithdrawLimitLock { 161 162 // Amount that should be reserved from the quota. 163 limit: Amount; 164 165 // ID for the lock. FIXME: could also be 32-byte nonce? 166 lock: string; 167 168 // How long should the lock be held? 169 expiration: Timestamp; 170 } 171 172 .. http:delete:: /quotas/$UUID/lock/$LOCK 173 174 This endpoint allows the terminal to clear a lock it may have 175 previously created. 176 177 **Response:** 178 179 :http:statuscode:`204 No content`: 180 The lock was cleared. 181 :http:statuscode:`404 Not found`: 182 The lock is unknown. 183 :http:statuscode:`409 Conflict`: 184 The lock was already used in a withdrawal operation. 185 186 187 .. http:post:: /withdrawals 188 189 This endpoint allows the terminal to set up a new withdrawal 190 operation. 191 192 **Request:** 193 194 The request should be a `TerminalWithdrawalSetup`. 195 196 **Response:** 197 198 :http:statuscode:`200 Ok`: 199 The operation was created. The response will be 200 a `TerminalWithdrawalSetupResponse`. 201 :http:statuscode:`404 Not found`: 202 A lock was specified but the lock is not known for 203 the given user. 204 :http:statuscode:`409 Conflict`: 205 A conflicting withdrawal operation already exists or 206 the amount would violate the quota for the specified user. 207 208 **Details:** 209 210 .. ts:def:: TerminalWithdrawalSetup 211 212 interface TerminalWithdrawalSetup { 213 214 // Amount to withdraw. If given, the wallet 215 // cannot change the amount! 216 amount?: Amount; 217 218 // Suggested amount to withdraw. If given, the wallet can 219 // still change the suggestion. 220 suggested_amount?: Amount; 221 222 // A provider-specific transaction identifier. 223 // This identifier may be used to attest the 224 // payment at the provider's backend. Optional, 225 // as we may not know it at this time. 226 provider_transaction_id?: string; 227 228 // The non-Taler fees the customer will have 229 // to pay to the service provider 230 // they are using to make this withdrawal. 231 // If the fees cannot be precalculated, 232 // they can be specified in the /withdrawals/$WITHDRAWAL_ID/check 233 // request after the transaction was executed. 234 terminal_fees?: Amount; 235 236 // Unique request ID to make retried requests idempotent. 237 request_uid: string; 238 239 // Unique user ID of the user. Optional 240 // in case a user Id is not (yet) known. 241 user_uuid?: string; 242 243 // ID identifying a lock on the quota that the client 244 // may wish to use in this operation. May only be 245 // present if ``user_uuid`` is also given. 246 lock?: string; 247 } 248 249 .. ts:def:: TerminalWithdrawalSetupResponse 250 251 interface TerminalWithdrawalSetupResponse { 252 253 // ID identifying the withdrawal operation being created. 254 withdrawal_id: string; 255 } 256 257 258 .. http:post:: /withdrawals/$WITHDRAWAL_ID/check 259 260 Endpoint for providers to notify the terminal backend about a payment having 261 happened. This will cause the bank to validate the transaction and allow 262 the withdrawal to proceed. The API is idempotent, meaning sending a payment 263 notification for the same ``WITHDRAWAL_ID`` return successfuly but not 264 change anything. This endpoint is always *optional*: the bank, exchange and 265 wallet should all eventually notice the wire transfer with or without this 266 endpoint being called. However, by calling this endpoint checks that might 267 otherwise only happen periodically can be triggered immediately. 268 269 The endpoint may also be used to associate a user ID at a very late stage 270 with the withdrawal --- and still get an immediate failure if we are above 271 the quota. 272 273 .. note:: 274 275 The backend shall **never** just accept this claim that the payment was 276 confirmed, but instead needs to internally attest that the payment was 277 successful using provider-specific transaction validation logic! The point 278 of this endpoint is merely to trigger this validation **now**. 279 280 **Request:** 281 282 The body of the request must be a `TerminalWithdrawalConfirmationRequest`. 283 284 **Response:** 285 286 :http:statuscode:`204 No content`: 287 The payment notification was processed successfully. 288 :http:statuscode:`404 Not found`: 289 The withdrawal operation was not found. 290 :http:statuscode:`409 Conflict`: 291 The withdrawal operation has been previously aborted 292 and cannot be confirmed anymore. 293 :http:statuscode:`451 Unavailable for Legal Reasons`: 294 The withdrawal operation cannot be confirmed because 295 it would put the user above the legal limit. The 296 payment service will eventually bounce the transfer 297 (if it were to become effective), but the user should 298 already be shown an error. 299 300 **Details:** 301 302 .. ts:def:: TerminalWithdrawalConfirmationRequest 303 304 interface TerminalWithdrawalConfirmationRequest { 305 306 // A provider-specific transaction identifier. 307 // This identifier may be used to facilitate the 308 // backend to check that the credit was confirmed. 309 provider_transaction_id?: string; 310 311 // The fees which the customer had to pay to the 312 // provider 313 terminal_fees?: Amount; 314 315 // A user-specific identifier for quota checks. 316 user_uuid?: string; 317 318 // ID identifying a lock on the quota that the client 319 // may wish to use in this operation. May only be 320 // present if ``user_uuid`` is also given. 321 lock?: string; 322 } 323 324 .. http:get:: /withdrawals/$WITHDRAWAL_ID 325 326 Query information about a withdrawal, identified by the ``WITHDRAWAL_ID``. 327 328 **Request:** 329 330 :query long_poll_ms: 331 *Optional.* If specified, the bank will wait up to ``long_poll_ms`` 332 milliseconds for operationt state to be different from ``old_state`` before sending the HTTP 333 response. A client must never rely on this behavior, as the bank may 334 return a response immediately. 335 :query old_state: 336 *Optional.* Defaults to "pending". 337 338 **Response:** 339 340 :http:statuscode:`200 OK`: 341 The withdrawal operation is known to the bank, and details are given 342 in the `BankWithdrawalOperationStatus` response body. 343 :http:statuscode:`404 Not found`: 344 The operation was not found. 345 346 .. http:delete:: /withdrawals/$WITHDRAWAL_ID/abort 347 348 Aborts ``WITHDRAWAL_ID`` operation. Has no effect on an already aborted 349 operation. This endpoint can be used by the terminal if the terminal aborts 350 the transaction, ensuring that the operation is also aborted at the 351 bank. 352 353 **Request:** 354 355 The request body is empty. 356 357 **Response:** 358 359 :http:statuscode:`204 No content`: 360 The withdrawal operation has been aborted. 361 :http:statuscode:`404 Not found`: 362 The withdrawal operation was not found. 363 :http:statuscode:`409 Conflict`: 364 The withdrawal operation has been confirmed previously and 365 can't be aborted. 366 367 368 Endpoints for Integrated Sub-APIs 369 --------------------------------- 370 371 .. http:any:: /taler-integration/* 372 373 All endpoints under this prefix are specified by the. 374 :doc:`GNU Taler bank integration API </core/api-bank-integration>`. 375 This API handles the communication with Taler wallets. 376 377 378 .. http:any:: /taler-wire-gateway/* 379 380 All endpoints under this prefix are specified 381 by the :doc:`GNU Taler wire gateway API </core/api-bank-wire>`. 382 383 The endpoints are only available for accounts configured with ``is_taler_exchange=true``.