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-V2 signature?
  • Why does my Ayrshare webhook signature fail after rotating the secret?
  • How do I handle Ayrshare scheduled, social, messages or comments actions?
  • 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.

actionDetailTriggered when
scheduledstatus, postIds, errors; subAction: tikTokPublishedA scheduled post was processed (success or error); TikTok finished publishing
socialtype: link, unlink, refreshA social account was linked, unlinked or needs refreshing
messagessubAction: messageCreated, messageEdited, messageRead, reactionCreatedA direct message was received, edited, read or reacted to
commentssubAction: commentA comment was created on connected content
mentionssubAction: mentionYour Instagram account was mentioned
batchbatchType, url, userCountA batch export of users is ready
feeddataA new RSS feed item was found
automationstype: automation.triggered, automation.completedAn automation fired or finished
adstype: created, spendSynced, accountConnected, accountDisconnected, accountRevokedAn ad or ad account changed
demotype: upgradeWarning, upgradeDemo plan limits
suspendedtype: suspend, unsuspendProfile 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


Repository

hookdeck/webhook-skills

v0.1.0 · MIT · Updated Nov 11, 2026

View on GitHub →