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

# Getting Started

Feedspace provides webhooks to notify your application about important events in real-time. This section documents all available webhook events and their payloads.

### How to Get Webhook Access

To get webhook access:

1. Go to the [Webhook Access](https://app.feedspace.io/feedbox#my-account?tab=webhooks) page in your Feedspace account.
2. Enter your webhook endpoint URL in the provided input field.
3. After adding your endpoint URL, you can select which events you want to receive notifications for.
4. Click the "Activate" button to enable webhook access for your account.

Once activated, Feedspace will start sending webhook notifications for the selected events to your specified endpoint.

### Available Webhook Events

Feedspace currently supports the following webhook events:

* `feed.text.received`: Triggered when a new text review is received
* `feed.video.received`: Triggered when a new video review is received
* `feed.audio.received`: Triggered when a new audio review is received

### Webhook Delivery

Feedspace will send webhook notifications as HTTP POST requests to your specified webhook URL. Each notification follows this format:

```json theme={null}
{
  "type": "event type",
  "data": {
    // Event-specific data
  }
}
```

The notification contains:

* `type`: The event type (e.g., "feed.text.received", "feed.video.received", "feed.audio.received")
* `data`: The event-specific data payload

### Example Request

When a new text review is received, Feedspace will send a POST request to your webhook URL with a payload like this:

```json theme={null}
{
  "event": "feed.text.received",
  "data": {
    ...
  }
}
```

## Verify Webhook Signature

To ensure the integrity and authenticity of incoming webhook requests, Feedspace signs each payload with a unique secret. We strongly recommend verifying this signature for all production webhooks.

### How It Works

1. **The Signature Headers:** Feedspace sends two headers with each webhook request:
   * `x-feedspace-signature`: The HMAC-SHA256 signature of the payload.
   * `x-feedspace-timestamp`: The Unix timestamp (in seconds) when the webhook was sent

2. **Your Signing Secret:** Each webhook in your workspace has a unique signing secret. You can find this secret in your Feedspace dashboard under **Automation > Webhook**. Secrets are prefixed with `whsec_`.

3. **Verification Process:** You reconstruct the signature on your server using the timestamp, the raw request body, and your secret. If it matches the `x-feedspace-signature` header, the webhook is legitimate.

### Sample Verification Code

<CodeGroup>
  ```php PHP theme={null}
  <?php

  // 1. Retrieve the signature and timestamp from the headers
  $headers = getallheaders();
  $signature = $headers['x-feedspace-signature'] ?? null;
  $timestamp = $headers['x-feedspace-timestamp'] ?? null;

  // 2. Get the raw payload from the input stream
  $payload = file_get_contents('php://input');

  // 3. Define your secrets (Store these securely, e.g., in environment variables!)
  $secret = 'whsec_test_1234222222232s334weee';

  // 4. Compute the expected signature
  $expectedSignature = hash_hmac('sha256', $timestamp . '.' . $payload, $secret);

  // 6. Compare the signatures using a time-safe comparison
  if (hash_equals($expectedSignature, $signature)) {
      // Webhook is verified! Process the event.
  }
  ```

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

  // 1. Retrieve the signature and timestamp from the headers
  const signature = req.headers['x-feedspace-signature'];
  const timestamp = req.headers['x-feedspace-timestamp'];

  // 2. Get the raw payload
  const payload = JSON.stringify(req.body);

  // 3. Define your secret (Store securely in environment variables!)
  const secret = 'whsec_test_1234222222232s334weee';

  // 4. Compute the expected signature
  const expectedSignature = crypto
    .createHmac('sha256', secret)
    .update(timestamp + '.' + payload)
    .digest('hex');

  // 5. Compare the signatures using a time-safe comparison
  if (crypto.timingSafeEqual(Buffer.from(expectedSignature), Buffer.from(signature))) {
      // Webhook is verified! Process the event.
  }
  ```

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

  # 1. Retrieve the signature and timestamp from the headers
  signature = request.headers.get('x-feedspace-signature')
  timestamp = request.headers.get('x-feedspace-timestamp')

  # 2. Get the raw payload
  payload = request.get_data()

  # 3. Define your secret (Store securely in environment variables!)
  secret = 'whsec_test_1234222222232s334weee'

  # 4. Compute the expected signature
  expected_signature = hmac.new(
      secret.encode('utf-8'),
      f"{timestamp}.{payload.decode('utf-8')}".encode('utf-8'),
      hashlib.sha256
  ).hexdigest()

  # 5. Compare the signatures using a time-safe comparison
  if hmac.compare_digest(expected_signature, signature):
      # Webhook is verified! Process the event.
      pass
  ```

  ```ruby Ruby theme={null}
  require 'openssl'

  # 1. Retrieve the signature and timestamp from the headers
  signature = request.headers['x-feedspace-signature']
  timestamp = request.headers['x-feedspace-timestamp']

  # 2. Get the raw payload
  payload = request.body.read

  # 3. Define your secret (Store securely in environment variables!)
  secret = 'whsec_test_1234222222232s334weee'

  # 4. Compute the expected signature
  expected_signature = OpenSSL::HMAC.hexdigest(
    'SHA256', 
    secret, 
    "#{timestamp}.#{payload}"
  )

  # 5. Compare the signatures using a time-safe comparison
  if Rack::Utils.secure_compare(expected_signature, signature)
    # Webhook is verified! Process the event.
  end
  ```
</CodeGroup>

### Best Practices

* Implement proper error handling for incoming webhook requests
* Consider implementing request validation to verify the authenticity of webhook requests
* Handle different event types appropriately in your application
* Keep your webhook endpoint URL secure and accessible
