Skip to main content
Skip to main content
Guide

Webhooks

Receive real-time notifications when tasks complete instead of polling. Set up webhook endpoints to get instant results delivered to your server.

Setting Up Webhooks

Configure a webhook URL in your dashboard under Settings > Webhooks. Your endpoint must accept POST requests and return a 2xx status code.

  1. Go to Dashboard > Settings > Webhooks
  2. Enter your endpoint URL (must use HTTPS)
  3. Select which events to receive
  4. Copy the signing secret for verification
  5. Save and send a test event to verify
Example endpoint (Express.js)
app.post('/webhooks/capsolution', express.json(), (req, res) => {
  const event = req.body;
  console.log('Received event:', event.event);

  switch (event.event) {
    case 'task.completed':
      console.log('Task solved:', event.taskId);
      console.log('Token:', event.solution.token);
      break;
    case 'task.failed':
      console.log('Task failed:', event.taskId);
      break;
    case 'balance.low':
      console.log('Low balance:', event.balance);
      break;
  }

  // Always return 200 to acknowledge receipt
  res.status(200).json({ received: true });
});

Signature Verification

All webhook deliveries include an HMAC-SHA256 signature in the X-Webhook-Signature header. Always verify this signature to ensure the request came from CapSolution.

Security Warning
Never process webhook events without verifying the signature. An attacker could send forged events to your endpoint.
const crypto = require('crypto');

function verifyWebhookSignature(payload, signature, secret) {
  const expectedSignature = crypto
    .createHmac('sha256', secret)
    .update(JSON.stringify(payload))
    .digest('hex');

  return crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(expectedSignature)
  );
}

// In your webhook handler:
app.post('/webhooks/capsolution', express.json(), (req, res) => {
  const signature = req.headers['x-webhook-signature'];
  const secret = process.env.WEBHOOK_SECRET;

  if (!verifyWebhookSignature(req.body, signature, secret)) {
    return res.status(401).json({ error: 'Invalid signature' });
  }

  // Process the verified event...
  res.status(200).json({ received: true });
});

Event Types

task.completed

Fired when a solve task completes successfully.

Payload
{
  "event": "task.completed",
  "taskId": "task_abc123",
  "status": "ready",
  "solution": {
    "token": "0.mF7gg2...",
    "userAgent": "Mozilla/5.0..."
  },
  "timestamp": "2026-03-28T12:00:00Z"
}
task.failed

Fired when a solve task fails after all retries.

Payload
{
  "event": "task.failed",
  "taskId": "task_abc123",
  "status": "failed",
  "errorId": 10,
  "errorCode": "ERROR_CAPTCHA_UNSOLVABLE",
  "timestamp": "2026-03-28T12:00:00Z"
}
balance.low

Fired when account credits drop below the configured threshold.

Payload
{
  "event": "balance.low",
  "balance": 45.5,
  "threshold": 50,
  "timestamp": "2026-03-28T12:00:00Z"
}

Retry Behavior

If your webhook endpoint returns a non-2xx status code or times out, CapSolution will retry delivery with exponential backoff.

AttemptDelayTimeout
1st retry30 seconds10s
2nd retry2 minutes10s
3rd retry10 minutes10s
4th retry1 hour10s
5th retry (final)4 hours10s
After 5 failed delivery attempts, the event is marked as failed and your webhook will be disabled. You can re-enable it from the dashboard.