API Reference

Gateway - Generating Signatures

These are the Pay1st best practices for generating signatures for gateway Integrations

Overview

For all non authentication requests, a signature needs to be generated for the intended payload. We do this so that we can validate that API requests have not been tampered with.

Signature Description

The signature is a hex encoded HMAC-SHA256 and is generated and sent using the X-SIGNATURE HTTP request header.
The signature can be generated using the following steps:

  • Prepare the Payload - The payload string is made up of two parts:
    • Timestamp - Generate a timestamp in ISO-8601 format.
    • Request JSON - Use the exact JSON that is sent to the server
  • Create the Payload String - Concatenate the timestamp with the request JSON
    • Generate HMAC-SHA256
    • Use the payload string as the HMAC key.
    • Use the Signing Key (which is obtained from Configuring API Credentials) as the data to sign the payload.
      Ensure that the HMAC result is in lowercase (some languages return this by default).
📘

Timestamp

The same timestamp of this request will also be expected to be sent in the X-Timestamp HTTP Header alongside the X-Signature when submitting API requests to the Pay1st Gateway.

Test Cases

The following table can be used as test cases to check for the correctness of the signature

Expected SignatureTimestampSigning KeyJSON Payload
85aa0862aa052f737d3cf4d38f92091ea7c015e782d207ea18cc5641d3e477552025-03-17T08:10:52.544247646ZhCyO_Flnu6aid-bhFYTYOowkxXRzoZkgzO32rB6Ik8Y{"countryCode":"NG","currencyCode":"NGN","amount":100,"partnerReference":"4a662291-2840-4bcd-aae9-553ab24601ed","callbackSuccessUrl":"<https://callback.success","callbackFailureUrl":"https://callback.failure","callbackPendingUrl":"https://callback.pending","callbackCancelUrl":"https://callback.cancel","webhookUrl":"https://webhook.success","products":[{"title":"10> Credits","sku":"12345","price":100,"quantity":1,"currencyCode":"NGN"}],"metadata":[{"key":"customerId","value":"1"}]}

Code Samples

The following code samples can be used as a reference (or the signature description can be code generated using an LLM)

KEY="YXBpdXNlcjphcGlwYXNzd29yZA=="
PAYLOAD="{\"countryCode\":\"NG\",\"currencyCode\":\"NGN\",\"amount\":100,\"partnerReference\":\"{{pay1stPartnerReference}}\",\"callbackSuccessUrl\":\"https://callback.success\",\"callbackFailureUrl\":\"https://callback.failure\",\"callbackPendingUrl\":\"https://callback.pending\",\"callbackCancelUrl\":\"https://callback.cancel\",\"webhookUrl\":\"https://webhook.success\",\"products\":[{\"title\":\"10Credits\",\"sku\":\"12345\",\"price\":100,\"quantity\":1,\"currencyCode\":\"NGN\"}],\"metadata\":[{\"key\":\"customerId\",\"value\":\"1\"}]}";

echo -en "$PAYLOAD" \
    | openssl sha256 -hmac "$KEY" \
    | awk '{print $2}'
<?php
$payload = "{\"countryCode\":\"NG\",\"currencyCode\":\"NGN\",\"amount\":100,\"partnerReference\":\"{{pay1stPartnerReference}}\",\"callbackSuccessUrl\":\"https://callback.success\",\"callbackFailureUrl\":\"https://callback.failure\",\"callbackPendingUrl\":\"https://callback.pending\",\"callbackCancelUrl\":\"https://callback.cancel\",\"webhookUrl\":\"https://webhook.success\",\"products\":[{\"title\":\"10Credits\",\"sku\":\"12345\",\"price\":100,\"quantity\":1,\"currencyCode\":\"NGN\"}],\"metadata\":[{\"key\":\"customerId\",\"value\":\"1\"}]}";;
$key = "YXBpdXNlcjphcGlwYXNzd29yZA==";

echo hash_hmac('sha256', trim($payload), $key);
import java.nio.charset.Charset;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import org.apache.commons.codec.binary.Hex;

public class Signature {

    public static void main(String[] args) throws Exception {
        String payload = "{\"countryCode\":\"NG\",\"currencyCode\":\"NGN\",\"amount\":100,\"partnerReference\":\"{{pay1stPartnerReference}}\",\"callbackSuccessUrl\":\"https://callback.success\",\"callbackFailureUrl\":\"https://callback.failure\",\"callbackPendingUrl\":\"https://callback.pending\",\"callbackCancelUrl\":\"https://callback.cancel\",\"webhookUrl\":\"https://webhook.success\",\"products\":[{\"title\":\"10Credits\",\"sku\":\"12345\",\"price\":100,\"quantity\":1,\"currencyCode\":\"NGN\"}],\"metadata\":[{\"key\":\"customerId\",\"value\":\"1\"}]}";
        String key = "YXBpdXNlcjphcGlwYXNzd29yZA==";

        Mac hmac = Mac.getInstance("HmacSHA256");
        SecretKeySpec secretKeySpec = new SecretKeySpec(key.getBytes(Charset.defaultCharset()), "HmacSHA256");
        hmac.init(secretKeySpec);

        String signature = new String(Hex.encodeHex(hmac.doFinal(String.format(payload).trim().getBytes(Charset.defaultCharset()))));

        System.out.println(signature);
    }
using System;
using System.Text;
using System.Security.Cryptography;

class Signature
{
    public static void Main (string[] args)
    {
        string payload = "{\"countryCode\":\"NG\",\"currencyCode\":\"NGN\",\"amount\":100,\"partnerReference\":\"{{pay1stPartnerReference}}\",\"callbackSuccessUrl\":\"https://callback.success\",\"callbackFailureUrl\":\"https://callback.failure\",\"callbackPendingUrl\":\"https://callback.pending\",\"callbackCancelUrl\":\"https://callback.cancel\",\"webhookUrl\":\"https://webhook.success\",\"products\":[{\"title\":\"10Credits\",\"sku\":\"12345\",\"price\":100,\"quantity\":1,\"currencyCode\":\"NGN\"}],\"metadata\":[{\"key\":\"customerId\",\"value\":\"1\"}]}";
        string key = "YXBpdXNlcjphcGlwYXNzd29yZA==";

        HMACSHA256 hmac = new HMACSHA256 (Encoding.Default.GetBytes (key));

        byte[] hash = hmac.ComputeHash (Encoding.Default.GetBytes(payload).Trim()));

        string signature = String.Concat(Array.ConvertAll(hash, x => x.ToString("X2")));

        Console.Write (signature);
    }
}
import hmac
import hashlib

key = 'YXBpdXNlcjphcGlwYXNzd29yZA=='
payload = "{\"countryCode\":\"NG\",\"currencyCode\":\"NGN\",\"amount\":100,\"partnerReference\":\"{{pay1stPartnerReference}}\",\"callbackSuccessUrl\":\"https://callback.success\",\"callbackFailureUrl\":\"https://callback.failure\",\"callbackPendingUrl\":\"https://callback.pending\",\"callbackCancelUrl\":\"https://callback.cancel\",\"webhookUrl\":\"https://webhook.success\",\"products\":[{\"title\":\"10Credits\",\"sku\":\"12345\",\"price\":100,\"quantity\":1,\"currencyCode\":\"NGN\"}],\"metadata\":[{\"key\":\"customerId\",\"value\":\"1\"}]}"

print hmac.new(key, (payload).strip(), hashlib.sha256).hexdigest()