Webhooks
Webhooks let you connect SimpleCommenter with any external service. Send data out when events happen, or receive updates back to sync changes from other systems.
Two Types of Webhooks
SimpleCommenter supports two webhook directions:
- Name
Outbound- Type
- Sends data out
- Description
When events happen in SimpleCommenter (new comment, reply, status change), we send data to your URL.
- Name
Inbound- Type
- Receives data
- Description
External systems can call our API to update comments in SimpleCommenter (add replies, change status/priority).
Outbound Webhooks
Send data to your servers when events occur in SimpleCommenter.
Setup
- Go to Project Settings > Integrations
- Click Webhook
- Click New Webhook
- Configure your webhook:
- Name - A friendly identifier
- Trigger Event - When to fire the webhook
- URL - Your endpoint
- Authentication - Optional auth for your endpoint
- Enable the webhook with the toggle
- Click Save
Trigger Events
You can create separate webhooks for each event type:
- Name
New Comment- Type
- comment
- Description
Fires when a visitor submits new feedback.
- Name
Reply- Type
- reply
- Description
Fires when someone replies to a comment.
- Name
Status/Priority Update- Type
- status_update
- Description
Fires when a comment's status or priority changes.
Endpoint Requirements
Your webhook endpoint must:
- Accept
POSTorPUTrequests (configurable) - Accept
application/jsoncontent type - Return a
2xxstatus code - Be publicly accessible (no localhost in production)
Payload Reference
All outbound webhooks send JSON. The type field tells you which event triggered the webhook.
New Comment Payload
{
"type": "comment",
"commentId": "507f1f77bcf86cd799439011",
"commentNumber": 42,
"projectId": "my-site",
"projectName": "My Site",
"publicKey": "sc_abc123",
"title": "Bug Report",
"text": "The checkout button doesn't work on mobile",
"status": "todo",
"priority": "normal",
"date": "2024-01-15T10:30:00.000Z",
"by": "John Doe",
"userData": { "name": "John Doe", "email": "john@example.com" },
"domain": "https://example.com",
"slug": "/checkout",
"link": "https://example.com#simple-comment=507f1f77bcf86cd799439011",
"metadata": {
"browser": "Chrome 120",
"os": "iOS 17"
},
"mentions": [],
"attachedUsers": [],
"attachments": [
{
"type": "image",
"url": "https://s3.amazonaws.com/...",
"name": "Screenshot"
},
{
"type": "file",
"url": "https://s3.amazonaws.com/...",
"name": "error-log.txt"
}
]
}
- Name
type- Type
- string
- Description
Always
"comment"for new comments.
- Name
commentId- Type
- string
- Description
Unique identifier for the comment.
- Name
commentNumber- Type
- number
- Description
Human-readable comment number (e.g., #42).
- Name
projectId- Type
- string | null
- Description
Your friendly project ID, if set.
- Name
projectName- Type
- string | null
- Description
The project's display name.
- Name
publicKey- Type
- string | null
- Description
The project's public key (
sc_...).
- Name
title- Type
- string | null
- Description
Comment title if provided.
- Name
text- Type
- string
- Description
The feedback message content.
- Name
status- Type
- string
- Description
Current status:
todo,in_progress,review,rework,on_hold,blocked,done,cancelled,wont_fix.
- Name
priority- Type
- string
- Description
Priority level:
low,normal,high,urgent.
- Name
date- Type
- string
- Description
ISO 8601 timestamp when submitted.
- Name
by- Type
- string
- Description
Name or email of person who submitted.
- Name
userData- Type
- object | null
- Description
The submitter's details (name, email) when available.
- Name
domain- Type
- string
- Description
The website domain.
- Name
slug- Type
- string
- Description
Page path where feedback was submitted.
- Name
link- Type
- string
- Description
Direct link to view the comment.
- Name
metadata- Type
- object
- Description
Additional context (browser, OS, custom fields).
- Name
mentions- Type
- array
- Description
Users mentioned in the comment text.
- Name
attachedUsers- Type
- array
- Description
Users tagged on the comment (notified about it).
- Name
attachments- Type
- array
- Description
Screenshots and uploaded files with presigned URLs.
Reply Payload
{
"type": "reply",
"commentId": "507f1f77bcf86cd799439011",
"commentNumber": 42,
"replyText": "Thanks for reporting! We're looking into this.",
"date": "2024-01-15T11:00:00.000Z",
"by": "Support Team",
"domain": "https://example.com",
"slug": "/checkout",
"link": "https://example.com#simple-comment=507f1f77bcf86cd799439011",
"metadata": {},
"attachments": []
}
- Name
type- Type
- string
- Description
Always
"reply"for replies.
- Name
replyText- Type
- string
- Description
The reply message content.
- Name
by- Type
- string
- Description
Name of the person who replied.
Status Update Payload
{
"type": "status_update",
"commentId": "507f1f77bcf86cd799439011",
"commentNumber": 42,
"status": "in_progress",
"priority": "high",
"previousStatus": "todo",
"previousPriority": "normal",
"updatedFields": ["status", "priority"],
"date": "2024-01-15T11:30:00.000Z",
"by": "Jane Smith",
"domain": "https://example.com",
"slug": "/checkout",
"link": "https://example.com#simple-comment=507f1f77bcf86cd799439011"
}
- Name
type- Type
- string
- Description
Always
"status_update"for status/priority changes.
- Name
status- Type
- string
- Description
New status value.
- Name
priority- Type
- string
- Description
New priority value.
- Name
previousStatus- Type
- string
- Description
Status before the change.
- Name
previousPriority- Type
- string
- Description
Priority before the change.
- Name
updatedFields- Type
- array
- Description
Which fields changed:
["status"],["priority"], or["status", "priority"].
Authentication
Outbound Authentication
Protect your endpoint by requiring authentication. SimpleCommenter supports:
- Name
None- Type
- No auth
- Description
No authentication header sent.
- Name
Bearer Token- Type
- Authorization header
- Description
Sends
Authorization: Bearer your-token. For endpoints that strip theAuthorizationheader, the same token is also sent asX-Webhook-Token.
- Name
Basic Auth- Type
- Authorization header
- Description
Sends
Authorization: Basic base64(username:password). The same value is also sent asX-Webhook-Auth.
Inbound Webhooks (Two-Way Sync)
Allow external systems to update SimpleCommenter by calling our API.
Generate an Integration Token
- Go to Project Settings > Integrations > Webhook
- In the Inbound Actions section, select which actions to allow:
- Reply to comments - Add replies from external systems
- Update status/priority - Change comment status or priority
- Delete comments - Archive comments from external systems
- Click Generate Token
- Copy the token immediately (it won't be shown again)
Store your integration token securely. Anyone with this token can perform the allowed actions on your comments.
API Endpoint
POST https://www.simplecommenter.com/api/integrations/action
Request Format
{
"token": "your-integration-token",
"action": "reply",
"payload": {
"commentId": "507f1f77bcf86cd799439011",
"text": "This has been fixed in version 2.1",
"name": "Bot",
"email": "bot@example.com"
}
}
If your token is scoped to a single project, the domain is inferred
automatically. If it is an account-level token (not tied to one project), you
must also include a domain field in the payload (the project's website
URL), or the request returns 400 Domain is required for user-level tokens.
Available Actions
Reply Action
Add a reply to a comment from an external system.
{
"token": "your-integration-token",
"action": "reply",
"payload": {
"commentId": "507f1f77bcf86cd799439011",
"text": "Thanks for your feedback!",
"name": "Support Bot",
"email": "support@example.com"
}
}
- Name
commentId- Type
- string
- required
- Description
The ID of the comment to reply to.
- Name
text- Type
- string
- required
- Description
The reply message.
- Name
name- Type
- string
- Description
Display name for the reply author.
- Name
email- Type
- string
- Description
Email for the reply author.
Status Update Action
Change a comment's status or priority.
{
"token": "your-integration-token",
"action": "status_update",
"payload": {
"commentId": "507f1f77bcf86cd799439011",
"status": "done",
"priority": "high"
}
}
- Name
commentId- Type
- string
- required
- Description
The ID of the comment to update.
- Name
status- Type
- string
- Description
New status. Must be one of:
todo,in_progress,review,rework,on_hold,blocked,done,cancelled,wont_fix.
- Name
priority- Type
- string
- Description
New priority. Must be one of:
low,normal,high,urgent.
At least one of status or priority is required for status_update action.
Delete Action
Archive a comment from an external system. Comments are soft-deleted (archived), not permanently removed.
{
"token": "your-integration-token",
"action": "delete",
"payload": {
"commentId": "507f1f77bcf86cd799439011"
}
}
- Name
commentId- Type
- string
- required
- Description
The ID of the comment to archive.
The delete action must be allowed by your integration token's scope, the
same way reply and status_update are.
Response Format
Success Response
{
"success": true,
"message": "Integration action completed successfully",
"result": {
"_id": "507f1f77bcf86cd799439011",
"oldStatus": "todo",
"newStatus": "done"
}
}
Error Responses
Invalid Token (403)
{
"error": "Invalid token"
}
Action Not Allowed (403)
{
"error": "Action not allowed"
}
Comment Not Found (500)
{
"error": "Comment with ID xyz not found"
}
Invalid Status (500)
{
"error": "Invalid status: invalid. Must be one of: todo, in_progress, ..."
}
Example: Node.js Webhook Handler
const express = require("express");
const app = express();
app.use(express.json());
app.post("/webhook", (req, res) => {
const { type, commentId, commentNumber } = req.body;
switch (type) {
case "comment":
console.log(`New comment #${commentNumber}: ${req.body.text}`);
// Create ticket in your system, send to Slack, etc.
break;
case "reply":
console.log(`Reply to #${commentNumber}: ${req.body.replyText}`);
break;
case "status_update":
console.log(
`#${commentNumber} status: ${req.body.previousStatus} → ${req.body.status}`,
);
break;
}
res.status(200).json({ received: true });
});
app.listen(3000);
Example: Calling Inbound API
const response = await fetch(
"https://simplecommenter.com/api/integrations/action",
{
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
token: process.env.SIMPLECOMMENTER_TOKEN,
action: "status_update",
payload: {
commentId: "507f1f77bcf86cd799439011",
status: "done",
},
}),
},
);
const result = await response.json();
console.log(result.success ? "Updated!" : result.error);
Use Cases
Sync with Project Management Tools
When a new comment comes in, create a task in your project management tool. When the task is completed there, call the inbound API to update the status in SimpleCommenter.
Custom Notifications
Send new comments to Discord, Slack, or email using your own formatting and routing logic.
Analytics & Reporting
Forward all webhook events to your data warehouse to build custom dashboards and reports.
Automated Responses
Use the inbound API to automatically reply to comments that match certain criteria (e.g., auto-acknowledge bug reports).
Next Steps
- Trello Integration - Push feedback, replies, and status updates into Trello
- Slack Integration - Real-time team notifications