ShrubberyDocs
Sign in

Inbox Webhook Integration

Overview

The Inbox webhook lets an external system (Jira, Linear, GitHub, or a custom tool) push a commitment directly into Shrubbery as a Pending_Handshake row. The Knight receives a Nudge and sees the row in their Accord without any Lead action in-app. This guide walks through setting up the integration end-to-end.

For the raw API reference, see POST /api/v1/inbox.

Actors

  • Lead — mints the API Token, monitors the Garden for incoming rows.
  • External System — sends the HTTP call on each relevant event (e.g. issue created, ticket assigned).
  • Knight — receives the Nudge and Handshakes in the Accord.
  • Squire — not involved. No AI extraction on Inbox rows.

Flow

1. Mint an API Token

  1. Lead navigates to /settingsAPI TokensGenerate new token.
  2. Copy the raw token value immediately — it is shown only once.
  3. Store it as a secret in the external system's webhook configuration (e.g. SHRUBBERY_TOKEN in GitHub Actions, a Jira webhook secret field).

2. Configure the external webhook

Point the external system's outbound webhook at POST https://shrubbery.eu/api/v1/inbox with:

POST /api/v1/inbox HTTP/1.1
Authorization: Bearer <your-token>
Content-Type: application/json
 
{
  "assignerEmail": "lead@example.com",
  "assigneeEmail": "knight@example.com",
  "description": "Ship the Q3 report",
  "deadline": "2026-09-30T17:00:00.000Z",
  "externalSystem": "jira",
  "externalId": "PROJ-123"
}

externalSystem and externalId should identify the source ticket uniquely within the external system. They enable deduplication and power the Sync flow later.

3. Verify the integration

A successful call returns 201 Created with the Shrubbery's id. Confirm by checking:

  • The row appears in the Garden under Pending_Handshake.
  • The assignee received a Nudge via their preferred channel.
  • The Audit Trail shows created + nudge_sent events with actor_kind = api_token.

4. Pair with Sync for close events

Once the integration is live, also configure a POST /api/v1/sync call for when the external issue closes. See Sync Webhook Integration.

Edge cases

  • Duplicate deliveries — the endpoint is idempotent on (externalSystem, externalId, assigner). A webhook retry with the same payload returns 409 duplicate_external_ref; no duplicate row is created.
  • Unknown assignee email — if assigneeEmail does not match any Shrubbery user, the request returns 422 assignee_not_found. The external system should handle this gracefully (e.g. alert the Lead to add the user first).
  • Missing deadlinedeadline is required. If the external system does not provide one, the integration layer should supply a default (e.g. 30 days from creation) rather than omitting the field.
  • Nudge delivery failure — if Inngest cannot deliver the Nudge (channel misconfigured, transient failure), it retries automatically. The Shrubbery row exists regardless; only the Nudge delivery is retried.

Last updated: 22 June 2026