Webhooks
Active Development
Webhook payload formats are determined by the source platform (GitHub, GitLab, etc.) and are not controlled by Aether. The information here reflects Aether's current handling logic, which may evolve as integrations are updated.
Unified Webhook Endpoint
All webhooks are received at a single endpoint:
POST /webhook/:slugThe :slug identifies the source. For built-in integrations, use:
| Source | Slug | URL |
|---|---|---|
| GitHub | github | POST /webhook/github |
| GitLab | gitlab | POST /webhook/gitlab |
| Jira | jira | POST /webhook/jira |
| Plane | plane | POST /webhook/plane |
For dynamic integrations, the slug is the identifier you assign when creating the integration.
How Webhooks Are Processed
Incoming webhook
│
▼
1. Verify signature / token (if configured)
│
▼
2. Persist raw webhook event to database
│
▼
3. Extract source + event type + action from payload
│
▼
4. Look up canonical trigger from source_event_mappings table
│
▼
5. If no mapping found → log and discard
If mapping found → look up tasks from trigger_task_mappings
│
▼
6. For each task → call agent via LLM → post response to trackerUnhandled events (no mapping) are silently discarded with a log entry. No error is returned to the sender.
Security Verification
GitHub
GitHub signs payloads with HMAC-SHA256. Aether verifies the X-Hub-Signature-256 header against the secret you configure when setting up the webhook in GitHub.
- If no secret is configured on the GitHub side, Aether accepts unsigned payloads (not recommended for production).
GitLab
GitLab sends a secret token in the X-Gitlab-Token header. Configure the same token in both GitLab's webhook settings and Aether's GITLAB_TOKEN.
Jira
Jira webhooks do not include built-in signing. Aether accepts all payloads at the Jira endpoint. Use network-level controls (firewall, IP allowlist) to restrict access.
Plane
Plane sends the API key in the X-API-Key header. Aether validates it against PLANE_API_KEY.
GitHub Payloads
Required headers:
Content-Type: application/json
X-GitHub-Event: <event-name>
X-Hub-Signature-256: sha256=<hmac> (if secret configured)Issues Event
{
"action": "opened",
"issue": {
"number": 456,
"title": "Bug in login flow",
"body": "When I click login, nothing happens.",
"state": "open",
"user": { "login": "dev-user" },
"labels": [{ "name": "bug" }]
},
"repository": {
"full_name": "owner/repo"
}
}Handled actions: opened, edited, closed, reopened, labeled, unlabeled
Pull Request Event
{
"action": "opened",
"pull_request": {
"number": 123,
"title": "Add OAuth support",
"body": "Implements OAuth 2.0 login.",
"state": "open",
"head": { "ref": "feature/oauth" },
"base": { "ref": "main" }
},
"repository": {
"full_name": "owner/repo"
}
}Handled actions: opened, edited, closed, reopened, ready_for_review, synchronize
Issue Comment Event
{
"action": "created",
"issue": { "number": 456 },
"comment": {
"id": 999,
"body": "Can you provide steps to reproduce?"
},
"repository": {
"full_name": "owner/repo"
}
}GitLab Payloads
Required headers:
Content-Type: application/json
X-Gitlab-Event: <hook-type>
X-Gitlab-Token: <secret> (if configured)Issue Hook
{
"object_kind": "issue",
"event_type": "issue",
"user": { "username": "dev-user" },
"project": {
"id": 123,
"path_with_namespace": "group/project"
},
"object_attributes": {
"iid": 42,
"title": "Performance regression in API",
"description": "Response times increased by 300ms",
"state": "opened",
"action": "open"
}
}Handled actions: open, close, reopen, update
Merge Request Hook
{
"object_kind": "merge_request",
"event_type": "merge_request",
"user": { "username": "dev-user" },
"project": {
"id": 123,
"path_with_namespace": "group/project"
},
"object_attributes": {
"iid": 55,
"title": "Fix memory leak in worker pool",
"description": "Adds proper cleanup on shutdown",
"state": "opened",
"action": "open",
"source_branch": "fix/memory-leak",
"target_branch": "main"
}
}Jira Payloads
Issue Created
{
"webhookEvent": "jira:issue_created",
"issue": {
"key": "PROJ-123",
"fields": {
"summary": "Login fails for SSO users",
"description": "Users with SSO enabled cannot log in.",
"issuetype": { "name": "Bug" },
"priority": { "name": "High" },
"status": { "name": "Open" }
}
}
}Issue Updated
{
"webhookEvent": "jira:issue_updated",
"issue": {
"key": "PROJ-123",
"fields": {
"summary": "Login fails for SSO users",
"status": { "name": "In Progress" }
}
},
"changelog": {
"items": [
{
"field": "status",
"fromString": "Open",
"toString": "In Progress"
}
]
}
}Comment Created
{
"webhookEvent": "comment_created",
"comment": {
"id": "12345",
"body": "Reproduced on version 2.3.1.",
"author": { "displayName": "QA Engineer" }
},
"issue": { "key": "PROJ-123" }
}Plane Payloads
Issue Created
{
"event": "issue.created",
"data": {
"id": "abc123def456",
"name": "API rate limiting needed",
"description": "We need to add rate limiting to the public API.",
"state": "backlog",
"priority": "high",
"project_id": "project-uuid",
"workspace_slug": "my-workspace"
}
}Issue Updated
{
"event": "issue.updated",
"data": {
"id": "abc123def456",
"name": "API rate limiting needed",
"state": "in_progress",
"changes": {
"state": {
"old": "backlog",
"new": "in_progress"
}
}
}
}Comment Created
{
"event": "issue.activity.created",
"data": {
"activity_type": "comment",
"comment": "Added Redis-based rate limiting in PR #45",
"issue_id": "abc123def456"
}
}Testing Webhooks
Use curl to send test webhooks without configuring the actual external service:
GitHub Issue Opened
curl -X POST http://localhost:8000/webhook/github \
-H "Content-Type: application/json" \
-H "X-GitHub-Event: issues" \
-d '{
"action": "opened",
"issue": {
"number": 1,
"title": "Test Issue",
"body": "This is a test issue for verifying the webhook integration."
},
"repository": {
"full_name": "test-org/test-repo"
}
}'GitLab Issue Opened
curl -X POST http://localhost:8000/webhook/gitlab \
-H "Content-Type: application/json" \
-H "X-Gitlab-Event: Issue Hook" \
-d '{
"object_kind": "issue",
"object_attributes": {
"iid": 1,
"title": "Test GitLab Issue",
"description": "Testing webhook integration",
"action": "open"
},
"project": {
"path_with_namespace": "test-group/test-project"
}
}'Jira Issue Created
curl -X POST http://localhost:8000/webhook/jira \
-H "Content-Type: application/json" \
-d '{
"webhookEvent": "jira:issue_created",
"issue": {
"key": "TEST-1",
"fields": {
"summary": "Test Jira Issue",
"description": "Testing webhook integration"
}
}
}'Plane Issue Created
curl -X POST http://localhost:8000/webhook/plane \
-H "Content-Type: application/json" \
-d '{
"event": "issue.created",
"data": {
"id": "test-issue-id",
"name": "Test Plane Issue",
"description": "Testing webhook integration",
"state": "backlog",
"priority": "medium"
}
}'View Processing Logs
docker-compose logs -f goway | grep -i webhookConfiguring Webhooks in External Services
GitHub
- Go to Repository Settings → Webhooks → Add webhook
- Payload URL:
https://your-aether-host/webhook/github - Content type:
application/json - Secret: Set a secret and match it in your Aether config (recommended for production)
- Events: Select the events you want — at minimum, "Issues" and "Pull requests"
GitLab
- Go to Project Settings → Webhooks → Add new webhook
- URL:
https://your-aether-host/webhook/gitlab - Secret token: Optional but recommended
- Trigger: Issues events, Merge request events, Comments
Jira
- Go to Jira Administration → System → WebHooks → Create a WebHook
- URL:
https://your-aether-host/webhook/jira - Events:
jira:issue_created,jira:issue_updated,comment_created - JQL filter: Optionally filter to specific projects
Plane
- Go to Project Settings → Members & Settings → Webhooks
- URL:
https://your-aether-host/webhook/plane - Events: issue.created, issue.updated, issue.activity.created
Troubleshooting
Webhook delivered but nothing happens:
- Check that a source_event_mapping exists for this source + event + action
- Check that a trigger_task_mapping exists for the canonical trigger
- Check Aether logs:
docker-compose logs -f goway
Webhook not being received:
- Verify the URL is correct and publicly reachable
- Check for firewall or reverse proxy issues
- Review the "Recent Deliveries" in GitHub/GitLab webhook settings
Signature verification failing:
- Ensure the secret matches exactly on both sides
- Check for whitespace or encoding issues in the secret
