Chapter 24 · Operator · Integrations & webhooks

Integrations. The wires.

The operator-side surface for third-party integrations and webhook plumbing. Five components compose the integrations workflow: integration cards, a filterable grid, a webhook delivery console, OAuth-callback banners, and a drop-in integrations page wrapper.

24.1 Integration card

A directory tile for one third-party integration. The card composes a vendor logo + name + status pill in a flex head, an optional description body, and a consumer-supplied action footer pinned to the bottom via margin-top: auto so unequal description lengths don’t misalign the action row across the grid. The status pill (dot + label) maps four canonical states to colour pairs: is-connected uses --success-text for the live-and-wired meaning, is-disconnected uses the sunken neutral for the not-yet-wired meaning, is-error uses --error-text for the delivery-failure meaning, and is-pending uses --warning-text for the awaiting-OAuth meaning. .integration-card-grid is the canonical 3×2 grid wrapper — 3-up on desktop, 2-up at tablet, single-column on phone.

Six cards — Slack, GitHub, Stripe, Notion, Linear, Figma

.integration-card

Six integration cards arranged in the canonical 3×2 .integration-card-grid, one per canonical state. Slack (Productivity / connected / Manage) and GitHub (Developer / connected / Manage) demo the live-and-wired meaning; Stripe (Payments / error / Retry) demos the delivery-failure meaning; Notion (Productivity / disconnected / Connect) and Figma (Design / disconnected / Connect) demo the not-yet-wired meaning; Linear (Developer / pending / Cancel) demos the awaiting-OAuth meaning. Each card carries its own simple inline-SVG lettermark logo — a 40×40 tinted rect with a centred white initial — keeping the demo deterministic without external assets.

Slack Connected

Send deal updates and pipeline notifications to a channel.

GitHub Connected

Open pull requests and surface review status on deal cards.

Stripe Error

Pull invoice and subscription data into the billing tab.

Notion Disconnected

Mirror meeting notes and project briefs into linked records.

Linear Pending

Two-way sync issues to deals — awaiting OAuth confirmation.

Figma Disconnected

Embed design file previews and version links on records.

<div class="integration-card-grid">
  <div class="integration-card">
    <div class="integration-card-head">
      <span class="integration-card-logo">
        <svg width="40" height="40" viewBox="0 0 40 40" aria-hidden="true">
          <rect width="40" height="40" rx="8" fill="#611F69"/>
          <text x="20" y="26" text-anchor="middle" font-size="16" font-weight="700" fill="#fff">S</text>
        </svg>
      </span>
      <span class="integration-card-name">Slack</span>
      <span class="integration-card-status is-connected">
        <span class="integration-card-status-dot" aria-hidden="true"></span>
        Connected
      </span>
    </div>
    <p class="integration-card-desc">Send deal updates…</p>
    <div class="integration-card-action">
      <button type="button" class="btn btn-ghost">Manage</button>
    </div>
  </div>
  …
</div>
.integration-card {
  display: flex;
  flex-direction: column;
  gap: var(--s-3);
  padding: var(--s-4);
  border: 1px solid var(--hair);
  border-radius: var(--r-md);
  background: var(--bg-paper);
}

.integration-card-head {
  display: flex;
  align-items: center;
  gap: var(--s-3);
}

.integration-card-logo {
  width: 40px;
  height: 40px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  color: var(--fg);
  flex-shrink: 0;
}

.integration-card-name {
  font: 600 14px/1.3 var(--f-body);
  color: var(--fg);
}

.integration-card-status {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font: 500 11px/1 var(--f-mono);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

.integration-card-status.is-connected    { color: var(--success-text); }

.integration-card-status.is-disconnected { color: var(--fg-dim); }

.integration-card-status.is-error        { color: var(--error-text); }

.integration-card-status.is-pending      { color: var(--warning-text); }

.integration-card-status-dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: currentColor;
}

.integration-card-desc {
  font: 400 13px/1.5 var(--f-body);
  color: var(--fg-soft);
  margin: 0;
}

.integration-card-action {
  margin-top: auto;
}

.integration-card-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--s-3);
}

@media (max-width: 720px) {
  .integration-card-grid { grid-template-columns: repeat(2, 1fr); }
}

@media (max-width: 480px) {
  .integration-card-grid { grid-template-columns: 1fr; }
  .integration-card-action { width: 100%; }
  .integration-card-action .btn { width: 100%; }
}
import { IntegrationCard } from "@magicblocksai/ui";

<div className="integration-card-grid">
  <IntegrationCard
    logo={<SlackLogo />}
    name="Slack"
    description="Send deal updates and pipeline notifications to a channel."
    status="connected"
    category="Productivity"
    action={<button type="button" className="btn btn-ghost">Manage</button>}
  />
  <IntegrationCard
    logo={<GitHubLogo />}
    name="GitHub"
    description="Open pull requests and surface review status on deal cards."
    status="connected"
    category="Developer"
    action={<button type="button" className="btn btn-ghost">Manage</button>}
  />
  <IntegrationCard
    logo={<StripeLogo />}
    name="Stripe"
    description="Pull invoice and subscription data into the billing tab."
    status="error"
    category="Payments"
    action={<button type="button" className="btn btn-ghost">Retry</button>}
  />
  <IntegrationCard
    logo={<NotionLogo />}
    name="Notion"
    description="Mirror meeting notes and project briefs into linked records."
    status="disconnected"
    category="Productivity"
    action={<button type="button" className="btn btn-primary">Connect</button>}
  />
  <IntegrationCard
    logo={<LinearLogo />}
    name="Linear"
    description="Two-way sync issues to deals — awaiting OAuth confirmation."
    status="pending"
    category="Developer"
    action={<button type="button" className="btn btn-ghost">Cancel</button>}
  />
  <IntegrationCard
    logo={<FigmaLogo />}
    name="Figma"
    description="Embed design file previews and version links on records."
    status="disconnected"
    category="Design"
    action={<button type="button" className="btn btn-primary">Connect</button>}
  />
</div>

24.2 Integrations grid

A wrapper that pairs a row of category filter chips with a responsive grid of integration cards. The chip row reuses the kit’s global .chip styling and toggles .is-active on the selected chip; the inner .integrations-grid-list is 3-up on desktop, 2-up at tablet, and single-column on phone — and the chip row switches to a horizontal scroller at the phone breakpoint so a longer category list never overflows. The wrapper itself doesn’t filter the children: filtering happens at the consumer’s data layer via the onCategoryChange callback, keeping the grid layout fully declarative.

Filtered grid — All / Productivity / Developer / Payments

.integrations-grid

An .integrations-grid with four filter chips above the canonical six-card grid from section 26.1. The first chip (All) is active; the chips render as <button class="chip"> with aria-pressed mirroring active state. Each card carries its own inline-SVG lettermark logo (40×40 tinted rect + centred white initial), keeping the demo deterministic without external assets.

Slack Connected

Send deal updates and pipeline notifications to a channel.

GitHub Connected

Open pull requests and surface review status on deal cards.

Stripe Error

Pull invoice and subscription data into the billing tab.

Notion Disconnected

Mirror meeting notes and project briefs into linked records.

Linear Pending

Two-way sync issues to deals — awaiting OAuth confirmation.

Figma Disconnected

Embed design file previews and version links on records.

<div class="integrations-grid">
  <div class="integrations-grid-filters" role="group" aria-label="Filter integrations by category">
    <button type="button" class="chip is-active" aria-pressed="true">All</button>
    <button type="button" class="chip" aria-pressed="false">Productivity</button>
    <button type="button" class="chip" aria-pressed="false">Developer</button>
    <button type="button" class="chip" aria-pressed="false">Payments</button>
  </div>
  <div class="integrations-grid-list">
    <div class="integration-card">…</div>
    …
  </div>
</div>
.integrations-grid {
  display: flex;
  flex-direction: column;
  gap: var(--s-4);
}

.integrations-grid-filters {
  display: flex;
  gap: var(--s-2);
  flex-wrap: wrap;
}

.integrations-grid-list {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--s-3);
}

@media (max-width: 720px) {
  .integrations-grid-list { grid-template-columns: repeat(2, 1fr); }
}

@media (max-width: 480px) {
  .integrations-grid-list { grid-template-columns: 1fr; }
  .integrations-grid-filters { overflow-x: auto; flex-wrap: nowrap; }
}
import { IntegrationsGrid, IntegrationCard } from "@magicblocksai/ui";

<IntegrationsGrid
  categories={["All", "Productivity", "Developer", "Payments"]}
  defaultActiveCategory="All"
  onCategoryChange={(cat) => setFilter(cat)}
>
  <IntegrationCard
    logo={<SlackLogo />}
    name="Slack"
    description="Send deal updates and pipeline notifications to a channel."
    status="connected"
    category="Productivity"
    action={<button type="button" className="btn btn-ghost">Manage</button>}
  />
  <IntegrationCard
    logo={<GitHubLogo />}
    name="GitHub"
    description="Open pull requests and surface review status on deal cards."
    status="connected"
    category="Developer"
    action={<button type="button" className="btn btn-ghost">Manage</button>}
  />
  <IntegrationCard
    logo={<StripeLogo />}
    name="Stripe"
    description="Pull invoice and subscription data into the billing tab."
    status="error"
    category="Payments"
    action={<button type="button" className="btn btn-ghost">Retry</button>}
  />
  <IntegrationCard
    logo={<NotionLogo />}
    name="Notion"
    description="Mirror meeting notes and project briefs into linked records."
    status="disconnected"
    category="Productivity"
    action={<button type="button" className="btn btn-primary">Connect</button>}
  />
  <IntegrationCard
    logo={<LinearLogo />}
    name="Linear"
    description="Two-way sync issues to deals — awaiting OAuth confirmation."
    status="pending"
    category="Developer"
    action={<button type="button" className="btn btn-ghost">Cancel</button>}
  />
  <IntegrationCard
    logo={<FigmaLogo />}
    name="Figma"
    description="Embed design file previews and version links on records."
    status="disconnected"
    category="Design"
    action={<button type="button" className="btn btn-primary">Connect</button>}
  />
</IntegrationsGrid>

24.3 Webhook console

A mono-font table of recent webhook deliveries — timestamp / endpoint / event / status / duration. Status codes are colour-coded by first digit so a glance reads the health of the queue without parsing every row: .is-2xx uses --success-text for the OK path, .is-4xx uses --warning-text for client-side errors (rate-limit, validation), and .is-5xx uses --error-text for server-side failures. The header row is always a <div>; each delivery row is rendered as a <button> when the consumer wires onDeliveryClick (typically to open a detail drawer) or a <div> when the console reads as a read-only log. Below 480px the five-column grid reflows to a two-row layout: timestamp + endpoint on the first row, event spanning both columns on the second row, status pinned to the right of the first row, and duration dropped to preserve the timestamp + status priority at the phone breakpoint.

Six deliveries — mixed status (200 / 200 / 200 / 429 / 500 / 204)

.webhook-console

A read-only .webhook-console with six recent deliveries newest-first: three healthy 2xx responses (Slack lead.created, Stripe payment.succeeded, Zapier task.completed), one 429 rate-limit retry on the same Zapier endpoint (.is-4xx), one 500 server failure on Slack message.received (.is-5xx, 5012ms duration showing the slow timeout-then-fail path), and one 204 no-content on a Notion page.updated webhook. Status codes carry the colour-coded modifier; rows are static <div>s since no click handler is wired in the demo.

Time Endpoint Event Status Duration
10:34:12 POST /webhooks/slack lead.created 200 142ms
10:31:54 POST /webhooks/stripe payment.succeeded 200 89ms
10:28:22 POST /webhooks/zapier task.completed 200 234ms
10:24:08 POST /webhooks/zapier task.completed 429 0ms
10:18:43 POST /webhooks/slack message.received 500 5012ms
10:12:01 POST /webhooks/notion page.updated 204 67ms
<div class="webhook-console">
  <div class="webhook-console-row is-header" role="row">
    <span class="webhook-console-timestamp">Time</span>
    <span class="webhook-console-endpoint">Endpoint</span>
    <span class="webhook-console-event">Event</span>
    <span class="webhook-console-status">Status</span>
    <span class="webhook-console-duration">Duration</span>
  </div>
  <div class="webhook-console-row">
    <span class="webhook-console-timestamp">10:34:12</span>
    <span class="webhook-console-endpoint">POST /webhooks/slack</span>
    <span class="webhook-console-event">lead.created</span>
    <span class="webhook-console-status is-2xx">200</span>
    <span class="webhook-console-duration">142ms</span>
  </div>
  …
</div>
.webhook-console {
  background: var(--bg-paper);
  border: 1px solid var(--hair);
  border-radius: var(--r-md);
  overflow: hidden;
}

.webhook-console-row {
  display: grid;
  grid-template-columns: auto 1fr auto auto auto;
  gap: var(--s-3);
  padding: var(--s-3) var(--s-4);
  border-bottom: 1px solid var(--hair);
  font: 13px var(--f-mono);
  align-items: center;
  text-align: left;
  width: 100%;
  background: transparent;
}

.webhook-console-row:last-child { border-bottom: 0; }

button.webhook-console-row { border-left: 0; border-right: 0; border-top: 0; color: inherit; cursor: pointer; }

button.webhook-console-row:hover { background: var(--bg-sunk); }

.webhook-console-row.is-header {
  background: var(--bg-sunk);
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--fg-faint);
}

.webhook-console-timestamp { color: var(--fg-dim); white-space: nowrap; }

.webhook-console-endpoint { color: var(--fg); min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.webhook-console-event { color: var(--accent-text); }

.webhook-console-status { font-weight: 600; }

.webhook-console-status.is-2xx { color: var(--success-text); }

.webhook-console-status.is-4xx { color: var(--warning-text); }

.webhook-console-status.is-5xx { color: var(--error-text); }

.webhook-console-duration { color: var(--fg-dim); }

@media (max-width: 480px) {
  .webhook-console-row { grid-template-columns: 1fr auto; grid-template-rows: auto auto; }
  .webhook-console-event { grid-column: 1 / 3; grid-row: 2; font-size: 11px; }
  .webhook-console-duration { display: none; }
}
import { WebhookConsole } from "@magicblocksai/ui";

<WebhookConsole
  deliveries={[
    { id: "d1", timestamp: "10:34:12", endpoint: "POST /webhooks/slack",
      eventType: "lead.created", statusCode: 200, durationMs: 142 },
    { id: "d2", timestamp: "10:31:54", endpoint: "POST /webhooks/stripe",
      eventType: "payment.succeeded", statusCode: 200, durationMs: 89 },
    { id: "d3", timestamp: "10:28:22", endpoint: "POST /webhooks/zapier",
      eventType: "task.completed", statusCode: 200, durationMs: 234 },
    { id: "d4", timestamp: "10:24:08", endpoint: "POST /webhooks/zapier",
      eventType: "task.completed", statusCode: 429, durationMs: 0 },
    { id: "d5", timestamp: "10:18:43", endpoint: "POST /webhooks/slack",
      eventType: "message.received", statusCode: 500, durationMs: 5012 },
    { id: "d6", timestamp: "10:12:01", endpoint: "POST /webhooks/notion",
      eventType: "page.updated", statusCode: 204, durationMs: 67 },
  ]}
/>

24.4 OAuth callback banner

A page-level banner that confirms the outcome of an OAuth round-trip — tick + green on success, cross + red on failure, clock + amber on pending. The intent is carried on the root <aside> via data-intent, which drives both the colour pair (success--success-*, failure--error-*, pending--warning-*) and the leading icon glyph. The actions slot lives to the right of the body block on desktop; at the phone breakpoint the banner stacks vertically and the slot stretches to full width so two buttons sit comfortably below the title. .oauth-callback-stack is the canonical wrapper for showing two or three banners in sequence (e.g. queueing OAuth outcomes that arrived in the same session).

Three banners stacked — success / failure / pending

.oauth-callback-banner

Three .oauth-callback-banners wrapped in .oauth-callback-stack, one per intent. Success demos a freshly-linked Slack workspace with a "View setup" link action; failure demos a rejected Stripe OAuth token with a "Retry" + "Contact support" action pair; pending demos a verification-email round-trip awaiting confirmation, no actions. Each banner carries its own inline SVG glyph (tick / cross / clock) keeping the demo deterministic without depending on the kit’s icon barrel.

<div class="oauth-callback-stack">
  <aside class="oauth-callback-banner" data-intent="success">
    <span class="oauth-callback-banner-icon">
      <svg width="20" height="20" viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="1.6">
        <circle cx="10" cy="10" r="8"/>
        <path d="M6.5 10.5L9 13L14 7.5"/>
      </svg>
    </span>
    <div class="oauth-callback-banner-text">
      <span class="oauth-callback-banner-title">Slack connected</span>
      <span class="oauth-callback-banner-desc">We’ve linked your workspace…</span>
    </div>
    <div class="oauth-callback-banner-actions">
      <a class="btn btn-ghost" href="#">View setup</a>
    </div>
  </aside>
  <aside class="oauth-callback-banner" data-intent="failure">…</aside>
  <aside class="oauth-callback-banner" data-intent="pending">…</aside>
</div>
.oauth-callback-banner {
  display: flex;
  gap: var(--s-3);
  padding: var(--s-3) var(--s-4);
  border-radius: var(--r-md);
  border: 1px solid;
  align-items: flex-start;
}

.oauth-callback-banner[data-intent="success"] {
  background: var(--success-soft);
  border-color: var(--success);
  color: var(--success-text);
}

.oauth-callback-banner[data-intent="failure"] {
  background: var(--error-soft);
  border-color: var(--error);
  color: var(--error-text);
}

.oauth-callback-banner[data-intent="pending"] {
  background: var(--warning-soft);
  border-color: var(--warning);
  color: var(--warning-text);
}

.oauth-callback-banner-icon {
  width: 20px;
  height: 20px;
  flex-shrink: 0;
}

.oauth-callback-banner-text {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.oauth-callback-banner-title { font: 600 14px/1.3 var(--f-body); }

.oauth-callback-banner-desc { font: 400 13px/1.5 var(--f-body); opacity: 0.85; }

.oauth-callback-banner-actions {
  flex-shrink: 0;
  display: flex;
  gap: var(--s-2);
}

@media (max-width: 480px) {
  .oauth-callback-banner { flex-direction: column; }
  .oauth-callback-banner-actions { width: 100%; }
}

.oauth-callback-stack {
  display: flex;
  flex-direction: column;
  gap: var(--s-3);
}
import { OAuthCallbackBanner } from "@magicblocksai/ui";

<div className="oauth-callback-stack">
  <OAuthCallbackBanner
    intent="success"
    title="Slack connected"
    description="We've linked your workspace. Webhooks will start firing in 30 seconds."
    actions={<a className="btn btn-ghost" href="/settings/integrations/slack">View setup</a>}
  />
  <OAuthCallbackBanner
    intent="failure"
    title="Connection failed"
    description="Stripe rejected the OAuth token. Check your API credentials and try again."
    actions={<>
      <button type="button" className="btn btn-ghost" onClick={retry}>Retry</button>
      <a className="btn btn-ghost" href="/support">Contact support</a>
    </>}
  />
  <OAuthCallbackBanner
    intent="pending"
    title="Awaiting confirmation"
    description="We've sent a verification email to admin@acme.com. Click the link to finish the connection."
  />
</div>

24.5 Integrations page

A page-shaped wrapper composing the chapter’s four primitives into the canonical integrations-page layout: an optional <OAuthCallbackBanner> on top, then the <IntegrationsGrid> wrapping a flat list of <IntegrationCard> children, then the <WebhookConsole> beneath. The two lower sections each carry a small uppercase sub-header (.integrations-page-section-label) styled as a 16px var(--f-display) 600-weight label in var(--fg-soft); the banner section is unlabelled so the freshly-arrived OAuth outcome reads as the page’s lede. The wrapper is stateless glue — <IntegrationsGrid> owns its filter-chip state, <WebhookConsole> wires the consumer’s onDeliveryClick when interactivity is needed, and each composed primitive carries its own mobile reflow so the page surface reflows naturally at every breakpoint.

Realistic integrations page — banner + 6 cards + 4 deliveries

.integrations-page

A realistic post-OAuth view: a success banner confirms a freshly-linked Slack workspace, the integrations grid surfaces the six canonical states from 26.1 with the four category chips from 26.2 above, and the webhook-delivery console below shows four recent deliveries (three healthy 2xx responses + one 429 rate-limit retry) drawn from the section 26.3 dataset. The page wrapper just stacks the three sections; everything inside each section delegates to the primitive from 26.1–26.4.

Slack Connected

Send deal updates and pipeline notifications to a channel.

GitHub Connected

Open pull requests and surface review status on deal cards.

Stripe Error

Pull invoice and subscription data into the billing tab.

Notion Disconnected

Mirror meeting notes and project briefs into linked records.

Linear Pending

Two-way sync issues to deals — awaiting OAuth confirmation.

Figma Disconnected

Embed design file previews and version links on records.

Time Endpoint Event Status Duration
10:34:12 POST /webhooks/slack lead.created 200 142ms
10:31:54 POST /webhooks/stripe payment.succeeded 200 89ms
10:28:22 POST /webhooks/zapier task.completed 200 234ms
10:24:08 POST /webhooks/zapier task.completed 429 0ms
<div class="integrations-page">
  <aside class="oauth-callback-banner" data-intent="success">…</aside>
  <section class="integrations-page-section">
    <h2 class="integrations-page-section-label">Integrations</h2>
    <div class="integrations-grid">
      <div class="integrations-grid-filters" role="group">…</div>
      <div class="integrations-grid-list">
        <div class="integration-card">…</div>
        …
      </div>
    </div>
  </section>
  <section class="integrations-page-section">
    <h2 class="integrations-page-section-label">Webhook deliveries</h2>
    <div class="webhook-console">…</div>
  </section>
</div>
.integrations-page {
  display: flex;
  flex-direction: column;
  gap: var(--s-8);
}

.integrations-page-section {
  display: flex;
  flex-direction: column;
  gap: var(--s-4);
}

.integrations-page-section-label {
  margin: 0;
  font: 600 16px/1.2 var(--f-display);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--fg-soft);
}
import { IntegrationsPage } from "@magicblocksai/ui";

<IntegrationsPage
  banner={{
    intent: "success",
    title: "Slack connected",
    description: "We've linked your workspace. Webhooks will start firing in 30 seconds.",
    actions: <a className="btn btn-ghost" href="/settings/integrations/slack">View setup</a>,
  }}
  categories={["All", "Productivity", "Developer", "Payments"]}
  integrations={[
    { logo: <SlackLogo />, name: "Slack",
      description: "Send deal updates and pipeline notifications to a channel.",
      status: "connected", category: "Productivity",
      action: <button type="button" className="btn btn-ghost">Manage</button> },
    { logo: <GitHubLogo />, name: "GitHub",
      description: "Open pull requests and surface review status on deal cards.",
      status: "connected", category: "Developer",
      action: <button type="button" className="btn btn-ghost">Manage</button> },
    { logo: <StripeLogo />, name: "Stripe",
      description: "Pull invoice and subscription data into the billing tab.",
      status: "error", category: "Payments",
      action: <button type="button" className="btn btn-ghost">Retry</button> },
    { logo: <NotionLogo />, name: "Notion",
      description: "Mirror meeting notes and project briefs into linked records.",
      status: "disconnected", category: "Productivity",
      action: <button type="button" className="btn btn-primary">Connect</button> },
    { logo: <LinearLogo />, name: "Linear",
      description: "Two-way sync issues to deals — awaiting OAuth confirmation.",
      status: "pending", category: "Developer",
      action: <button type="button" className="btn btn-ghost">Cancel</button> },
    { logo: <FigmaLogo />, name: "Figma",
      description: "Embed design file previews and version links on records.",
      status: "disconnected", category: "Design",
      action: <button type="button" className="btn btn-primary">Connect</button> },
  ]}
  webhookDeliveries={[
    { id: "d1", timestamp: "10:34:12", endpoint: "POST /webhooks/slack",
      eventType: "lead.created", statusCode: 200, durationMs: 142 },
    { id: "d2", timestamp: "10:31:54", endpoint: "POST /webhooks/stripe",
      eventType: "payment.succeeded", statusCode: 200, durationMs: 89 },
    { id: "d3", timestamp: "10:28:22", endpoint: "POST /webhooks/zapier",
      eventType: "task.completed", statusCode: 200, durationMs: 234 },
    { id: "d4", timestamp: "10:24:08", endpoint: "POST /webhooks/zapier",
      eventType: "task.completed", statusCode: 429, durationMs: 0 },
  ]}
/>