OTP Payments API

This document describes the API used to receive payments from the Tpaga Wallet, using OTP (One Time Password) payment codes.

Depending on the use case you are trying to implement, you have two different options to process payments using OTP payments: (please check with out team before deciding which option to use. We will help based on your particular case).

  1. Immediate capture-settle. (In one step).
  2. Authorize first then settle. This option is mostly used when you want to authorize a charge first (maybe because you don't know the final amount yet) and then, after you deliver your product/service, you can settle the final amount.

1. Immediate capture-settle

Overview of the payment process

The sequence of operations required to receive a payment from a Tpaga Wallet user is as follows:

  • The wallet user (your customer) shows you an OTP payment code; you can scan it as a QR code, or type it in manually in your system/POS.
  • Your backend system performs a request to our API (/capture), asking it to charge the amount you indicate, and pay it using the OTP code you received from the Wallet user.
  • Tpaga charges the Wallet user, and reports back to you, and to the Wallet user, about the purchase.

The sequence of events is shown in the diagram below:

@startuml
   title Paying with a Payment Token
   actor "Wallet user" as driver
   participant "Merchant\nbackend" as merchant
   participant "Tpaga App\nWallet" as app  #d3ffef
   participant "Tpaga API\nWallet" as api  #d3ffef
   participant "Payment\nacc.\nbackend" as pacapi #d0e6ff

   driver   -> merchant : Shows QR\nwith payment\ntoken\n1234567
   merchant -> api      : ""POST /api/v1/otp/capture/""\n**payment_token:** 1234567\n**amount:** 32500\n**currency:** COP\n**purchase_order_id:** ORD-001
   api      -> pacapi   : ""POST /transaction/"" \n**uuid:** uuid-of-payment-acc\n**amount:** **32500**\n**currency:** COP

   alt success
       pacapi   -> api      : ""HTTP 201""\n**amount:** 32500\n**currency:** COP\n**balance:** 809500
       api      -> merchant : ""HTTP 200""\n**payment_token:** 1234567\n**captured_amount:**32500\n**currency:** COP

       api    -> app      : ""PUSH NOTIF.""\n**payment_token:** 1234567\n**captured_amount:**32500\n**currency:** COP
   else not enough funds
       pacapi   -> api      : ""HTTP 402""
       api      -> merchant : ""HTTP 402""
       api    -> app      : ""PUSH NOTIF.""\n**payment_token:** 1234567\n**message:** Sin fondos
   end
   app    -> driver   : Shows message\nnotifying usage\nof token

@enduml

2. Authorize first then settle

It is possible to receive a payment by authorizing it, and then settling it (these two operations together have the same effect as capturing the OTP as explained before). Receiving a payment in this fashion allows you to check earlier in the transaction that a given OTP actually has enough funds to cover the cost of the purchase.

The sequence of operations to receive a payment in this fashion is the following:

  • The wallet user (your customer) shows you an OTP payment code; you can scan it as a QR code, or type it in manually in your system/POS.
  • Your backend system performs a request to our API (/authorize), asking it to authorize the amount you indicate, using the OTP code you received from the Wallet user.
  • The Tpaga API answers your backend telling it whether the OTP has enough money to back it or not, and the OTP data.
  • If the authorization was succesful, you can deliver the product/service, and settle the transaction by consuming the /settle endpoint.
  • The Tpaga API answers back to your backend system with the purchase information, and notifies the Wallet user.

The sequence of events is shown in the diagram below:

@startuml
   title Paying with a Payment Token
   actor "Wallet user" as driver
   participant "Merchant\nbackend" as merchant
   participant "Tpaga App\nWallet" as app  #d3ffef
   participant "Tpaga API\nWallet" as api  #d3ffef
   participant "Payment\nacc.\nbackend" as pacapi #d0e6ff

   driver   -> merchant : Shows QR\nwith payment\ntoken\n1234567
   merchant -> api      : ""POST /api/v1/otp/authorize/""\n**payment_token:** 1234567\n**amount:** 50000\n**currency:** COP\n**
   api      -> pacapi   : ""POST /transaction/"" \n**uuid:** uuid-of-payment-acc\n**amount:** **50000**\n**currency:** COP

   alt success
       pacapi   -> api      : ""HTTP 201""\n**amount:** 32500\n**currency:** COP\n**balance:** 809500
       api      -> merchant : ""HTTP 200""\n**authorization_code:** basd3sww\n**payment_token:** 1234567\n**captured_amount:**50000\n**currency:** COP

       api    -> app      : ""PUSH NOTIF.""\n**payment_token:** 1234567\n**authorized_amount:**50000\n**currency:** COP
       merchant -> api      : ""POST /api/v1/otp/settle/""\n**authorization_code:** basd3sww\n**amount:** 35000\n**currency:** COP\n
       api      -> pacapi   : ""POST /transaction/"" \n**uuid:** uuid-of-payment-acc\n**amount:** **15000**\n**currency:** COP
       pacapi   -> api      : ""HTTP 201""\n**amount:** 32500\n**currency:** COP\n**balance:** 809500
       api      -> merchant : ""HTTP 200""\n**authorization_code:** basd3sww\n**payment_token:** 1234567\n**captured_amount:**35000\n**currency:** COP
   else not enough funds
       pacapi   -> api      : ""HTTP 402""
       api      -> merchant : ""HTTP 402""
       api    -> app      : ""PUSH NOTIF.""\n**payment_token:** 1234567\n**message:** Sin fondos
   end
   app    -> driver   : Shows message\nnotifying usage\nof token

@enduml

Authentication

To use this API you must have an API key, which Tpaga will provide you, both for our staging (sandbox) and production environments.

Once you have it, you can authenticate your requests by adding the Authorization HTTP header, and passing the API key as the value for that header. For example, if the API key is mak-1234512345, then you must send the HTTP header Authorization: mak-1234512345 with all of your requests to this API.

Endpoints

HTTP responses common to all endpoints

If you do not provide an authentication header, or send it with the wrong API Key, you will receive a response with an HTTP 401 code.

If there is any validation error in the data received, like a missing field or a field with a data type different from the one required, the endpoint will return an HTTP 422 code.

When there is a temporary failure in Tpaga’s systems, this endpoint will return an HTTP 503 code. It is possible to retry the request later.

/authorize

This endpoint processes an OTP code, reserving the money amount attached to the OTP, to the merchant. See the full reference for the input data and output data here.

This endpoint only starts the purchase between you (the merchant) and the customer. You must finish the purchase by calling the /settle endpoint.

You can authorize any amount you decide, as long as it is below the maximum amount the Wallet user specified for the OTP. This amount will be effectively frozen from the user account. Later, when settling the purchase, you can specify the final amount you purchased, which will have to be smaller or equal to the authorized amount.

If you need to keep additional information (for example, data about the place where the payment is being made, the id for your office/cash machine/etc.), you can send it in the additional_data field of the request, where you can put a JSON dictionary with whatever structure you require.

When this operation succeeds, the money amount attached to the OTP is reserved (freezed) for the merchant by our system, and the endpoint reports that back as an HTTP 200, along with an authorization code (authorization_code).

Warning

Please take into account that, after authorizing a code, you only have 24 hours to settle the payment code. If you don’t do it before it expires, the OTP code will be considered expired and the money will be returned to the user.

Non-retryable failed requests

In the following situations, it makes no sense to retry the request:

When there are no funds, HTTP 402 (Payment Required) will be returned.

When given a code with typos, the error will be identified by the validation, and the endpoint will return HTTP 422, suggesting to check and re-type the code.

The following situations will provoke a HTTP 404 response:

  • Providing a non-existent code.
  • Providing an expired code.
  • Providing an already-authorized code.

When our API sees a system failure from the remote payment system, this endpoint will return an HTTP 502 code.

Retryable failed requests

Under certain conditions, this endpoint might return an HTTP 503 code. In this situation, we can guarantee we did not freeze the user funds, and that it is safe to retry the request.

/settle

This endpoint allows settling a previously authorized OTP. From the business-logic point of view, this endpoint finalizes the commercial transaction, transferring the money previously authorized, from the wallet user to the merchant.

For consuming this endpoint, the main pieces of data required are the authorization code (which identifies the authorized purchase in Tpaga’s DB), the amount of the purchase, and the order ID, which identifies the purchase in your system. For the full reference, check here.

Note

keep in mind that you can only give to this endpoint an amount smaller or equal than the authorized amount.

Also it is important to send the purchase_items as a JSON object with structure defined in the swagger docs, containing the information about what is being purchased.

In a similar way to the /authorize endpoint, you can also send additional_data as a JSON object with whatever structure/data you require.

When the operation succeeds, the amount indicated in the request goes to your balance, and that amount is deducted from the customer (Wallet user) payment account. This is notified as an HTTP 200 response.

The amount settled using this endpoint can be less than or equal to the amount authorized. A larger amount results in a data validation error.

If the amount settled is smaller than the authorized amount, Tpaga takes care of returning the difference to the Wallet user.

When the authorization code does not exist, or if it expired, HTTP 404 is returned.

It is safe to perform multiple requests to this endpoint with the same data. When this happens, the API charges the user payment account only the first time; any subsequent request will give you back immediately the result obtained in the first request. For this endpoint, two requests are considered the same if they have the same authorization code returned by Tpaga in /authorize

/capture

This endpoint performs the authorization and settlement of an OTP in a single request. To do so, you must provide the OTP code, the amount you will charge from that OTP, and the order ID of this purchase in your system. The full reference for the input and output data for this endpoint is available here.

When the operation succeeds, the amount indicated in the request goes to your balance, and that amount is deducted from the customer (Wallet user) payment account. This is notified as an HTTP 200 response.

The possible failures (alternative HTTP responses) are the same of the /authorize.

It is safe to perform multiple requests to this endpoint with the same data. When this happens, the API charges the user payment account only the first time; any subsequent request will give you back immediately the result obtained in the first request. For this endpoint, two requests are considered the same if they have the same order ID, and have been issued within the last 24 hours. In other words, you can re-use order IDs for different payments, provided there are more than 24 hours between each payment.

/cancel

This endpoint marks a payment as void, and takes care of returning the money back to the wallet user, if there was any money transfer. See the full reference for input and output data here.

On success the endpoint will return HTTP 200.

For safety/fraud reasons, cancelling an OTP is only allowed within the first 24 hours of its creation. If there is a cancellation attempt after that period, the cancellation will fail with status HTTP 403.

If there are no OTP payments with the received authorization code, the endpoint will return HTTP 404.

Retrying a cancellation for the same authorization code is safe; attempting to cancel an already-cancelled OTP will just return the same data as in the first request: HTTP 200.

/revert

This endpoint has the same effect as /cancel (marks a payment as void, refunds money back), but it’s intended for situations where you do not know whether an authorization/capture succeeded or not, and you wish to revert the charge, but you don’t know the authorization code for the operation.

In this situation, to void a payment, you must provide the same order ID that you provided during the authorization or capture requests.

See the full reference for input and output data here.

On success, HTTP 200 is returned.

Attempting to refund a non-existent order ID will return HTTP 404.

In a similar way to the /capture endpoint, the order ID uniquely identifies OTPs captured in the last 24 hours only. Because of this, attempts of voiding an OTP will only work if the authorization/capture was made in the last 24 hours. When attempting to void an OTP created more than 24 hours ago, the endpoint will return HTTP 404.

/info

This endpoint obtains information about a specific code without modifying it, it is safe to perform multiple requests. It is important to note that this endpoint only guarantees the existence of the code, not the availability of the money.

See the full reference for input and output data here.

On success, this endpoint will return HTTP 200.

If the code isn’t valid or it has expired, the response will be HTTP 404.

If the information received does not pass the validations, the response form this endpoint will be HTTP 422.

About the generated OTP codes

An OTP code is a temporary token that can be used to perform payments.

It is generated by the wallet user (your customer).

Once created by the wallet user, it must be used within the next 3 minutes; after that time, it expires, and it can no longer be authorized/captured.

It is a mere sequence of 6 digits + 1 digit used for verification. The verification is performed using the Luhn algorithm. This verification is intended to prevent errors when somebody inputs the code manually.

The existence of an OTP code does not guarantee the availability of the money amount attached to it. If you want to “freeze” that amount, and make sure it’s available, use authorization endpoint (see /authorize).

A wallet user can only have one active/available payment code.

The numerical code for an active OTP is guaranteed to be unique, but only among the set of all the currently active OTPs; an active OTP might have the same code of an older, already processed/expired OTP code.

Also is possible to validate the correctness of an OTP code using Luhn validation of the last digit, this is useful when the OTP code is manually entered in the system, and can be checked for typos before being sent to the Tpaga Wallet server, for example given a code 123456 the last digit should be 1, making the valid OTP 1234561, because 1 is the Luhn checksum mod 10 of 123456.