Usage & Integration
Create and manage events with the Events API and Stripe integration
This page shows practical examples of creating, fetching, and deleting events in Plainform.
Creating Events with Postman
Send a POST request to /api/events with authentication:
Setup:
- Method:
POST - URL:
http://localhost:3000/api/events(or your production domain) - Headers:
Content-Type: application/jsonAuthorization: Bearer your_event_api_secret
Body:
{
"text": "🎉 New blog post: How to build SaaS apps faster",
"type": "post",
"slug": "/blog/how-to-build-saas-apps-faster",
"icon": "Newspaper"
}Response (201):
{
"message": "Event saved (replaced any previous).",
"ok": true
}The Authorization header is required. Without it, you'll get a 401 Unauthorized response.
Event Data Structure
| Field | Type | Required | Description |
|---|---|---|---|
text | string | Yes | Display text (3-500 characters) |
type | enum | Yes | 'post', 'coupon', or 'product' |
slug | string | Yes | URL to link to |
icon | string | No | Icon name |
Example payloads:
{
"text": "📝 New guide: Building authentication flows",
"type": "post",
"slug": "/blog/building-authentication-flows"
}{
"text": "🎉 Limited time: 50% off all plans!",
"type": "coupon",
"slug": "/#buy",
"icon": "Sparkles"
}Automatic Creation from Stripe
Events are automatically created when you add a Stripe coupon with isFeatured: true metadata.
Steps:
- Go to Products → Coupons in Stripe Dashboard
- Click Create coupon
- Set coupon details (name, discount, duration)
- Add metadata:
isFeatured=true - Click Create coupon
The webhook automatically creates an event using the coupon name as the text.
Webhook handler:
switch (event.type) {
case 'coupon.created':
case 'coupon.updated':
if (event?.data?.object?.metadata?.isFeatured === 'true') {
await recordEvent({
text: event?.data?.object?.name as string,
slug: '#coupon',
type: 'coupon',
});
revalidateTag('event', 'max');
}
break;
case 'coupon.deleted':
if (event?.data?.object?.metadata?.isFeatured === 'true') {
await deleteEventByType('coupon');
}
break;
}Fetching Events
Get the most recent event with a GET request:
curl http://localhost:3000/api/eventsResponse:
{
"event": {
"id": "clx1234567890",
"text": "🎉 50% off - Limited time offer!",
"type": "coupon",
"slug": "/#buy",
"timestamp": "1704067200000"
}
}Using in components:
import { getEvent } from '@/lib/events/getEvent';
export default async function HomePage() {
const data = await getEvent();
if (!data?.event) {
return null;
}
return (
<a href={data.event.slug}>
{data.event.text}
</a>
);
}Deleting Events
Delete by Type
Remove all events of a specific type using Postman:
- Method:
DELETE - URL:
http://localhost:3000/api/events(or your production domain) - Headers: Same as POST
- Body:
{
"type": "coupon"
}Delete by ID
Remove a specific event:
{
"id": "clx1234567890"
}Event Replacement
Creating a new event of the same type replaces the previous one:
// Remove old event of same type
await prisma.event.deleteMany({ where: { type } });
// Create new event
await prisma.event.create({
data: { text, type, slug, icon, timestamp }
});This ensures only one event per type exists in the database.
Mock Event Fallback
If no events exist, the component displays a mock event from locales/en.json:
{
"homePage": {
"mockEvent": {
"text": "Your event announcement goes here",
"slug": "#buy",
"type": "coupon"
}
}
}Update this to match your brand messaging during development.
Rate Limiting
The API limits requests to prevent abuse:
- Limit: 10 requests per 10 seconds per IP
- Applies to: POST and DELETE requests
- GET requests: Not rate limited
Rate limit response:
{
"error": "Too many requests",
"retryAfter": 8
}Next Steps
- Setup & Configuration - Configure EVENT_API_SECRET
- Payments Overview - Learn about Stripe webhooks
How is this guide ?
Last updated on