TunnelPayment API (1.0)

Download OpenAPI specification:Download

TunnelPayment API

HMAC Signature

To authenticate requests, you must generate a signature using your private key. The signature is generated by concatenating the following parameters in the order they are listed, separated by an ampersand (&), and then hashing the resulting string using the SHA-512 algorithm.

  • apiKey: Your API key
  • dataHash: SHA-512 hash of the request body
  • nonce: A unique value for each request
  • path: The request path parameters are concatenated in the following format

apiKey=your_api_key&dataHash=sha512_hash_of_request_body&nonce=unique_nonce&path=request_path

The resulting hash is then encoded as a hexadecimal string and sent in the X-Signature header. You must include your API key in the X-API-Key, nonce in the X-Nonce, and signature in the X-Signature headers.

Code Examples

package main

import (
    "bytes"
    "crypto/hmac"
    "crypto/sha512"
    "encoding/hex"
    "fmt"
    "net/http"
)

const APIKEY = "123456"
const PRIVATE_KEY = "1234567890"

func makeSignature(bodyString, privateKey, path, nonce string) string {
    signData := map[string]string{
        "apiKey":   APIKEY,
        "dataHash": fmt.Sprintf("%x", sha512.Sum512([]byte(bodyString))),
        "nonce":    nonce,
        "path":     path,
    }
    params := fmt.Sprintf("apiKey=%s&dataHash=%s&nonce=%s&path=%s", signData["apiKey"], signData["dataHash"], signData["nonce"], signData["path"])
    fmt.Println(params)
    signMaker := hmac.New(sha512.New, []byte(privateKey))
    signMaker.Write([]byte(params))
    return hex.EncodeToString(signMaker.Sum(nil))
}

func generateNonce() string {
    return "1234567890"
}

func main() {
    url := "https://api.tunnelpayment.com/api/v1/checkout"
    nonce := generateNonce()
    body := []byte(`{"amount": 3.14, "currency": "USD", "callback_url": "https://example.com/callback", "success_url": "https://example.com/success", "cancel_url": "https://example.com/cancel"}`)
    req, _ := http.NewRequest("POST", url, bytes.NewBuffer(body))
    req.Header.Set("Content-Type", "application/json")
    req.Header.Set("X-API-Key", APIKEY)
    req.Header.Set("X-Nonce", nonce)
    req.Header.Set("X-Signature", makeSignature(string(body), PRIVATE_KEY, "/api/v1/checkout", nonce))
    client := &http.Client{}
    resp, err := client.Do(req)
    if err != nil {
        fmt.Println(err)
        return
    }
    defer resp.Body.Close()
    fmt.Println(resp.Status)
}
import requests
import hashlib
import hmac

API_KEY = "123456"
PRIVATE_KEY = "1234567890"

def make_signature(body_string, private_key, path, nonce):
    api_key = API_KEY
    data_hash = hashlib.sha512(body_string.encode()).hexdigest()
    sign_data = f"apiKey={api_key}&dataHash={data_hash}&nonce={nonce}&path={path}"
    signature = hmac.new(private_key.encode(), sign_data.encode(), hashlib.sha512).hexdigest()
    return signature

def generate_nonce():
    return "1234567890"

url = "https://api.tunnelpayment.com/api/v1/checkout"
nonce = generate_nonce()
body = '{"amount": 3.14, "currency": "USD", "callback_url": "https://example.com/callback", "success_url": "https://example.com/success", "cancel_url": "https://example.com/cancel"}'

headers = {
    "Content-Type": "application/json",
    "X-API-Key": API_KEY,
    "X-Nonce": nonce,
    "X-Signature": make_signature(body, PRIVATE_KEY, "/api/v1/checkout", nonce)
}

response = requests.post(url, data=body, headers=headers)
print(response.status_code)
using System;
using System.Net.Http;
using System.Security.Cryptography;
using System.Text;

namespace CryptoCheckout
{
    public class Program
    {
        private const string ApiKey = "123456";
        private const string PrivateKey = "1234567890";

        public static void Main(string[] args)
        {
            string url = "https://api.tunnelpayment.com/api/v1/checkout";
            string nonce = GenerateNonce();
            string body = "{\"amount\": 3.14, \"currency\": \"USD\", \"callback_url\": \"https://example.com/callback\", \"success_url\": \"https://example.com/success\", \"cancel_url\": \"https://example.com/cancel\"}";

            using (HttpClient client = new HttpClient())
            {
                HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, url);
                request.Content = new StringContent(body, Encoding.UTF8, "application/json");
                request.Headers.Add("X-API-Key", ApiKey);
                request.Headers.Add("X-Nonce", nonce);
                request.Headers.Add("X-Signature", MakeSignature(body, PrivateKey, "/api/v1/checkout", nonce));

                HttpResponseMessage response = client.SendAsync(request).Result;
                Console.WriteLine(response.StatusCode);
            }
        }

        private static string MakeSignature(string bodyString, string privateKey, string path, string nonce)
        {
            string apiKey = ApiKey;
            string dataHash = GetSha512Hash(bodyString);
            string signData = $"apiKey={apiKey}&dataHash={dataHash}&nonce={nonce}&path={path}";

            using (HMACSHA512 hmac = new HMACSHA512(Encoding.UTF8.GetBytes(privateKey)))
            {
                byte[] signatureBytes = hmac.ComputeHash(Encoding.UTF8.GetBytes(signData));
                return BitConverter.ToString(signatureBytes).Replace("-", "").ToLower();
            }
        }

        private static string GetSha512Hash(string input)
        {
            using (SHA512 sha512 = SHA512.Create())
            {
                byte[] inputBytes = Encoding.UTF8.GetBytes(input);
                byte[] hashBytes = sha512.ComputeHash(inputBytes);
                return BitConverter.ToString(hashBytes).Replace("-", "").ToLower();
            }
        }

        private static string GenerateNonce()
        {
            return "1234567890";
        }
    }
}
const axios = require('axios');

const API_KEY = '123456';
const PRIVATE_KEY = '1234567890';

function makeSignature(bodyString, privateKey, path, nonce) {
    const apiKey = API_KEY;
    const dataHash = getSha512Hash(bodyString);
    const signData = `apiKey=${apiKey}&dataHash=${dataHash}&nonce=${nonce}&path=${path}`;
    const signature = crypto.createHmac('sha512', privateKey).update(signData).digest('hex');
    return signature;
}

function getSha512Hash(input) {
    return crypto.createHash('sha512').update(input).digest('hex');
}

function generateNonce() {
    return '1234567890';
}

const url = 'https://api.tunnelpayment.com/api/v1/checkout';
const nonce = generateNonce();
const body = JSON.stringify({
    amount: 3.14,
    currency: 'USD',
    callback_url: 'https://example.com/callback',
    success_url: 'https://example.com/success',
    cancel_url: 'https://example.com/cancel'
});

const headers = {
    'Content-Type': 'application/json',
    'X-API-Key': API_KEY,
    'X-Nonce': nonce,
    'X-Signature': makeSignature(body, PRIVATE_KEY, '/api/v1/checkout', nonce)
};

axios.post(url, body, { headers })
    .then(response => {
        console.log(response.status);
    })
    .catch(error => {
        console.error(error);
    });

Webhook

Request

header: {
    "talaps-signature": "DEMO-SIGNATURE"
}
body: {
   "data":{
      "amount":2,
      "currency":"USD",
      "uuid":"123e4567-e89b-12d3-a456-426614174000",
      "created_at":"2021-01-01T00:00:00Z",
      "valid_until":"2021-01-01T00:20:00Z",
      "status":"PAID",
      "success_url":"",
      "cancel_url":"",
      "merchant":{
         "uuid":"",
         "name":"Acme Corp",
         "logo_url":""
      },
      "asset_options":null,
      "asset":null,
      "deposit_address":null,
      "deposit_amount":null,
      "paid_amount":null,
      "receipt_email":null,
      "confirmations_required":null,
      "confirmations_completed":null
   }
}

Header Signature

To use webhooks, first, specify your Notification URL in the API section of the panel. Make sure the URL you provide is public and listening for POST requests. Then, create your signature. Remember, you can only view your signature once, so ensure you store it securely and make sure to redact the talaps-signature field in your logs. If the webhook request is responded to with a 200 or 201 status code, it will not resend the POST request to the relevant endpoint.

Code Examples

const express = require('express');
const bodyParser = require('body-parser');

const app = express();
const port = 3000;
const DEMO_SIGNATURE = 'DEMO-SIGNATURE';

app.use(bodyParser.json());

app.post('/demo-webhook', (req, res) => {
  const signature = req.headers['talaps-signature'];

  if (!signature || signature !== DEMO_SIGNATURE) {
    console.info("Signatures don't match.");
    return res.status(401).send('Invalid signature');
  }

  console.log(req.body)
  res.status(200).send('OK');
});

app.use((req, res) => {
  res.status(404).send('Not Found');
});

app.listen(port, () => {
  console.log(`Demo-Server running on port:${port}`);
});

Transaction

Get Transactions

Get transactions details

Authorizations:
(AuthAPIKeyAuthNonceAuthSignature)
query Parameters
page
integer
Default: 1

Page number

limit
integer
Default: 50

Page limit (25, 50, 100)

Responses

Response samples

Content type
application/json
{
  • "count": 25,
  • "data": [
    ],
  • "page": 1,
  • "total": 432
}

Checkout

Create Checkout

Initialize a new checkout session

Authorizations:
(AuthAPIKeyAuthNonceAuthSignature)
Request Body schema: application/json
required

Create Checkout Request

amount
required
number
cancel_url
required
string
currency
required
string
success_url
required
string

Responses

Request samples

Content type
application/json
{}

Response samples

Content type
application/json
{}

Get Checkout

Get checkout details

Authorizations:
(AuthAPIKeyAuthNonceAuthSignature)

Responses

Response samples

Content type
application/json
{}