Handling Webhooks
When your Monitor (Manager) identifies a matching post, it can emit a real-time event directly to your server via an HTTP Webhook Connection.
Webhooks are the recommended way to integrate Advite with your applications, as they remove the need to constantly poll the API for new matches.
Configuring Webhooks
Setting up webhooks involves two steps: creating the Connection (specifying your server URL) and then attaching that connection as a Notice on your Monitor (Manager).
Step 1: Create a Connection
Create an HTTP connection in your Workspace (Namespace) by specifying your destination server URL:
curl -X POST https://api.advite.ai/v1/namespaces/{namespaceId}/connections \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"nickname": "My Webhook Receiver",
"type": "HTTP_CONNECTION",
"url": "https://your-server.com/webhooks/advite",
"method": "POST"
}'
Extract the name property from the JSON response (e.g., namespaces/abc123xyz/connections/conn456). You'll use this connection path in Step 2.
Step 2: Attach to a Monitor (Manager)
Associate the Webhook with your Monitor by listing it in the notices array when creating (or updating) your Monitor (Manager):
curl -X POST https://api.advite.ai/v1/namespaces/{namespaceId}/managers \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"nickname": "My Reddit Monitor",
"type": "FEED_MANAGER",
"enable": true,
"source": {
"type": "REDDIT"
},
"input": {
"type": "STRUCTURED",
"urls": [
"https://mycompany.com"
],
"focus": {
"type": "SALES"
}
},
"notices": [
{
"type": "HTTP_REQUEST",
"connection": "namespaces/abc123xyz/connections/conn456"
}
]
}'
Now, every match identified by this Monitor will automatically trigger a POST request to your webhook URL.
Webhook Payload Schema
Each webhook event sent by Advite is an HTTP POST request containing a JSON payload. The payload structure matches the namespace-feed-notice-request-body OpenAPI schema:
{
"type": "SCAN",
"name": "namespaces/abc123xyz/managers/mgr789/scans/scan999",
"post": {
"type": "REDDIT_LINK",
"time": "2026-06-13T12:10:00Z",
"id": "t3_123456",
"title": "Looking for recommendations for social-monitoring tools",
"text": "My company is growing and we need to monitor brand mentions and potential leads on social media. Are there any good automated platforms out there?",
"url": "https://reddit.com/r/marketing/comments/123456/recs_needed",
"subreddit": {
"id": "t5_2qi1r",
"name": "marketing",
"url": "https://reddit.com/r/marketing"
},
"user": {
"id": "t2_abc123",
"name": "marketing_pro",
"url": "https://reddit.com/user/marketing_pro"
}
}
}
Key Payload Properties
type: The event action type. Currently, this is always"SCAN".name: The full resource path of the matched Scan (e.g.,namespaces/{namespaceId}/managers/{managerId}/scans/{scanId}).post: The full content of the matched social media post. Depending on the platform source, thepost.typewill vary (e.g.,REDDIT_LINK,TWITTER_TWEET,FACEBOOK_POST, etc.) and provide platform-specific fields.
Receiving Webhooks (Examples)
Your server must listen for POST requests and respond with a 2xx HTTP status code (typically 200 OK or 204 No Content) to acknowledge receipt.
Node.js (Express) Example
import express from 'express';
const app = express();
app.use(express.json());
app.post('/webhooks/advite', (req, res) => {
const event = req.body;
// Acknowledge receipt immediately to avoid timeouts.
res.status(200).send('received');
// Offload processing to a background worker / async process.
if (event.type === 'SCAN') {
const scanId = event.name.split('/').pop();
const post = event.post;
console.log(
`processing matched post ${scanId}: "${post.title || post.text.slice(0, 30)}..."`,
);
// Your processing logic here...
}
});
app.listen(3000, () => console.log('server listening on port 3000'));
Python (FastAPI) Example
from fastapi import FastAPI, BackgroundTasks, Response
from pydantic import BaseModel
from typing import Optional
app = FastAPI()
class Subreddit(BaseModel):
id: str
name: str
url: str
class User(BaseModel):
id: str
name: str
url: str
class Post(BaseModel):
type: str
time: str
id: str
url: str
text: str
title: Optional[str] = None
subreddit: Optional[Subreddit] = None
user: User
class WebhookEvent(BaseModel):
type: str
name: str
post: Post
def process_match(event: WebhookEvent):
# Your processing logic here (runs in background).
print(f"processing matched post from: {event.post.url}")
@app.post("/webhooks/advite")
async def receive_webhook(event: WebhookEvent, background_tasks: BackgroundTasks):
# Offload work to background and return 200 immediately.
background_tasks.add_task(process_match, event)
return Response(status_code=200)
Best Practices
To ensure a robust integration, follow these operational best practices:
1. Respond Quickly
Advite expects your server to respond within 10 seconds. If your server takes longer, the request will timeout, and Advite may attempt to retry the event. Always acknowledge the receipt immediately by returning a 2xx response code, and handle any heavy computation, database writes, or notifications asynchronously in a background queue.
2. Configure Custom Verification Headers
When creating your Connection, you can pass custom HTTP headers in the request payload:
{
"type": "HTTP_CONNECTION",
"url": "https://your-server.com/webhooks/advite",
"headers": {
"X-Advite-Webhook-Secret": "your_secure_random_token"
}
}
Verify that this header is present and matches your secret token in every incoming request to guarantee that the payload was sent by Advite and not a third party.
3. Handle Duplicate Events (Idempotency)
While rare, network issues can cause a webhook to be delivered more than once. Use the unique name or post.id field as an idempotency key to deduplicate incoming events on your side.