Signing & code examples
All examples assume BASE_URL, API_KEY (apiKeyId), and SECRET come from
secure server-side config. The rule that matters most: sign the exact bytes you
send — serialize once, sign that string, transmit that same string.
Award EP — POST /v1/ep/webhook
Section titled “Award EP — POST /v1/ep/webhook”import crypto from "node:crypto";
const BASE_URL = process.env.EP_BASE_URL; // e.g. https://voting-dev.eventista.vn/voting/apiconst API_KEY = process.env.EP_API_KEY; // X-Api-Keyconst SECRET = process.env.EP_WEBHOOK_SECRET; // HMAC secret
export async function awardEp(payload) { const body = JSON.stringify(payload); // serialize ONCE const timestamp = Date.now().toString(); // epoch ms const signature = crypto .createHmac("sha256", SECRET) .update(`${timestamp}.${body}`) .digest("hex");
const res = await fetch(`${BASE_URL}/v1/ep/webhook`, { method: "POST", headers: { "Content-Type": "application/json", "X-Api-Key": API_KEY, "X-Timestamp": timestamp, "X-Signature": signature, }, body, // send the EXACT bytes we signed });
const data = await res.json(); if (res.status === 202) return { credited: true, ...data }; if (res.status === 200 && data.code === "DUPLICATE") return { credited: true, duplicate: true, ...data }; throw new Error(`EP award failed [${res.status}] ${data.code}: ${data.message}`);}
await awardEp({ tenantId: "7g1RP3", orderId: "order-2026-0001", userEmail: "user@example.com", amount: 50000, note: "Order #2026-0001 cashback",});import hmac, hashlib, json, time, requests
BASE_URL = "https://voting-dev.eventista.vn/voting/api"API_KEY = "pk_..."SECRET = "..."
def award_ep(payload: dict): body = json.dumps(payload, separators=(",", ":")) # serialize ONCE timestamp = str(int(time.time() * 1000)) # epoch ms signature = hmac.new( SECRET.encode(), f"{timestamp}.{body}".encode(), hashlib.sha256 ).hexdigest()
resp = requests.post( f"{BASE_URL}/v1/ep/webhook", headers={ "Content-Type": "application/json", "X-Api-Key": API_KEY, "X-Timestamp": timestamp, "X-Signature": signature, }, data=body, # send the exact bytes we signed ) data = resp.json() if resp.status_code in (200, 202): return data raise RuntimeError(f"EP award failed [{resp.status_code}] {data['code']}: {data['message']}")
award_ep({ "tenantId": "7g1RP3", "orderId": "order-2026-0001", "userEmail": "user@example.com", "amount": 50000,})BASE_URL="https://voting-dev.eventista.vn/voting/api"API_KEY="pk_..."SECRET="..."
BODY='{"tenantId":"7g1RP3","orderId":"order-2026-0001","userEmail":"user@example.com","amount":50000}'TS=$(( $(date +%s) * 1000 ))SIG=$(printf '%s' "$TS.$BODY" | openssl dgst -sha256 -hmac "$SECRET" -hex | sed 's/^.* //')
curl -sS -X POST "$BASE_URL/v1/ep/webhook" \ -H "Content-Type: application/json" \ -H "X-Api-Key: $API_KEY" \ -H "X-Timestamp: $TS" \ -H "X-Signature: $SIG" \ --data "$BODY"Status lookup — GET …/transactions/{orderId}
Section titled “Status lookup — GET …/transactions/{orderId}”Here signedBody is the orderId (no request body).
const orderId = "order-2026-0001";const timestamp = Date.now().toString();const signature = crypto .createHmac("sha256", SECRET) .update(`${timestamp}.${orderId}`) // signedBody = orderId, no body .digest("hex");
const res = await fetch( `${BASE_URL}/v1/ep/webhook/transactions/${encodeURIComponent(orderId)}`, { headers: { "X-Api-Key": API_KEY, "X-Timestamp": timestamp, "X-Signature": signature } },);For listing your full award history (signing the tenantId, with pagination),
see Award history.