Generate a signature

Learn how to create a signature for your API requests. This is required for all requests to dLocal’s API.

What is a signature, and why is it required?

A signature acts as a security mechanism to verify your identity and protect your data when making requests to dLocal’s API. Think of it as a digital fingerprint, created by combining your API credentials, the current timestamp, and the data you're sending. This ensures that every request originates from an authorized source and hasn't been tampered with in transit.

How to generate a signature

The steps below apply to the standard HMAC-based authentication (not certificate-based). For certificate-based authentication, please refer to Mutual TLS Certificates.

  1. Get your credentials
    You'll need your x-login, x-trans-key, and secret key. You can learn how to find find them in the Get API credentials article.

  2. Prepare the data to sign
    Concatenate your x-login, the current timestamp (x-date), and the request body. Concatenate the values as: x-login + x-date + requestBody (all as strings, no delimiters).

  3. Generate the signature
    Use HMAC SHA256 with your secret key to hash the data you have prepared following the previous step.

  4. Add the signature to your request
    Include it in the Authorization header.

Required headers

HeaderTypeDescription
X-DateStringISO8601 Datetime with Timezone. Example: 2018-07-12T13:46:28.629Z
X-LoginStringIdentifies the merchant making the request. Find your keys in the Merchant Dashboard
X-Trans-KeyStringUsed along with x-login to authenticate the request. Find your keys in the Merchant Dashboard
Content-TypeStringAlways complete application/json
X-VersionStringCurrent API Version number: 2.1
User-AgentStringIdentifies the application type, operating system, or software version of the requesting user agent
AuthorizationStringUse the format: V2-HMAC-SHA256, Signature: <hmac(secretKey, "X-Login+X-Date+RequestBody")>

Signature differences for Payins and Payouts

Note. You can start with the basic signature method above. The differences below are relevant when you're ready to implement both payment types.

Payins signatures

For payment operations (accepting payments):

  • Use the HMAC-SHA256 algorithm with the format: V2-HMAC-SHA256, Signature: <signature>
  • Signature data includes: x-login + x-date + RequestBody
  • Include as the Authorization header in your request

Payouts signatures

For disbursement operations (sending money):

  • Use the HMAC-SHA256 algorithm with the signature in hexadecimal lowercase format
  • Signature data uses the request payload as the data to be hashed
  • The signature must be included in the Payload-Signature header

Important. Always check the specific documentation for Payins or Payouts to ensure you're using the correct signature format.

Using the signature in headers

For Payins

curl -X POST \
   -H 'X-Date: {x-date}' \
   -H 'X-Login: {x-login}' \
   -H 'X-Trans-Key: {x-trans-key}' \
   -H 'Content-Type: application/json' \
   -H 'X-Version: 2.1' \
   -H 'User-Agent: MerchantTest / 1.0 ' \
   -H 'Authorization: V2-HMAC-SHA256, Signature: {Signature}' \
   -d '{body}'
    https://api.dlocal.com/payments

For Payouts

The signature process differs slightly; specifically, the signature data uses the request payload as the data to be hashed.

You can find detailed requirements in our Payouts Security documentation.

Examples of HMAC signature generation

Our GitHub repository hosts a variety of signature examples, which can be a valuable resource for understanding implementation details and for reference in your development process.

Check out signature examples on GitHub >

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.Formatter;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;

public final class SignatureCalculator {

    private static final String HMAC_ALGORITHM = "HmacSHA256";
    private static final String CHARSET = "UTF-8";

    public static String calculateSignature(String x_Login, String x_Date, String secretKey, String body)
        throws IOException, InvalidKeyException, NoSuchAlgorithmException {

        // Create byte array with the required data for the signature.
        ByteArrayOutputStream bout = new ByteArrayOutputStream();
        bout.write(x_Login.getBytes(CHARSET));
        bout.write(x_Date.getBytes(CHARSET));
        bout.write(body.getBytes(CHARSET));

        // Calculate the signature.
        SecretKeySpec signingKey = new SecretKeySpec(secretKey.getBytes(), HMAC_ALGORITHM);
        Mac mac = Mac.getInstance(HMAC_ALGORITHM);
        mac.init(signingKey);
        byte[] signature = mac.doFinal(bout.toByteArray());

        // Create a String with the signature value.
        Formatter formatter = new Formatter();
        for (byte b : signature) {
            formatter.format("%02x", b);
        }
        return formatter.toString();
    }
}
$signature = hash_hmac("sha256", "$X-Login$X-Date$RequestBody", $secretKey);
signature = hmac.new(secretKey, X-Login+X-Date+RequestBody, hashlib.sha256).hexdigest()
signature = OpenSSL::HMAC.hexdigest('sha256', secretKey, $X-Login + $X-Date + RequestBody)

import * as crypto from 'crypto';

class SignatureCalculator {
    calculateSignature(timestamp: string, body?: string): string {
        let message: string = process.env.DLOCAL_X_LOGIN + timestamp;

        if (body) {
            message += body;
        }

        const hmac = crypto.createHmac('sha256', process.env.DLOCAL_SECRET_KEY);
        hmac.update(message, 'utf-8');
        const signature: string = hmac.digest('hex');

        return `V2-HMAC-SHA256, Signature: ${signature}`;
    }
}

// Example usage
const calculator = new SignatureCalculator();
const timestamp = new Date().toISOString(); // Corrected the timestamp
const body = "yourRequestBody";
const result = calculator.calculateSignature(timestamp, body);
console.log(result);
function calculateSignature(timestamp, body) {
    let message = process.env.DLOCAL_X_LOGIN + timestamp;

    if (body) {
        message += body;
    }

    const hmac = crypto.createHmac('sha256', process.env.DLOCAL_SECRET_KEY);
    hmac.update(message, 'utf-8');
    const signature = hmac.digest('hex');

    return `V2-HMAC-SHA256, Signature: ${signature}`;
}

// Example usage
const timestamp = new Date().toISOString(); // Set timestamp to current time
const body = "yourRequestBody";
const result = calculateSignature(timestamp, body);
console.log(result);
static string SignatureCalculator(string x_Login, string x_Date, string secretKey, string body)
    {
        string concatenatedData = x_Login + x_Date + body;
        byte[] data = Encoding.UTF8.GetBytes(concatenatedData);
        byte[] keyBytes = Encoding.UTF8.GetBytes(secretKey);

        using (var hmacsha256 = new HMACSHA256(keyBytes))
        {
            byte[] hashBytes = hmacsha256.ComputeHash(data);
            StringBuilder signatureBuilder = new StringBuilder();

            foreach (byte b in hashBytes)
            {
                signatureBuilder.Append(b.ToString("x2"));
            }

            return signatureBuilder.ToString();
        }
    }