Code Examples
Complete, runnable examples. The only tricky part of this API is the request signature — sign the exact raw body string you send, joined to the millisecond timestamp with a newline. Every example below does exactly that.
signature = "sha256=" + hex( HMAC_SHA256( signing_secret, timestamp + "\n" + rawBody ) )
Node.js — create a placement
const crypto = require('crypto');
const API_KEY = process.env.BLASTS_API_KEY; // "Bearer" credential
const SIGNING_SECRET = process.env.BLASTS_SIGNING_SECRET; // HMAC secret
const ENDPOINT = 'https://api.blasts.app/api/ping/ads/placement';
async function blastsAds(bodyObj, idempotencyKey) {
const rawBody = JSON.stringify(bodyObj); // serialize ONCE
const timestamp = Date.now(); // Unix ms
const signature = 'sha256=' + crypto
.createHmac('sha256', SIGNING_SECRET)
.update(`${timestamp}\n${rawBody}`) // newline separator
.digest('hex');
const res = await fetch(ENDPOINT, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${API_KEY}`,
'X-Blasts-Timestamp': String(timestamp),
'X-Blasts-Signature': signature,
...(idempotencyKey ? { 'Idempotency-Key': idempotencyKey } : {})
},
body: rawBody // send the SAME string you signed
});
return res.json();
}
// Create: 25-mile radius around Newark NJ, business recipients, founders/owners.
const thirtyDays = 30 * 24 * 60 * 60 * 1000;
blastsAds({
action: 'create',
deal: {
deal_id: 'newark_founders_q3',
expires_at: Date.now() + thirtyDays,
payout_weight: 60,
creative: {
copy: 'Free payroll setup for NJ small businesses — offer ends this quarter.',
url: 'https://advertiser.example.com/nj-payroll'
},
snap_badge: { shape: 'pill', color: '#1E1E1E', label: 'AD' },
targeting: {
target_mode: 'business',
geo_radius: [{ zip: '07104', miles: 25, branch: 'business' }],
business_filters: { primary_roles: ['founder_owner'], org_sizes: ['solo', '2_10'] }
}
}
}, 'newark-founders-q3-v1').then(console.log);
// → { ok: true, deal_id: 'p_yourpartnerid_newark_founders_q3', ad: { … } }
Python — pull the ledger
import hashlib, hmac, json, os, time
import urllib.request
API_KEY = os.environ['BLASTS_API_KEY']
SIGNING_SECRET = os.environ['BLASTS_SIGNING_SECRET'].encode()
ENDPOINT = 'https://api.blasts.app/api/ping/ads/placement'
def blasts_ads(body_obj):
raw_body = json.dumps(body_obj, separators=(',', ':')) # serialize ONCE
timestamp = str(int(time.time() * 1000)) # Unix ms
payload = f'{timestamp}\n{raw_body}'.encode() # newline separator
signature = 'sha256=' + hmac.new(SIGNING_SECRET, payload, hashlib.sha256).hexdigest()
req = urllib.request.Request(
ENDPOINT,
data=raw_body.encode(), # same bytes you signed
method='POST',
headers={
'Content-Type': 'application/json',
'Authorization': f'Bearer {API_KEY}',
'X-Blasts-Timestamp': timestamp,
'X-Blasts-Signature': signature,
},
)
with urllib.request.urlopen(req) as res:
return json.load(res)
ledger = blasts_ads({'action': 'ledger'})
print(ledger['month'], ledger['month_to_date_sends'], '/', ledger['monthly_send_cap'])
for d in ledger['deals']:
t = d['totals']
print(d['deal_id'], 'sends:', t['sends'], 'views:', t['views'], 'clicks:', t['clicks'])
cURL / bash — list live placements
#!/usr/bin/env bash
API_KEY="$BLASTS_API_KEY"
SIGNING_SECRET="$BLASTS_SIGNING_SECRET"
ENDPOINT="https://api.blasts.app/api/ping/ads/placement"
BODY='{"action":"list"}'
TS="$(($(date +%s) * 1000))"
# HMAC-SHA256 over "\n" — printf '%s\n%s' produces exactly that.
SIG="sha256=$(printf '%s\n%s' "$TS" "$BODY" \
| openssl dgst -sha256 -hmac "$SIGNING_SECRET" -hex \
| sed 's/^.*= //')"
curl -sS -X POST "$ENDPOINT" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $API_KEY" \
-H "X-Blasts-Timestamp: $TS" \
-H "X-Blasts-Signature: $SIG" \
--data-raw "$BODY"
Node.js — update, then retract
// Raise the bid and refresh the expiry (placements live max 30 days per write):
await blastsAds({
action: 'update',
deal_id: 'p_yourpartnerid_newark_founders_q3',
deal: {
payout_weight: 85,
expires_at: Date.now() + 30 * 24 * 60 * 60 * 1000
}
});
// Campaign over — pull it. Out of rotation within ~60 seconds:
await blastsAds({
action: 'delete',
deal_id: 'p_yourpartnerid_newark_founders_q3'
});
Common signature mistakes
Re-serializing after signing. If your HTTP client
re-encodes the JSON (different key order, added whitespace), the bytes on the wire differ from the
bytes you signed → invalid_signature. Always pass the pre-serialized string as the body.
Seconds instead of milliseconds.
X-Blasts-Timestamp is Unix milliseconds. A seconds value looks ~56 years old
→ timestamp_expired.
Wrong separator. The signing payload joins
timestamp and body with a newline (\n) — not a dot, not nothing.
Missing the sha256= prefix. The header
value is sha256=<hex> (a bare hex digest is also accepted, but the prefix form is
canonical).
Full field-by-field contract in the API Reference, or email AL@SavingsSites.com — sandbox credentials available for integration testing.