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

# GET /v1/platform/webhook/logs

> View webhook delivery history and monitor webhook health

## Overview

Monitor webhook deliveries to debug issues, track success rates, and ensure your integration is working correctly.

## Authentication

Requires **Platform API Key** in the `X-API-Key` header.

## Request

```bash theme={null}
GET https://api.syncline.run/v1/platform/webhook/logs
```

### Query Parameters

<ParamField query="limit" type="number">
  Number of delivery records to return (default: 50, max: 200)
</ParamField>

<ParamField query="event" type="string">
  Filter by event type (e.g., "meeting.scheduled", "user.calendar\_connected")
</ParamField>

<ParamField query="status" type="string">
  Filter by status: "success" or "failed"
</ParamField>

## Response

```json theme={null}
{
  "deliveries": [
    {
      "id": "wh_del_abc123",
      "event": "meeting.scheduled",
      "timestamp": "2025-01-20T10:35:00Z",
      "status": "success",
      "response_code": 200,
      "attempts": 1,
      "duration_ms": 145,
      "url": "https://yourapp.com/webhooks/syncline"
    },
    {
      "id": "wh_del_def456",
      "event": "user.calendar_connected",
      "timestamp": "2025-01-20T10:30:00Z",
      "status": "failed",
      "response_code": 500,
      "attempts": 3,
      "duration_ms": 5000,
      "error": "Connection timeout after 3 attempts",
      "url": "https://yourapp.com/webhooks/syncline"
    }
  ],
  "stats": {
    "total_sent": 1247,
    "success_rate": 0.987,
    "avg_response_time_ms": 156,
    "last_30_days": {
      "success": 1231,
      "failed": 16
    }
  },
  "pagination": {
    "next_cursor": "wh_del_xyz789",
    "has_more": true
  }
}
```

## Response Fields

<ResponseField name="deliveries" type="array">
  Array of webhook delivery records
</ResponseField>

<ResponseField name="stats" type="object">
  Aggregate statistics about webhook health
</ResponseField>

### Delivery Object

<ResponseField name="id" type="string">
  Unique delivery identifier
</ResponseField>

<ResponseField name="event" type="string">
  Event type (e.g., "meeting.scheduled")
</ResponseField>

<ResponseField name="status" type="string">
  "success" or "failed"
</ResponseField>

<ResponseField name="response_code" type="number">
  HTTP status code returned by your endpoint
</ResponseField>

<ResponseField name="attempts" type="number">
  Number of delivery attempts (max 3)
</ResponseField>

<ResponseField name="duration_ms" type="number">
  Response time in milliseconds
</ResponseField>

<ResponseField name="error" type="string">
  Error message if delivery failed
</ResponseField>

## Use Cases

### Debug Failed Deliveries

```javascript theme={null}
// Check recent failed webhooks
async function debugWebhookFailures() {
  const response = await fetch(
    'https://api.syncline.run/v1/platform/webhook/logs?status=failed&limit=20',
    {
      headers: { 'X-API-Key': process.env.SYNCLINE_API_KEY }
    }
  );

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

  deliveries.forEach(delivery => {
    console.log(`❌ Failed: ${delivery.event} at ${delivery.timestamp}`);
    console.log(`   Error: ${delivery.error}`);
    console.log(`   Attempts: ${delivery.attempts}`);
    console.log(`   Response Code: ${delivery.response_code}`);
  });
}
```

### Monitor Webhook Health

```javascript theme={null}
// Check webhook success rate
async function checkWebhookHealth() {
  const { stats } = await fetch(
    'https://api.syncline.run/v1/platform/webhook/logs',
    {
      headers: { 'X-API-Key': process.env.SYNCLINE_API_KEY }
    }
  ).then(r => r.json());

  if (stats.success_rate < 0.95) {
    await alertTeam({
      title: '⚠️ Webhook Health Alert',
      message: `Webhook success rate is ${(stats.success_rate * 100).toFixed(1)}%`,
      stats: stats.last_30_days
    });
  }

  return {
    health: stats.success_rate > 0.95 ? 'healthy' : 'degraded',
    success_rate: stats.success_rate,
    avg_response_time: stats.avg_response_time_ms,
    recent_failures: stats.last_30_days.failed
  };
}
```

### Track Specific Events

```javascript theme={null}
// Monitor meeting scheduling webhooks
async function trackMeetingWebhooks() {
  const response = await fetch(
    'https://api.syncline.run/v1/platform/webhook/logs?event=meeting.scheduled&limit=100',
    {
      headers: { 'X-API-Key': process.env.SYNCLINE_API_KEY }
    }
  );

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

  const analysis = {
    total: deliveries.length,
    successful: deliveries.filter(d => d.status === 'success').length,
    avg_response_time: deliveries.reduce((sum, d) => sum + d.duration_ms, 0) / deliveries.length,
    slow_deliveries: deliveries.filter(d => d.duration_ms > 1000).length
  };

  console.log('Meeting webhook analysis:', analysis);
  return analysis;
}
```

### Alert on Performance Issues

```javascript theme={null}
// Set up automated monitoring
async function monitorWebhookPerformance() {
  const { stats, deliveries } = await getWebhookLogs();

  // Alert on high failure rate
  if (stats.success_rate < 0.90) {
    await sendAlert({
      severity: 'high',
      message: `Webhook failure rate: ${((1 - stats.success_rate) * 100).toFixed(1)}%`,
      failed_count: stats.last_30_days.failed
    });
  }

  // Alert on slow response times
  if (stats.avg_response_time_ms > 2000) {
    await sendAlert({
      severity: 'medium',
      message: `Webhook response time: ${stats.avg_response_time_ms}ms (above 2s threshold)`
    });
  }

  // Alert on recent failures
  const recentFailures = deliveries
    .filter(d => d.status === 'failed')
    .filter(d => Date.now() - new Date(d.timestamp).getTime() < 3600000); // Last hour

  if (recentFailures.length > 5) {
    await sendAlert({
      severity: 'high',
      message: `${recentFailures.length} webhook failures in the last hour`,
      failures: recentFailures.map(f => ({
        event: f.event,
        error: f.error,
        timestamp: f.timestamp
      }))
    });
  }
}

// Run every 15 minutes
setInterval(monitorWebhookPerformance, 15 * 60 * 1000);
```

## Common Failure Patterns

### Connection Timeouts

```json theme={null}
{
  "status": "failed",
  "response_code": 0,
  "error": "Connection timeout after 3 attempts",
  "duration_ms": 30000
}
```

**Solution**: Check your webhook endpoint is responding within 30 seconds. Return 200 OK immediately and process asynchronously.

### 5xx Server Errors

```json theme={null}
{
  "status": "failed",
  "response_code": 500,
  "error": "Internal server error",
  "attempts": 3
}
```

**Solution**: Check your webhook handler logs. Common causes:

* Unhandled exceptions
* Database connection issues
* Missing environment variables

### 401 Unauthorized

```json theme={null}
{
  "status": "failed",
  "response_code": 401,
  "error": "Invalid webhook signature",
  "attempts": 3
}
```

**Solution**: Verify your webhook signature verification code. Ensure `SYNCLINE_WEBHOOK_SECRET` is set correctly.

### SSL/TLS Errors

```json theme={null}
{
  "status": "failed",
  "response_code": 0,
  "error": "SSL certificate verification failed",
  "attempts": 3
}
```

**Solution**: Ensure your webhook URL uses a valid SSL certificate. Self-signed certificates are not supported.

## Dashboard Example

```javascript theme={null}
// Build a webhook monitoring dashboard
async function buildWebhookDashboard() {
  const { deliveries, stats } = await getWebhookLogs();

  return {
    overview: {
      total_sent: stats.total_sent,
      success_rate: (stats.success_rate * 100).toFixed(1) + '%',
      avg_response_time: stats.avg_response_time_ms + 'ms',
      health: stats.success_rate > 0.95 ? '🟢 Healthy' : '🟡 Degraded'
    },
    last_30_days: {
      successful: stats.last_30_days.success,
      failed: stats.last_30_days.failed,
      failure_rate: (stats.last_30_days.failed / (stats.last_30_days.success + stats.last_30_days.failed) * 100).toFixed(1) + '%'
    },
    recent_deliveries: deliveries.slice(0, 10).map(d => ({
      event: d.event,
      status: d.status === 'success' ? '✓' : '✗',
      response_time: d.duration_ms + 'ms',
      timestamp: new Date(d.timestamp).toLocaleString()
    })),
    by_event_type: groupByEventType(deliveries)
  };
}

function groupByEventType(deliveries) {
  const grouped = {};
  deliveries.forEach(d => {
    if (!grouped[d.event]) {
      grouped[d.event] = { total: 0, success: 0, failed: 0 };
    }
    grouped[d.event].total++;
    if (d.status === 'success') {
      grouped[d.event].success++;
    } else {
      grouped[d.event].failed++;
    }
  });
  return grouped;
}
```

## Best Practices

### Regular Monitoring

Check webhook logs daily to catch issues early:

```javascript theme={null}
// Daily health check
async function dailyWebhookHealthCheck() {
  const { stats } = await getWebhookLogs();

  const report = {
    date: new Date().toISOString().split('T')[0],
    success_rate: stats.success_rate,
    total_sent: stats.total_sent,
    avg_response_time: stats.avg_response_time_ms,
    recent_failures: stats.last_30_days.failed
  };

  // Store in database for trending
  await db.webhook_health.create(report);

  // Alert if degraded
  if (stats.success_rate < 0.95) {
    await notifyTeam(report);
  }
}
```

### Set Up Alerts

Configure alerts for critical issues:

* Success rate drops below 95%
* Average response time exceeds 2 seconds
* More than 5 failures in 1 hour
* Any SSL/TLS certificate errors

### Investigate Patterns

Look for patterns in failed deliveries:

```javascript theme={null}
async function analyzeFai lurePatterns() {
  const { deliveries } = await fetch(
    'https://api.syncline.run/v1/platform/webhook/logs?status=failed&limit=200',
    { headers: { 'X-API-Key': process.env.SYNCLINE_API_KEY } }
  ).then(r => r.json());

  // Group by error message
  const errorTypes = {};
  deliveries.forEach(d => {
    const errorKey = d.error.split(':')[0]; // First part of error message
    errorTypes[errorKey] = (errorTypes[errorKey] || 0) + 1;
  });

  // Most common failures
  const sorted = Object.entries(errorTypes)
    .sort(([,a], [,b]) => b - a);

  console.log('Most common webhook failures:');
  sorted.forEach(([error, count]) => {
    console.log(`  ${error}: ${count} occurrences`);
  });
}
```

## Related Endpoints

<CardGroup cols={3}>
  <Card title="Configure Webhooks" icon="gear" href="/webhooks">
    Set up webhook URL and events
  </Card>

  <Card title="Test Webhook" icon="flask" href="/webhooks">
    Send test webhook event
  </Card>

  <Card title="Platform Settings" icon="sliders" href="/api-reference/platform-settings">
    Update platform configuration
  </Card>
</CardGroup>
