Skip to content

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.yaml under .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 named KIKET_SECRET_<SETTING_KEY> (e.g., api.tokenKIKET_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-Signature header (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 loads extension.yaml, merges default settings, and reads KIKET_WEBHOOK_SECRET, KIKET_WORKSPACE_TOKEN, and any KIKET_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 a dbt_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 run per installation. Results land in analytics_ext_<org>_<extension>_<installation_id> so data never leaks between customers.
  • During the run Kiket injects:
  • KIKET_INSTALLATION_ID, KIKET_PRODUCT_IDENTIFIER, and DBT_INSTALLATION_SCHEMA so models know which tenant/schema they should target.
  • INSTALLATION_SECRET_<KEY> environment variables for every secret stored against the installation (sourced from deployment.secret_keys and the manifest configuration.secret: true fields). Use them in profiles.yml/vars instead of hardcoding credentials.
  • kiket extensions lint/kiket extensions package detect 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 authentication block with a short-lived runtime token plus an api.base_url hint. The SDKs consume this automatically and send X-Kiket-Runtime-Token instead 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 ngrok or cloudflared to 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-guardian from 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). Set KIKET_SDK_TELEMETRY_OPTOUT=1 to 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:

  1. Declare actions in manifest.yaml:

    actions:
      - key: sync_contacts
        label: Sync Contacts
        description: Pull latest contacts from CRM
        icon: refresh
        scopes: [project, issue]
    

  2. Implement the action endpoint: Kiket sends a POST to your callback URL with action_key and context (project, issue, user).

  3. Return results: Respond with status, optional message, and any data to display:

    {
      "status": "success",
      "message": "Synced 42 contacts",
      "data": {"synced_count": 42}
    }
    

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.