Skip to main content

Webhooks

Webhooks let you subscribe to events from your LLMTune workspace for automation and monitoring. Receive real-time notifications when training jobs complete, deployments change, or usage thresholds are reached.

Supported Events

EventTrigger
training.startedA fine-tuning job enters the running state
training.completedA job finishes successfully
training.failedA job fails or is cancelled
model.deployedA model is promoted to an endpoint

Register a Webhook

  1. Navigate to Webhooks in the dashboard.
  2. Click Create Webhook.
  3. Provide:
    • Target URL (HTTPS recommended)
    • Events to subscribe to (select one or more)
  4. Save. A secret is generated automatically (e.g. whsec_...). Use it to verify the X-Webhook-Signature header.
  5. Test using the Send test event action in the dashboard.

Payload Format

LLMTune sends POST requests to your webhook URL with these headers:
  • Content-Type: application/json
  • X-Webhook-Signature – HMAC-SHA256 of the raw JSON body using your webhook secret (hex-encoded)
  • X-Webhook-Event – Event name (e.g. training.completed)
Payload structure:
{
  "event": "training.completed",
  "data": {
    "jobId": "job-uuid",
    "modelName": "meta-llama/Llama-3.3-70B-Instruct"
  },
  "timestamp": "2025-11-08T14:22:31.000Z"
}
The data object may include additional fields depending on the event (e.g. provider for training.started). Use the secret shown in the dashboard to verify the signature.

Training Events

For training.started, training.completed, and training.failed, data includes at least jobId and modelName. Other fields (e.g. metrics, error) may be present.

Deployment Events

For model.deployed, data includes deployment details such as modelId and endpoint information.

Signature Verification

LLMTune signs the raw request body (string) with HMAC-SHA256 using your webhook secret. The signature is sent in the X-Webhook-Signature header (hex-encoded). Verify it before processing:
const crypto = require('crypto');

function verifySignature(rawBody, signature, secret) {
  const expected = crypto.createHmac('sha256', secret).update(rawBody).digest('hex');
  return crypto.timingSafeEqual(Buffer.from(signature, 'hex'), Buffer.from(expected, 'hex'));
}

// In your handler: use the raw body, not parsed JSON
app.post('/webhooks/llmtune', express.raw({ type: 'application/json' }), (req, res) => {
  const sig = req.headers['x-webhook-signature'];
  if (!verifySignature(req.body.toString(), sig, process.env.WEBHOOK_SECRET)) {
    return res.status(401).send('Invalid signature');
  }
  const payload = JSON.parse(req.body.toString());
  // ...
});

Response Handling

  • Respond with 2xx status codes to acknowledge receipt quickly; process the event asynchronously if needed
  • Request timeout: 5 seconds. Slow responses may be treated as failures

Best Practices

  1. Use unique secrets per webhook endpoint
  2. Acknowledge quickly – Respond with 200 OK immediately, then process asynchronously
  3. Log received events for debugging and auditing
  4. Validate signatures to ensure requests are from LLMTune
  5. Handle idempotency – Events may be delivered multiple times; use event IDs to deduplicate
  6. Monitor webhook health – Set up alerts if webhooks fail repeatedly

Testing Webhooks

  1. Use the Send Test Event button in the webhook configuration
  2. Test your endpoint locally using tools like ngrok or localtunnel
  3. Verify your endpoint handles all subscribed event types

Troubleshooting

  • Webhook not receiving events: Check that your endpoint is publicly accessible (HTTPS) and returns 2xx responses
  • Signature verification fails: Ensure you’re using the correct secret and computing the signature correctly
  • Events delayed: Check your endpoint response time; slow responses may cause retries
  • Missing events: Review webhook logs in the dashboard to see delivery status

Next Steps