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

# Create Webhook

Creates a new webhook configuration for receiving event notifications.

## Overview

Create a webhook to receive real-time HTTP notifications when events occur in your InstaView account. The signing secret is returned only once during creation—store it securely.

## Authentication

<ParamField header="Authorization" type="string" required>
  Bearer token with `write:webhooks` scope
</ParamField>

## Request Body

<ParamField body="url" type="string" required>
  The HTTPS endpoint URL to receive webhook notifications. Maximum 2048 characters.
</ParamField>

<ParamField body="events" type="array" required>
  Array of event type strings to subscribe to:

  * `"ANALYSIS_COMPLETED"` - Analysis finished successfully
  * `"ANALYSIS_FAILED"` - Analysis processing failed
  * `"PING"` - Test event for connectivity
  * `"INTERVIEW_COMPLETED"` - Interview finished with analysis
  * `"INTERVIEW_FAILED"` - Technical failure during interview
  * `"INTERVIEW_STARTED"` - Interview session began
  * `"INTERVIEW_RESCHEDULED"` - A follow-up call attempt has been scheduled
  * `"INTERVIEW_CANCELLED"` - Interview terminated without completing
  * `"SOURCING_COMPLETED"` - Sourcing run finished with scored candidates
  * `"SOURCING_FAILED"` - Sourcing run terminated with an error
  * `"ENRICH_COMPLETED"` - Enrichment run completed
  * `"ENRICH_FAILED"` - Enrichment run terminated with an error
</ParamField>

<ParamField body="name" type="string">
  Human-readable name for the webhook. Maximum 255 characters.
</ParamField>

<ParamField body="description" type="string">
  Description of what this webhook is used for.
</ParamField>

<ParamField body="companyId" type="string">
  Company ID to associate this webhook with. If omitted, webhook will receive events for all companies accessible by the API key. Useful for ATS integrations managing multiple companies with different subdomains.
</ParamField>

<ParamField body="headers" type="array">
  Custom headers to include in webhook requests. Maximum 50 headers.

  Each header object:

  * `name` (string, required): Header name (1-255 characters)
  * `value` (string, required): Header value (1-4096 characters)
</ParamField>

## Response

Returns the created webhook configuration with the signing secret.

<Warning>
  The `signingSecret` is only returned once during creation. Store it securely
  immediately. If you lose it, you must delete and recreate the webhook.
</Warning>

<ResponseField name="id" type="string">
  Unique identifier for the webhook
</ResponseField>

<ResponseField name="signingSecret" type="string">
  HMAC signing secret for verifying webhook signatures (hex-encoded, 64 characters)
</ResponseField>

<ResponseField name="url" type="string">
  The endpoint URL
</ResponseField>

<ResponseField name="events" type="array">
  Array of subscribed event type labels
</ResponseField>

<ResponseField name="isActive" type="boolean">
  Whether the webhook is active (always `true` for new webhooks)
</ResponseField>

## Example Request

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST https://api.instaview.sk/webhooks \
    -H "Authorization: Bearer sk_your_key_here" \
    -H "Content-Type: application/json" \
    -d '{
      "url": "https://api.example.com/webhooks/instaview",
      "name": "Production Webhook",
      "description": "Receives interview completion notifications",
      "events": ["INTERVIEW_COMPLETED", "ANALYSIS_COMPLETED"],
      "headers": [
        { "name": "Authorization", "value": "Bearer your-internal-token" }
      ]
    }'
  ```

  ```javascript Node.js theme={null}
  const response = await fetch('https://api.instaview.sk/webhooks', {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${process.env.INSTAVIEW_API_KEY}`,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      url: 'https://api.example.com/webhooks/instaview',
      name: 'Production Webhook',
      description: 'Receives interview completion notifications',
      events: ["INTERVIEW_COMPLETED", "ANALYSIS_COMPLETED"],
      headers: [
        { name: 'Authorization', value: 'Bearer your-internal-token' }
      ]
    })
  });

  const { data } = await response.json();

  // IMPORTANT: Store this securely - only shown once!
  console.log('Signing secret:', data.signingSecret);
  ```

  ```python Python theme={null}
  response = requests.post(
      'https://api.instaview.sk/webhooks',
      headers={
          'Authorization': f'Bearer {os.environ["INSTAVIEW_API_KEY"]}',
          'Content-Type': 'application/json'
      },
      json={
          'url': 'https://api.example.com/webhooks/instaview',
          'name': 'Production Webhook',
          'description': 'Receives interview completion notifications',
          'events': ["INTERVIEW_COMPLETED", "ANALYSIS_COMPLETED"],
          'headers': [
              {'name': 'Authorization', 'value': 'Bearer your-internal-token'}
          ]
      }
  )

  data = response.json()['data']

  # IMPORTANT: Store this securely - only shown once!
  print(f'Signing secret: {data["signingSecret"]}')
  ```
</CodeGroup>

## Example Response

```json theme={null}
{
  "success": true,
  "data": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "apiKeyId": "api-key-uuid",
    "companyId": "company-uuid",
    "url": "https://api.example.com/webhooks/instaview",
    "name": "Production Webhook",
    "description": "Receives interview completion notifications",
    "headers": [
      { "name": "Authorization", "isMasked": true }
    ],
    "events": ["interview.completed", "analysis.completed"],
    "isActive": true,
    "maxRetries": 3,
    "timeoutMs": 30000,
    "consecutiveFailures": 0,
    "circuitOpenedAt": null,
    "signingSecret": "a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7r8s9t0u1v2w3x4y5z6a7b8c9d0e1f2",
    "createdAt": "2024-01-15T10:30:00Z",
    "updatedAt": "2024-01-15T10:30:00Z"
  }
}
```

## Error Responses

<AccordionGroup>
  <Accordion title="400 - Validation Error">
    ```json theme={null}
    {
      "success": false,
      "error": {
        "code": "VALIDATION_ERROR",
        "message": "url must be a valid URL"
      }
    }
    ```
  </Accordion>

  <Accordion title="403 - Insufficient Permissions">
    ```json theme={null}
    {
      "success": false,
      "error": {
        "code": "INSUFFICIENT_PERMISSIONS",
        "message": "Required scope write:webhooks not found"
      }
    }
    ```
  </Accordion>
</AccordionGroup>

## Best Practices

1. **Store the signing secret immediately** - It's only returned once
2. **Include the ping event** for testing - You can remove it later
3. **Use HTTPS endpoints** - HTTP is only allowed for localhost
4. **Add authentication headers** - Protect your webhook endpoint

## Related

<CardGroup cols={2}>
  <Card title="Webhooks Guide" icon="webhook" href="/guides/webhooks">
    Learn about signature verification and payloads
  </Card>

  <Card title="Test Webhook" icon="flask" href="/api-reference/webhooks/test-webhook">
    Test your webhook endpoint
  </Card>
</CardGroup>
