Developer Docs

API Reference

Complete API documentation for Huddle Pulse. Query events, manage apps, handle RSVPs, and more through our REST API.

Apps Ecosystem
Role-based Participants
Portal Integration
Base URL
https://www.huddlepulse.xyz

No Auth Required

Public GET endpoints are open. No API key needed.

REST JSON API

Standard HTTP verbs, JSON responses throughout.

Write Protection

POST/PATCH/DELETE require valid session authentication.

API Categories

Events

Wave management, RSVPs, and event discovery

Apps

App ecosystem, associations, and app-specific events

Users

Identity resolution, search, and participant management

Portal

Proxy endpoints for Abstract Portal integration

Auth

Session management and user preferences

Admin

Reports, content moderation, and system utilities

Endpoints

GET/api/events

Returns a list of active and upcoming Waves from the last 6 months. Supports filtering, search, and pagination.

Query Parameters
?category=<string>&search=<string>&limit=<number>&offset=<number>&creator=<address>
Example Response
[
  {
    "id": "uuid",
    "title": "string",
    "description": "string",
    "startTime": "ISO 8601",
    "endTime": "ISO 8601 | null",
    "bannerUrl": "string | null",
    "category": "string",
    "repeat": "none | daily | weekly | biweekly | monthly",
    "priority": "number",
    "eventType": "spotlight | standard",
    "isMintedOut": "boolean",
    "creator": { "address": "0x..." },
    "link": "string | null",
    "prize": "string | null",
    "physicalAddress": "string | null",
    "latitude": "number | null",
    "longitude": "number | null",
    "videoUrl": "string | null"
  }
]
GET/api/events/[id]

Returns detailed information for a specific Wave including RSVP status if userAddress is provided.

Query Parameters
?userAddress=<address>
Example Response
{
  "id": "uuid",
  "title": "string",
  "description": "string",
  "startTime": "ISO 8601",
  "endTime": "ISO 8601 | null",
  "bannerUrl": "string | null",
  "category": "string",
  "repeat": "none | daily | weekly | biweekly | monthly",
  "priority": "number",
  "eventType": "spotlight | standard",
  "isMintedOut": "boolean",
  "creator": { "address": "0x..." },
  "link": "string | null",
  "prize": "string | null",
  "physicalAddress": "string | null",
  "latitude": "number | null",
  "longitude": "number | null",
  "videoUrl": "string | null",
  "rsvpd": "boolean | null", // if userAddress provided
  "participantsCount": "number"
}
GET/api/events/mine

Returns the creator's own Waves, including pending (`approved: false`) and hidden (`visible: false`) events. With public session auth it returns the current wallet's events. With API key auth, pass `?creator=<address>`.

Query Parameters
?creator=<address> // required only for API key usage
Example Response
{
  "events": [
    {
      "id": "uuid",
      "title": "string",
      "description": "string | null",
      "startTime": "ISO 8601 | null",
      "endTime": "ISO 8601 | null",
      "bannerUrl": "string | null",
      "galleryUrls": ["string"],
      "category": "string | null",
      "repeat": "none | daily | weekly | biweekly | monthly",
      "priority": "number",
      "eventType": "spotlight | standard",
      "isMintedOut": "boolean",
      "isTba": "boolean",
      "visible": "boolean",
      "approved": "boolean",
      "creator": { "address": "0x..." },
      "link": "string | null",
      "isReferralLink": "boolean",
      "videoUrl": "string | null",
      "physicalAddress": "string | null",
      "latitude": "number | null",
      "longitude": "number | null",
      "zoomLevel": "number | null",
      "createdAt": "ISO 8601"
    }
  ]
}
POST/api/events

Creates a new Wave via API key. If `approved` is omitted, it defaults to `false`. API-created events are not subject to the end-user daily creation limit. When `sourceEventId` is provided for another event by the same creator, the API also copies the banner image, linked apps, and role participants from the source event.

Request Body
{
  "creator_address": "0x...",
  "title": "string",
  "description": "string | null",
  "start_time": "ISO 8601",
  "end_time": "ISO 8601 | null",
  "category": "string | null",
  "repeat": "none | daily | weekly | biweekly | monthly",
  "link": "string | null",
  "banner_url": "string | null",
  "gallery_urls": ["string"],
  "physical_address": "string | null",
  "latitude": "number | null",
  "longitude": "number | null",
  "zoom_level": "number",
  "video_url": "string | null",
  "video_format": "landscape | portrait | square",
  "visible": "boolean",
  "approved": "boolean // defaults to false if omitted",
  "is_referral_link": "boolean",
  "is_minted_out": "boolean",
  "is_tba": "boolean",
  "sourceEventId": "uuid | null // optional duplicate source; copies banner/apps/participants"
}
Example Response
{
  "success": true,
  "eventId": "uuid",
  "approved": "boolean",
  "visible": "boolean",
  "isPending": "boolean",
  "warnings": ["string"]
}
GET/api/events/recurring-candidates

Automation helper endpoint for recurring Waves. Without query params it returns recently ended, approved, visible events whose `repeat` is not `none`, filtered by a repeat-specific age window. With `creator`, `window_start`, and `window_end`, it returns candidate successor events for duplicate detection.

Query Parameters
?limit=<number>&now=<ISO 8601>
or
?creator=<address>&window_start=<ISO 8601>&window_end=<ISO 8601>&exclude_event_id=<uuid>&limit=<number>
Example Response
{
  "mode": "candidates | window",
  "now": "ISO 8601",
  "windows": {
    "daily": 2,
    "weekly": 7,
    "monthly": 31,
    "biweekly": 14
  },
  "events": [
    {
      "id": "uuid",
      "creator_address": "0x...",
      "title": "string",
      "description": "string | null",
      "start_time": "ISO 8601",
      "end_time": "ISO 8601 | null",
      "banner_url": "string | null",
      "category": "string | null",
      "repeat": "daily | weekly | biweekly | monthly",
      "link": "string | null",
      "is_referral_link": "boolean",
      "is_minted_out": "boolean",
      "visible": "boolean",
      "approved": "boolean",
      "physical_address": "string | null",
      "latitude": "number | null",
      "longitude": "number | null",
      "zoom_level": "number | null",
      "video_url": "string | null",
      "video_format": "string | null",
      "is_tba": "boolean",
      "priority": "number",
      "event_type": "spotlight | standard",
      "recurrence_window_days": "number",
      "effective_end_time": "ISO 8601"
    }
  ]
}
PATCH/api/events/[id]

Updates an existing Wave via API key. `creator_address` must match the event creator. This endpoint can also update moderation flags like `approved` and `visible`.

Request Body
{
  "creator_address": "0x...",
  "title": "string | null",
  "description": "string | null",
  "start_time": "ISO 8601 | null",
  "end_time": "ISO 8601 | null",
  "category": "string | null",
  "repeat": "none | daily | weekly | biweekly | monthly | null",
  "link": "string | null",
  "banner_url": "string | null",
  "gallery_urls": ["string"] | null,
  "physical_address": "string | null",
  "latitude": "number | null",
  "longitude": "number | null",
  "zoom_level": "number | null",
  "video_url": "string | null",
  "video_format": "landscape | portrait | square | null",
  "visible": "boolean | null",
  "approved": "boolean | null",
  "is_referral_link": "boolean | null",
  "is_minted_out": "boolean | null",
  "is_tba": "boolean | null"
}
Example Response
{
  "success": true
}
DELETE/api/events/[id]

Deletes a Wave via API key. `creator_address` must match the event creator.

Request Body
{
  "creator_address": "0x..."
}
Example Response
{
  "success": true
}
GET/api/events/light

Lightweight event listing for performance-critical use cases. Returns minimal event data.

Example Response
[
  {
    "id": "uuid",
    "title": "string",
    "startTime": "ISO 8601",
    "endTime": "ISO 8601 | null",
    "category": "string",
    "priority": "number",
    "creator": { "address": "0x..." },
    "bannerUrl": "string | null"
  }
]
GET/api/events/[id]/participants

Returns the participant list for a specific Wave with identity data.

Example Response
[
  {
    "address": "0x...",
    "name": "string | null",
    "avatar": "string | null",
    "verificationType": "portal | verified | regular",
    "identityPreference": "ans | portal | null"
  }
]
GET/api/rsvp

Returns the RSVP list for a given Wave. Pass ?eventId=<uuid> as query param.

Query Parameters
?eventId=<uuid>
Example Response
{
  "count": number,
  "attendees": ["0x...", "0x..."]
}
POST/api/rsvp

RSVP to a Wave. Requires wallet authentication.

Request Body
{
  "eventId": "uuid",
  "action": "rsvp" | "cancel"
}
Example Response
{
  "success": true,
  "message": "string"
}
DELETE/api/rsvp

Cancel RSVP to a Wave. Requires wallet authentication.

Request Body
{
  "eventId": "uuid"
}
Example Response
{
  "success": true,
  "message": "string"
}
GET/api/apps

Search apps by name. Returns up to 5 results sorted by shortest name first.

Query Parameters
?q=<search_query>
Example Response
[
  {
    "id": "number",
    "name": "string",
    "icon": "string | null",
    "category": "string | null",
    "in_portal": "boolean"
  }
]
GET/api/apps/all

Returns all apps with complete information (SELECT *). No query parameters required.

Example Response
[
  {
    "id": "number",
    "name": "string",
    "description": "string | null",
    "icon": "string | null",
    "banner": "string | null",
    "link": "string | null",
    "docs_url": "string | null",
    "spotlight": "daily | weekly | null",
    "launched": "boolean",
    "in_portal": "boolean",
    "category": "string | null",
    "socials": "object",
    "created_at": "ISO 8601",
    "updated_at": "ISO 8601"
  }
]
GET/api/apps/list

Returns apps with pagination and optional in_portal filter. Returns complete information for each app.

Query Parameters
?page=<number>&limit=<number>&in_portal=<boolean>
Example Response
{
  "data": [
    {
      "id": "number",
      "name": "string",
      "description": "string | null",
      "icon": "string | null",
      "banner": "string | null",
      "link": "string | null",
      "docs_url": "string | null",
      "spotlight": "daily | weekly | null",
      "launched": "boolean",
      "in_portal": "boolean",
      "category": "string | null",
      "socials": "object",
      "created_at": "ISO 8601",
      "updated_at": "ISO 8601"
    }
  ],
  "pagination": {
    "page": 1,
    "limit": 50,
    "total": 150,
    "totalPages": 3
  }
}
GET/api/apps/[id]

Get detailed information for a specific app.

Example Response
{
  "id": "number",
  "name": "string",
  "description": "string | null",
  "icon": "string | null",
  "banner": "string | null",
  "link": "string | null",
  "docs_url": "string | null",
  "spotlight": "daily | weekly | null",
  "launched": "boolean",
  "in_portal": "boolean",
  "category": "string | null",
  "socials": "object",
  "created_at": "ISO 8601",
  "updated_at": "ISO 8601"
}
GET/api/apps/[id]/events

Get events associated with a specific app. Can include past events.

Query Parameters
?includePast=<boolean>
Example Response
[
  {
    "id": "uuid",
    "title": "string",
    "description": "string",
    "startTime": "ISO 8601",
    "endTime": "ISO 8601 | null",
    "bannerUrl": "string | null",
    "category": "string",
    "link": "string | null",
    "creator": { "address": "0x..." },
    "isMintedOut": "boolean",
    "approved": "boolean",
    "visible": "boolean"
  }
]
GET/api/events/[id]/apps

Get apps associated with a specific event.

Example Response
[
  {
    "id": "string",
    "event_id": "string",
    "app_id": "number",
    "created_at": "ISO 8601",
    "app": {
      "id": "number",
      "name": "string",
      "icon": "string | null",
      "category": "string | null",
      "in_portal": "boolean"
    }
  }
]
POST/api/events/[id]/apps

Set apps for an event (replaces all existing associations). Requires event creator permissions.

Request Body
{
  "appIds": [number, number, ...]
}
Example Response
{
  "success": true
}
GET/api/events/[id]/participants

Get participants with roles for a specific event.

Example Response
[
  {
    "id": "string",
    "event_id": "string",
    "wallet_address": "string",
    "role": "host | co-host | speaker | panelist | moderator | participant | guest",
    "created_at": "ISO 8601",
    "display_name": "string | null",
    "avatar": "string | null",
    "verified": "boolean",
    "verified_portal": "boolean",
    "identity_preference": "ans | portal | null"
  }
]
POST/api/events/[id]/participants

Set participants with roles for an event (replaces all existing). Requires event creator permissions.

Request Body
{
  "participants": [
    {
      "wallet_address": "string",
      "role": "host | co-host | speaker | panelist | moderator | participant | guest"
    }
  ]
}
Example Response
{
  "success": true
}
POST/api/apps

Create a single app. Requires API key with POST permission on "apps". Only name and description are required.

Request Body
{
  "name": "string",              // Required
  "description": "string",      // Required
  "icon": "string | null",
  "banner": "string | null",
  "link": "string | null",
  "docs_url": "string | null",
  "category": "Skill Based Games | Arcade Games | Trading | Social | Collectibles | Tools | Others | null",
  "launched": "boolean",
  "in_portal": "boolean",
  "spotlight": "daily | weekly | null",
  "socials": { "twitter": "url", "discord": "url" }
}
Example Response
{
  "success": true,
  "app": { "id": 123, "name": "My App" }
}
POST/api/apps/batch

Create multiple apps in a single request (max 50). Each app requires name and description. Returns created apps and any validation errors.

Request Body
{
  "apps": [
    {
      "name": "string",            // Required
      "description": "string",    // Required
      "icon": "string | null",
      "banner": "string | null",
      "link": "string | null",
      "category": "string | null",
      "launched": "boolean",
      "in_portal": "boolean",
      "socials": {}
    }
  ]
}
Example Response
{
  "success": true,
  "created": [{ "id": 123, "name": "App A" }, { "id": 124, "name": "App B" }],
  "errors": [{ "index": 2, "error": ""name" is required" }]
}
PATCH/api/apps/[id]

Update a single app by ID. Only provided fields are updated. Returns 404 if app not found.

Request Body
{
  "name": "string | null",
  "description": "string | null",
  "icon": "string | null",
  "banner": "string | null",
  "link": "string | null",
  "docs_url": "string | null",
  "category": "Skill Based Games | Arcade Games | Trading | Social | Collectibles | Tools | Others | null",
  "launched": "boolean | null",
  "in_portal": "boolean | null",
  "spotlight": "daily | weekly | null",
  "socials": "object | null"
}
Example Response
{
  "success": true,
  "app": {
    "id": 123,
    "name": "Updated App Name",
    "icon": "icon-name",
    "category": "Skill Based Games",
    "in_portal": true,
    "launched": true,
    "banner": "banner-url",
    "link": "https://app.com",
    "docs_url": "https://docs.app.com",
    "socials": {},
    "spotlight": "daily",
    "description": "Updated description"
  }
}
PATCH/api/apps/batch

Update multiple apps in a single request (max 50). Each item must include an "id" field. Returns updated apps and any errors per app.

Request Body
{
  "apps": [
    {
      "id": 123,                     // Required
      "name": "string | null",
      "description": "string | null",
      "icon": "string | null",
      "banner": "string | null",
      "link": "string | null",
      "category": "string | null",
      "launched": "boolean | null",
      "in_portal": "boolean | null",
      "spotlight": "daily | weekly | null",
      "socials": "object | null"
    }
  ]
}
Example Response
{
  "success": true,
  "updated": [
    {
      "id": 123,
      "name": "Updated App 1",
      "icon": "icon-name",
      "category": "Skill Based Games",
      "in_portal": true,
      "launched": true,
      "spotlight": "daily"
    },
    {
      "id": 124,
      "name": "Updated App 2",
      "category": "Social",
      "in_portal": true,
      "spotlight": "weekly"
    }
  ],
  "errors": [
    {
      "id": 125,
      "error": "App not found"
    }
  ]
}
GET/api/users/search

Search users by name or address. Combines local database with Portal API results.

Query Parameters
?q=<search_query>
Example Response
[
  {
    "wallet_address": "string",
    "portal_name": "string | null",
    "portal_avatar": "string | null",
    "ans_name": "string | null",
    "ans_avatar": "string | null",
    "verified": "boolean",
    "verified_portal": "boolean",
    "identity_preference": "ans | portal | null",
    "in_db": "boolean"
  }
]
GET/api/portal/fetch

Proxy endpoint to fetch data from the Abstract Portal API to bypass CORS.

Query Parameters
?url=<encoded_portal_url>
Example Response
{
  "data": "object",
  "cached": "boolean"
}
POST/api/portal/fetch

POST proxy to Abstract Portal API.

Request Body
{
  "url": "string",
  "method": "GET | POST",
  "body": "object | null"
}
Example Response
{
  "data": "object",
  "cached": "boolean"
}
GET/api/session

Check if a valid session exists (reads httpOnly cookie).

Example Response
{
  "valid": "boolean",
  "address": "string | null"
}
POST/api/session

Session operations. Use action parameter.

Query Parameters
?action=nonce | verify
Request Body
{
  "action": "nonce",
  "address": "string"
}
Example Response
{
  "nonce": "string",
  "message": "string"
}
DELETE/api/session

Destroy the current session (logout).

Example Response
{
  "success": "boolean"
}
GET/api/preferences

Get user notification and identity preferences.

Example Response
{
  "email_notifications": "boolean",
  "push_notifications": "boolean",
  "identity_preference": "ans | portal | null"
}
POST/api/preferences

Update user preferences.

Request Body
{
  "email_notifications": "boolean",
  "push_notifications": "boolean",
  "identity_preference": "ans | portal | null"
}
Example Response
{
  "success": true
}
POST/api/reports

Submit a report for inappropriate content.

Request Body
{
  "eventId": "string",
  "message": "string"
}
Example Response
{
  "success": true
}
GET/api/twitter/resolve

Resolve Twitter handle to wallet address via Abstract Name Service.

Query Parameters
?handle=<twitter_handle>
Example Response
{
  "address": "string | null",
  "handle": "string"
}

Data Models

Event Model

{
  id: string,                    // UUID
  title: string,
  description: string,
  startTime: string,             // ISO 8601
  endTime: string | null,        // ISO 8601
  bannerUrl: string | null,
  category: "irl" | "online" | "mint" | "other",
  priority: number,              // For ordering spotlight events
  eventType: "spotlight" | "standard",
  isMintedOut: boolean,
  creator: {
    address: string              // Wallet address
  },
  link: string | null,           // External link
  prize: string | null,          // Prize description
  physicalAddress: string | null,
  latitude: number | null,
  longitude: number | null,
  videoUrl: string | null,
  approved: boolean,             // Admin approval status
  visible: boolean,              // Public visibility
  createdAt: string,             // ISO 8601
  updatedAt: string              // ISO 8601
}

App Model

{
  id: number,
  name: string,
  description: string | null,
  icon: string | null,           // URL to icon image
  banner: string | null,         // URL to banner image
  link: string | null,           // Main app URL
  docs_url: string | null,       // Documentation URL
  spotlight: "daily" | "weekly" | null,
  launched: boolean,
  in_portal: boolean,            // Listed on Abstract Portal
  category: "Skill Based Games" | "Arcade Games" | "Trading" | "Social" | "Collectibles" | "Tools" | "Others" | null,
  socials: object,               // { platform: url, ... }
  created_at: string,            // ISO 8601
  updated_at: string             // ISO 8601
}

Participant Roles

hostEvent organizer/creator
co-hostSecondary organizer
speakerEvent speaker/presenter
panelistPanel discussion member
moderatorQ&A moderator
participantGeneral participant
guestSpecial guest

Need more endpoints or a dedicated integration?

Contact us on X