Authentication
The new Pago46 Core API uses a security scheme based on HMAC SHA-256 to guarantee the integrity and authenticity of each transaction.
This mechanism ensures that whoever sends the request possesses the correct credentials and that the message has not been altered en route nor is it a repetition of an old request.
Mandatory Headers
Every HTTP request you make to our API must include the following headers:
| Header | Type | Description |
|---|---|---|
Provider-Key | String | Your unique provider identifier (API Key). |
Message-Date | Timestamp | Unix Timestamp (floating point seconds or milliseconds). |
Message-Hash | String | The hexadecimal result of the calculated HMAC signature. |
The server will validate that the difference between the sent Message-Date and the current server time is not greater than 24 hours. If the time exceeds this range, the request will be rejected to prevent replay attacks.
Signature Algorithm
To generate a valid Message-Hash, you must strictly follow the algorithm below to construct the signature string.
1. String Construction (String to Sign)
Unlike previous versions, this flow does not require sorting parameters alphabetically. The string is constructed by concatenating the following values separated by colons (:):
- Provider Key
- Message Date (The same value sent in the header)
- HTTP Method (E.g.,
POST,GET) - Path (The resource path, e.g.,
/api/v1/payments) - Body (The raw body of the request in UTF-8)
Format:
PROVIDER_KEY:MESSAGE_DATE:METHOD:PATH:BODY
If the request is GET and has no body, the BODY value must be an empty string. If it is a POST with JSON, make sure to use the exact JSON string you will send in the request, without extra spaces or modifications.
2. Hash Generation
Once the string is built, you must sign it using:
- Algorithm: HMAC SHA-256
- Secret: Your
Provider Secret(provided by Pago46) - Message: The string built in step 1.
- Output: Hexdigest (hexadecimal string).
Implementation Examples
Below, we present how to generate this signature in different languages.
- Python
- Node.js
- Go
import hmac
import hashlib
import time
import requests
import json
def send_authenticated_request(provider_key, provider_secret, method, path, body_dict=None):
# 1. Prepare data
host = "[https://api.pago46.com](https://api.pago46.com)"
timestamp = str(time.time()) # Current Timestamp (float as string)
# If there is a body, convert to JSON string, otherwise, it is empty
body_str = json.dumps(body_dict) if body_dict else ""
# 2. Build the signature string (IMPORTANT: Separator is ":")
# Format: KEY:DATE:METHOD:PATH:BODY
string_to_sign = f"{provider_key}:{timestamp}:{method}:{path}:{body_str}"
# 3. Calculate HMAC SHA-256
calculated_hmac = hmac.new(
provider_secret.encode("utf-8"),
string_to_sign.encode("utf-8"),
hashlib.sha256
).hexdigest()
# 4. Send Request
headers = {
"Provider-Key": provider_key,
"Message-Date": timestamp,
"Message-Hash": calculated_hmac,
"Content-Type": "application/json"
}
response = requests.request(
method=method,
url=f"{host}{path}",
headers=headers,
data=body_str
)
return response
# Usage
response = send_authenticated_request(
provider_key="PK_12345",
provider_secret="SECRET_XYZ",
method="POST",
path="/api/v1/payments/",
body_dict={"amount": 100, "currency": "CLP"}
)
print(response.status_code)
const crypto = require('crypto');
const axios = require('axios');
async function sendAuthenticatedRequest(providerKey, providerSecret, method, path, body = null) {
// 1. Current Timestamp
const timestamp = (Date.now() / 1000).toString(); // Python uses float seconds, JS uses ms. Adjust per backend.
// Note: Backend accepts float timestamp. Date.now() / 1000 is compatible.
// 2. Body string
const bodyStr = body ? JSON.stringify(body) : '';
// 3. Build string (Separator ":")
const stringToSign = [
providerKey,
timestamp,
method,
path,
bodyStr
].join(':');
// 4. Calculate HMAC
const signature = crypto
.createHmac('sha256', providerSecret)
.update(stringToSign)
.digest('hex');
// 5. Send
try {
const response = await axios({
method: method,
url: `https://api.pago46.com${path}`,
headers: {
'Provider-Key': providerKey,
'Message-Date': timestamp,
'Message-Hash': signature,
'Content-Type': 'application/json'
},
data: bodyStr
});
return response.data;
} catch (error) {
console.error("Auth Error", error.response?.status);
}
}
package main
import (
"crypto/hmac"
"crypto/sha256"
"encoding/hex"
"fmt"
"strings"
"time"
)
func GenerateAuthHeaders(apiKey, apiSecret, method, path, bodyStr string) map[string]string {
// 1. Timestamp
timestamp := fmt.Sprintf("%f", float64(time.Now().Unix()))
// 2. Build string
parts := []string{apiKey, timestamp, method, path, bodyStr}
stringToSign := strings.Join(parts, ":")
// 3. HMAC
h := hmac.New(sha256.New, []byte(apiSecret))
h.Write([]byte(stringToSign))
signature := hex.EncodeToString(h.Sum(nil))
return map[string]string{
"Provider-Key": apiKey,
"Message-Date": timestamp,
"Message-Hash": signature,
}
}
Common Errors
| HTTP Code | Message | Probable Cause |
|---|---|---|
403 Forbidden | Invalid authentication credentials | The Provider-Key header does not exist or was not found in the database. |
403 Forbidden | Possible replay attack | The Message-Date has a difference of more than 24 hours with the server. |
403 Forbidden | Hash mismatch | The signature does not match. Verify that the separator is :, that the body is exact, and that the path is correct. |