Agent skill
Ayrshare Webhooks Skill
Receive and verify Ayrshare webhooks. Use when setting up Ayrshare social media API webhook handlers, debugging X-Authorization-Content-SHA256-V2 signature verification, rotating the signing secret, or handling scheduled, social, messages, comments, mentions and ads actions.
Install this skill
npx skills add hookdeck/webhook-skills --skill ayrshare-webhooks
Ayrshare is a social media posting and management API. It POSTs JSON to a URL you register per action (scheduled posts, social account linking, messages, comments, ads, ...) on your Primary Profile or a User Profile. Deliveries are signed with HMAC-SHA256 when you set a signing secret.
Register a webhook secret with Ayrshare. Without one, deliveries are unsigned and fail verification.
When to Use This Skill
- How do I receive Ayrshare webhooks?
- How do I verify the Ayrshare
X-Authorization-Content-SHA256-V2signature? - Why does my Ayrshare webhook signature fail after rotating the secret?
- How do I handle Ayrshare
scheduled,social,messagesorcommentsactions? - How do I deduplicate Ayrshare webhook retries (
hookId)?
Verification (core)
Ayrshare sends X-Authorization-Content-SHA256-V2: v1=<hex>, the lowercase hex HMAC-SHA256 of the raw request body keyed with your signing secret (UTF-8 bytes, used as-is). For 24 hours after a rotation the header carries two entries, v1=<current>,v1=<previous>: accept the delivery if any v1= entry matches. The timestamp header (X-Authorization-Timestamp) is not signed, so there is no replay window to check.
const crypto = require('crypto');
const HEX_SHA256 = /^[0-9a-fA-F]{64}$/;
function verifyAyrshareSignature(rawBody /* Buffer */, header, secret) {
if (!header || !secret) return false;
const expected = crypto.createHmac('sha256', secret).update(rawBody).digest();
let matched = false;
for (const part of header.split(',')) {
let candidate = part.trim();
if (candidate.startsWith('v1=')) candidate = candidate.slice(3);
else if (candidate.includes('=')) continue; // other key: ignore
if (!HEX_SHA256.test(candidate)) continue; // validate before decoding
if (crypto.timingSafeEqual(Buffer.from(candidate, 'hex'), expected)) matched = true;
}
return matched;
}
Return 401 for a missing, empty, malformed or non-matching header. Parse the JSON only after the check, and treat every field of the parsed body as untrusted (check types before reading into nested objects).
For complete handlers with tests, see examples/express/, examples/nextjs/, examples/fastapi/.
Hookdeck's Ayrshare source (AYRSHARE) verifies the same header: HMAC SHA-256, hex, x-authorization-content-sha256-v2.
Common Event Types
Dispatch on the body's top-level action. subAction refines messages, comments, mentions and scheduled; automations and ads carry a type.
action | Detail | Triggered when |
|---|---|---|
scheduled | status, postIds, errors; subAction: tikTokPublished | A scheduled post was processed (success or error); TikTok finished publishing |
social | type: link, unlink, refresh | A social account was linked, unlinked or needs refreshing |
messages | subAction: messageCreated, messageEdited, messageRead, reactionCreated | A direct message was received, edited, read or reacted to |
comments | subAction: comment | A comment was created on connected content |
mentions | subAction: mention | Your Instagram account was mentioned |
batch | batchType, url, userCount | A batch export of users is ready |
feed | data | A new RSS feed item was found |
automations | type: automation.triggered, automation.completed | An automation fired or finished |
ads | type: created, spendSynced, accountConnected, accountDisconnected, accountRevoked | An ad or ad account changed |
demo | type: upgradeWarning, upgrade | Demo plan limits |
suspended | type: suspend, unsuspend | Profile suspended or reinstated |
The examples handle scheduled, social, messages, comments and ads, and log the rest.
Delivery and Idempotency
Answer 200 within 15 seconds. 408, 425, 429, 5xx, timeouts and dropped connections are retried (up to 9 attempts over about an hour, then roughly 5 min, 30 min, 2 h and 12 h later); other 4xx responses are final. Delivery is at least once: dedupe on the body's hookId and hold claims for 24 hours or more. A retry rebuilds the payload, so the bytes (and signature) can differ between attempts.
Environment Variables
AYRSHARE_WEBHOOK_SECRET=your_ayrshare_signing_secret
One secret per User Profile, shared by every action that profile registers. The examples return 500 if it is not set.
Local Development
For local webhook testing, run the Hookdeck CLI via npx (no install required):
npx hookdeck-cli listen 3000 ayrshare --path /webhooks/ayrshare
No account required. The CLI provides a public URL that tunnels to your local server, plus a web UI for inspecting requests.
Reference Materials
- references/overview.md - Ayrshare webhook concepts, actions, payload fields
- references/setup.md - Register webhooks and set the signing secret
- references/verification.md - Signature details, rotation, debugging
- examples/ - Express, Next.js, and FastAPI handlers with tests