Skills Development Perplexity Webhook Events

Perplexity Webhook Events

v20260311
perplexity-webhooks-events
Provides guidance for validating Perplexity webhook signatures and handling event-driven search pipelines, covering streaming SSE responses, batch research callbacks, and news monitoring hooks for secure automation.
Get Skill
102 downloads
Overview

Perplexity Events & Async Patterns

Overview

Build event-driven architectures around Perplexity's AI search API. Perplexity provides a chat completions API at api.perplexity.ai with real-time web search capabilities.

Prerequisites

  • Perplexity API key stored in PERPLEXITY_API_KEY environment variable
  • Understanding of Perplexity models (sonar, sonar-pro, sonar-reasoning)
  • Queue system for batch search processing
  • Familiarity with OpenAI-compatible API format

Event Patterns

Pattern Trigger Use Case
Streaming SSE Client search request Real-time search answers
Batch research callback Queue job completes Research automation pipeline
Scheduled search monitor Cron trigger News monitoring, trend alerts
Citation extraction Post-processing Source verification workflow

Instructions

Step 1: Streaming Search Responses

app.post("/api/search/stream", async (req, res) => {
  const { query, model } = req.body;

  res.writeHead(200, {  # HTTP 200 OK
    "Content-Type": "text/event-stream",
    "Cache-Control": "no-cache",
  });

  const response = await fetch("https://api.perplexity.ai/chat/completions", {
    method: "POST",
    headers: {
      "Authorization": `Bearer ${process.env.PERPLEXITY_API_KEY}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      model: model || "sonar",
      messages: [{ role: "user", content: query }],
      stream: true,
      return_citations: true,
    }),
  });

  const reader = response.body!.getReader();
  const decoder = new TextDecoder();

  while (true) {
    const { done, value } = await reader.read();
    if (done) break;

    const chunk = decoder.decode(value);
    res.write(chunk);
  }

  res.end();
});

Step 2: Batch Research Pipeline

import { Queue, Worker } from "bullmq";

const searchQueue = new Queue("perplexity-research");

async function queueResearch(queries: string[], callbackUrl: string) {
  const batchId = crypto.randomUUID();

  for (const query of queries) {
    await searchQueue.add("search", {
      batchId,
      query,
      callbackUrl,
    });
  }

  return batchId;
}

const worker = new Worker("perplexity-research", async (job) => {
  const { query, callbackUrl, batchId } = job.data;

  const response = await fetch("https://api.perplexity.ai/chat/completions", {
    method: "POST",
    headers: {
      "Authorization": `Bearer ${process.env.PERPLEXITY_API_KEY}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      model: "sonar-pro",
      messages: [{ role: "user", content: query }],
      return_citations: true,
    }),
  });

  const result = await response.json();
  const answer = result.choices[0].message.content;
  const citations = result.citations || [];

  await fetch(callbackUrl, {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({
      event: "perplexity.search.completed",
      batchId,
      query,
      answer,
      citations,
      model: result.model,
    }),
  });
});

Step 3: News Monitoring Service

async function monitorTopic(topic: string, webhookUrl: string) {
  const response = await fetch("https://api.perplexity.ai/chat/completions", {
    method: "POST",
    headers: {
      "Authorization": `Bearer ${process.env.PERPLEXITY_API_KEY}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      model: "sonar",
      messages: [{
        role: "user",
        content: `What are the latest developments about ${topic} in the past 24 hours? Include specific sources.`,
      }],
      return_citations: true,
      search_recency_filter: "day",
    }),
  });

  const result = await response.json();

  if (result.choices[0].message.content.length > 100) {
    await fetch(webhookUrl, {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({
        event: "perplexity.monitor.update",
        topic,
        summary: result.choices[0].message.content,
        citations: result.citations,
      }),
    });
  }
}

Error Handling

Issue Cause Solution
Rate limited (429) Too many requests Add delays between requests, use queue
Empty citations Query too abstract Make queries more specific and factual
Stale results No recency filter Use search_recency_filter parameter
Model unavailable Capacity limit Fall back to smaller model variant

Examples

Quick Search with Citations

set -euo pipefail
curl -X POST https://api.perplexity.ai/chat/completions \
  -H "Authorization: Bearer $PERPLEXITY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"model": "sonar", "messages": [{"role": "user", "content": "Latest AI developments"}], "return_citations": true}'

Resources

Next Steps

For deployment setup, see perplexity-deploy-integration.

Output

  • Configuration files or code changes applied to the project
  • Validation report confirming correct implementation
  • Summary of changes made and their rationale
Info
Category Development
Name perplexity-webhooks-events
Version v20260311
Size 5.78KB
Updated At 2026-03-12
Language