Webhooks

Webhooks

Receive real-time HTTP notifications when events occur on your listings. Configure webhooks from your Dashboard or the public API.

Overview

  • Dashboard and API Management - Create, list, and delete webhooks by API; edit and test from the Dashboard
  • Unlimited endpoints - Create as many webhook endpoints as your integration needs
  • Per-listing binding - Select which webhooks fire for each listing
  • HMAC-SHA256 Signatures - Verify payload authenticity
  • Auto-disable - Deactivated after 5 consecutive failures

Management API

Public API keys can create, list, and delete webhooks. Dashboard-only actions such as testing, editing, toggling active state, and regenerating secrets are managed from the Dashboard. Webhook endpoints are unlimited for every Verified level.

Create Webhook

POST /v1/webhooks
FieldTypeRequiredDescription
namestringNoDisplay name. Defaults to API Webhook.
urlstringYesEndpoint that receives webhook POST requests.
eventsstring[] | nullNoSubscribed event names. Omit or send empty to receive all supported events.
Request
curl -X POST https://api.markidy.com/v1/webhooks \
  -H "Authorization: Bearer mk_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Production Webhook",
    "url": "https://example.com/webhooks/markidy",
    "events": ["match_request.received", "message.new"]
  }'
Response (201)
{
  "id": "wh_abc123",
  "name": "Production Webhook",
  "url": "https://example.com/webhooks/markidy",
  "secret": "a1b2c3...",
  "events": ["match_request.received", "message.new"],
  "active": true,
  "createdAt": "2026-03-18T12:00:00Z",
  "updatedAt": "2026-03-18T12:00:00Z"
}

List Webhooks

GET /v1/webhooks
Response
{
  "webhooks": [
    {
      "id": "wh_abc123",
      "name": "Production Webhook",
      "url": "https://example.com/webhooks/markidy",
      "secret": "a1b2c3...",
      "events": ["match_request.received"],
      "active": true,
      "failCount": 0,
      "createdAt": "2026-03-18T12:00:00Z",
      "updatedAt": "2026-03-18T12:00:00Z"
    }
  ]
}

Delete Webhook

DELETE /v1/webhooks/{id}
Response
{
  "id": "wh_abc123",
  "deleted": true
}

Linking Webhooks to Listings

When creating or editing a listing, pass webhookIds to associate specific webhooks:

POST /v1/listings
{
  "categoryKey": "mentoring",
  "roleKey": "mentor",
  "meta": {
    "headline": "Product mentor for early-stage founders",
    "about-me": "<p>I help teams ship faster with better product decisions.</p>",
    "format": "Remote",
    "rate": "$50-$100 / hour"
  },
  "channels": ["markidy"],
  "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

EventTriggerWho Receives
match_request.receivedNew match request for a listingListing owner
match_request.acceptedOwner accepts the requestListing owner
match_request.rejectedOwner rejects the requestListing owner
message.newNew message sent in conversationRecipient
match_request.* events fire to the webhooks bound to the listing via webhookIds. message.new 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"
  }
}

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

KeyPlatform
xX (Twitter)
linkedinLinkedIn
githubGitHub
instagramInstagram
tiktokTikTok
youtubeYouTube
websitePersonal Website

Request Headers

HeaderDescription
Content-Typeapplication/json
X-Webhook-EventEvent name (e.g., match_request.received)
X-Webhook-SignatureHMAC-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

BehaviorDetail
Timeout10 seconds per request
SuccessHTTP 2xx - failCount resets to 0
FailureNon-2xx or timeout - failCount +1
Auto-disableAfter 5 consecutive failures - active: false
Re-enableManually toggle back on in Dashboard