WaffarX Signature

Overview

WaffarX API requires each request to be accompanied by a digital signature for authentication. This signature is an HMAC-SHA256 digest that ensures the request data has not been altered and that it comes from an authorized client. To generate the signature, you will use your Client Key (a public identifier for your application) and your Client Secret (a private key known only to you and WaffarX). The Client Secret is used to sign each request, while the Client Key identifies which client is making the request.

Caution

Protect your client secret. Do not expose it in client-side code or share it. Anyone with your secret could generate valid signatures and impersonate your requests.

The signature generation involves hashing the request payload, formatting the current timestamp, and computing an HMAC-SHA256 using your client secret. The resulting signature is then sent in the request headers for WaffarX to verify. If any part of the signature is incorrect, the server will reject the request with an authentication error.

When to Use the Signature

The signature is required for all authenticated API endpoints. It must be generated for each request and included alongside:

  • wxc-auth: Contains the generated signature

  • wxc-date: UTC timestamp used in the signature

  • wxc-id: Your WaffarX client Id

  • Other required headers (e.g., accept-language, content-type, etc.)

Signature Generation Steps

Follow these simplified steps in order to create your request signature:

  1. Hash the payload If your request has a body, first trim whitespace and lowercase the content, then compute its SHA-256 and hex-encode it:

    Note

    If there is no request body, skip this step entirely and do not include a payload hash in your string to sign.

  2. Build the string to sign

    • No payload: Concatenate four components with hyphens (-):

      METHOD-ACTION_NAME-CLIENT_KEY-TIMESTAMP

      Example (no payload)
        get-/api/valu/getstores-9E102E81-2EDF-4C79-8EBA-25DD2B563281-20240424T123456Z
      
    • With payload: Concatenate five components with hyphens (-):

      METHOD-ACTION_NAME-CLIENT_KEY-TIMESTAMP-PAYLOAD_HASH

      Example (with payload)
       post-/api/valu/search-9E102E81-2EDF-4C79-8EBA-25DD2B563281-20240424T123456Z-3a5f1d2e4c...
      

      Where:

      • METHOD = get | post  (lower-case path)

      • ACTION_NAME = /api/valu/getstores` (lower-case path)

      • CLIENT_KEY = <CLIENT_KEY>

      • TIMESTAMP = 20240424T123456Z` (ISO8601 format `yyyyMMddTHHmmssZ`)

      • PAYLOAD_HASH is the lowercase hex SHA-256 of your trimmed-and-lowercased body. 3a5f1d2e4c...

    Note

    Make sure each component (especially ACTION_NAME and TIMESTAMP) matches exactly how you send the request.

  3. Compute HMAC-SHA256 Convert your secret key to UTF-8 bytes, compute the HMAC over the string-to-sign, and hex-encode the result then convert it to string, you will get the final signature.

  4. Send the request Include this signature in your HTTP call:

    • wxc-auth: {signature}

    Note

    The timestamp header value must exactly match the one you used when building the string to sign.

Code Examples

using System;
using System.Globalization;
using System.Security.Cryptography;
using System.Text;

public class HelloWorld
{
   public static string GenerateSignature(
      string payload,
      string method,
      string actionName,
      string clientkey,
      string clientSecret,
      string HeaderDate)
   {
      // parse date as UTC
      var datetime = DateTime.Parse(
            HeaderDate,
            CultureInfo.InvariantCulture,
            DateTimeStyles.AdjustToUniversal);

      // 1) trim & lowercase payload
      var serializedData = payload.Trim().ToLowerInvariant();

      // 2) SHA-256 of payload
      byte[] hashedBytes;
      using (var sha256 = SHA256.Create())
            hashedBytes = sha256.ComputeHash(Encoding.UTF8.GetBytes(serializedData));

      var payloadHashHex = new StringBuilder();
      foreach (var b in hashedBytes)
            payloadHashHex.Append(b.ToString("x2"));

      // 3) format date as "yyyyMMddTHHmmssZ"
      const string fmt = "yyyyMMddTHHmmssZ";
      var dateString = datetime.ToString(fmt, CultureInfo.InvariantCulture);

      // 4) build the string-to-sign (note lowercase method & actionName)
      string stringToSign = serializedData.Length == 0
            ? $"{method.ToLowerInvariant()}-{actionName.ToLowerInvariant()}-{clientkey}-{dateString}"
            : $"{method.ToLowerInvariant()}-{actionName.ToLowerInvariant()}-{clientkey}-{dateString}-{payloadHashHex}";

      // 5) HMAC-SHA256 over stringToSign
      var keyBytes = Encoding.UTF8.GetBytes(clientSecret);
      byte[] hmacBytes;
      using (var hmac = new HMACSHA256(keyBytes))
            hmacBytes = hmac.ComputeHash(Encoding.UTF8.GetBytes(stringToSign));

      // 6) hex-encode the HMAC
      var sb = new StringBuilder();
      foreach (var b in hmacBytes)
            sb.Append(b.ToString("x2"));

      return sb.ToString();
   }

   public static void Main()
   {
      // test (should now match the Python version below)
      Console.WriteLine(GenerateSignature(
            "YourPayloadString",
            "POST",
            "myEndpoint",
            "ClientKeyABC123",
            "SecretKeyXYZ456",
            "2025-05-01T12:34:56Z"
      ));
   }
}