Skip to main content

Webhooks

Receive real-time notifications when events occur in your workspace.

Overview

Webhooks allow your application to receive HTTP POST callbacks whenever significant events happen — new buyer requests, match completions, trade state transitions, and more. Each delivery is signed with HMAC-SHA256 so you can verify authenticity.

Event Types

buyer_request.createdNew buyer request submitted
buyer_request.matchedBuyer request matched with inventory
buyer_request.archivedBuyer request archived
match.completedMatch engine run completed
offer.createdNew offer sent
offer.acceptedOffer accepted by buyer
offer.rejectedOffer rejected
offer.counteredCounter-offer received
trade.initiatedNew trade created
trade.paidPayment received
trade.shippedTrade marked as shipped
trade.completedTrade completed successfully
trade.cancelledTrade cancelled
hold.createdNew hold placed
hold.expiredHold expired without conversion
hold.deposit_paidHold deposit payment received
inventory.createdNew inventory item added
inventory.updatedInventory item updated
inventory.deletedInventory item removed
live_session.startedLive selling session started
live_session.endedLive session ended
reserve.placedReserve placed on live lot

Registering a Webhook

typescript
const webhook = await ciq.webhooks.create({
  url: 'https://your-app.com/webhooks/collectiq',
  events: ['trade.completed', 'offer.accepted', 'match.completed'],
});

if (webhook.success) {
  // Save this secret securely — it is shown only once
  console.log('Signing secret:', webhook.data.secret);
}
bash
curl -X POST https://collectiqhq.com/api/v1/webhooks \
  -H "Authorization: Bearer ciq_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://your-app.com/webhooks/collectiq",
    "events": ["trade.completed", "offer.accepted"]
  }'

Signature Verification

Every webhook delivery includes a X-CollectIQ-Signature header containing an HMAC-SHA256 signature of the request body using your webhook secret.

typescript
import { createHmac, timingSafeEqual } from 'crypto';

function verifyWebhookSignature(
  body: string,
  signature: string,
  secret: string,
): boolean {
  const expected = createHmac('sha256', secret)
    .update(body)
    .digest('hex');

  const sig = signature.replace('sha256=', '');

  return timingSafeEqual(
    Buffer.from(sig, 'hex'),
    Buffer.from(expected, 'hex'),
  );
}

// In your webhook handler:
app.post('/webhooks/collectiq', (req, res) => {
  const signature = req.headers['x-collectiq-signature'];
  const isValid = verifyWebhookSignature(
    req.rawBody,
    signature,
    process.env.COLLECTIQ_WEBHOOK_SECRET,
  );

  if (!isValid) {
    return res.status(401).json({ error: 'Invalid signature' });
  }

  const event = req.body;
  console.log('Event type:', event.type);
  console.log('Event data:', event.data);

  res.status(200).json({ received: true });
});

⚠ Always verify signatures before processing webhook payloads. Use timingSafeEqual to prevent timing attacks.

Payload Format

json
{
  "id": "evt_a1b2c3d4e5f6",
  "type": "trade.completed",
  "created_at": "2025-01-15T10:30:00Z",
  "workspace_id": "ws_...",
  "data": {
    "trade_id": "trd_...",
    "offer_id": "ofr_...",
    "amount": 299.99,
    "status": "completed"
  }
}

Retry Policy

If your endpoint returns a non-2xx status code or times out (30s), CollectIQ will retry the delivery with exponential backoff:

Attempt 1ImmediateAttempt 2After 1 minuteAttempt 3After 5 minutesAttempt 4After 30 minutesAttempt 5After 2 hoursMax attempts5

Testing Webhooks

Send a test event to verify your endpoint is working:

typescript
// Send a test delivery via SDK
const test = await ciq.webhooks.test('<webhook-id>');

if (test.success) {
  console.log('Status:', test.data.status);
  console.log('Response:', test.data.body);
}

View delivery history in Portal → Webhooks to inspect payloads and response codes.