'use client' import { useState } from 'react' import { Copy, Eye, EyeOff, RotateCcw } from 'lucide-react' import { rotateWebhookSecret } from '@/lib/actions' import type { SaveStatus, Space } from '../types' interface Props extends SaveStatus { space: Space isAdmin: boolean } export function WebhooksPanel({ space, isAdmin, saving, setSaving, setMessage }: Props) { const [webhookSecret, setWebhookSecret] = useState(space.webhook_secret || '') const [copiedWebhook, setCopiedWebhook] = useState(false) const [copiedSecret, setCopiedSecret] = useState(false) const [showWebhookSecret, setShowWebhookSecret] = useState(false) async function handleRotateWebhook() { if (!isAdmin) return setSaving(true) const result = await rotateWebhookSecret() if (result.secret) { setWebhookSecret(result.secret) setShowWebhookSecret(true) setMessage({ type: 'success', text: 'New signing secret generated. Copy it now and store it securely.' }) } setSaving(false) } function copyToClipboard(text: string) { navigator.clipboard.writeText(text) setCopiedWebhook(true) setTimeout(() => setCopiedWebhook(false), 2000) } function copySecretToClipboard(text: string) { if (!text) return navigator.clipboard.writeText(text) setCopiedSecret(true) setTimeout(() => setCopiedSecret(false), 2000) } return (

Webhook Endpoint

POST members to this endpoint for external integration or automation.

https://api.hackerspace.sh/{space.slug}/members
View Docs

Signing Secret

Every delivery is signed with HMAC-SHA256 using this secret. See the docs for verification examples in Node and Python.

{webhookSecret ? (showWebhookSecret ? webhookSecret : '•'.repeat(Math.min(webhookSecret.length, 48))) : No secret set. Rotate to generate one.} {webhookSecret && ( )}
{webhookSecret && ( )} {isAdmin && ( )}
{webhookSecret && (

Rotating immediately invalidates the previous secret. Update your receiver before rotating in production.

)}
) }