> ## Documentation Index
> Fetch the complete documentation index at: https://help.hubsy.cloud/llms.txt
> Use this file to discover all available pages before exploring further.

# Webhooks

> Receive real-time notifications for events in your Hubsy Cloud account

## Overview

Webhooks allow you to receive real-time HTTP notifications when events occur in your Hubsy Cloud account. Instead of polling for changes, Hubsy pushes event data to your specified endpoint.

## Setting Up Webhooks

<Steps>
  <Step title="Create Endpoint">
    Set up an HTTPS endpoint on your server to receive webhook events:

    ```javascript Example Node.js Endpoint theme={null}
    app.post('/webhooks/hubsy', (req, res) => {
      const event = req.body;

      // Verify webhook signature
      if (!verifySignature(req)) {
        return res.status(401).send('Invalid signature');
      }

      // Process event
      handleEvent(event);

      // Respond quickly
      res.status(200).send('OK');
    });
    ```
  </Step>

  <Step title="Register Webhook">
    Register your webhook endpoint via API or dashboard:

    ```bash theme={null}
    curl -X POST https://api.hubsy.cloud/v1/webhooks \
      -H "Authorization: Bearer YOUR_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{
        "url": "https://yourapp.com/webhooks/hubsy",
        "events": ["file.uploaded", "file.deleted"],
        "secret": "your_webhook_secret"
      }'
    ```
  </Step>

  <Step title="Test Webhook">
    Send a test event to verify setup:

    ```bash theme={null}
    curl -X POST https://api.hubsy.cloud/v1/webhooks/{webhook_id}/test \
      -H "Authorization: Bearer YOUR_API_KEY"
    ```
  </Step>

  <Step title="Go Live">
    Your webhook is now active and will receive events in real-time
  </Step>
</Steps>

## Available Events

Subscribe to these events:

<AccordionGroup>
  <Accordion title="file.uploaded" icon="file-arrow-up">
    Triggered when a file is uploaded

    ```json theme={null}
    {
      "event": "file.uploaded",
      "timestamp": "2024-01-15T10:30:00Z",
      "data": {
        "file": {
          "id": "file_abc123",
          "name": "document.pdf",
          "size": 2458624,
          "type": "application/pdf",
          "folder_id": "folder_123",
          "uploaded_by": "user_xyz",
          "created_at": "2024-01-15T10:30:00Z"
        }
      }
    }
    ```
  </Accordion>

  <Accordion title="file.deleted" icon="trash">
    Triggered when a file is deleted

    ```json theme={null}
    {
      "event": "file.deleted",
      "timestamp": "2024-01-15T11:00:00Z",
      "data": {
        "file": {
          "id": "file_abc123",
          "name": "old-document.pdf",
          "deleted_by": "user_xyz",
          "deleted_at": "2024-01-15T11:00:00Z",
          "permanent": false
        }
      }
    }
    ```
  </Accordion>

  <Accordion title="file.shared" icon="share">
    Triggered when a file is shared

    ```json theme={null}
    {
      "event": "file.shared",
      "timestamp": "2024-01-15T12:00:00Z",
      "data": {
        "file": {
          "id": "file_abc123",
          "name": "presentation.pdf"
        },
        "share": {
          "id": "share_def456",
          "url": "https://hubsy.cloud/s/abc123xyz",
          "password_protected": true,
          "expires_at": "2024-02-15T12:00:00Z",
          "created_by": "user_xyz"
        }
      }
    }
    ```
  </Accordion>

  <Accordion title="share.accessed" icon="eye">
    Triggered when a shared file is accessed

    ```json theme={null}
    {
      "event": "share.accessed",
      "timestamp": "2024-01-15T13:00:00Z",
      "data": {
        "share": {
          "id": "share_def456",
          "file_id": "file_abc123"
        },
        "access": {
          "ip_address": "192.168.1.1",
          "user_agent": "Mozilla/5.0...",
          "location": "United States",
          "action": "download"
        }
      }
    }
    ```
  </Accordion>

  <Accordion title="folder.created" icon="folder-plus">
    Triggered when a folder is created

    ```json theme={null}
    {
      "event": "folder.created",
      "timestamp": "2024-01-15T14:00:00Z",
      "data": {
        "folder": {
          "id": "folder_789",
          "name": "New Project",
          "parent_id": "folder_123",
          "created_by": "user_xyz"
        }
      }
    }
    ```
  </Accordion>

  <Accordion title="storage.warning" icon="triangle-exclamation">
    Triggered when storage reaches threshold

    ```json theme={null}
    {
      "event": "storage.warning",
      "timestamp": "2024-01-15T15:00:00Z",
      "data": {
        "storage": {
          "used": 858993459,
          "limit": 1073741824,
          "percentage": 80,
          "threshold": "80%"
        }
      }
    }
    ```
  </Accordion>

  <Accordion title="user.quota_exceeded" icon="circle-exclamation">
    Triggered when storage quota is exceeded

    ```json theme={null}
    {
      "event": "user.quota_exceeded",
      "timestamp": "2024-01-15T16:00:00Z",
      "data": {
        "storage": {
          "used": 1073741824,
          "limit": 1073741824,
          "overage": 0
        },
        "action_required": true
      }
    }
    ```
  </Accordion>
</AccordionGroup>

## Webhook Payload Structure

All webhook events follow this structure:

```json theme={null}
{
  "event": "event.name",
  "timestamp": "2024-01-15T10:30:00Z",
  "webhook_id": "webhook_abc123",
  "data": {
    // Event-specific data
  },
  "signature": "sha256=..."
}
```

<ParamField body="event" type="string">
  The event type (e.g., "file.uploaded")
</ParamField>

<ParamField body="timestamp" type="string">
  ISO 8601 timestamp when the event occurred
</ParamField>

<ParamField body="webhook_id" type="string">
  ID of the webhook configuration that sent this event
</ParamField>

<ParamField body="data" type="object">
  Event-specific payload data
</ParamField>

<ParamField body="signature" type="string">
  HMAC SHA-256 signature for verification
</ParamField>

## Verifying Webhooks

Verify webhook authenticity using the signature:

<CodeGroup>
  ```javascript Node.js theme={null}
  const crypto = require('crypto');

  function verifyWebhook(payload, signature, secret) {
    const hmac = crypto.createHmac('sha256', secret);
    const digest = 'sha256=' + hmac.update(JSON.stringify(payload)).digest('hex');

    return crypto.timingSafeEqual(
      Buffer.from(signature),
      Buffer.from(digest)
    );
  }

  app.post('/webhooks/hubsy', (req, res) => {
    const signature = req.headers['x-hubsy-signature'];
    const secret = process.env.WEBHOOK_SECRET;

    if (!verifyWebhook(req.body, signature, secret)) {
      return res.status(401).send('Invalid signature');
    }

    // Process event
    res.status(200).send('OK');
  });
  ```

  ```python Python theme={null}
  import hmac
  import hashlib

  def verify_webhook(payload, signature, secret):
      expected_sig = 'sha256=' + hmac.new(
          secret.encode(),
          payload.encode(),
          hashlib.sha256
      ).hexdigest()

      return hmac.compare_digest(signature, expected_sig)

  @app.route('/webhooks/hubsy', methods=['POST'])
  def webhook():
      signature = request.headers.get('X-Hubsy-Signature')
      secret = os.getenv('WEBHOOK_SECRET')
      payload = request.get_data(as_text=True)

      if not verify_webhook(payload, signature, secret):
          return 'Invalid signature', 401

      # Process event
      return 'OK', 200
  ```

  ```php PHP theme={null}
  function verifyWebhook($payload, $signature, $secret) {
      $expectedSig = 'sha256=' . hash_hmac('sha256', $payload, $secret);
      return hash_equals($signature, $expectedSig);
  }

  $payload = file_get_contents('php://input');
  $signature = $_SERVER['HTTP_X_HUBSY_SIGNATURE'];
  $secret = getenv('WEBHOOK_SECRET');

  if (!verifyWebhook($payload, $signature, $secret)) {
      http_response_code(401);
      die('Invalid signature');
  }

  // Process event
  http_response_code(200);
  echo 'OK';
  ```
</CodeGroup>

## Managing Webhooks

### Create Webhook

```bash theme={null}
curl -X POST https://api.hubsy.cloud/v1/webhooks \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://yourapp.com/webhooks/hubsy",
    "events": ["file.uploaded", "file.deleted"],
    "secret": "your_webhook_secret",
    "active": true
  }'
```

### List Webhooks

```bash theme={null}
curl https://api.hubsy.cloud/v1/webhooks \
  -H "Authorization: Bearer YOUR_API_KEY"
```

### Update Webhook

```bash theme={null}
curl -X PATCH https://api.hubsy.cloud/v1/webhooks/webhook_abc123 \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "events": ["file.uploaded", "file.deleted", "file.shared"],
    "active": true
  }'
```

### Delete Webhook

```bash theme={null}
curl -X DELETE https://api.hubsy.cloud/v1/webhooks/webhook_abc123 \
  -H "Authorization: Bearer YOUR_API_KEY"
```

## Webhook Delivery

### Delivery Behavior

* **Timeout**: 30 seconds
* **Retries**: Up to 3 attempts with exponential backoff
* **Expected Response**: 200-299 status code
* **Retry Schedule**: Immediately, 5 seconds, 25 seconds

### Delivery Headers

Hubsy sends these headers with webhook requests:

```
Content-Type: application/json
X-Hubsy-Signature: sha256=...
X-Hubsy-Event: file.uploaded
X-Hubsy-Webhook-ID: webhook_abc123
X-Hubsy-Delivery-ID: delivery_xyz789
User-Agent: Hubsy-Webhook/1.0
```

## Best Practices

<AccordionGroup>
  <Accordion title="Respond Quickly" icon="bolt">
    Return 200 OK quickly:

    * Process events asynchronously
    * Don't perform long operations in webhook handler
    * Use a queue for processing
    * Respond within 5 seconds
  </Accordion>

  <Accordion title="Handle Duplicates" icon="copy">
    Webhooks may be delivered multiple times:

    * Use delivery ID for idempotency
    * Track processed events
    * Handle duplicates gracefully
  </Accordion>

  <Accordion title="Secure Your Endpoint" icon="lock">
    Protect your webhook endpoint:

    * Always verify signature
    * Use HTTPS only
    * Validate payload structure
    * Rate limit requests
  </Accordion>

  <Accordion title="Monitor Failures" icon="chart-line">
    Track webhook health:

    * Monitor delivery success rate
    * Alert on repeated failures
    * Review failed deliveries
    * Update endpoint if needed
  </Accordion>
</AccordionGroup>

## Troubleshooting

<AccordionGroup>
  <Accordion title="Not Receiving Webhooks" icon="question">
    Check:

    * Webhook is active
    * URL is accessible from internet
    * HTTPS is configured correctly
    * Firewall allows incoming requests
    * Server is responding with 200 OK
  </Accordion>

  <Accordion title="Signature Verification Fails" icon="shield-xmark">
    Ensure:

    * Using correct webhook secret
    * Comparing raw request body
    * Using timing-safe comparison
    * Secret hasn't been rotated
  </Accordion>

  <Accordion title="Too Many Events" icon="fire">
    To reduce volume:

    * Subscribe only to needed events
    * Use API polling for some data
    * Batch process events
    * Consider using filters (coming soon)
  </Accordion>
</AccordionGroup>

## Webhook Logs

View webhook delivery logs in your dashboard:

* Delivery attempts and outcomes
* Response codes and times
* Payload sent
* Error messages
* Retry history

Or fetch via API:

```bash theme={null}
curl https://api.hubsy.cloud/v1/webhooks/webhook_abc123/deliveries \
  -H "Authorization: Bearer YOUR_API_KEY"
```
