Observation Webhook
The observation webhook allows you to subscribe to assessment-related events. You can select which specific events to subscribe to, and your system will receive an HTTP request each time one of the selected events occurs.
| Events |
|---|
| assessment.created |
| assessment.completed |
| assessment.destroyed |
Teachstone will POST to https://your-endpoint.com/path
{
"item_type": "assessment",
"item_id": 6252,
"time": "2023-03-07T17:17:37.933Z",
"time_unix": 1678209457,
"event": "assessment.created"
}
Webhook Security
info
Implementing webhook signature verification will ensure the requests are genuinely coming from Teachstone and haven't been tampered with.
How Webhook Signing Works
- Provide a Secret Key: Share a secret key with Teachstone when configuring your webhook endpoint
- Signature Generation: Teachstone signs each webhook payload using HMAC-SHA512 with your secret key
- Signature Header: The signature is sent in the
x-teachstone-signatureheader as a Base64 encoded string - Verification Process:
- Generate your own HMAC-SHA512 digest using the payload + your secret key
- Encode your digest to Base64
- Compare your Base64 string with the received signature
- Do NOT decode the received signature - always encode yours and compare strings
Example Webhook Request Headers
POST /your-webhook-endpoint HTTP/1.1
Host: your-domain.com
Content-Type: application/json
x-teachstone-signature: Kv6/TyL5BCYJKcF/HRoI7qUHZzrCq9J8mBJCF2Lmqik=
Content-Length: 123
Implementation Example (Node.js)
const crypto = require('crypto');
function verifyWebhookSignature(payload, signature, secretKey) {
// Generate your own HMAC-SHA512 digest
const expectedSignature = crypto
.createHmac('sha512', secretKey)
.update(payload, 'utf8')
.digest('base64');
// Compare Base64 strings
return signature === expectedSignature;
}
// Express.js endpoint
app.post('/webhook', (req, res) => {
const signature = req.headers['x-teachstone-signature'];
const payload = JSON.stringify(req.body);
if (!verifyWebhookSignature(payload, signature, process.env.TEACHSTONE_SECRET)) {
return res.status(401).json({ error: 'Invalid signature' });
}
// Process webhook data
const { event, item_id } = req.body;
console.log(`Received ${event} for assessment ${item_id}`);
res.json({ success: true });
});