Webhooks

Receive real-time notifications when events happen in your OverSkill workspace. Subscribe to events and get HTTP POST requests to your endpoint.

How Webhooks Work

  1. Create a webhook endpoint that can receive POST requests
  2. Register your endpoint URL with OverSkill via the API
  3. Select which events you want to receive
  4. When events occur, OverSkill sends a POST request to your endpoint
  5. Your endpoint returns a 2xx status to acknowledge receipt

💡 Tip

Use a service like webhook.site to test webhooks during development.

Payload Format

All webhook payloads follow this standard format:

{
  "event": "app.created",
  "timestamp": "2025-12-23T12:00:00Z",
  "team_id": 123,
  "data": {
    // Event-specific data
  }
}

Request Headers

Header Description
Content-Type application/json
X-Overskill-Event The event type (e.g., app.created)
X-Overskill-Delivery Unique delivery ID (for deduplication)
X-Overskill-Signature HMAC-SHA256 signature for verification
X-Overskill-Timestamp Unix timestamp when request was sent

Signature Verification

Verify webhook authenticity to ensure requests come from OverSkill:

Signature Format

X-Overskill-Signature: t=1703332800,v1=abc123def456...

Verification Steps

  1. Extract the timestamp (t) and signature (v1) from the header
  2. Compute expected signature: HMAC-SHA256(timestamp + "." + request_body, signing_secret)
  3. Compare your computed signature with the v1 value
  4. Optionally check timestamp is within acceptable window (e.g., 5 minutes)

Example (Node.js)

const crypto = require('crypto');

function verifyWebhook(payload, signature, secret) {
  const parts = signature.split(',');
  const timestamp = parts[0].split('=')[1];
  const receivedSig = parts[1].split('=')[1];

  const signedPayload = `${timestamp}.${payload}`;
  const expectedSig = crypto
    .createHmac('sha256', secret)
    .update(signedPayload)
    .digest('hex');

  return crypto.timingSafeEqual(
    Buffer.from(receivedSig),
    Buffer.from(expectedSig)
  );
}

Example (Python)

import hmac
import hashlib

def verify_webhook(payload, signature, secret):
    parts = dict(p.split('=') for p in signature.split(','))
    timestamp = parts['t']
    received_sig = parts['v1']

    signed_payload = f"{timestamp}.{payload}"
    expected_sig = hmac.new(
        secret.encode(),
        signed_payload.encode(),
        hashlib.sha256
    ).hexdigest()

    return hmac.compare_digest(received_sig, expected_sig)

Event Types

app.created

Triggered when a new app is created

Example Payload

{
  "event": "app.created",
  "timestamp": "2025-12-23T12:00:00Z",
  "team_id": 123,
  "data": {
    "id": "abc123",
    "name": "My App",
    "status": "draft",
    "created_at": "2025-12-23T12:00:00Z"
  }
}

app.generation.completed

Triggered when app generation completes successfully

Example Payload

{
  "event": "app.generation.completed",
  "timestamp": "2025-12-23T12:05:00Z",
  "team_id": 123,
  "data": {
    "app_id": "abc123",
    "message_id": 456,
    "status": "completed",
    "preview_url": "https://preview-abc123.overskill.app"
  }
}

app.deployment.completed

Triggered when deployment completes

Example Payload

{
  "event": "app.deployment.completed",
  "timestamp": "2025-12-23T12:10:00Z",
  "team_id": 123,
  "data": {
    "app_id": "abc123",
    "environment": "production",
    "production_url": "https://abc123.overskill.app"
  }
}

app.user.created

Triggered when a new user accesses an app

Example Payload

{
  "event": "app.user.created",
  "timestamp": "2025-12-23T12:15:00Z",
  "team_id": 123,
  "data": {
    "id": 789,
    "app_id": "abc123",
    "user_email": "[email protected]",
    "access_tier": "free"
  }
}

Retry Policy

If your endpoint returns a non-2xx status or times out, we'll retry with exponential backoff:

Attempt Delay
1st retry 1 minute
2nd retry 5 minutes
3rd retry 30 minutes
4th retry 2 hours
5th retry (final) 8 hours

⚠️ Important

After 5 failed attempts, the delivery is marked as failed. Ensure your endpoint responds within 30 seconds.

Best Practices

  • Return 200 quickly - Process webhooks asynchronously. Acknowledge receipt immediately, then process the payload in a background job.
  • Handle duplicates - Use the X-Overskill-Delivery header to deduplicate webhooks. Network issues may cause retries.
  • Verify signatures - Always verify the X-Overskill-Signature header to ensure authenticity.
  • Use HTTPS - Your webhook endpoint must use HTTPS. We don't send webhooks to HTTP endpoints.
  • Monitor failures - Check the webhook deliveries API to monitor for failed deliveries.