Go
Kiket Go SDK.
Official Go SDK for building Kiket extensions.
Installation
go get github.com/kiket-dev/kiket/sdk/goQuick 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: mediumWebhook 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(), nilOutput 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:
- Payload secrets (per-org configuration from
payload["secrets"]) - 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 telemetryKIKET_SECRET_*- Override secret values (whenAutoEnvSecrets: true)
License
MIT License - see LICENSE for details.