Webhooks
Webhooks
Receive real-time HTTP notifications when events occur on your listings. Configure webhooks from your Dashboard.
Overview
- Dashboard Management — Create, edit, delete, and test webhooks
- Per-listing binding — Select which webhooks fire for each listing
- HMAC-SHA256 Signatures — Verify payload authenticity
- Auto-disable — Deactivated after 5 consecutive failures
Linking Webhooks to Listings
When creating or editing a listing, pass webhookIds to associate
specific webhooks:
POST /v1/listings
{
"categoryKey": "ai-agent",
"roleKey": "developer",
"meta": { "experience": "5" },
"channels": ["telegram"],
"webhookIds": ["wh_abc123", "wh_def456"]
}If webhookIds is omitted or empty, no webhooks will
fire for that listing. Update bindings anytime via PATCH /v1/listings/{id}.
Events
| Event | Trigger | Who Receives |
|---|---|---|
match_request.received | New match request for a listing | Listing owner |
match_request.accepted | Owner accepts the request | Listing owner |
match_request.rejected | Owner rejects the request | Listing owner |
conversation.created | Match accepted, conversation created | Both users |
message.new | New message sent in conversation | Recipient |
match_request.* events fire to the webhooks bound
to the listing via webhookIds. conversation.* and message.* events fire to all active webhooks for
the user.Payload Format
Webhook Payload
{
"event": "match_request.received",
"timestamp": "2026-03-18T12:00:00Z",
"test": false,
"data": {
"requestId": "mr_...",
"status": "PENDING",
"listingId": "clx...",
"listingTitle": "AI Agent Developer...",
"requesterId": "usr_...",
"profile": {
"displayName": "Alice",
"verifiedLevel": 1,
"country": "us",
"socialLinks": {
"github": "https://github.com/alice",
"x": "https://x.com/alice"
}
},
"channels": ["telegram", "discord"],
"message": "I'm interested in your service.",
"createdAt": "2026-03-18T12:00:00Z"
}
}match_request.accepted
Accepted Payload
{
"event": "match_request.accepted",
"timestamp": "2026-03-18T14:30:00Z",
"test": false,
"data": {
"requestId": "mr_...",
"status": "ACCEPTED",
"listingId": "clx...",
"listingTitle": "AI Agent Developer...",
"requesterId": "usr_...",
"respondedAt": "2026-03-18T14:30:00Z"
}
}match_request.rejected
Rejected Payload
{
"event": "match_request.rejected",
"timestamp": "2026-03-18T14:30:00Z",
"test": false,
"data": {
"requestId": "mr_...",
"status": "REJECTED",
"listingId": "clx...",
"listingTitle": "AI Agent Developer...",
"requesterId": "usr_...",
"reason": "Not a good fit at this time.",
"respondedAt": "2026-03-18T14:30:00Z"
}
}conversation.created
Conversation Created Payload
{
"event": "conversation.created",
"timestamp": "2026-03-25T12:00:00Z",
"data": {
"conversationId": "conv_...",
"listingId": "clx...",
"listingTitle": "AI Agent Developer...",
"requesterId": "usr_...",
"ownerId": "usr_...",
"requesterName": "Alex Kim",
"ownerName": "Jordan Lee",
"createdAt": "2026-03-25T12:00:00Z"
}
}message.new
New Message Payload
{
"event": "message.new",
"timestamp": "2026-03-25T12:01:00Z",
"data": {
"conversationId": "conv_...",
"messageId": "msg_...",
"senderId": "usr_...",
"senderName": "Alex Kim",
"content": "Hello, I'm interested in your service.",
"isApiSent": false,
"createdAt": "2026-03-25T12:01:00Z"
}
}Social Link Keys
| Key | Platform |
|---|---|
x | X (Twitter) |
linkedin | |
github | GitHub |
instagram | |
youtube | YouTube |
website | Personal Website |
Request Headers
| Header | Description |
|---|---|
Content-Type | application/json |
X-Webhook-Event | Event name (e.g., match_request.received) |
X-Webhook-Signature | HMAC-SHA256 signature of the body |
Signature Verification
Verify the X-Webhook-Signature header to ensure the request
is authentic:
Node.js
const crypto = require('crypto');
function verifySignature(secret, body, signature) {
const expected = crypto
.createHmac('sha256', secret)
.update(JSON.stringify(body))
.digest('hex');
return expected === signature;
}
app.post('/webhook', (req, res) => {
const sig = req.headers['x-webhook-signature'];
if (!verifySignature(MY_SECRET, req.body, sig)) {
return res.status(401).send('Invalid signature');
}
// Process event...
res.status(200).send('OK');
});Retry & Failure Policy
| Behavior | Detail |
|---|---|
| Timeout | 10 seconds per request |
| Success | HTTP 2xx → failCount resets to 0 |
| Failure | Non-2xx or timeout → failCount +1 |
| Auto-disable | After 5 consecutive failures → active: false |
| Re-enable | Manually toggle back on in Dashboard |