Webhooks & Events
Webhooks push real-time notifications when important events occur so your systems can react instantly without polling the API.
Supported Events
| Event | Description | Example Use Cases |
|---|---|---|
post.scheduled | A post is scheduled or rescheduled. | Update external calendars, trigger approval workflows. |
post.published | A scheduled post goes live. | Notify sales teams, archive content, or trigger ads. |
review.created | A new Google Business review is ingested. | Create support tickets or Slack alerts. |
review.responded | A review response is published. | Sync sentiment with CRM. |
token.expiring | A connected social token will expire soon. | Prompt users to reauthenticate inside your app. |
workspace.member.invited | A new member invitation is sent. | Provision downstream systems. |
Creating a Subscription
- Go to Workspace Settings → Integrations → Webhooks.
- Click Create Subscription.
- Provide the public HTTPS endpoint that will receive events.
- Select the events to subscribe to.
- Copy the signing secret (displayed once) and store it securely.
You can also manage subscriptions via the API:
POST /webhooks
{
"url": "https://hooks.yourdomain.com/altyaa",
"events": ["post.published", "review.created"]
}
Delivery Behavior
- Events are delivered as JSON via POST requests.
- Retries use exponential backoff: 1 min, 5 min, 15 min, 1 hr (up to 24 hours total).
- After repeated failures the subscription is paused and you receive an email notification.
Verifying Signatures
Each payload includes headers to verify authenticity:
X-Altyaa-Signature: t=1731523200,v1=hash
To verify:
- Concatenate the timestamp, period (
.), and raw request body. - Compute an HMAC SHA-256 hash with your webhook secret.
- Compare the computed hash to the
v1value. - Reject requests where the timestamp differs by more than 5 minutes to prevent replay attacks.
Example (TypeScript):
import crypto from 'node:crypto';
export function verifySignature({ body, header, secret }: {
body: string;
header: string;
secret: string;
}) {
const [timestampPart, hashPart] = header.split(',');
const timestamp = timestampPart.split('=')[1];
const providedHash = hashPart.split('=')[1];
const payload = `${timestamp}.${body}`;
const expectedHash = crypto
.createHmac('sha256', secret)
.update(payload)
.digest('hex');
return crypto.timingSafeEqual(Buffer.from(providedHash), Buffer.from(expectedHash));
}
Processing Payloads
Payloads share a common envelope:
{
"id": "evt_01hdw6q2t5z9",
"type": "post.published",
"createdAt": "2025-10-14T10:21:00.000Z",
"data": {
"workspaceId": "wksp_123",
"postId": "post_456",
"publishedAt": "2025-10-14T10:20:00.000Z"
}
}
Use the id to deduplicate events—retry deliveries reuse the same ID.
Securing Your Endpoint
- Serve webhooks over HTTPS only.
- Validate the signature before processing the payload.
- Return a
2xxresponse within 10 seconds. For longer work, enqueue a background job and acknowledge immediately. - Use allowlists or secret URLs combined with the signing secret for defense in depth.
Continue to Rate Limits & Quotas to understand delivery expectations, or dive into Scheduling & Data Model to see how posts transition through lifecycle events.