Skip to main content
Docs/Webhooks

Webhooks

Receive real-time notifications when events happen on your skills and account.

Overview

Webhooks allow you to receive HTTP POST requests to your server when specific events occur on Asterism. This enables you to build integrations, automate workflows, and react to events in real-time.

Tip: Webhooks are available on Pro plans and above.View pricing

Creating a Webhook

You can create webhooks via the API or through your dashboard.

Via Dashboard

  1. Go to Dashboard → Settings → Webhooks
  2. Click "Add Webhook"
  3. Enter your endpoint URL (must be HTTPS)
  4. Select the events you want to receive
  5. Click "Create Webhook"

Via API

curl -X POST https://api.joinasterism.com/v1/webhooks \
  -H "Authorization: Bearer aster_live_xxx" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://your-server.com/webhooks/ask",
    "events": ["skill.published", "skill.downloaded"],
    "secret": "your-webhook-secret"
  }'

Available Events

Subscribe to specific events to receive notifications when they occur.

skill.published

Triggered when a new skill version is published

{
  "event": "skill.published",
  "timestamp": "2026-01-23T12:00:00Z",
  "data": {
    "skill": {
      "id": "sk_xxx",
      "name": "my-skill",
      "fullName": "@username/my-skill",
      "version": "1.2.0",
      "description": "My awesome skill",
      "securityScore": 95
    },
    "publisher": {
      "id": "usr_xxx",
      "username": "username"
    }
  }
}
skill.downloaded

Triggered when your skill is downloaded/installed

{
  "event": "skill.downloaded",
  "timestamp": "2026-01-23T12:00:00Z",
  "data": {
    "skill": {
      "id": "sk_xxx",
      "name": "my-skill",
      "fullName": "@username/my-skill"
    },
    "client": "claude-code",
    "downloadCount": 1542
  }
}
skill.starred

Triggered when your skill receives a star

{
  "event": "skill.starred",
  "timestamp": "2026-01-23T12:00:00Z",
  "data": {
    "skill": {
      "id": "sk_xxx",
      "name": "my-skill",
      "fullName": "@username/my-skill"
    },
    "user": {
      "id": "usr_xxx",
      "username": "fan"
    },
    "starCount": 89
  }
}
skill.review.created

Triggered when a new review is posted on your skill

{
  "event": "skill.review.created",
  "timestamp": "2026-01-23T12:00:00Z",
  "data": {
    "skill": {
      "id": "sk_xxx",
      "name": "my-skill"
    },
    "review": {
      "id": "rev_xxx",
      "rating": 5,
      "title": "Great skill!",
      "body": "This skill saved me hours..."
    },
    "reviewer": {
      "username": "reviewer"
    }
  }
}
skill.issue.created

Triggered when a new issue is opened on your skill

{
  "event": "skill.issue.created",
  "timestamp": "2026-01-23T12:00:00Z",
  "data": {
    "skill": {
      "id": "sk_xxx",
      "name": "my-skill"
    },
    "issue": {
      "id": "iss_xxx",
      "type": "bug",
      "title": "Error when processing large files",
      "body": "I'm getting an error..."
    },
    "author": {
      "username": "reporter"
    }
  }
}
user.followed

Triggered when someone follows you

{
  "event": "user.followed",
  "timestamp": "2026-01-23T12:00:00Z",
  "data": {
    "follower": {
      "id": "usr_xxx",
      "username": "newfollower"
    },
    "followerCount": 156
  }
}

Verifying Webhook Signatures

All webhook requests include a signature header that you should verify to ensure the request came from Asterism.

Signature Header

Each request includes an X-Ask-Signature header containing an HMAC-SHA256 signature of the request body using your webhook secret.

Verification Example (Node.js)

import crypto from 'crypto';

function verifyWebhook(payload: string, signature: string, secret: string): boolean {
  const expectedSignature = crypto
    .createHmac('sha256', secret)
    .update(payload)
    .digest('hex');

  return crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(`sha256=${expectedSignature}`)
  );
}

// In your webhook handler
app.post('/webhooks/ask', (req, res) => {
  const signature = req.headers['x-aster-signature'];
  const payload = JSON.stringify(req.body);

  if (!verifyWebhook(payload, signature, process.env.WEBHOOK_SECRET)) {
    return res.status(401).json({ error: 'Invalid signature' });
  }

  // Process the webhook
  const event = req.body;
  console.log('Received event:', event.event);

  res.status(200).json({ received: true });
});

Verification Example (Python)

import hmac
import hashlib

def verify_webhook(payload: bytes, signature: str, secret: str) -> bool:
    expected = hmac.new(
        secret.encode(),
        payload,
        hashlib.sha256
    ).hexdigest()
    return hmac.compare_digest(f"sha256={expected}", signature)

# In your Flask handler
@app.route('/webhooks/ask', methods=['POST'])
def handle_webhook():
    signature = request.headers.get('X-Ask-Signature')
    payload = request.get_data()

    if not verify_webhook(payload, signature, os.environ['WEBHOOK_SECRET']):
        return {'error': 'Invalid signature'}, 401

    event = request.json
    print(f"Received event: {event['event']}")

    return {'received': True}, 200

Best Practices

  • Respond quickly: Return a 2xx response within 5 seconds. Process events asynchronously if needed.
  • Handle duplicates: Webhooks may be retried. Use the event ID for idempotency.
  • Verify signatures: Always verify the webhook signature before processing.
  • Use HTTPS: Webhook endpoints must use HTTPS for security.
  • Monitor failures: Check the webhook delivery history in your dashboard.

Retry Policy

If your endpoint returns a non-2xx status code or times out, we will retry the delivery using exponential backoff:

  • Attempt 1: Immediate
  • Attempt 2: After 1 minute
  • Attempt 3: After 5 minutes
  • Attempt 4: After 30 minutes
  • Attempt 5: After 2 hours

After 5 failed attempts, the webhook will be marked as failed. You can view delivery history and retry failed webhooks from your dashboard.

API Reference

GET/api/v1/webhooks

List all your webhooks

POST/api/v1/webhooks

Create a new webhook

GET/api/v1/webhooks/:id

Get webhook details with delivery history

PATCH/api/v1/webhooks/:id

Update webhook URL or events

DELETE/api/v1/webhooks/:id

Delete a webhook