Skip to main content

Notifications

DotVault supports real-time notifications via Slack, Discord, and generic webhooks to keep your team informed of important events.

Overview

Notifications help you:

  • Monitor activity: Know when secrets are accessed or modified
  • Respond quickly: Get alerted to security events
  • Maintain compliance: Track all changes in real-time
  • Integrate workflows: Connect with your existing tools

Supported Channels

Slack

Receive notifications in Slack channels with rich formatting.

Features:

  • Rich message formatting with color-coded events
  • Direct mention support for urgent events
  • Thread replies for related events
  • Mobile push notifications

Setup:

  1. Create a Slack app with incoming webhooks
  2. Copy webhook URL
  3. Configure in DotVault project settings

Discord

Get notifications in Discord channels with embed formatting.

Features:

  • Rich embeds with event details
  • Color-coded by severity
  • Role mention support
  • Mobile notifications

Setup:

  1. Create a Discord webhook in channel settings
  2. Copy webhook URL
  3. Configure in DotVault project settings

Generic Webhooks

Send notifications to any HTTP endpoint for custom integrations.

Features:

  • Custom payload format
  • Signature verification
  • Retry logic
  • Custom headers

Use Cases:

  • SIEM integration
  • Custom dashboards
  • Automated workflows
  • PagerDuty/Opsgenie

Event Types

Environment Events

EventDescriptionSeverity
env.createdNew environment createdInfo
env.updatedEnvironment modifiedInfo
env.deletedEnvironment deletedWarning
env.viewedEnvironment accessedInfo
env.exportedEnvironment exportedInfo

Member Events

EventDescriptionSeverity
member.invitedNew member invitedInfo
member.joinedInvitation acceptedInfo
member.removedMember removedWarning
member.role_changedRole updatedInfo

Access Control Events

EventDescriptionSeverity
access.requestedAccess request submittedInfo
access.approvedAccess request approvedInfo
access.rejectedAccess request rejectedInfo
emergency.access.usedEmergency access activatedCritical

Security Events

EventDescriptionSeverity
login.failedFailed login attemptWarning
login.succeededSuccessful loginInfo
secret.rotatedSecret rotatedInfo
sync.completedEnvironment sync completedInfo

Configuration

Web Interface

  1. Go to Project SettingsNotifications
  2. Click Add Webhook
  3. Select channel type (Slack/Discord/Generic)
  4. Enter webhook URL
  5. Select events to subscribe to
  6. Optional: Add secret for signature verification
  7. Test the configuration
  8. Save

CLI

# Add Slack webhook
dotvault webhook add my-project \
--type slack \
--url https://hooks.slack.com/services/T00000000/B00000000/XXXXXXXXXXXXXXXXXXXXXXXX \
--events env.updated,env.deleted,emergency.access.used

# Add Discord webhook
dotvault webhook add my-project \
--type discord \
--url https://discord.com/api/webhooks/... \
--events "*"

# Add generic webhook
dotvault webhook add my-project \
--type generic \
--url https://your-api.com/webhook \
--events env.updated \
--secret your-webhook-secret

# List webhooks
dotvault webhook list my-project

# Test webhook
dotvault webhook test my-project --webhook-id whk_xxx

# Remove webhook
dotvault webhook remove my-project --webhook-id whk_xxx

API

# Create webhook
POST /api/projects/{projectId}/webhooks
{
"type": "slack",
"url": "https://hooks.slack.com/services/...",
"events": ["env.updated", "env.deleted", "emergency.access.used"],
"secret": "optional-signing-secret"
}

Response:
{
"data": {
"id": "whk_xxx",
"type": "slack",
"url": "https://hooks.slack.com/services/...",
"events": ["env.updated", "env.deleted", "emergency.access.used"],
"isActive": true,
"createdAt": "2024-01-15T10:30:00Z"
}
}

# Test webhook
POST /api/projects/{projectId}/webhooks/{webhookId}/test

Response:
{
"data": {
"success": true,
"responseStatus": 200,
"responseTime": 245
}
}

Message Formats

Slack Format

{
"attachments": [
{
"color": "#10b981",
"title": "✓ Environment Updated",
"fields": [
{
"title": "Project",
"value": "My Project",
"short": true
},
{
"title": "User",
"value": "John Doe (john@example.com)",
"short": true
},
{
"title": "Environment",
"value": "production",
"short": true
}
],
"footer": "DotVault",
"ts": 1705315800
}
]
}

Discord Format

{
"embeds": [
{
"title": "✓ Environment Updated",
"color": 65280,
"fields": [
{
"name": "Project",
"value": "My Project",
"inline": true
},
{
"name": "User",
"value": "John Doe (john@example.com)",
"inline": true
}
],
"footer": {
"text": "DotVault"
},
"timestamp": "2024-01-15T10:30:00.000Z"
}
]
}

Generic Webhook Format

{
"event": "env.updated",
"projectId": "proj_xxx",
"projectName": "My Project",
"user": {
"id": "user_xxx",
"name": "John Doe",
"email": "john@example.com"
},
"timestamp": "2024-01-15T10:30:00.000Z",
"details": {
"label": "production",
"via": "web"
},
"ipAddress": "192.168.1.1",
"source": "dotvault",
"version": "1.0"
}

Signature Verification

For generic webhooks, verify the signature to ensure authenticity:

Node.js Example

const crypto = require("crypto");

function verifyWebhook(payload, signature, secret) {
const expected = crypto
.createHmac("sha256", secret)
.update(JSON.stringify(payload))
.digest("hex");

return signature === `sha256=${expected}`;
}

// Express middleware
app.post("/webhook", (req, res) => {
const signature = req.headers["x-dotvault-signature"];
const secret = process.env.DOTVAULT_WEBHOOK_SECRET;

if (!verifyWebhook(req.body, signature, secret)) {
return res.status(401).send("Invalid signature");
}

// Process webhook
console.log("Event:", req.body.event);
res.status(200).send("OK");
});

Python Example

import hmac
import hashlib
import json

from flask import Flask, request, abort

app = Flask(__name__)

@app.route('/webhook', methods=['POST'])
def webhook():
signature = request.headers.get('X-DotVault-Signature', '')
secret = os.environ['DOTVAULT_WEBHOOK_SECRET']

expected = 'sha256=' + hmac.new(
secret.encode(),
request.data,
hashlib.sha256
).hexdigest()

if not hmac.compare_digest(signature, expected):
abort(401)

payload = request.get_json()
print(f"Event: {payload['event']}")

return 'OK'

Best Practices

1. Subscribe to Relevant Events

Don't subscribe to all events - choose what's important:

Recommended for most teams:

  • env.updated
  • env.deleted
  • member.removed
  • emergency.access.used
  • login.failed

For security-focused teams, add:

  • env.viewed
  • access.requested
  • access.approved

2. Use Separate Channels

Create dedicated channels for different purposes:

  • #dotvault-alerts - Critical events only
  • #dotvault-activity - All activity
  • #dotvault-security - Security events

3. Set Up Monitoring

Monitor webhook health:

# Check webhook status
dotvault webhook status my-project

# View delivery logs
dotvault webhook logs my-project --webhook-id whk_xxx

4. Handle Failures

Implement retry logic in your webhook handler:

app.post("/webhook", async (req, res) => {
try {
await processWebhook(req.body);
res.status(200).send("OK");
} catch (error) {
// Return 500 to trigger retry
res.status(500).send("Error");
}
});

5. Secure Your Endpoints

  • Use HTTPS only
  • Verify signatures
  • Implement IP allowlisting
  • Use strong webhook secrets

Troubleshooting

Webhook Not Firing

  1. Check webhook is active
  2. Verify event subscription
  3. Test webhook manually
  4. Check delivery logs

Messages Not Received

  1. Verify webhook URL is correct
  2. Check channel permissions
  3. Test with curl:
    curl -X POST https://hooks.slack.com/services/... \
    -H 'Content-Type: application/json' \
    -d '{"text":"Test"}'

Signature Verification Failing

  1. Ensure secret matches
  2. Check payload isn't modified
  3. Verify encoding (UTF-8)
  4. Check header name case

Rate Limiting

If receiving 429 errors:

  1. Implement exponential backoff
  2. Process webhooks asynchronously
  3. Return 200 quickly, process later
  4. Contact support if persistent

API Reference

List Webhooks

GET /api/projects/{projectId}/webhooks

Response:
{
"data": {
"webhooks": [
{
"id": "whk_xxx",
"type": "slack",
"url": "https://hooks.slack.com/services/...",
"events": ["env.updated", "env.deleted"],
"isActive": true,
"lastSuccessAt": "2024-01-15T10:30:00Z",
"lastError": null,
"createdAt": "2024-01-15T09:00:00Z"
}
]
}
}

Update Webhook

PATCH /api/projects/{projectId}/webhooks/{webhookId}
{
"events": ["env.updated", "env.deleted", "member.removed"],
"isActive": true
}

Delete Webhook

DELETE /api/projects/{projectId}/webhooks/{webhookId}

Response:
{
"data": {
"success": true
}
}

Get Delivery Logs

GET /api/projects/{projectId}/webhooks/{webhookId}/logs?page=1&limit=50

Response:
{
"data": {
"logs": [
{
"id": "log_xxx",
"event": "env.updated",
"status": "delivered",
"statusCode": 200,
"responseTime": 245,
"createdAt": "2024-01-15T10:30:00Z"
},
{
"id": "log_yyy",
"event": "env.deleted",
"status": "failed",
"statusCode": 500,
"error": "Internal Server Error",
"createdAt": "2024-01-15T10:35:00Z"
}
]
}
}

Pricing

Notification limits by plan:

PlanWebhooksEvents/Month
Free1100
Pro510,000
EnterpriseUnlimitedUnlimited

Enterprise features:

  • Custom webhook formats
  • Advanced retry logic
  • Webhook analytics
  • Priority delivery

Support