Checkout Links
Create and manage shareable payment links for your business.
How It Works
Create a link, share it, receive payments
Create LinkShare URLCustomer PaysFunds Received
1
What are Checkout Links?
Checkout links are shareable payment URLs that allow customers to pay you directly without needing to set up a complicated checkout flow.
**Key Benefits:**
- Share a single URL with customers
- No code required for basic payments
- Customizable plan names and descriptions
- Support for recurring and one-time payments
- Track payments in your dashboard2
Creating a Checkout Link
Use the `createCheckoutLink` server action to create a new payment link.
**Required Parameters:**
```typescript
import { createCheckoutLink } from "@/lib/checkout-links";
type CreateCheckoutLinkInput = {
planName: string; // Display name (e.g., "Premium Plan")
plan: string; // Internal ID (e.g., "premium")
description: string; // Customer-facing description
price: string; // Amount in USD (e.g., "50.00")
billing: "recurring" | "one-time";
initialFee: string; // Optional upfront charge
trial: string; // Optional trial days
stock: string; // Optional inventory limit
};
await createCheckoutLink("biz_your_business_id", {
planName: "Premium Plan",
plan: "premium",
description: "Full access to all features",
price: "50.00",
billing: "recurring",
initialFee: "10.00",
trial: "7",
stock: "100",
});
```
**Response:**
```typescript
// Success
{ ok: true }
// Error
{ ok: false; error: "Plan name is required." }
```3
Checkout Link Properties
Each checkout link has the following properties:
```typescript
import { checkoutLinks } from "@/db/schema";
export const checkoutLinks = pgTable("checkout_links", {
id: uuid("id").primaryKey().defaultRandom(),
businessId: uuid("business_id")
.notNull()
.references(() => businesses.id, { onDelete: "cascade" }),
planId: text("plan_id").notNull().unique(),
planName: text("plan_name").notNull(),
plan: text("plan"),
description: text("description"),
price: numeric("price", { precision: 20, scale: 6 }).notNull(),
currency: text("currency").notNull().default("USDC"),
network: text("network").notNull().default("base-sepolia"),
billing: billingEnum("billing").notNull().default("recurring"),
initialFee: numeric("initial_fee", { precision: 20, scale: 6 }),
trialDays: integer("trial_days"),
stock: integer("stock"),
createdAt: timestamp("created_at").notNull().defaultNow(),
updatedAt: timestamp("updated_at").notNull().defaultNow(),
});
```
**Field Descriptions:**
| Field | Type | Description |
|-------|------|-------------|
| `id` | UUID | Unique identifier |
| `businessId` | UUID | Owner business |
| `planId` | string | Unique plan identifier (plan_...) |
| `planName` | string | Display name shown to customers |
| `plan` | string | Internal plan identifier |
| `description` | string | Detailed description |
| `price` | numeric | Price in USD |
| `currency` | string | Payment currency (default: USDC) |
| `network` | string | Blockchain network |
| `billing` | enum | "recurring" or "one-time" |
| `initialFee` | numeric | Optional upfront charge |
| `trialDays` | integer | Optional free trial period |
| `stock` | integer | Optional inventory limit |4
Retrieving Checkout Links
Fetch all checkout links for your business:
```typescript
import { getCheckoutLinks } from "@/lib/checkout-links";
// Get all links for a business
const links = await getCheckoutLinks("biz_your_business_id");
// Example response
links.forEach(link => {
console.log(`${link.planName}: ${link.price} USD`);
});
```
**Response Structure:**
```typescript
CheckoutLink[] {
id: string;
businessId: string;
planId: string;
planName: string;
plan: string | null;
description: string | null;
price: string;
currency: string;
network: string;
billing: "recurring" | "one-time";
initialFee: string | null;
trialDays: number | null;
stock: number | null;
createdAt: Date;
updatedAt: Date;
}
```5
Deleting a Checkout Link
Remove a checkout link when it's no longer needed:
```typescript
import { deleteCheckoutLink } from "@/lib/checkout-links";
await deleteCheckoutLink("biz_your_business_id", "plan_abc123");
// Response
// { ok: true } | { ok: false; error: "..." }
```
**Important:** Deleting a link prevents new payments but doesn't affect existing transactions.Code Examples
One-Time Payment
// One-time payment for a service
await createCheckoutLink("biz_abc123", {
planName: "Website Redesign",
plan: "web-design",
description: "Full website redesign with 5 pages",
price: "500.00",
billing: "one-time",
initialFee: "",
trial: "",
stock: "",
});Recurring Subscription
// Monthly subscription with trial
await createCheckoutLink("biz_abc123", {
planName: "Premium Monthly",
plan: "premium-monthly",
description: "Monthly premium subscription",
price: "29.00",
billing: "recurring",
initialFee: "10.00",
trial: "7",
stock: "100",
});Best Practices
Use Descriptive Plan Names
Make plan names clear and descriptive so customers understand what they're paying for.
Set Trial Periods
Offer trial periods to reduce friction and increase conversion rates.
Include Detailed Descriptions
Provide comprehensive descriptions to reduce customer questions and support requests.