Building Extensions¶
This guide walks through the lifecycle of creating, testing, and deploying a Kiket extension.
1. Design the Use Case¶
- Identify the events you need (issue created, workflow transitioned, board refreshed, analytics thresholds crossed).
- Decide whether the extension needs to call back into Kiket (via REST API) or only respond to events.
2. Create the Manifest¶
- Place
manifest.yamlunder.kiket/extensions/<extension-key>/. - Declare metadata, permissions, triggers, optional UI surfaces, and configuration fields.
- Mark configuration fields that should never be stored in plaintext with
secret: true. During runtime these map to environment variables namedKIKET_SECRET_<SETTING_KEY>(e.g.,api.token→KIKET_SECRET_API_TOKEN), which the SDK reads automatically before falling back to the platform secret store. - Version the manifest to control rollout.
3. Implement Endpoints¶
- Build HTTPS endpoints for each trigger. Use your preferred stack (Nest.js, Express, Go, serverless, etc.).
- Verify incoming requests using the
X-Kiket-Signatureheader (HMAC SHA-256 with your extension secret). - Respond within 10 seconds; otherwise Kiket retries with exponential backoff.
Guard Responses for workflow.before_transition¶
When a hook is declared as required: true, Kiket evaluates the HTTP response synchronously before applying the transition. Respond with JSON containing a status field:
{
"status": "allow",
"message": "optional human-readable detail",
"metadata": {"approval_id": "abc"}
}
Supported values:
| Status | Effect |
|---|---|
allow (default) |
Transition proceeds immediately. |
pending |
Transition stays blocked until approvals resolve; message is shown to the user. |
deny |
Transition is cancelled and the message is displayed as an error. |
If the response body is empty or malformed, the runtime assumes allow. HTTP failures (4xx/5xx or timeouts) are treated as deny for required guards. Non-required hooks continue to run asynchronously via the delivery job.
4. Bootstrap the Runtime¶
- When you use the Python SDK,
KiketSDK()automatically loadsextension.yaml, merges default settings, and readsKIKET_WEBHOOK_SECRET,KIKET_WORKSPACE_TOKEN, and anyKIKET_SECRET_*values from the environment. Override them explicitly only when you need custom configuration. - Other runtimes should follow the same convention: keep secrets in
KIKET_SECRET_*env vars and avoid hard-coding them. - The SDK automatically uses runtime tokens (described below) for all
/api/v1/ext/*endpoints (telemetry, custom data, secret sync). Runtime tokens are minted per invocation and delivered in webhook payloads.
4a. Ship DBT Modules Per Installation¶
- Place DBT projects under
.kiket/modules/<module>/dbt/and include adbt_project.yml. Each module can expose its own models/seeds/macros. - The installer now copies those projects into a tenant-specific workspace and executes
dbt runper installation. Results land inanalytics_ext_<org>_<extension>_<installation_id>so data never leaks between customers. - During the run Kiket injects:
KIKET_INSTALLATION_ID,KIKET_PRODUCT_IDENTIFIER, andDBT_INSTALLATION_SCHEMAso models know which tenant/schema they should target.INSTALLATION_SECRET_<KEY>environment variables for every secret stored against the installation (sourced fromdeployment.secret_keysand the manifestconfiguration.secret: truefields). Use them inprofiles.yml/varsinstead of hardcoding credentials.kiket extensions lint/kiket extensions packagedetect DBT projects automatically. Running those commands in CI guarantees the manifests, schemas, and DBT configs stay in sync before they reach the marketplace.
5. Call the API¶
- Every webhook payload now includes an
authenticationblock with a short-lived runtime token plus anapi.base_urlhint. The SDKs consume this automatically and sendX-Kiket-Runtime-Tokeninstead of your long-lived API key. - Kiket also provides a static API key per installation (accessible from the manifest/CLI) for CI jobs or long-running maintenance tasks that cannot rely on webhook-delivered tokens.
- Use standard REST endpoints to fetch issues, create comments, or update custom fields.
- Respect rate limits (see API Reference) and scope restrictions.
Runtime token payload¶
Each invocation includes a payload segment similar to:
"authentication": {
"token_type": "runtime",
"runtime_token": "rt_PeXQw....",
"expires_at": "2025-11-10T12:34:56Z",
"scopes": ["ext.api.read", "ext.api.write", "ext.secrets.read"]
},
"api": {
"base_url": "https://kiket.dev",
"runtime_header": "X-Kiket-Runtime-Token"
}
SDKs read this block and automatically send the runtime token to /api/v1/ext/** endpoints. Tokens expire within 15 minutes (configurable per delivery up to 60 minutes) and are scoped to the invoking project/install.
6. Test Locally¶
- Use
ngrokorcloudflaredto expose your local server. - Trigger workflows in a sandbox project and inspect delivery logs in Project → Extensions → Activity.
- Add integration tests to your extension repository to simulate webhook payloads (fixtures are available under
spec/fixtures/extensions/). - Need a turnkey example? Copy
extensions/reference/webhook-guardianfrom this repo—it already includes a.kiket/manifest.yaml, pytest suite, replay payloads, and a GitHub Actions workflow wired to the CLI commands (kiket extensions lint/test/replay). - Telemetry is emitted automatically by the SDKs; the data feeds the marketplace telemetry dashboard and CLI (
kiket marketplace telemetry report). SetKIKET_SDK_TELEMETRY_OPTOUT=1to disable in local environments.
7. Choose Your Hosting Model¶
Kiket supports two hosting approaches for extensions:
Self-Hosted Extensions¶
Deploy to your own infrastructure and receive webhooks from Kiket:
extension:
id: my-extension
delivery: http
callback:
url: https://my-server.example.com/webhook
secret: env.WEBHOOK_SECRET
Advantages: - Full control over infrastructure and scaling - Use any hosting provider (Cloud Run, Vercel, Lambda, etc.) - No additional hosting fees from Kiket
Responsibilities: - Provision and maintain infrastructure - Handle SSL certificates and uptime - Manage scaling and resource allocation
Managed Extensions (Kiket-Hosted)¶
Let Kiket host and run your extension:
hosting:
tier: standard # minimal, standard, compute, or memory
egress:
- api.slack.com
- hooks.example.com
Advantages: - No infrastructure to manage - Automatic scaling and updates - Integrated monitoring and logging - Simple billing (per-tier pricing)
Hosting Tiers:
| Tier | Resources | Price | Best For |
|---|---|---|---|
minimal |
0.25 CPU, 256Mi | $5/mo | Simple webhooks, notifications |
standard |
1 CPU, 512Mi | $15/mo | Most extensions, API integrations |
compute |
2 CPU, 1Gi | $35/mo | Data processing, heavy workloads |
memory |
1 CPU, 2Gi | $30/mo | Large datasets, caching |
For marketplace publishers, managed hosting simplifies distribution - customers install your extension without deploying infrastructure.
8. Deploy & Monitor¶
- For self-hosted: Deploy to your infrastructure (Cloud Run, Vercel, Lambda).
- For managed: Push to your repository and publish to the marketplace.
- Set up monitoring for latency, error rates, and retries.
- Update the manifest version and sync to roll out improvements.
Exposing Actions¶
Extensions can expose actions that users trigger from the Kiket UI or via API:
-
Declare actions in manifest.yaml:
-
Implement the action endpoint: Kiket sends a POST to your callback URL with
action_keyand context (project, issue, user). -
Return results: Respond with status, optional message, and any data to display:
Actions appear in context menus, command palette, and can be triggered via /api/v1/extensions/:id/actions/:action_key.
By following this process you can ship reliable, maintainable extensions that feel native to Kiket.