Skip to content

Webhook Sink

The webhook sink POSTs session data as JSON to any URL. It’s the most universal sink — works with any backend that accepts HTTP requests.

import { WriteTrack, webhook } from 'writetrack';
const tracker = new WriteTrack({ target: textarea });
tracker.pipe(
webhook({
url: 'https://api.example.com/writetrack',
})
);
tracker.start();

When getData() is called, the sink sends a POST request with Content-Type: application/json and the full WriteTrackDataSchema as the body.

OptionTypeDefaultDescription
urlstringURL to POST session data to Required
headersRecord<string, string>{}Additional headers to include
retriesnumber0Number of retries on failure
keepalivebooleanfalseUse fetch keepalive so delivery completes after page close (64 KB body limit)
tracker.pipe(
webhook({
url: 'https://api.example.com/writetrack',
headers: {
Authorization: 'Bearer sk_live_...',
},
})
);
tracker.pipe(
webhook({
url: 'https://api.example.com/writetrack',
retries: 2, // up to 3 total attempts
})
);

Retries fire immediately on non-2xx responses. The sink throws after all attempts are exhausted.

The webhook delivers the full WriteTrackDataSchema object. Here’s a minimal Express handler:

app.post('/writetrack', (req, res) => {
const data = req.body;
console.log('Session from:', data.metadata.userId);
console.log('Quality:', data.quality.qualityLevel);
console.log('Duration:', data.metadata.duration, 'ms');
console.log('Keystrokes:', data.session.events.length);
// Store or process the session data
db.sessions.insert(data);
res.sendStatus(200);
});
tracker.on('pipe:error', (err, sink) => {
console.error('Webhook delivery failed:', err.message);
// e.g. "Webhook failed: 500 Internal Server Error"
});

The webhook sends:

  • Method: POST
  • Content-Type: application/json
  • Body: The complete WriteTrackDataSchema object (see Data Schema)

A non-2xx response is treated as a failure and triggers retries (if configured) or a pipe:error event.