Good Webhooks

Better Auth client

Client methods, event-name inference, and JSON result types.

good-webhooks/better-auth/client gives a Better Auth client typed methods for the plugin's endpoint management routes.

import { goodWebhooksClient } from 'good-webhooks/better-auth/client'

goodWebhooksClient

goodWebhooksClient<const EventTypes extends readonly string[] = readonly string[]>(
	options?: { eventTypes: EventTypes },
)
auth-client.ts
import { createAuthClient } from 'better-auth/client'
import { goodWebhooksClient } from 'good-webhooks/better-auth/client'

const eventTypes = ['invoice.created', 'invoice.paid'] as const

export const authClient = createAuthClient({
  plugins: [goodWebhooksClient({ eventTypes })],
})

Returns a Better Auth client plugin for createAuthClient.

OptionContract
eventTypesOptional tuple that carries the server's event-name literals into client types. Omitting it leaves event names typed as string. It does not change the server's configured names or authorize requests.

The dedicated client entry point has no runtime import of the server plugin, database driver, or delivery worker. It configures all Good Webhooks route methods as POST and preserves JSON values with JSON.parse, including descriptions that look like dates.

Client methods

import { authClient } from './auth-client.js'

const { data, error } = await authClient.goodWebhooks.create({
  url: 'https://receiver.example/webhooks',
  eventTypes: ['invoice.paid'],
})
if (error) throw new Error(error.message)
console.log(data.secret) // Show once. No later response contains it.

All methods return Better Auth's client result containing data and error. Request bodies and data shapes match the server route reference.

Client methodServer methoddata
authClient.goodWebhooks.create(input)createWebhookEndpoint{ endpoint, secret }
authClient.goodWebhooks.list(input)listWebhookEndpointsWebhookEndpointDTO[]
authClient.goodWebhooks.get(input)getWebhookEndpointWebhookEndpointDTO
authClient.goodWebhooks.update(input)updateWebhookEndpointWebhookEndpointDTO
authClient.goodWebhooks.pause(input)pauseWebhookEndpointWebhookEndpointDTO
authClient.goodWebhooks.resume(input)resumeWebhookEndpointWebhookEndpointDTO
authClient.goodWebhooks.remove(input)removeWebhookEndpointWebhookEndpointDTO
authClient.goodWebhooks.rotateSecret(input)rotateWebhookEndpointSecret{ endpoint, secret }

Each input accepts optional scope. Omission selects the signed-in user's personal scope. scope: null requests application scope and requires server policy. The client does not weaken server authorization. See scope authorization.

Endpoint timestamps remain ISO strings.

Inference example

This compile-only example checks the public server and client types. It omits the database and session setup required by a running application. The Better Auth quick start provides that setup.

Typed Better Auth client
const eventTypes = ['invoice.created', 'invoice.paid'] as const
const auth = betterAuth({ plugins: [goodWebhooks({ eventTypes })] })
const client = createAuthClient({ plugins: [goodWebhooksClient({ eventTypes })] })

const result = await client.goodWebhooks.create({
  url: 'https://receiver.example/hook',
  eventTypes: ['invoice.created'],
})

The same event-name tuple restricts both APIs to invoice.created and invoice.paid. Unknown names fail typechecking.

On this page