Search...Search plugins and themes...
⌘K
Sign in
  • Get started
  • Download
  • Pricing
  • Enterprise
  • Account
  • Obsidian
  • Overview
  • Sync
  • Publish
  • Canvas
  • Mobile
  • Web Clipper
  • CLI
  • Learn
  • Help
  • Developers
  • Changelog
  • About
  • Roadmap
  • Blog
  • Resources
  • System status
  • License overview
  • Terms of service
  • Privacy policy
  • Security
  • Community
  • Plugins
  • Themes
  • Discord
  • Forum / 中文论坛
  • Merch store
  • Brand guidelines
Follow us
DiscordTwitterBlueskyThreadsMastodonYouTubeGitHub
© 2026 Obsidian

Webhooks Server

khabaroffkhabaroffkhabaroff-studiokhabaroff-studio247 downloads

Receive webhooks from external services and create notes in your vault via a self-hosted server with real-time delivery.

Add to Obsidian
  • Overview
  • Scorecard
  • Updates4

Turn any external event into notes in your Obsidian vault — self-hosted, real-time, encrypted.

Receive webhooks from Zapier, Make, n8n, AI agents, or any HTTP client. Events are delivered to the Obsidian plugin instantly via SSE (with polling fallback) and guaranteed exactly-once via ACK system.

Features

  • Real-time delivery — Server-Sent Events (SSE) with polling fallback
  • Exactly-once guarantee — ACK system prevents duplicates
  • Encryption at rest — AES-256-GCM for all event data
  • Passwordless auth — email magic links, no passwords
  • Self-hosted — full control over your data, no third parties
  • Production-ready — rate limiting, auto-cleanup, health checks, CI/CD

Quick Start

git clone https://github.com/khabaroff-studio/obsidian-webhooks-server.git
cd obsidian-webhooks-server

cp .env.example .env
# Edit .env: DATABASE_URL, JWT_SECRET, MAILGUN credentials

docker compose up -d

Verify: curl http://localhost:8081/health

Register & Connect

  1. Open http://localhost:8081 — enter your email
  2. Click the magic link in your inbox
  3. Install the Obsidian plugin from your dashboard (or build: cd plugin && bun install && bun run build)
  4. Enter Client Key and Server URL in plugin settings

Send Your First Webhook

curl -X POST "http://localhost:8081/webhook/wh_YOUR_KEY?path=inbox/test.md" \
  -H "Content-Type: application/json" \
  -d '{"title": "Hello!", "content": "It works.", "tags": ["test"]}'

Check your vault — inbox/test.md should appear.

How It Works

Architecture

API

Method Path Description
POST /webhook/{key}?path=file.md Send event (body: JSON or plain text)
GET /events/{client_key} SSE event stream
POST /ack/{client_key}/{event_id} Acknowledge event
POST /auth/register Register (sends magic link)
GET /auth/verify?token=xxx Verify magic link
GET /dashboard User dashboard
GET /health Health check

Webhook Body Format

JSON fields are converted to Markdown with YAML frontmatter:

{"title": "Meeting", "tags": ["work"], "source": "n8n", "content": "# Notes\n\n- Item 1"}
---
title: Meeting
tags: ["work"]
source: n8n
---

# Notes

- Item 1

Non-JSON body is written as-is. Max payload: 10 MB.

Use Cases

Email to Notes (Zapier/Make):

POST /webhook/wh_xxx?path=inbox/emails/{{date}}.md
{"title": "{{subject}}", "content": "From: {{sender}}\n\n{{body}}"}

GitHub Issues:

POST /webhook/wh_xxx?path=projects/github-issues.md
{"title": "{{issue.title}}", "content": "{{issue.body}}", "tags": ["github"]}

Custom API:

requests.post(
    "https://your-server/webhook/wh_xxx?path=logs/api.md",
    json={"content": f"Result: {data}", "source": "api"}
)

Tech Stack

Layer Technology
Server Go 1.24, Gin
Database PostgreSQL (Supabase)
Plugin TypeScript, Obsidian API
Auth Mailgun (magic links), JWT
Encryption AES-256-GCM
Frontend Tailwind CSS (pre-built)
Deploy Docker, Nginx
CI/CD GitHub Actions

Configuration

Required

DATABASE_URL=postgres://user:pass@host:5432/db
JWT_SECRET=your-random-secret           # openssl rand -base64 32
ENCRYPTION_KEY=64-char-hex-string       # openssl rand -hex 32
MAILGUN_DOMAIN=mail.yourdomain.com
MAILGUN_API_KEY=your-mailgun-key
[email protected]

Admin (first run only)

ADMIN_USERNAME=admin
ADMIN_PASSWORD=your-secure-password

Admin is auto-created on first start. Password can be removed from .env after.

Optional

EVENT_TTL_DAYS=30              # Event retention (default: 30)
ENABLE_AUTO_CLEANUP=true       # Auto-delete expired events
POSTHOG_ENABLED=false          # Analytics (disabled by default)
MAILERLITE_API_KEY=            # Marketing automation (optional)

See .env.example for full reference.

Development

# Run locally
go run main.go

# Tests (72 tests)
make test

# Lint
make lint

# Rebuild Tailwind CSS (after changing HTML templates)
npm install        # first time only
make css

# Test database
docker compose -f docker-compose.test.yml up -d   # port 5433

# Build
make build

Project Structure

main.go                      # Entry point & routes
schema.sql                   # Database schema
tailwind.config.js           # Tailwind CSS config
package.json                 # Node.js deps (Tailwind build only)
src/
├── handlers/                # HTTP handlers (webhook, SSE, ACK, auth, admin)
├── services/                # Business logic (keys, events, auth, email, crypto)
├── middleware/               # Auth, rate limiting, validation, logging
├── models/                  # Data models & constants
├── database/                # Connection pool & test helpers
├── repositories/            # Interfaces & mocks
└── templates/               # HTML pages & email templates
    └── assets/              # CSS, fonts, images
plugin/                      # Obsidian plugin (TypeScript)
├── main.ts                  # Plugin entry point
├── handlers/                # SSE, polling, ACK, file handlers
└── settings_tab.ts          # Settings UI

Security

  • Passwordless auth — crypto-secure magic links (32 bytes, one-time, 60-min expiry)
  • AES-256-GCM encryption for event data at rest
  • Rate limiting — per IP (auth: 3/min) and per webhook key
  • JWT sessions with crypto/rand secret generation
  • Request body limits via io.LimitReader (10 MB)
  • Mutex protection for SSE client map

Acknowledgments

Inspired by obsidian-webhooks by @trashhalo — the original proof of concept for webhook-driven Obsidian workflows.

License

MIT

HealthExcellent
ReviewSatisfactory
About
Turn external HTTP events into Markdown notes in your vault in real time. Deliver events instantly via Server-Sent Events (SSE) with polling fallback, guarantee exactly-once delivery using ACKs, and store event data encrypted at rest for self-hosted control. Use passwordless email magic links for secure access.
ImportIntegrationsAutomation
Details
Current version
2.0.3
Last updated
5 months ago
Created
8 months ago
Updates
4 releases
Downloads
247
Compatible with
Obsidian 0.15.0+
Platforms
Desktop, Mobile
License
MIT
Report bugRequest featureReport plugin
Authors
khabaroffkhabaroff
GitHubkhabaroff
khabaroff-studiokhabaroff-studio
github.com/khabaroff
GitHubkhabaroff-studio
  1. Community
  2. Plugins
  3. Import
  4. Webhooks Server

Related plugins

Readwise Official

Sync highlights from Readwise to your vault.

Granola Sync

Sync Granola notes to your vault.

BRAT

Easily install a beta version of a plugin for testing.

Zotero Integration

Insert and import citations, bibliographies, notes, and PDF annotations from Zotero.

Snipd Official

Sync Snipd podcast highlights to your vault with transcript, notes, AI summaries and metadata.

Actions URI

Add additional `x-callback-url` endpoints to the app for common actions — it's a clean, super-charged addition to Obsidian URI.

Todoist Sync

Materialize Todoist tasks within your notes.

Shell commands

Define system commands that you want to execute via command palette, hotkeys, URI links or automated events. E.g. open external applications or perform automated file modifications.

ZotLit

Integrate with Zotero, create literature notes, and insert citations from a Zotero library.

Importer

Convert your data to Markdown files you can use in Obsidian. Works with Apple Notes, OneNote, Evernote, Notion, Google Keep, and many other formats.