Skip to main content

Webhooks Overview

Webhooks allow your application to receive real-time notifications when events occur in your Matchr account.
Webhooks push data to your server instantly when events occur, eliminating the need to poll our API.

Available Events

EventDescription
order.createdA new order was submitted
order.filledAn order was completely filled
order.partially_filledAn order was partially filled
order.cancelledAn order was cancelled
position.openedA new position was opened
position.closedA position was closed
position.resolvedA position’s market was resolved
market.matchedA cross-platform market match was found
price.alertA price alert was triggered
deposit.completedFunds were deposited
withdrawal.completedFunds were withdrawn

Setting Up Webhooks

1. Register Your Endpoint

Navigate to Settings → Webhooks or use the API:
curl -X POST "https://api.matchr.xyz/v1/webhooks" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://your-app.com/webhooks/matchr",
    "events": ["order.filled", "position.resolved"],
    "secret": "your_webhook_secret"
  }'

Response

{
  "success": true,
  "data": {
    "id": "whk_abc123",
    "url": "https://your-app.com/webhooks/matchr",
    "events": ["order.filled", "position.resolved"],
    "status": "active",
    "created_at": "2025-10-15T10:00:00Z"
  }
}

Webhook Payload

All webhooks are sent as POST requests with a JSON body.

Headers

HeaderDescription
Content-Typeapplication/json
X-Matchr-SignatureHMAC signature for verification
X-Matchr-TimestampUnix timestamp of the request
X-Matchr-EventEvent type (e.g., order.filled)
X-Matchr-Delivery-IdUnique delivery ID for deduplication

Payload Structure

{
  "id": "evt_delivery_123",
  "type": "order.filled",
  "timestamp": "2025-10-15T14:30:00Z",
  "data": {
    // Event-specific data
  }
}

Event Payloads

order.filled

{
  "id": "evt_delivery_123",
  "type": "order.filled",
  "timestamp": "2025-10-15T14:30:00Z",
  "data": {
    "order_id": "ord_abc123",
    "market_id": "mkt_yes123",
    "platform": "polymarket",
    "side": "buy",
    "type": "limit",
    "amount": 100,
    "price": 0.52,
    "filled_amount": 100,
    "average_fill_price": 0.518,
    "fees": 0.52,
    "position_id": "pos_xyz789"
  }
}

position.resolved

{
  "id": "evt_delivery_456",
  "type": "position.resolved",
  "timestamp": "2025-10-15T16:00:00Z",
  "data": {
    "position_id": "pos_xyz789",
    "market_id": "mkt_yes123",
    "event_title": "Will Trump win the 2025 election?",
    "outcome": "Yes",
    "resolution": "Yes",
    "won": true,
    "size": 500,
    "cost_basis": 260.0,
    "payout": 500.0,
    "realized_pnl": 240.0,
    "redeemable": true
  }
}

market.matched

{
  "id": "evt_delivery_789",
  "type": "market.matched",
  "timestamp": "2025-10-15T12:00:00Z",
  "data": {
    "match_id": "match_abc123",
    "confidence": 0.95,
    "platforms": {
      "polymarket": {
        "event_id": "evt_poly123",
        "title": "Will BTC hit $100K by end of 2025?",
        "yes_price": 0.35
      },
      "kalshi": {
        "event_id": "evt_kalshi456",
        "title": "Bitcoin price $100,000 or above on December 31",
        "yes_price": 0.38
      }
    },
    "spread": 0.03,
    "spread_pct": 8.57
  }
}

price.alert

{
  "id": "evt_delivery_101",
  "type": "price.alert",
  "timestamp": "2025-10-15T14:45:00Z",
  "data": {
    "alert_id": "alert_123",
    "market_id": "mkt_yes123",
    "event_title": "Will Trump win the 2025 election?",
    "condition": "price_above",
    "threshold": 0.55,
    "current_price": 0.56,
    "platform": "polymarket"
  }
}

Signature Verification

Always verify webhook signatures to ensure requests are from Matchr.

How Signatures Work

  1. Matchr creates a signature using your webhook secret
  2. The signature is included in the X-Matchr-Signature header
  3. You recreate the signature and compare

Verification Code

import crypto from 'crypto';

function verifyWebhook(
payload: string,
signature: string,
timestamp: string,
secret: string
): boolean {
const signedPayload = `${timestamp}.${payload}`;
const expectedSignature = crypto
.createHmac('sha256', secret)
.update(signedPayload)
.digest('hex');

return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(`sha256=${expectedSignature}`)
);
}

// Express middleware
app.post('/webhooks/matchr', (req, res) => {
const signature = req.headers['x-matchr-signature'];
const timestamp = req.headers['x-matchr-timestamp'];
const payload = JSON.stringify(req.body);

if (!verifyWebhook(payload, signature, timestamp, WEBHOOK_SECRET)) {
return res.status(401).send('Invalid signature');
}

// Process webhook
const event = req.body;
console.log('Received event:', event.type);

res.status(200).send('OK');
});


Retry Policy

If your endpoint fails to respond with a 2xx status code, we’ll retry:
AttemptDelay
1Immediate
21 minute
35 minutes
430 minutes
52 hours
612 hours
After 6 failed attempts, the webhook is marked as failed and disabled.

Handling Failures

Always return a 200 OK response quickly, even if processing takes time. Process webhooks asynchronously.
app.post("/webhooks/matchr", async (req, res) => {
  // Verify signature first
  if (!verifySignature(req)) {
    return res.status(401).send("Invalid");
  }

  // Respond immediately
  res.status(200).send("OK");

  // Process asynchronously
  processWebhookAsync(req.body);
});

Managing Webhooks

List Webhooks

curl -X GET "https://api.matchr.xyz/v1/webhooks" \
  -H "Authorization: Bearer YOUR_API_KEY"

Update Webhook

curl -X PATCH "https://api.matchr.xyz/v1/webhooks/whk_abc123" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "events": ["order.filled", "order.cancelled", "position.resolved"]
  }'

Delete Webhook

curl -X DELETE "https://api.matchr.xyz/v1/webhooks/whk_abc123" \
  -H "Authorization: Bearer YOUR_API_KEY"

Test Webhook

Send a test event to verify your endpoint:
curl -X POST "https://api.matchr.xyz/v1/webhooks/whk_abc123/test" \
  -H "Authorization: Bearer YOUR_API_KEY"

Webhook Logs

View recent webhook deliveries:
curl -X GET "https://api.matchr.xyz/v1/webhooks/whk_abc123/deliveries?limit=20" \
  -H "Authorization: Bearer YOUR_API_KEY"

Response

{
  "success": true,
  "data": [
    {
      "id": "del_123",
      "event_type": "order.filled",
      "status": "success",
      "response_code": 200,
      "response_time_ms": 145,
      "timestamp": "2025-10-15T14:30:00Z"
    },
    {
      "id": "del_122",
      "event_type": "position.resolved",
      "status": "failed",
      "response_code": 500,
      "error": "Connection timeout",
      "retry_count": 2,
      "timestamp": "2025-10-15T14:25:00Z"
    }
  ]
}

Best Practices

Respond Quickly

Return 200 within 5 seconds. Process data asynchronously.

Verify Signatures

Always verify the X-Matchr-Signature header.

Handle Duplicates

Use X-Matchr-Delivery-Id for idempotency.

Use HTTPS

Only HTTPS endpoints are supported.