Documentation Index
Fetch the complete documentation index at: https://docs.posthook.io/llms.txt
Use this file to discover all available pages before exploring further.
When events fire in rapid succession, such as a user saving a document repeatedly, you often only want to perform a reaction (like syncing to an external API) once the activity stops.
Instead of cancelling previous hooks (which requires tracking IDs), you can use a Stale Check pattern.
Workflow
- Schedule: On every event, schedule a hook for
X minutes in the future. Pass the current timestamp.
- Verify: When the hook fires, compare the passed timestamp with the resource’s current
updatedAt.
- Discard: If the resource is newer than the event, it means a subsequent event occurred. Discard this hook.
Example: Sync to Salesforce
Sync a user profile to Salesforce 5 minutes after their last edit.
import Posthook from '@posthook/node';
import { Signatures, SignatureVerificationError } from '@posthook/node';
const posthook = new Posthook(process.env.POSTHOOK_API_KEY);
const signatures = new Signatures(process.env.POSTHOOK_SIGNING_KEY);
/* 1. Schedule */
async function onUserProfileUpdate(user) {
// Always schedule the sync for 5 minutes later
// Pass the creation time of THIS specific event
await posthook.hooks.schedule({
path: '/webhooks/sync/salesforce',
postIn: '5m',
data: {
userId: user.id,
triggeredAt: new Date().toISOString()
}
});
}
/* 2. Handle */
app.post('/webhooks/sync/salesforce', async (req, res) => {
try {
const delivery = signatures.parseDelivery(req.body, req.headers);
const { userId, triggeredAt } = delivery.data;
const user = await db.getUser(userId);
// STALE CHECK:
// If the user record has been updated SINCE this hook was scheduled,
// then a newer hook exists in the queue. We can safely skip this one.
if (new Date(user.updatedAt) > new Date(triggeredAt)) {
return res.status(200).send('Stale request, skipping');
}
// If timestamps match (or are very close), this is the latest action.
await salesforce.sync(user);
res.status(200).send('Synced');
} catch (err) {
if (err instanceof SignatureVerificationError) {
return res.status(401).json({ error: err.message });
}
throw err;
}
});
This ensures that if a user updates their profile 10 times in one minute, only the last hook will actually trigger the sync. The previous 9 will detect they are “stale” and exit immediately.