# How to Integrate Bolt.new with Eventbrite

- Tool: Bolt.new
- Difficulty: Intermediate
- Time required: 25 minutes
- Last updated: April 2026

## TL;DR

Eventbrite's REST API integrates with Bolt.new through a Next.js API route using a private token for fetching events, ticket types, and attendee data. For simple event listings, Eventbrite also provides an embeddable checkout widget. Webhook notifications (ticket purchased, attendee checked in) require a publicly accessible deployed URL — they cannot be received in Bolt's WebContainer preview.

## Building Custom Event Pages and Attendee Dashboards with Eventbrite in Bolt.new

Eventbrite is the world's largest event marketplace and ticketing platform, hosting millions of events from small meetups to large conferences. For developers building with Bolt.new, Eventbrite integration opens two powerful workflows. The first is building custom event discovery and ticketing experiences — rather than sending users to Eventbrite's website, you display event listings styled to match your app, embed the ticket purchase flow directly in your UI, and track conversions as part of your funnel. The second is building tools for event organizers — attendee management dashboards, check-in apps, custom registration forms, and real-time attendance analytics that organizers can use before, during, and after events.

Eventbrite's API is a standard REST API with comprehensive coverage of the platform's features. Authentication uses a private token (long-lived OAuth token) that you get by creating an Eventbrite app in their developer portal. The API covers events (listing, searching, creating, updating), tickets and ticket classes (pricing tiers, availability), orders (ticket purchases), attendees (registration details, check-in status), and organizations (managing multiple events under one account).

For simple use cases — displaying an event on your marketing site with a 'Buy Tickets' button — Eventbrite's embeddable checkout widget is far simpler than building an API integration. The embed loads a Eventbrite-hosted modal with full ticket selection and payment handling. You only need the event ID from the URL. This widget works in Bolt's WebContainer preview immediately and requires no API token. For custom attendee dashboards, advanced ticket management, or automated workflows triggered by ticket purchases, the REST API approach is necessary and is covered in full in this guide.

## Before you start

- An Eventbrite account (eventbrite.com) with at least one published event (or use Eventbrite's test event functionality)
- An Eventbrite private token from the Eventbrite API developer portal at eventbrite.com/platform/api — create an app and copy the private token from the API Keys section
- Your Eventbrite organization ID or user ID — find it by calling GET /v3/users/me/ with your token or checking your Eventbrite account URL
- A Bolt.new project using Next.js for the API route pattern
- A deployed URL on Netlify or Bolt Cloud for webhook testing (required only if you need booking confirmation webhooks)

## Step-by-step guide

### 1. Get an Eventbrite API token and set up environment variables

Eventbrite's REST API requires a private OAuth token for authentication. Unlike some simpler APIs that give you an API key directly, Eventbrite requires you to create an 'App' in their developer portal first, which then grants you an OAuth token for your account.

To get your token, go to eventbrite.com and sign in. Navigate to your account settings and find the developer section, or go directly to eventbrite.com/platform/api. Click 'Create App.' Give your app a name (e.g., 'My Bolt Event App'), provide a brief description, enter your application URL (you can use your Bolt project URL or localhost for now), and enter any callback URL (can be https://localhost for development purposes). Accept the terms and click 'Create Key.'

On the API Keys page for your new app, you will see three values: the API Key, the API Secret (Client Secret), and the Private Token. For server-to-server integrations in Bolt.new, you want the Private Token — it acts as a pre-authorized Bearer token for your own Eventbrite account. Copy it.

Also note your Organization ID if you want to list events by organizer. Call the Eventbrite API directly from your browser: https://www.eventbriteapi.com/v3/users/me/?token=YOUR_TOKEN_HERE. Look for the 'id' field in the response — this is your user ID, which often matches your organization ID for single-account setups. For multi-organization accounts, check the organizations array in the response.

Add these values to your Bolt.new .env file: EVENTBRITE_TOKEN (the private token, server-side only, no NEXT_PUBLIC_ prefix) and NEXT_PUBLIC_EVENTBRITE_ORG_ID (the organization/user ID, safe for client-side use since it is not sensitive). The organization ID is a public identifier used to filter event listings.

```
# .env
# Eventbrite private token — server-side only
# Get from: eventbrite.com/platform/api → Your Apps → API Keys → Private Token
EVENTBRITE_TOKEN=your_private_token_here

# Eventbrite Organization/User ID — safe for client-side use
# Find by calling: https://www.eventbriteapi.com/v3/users/me/?token=YOUR_TOKEN
# Look for the 'id' field in the response
NEXT_PUBLIC_EVENTBRITE_ORG_ID=123456789

# Test your token works:
# curl https://www.eventbriteapi.com/v3/users/me/ -H 'Authorization: Bearer YOUR_TOKEN'
```

**Expected result:** Your .env file contains the Eventbrite private token and organization ID. Testing the token with a direct API call (GET /v3/users/me/ with the Bearer token) returns your account details, confirming the credentials are correct.

### 2. Create the Eventbrite API service and event listing route

With credentials in place, build the API service layer in Bolt.new. The Eventbrite API base URL is https://www.eventbriteapi.com/v3 and uses Bearer token authentication. Create a lib/eventbrite.ts utility module that handles the Authorization header and wraps fetch calls with error handling.

Eventbrite's event listing endpoint is GET /v3/organizations/{orgId}/events/. The key query parameters are: status (draft, live, completed, canceled, started — use 'live' for public published events), time_filter (current_future for upcoming events, past for past events), expand (comma-separated list of related objects to include in the response — use 'venue,ticket_classes,logo' to get location, ticket pricing, and event images in one call), and page_size (up to 50 events per page). The expand parameter is essential for avoiding N+1 API calls — without it, you would need separate requests for each event's venue and ticket details.

The event object returned by Eventbrite has a rich structure: name.text (event title), description.text (plain text description), description.html (full HTML description), start.local and end.local (ISO datetime strings), venue (full venue object if expanded), ticket_classes (array of ticket tiers if expanded), logo.original.url (event banner image), and online_event (boolean).

Prompt Bolt to generate the API service and event listing route. After Bolt generates the code, test it in the Bolt preview by navigating to /api/eventbrite/events in the browser — you should see a JSON response with your published events. If you do not have any live events, create a simple test event in Eventbrite to verify the integration.

```
// lib/eventbrite.ts
const EVENTBRITE_BASE = 'https://www.eventbriteapi.com/v3';

async function eventbriteFetch<T>(endpoint: string, params?: Record<string, string>): Promise<T> {
  const token = process.env.EVENTBRITE_TOKEN;
  if (!token) throw new Error('EVENTBRITE_TOKEN not configured');

  const url = new URL(`${EVENTBRITE_BASE}${endpoint}`);
  if (params) {
    Object.entries(params).forEach(([k, v]) => url.searchParams.set(k, v));
  }

  const res = await fetch(url.toString(), {
    headers: { Authorization: `Bearer ${token}` },
  });

  if (!res.ok) {
    const err = await res.json().catch(() => ({}));
    throw new Error(`Eventbrite API error ${res.status}: ${JSON.stringify(err)}`);
  }
  return res.json();
}

interface RawEvent {
  id: string;
  name: { text: string };
  description: { text: string };
  start: { local: string };
  end: { local: string };
  url: string;
  online_event: boolean;
  logo?: { original?: { url: string } };
  venue?: { name: string; address?: { localized_address_display: string } };
  ticket_classes?: Array<{ cost?: { display: string; value: number }; free: boolean }>;
}

interface EventListResponse { events: RawEvent[]; pagination: { has_more_items: boolean; continuation: string } }

export async function listEvents(orgId: string) {
  const data = await eventbriteFetch<EventListResponse>(`/organizations/${orgId}/events/`, {
    status: 'live',
    time_filter: 'current_future',
    expand: 'venue,ticket_classes,logo',
    page_size: '20',
  });

  return data.events.map((e) => {
    const prices = (e.ticket_classes ?? []).filter((t) => !t.free).map((t) => t.cost?.value ?? 0);
    return {
      id: e.id,
      name: e.name.text,
      description: e.description.text ?? '',
      startTime: e.start.local,
      endTime: e.end.local,
      venueName: e.venue?.name ?? (e.online_event ? 'Online' : ''),
      venueAddress: e.venue?.address?.localized_address_display ?? '',
      isOnline: e.online_event,
      imageUrl: e.logo?.original?.url ?? '',
      isFree: (e.ticket_classes ?? []).every((t) => t.free),
      minPrice: prices.length ? Math.min(...prices) / 100 : 0,
      maxPrice: prices.length ? Math.max(...prices) / 100 : 0,
      eventbriteUrl: e.url,
    };
  });
}
```

**Expected result:** The /api/eventbrite/events route returns normalized event data including names, dates, venues, and ticket prices. The Bolt preview shows a JSON array of your organization's upcoming published events.

### 3. Build the event listing UI with ticket purchase

With event data flowing from the API route, build the React event listing interface. This UI displays events from your Eventbrite account in a custom-designed format that matches your brand — completely different from Eventbrite's standard page layout.

For the ticket purchase flow, you have two approaches. The simpler approach uses Eventbrite's embeddable checkout widget: a JavaScript library that opens a Eventbrite-hosted checkout modal when clicked. This requires only the event ID and handles all payment processing, ticket delivery, and confirmation natively. The more advanced approach uses Eventbrite's Orders API to build a fully custom checkout flow — but this requires PCI compliance consideration since you would be handling payment data, making the embed widget strongly preferable for most use cases.

The embed widget is loaded from Eventbrite's CDN as a script tag. Once loaded, calling EBWidgets.createWidget() with your event ID renders a checkout button that opens a modal. The modal is hosted by Eventbrite and handles all payment processing — your React app never sees the payment details. This approach works in Bolt's WebContainer preview as long as your event is published and live in Eventbrite.

For the event listing cards, display: event cover image (with a placeholder gradient if no image), event name, date and time formatted in the user's local timezone, location (or 'Online Event'), ticket price range (or 'Free'), and a 'Get Tickets' button that triggers the Eventbrite embed widget for that event. Add filtering by date, event type, or price range if your organization hosts multiple event categories.

```
// components/EventCard.tsx
'use client';
import { useEffect } from 'react';

interface Event {
  id: string;
  name: string;
  startTime: string;
  venueName: string;
  imageUrl: string;
  isFree: boolean;
  minPrice: number;
  maxPrice: number;
  eventbriteUrl: string;
}

declare global {
  interface Window {
    EBWidgets?: {
      createWidget: (options: {
        widgetType: string;
        eventId: string;
        modal: boolean;
        modalTriggerElementId: string;
        onOrderComplete: () => void;
      }) => void;
    };
  }
}

export function EventCard({ event }: { event: Event }) {
  const buttonId = `eb-btn-${event.id}`;

  useEffect(() => {
    // Load Eventbrite widget script if not already loaded
    if (!document.getElementById('eb-widget-script')) {
      const script = document.createElement('script');
      script.id = 'eb-widget-script';
      script.src = 'https://www.eventbrite.com/static/widgets/eb_widgets.js';
      script.async = true;
      script.onload = () => initWidget();
      document.head.appendChild(script);
    } else if (window.EBWidgets) {
      initWidget();
    }

    function initWidget() {
      window.EBWidgets?.createWidget({
        widgetType: 'checkout',
        eventId: event.id,
        modal: true,
        modalTriggerElementId: buttonId,
        onOrderComplete: () => {
          console.log(`Order complete for event ${event.id}`);
        },
      });
    }
  }, [event.id, buttonId]);

  const priceLabel = event.isFree ? 'Free' :
    event.minPrice === event.maxPrice ? `$${event.minPrice}` :
    `$${event.minPrice}–$${event.maxPrice}`;

  return (
    <div className="rounded-xl overflow-hidden border shadow-sm hover:shadow-md transition-shadow">
      {event.imageUrl ? (
        <img src={event.imageUrl} alt={event.name} className="h-48 w-full object-cover" />
      ) : (
        <div className="h-48 w-full bg-gradient-to-br from-purple-500 to-pink-500" />
      )}
      <div className="p-5">
        <h3 className="font-bold text-lg line-clamp-2">{event.name}</h3>
        <p className="mt-1 text-sm text-gray-500">{new Date(event.startTime).toLocaleDateString('en-US', { weekday: 'long', month: 'long', day: 'numeric' })}</p>
        <p className="text-sm text-gray-500">{event.venueName}</p>
        <div className="mt-4 flex items-center justify-between">
          <span className="font-medium text-purple-600">{priceLabel}</span>
          <button id={buttonId} className="rounded-lg bg-purple-600 px-4 py-2 text-sm font-medium text-white hover:bg-purple-700">
            Get Tickets
          </button>
        </div>
      </div>
    </div>
  );
}
```

**Expected result:** The events page displays custom-styled event cards fetched from Eventbrite. Clicking 'Get Tickets' opens Eventbrite's checkout modal. Users can complete ticket purchases directly in the modal without leaving your app.

### 4. Handle Eventbrite webhooks for booking notifications after deployment

Eventbrite webhooks notify your app when events occur on the platform: order.placed (ticket purchased), order.updated, order.refunded, event.created, event.updated, and attendee.updated. These event-driven notifications enable post-booking automation — sending custom confirmation emails, provisioning access to a members area, adding the attendee to a mailing list, or updating internal dashboards in real time.

As with all webhook-based integrations in Bolt.new, there is a critical limitation to understand: Bolt's WebContainer has no public URL, so Eventbrite cannot send webhook events to your development environment. You must deploy to Netlify or Bolt Cloud first to get a public HTTPS URL, then register that URL in Eventbrite's webhook settings.

First, create the webhook handler in Bolt. Add a Next.js API route at app/api/webhooks/eventbrite/route.ts. Eventbrite webhooks send a JSON payload containing the event action, the user's API key (which you can use to verify the webhook came from Eventbrite), and the object that changed. Unlike some webhook providers, Eventbrite does not use HMAC signatures for verification — instead, they include the API key associated with the app in the webhook payload, which you compare to your known token.

After deployment, register your webhook URL in Eventbrite's developer portal: go to eventbrite.com/platform/api → Your Apps → select your app → Webhooks → Add new webhook. Enter your deployed URL (https://yourapp.netlify.app/api/webhooks/eventbrite), select the actions to receive (order.placed is the most commonly needed), and save. Eventbrite will send a test ping to verify your endpoint is reachable.

```
// app/api/webhooks/eventbrite/route.ts
// NOTE: Webhooks require a public URL — deploy first, then register in Eventbrite developer portal
import { NextResponse } from 'next/server';

export async function POST(request: Request) {
  const body = await request.json();

  const { action, api_url: apiUrl, config } = body;

  // Basic verification — check the user ID matches your account
  const expectedUserId = process.env.EVENTBRITE_USER_ID;
  if (expectedUserId && config?.user_id && config.user_id !== expectedUserId) {
    return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
  }

  if (action === 'order.placed' && apiUrl) {
    try {
      // Fetch the full order details from Eventbrite
      const orderRes = await fetch(apiUrl, {
        headers: { Authorization: `Bearer ${process.env.EVENTBRITE_TOKEN}` },
      });
      const order = await orderRes.json();

      const attendee = order.attendees?.[0];
      console.log(`New order ${order.id}: ${attendee?.profile?.name} (${attendee?.profile?.email})`);

      // TODO: Add to database, send custom confirmation email, etc.
    } catch (err) {
      console.error('Failed to process order webhook:', err);
    }
  } else if (action === 'order.refunded') {
    console.log(`Order refunded: ${apiUrl}`);
    // TODO: Update database, revoke access
  } else if (action === 'attendee.updated') {
    console.log(`Attendee updated: ${apiUrl}`);
    // TODO: Sync updated attendee info
  }

  // Always return 200 immediately so Eventbrite does not retry
  return NextResponse.json({ received: true });
}
```

**Expected result:** After deployment, Eventbrite webhooks reach the handler at /api/webhooks/eventbrite. Server logs show new ticket purchases with attendee names and emails within seconds of a booking being completed.

## Best practices

- Use the Eventbrite checkout widget for ticket purchase flows rather than building a custom checkout — the widget is maintained by Eventbrite, handles payment security compliance, and works without any backend code
- Always use the expand parameter when listing events to fetch venue, ticket classes, and logo in a single API call — this avoids N+1 requests that waste API quota
- Store EVENTBRITE_TOKEN in .env (development) and your hosting platform's environment variables (production) — it is effectively a full-access token to your Eventbrite account
- Add image placeholders (gradient divs or a default event banner) for events that have no uploaded image — relying on imageUrl being present will cause broken img tags for events without covers
- Cache event listings in React state or SWR with a 5-minute TTL — event data changes infrequently and does not need to be refetched on every page visit
- Register Eventbrite webhooks pointing to your production URL, not a staging URL — Eventbrite delivers webhooks in real time and retries failed deliveries, so a staging endpoint could receive production booking data
- Respond to Eventbrite webhooks within 5 seconds and return 200 immediately — process the webhook payload asynchronously to avoid timeout retries

## Use cases

### Custom Event Landing Page with Ticket Purchase

A fully branded event landing page that displays event details, a speaker lineup, schedule, and ticket options fetched from Eventbrite's API. Clicking 'Buy Tickets' opens Eventbrite's embedded checkout modal. The page design matches the event brand rather than using Eventbrite's default event page.

Prompt example:

```
Build a custom event landing page using Eventbrite's API. Create a Next.js API route at /api/eventbrite/event/[eventId]/route.ts that fetches event details (name, description, start/end time, venue, logo) and ticket classes (name, price, availability) using EVENTBRITE_TOKEN from process.env. Display a hero section with the event name and date, a description section, a speaker grid (from event description), and a ticket purchase section showing available ticket types. Add an Eventbrite embed widget for ticket purchase using the event ID. Use Tailwind CSS for a professional event page layout.
```

### Event Organizer Dashboard

An internal dashboard for an event organizer showing real-time attendee counts, ticket type breakdowns, revenue, and order details for their events. Organizers can view their events, see check-in progress, and export attendee lists — all in a custom interface.

Prompt example:

```
Create an event organizer dashboard that reads data from Eventbrite API. Create API routes for: (1) /api/eventbrite/events - list my organization's events with name, date, attendee count, capacity, revenue. (2) /api/eventbrite/events/[id]/attendees - list attendees for an event with name, email, order date, ticket type, check-in status. Build a React dashboard with an event selector, summary stats (total tickets sold, checked in, revenue), and a searchable attendee table with CSV export. Use EVENTBRITE_TOKEN in process.env. Use Tailwind and shadcn/ui Table.
```

### Multi-Event Series Discovery Page

A content site for a recurring event series (monthly meetups, workshop series) that automatically pulls upcoming events from Eventbrite and displays them in a clean listing format. When new events are created in Eventbrite, they automatically appear on the site without any manual content updates.

Prompt example:

```
Build an upcoming events listing page that fetches events from a specific Eventbrite organizer. Create an API route at /api/eventbrite/upcoming that calls https://www.eventbriteapi.com/v3/organizations/{ORG_ID}/events/?status=live&time_filter=current_future&expand=venue,ticket_classes with EVENTBRITE_TOKEN. Display events as cards with event image (or placeholder), name, date/time, location, price range (free to paid), and a 'Register' button linking to the Eventbrite event page or embedding the checkout widget. Add a skeleton loading state and handle 'no upcoming events' gracefully.
```

## Troubleshooting

### Eventbrite API returns 401 INVALID_AUTH on all requests

Cause: The EVENTBRITE_TOKEN in .env is incorrect or the private token has been revoked. Eventbrite private tokens are associated with a specific OAuth app and user account.

Solution: Go to eventbrite.com/platform/api → Your Apps → select your app → API Keys. Copy the Private Token from this page. If the app was deleted or the token revoked, create a new app to generate a fresh token. Paste the new token into EVENTBRITE_TOKEN in your .env file. Verify by testing the token: fetch https://www.eventbriteapi.com/v3/users/me/ with Authorization: Bearer YOUR_TOKEN in a browser or curl.

### Event listing returns an empty 'events' array even though events exist in Eventbrite

Cause: The events are in draft or past status, or the organization ID is incorrect. The API route filters for status=live and time_filter=current_future, which excludes draft events, past events, and canceled events.

Solution: Verify your events are 'Published' (not draft) in Eventbrite. Check the organization ID is correct by calling /v3/users/me/ and looking at the id field. If testing with future events only, remove the time_filter parameter temporarily to see all event statuses. For development testing, create a live published event in Eventbrite — even a free test event works.

```
// Temporarily remove time_filter to see all events regardless of date
const data = await eventbriteFetch<EventListResponse>(`/organizations/${orgId}/events/`, {
  status: 'live',
  // time_filter: 'current_future',  // Remove this to see all live events
  expand: 'venue,ticket_classes,logo',
});
```

### Eventbrite checkout widget button does nothing when clicked

Cause: The EBWidgets.createWidget() call failed silently because the Eventbrite widget script had not fully loaded when initWidget() was called, or the event ID does not exist or is not published.

Solution: Ensure createWidget is called inside the script's onload callback, not immediately after the script tag is added. Check the browser console for any Eventbrite widget errors. Verify the event ID is a numeric string (not a URL or slug). Confirm the event is published as 'Live' in Eventbrite — draft events do not work with the checkout widget.

```
// Add error logging to diagnose widget initialization issues
script.onload = () => {
  console.log('EBWidgets loaded:', !!window.EBWidgets);
  if (window.EBWidgets) {
    window.EBWidgets.createWidget({ ... });
  } else {
    console.error('EBWidgets not available after script load');
  }
};
```

### Eventbrite webhooks are not being received in development

Cause: Bolt's WebContainer has no public URL for Eventbrite to send webhooks to. This is expected behavior — webhooks cannot be tested in Bolt's browser-based development environment.

Solution: Deploy to Netlify or Bolt Cloud first to get a public HTTPS URL. Then register the deployed URL in Eventbrite's developer portal under Your Apps → Webhooks. Use Eventbrite's 'Test webhook' functionality in the developer portal to send a test event to your deployed endpoint and verify it arrives correctly.

## Frequently asked questions

### Does Bolt.new work with Eventbrite?

Yes. Eventbrite's REST API integrates with Bolt.new through a standard Next.js API route that authenticates using a private Bearer token. The checkout widget embeds directly in React components and works in the Bolt WebContainer preview. Webhooks require a deployed URL but are straightforward to configure after deployment.

### Can I embed an Eventbrite ticket purchase widget without an API key in Bolt.new?

Yes — Eventbrite's checkout widget requires only the event ID (a numeric string visible in your event's Eventbrite URL). Load the widget script from Eventbrite's CDN and call EBWidgets.createWidget() with your event ID. No API token, no backend code, and no environment variables needed. The widget works in the Bolt WebContainer preview immediately and handles all payment processing through Eventbrite's platform.

### Can I receive Eventbrite webhook notifications in the Bolt.new preview?

No — Eventbrite webhooks require a public HTTPS URL, and Bolt's WebContainer has no public URL during development. Deploy your app to Netlify or Bolt Cloud first, then register the deployed URL (e.g., https://yourapp.netlify.app/api/webhooks/eventbrite) in Eventbrite's developer portal under Your Apps → Webhooks. Use Eventbrite's test webhook button to verify the deployed endpoint.

### How do I list only my upcoming events (not past events) in a Bolt.new app?

Use the time_filter=current_future query parameter in your Eventbrite API request. Combined with status=live, this returns only published events that have not yet started. Events in the past are filtered out automatically. If you want to display past events (e.g., for an event archive), use time_filter=past instead.

### How do I deploy an Eventbrite Bolt.new app to Netlify?

Use Bolt's Netlify integration (Settings → Applications → Connect Netlify) or push to GitHub and connect to Netlify. In Netlify's environment variables settings, add EVENTBRITE_TOKEN, EVENTBRITE_USER_ID, and NEXT_PUBLIC_EVENTBRITE_ORG_ID. Trigger a redeploy. After deployment, register your webhook URL in Eventbrite's developer portal to start receiving event notifications.

### Is Eventbrite free to use for API access in Bolt.new?

Eventbrite's API is free — creating an app and generating an API token costs nothing. Eventbrite charges service fees on paid event tickets (2.5% + $0.99 per order for Flex plan, capped at $19.99) but free events have no Eventbrite fees. The API itself does not have usage charges or rate limit fees for standard integration volumes.

---

Source: https://www.rapidevelopers.com/bolt-ai-integrations/eventbrite
© RapidDev — https://www.rapidevelopers.com/bolt-ai-integrations/eventbrite
