Kiket docs
API & SDKsSDKs

Go

Kiket Go SDK.

Official Go SDK for building Kiket extensions.

Installation

go get github.com/kiket-dev/kiket/sdk/go

Quick Start

package main

import (
    "context"
    "log"
    "net/http"

    "github.com/kiket-dev/kiket/sdk/go/kiket"
)

func main() {
    // Create SDK instance
    sdk, err := kiket.New(kiket.Config{
        ExtensionAPIKey: "your-api-key",
        ExtensionID:     "com.example.my-extension",
    })
    if err != nil {
        log.Fatal(err)
    }
    defer sdk.Close()

    // Register webhook handlers
    sdk.On("case.created", func(ctx context.Context, payload kiket.WebhookPayload, hctx *kiket.HandlerContext) (interface{}, error) {
        case := payload["case"].(map[string]interface{})
        log.Printf("New case created: %s", case["title"])

        // Access custom data
        customData := hctx.Endpoints.CustomData(payload["project_id"])
        records, err := customData.List(ctx, "my-module", "my-table", nil)
        if err != nil {
            return nil, err
        }
        log.Printf("Found %d records", len(records.Data))

        return map[string]string{"status": "processed"}, nil
    })

    // Start HTTP server
    log.Println("Starting server on :8080")
    http.Handle("/webhook", sdk)
    log.Fatal(http.ListenAndServe(":8080", nil))
}

Configuration

The SDK can be configured programmatically or via manifest file:

sdk, err := kiket.New(kiket.Config{
    // Authentication
    ExtensionAPIKey: "ext-api-key",      // For extension API calls
    WorkspaceToken:  "workspace-token",  // Alternative: workspace auth

    // Extension info
    ExtensionID:      "com.example.my-ext",
    ExtensionVersion: "1.0.0",

    // Optional
    BaseURL:          "https://kiket.dev",
    Settings:         kiket.Settings{"key": "value"},
    ManifestPath:     "extension.yaml",
    AutoEnvSecrets:   true,
    TelemetryEnabled: true,
})

Manifest File

Create extension.yaml in your workspace root:

id: com.example.my-extension
version: 1.0.0

settings:
  - key: api_token
    secret: true
  - key: default_priority
    default: medium

Webhook Handlers

Register handlers for Kiket events:

// Issue events
sdk.On("case.created", handleIssueCreated)
sdk.On("case.updated", handleIssueUpdated)
sdk.On("case.status_changed", handleStatusChange)
sdk.On("case.assigned", handleAssignment)
sdk.On("case.closed", handleClosed)

// Workflow events
sdk.On("workflow.triggered", handleWorkflowTrigger)
sdk.On("workflow.sla_status", handleSLAStatus)
sdk.On("workflow.before_transition", handleBeforeTransition)

// Comment events
sdk.On("comment.created", handleCommentCreated)

Extension Endpoints

Response Helpers

Use the response helpers to build properly formatted responses:

import "github.com/kiket-dev/kiket/sdk/go/kiket"

// Simple allow
return kiket.Allow().Build(), nil

// Allow with message and data
return kiket.Allow().
    Message("Successfully configured").
    Data("routeId", 123).
    Build(), nil

// Allow with output fields (displayed in configuration UI)
return kiket.Allow().
    Message("Mailjet configured successfully").
    Data("routeId", route.ID).
    OutputField("inbound_email", route.Email).
    Build(), nil

// Deny with error details
return kiket.Deny("Invalid credentials").
    Data("errorCode", "AUTH_FAILED").
    Build(), nil

// Pending for async operations
return kiket.Pending("Awaiting approval").
    Data("jobId", "abc123").
    Build(), nil

Output fields are displayed in the extension configuration UI after setup, allowing extensions to expose generated data like email addresses, webhook URLs, or status information.

Secret Helper

The Secret() method provides a simple way to retrieve secrets with automatic fallback:

// Checks payload secrets first (per-org config), falls back to ENV
slackToken := hctx.Secret("SLACK_BOT_TOKEN")

// Example usage
sdk.On("case.created", func(ctx context.Context, payload kiket.WebhookPayload, hctx *kiket.HandlerContext) (interface{}, error) {
    apiKey := hctx.Secret("API_KEY")
    if apiKey == "" {
        return nil, fmt.Errorf("API_KEY not configured")
    }
    // Use apiKey...
    return map[string]string{"status": "ok"}, nil
})

The lookup order is:

  1. Payload secrets (per-org configuration from payload["secrets"])
  2. Environment variables (extension defaults)

This allows organizations to override extension defaults with their own credentials.

Secret Manager (API-based)

For programmatic secret management via the Kiket API:

// Get a secret
value, err := hctx.Secrets.Get(ctx, "api_token")

// Set a secret
err := hctx.Secrets.Set(ctx, "api_token", "new-value")

// List all secret keys
keys, err := hctx.Secrets.List(ctx)

// Delete a secret
err := hctx.Secrets.Delete(ctx, "api_token")

// Rotate a secret
err := hctx.Secrets.Rotate(ctx, "api_token", "rotated-value")

Custom Data

customData := hctx.Endpoints.CustomData(projectID)

// List records
records, err := customData.List(ctx, "module-key", "table-name", &kiket.CustomDataListOptions{
    Limit: 100,
    Filters: map[string]interface{}{
        "status": "active",
    },
})

// Get a record
record, err := customData.Get(ctx, "module-key", "table-name", recordID)

// Create a record
record, err := customData.Create(ctx, "module-key", "table-name", map[string]interface{}{
    "name": "Test",
    "value": 42,
})

// Update a record
record, err := customData.Update(ctx, "module-key", "table-name", recordID, map[string]interface{}{
    "value": 100,
})

// Delete a record
err := customData.Delete(ctx, "module-key", "table-name", recordID)

SLA Events

slaEvents := hctx.Endpoints.SLAEvents(projectID)

// List SLA events
events, err := slaEvents.List(ctx, &kiket.SLAEventsListOptions{
    State: "breached",
    Limit: 50,
})

Rate Limiting

info, err := hctx.Endpoints.RateLimit(ctx)
log.Printf("Remaining: %d/%d (resets in %ds)",
    info.Remaining, info.Limit, info.ResetIn)

Authentication

The SDK automatically verifies JWT runtime tokens from webhook payloads. The token is verified against Kiket's JWKS endpoint.

// Access authentication context in handlers
sdk.On("case.created", func(ctx context.Context, payload kiket.WebhookPayload, hctx *kiket.HandlerContext) (interface{}, error) {
    // Auth context is available after JWT verification
    if hctx.Auth != nil {
        log.Printf("Org ID: %d", *hctx.Auth.OrgID)
        log.Printf("Scopes: %v", hctx.Auth.Scopes)
    }
    return nil, nil
})

For manual JWT verification:

jwtPayload, err := kiket.DecodeJWT(ctx, tokenString, baseURL)
if err != nil {
    if kiket.IsAuthenticationError(err) {
        // Invalid or expired token
    }
}

HTTP Server Integration

The SDK implements http.Handler:

// Standard library
http.Handle("/webhook", sdk)

// Gin
router.POST("/webhook", gin.WrapH(sdk))

// Echo
e.POST("/webhook", echo.WrapHandler(sdk))

// Chi
r.Post("/webhook", sdk.ServeHTTP)

Testing

For testing, you can clear the JWKS cache between tests:

kiket.ClearJWKSCache()

Environment Variables

  • KIKET_SDK_TELEMETRY_OPTOUT=1 - Disable telemetry
  • KIKET_SECRET_* - Override secret values (when AutoEnvSecrets: true)

License

MIT License - see LICENSE for details.

On this page