@payclave/sdk-server
v0.1.1
Published
TypeScript server SDK for Payclave non-custodial crypto checkout.
Maintainers
Readme
@payclave/sdk-server
TypeScript server SDK for Payclave — non-custodial crypto checkout for merchants.
Use this package from your backend with a Payclave secret key. Never expose sk_test_... or sk_live_... keys in browser code.
Package name: @payclave/sdk-server.
Install
npm install @payclave/sdk-server
# or
bun add @payclave/sdk-serverCreate a checkout session
import { createPayclaveServerClient } from "@payclave/sdk-server"
const payclave = createPayclaveServerClient({
secretKey: process.env.PAYCLAVE_SECRET_KEY!,
})
export async function POST(request: Request) {
const order = await request.json()
const session = await payclave.createCheckoutSession({
amount: order.total,
externalReference: order.id,
customerEmail: order.customerEmail,
successUrl: `https://merchant.example/orders/${order.id}/success`,
cancelUrl: "https://merchant.example/cart",
metadata: {
cartId: order.cartId,
},
idempotencyKey: order.id,
})
return Response.json({ checkoutUrl: session.checkoutUrl })
}API
createPayclaveServerClient(options)
| Option | Type | Description |
| ------------ | ------------------------- | ----------------------------------------------------------------- |
| secretKey | string | sk_test_... or sk_live_.... Required. |
| apiBaseUrl | string | Override the API base URL. Defaults to https://api.payclave.com. |
| fetcher | (url, init) => Response | Custom fetch implementation for tests or custom runtimes. |
| timeoutMs | number | Per-request timeout. |
Returns typed helpers:
createCheckoutSession(input)getCheckoutSession(id)createInvoice(input)getInvoice(id)getPayment(id)createWebhookEndpoint(input)createTestWebhook(input)listWebhookDeliveries(input?)
Authentication
This SDK is for backend code only and sends Authorization: Bearer sk_test_... or Authorization: Bearer sk_live_... on every request. Use publishable pk_test_... or pk_live_... keys only with browser checkout integrations.
Checkout session input
| Field | Type | Description |
| ------------------ | ------------- | ---------------------------------------------------------------------------- |
| amount | string | Positive USDT decimal with up to 6 fractional digits, e.g. "25.00". |
| externalReference | string? | Your order reference. |
| customerEmail | string? | Customer email for checkout records. |
| successUrl | string? | URL to return to after payment. |
| cancelUrl | string? | URL to return to when checkout is cancelled. |
| metadata | object? | Merchant-defined metadata. |
| expiresInMinutes | number? | Checkout expiry, 5 to 1440 minutes. |
| idempotencyKey | string? | Sent as Idempotency-Key; reuse only for retries of the same request. |
| signal | AbortSignal? | Cancel the request. |
Invoice input
createInvoice accepts amount, externalReference, metadata, expiresInMinutes, idempotencyKey, and signal. Reuse the same idempotencyKey only when retrying the same invoice creation request after a timeout, network failure, RATE_LIMIT_EXCEEDED, or 5xx response.
Webhook endpoints
createWebhookEndpoint accepts a url, optional eventTypes, and signal. Supported event types are exported as PAYCLAVE_WEBHOOK_EVENT_TYPES and currently include invoice.paid, invoice.expired, payment.failed, payment.underpaid, and payment.overpaid.
Payclave returns the endpoint signingSecret once when the endpoint is created. Store it securely and use it to verify incoming webhook deliveries.
Webhook signatures
Verify Payclave webhooks against the exact raw request body:
import { constructPayclaveWebhookEvent } from "@payclave/sdk-server"
export async function POST(request: Request) {
const rawBody = await request.text()
const signature = request.headers.get("X-Payclave-Signature") ?? ""
const event = constructPayclaveWebhookEvent({
payload: rawBody,
signature,
secret: process.env.PAYCLAVE_WEBHOOK_SECRET!,
})
if (event.type === "invoice.paid") {
// Fulfill the order referenced by event.data.
}
return new Response(null, { status: 204 })
}constructPayclaveWebhookEvent throws PayclaveError when the signature, timestamp, or payload is invalid. Use verifyPayclaveWebhookSignature when you only need a boolean.
Webhook deliveries include X-Payclave-Signature, X-Payclave-Timestamp, X-Payclave-Delivery, and X-Payclave-Event headers. The signature format is t=<unix_timestamp>,v1=<hex_hmac_sha256>.
Errors
All client- and server-side failures throw a PayclaveError:
import { PayclaveError } from "@payclave/sdk-server"
try {
await payclave.createCheckoutSession({ amount: "25.00" })
} catch (err) {
if (err instanceof PayclaveError) {
err.code
err.status
err.requestId
err.details
err.cause
}
}Built-in client codes include INVALID_SECRET_KEY, INVALID_API_BASE_URL, INVALID_TIMEOUT, INVALID_ID, INVALID_AMOUNT, INVALID_EXPIRY, INVALID_METADATA, INVALID_IDEMPOTENCY_KEY, INVALID_LIMIT, INVALID_WEBHOOK_URL, INVALID_REQUEST_BODY, INVALID_RESPONSE, NETWORK_ERROR, TIMEOUT, ABORTED, and webhook verification errors. Server-supplied API codes are passed through unchanged.
The package exports typed error-code lists for exhaustive handling and autocomplete:
PAYCLAVE_API_ERROR_CODESPAYCLAVE_SERVER_SDK_ERROR_CODESPAYCLAVE_WEBHOOK_VERIFICATION_ERROR_CODESPayclaveApiErrorCodePayclaveServerSdkErrorCodePayclaveWebhookVerificationErrorCodePayclaveErrorCode
SDK identification
Every request includes X-Payclave-Client: payclave-sdk-server/<version> so the API can correlate bug reports to SDK versions.
License
MIT — see LICENSE.
