Webhooks
Webhook endpoint configuration view component for DeveloperApp
Webhooks
The Webhooks view provides an interface for configuring webhook endpoints, managing event subscriptions, viewing delivery logs, and testing webhook integrations.
Type Signature
interface WebhooksViewProps {
/** Page title */
title?: string
/** Page description */
description?: string
/** View layout mode */
layout?: 'single' | 'column' | 'canvas' | 'vibe'
/** Webhook endpoints */
webhooks?: Array<{
id: string
url: string // Webhook URL
events: string[] // Subscribed event types
active: boolean
secret?: string // Webhook signing secret
created: string
}>
/** Recent deliveries */
deliveries?: Array<{
id: string
event: string
status: number // HTTP status code
timestamp: string
duration?: number // Response time in ms
}>
/** Allow testing webhooks */
allowTest?: boolean
/** Show delivery logs */
showLogs?: boolean
/** Page-level action buttons */
actions?: Array<{
id: string
label: string
icon?: string
onClick?: () => void
variant?: 'default' | 'primary' | 'destructive'
}>
/** Child content */
children?: React.ReactNode
}Usage
<App name="Developer Portal">
<Shell>
<WebhooksView
title="Webhooks"
description="Configure webhook endpoints for event notifications"
allowTest={true}
showLogs={true}
/>
</Shell>
</App>Props
title
The page title displayed in the header. Defaults to "Webhooks".
<WebhooksView title="Webhooks">description
Optional page description or subtitle.
<WebhooksView
title="Webhooks"
description="Receive real-time notifications when events occur in your account"
>layout
Layout mode for the view content. Defaults to 'single'.
// Single column layout (default)
<WebhooksView layout="single">
// Multi-column layout
<WebhooksView layout="column">webhooks
Array of configured webhook endpoints.
<WebhooksView
webhooks={[
{
id: 'wh_1',
url: 'https://api.example.com/webhooks',
events: ['user.created', 'user.updated', 'payment.success'],
active: true,
secret: 'whsec_••••••••••••8a3f',
created: '2024-01-15T10:30:00Z'
},
{
id: 'wh_2',
url: 'https://staging.example.com/webhooks',
events: ['user.created'],
active: false,
created: '2024-06-20T14:00:00Z'
}
]}
>deliveries
Recent webhook delivery attempts with status codes.
<WebhooksView
deliveries={[
{
id: 'del_1',
event: 'user.created',
status: 200,
timestamp: '2024-12-19T08:15:00Z',
duration: 145
},
{
id: 'del_2',
event: 'payment.success',
status: 500,
timestamp: '2024-12-19T08:10:00Z',
duration: 2340
}
]}
>allowTest
Enable webhook testing functionality. Defaults to true.
<WebhooksView allowTest={true}>
{/* Shows "Test" button for each webhook */}
</WebhooksView>showLogs
Display delivery logs for debugging. Defaults to true.
<WebhooksView showLogs={true}>
{/* Shows recent delivery attempts */}
</WebhooksView>actions
Page-level action buttons displayed in the header.
<WebhooksView
actions={[
{
id: 'create',
label: 'Add Endpoint',
icon: 'Plus',
variant: 'primary',
onClick: () => openCreateDialog()
},
{
id: 'docs',
label: 'Webhook Docs',
icon: 'Book',
onClick: () => navigateToDocs()
}
]}
>Webhook Management
Creating Endpoints
Configure new webhook endpoints with event subscriptions:
const handleCreateWebhook = async (data: CreateWebhookData) => {
const webhook = await createWebhook({
url: data.url,
events: data.events,
active: true
})
toast.success('Webhook created')
refetchWebhooks()
}
<WebhooksView>
<CreateWebhookDialog
onSubmit={handleCreateWebhook}
events={[
'user.created',
'user.updated',
'user.deleted',
'payment.success',
'payment.failed'
]}
/>
</WebhooksView>Updating Endpoints
Edit existing webhook configurations:
const handleUpdateWebhook = async (id: string, data: UpdateWebhookData) => {
await updateWebhook(id, {
url: data.url,
events: data.events,
active: data.active
})
toast.success('Webhook updated')
}
<WebhooksView>
<EditWebhookDialog
webhook={selectedWebhook}
onSubmit={(data) => handleUpdateWebhook(selectedWebhook.id, data)}
/>
</WebhooksView>Deleting Endpoints
Remove webhook endpoints:
const handleDeleteWebhook = async (id: string) => {
if (confirm('Delete this webhook endpoint?')) {
await deleteWebhook(id)
toast.success('Webhook deleted')
refetchWebhooks()
}
}
<WebhooksView
webhooks={webhooks}
onDelete={handleDeleteWebhook}
>Event Subscriptions
Subscribe to specific events:
<CreateWebhookDialog
events={[
{
id: 'user.created',
label: 'User Created',
description: 'Triggered when a new user is created'
},
{
id: 'user.updated',
label: 'User Updated',
description: 'Triggered when a user profile is updated'
},
{
id: 'payment.success',
label: 'Payment Success',
description: 'Triggered when a payment is successfully processed'
},
{
id: 'payment.failed',
label: 'Payment Failed',
description: 'Triggered when a payment fails'
}
]}
>
<FormField
label="Events"
name="events"
type="checkbox-group"
description="Select which events should trigger this webhook"
/>
</CreateWebhookDialog>Testing Webhooks
Send test events to verify webhook configuration:
const handleTestWebhook = async (webhookId: string, event: string) => {
const result = await testWebhook(webhookId, {
event,
data: generateSamplePayload(event)
})
if (result.status === 200) {
toast.success('Test webhook delivered successfully')
} else {
toast.error(`Test failed with status ${result.status}`)
}
}
<WebhooksView allowTest={true}>
<WebhookCard
webhook={webhook}
actions={[
{
label: 'Test',
onClick: () => openTestDialog(webhook.id)
}
]}
/>
<TestWebhookDialog
webhook={webhook}
events={webhook.events}
onTest={handleTestWebhook}
/>
</WebhooksView>Delivery Logs
View webhook delivery history and debug failures:
<WebhooksView showLogs={true}>
<DeliveryLogsTable
deliveries={deliveries}
columns={[
'event',
'status',
'timestamp',
'duration',
'actions'
]}
onRetry={(deliveryId) => retryDelivery(deliveryId)}
onViewDetails={(deliveryId) => showDeliveryDetails(deliveryId)}
/>
</WebhooksView>Delivery Details
Show detailed delivery information:
<DeliveryDetailsDialog
delivery={{
id: 'del_1',
event: 'user.created',
url: 'https://api.example.com/webhooks',
status: 200,
timestamp: '2024-12-19T08:15:00Z',
duration: 145,
request: {
headers: {
'Content-Type': 'application/json',
'X-Webhook-Signature': 'sha256=...'
},
body: {
event: 'user.created',
data: { id: 'usr_123', email: 'user@example.com' }
}
},
response: {
status: 200,
headers: { 'Content-Type': 'application/json' },
body: { received: true }
}
}}
>
<Tabs>
<TabsList>
<TabsTrigger value="request">Request</TabsTrigger>
<TabsTrigger value="response">Response</TabsTrigger>
</TabsList>
<TabsContent value="request">
<CodeBlock code={JSON.stringify(delivery.request, null, 2)} language="json" />
</TabsContent>
<TabsContent value="response">
<CodeBlock code={JSON.stringify(delivery.response, null, 2)} language="json" />
</TabsContent>
</Tabs>
</DeliveryDetailsDialog>Webhook Signatures
Secure webhooks with signing secrets:
<WebhooksView>
<WebhookCard webhook={webhook}>
<div className="mt-4">
<Label>Signing Secret</Label>
<div className="flex items-center gap-2">
<Code>{webhook.secret}</Code>
<Button size="sm" onClick={() => copySecret(webhook.id)}>
Copy
</Button>
<Button size="sm" onClick={() => rotateSecret(webhook.id)}>
Rotate
</Button>
</div>
<p className="text-sm text-muted-foreground mt-1">
Use this secret to verify webhook signatures
</p>
</div>
</WebhookCard>
</WebhooksView>Signature Verification Example
Show code examples for verifying signatures:
<WebhooksView>
<DocsSection title="Verifying Signatures">
<Tabs>
<TabsList>
<TabsTrigger value="node">Node.js</TabsTrigger>
<TabsTrigger value="python">Python</TabsTrigger>
<TabsTrigger value="php">PHP</TabsTrigger>
</TabsList>
<TabsContent value="node">
<CodeBlock language="javascript" code={`
const crypto = require('crypto');
function verifyWebhook(payload, signature, secret) {
const hash = crypto
.createHmac('sha256', secret)
.update(payload)
.digest('hex');
return signature === \`sha256=\${hash}\`;
}
`} />
</TabsContent>
</Tabs>
</DocsSection>
</WebhooksView>Retry Logic
Handle failed deliveries with automatic retries:
<WebhooksView>
<WebhookCard webhook={webhook}>
<div className="mt-4">
<Label>Retry Settings</Label>
<FormField
label="Max Retries"
name="maxRetries"
type="number"
defaultValue={3}
description="Number of retry attempts for failed deliveries"
/>
<FormField
label="Retry Delay"
name="retryDelay"
type="select"
options={[
{ value: '60', label: '1 minute' },
{ value: '300', label: '5 minutes' },
{ value: '900', label: '15 minutes' }
]}
/>
</div>
</WebhookCard>
</WebhooksView>Active/Inactive Webhooks
Toggle webhook status:
const handleToggleWebhook = async (id: string, active: boolean) => {
await updateWebhook(id, { active })
toast.success(active ? 'Webhook activated' : 'Webhook paused')
}
<WebhooksView>
<WebhookCard webhook={webhook}>
<Switch
checked={webhook.active}
onCheckedChange={(active) => handleToggleWebhook(webhook.id, active)}
label="Active"
/>
</WebhookCard>
</WebhooksView>Layout Examples
List Layout
Display webhooks in a list with delivery stats:
<WebhooksView layout="single">
<div className="space-y-4">
{webhooks.map(webhook => (
<Card key={webhook.id}>
<CardHeader>
<div className="flex items-center justify-between">
<CardTitle>{webhook.url}</CardTitle>
<Switch
checked={webhook.active}
onCheckedChange={(active) => toggleWebhook(webhook.id, active)}
/>
</div>
</CardHeader>
<CardContent>
<div className="space-y-2">
<div>
<Label>Events</Label>
<div className="flex flex-wrap gap-1 mt-1">
{webhook.events.map(event => (
<Badge key={event} variant="secondary">{event}</Badge>
))}
</div>
</div>
<div className="flex items-center gap-4 text-sm text-muted-foreground">
<span>Created {formatDate(webhook.created)}</span>
<span>{deliveryCount} deliveries</span>
<span>{successRate}% success</span>
</div>
</div>
</CardContent>
<CardFooter>
<Button variant="ghost" onClick={() => testWebhook(webhook.id)}>
Test
</Button>
<Button variant="ghost" onClick={() => editWebhook(webhook.id)}>
Edit
</Button>
<Button variant="destructive" onClick={() => deleteWebhook(webhook.id)}>
Delete
</Button>
</CardFooter>
</Card>
))}
</div>
</WebhooksView>Split View
Show webhooks and recent deliveries side-by-side:
<WebhooksView layout="column">
<div className="grid grid-cols-2 gap-6">
<div>
<h3 className="text-lg font-semibold mb-4">Endpoints</h3>
<WebhooksList webhooks={webhooks} />
</div>
<div>
<h3 className="text-lg font-semibold mb-4">Recent Deliveries</h3>
<DeliveryLogsTable deliveries={recentDeliveries} />
</div>
</div>
</WebhooksView>Empty State
Handle cases with no webhooks configured:
<WebhooksView>
{webhooks.length === 0 ? (
<EmptyState
icon="Webhook"
title="No webhooks configured"
description="Add a webhook endpoint to receive real-time notifications when events occur"
action={{
label: 'Add Endpoint',
onClick: () => openCreateDialog()
}}
/>
) : (
<WebhooksList webhooks={webhooks} />
)}
</WebhooksView>Integration with Payload CMS
Auto-wire to Payload webhooks collection:
// Auto-fetches from Payload 'webhooks' collection
<WebhooksView collection="webhooks">
{/* Webhooks loaded automatically */}
</WebhooksView>DeveloperApp Integration
Part of the DeveloperApp component suite:
<DeveloperDashboard
config={{
showAPIKeys: true,
showWebhooks: true,
showUsage: true,
showLogs: true
}}
>
<APIKeysView />
<WebhooksView />
<UsageView />
<LogsView />
</DeveloperDashboard>Responsive Behavior
The view adapts to screen size:
Desktop (≥1024px)
┌────────────────────────────────────────┐
│ Webhooks [Add] │
├────────────────────────────────────────┤
│ ┌──────────────────────────────────┐ │
│ │ https://api.example.com/webhooks │ │
│ │ [user.created] [payment.success] │ │
│ │ Active • Created Jan 15, 2024 │ │
│ │ 1,245 deliveries • 99.8% success │ │
│ │ [Test] [Edit] [Delete] │ │
│ └──────────────────────────────────┘ │
└────────────────────────────────────────┘
Full card layoutMobile (under 768px)
┌────────────────────────────┐
│ Webhooks [+] │
├────────────────────────────┤
│ ┌────────────────────┐ │
│ │ api.example.com │ │
│ │ [user.created] │ │
│ │ Active • Jan 15 │ │
│ │ [Test] [Edit] │ │
│ └────────────────────┘ │
└────────────────────────────┘
Compact card layoutAccessibility
The Webhooks view implements accessibility features:
- Keyboard navigation - Tab through webhooks and actions
- Screen reader labels - Descriptive labels for webhooks and status
- Focus management - Focus moves to newly created webhook
- Status announcements - Announce delivery success/failure
<WebhooksView aria-label="Webhook endpoint management">
<WebhookCard
aria-label={`Webhook endpoint ${webhook.url}, ${webhook.active ? 'active' : 'inactive'}`}
>
<Switch
aria-label={`Toggle webhook ${webhook.url}`}
checked={webhook.active}
onCheckedChange={toggleWebhook}
/>
</WebhookCard>
</WebhooksView>