Authentication
Authentication
Server SDKs sign POST requests with an app key and HMAC secret. Static sites use a web token and do not sign. Click URLs do not need a credential.
https://serve.meridianads.tech/v1/decisionStatic sites
HMAC stays on the server. A static page loads https://meridianads.tech/tag/v1.js with data-token="mw_live_…" and marks slots with data-meridian-placement. The tag sends X-Web-Key. It does not send X-App-Key, X-Timestamp, or X-Signature. The browser Origin must match an origin stored for that token, including scheme, host, and port. user_key is still required in the JSON body. The tag supplies it. See the JavaScript guide.
Headers
| Header | Value |
|---|---|
| X-App-Key | Your app key prefix from the console, for example mk_live_… |
| X-Timestamp | Unix seconds. Default allowed skew is 300 seconds. |
| X-Signature | Hex digest of HMAC-SHA256 over the canonical string. |
Canonical string
Build a string from four parts joined by dots: {unix_timestamp}.{METHOD}.{path}.{raw_body}. Use the HTTP method as sent ( POST), the path without query string ( /v1/decision or /v1/decisions), and the exact request body bytes. Whitespace in JSON must match what you sign.
The secret shown at key creation is hex-encoded. Decode it to bytes before computing HMAC-SHA256.
Node
import { createHmac } from 'node:crypto'
const ts = String(Math.floor(Date.now() / 1000))
const method = 'POST'
const path = '/v1/decision'
const body = JSON.stringify({
placement: 'home',
user_key: 'user-42',
context: { country: 'US' }
})
const canonical = `${ts}.${method}.${path}.${body}`
const secret = Buffer.from(secretHex, 'hex')
const signature = createHmac('sha256', secret).update(canonical).digest('hex')
await fetch('https://serve.meridianads.tech/v1/decision', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-App-Key': prefix,
'X-Timestamp': ts,
'X-Signature': signature
},
body
})Python
import hashlib, hmac, json, time, urllib.request
ts = str(int(time.time()))
method = "POST"
path = "/v1/decision"
body = json.dumps(
{"placement": "home", "user_key": "user-42", "context": {"country": "US"}},
separators=(",", ":"),
)
canonical = f"{ts}.{method}.{path}.{body}"
secret = bytes.fromhex(secret_hex)
signature = hmac.new(secret, canonical.encode(), hashlib.sha256).hexdigest()
req = urllib.request.Request(
"https://serve.meridianads.tech/v1/decision",
data=body.encode(),
method=method,
headers={
"Content-Type": "application/json",
"X-App-Key": prefix,
"X-Timestamp": ts,
"X-Signature": signature,
},
)