Toucan Tokenization Overview

Toucan by Pagos allows you to either replace or augment your current vaulting strategy to begin using network tokens in the place of primary account numbers (PAN). With Toucan, we make it easy for you to access network services directly with your own dedicated account, and control how and where you deploy network tokenization.

This guide outlines the two processes Toucan simplifies to make network tokenization more accessible:

  1. Provisioning a token from a primary account number (PAN)
  2. Obtaining a cryptogram for transacting with the network token

📘

Note

After you onboard with Toucan, you’ll have access to our Sandbox environment. At this time, however, all actions and processes in Toucan must be executed via the API.

Authenticating

To ensure only authorized entities access our services, we authenticate the identity of each client that submits requests to Toucan services. Learn more in our Toucan Authentication guide.

Provisioning a Network Token

“Provisioning a network token” refers to the step you take to convert a PAN into a network token. This is the critical step that signals to an issuer that your company is establishing a relationship with a cardholder that will persist over time. Every time you use the network token for a transaction, that context is accessible to the issuer.

You can provision a network token on POST: /tokenize

The following example demonstrates a /tokenize call—including the appropriate authentication signature—with a Mastercard test card:

const fetch = require('node-fetch');
const forge = require('node-forge');

tokenize = async function() { 
    
    const CLIENTKEY = process.env.CLIENTKEY
    const PRIVATEKEY = process.env.PRIVATEKEY
    const APIHOST = process.env.APIHOST
    
    const authorizationScheme = 'V1-HMAC-SHA256';
  
    function computeHash(message, base64key) {
        var key = forge.util.decode64(base64key);
        var hmac = forge.hmac.create();
        hmac.start('sha256', key);
        hmac.update(message);
        return forge.util.encode64(hmac.digest().bytes());
    }

    function createAuthHeader(CLIENTKEY, date, PRIVATEKEY, bodyJ) {
        var payloadToSign = CLIENTKEY + date + bodyJ;
        
        var computedSignature = computeHash(payloadToSign, PRIVATEKEY);
        let header = authorizationScheme + ', Signature: ' + computedSignature;
        return header;
    };

    var body = {
        'accountNumber': '5204736150000216',
        'expirationDate': {
            'year': '2022',
            'month': '12'
        },
        'cvv2': '836',
        'accountHolder': {
            'name': 'Tom',
            'address': {
                'line1': '45 Madison Ave',
                'line2': 'Suite 300',
                'line3': '',
                'city': 'New York',
                'state': 'NY',
                'country': 'USA',
                'postalCode': '10012',
                'phone': '2125551231234'
            }
        }
    };
    let date=new Date().toISOString();
    let bodyJSON = JSON.stringify(body);
    let authHeader = createAuthHeader(CLIENTKEY, date, PRIVATEKEY, bodyJSON);
    
    const res = await fetch(`${APIHOST}/tokenize`, {
      headers: { 
        'Content-Type': 'application/json',
        'X-Client-Key': CLIENTKEY,
        'X-Date': date,
        'Authorization': authHeader
      },
      method: 'POST',
      body: bodyJSON
    });
    console.log(await res.json());
}

tokenize();

Transacting With a Network Token

Before you can process a transaction with a network token, you must first fetch a cryptogram for that token. A cryptogram is an issuer-generated value for the transaction you’re processing, and is a key mechanism to the additional trust issuing banks give network tokens.

You can test this using the API on POST: /transact

The following example demonstrates a tokenize and transact call with a Mastercard test card:

const fetch = require('node-fetch');
const forge = require('node-forge');

const config = {
    CLIENTKEY: process.env.CLIENTKEY,
    PRIVATEKEY: process.env.PRIVATEKEY,
    APIHOST: process.env.APIHOST
}

const authorizationScheme = 'V1-HMAC-SHA256';

function computeHash(message, base64key) {
    var key = forge.util.decode64(base64key);
    var hmac = forge.hmac.create();
    hmac.start('sha256', key);
    hmac.update(message);
    return forge.util.encode64(hmac.digest().bytes());
}

function createAuthHeader(clientKey, date, privateKey, bodyJ) {
    var payloadToSign = clientKey + date + bodyJ;
    
    var computedSignature = computeHash(payloadToSign, privateKey);
    let header = authorizationScheme + ', Signature: ' + computedSignature;
    return header;
};

function createHeaders(cfg, bodyJSON) {
    let date=new Date().toISOString();
    let authHeader = createAuthHeader(cfg.CLIENTKEY, date, cfg.PRIVATEKEY, bodyJSON);
    return { 
        'Content-Type': 'application/json',
        'X-Client-Key': cfg.CLIENTKEY,
        'X-Date': date,
        'Authorization': authHeader
    };
}

async function tokenize(cfg, cardToTokenize ) { 
    let bodyJSON = JSON.stringify(cardToTokenize);
    let headers = createHeaders(cfg, bodyJSON);
    const res = await fetch(`${cfg.APIHOST}/tokenize`, {
      headers: headers,
      method: 'POST',
      body: bodyJSON
    });
    
    return await res.json();
}

async function transact(cfg, tokenRef) { 
    let bodyJSON = JSON.stringify({});
    let headers = createHeaders(cfg, bodyJSON);
    const res = await fetch(`${cfg.APIHOST}/transact/${tokenRef}`, {
      headers,
      method: 'POST',
      body: bodyJSON
    });
    
    return await res.json();
}

let card = {
    'accountNumber': '5204736150000216',
    'expirationDate': {
        'year': '2022',
        'month': '12'
    },
    'cvv2': '836',
    'accountHolder': {
        'name': 'Tom',
        'address': {
            'line1': '45 Madison Ave',
            'line2': 'Suite 300',
            'line3': '',
            'city': 'New York',
            'state': 'NY',
            'country': 'USA',
            'postalCode': '10012',
            'phone': '2125551231234'
        }
    }
};

// tokenize this card, and then request a cryptogram from that token
(async () => {
    let token = await tokenize(config, card);
    console.log(token);
    let cryptogram = await transact(config, token.toucanTokenRefId);
    console.log(cryptogram);  
})()

📘

Keep in Mind

When you sell recurring subscriptions, you aren’t required to fetch a cryptogram at this time—you can use the details of the token and the expiration date.