Revision History

  • 1.0 – 2019-05-16
    • Initial Document was created
  • 1.1 – 2019-11-12
    • Updated transaction data structures
  • 1.1 – 2020-03-02
    • Updated company logos
    • Added separation for test and live endpoints
  • 1.2 – 2020-04-17
    • Changed transaction details object
    • Added more fields (optional) for payment initiation
  • 1.3 – 2020-04-21
    • Improved protocol security with time stamps
    • Updated QR Code description
    • Added description for Card based payments

Introduction

Travel Union Third Party Provider API is created for TPP developers that will be implementing PSU access to services provider by Travel Union.

Document describes message structure, security and message flow.

The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “MAY”, and “OPTIONAL” in this document are to be interpreted as described in RFC 2119.

Get Started

In tables bellow there will be identification of value type next to its description:
[S] - value is string
[B] - value is binary content (byte array) represent in base64 encoded string
[I] - value is integer
[D] - value is double
[T] - value is time in seconds since UTC 2000-01-01 00:00:00

All communication with API Host is done via messages sent over secure web request (https://) using TLS 1.2 as transport encryption layer.

https://mytu.dev/ is for test sand box

https://mytu.live/ is for live (a.k.a. production environment)

TPP is identified by API KEY that TPP receives from Travel Union after it provides required documents and is verified by regulators. In the future system will support self registration using eIDAS certificates for automatic API key download.

Some requests that require customer interaction will come back as callbacks/webhooks to TPP callback address, it must be properly secured with TLS 1.2 or higher and with valid certificate. Callbacks will be repeated several times before callback delivery will expire.

In tables bellow there will be identification of value type next to its description:
[S] value is string
[B] value is binary content (byte array) represent in base64 encoded string
[I] value is integer
[D] value is double
[T] value is time in seconds since UTC 2000-01-01 00:00:00

Signing and verification

Signature verification example in PHP


Example uses simplito/elliptic-php library for ECDSA verification.
<?php require_once('vendor/autoload.php'); use Elliptic\EC; $ec = new EC('p256'); $signature = $_SERVER['HTTP_SIGNATURE']; $requestId = $_SERVER['HTTP_REQUESTID']; $requestMethod = $_SERVER['REQUEST_METHOD']; $fullRequestUrl = "https://" . "{$_SERVER['HTTP_HOST']}{$_SERVER['REQUEST_URI']}"; $message = $requestId . $requestMethod . $fullRequestUrl; $message = unpack("C*", $message); $hexPub = "04c177700.....34fe5cd64"; // taken from https://mytu.dev/public.hex $key = $ec->keyFromPublic($hexPub, "hex"); $result = $key->verify($message, $signature); echo "Verified: " . ($result == TRUE) ? "true" : "false");

Callback content is signed by the host using ECDSA key. Signature (DER format, hex encoding) is sent in the request header ("signature"). Also callbacks are comming from known (static) public IP address so we recommended to set up filters on incomming callbacks.

Test public keys can be downloaded from:

Live public keys can be downloaded from:

ECDSA Signature is calculated on the following request data:
<REQUEST ID><HTTP METOD><URL><CONTENT>

<REQUEST ID> Sent as a header, e.g. requestid: "8C7BEAB39BBF0C36:08D94602298E4149"
<HTTP METOD> POST, GET, PUT, …
<URL> Utf8 encoded full request url including ‘https://’ prefix
<CONTENT> Is byte array content of the request

ECDSA signer has to be initialised for HAMAC with SHA256 digest using secp256r1 named curve.

For optimal security third party/merchant system can have a “time window” that it accepts incomming GET requests, and use a unique requestid (in the request header) to filter out duplicates and prevent record replay attacks. TU host will not fire multiple requests with the same requestid value for the same unique callback uri.

Common Data Structures and Definitions

Trough out this specification there will be places where specification will refer to the following data structures and definitions. In order to not repeat it again and again, we specify it here:

<TRAN> - Transaction Details

                
{
    "id": <record id>,
    "ver": <version nr>,
    "timeStamp": <timestamp>,
    "tlc": <lifecyle>,
    "acc": <account to>,
    "name": <name>, // if available
    "street": <street address>, // if available
    "city": <city>,  // if available
    "country": <country code>,  // if available
    "msg": <message>,  // if available
    "time": <local time>, // if available
    "tcc": <tran. category>, // if available
    "amount": [<amount data>,...],
    "fee: [<amount data>, ...], // if available
}
                
            

QUERY PARAMETERS

Field Type Description
<record id> String Unique record ID
<version nr> Integer Record version number (so that you can discard irrelevant push).
<timestamp> Integer UTC Time Stamp of the operation
<lifecyle> String Operation life cycle. The values are the following:
  • T0 = Request / pending payment request
  • T1 = Posted / money in transit for external systems
  • T2 = Pending / this is open CASE needs review and approval by AML personnel
  • T3 = Executed / transfer is executed
  • T5 = Reversed / reversed due to technical reasons
  • T6 = Blocked / blocked automatically or after review
  • T7 = Failed / due to natural reasons, no account or similar
  • T8 = Rejected / by payer
  • T9 = Canceled / by requester aka payee
<account to> String Account that transaction have been made to
<name> String (Optional) Name of the money receiver or sender for display
<street address> String (Optional) Address of the money receiver or sender
<city> String (Optional) City of the money receiver or sender
<country code> String (Optional) Country code of the money receiver or sender in ISO 3166 alpha-3 uppercase form (e.g. LTU)
<message> String (Optional) Message attached to transfer
<local time> String (Optional) Local operation time for proximity payments. yyyy-MM-dd HH:mm:ss
<tran. category> String (Optional) Transaction category code in the following format: <TYPE> (see below for available transaction types)
<amount data> String (Optional) Amount data in the following format CCC+AMOUNT.DECIMALS First amount data in a list is Main amount, other values if present indicate additional balance operations on senders account. Samples: "EUR-100.12" when client pays 100.12 Eur. Payment is indicated by the minus (-) sign.

<TYPE> - Transaction Category / type

Valid values and visual recommendations:

  • GRCR Groceries (Shopping cart)
  • SHOP Shopping (Shopping bag)
  • REST Restaurants (Knife and Fork/Plate/Dishes)
  • TRAN Transport (Bus/Car/Train)
  • TRAV Travel (Plain)
  • ENTT Entertainment (Console Controller/Screen)
  • HLTH Health (Heart/Medical Box/Syringe)
  • SRVC Services (Tools)
  • OTHR General (Coins/Box/)
  • UTIL Utilities (Typical house)
  • TRSF Transfers (Arrows)
  • CASH Cash (Banknote)
  • INSR Insurance (Umbrella/Shield)
  • TXFN Tax & Fines (Person with a tie/Pie chart)
  • FEES Fees (%)
  • TOPA Acocunt top up by payment (like card) (Wallet)
  • CASH Cash operations deposit (or equivalent) or ATM (Money bill)
  • GMBL Gambling (Online and Offline) (Playing cards)

Given list is not exhaustive meaning that there may be other values, that should be represented as general Transfer on Unspecified (blank).

Scan Link

Scan link is used to display QR Code and redirect to myTU app when tapped on device.

The link has to be in the following format (for live and for dev environments):

  • https://mytu.live/scan?<encodded qrcode content>
  • https://mytu.dev/scan?<encodded qrcode content>

API for Account Information Services

As AISP TPP can get access to Travel Union Payment Service User (PSU) account information like balance and transaction history if granted by PSU. Account information access is granted by PSU consent on mobile application and comes in a form of unique token that has expiration time.

The following requests require secret APIKEY in Authorization header available to developers only and has to be protected accordingly.

REQUEST ACCESS

Request body structure:
                
{
    "acc": <account id>
}
                
            

POST https://mytu.live/ais/<access token>

This request has to be made as POST method and request body has to contain UTF8 encoded JSON. It is sent from AISP system (not a browser for customer facing device) to the server when PSU expressed will to give access to his account for TPP.

Field Type Description
<account id> String This is string value that contains either PSU phone number that is linked to his account like +37060000000 or IBAN like LT000000000000000000
<access token> String String consisting of following characters [0…9][A…Z][a…z] from 20 up to 40 chars long. If approved, it will become access token for TPP to gain access to PSU account information.

API Host may respond with various HTTP response codes indicating different reasons for decline like 401 for unauthorized access, or 400 for account not found.

If HTTP response code to request is 200 TPP system should expect a call back (given that user gives his consent for account access) with the following JSON object in POST request:

Request body structure:
                
{
    "token": <access token>, 
    "exp": <expiration time>
}
                
            

POST HTTPS://{TPPURI}/

Field Type Description
<expiration time> String This is token expiration time in yyyy-MM-dd HH:mm:ss format
<access token> String Access token that was used to request the access
{TPPURI} URI address pre configured in system for given third party service provider

Keep in mind that this request requires payment service user consent, thus it may take some time before callback is fired.

GET BALANCE

Request body structure:
                
{
    "EUR": <balance>,
    ...
    <CCC>: <balance>
}
                
            

GET https://mytu.live/ais/<access token>/BALANCE

This request has to be made as GET method when TPP needs to receive client balance(s) to provide service for PSU

If HTTP response code to request is 200 response will contain JSON object with the following content:

Field Type Description
<CCC> String Currency code for the balance. Samples: EUR, GBP
<balance> Double Balance for the given currency in major value. Sample: 10.99

GET TRANSACTIONS

Request body structure:
                
[
    <TRAN>, ...., <TRAN>
]
                
            

GET https://mytu.live/ais/<access token>/LIST

This request has to be made as GET method when TPP needs to receive client transaction list

If HTTP response code to request is 200 response will contain JSON array with the following content:

Field Type Description
<TRAN> specified in Common Data Structures and Definitions

API for Payment Initiation Services

As PISP TPP can get initiate payment on behalf of Travel Union Payment Service User (PSU). PSU will be notified about pending payment request and will have to either confirm or decline it. Payment request may also expire.

The following requests require secret APIKEY in Authorization header available to developers only and has to be protected accordingly.

Keep in mind that requests that require payment service user consent may take some time before callback is fired.

REQUEST ACCESS

Request body structure:
                
{
    "acc": <account id>
}
                
            

POST https://mytu.live/pis/<access token>

This request has to be made as POST method and request body has to contain UTF8 encoded JSON. It is sent from PISP system (not a browser for customer facing device) to the server when PSU expressed will to give access to his account for TPP.

Field Type Description
<account id> String This is string value that contains either PSU phone number that is linked to his account like +37060000000 or IBAN like LT000000000000000000
<access token> String String consisting of following characters [0…9][A…Z][a…z] from 20 up to 40 chars long. If approved, it will become access token for TPP to initiate payments.

API Host may respond with various HTTP response codes indicating different reasons for decline like 401 for unauthorized access, or 400 for account not found.

If HTTP response code to request is 200 TPP system should expect a call back with the following JSON object in POST request:

Request body structure:
                
{
    "token": <access token>,
    "exp": <expiration time>
}
                
            

POST HTTPS://{TPPURI}/

Field Type Description
<access token> String Access token that was used to request the access
<expiration time> String This is token expiration time in yyyy-MM-dd HH:mm:ss format.

INITIATE PAYMENT

Request body structure:
                    
    {
        "acc": <account id>,
        "amts": {
	    "<CCC>": <amount>
        },
        "name": <name>,
        "street": <street address>,
        "city": <city>,
        "country": <country code>,
        "msg": <message>,
        "time": <local time>,
        "tcc": <tran. category>
    }
                    
                

POST https://mytu.live/pis/<access token>/TX/<uuid>

This request has to be made as POST method and request body has to contain UTF8 encoded JSON. It is sent from PISP system (not a browser for customer facing device) to the server.

Field Type Description
<uuid> String Unique payment request identity consisting of following characters [0…9][A…Z][a…z] from 20 up to 40 chars long. It will be used in a callback to inform TPP about request outcome.
<account id> String This is string value that contains receiver account identification it can be in different formats like phone (+37060000000) or IBAN (LT000000000000000000)
<name> String Name of the money receiver for display
<street address> String Address of the money receiver
<city> String City of the money receiver
<country code> String Country code of the money receiver in AAA form like LTU, …
<message> String Message attached to transfer
<local time> String Local operation time for proximity payments. yyyy-MM-dd HH:mm:ss
<tran category> String Transaction category code in the following format: <TYPE> - specified in Common Data Structures and Definitions
<CCC> String Currency code Alpha char 3 ISO 4217 like EUR, USD, PLN, …
<amount> Double Amount in Major currency with decimals. like 0.5, 1, 1.99, …

API Host may respond with various HTTP response codes indicating different reasons for decline like 401 for unauthorized access, or 400 for account not found in case of internal account refference.

There is no need to provide name, street, city, country fields of account id is for Travel Union client

If HTTP response code to request is 200 TPP system should expect a call back with the following JSON object in POST request:

POST HTTPS://{TPPURI}/<uuid> the content for this callback will be <TRAN>

Field Type Description
<TRAN> String Specified in Common Data Structures and Definitions
{TPPURI} String URI address pre configured in system for given third party service provider

There may and will be more than one call back for the same payment request if it takes multiple steps to be executed for example like SEPA payment, it will first be POSTED and only later EXECUTED. This can be seen from TLC (transaction life cycle) property in transaction data.

Payment Initiation fall back

Payments can also be initiated trough QR Code, Link or NFC Tag. If Payment Initiation is not possible due to API endpoint failure unavailable, third party provider can trigger payment by asking Client to scan QR Code, or open a Link (that will trigger application switch on mobile device), or through NFC (in the future). With payment initiation he (customer) is asked to confirm his intent to perform given payment.

This method differs from PISP payment initiation in a way that it does not create outstanding payment request and is never eligible for frictionless payments, but instead fills all the blanks for payment that customer can perform. For better integration in to regular flow PISP should use CALLBACK URI format, as payment processing result will be posted into that URI and same processing flow can be applied.

In case payment needs to be initiated from Desktop or Tablet generate QR code for client to scan. If client uses Mobile Phone with myTU app on it, he can click on link to achieve same effect as qr code scan. Use the following format for clickable link: https://mytu.live/scan?CONTENT where CONTENT is QR Code content (uri encoded)

Client Authentication For Third Party Services

Travel Union has service for customer to authenticate (identify himself) at Third Party Services by the means of QR Code or NFC scan (or possibly other means in the future). This code is scanned by Travel Union Customer (User) with mobile app and is informed about TPSP and what kind of information he will receive. This may include customer name, shipping address, email or phone. If customer gives his consent TPSP will receive required customer information after customer authentication.

Authentication Code

TPSP needs to generate Authentication Code (string value) for customer to scan (in QR code format). This is the format that it needs to be in:

LOGIN:<CALLBACK URI>

Field Type Description
<CALLBACK URI> String This is url address where system will initial send GET request and if customer approves authentication system will send POST with client data. Url has to be without HTTPS:// prefix.
Request body structure:
                    
{
    "name": <entity name>,
    "perm": ["NAME","PHONE","EMAIL","ADDRESS","ID"],
    "code": <verification code>
}
                    
                

When customer scans qercode system will make signed GET HTTPS://<CALLBACK URI> request. Url should contain unique login identification. System expects valid TLS certificate and the following json content in response:

Field Type Description
<entity name> String The name of entity that wants to get user identity
perm String Field represents a set of information that Third Party wants to receive
<verification code> String Value is optional and if present is presented for User, and User can enter it at third party UI as additional security measure.
Request body structure:
                    
{
    "id": <customer id>,  // integer
    "token": <access token>, // string, for use to initiate payment request
    "name": <name>,  // string
    "phone": <phone>,  // string
    "email": <email>,  // string
    "address": <address>,  // string, street address
    "city": <city>,  // string
    "country": <country code>,  // 3 chars ISO
    "code": <person code> // string
}
                    
                

If user confirms login, system will send a call back with the following JSON object in POST request:

POST HTTPS://<CALLBACK URI>

Properties are self explaining by property name and all except <customer id> are optional and may not be present in object information.

Payment QR Code/NFC Code

QR Codes (scan links) can be used to initiate client payment operations. There are few different types of QR Codes, that have different payment processing flow.

Standalone QR Codes

This is a type of QR Code that contains full payment information and is used to “prefill” all the fields for the payment just like client would do that on his own. This method does not support any callbacks or hooks and does not integrate into any systems.

System supports two different QR Code formats for this kind of operation:

  • Standart EPC QR Code - specified by EPC and used by many countries
  • TX:<ACC>:<NAME>:<CCC>:<AMT>:<TYPE>:<MSG>

It all starts with client scanning QR Code and then confirming or canceling the payment.

Custom QR Code uses : to separate field, thus values cannot contain it (pay attention for NAME and MSG fields). If QR Code values does not correspond to the structure or will contain invalid values. It will simply be unreadable and will not initiate payment sequence for customer.

Field Type Description
<ACC> String This is string value that contains either phone number that is linked to Travel Union managed account like +37060000000 or IBAN like LT000000000000000000
<NAME> String Name of the money receiver or originator for display
<CCC> String Currency code Alpha char 3 ISO 4217 like EUR, USD, PLN, …
<AMT> Double Amount in Major currency with decimals. like 0.5, 1, 1.99, …
<TYPE> String Transaction Category Type value specified in Common Data Structures and Definitions
<MSG> String Message attached to transfer. Cannot contain any special characters and : Stick to [A-Z,a-z,0-9, -_.#@!$%&*]

Merchant QR Code

This is a type of QR Code that is used by Travel Union clients (legal entities) to receive payments into account from “customer”, using QR Code/scan link.

System supports the following QR Code format for this kind of operation:

  • TX:<CALLBACK URI>

It all starts with QR Code (or scan link) generation and visual presentation. When customer scans QR code with CALLBACK URI, system will initialy perform:

Response body structure:
                    
{
    "name": <name>,
    "acc": <account id>,
    "amts": {
    	"<CCC>": <amount>
    },
    "msg": <message>,
    "tcc": <transaction category>
}
                    
                

GET HTTPS://<CALLBACK URI>

and it will expect the following json object with properties (see an example in the column on the right)

it will then send payment information details to the payer’s app, and if payer will confirm payment, system will create transaction record in merchants account and will POST payment details in the form of <TRAN> as sgined content to <CALLBACK URI>.

It is up to merchants system to trigger customer view update/redirect to success page upon payment completion.

Field Type Description
<name> String Name of the money receiver or originator for display
<account id> String This is string value that contains Travel Union issued IBAN, for legal entity, to receive payment to
<message> String Message attached to transfer (not visible to payer, part of payment record)
<tran. category> String (Optional) Transaction category code in the following format: <TYPE> - specified in Common Data Structures and Definitions
<CCC> String Currency code Alpha char 3 ISO 4217 like EUR, USD, PLN, ...
<amount> Double Amount in Major currency with decimals. like 0.5, 1, 1.99, ...
<CALLBACK URI> String This is unique merchants call back (back end) url. Do not use HTTPS:// prefix, system will add it on its own.
<TRAN> String Specified in Common Data Structures and Definitions

Payment Initiation Fallback for TPP

The flow for this type of QR Code is very similar to Merchant QR Code payment scenario. The difference is the content of payment details that has to be sent in response to GET request. And it allows any valid SEPA (not justTravel Union isued) account numbers.

It all starts with QR Code (or scan link) generation and visual presentation for customer. When customer scans QR code URI, system will initialy perform:

GET HTTPS://<CALLBACK URI>

And it will expect the same json content as in payment initiation request to create payment order!

If user confirms given payment order, system will send a call back with the following JSON object in POST request:

POST HTTPS://<CALLBACK URI>

Field Type Description
<CALLBACK URI> String This is unique third party providers call back (back end) url. Recommended format: {TPPURI}/<uuid> Do not use HTTPS:// prefix, system will add it on its own.
<TRAN> String Specified in Common Data Structures and Definitions

Receive payment with payment card (online)

This is a way for a Travel Union client (legal entity) to receive money into account from “customer”, using online card payment.

It all starts with merchants web site making a:

POST request to https://mytu.live/cardrx

or for development/test enviroment:

POST request to https://mytu.dev/cardrx

                    POST request to https://mytu.live/cardrx and https://mytu.dev/cardrx expects the following payload:
                    
{
    "uri": <CALLBACK URI> 
}
                    
                

At that point system will initialy perform:

GET request to HTTPS://<CALLBACK URI>

                    GET HTTPS://<CALLBACK URI> expects the following JSON response:
                    
{
    "acc": <account id>, 
    "cur": <CCC>, 
    "amt": <amount>, 
    "msg": <message>, 
    "tcc": <tran. category>, 
    "success": <success uri>, 
    "failure": <failure uri>
}
                    
                

then it will create transaction request record in clients account, form payment request in payment gateway, and then it will redirect customer browser to payment gateway for for card data and 3DS authentication. When payment is completed or canceled, customer browser will be redirected to <success uri> or <failure uri> address, but that can only be used to trigger some page to be loaded (not to be treated as a transaction result), as true status of payment is always POST’ed as sgined content to <CALLBACK URI>.

When customer will make a payment/or payment will fail, system will update payment request record. It will also send a signed POST request with a JSON object in the body: <TRAN>

POST HTTPS://<CALLBACK URI>



Field Type Description
<account id> String This is string value that contains Travel Union issued IBAN, for legal entity, to receive payment to
<message> String Message attached to transfer (not visible to payer, part of payment record)
<tran. category> String Transaction category code in the following format: <TYPE> - specified in Common Data Structures and Definitions
<CCC> String Currency code Alpha char 3 ISO 4217 like EUR, USD, PLN, ...
<amount> Decimal Amount in Major currency with decimals. like 0.5, 1, 1.99, ...
<CALLBACK URI> String This is url address where system will initial send GET request for payment details, and then it will POST payment status changes. It must be unique for every payment. Do not use HTTPS:// prefix, system will add it on its own.
<success uri> String This is url address where gateway will redirect users browser after success.
<failure uri> String This is url address where gateway will redirect users browser after failure.
<TRAN> String Specified in Common Data Structures and Definitions