Documentation Index
Fetch the complete documentation index at: https://docs.usepaykit.dev/llms.txt
Use this file to discover all available pages before exploring further.
Any class that implements PayKitProvider works with PayKit. Only @paykit-sdk/core is needed.
Install
npm install @paykit-sdk/core
Full example (HTTP API)
import {
AbstractPayKitProvider,
PayKitProvider,
HTTPClient,
ProviderMetadataRegistry,
PaykitProviderOptions,
schema,
ValidationError,
NotImplementedError,
ProviderNotSupportedError,
createCheckoutSchema,
CreateCheckoutSchema,
Checkout,
WebhookEventPayload,
WebhookHandlerConfig,
} from '@paykit-sdk/core';
import { z } from 'zod';
// 1. Define typed provider_metadata per resource
interface MyMetadata extends ProviderMetadataRegistry {
checkout?: { custom_reference?: string };
refund?: { reason_code?: string };
}
// 2. Define typed raw events
type MyRawEvents = {
'myprovider.payment.completed': { id: string; amount: number };
'myprovider.refund.processed': { id: string };
};
// 3. Define options
export interface MyProviderOptions extends PaykitProviderOptions {
apiKey: string;
}
const optionsSchema = schema<MyProviderOptions>()(
z.object({
apiKey: z.string().min(1, 'API key is required'),
isSandbox: z.boolean(),
}),
);
// 4. Implement the provider
export class MyProvider
extends AbstractPayKitProvider
implements PayKitProvider<MyMetadata, null, MyRawEvents>
{
readonly providerName = 'my-provider';
private _client: HTTPClient;
constructor(protected readonly opts: MyProviderOptions) {
super(optionsSchema, opts, 'my-provider');
this._client = new HTTPClient({
baseUrl: opts.isSandbox
? 'https://api.sandbox.myprovider.com'
: 'https://api.myprovider.com',
headers: {
Authorization: `Bearer ${opts.apiKey}`,
'Content-Type': 'application/json',
},
retryOptions: { max: 3, baseDelay: 1000, debug: opts.debug ?? false },
});
}
get _native() { return null; }
createCheckout = async (
params: CreateCheckoutSchema<MyMetadata['checkout']>,
): Promise<Checkout> => {
const { error, data } = createCheckoutSchema.safeParse(params);
if (error) throw ValidationError.fromZodError(error, this.providerName, 'createCheckout');
const res = await this._client.post<Record<string, unknown>>('/checkouts', {
body: JSON.stringify(data),
});
if (!res.ok) throw new Error('Failed to create checkout');
return res.value as unknown as Checkout;
};
// Mark operations not supported by this provider
updateCheckout = (_id: string) =>
Promise.reject(
new ProviderNotSupportedError('updateCheckout', this.providerName, {
reason: 'This provider does not support modifying checkouts after creation',
}),
);
// Mark operations planned for the future
deleteCheckout = (_id: string) =>
Promise.reject(
new NotImplementedError('deleteCheckout', this.providerName, { futureSupport: true }),
);
// ... implement remaining required methods
handleWebhook = async (
payload: WebhookHandlerConfig,
webhookSecret: string,
): Promise<Array<WebhookEventPayload<MyRawEvents>>> => {
const signature = payload.headersAsObject['x-signature'];
if (!signature) throw new Error('Missing signature');
// verify signature, parse body, return typed events
return [];
};
}
Error helpers
| Class | Use for |
|---|
ValidationError.fromZodError(err, provider, method) | Invalid input |
ProviderNotSupportedError(method, provider, { reason }) | Operations the provider will never support |
NotImplementedError(method, provider, { futureSupport }) | Not built yet |
Register it
import { PayKit, createEndpointHandlers } from '@paykit-sdk/core';
export const paykit = new PayKit(
new MyProvider({ apiKey: 'key_...', isSandbox: true }),
);
export const endpoints = createEndpointHandlers(paykit);