api

package
v0.2.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 7, 2026 License: MIT Imports: 11 Imported by: 0

Documentation

Overview

Package api is a thin, typed client over the panel's management API (/api/v1). It carries the bearer token and refreshes it transparently when it is about to expire.

Index

Constants

View Source
const (
	KindPublic = "public"
	KindSecret = "secret"
)

Write-key kinds (non-negotiable #12): public keys identify the project in the browser; secret keys are backend-only.

Variables

This section is empty.

Functions

This section is empty.

Types

type APIKey

type APIKey struct {
	ID        int    `json:"id"`
	Kind      string `json:"kind"`
	Label     string `json:"label"`
	Key       string `json:"key"`
	CreatedAt string `json:"created_at"`
}

APIKey is a project write key. Key is masked on list, full on create.

type Campaign added in v0.2.0

type Campaign struct {
	Slug                    string         `json:"slug" yaml:"slug"`
	Name                    string         `json:"name" yaml:"name"`
	Status                  string         `json:"status" yaml:"status"`
	Cohort                  string         `json:"cohort,omitempty" yaml:"cohort,omitempty"`
	ExitEvent               string         `json:"exit_event,omitempty" yaml:"exit_event,omitempty"`
	Reentry                 string         `json:"reentry" yaml:"reentry"`
	ReentryDays             *int           `json:"reentry_days,omitempty" yaml:"reentry_days,omitempty"`
	FrequencyCap            *int           `json:"frequency_cap,omitempty" yaml:"frequency_cap,omitempty"`
	FrequencyCapWindowHours *int           `json:"frequency_cap_window_hours,omitempty" yaml:"frequency_cap_window_hours,omitempty"`
	FromName                string         `json:"from_name,omitempty" yaml:"from_name,omitempty"`
	ReplyToEmail            string         `json:"reply_to_email,omitempty" yaml:"reply_to_email,omitempty"`
	QuietHours              map[string]any `json:"quiet_hours,omitempty" yaml:"quiet_hours,omitempty"`
	Nodes                   []CampaignNode `json:"nodes" yaml:"nodes"`
	Edges                   []CampaignEdge `json:"edges" yaml:"edges"`
	UpdatedAt               string         `json:"updated_at,omitempty" yaml:"-"`
}

Campaign is a messaging flow (docs/57). Cohort names a cohort by ITS slug, never a uuid, so one document applies to more than one project.

type CampaignEdge added in v0.2.0

type CampaignEdge struct {
	From    string `json:"from" yaml:"from"`
	To      string `json:"to" yaml:"to"`
	Outcome string `json:"outcome,omitempty" yaml:"outcome,omitempty"`
}

CampaignEdge wires two nodes by key. Outcome defaults to "next"; branch arms are yes/no and split arms carry their variant ("split:<key>").

type CampaignNode added in v0.2.0

type CampaignNode struct {
	Key    string         `json:"key" yaml:"key"`
	Type   string         `json:"type" yaml:"type"`
	Config map[string]any `json:"config" yaml:"config"`
}

CampaignNode is one step of a campaign's flow. Key is its stable identity WITHIN the campaign: the engine's node id is derived from it (uuid v5), so renaming a key really is a different node — and re-applying an unchanged document leaves every in-flight journey exactly where it was (docs/57 §2).

type Catalog

type Catalog struct {
	Events []struct {
		Name  string `json:"name"`
		Count int    `json:"count"`
	} `json:"events"`
	Properties []struct {
		Key   string `json:"key"`
		Count int    `json:"count"`
	} `json:"properties"`
}

Catalog is the observed event names and property keys for a project.

type Client

type Client struct {
	// contains filtered or unexported fields
}

Client talks to one panel as one signed-in user.

func New

func New(creds *config.Credentials) *Client

New builds a client around stored credentials.

func (*Client) ApplyCampaign added in v0.2.0

func (c *Client) ApplyCampaign(ctx context.Context, projectID string, spec Campaign) (*Campaign, error)

func (*Client) ApplyCohort added in v0.2.0

func (c *Client) ApplyCohort(ctx context.Context, projectID string, spec Cohort) (*Cohort, error)

func (*Client) ApplyExperiment added in v0.2.0

func (c *Client) ApplyExperiment(ctx context.Context, projectID string, spec Experiment) (*Experiment, error)

func (*Client) ApplyFlag added in v0.2.0

func (c *Client) ApplyFlag(ctx context.Context, projectID string, spec Flag) (*Flag, error)

func (*Client) ApplyInsight added in v0.2.0

func (c *Client) ApplyInsight(ctx context.Context, projectID, slug string, spec Insight) (*Insight, error)

ApplyInsight upserts an insight by slug (idempotent create-or-update) and returns the stored form.

func (*Client) ApplyUnit added in v0.2.0

func (c *Client) ApplyUnit(ctx context.Context, projectID string, spec Unit) (*Unit, error)

func (*Client) Campaign added in v0.2.0

func (c *Client) Campaign(ctx context.Context, projectID, slug string) (*Campaign, error)

func (*Client) Campaigns added in v0.2.0

func (c *Client) Campaigns(ctx context.Context, projectID string) ([]Campaign, error)

func (*Client) Catalog

func (c *Client) Catalog(ctx context.Context, projectID string) (*Catalog, error)

Catalog returns the observed event names and property keys for a project.

func (*Client) Cohort added in v0.2.0

func (c *Client) Cohort(ctx context.Context, projectID, slug string) (*Cohort, error)

func (*Client) Cohorts added in v0.2.0

func (c *Client) Cohorts(ctx context.Context, projectID string) ([]Cohort, error)

Cohorts lists a project's config-as-code cohorts. Cohorts created in the panel carry no slug and are not returned here.

func (*Client) Context

func (c *Client) Context(ctx context.Context) (*Context, error)

Context returns the active team + project.

func (*Client) CreateIdentitySecret added in v0.2.0

func (c *Client) CreateIdentitySecret(ctx context.Context, projectID, kid string) (*IdentitySecret, error)

CreateIdentitySecret mints a secret under kid. The full value is only ever returned here.

func (*Client) CreateKey

func (c *Client) CreateKey(ctx context.Context, projectID, kind, label string) (*APIKey, error)

CreateKey mints a write key. The full value is only ever returned here.

func (*Client) CreateProject

func (c *Client) CreateProject(ctx context.Context, teamID int, name, timezone string) (*Project, error)

CreateProject creates a project inside a team.

func (*Client) DeleteCampaign added in v0.2.0

func (c *Client) DeleteCampaign(ctx context.Context, projectID, slug string) error

func (*Client) DeleteCohort added in v0.2.0

func (c *Client) DeleteCohort(ctx context.Context, projectID, slug string) error

func (*Client) DeleteExperiment added in v0.2.0

func (c *Client) DeleteExperiment(ctx context.Context, projectID, key string) error

func (*Client) DeleteFlag added in v0.2.0

func (c *Client) DeleteFlag(ctx context.Context, projectID, key string) error

func (*Client) DeleteInsight added in v0.2.0

func (c *Client) DeleteInsight(ctx context.Context, projectID, slug string) error

DeleteInsight removes a saved insight by slug.

func (*Client) DeleteUnit added in v0.2.0

func (c *Client) DeleteUnit(ctx context.Context, projectID, slug string) error

func (*Client) DisableIdentitySecret added in v0.2.0

func (c *Client) DisableIdentitySecret(ctx context.Context, projectID string, id int) (*IdentitySecret, error)

DisableIdentitySecret revokes a secret by id; the enricher stops accepting its kid within one refresh.

func (*Client) Events

func (c *Client) Events(ctx context.Context, projectID string, filters url.Values) (*EventsPage, error)

Events returns recent events for a project, newest first.

func (*Client) Experiment added in v0.2.0

func (c *Client) Experiment(ctx context.Context, projectID, key string) (*Experiment, error)

func (*Client) Experiments added in v0.2.0

func (c *Client) Experiments(ctx context.Context, projectID string) ([]Experiment, error)

func (*Client) Flag added in v0.2.0

func (c *Client) Flag(ctx context.Context, projectID, key string) (*Flag, error)

func (*Client) Flags added in v0.2.0

func (c *Client) Flags(ctx context.Context, projectID string) ([]Flag, error)

Flags lists a project's feature flags. Unlike the slugged resources this is ALL of them: `key` is the table's real identity, so config-as-code and the panel address the same rows (docs/56 §3.1).

func (*Client) IdentitySecrets added in v0.2.0

func (c *Client) IdentitySecrets(ctx context.Context, projectID string) ([]IdentitySecret, error)

IdentitySecrets lists a project's identity-verification secrets. The secret value itself is never returned here — only kid, timestamps and revoked state.

func (*Client) Insight added in v0.2.0

func (c *Client) Insight(ctx context.Context, projectID, slug string) (*Insight, error)

Insight returns one saved insight by slug.

func (*Client) Insights added in v0.2.0

func (c *Client) Insights(ctx context.Context, projectID string) ([]Insight, error)

Insights lists a project's config-as-code (slugged) insights. Insights created in the panel carry no slug and are not returned here.

func (*Client) Keys

func (c *Client) Keys(ctx context.Context, projectID string) ([]APIKey, error)

Keys lists a project's active write keys (secret keys are masked).

func (*Client) LivetailTicket added in v0.2.0

func (c *Client) LivetailTicket(ctx context.Context, projectID string) (*LivetailTicket, error)

LivetailTicket mints a short-lived ticket for the live-tail websocket.

func (*Client) MaterializeCohort added in v0.2.0

func (c *Client) MaterializeCohort(ctx context.Context, projectID, slug string) (*Cohort, error)

MaterializeCohort recomputes membership now instead of waiting out the sweep.

func (*Client) Project

func (c *Client) Project(ctx context.Context, projectID string) (*Project, error)

Project returns one project.

func (*Client) Projects

func (c *Client) Projects(ctx context.Context, teamID int) ([]Project, error)

Projects lists the projects of a team.

func (*Client) SwitchProject

func (c *Client) SwitchProject(ctx context.Context, projectID string) (*Context, error)

SwitchProject sets the active project (and pulls its team along).

func (*Client) SwitchTeam

func (c *Client) SwitchTeam(ctx context.Context, teamID int) (*Context, error)

SwitchTeam sets the active team.

func (*Client) Teams

func (c *Client) Teams(ctx context.Context) ([]Team, error)

Teams lists the user's teams.

func (*Client) Unit added in v0.2.0

func (c *Client) Unit(ctx context.Context, projectID, slug string) (*Unit, error)

func (*Client) Units added in v0.2.0

func (c *Client) Units(ctx context.Context, projectID string) ([]Unit, error)

func (*Client) Whoami

func (c *Client) Whoami(ctx context.Context) (*User, error)

Whoami returns the signed-in account and its current context.

type Cohort added in v0.2.0

type Cohort struct {
	Slug               string         `json:"slug" yaml:"slug"`
	Name               string         `json:"name" yaml:"name"`
	Definition         map[string]any `json:"definition" yaml:"definition"`
	MembersCount       int            `json:"members_count,omitempty" yaml:"-"`
	LastMaterializedAt string         `json:"last_materialized_at,omitempty" yaml:"-"`
	UpdatedAt          string         `json:"updated_at,omitempty" yaml:"-"`
}

Cohort is a materialized audience (docs/55). MembersCount and LastMaterializedAt are read-only.

type Context

type Context struct {
	Team    *Team    `json:"team"`
	Project *Project `json:"project"`
}

Context is the active team + project pair.

type Event

type Event struct {
	UUID             string `json:"uuid"`
	Event            string `json:"event"`
	DistinctID       string `json:"distinct_id"`
	PersonID         string `json:"person_id"`
	Properties       string `json:"properties"`
	Verified         int    `json:"verified"`
	VerificationMode string `json:"verification_mode"`
	Timestamp        string `json:"timestamp"`
}

Event is one row from the events explorer.

type EventsPage

type EventsPage struct {
	Events  []Event `json:"events"`
	Page    int     `json:"page"`
	PerPage int     `json:"perPage"`
	HasMore bool    `json:"hasMore"`
}

EventsPage is the paginated events response.

type Experiment added in v0.2.0

type Experiment struct {
	Key                     string           `json:"key" yaml:"key"`
	Flag                    string           `json:"flag" yaml:"flag"`
	Name                    string           `json:"name" yaml:"name"`
	Status                  string           `json:"status" yaml:"status"`
	Hypothesis              string           `json:"hypothesis,omitempty" yaml:"hypothesis,omitempty"`
	ControlVariant          string           `json:"control_variant" yaml:"control_variant"`
	AttributionWindowDays   int              `json:"attribution_window_days" yaml:"attribution_window_days"`
	MinimumDetectableEffect *float64         `json:"minimum_detectable_effect,omitempty" yaml:"minimum_detectable_effect,omitempty"`
	PrimaryMetric           map[string]any   `json:"primary_metric" yaml:"primary_metric"`
	SecondaryMetrics        []map[string]any `json:"secondary_metrics,omitempty" yaml:"secondary_metrics,omitempty"`
	GuardrailMetrics        []map[string]any `json:"guardrail_metrics,omitempty" yaml:"guardrail_metrics,omitempty"`
	UpdatedAt               string           `json:"updated_at,omitempty" yaml:"-"`
}

Experiment is a 1:1 lens over a multivariate flag (docs/59), which it names by the flag's key. A document can take it as far as `stopped`: concluding it and promoting a winner stay in the panel.

type Flag added in v0.2.0

type Flag struct {
	Key               string           `json:"key" yaml:"key"`
	Name              string           `json:"name" yaml:"name"`
	Active            bool             `json:"active" yaml:"active"`
	RolloutPercentage int              `json:"rollout_percentage" yaml:"rollout_percentage"`
	Filters           map[string]any   `json:"filters" yaml:"filters,omitempty"`
	Variants          []map[string]any `json:"variants,omitempty" yaml:"variants,omitempty"`
	UpdatedAt         string           `json:"updated_at,omitempty" yaml:"-"`
}

Flag is a feature flag (docs/56), addressed by the key the table already had. Variants nil means a boolean flag.

type IdentitySecret added in v0.2.0

type IdentitySecret struct {
	ID        int    `json:"id"`
	Kid       string `json:"kid"`
	Secret    string `json:"secret"`
	CreatedAt string `json:"created_at"`
	RevokedAt string `json:"revoked_at"`
}

IdentitySecret is a project's HS256 identity-verification secret. Secret is only present on create (shown once); listings omit it. RevokedAt is empty while the secret is active.

type Insight added in v0.2.0

type Insight struct {
	Slug      string         `json:"slug" yaml:"slug"`
	Type      string         `json:"type" yaml:"type"`
	Name      string         `json:"name" yaml:"name"`
	Config    map[string]any `json:"config" yaml:"config"`
	UpdatedAt string         `json:"updated_at,omitempty" yaml:"-"`
}

Insight is a saved insight managed as config-as-code, addressed by a stable slug so `kd apply` is idempotent. Config is the raw per-type parameter map (schema-less on the wire; the panel validates its shape). UpdatedAt is only populated on reads and is dropped from exported specs (yaml:"-").

type LiveEvent added in v0.2.0

type LiveEvent struct {
	UUID       string          `json:"uuid"`
	Event      string          `json:"event"`
	DistinctID string          `json:"distinct_id"`
	PersonID   string          `json:"person_id"`
	Timestamp  string          `json:"timestamp"`
	Verified   bool            `json:"verified"`
	Source     string          `json:"source"`
	Properties json.RawMessage `json:"properties"`
}

LiveEvent is one frame from the live-tail websocket (one event per frame).

type LivetailTicket added in v0.2.0

type LivetailTicket struct {
	Ticket    string `json:"ticket"`
	URL       string `json:"url"`
	ExpiresAt string `json:"expires_at"`
}

LivetailTicket gates the live-tail websocket handshake. The ticket is a short-lived (≤60s) HS256 JWT; url is the websocket endpoint to dial.

type Project

type Project struct {
	ID                       string `json:"id"`
	Name                     string `json:"name"`
	TeamID                   int    `json:"team_id"`
	Timezone                 string `json:"timezone"`
	IdentityVerificationMode string `json:"identity_verification_mode"`
	// Activated is true once a REAL event has landed — the panel excludes its
	// own test button, so this never congratulates somebody for a button we
	// pressed for them. It is what `kd init` waits on.
	Activated bool   `json:"activated"`
	PublicKey string `json:"public_key"`
	CreatedAt string `json:"created_at"`
}

Project carries the summary fields the API returns. current_project on the user/context payloads only fills ID and Name; the project endpoints fill the rest.

type Team

type Team struct {
	ID         int    `json:"id"`
	Name       string `json:"name"`
	Slug       string `json:"slug"`
	IsPersonal bool   `json:"isPersonal"`
	Role       string `json:"role"`
	RoleLabel  string `json:"roleLabel"`
	IsCurrent  bool   `json:"isCurrent"`
}

Team mirrors the panel's UserTeam DTO (camelCase keys, straight from response()->json).

type Unit added in v0.2.0

type Unit struct {
	Slug              string         `json:"slug" yaml:"slug"`
	Type              string         `json:"type" yaml:"type"`
	Name              string         `json:"name" yaml:"name"`
	Status            string         `json:"status" yaml:"status"`
	Content           map[string]any `json:"content" yaml:"content"`
	Targeting         map[string]any `json:"targeting" yaml:"targeting,omitempty"`
	RolloutPercentage int            `json:"rollout_percentage" yaml:"rollout_percentage"`
	Display           map[string]any `json:"display" yaml:"display,omitempty"`
	StartsAt          string         `json:"starts_at,omitempty" yaml:"starts_at,omitempty"`
	EndsAt            string         `json:"ends_at,omitempty" yaml:"ends_at,omitempty"`
	UpdatedAt         string         `json:"updated_at,omitempty" yaml:"-"`
}

Unit is an in-app unit or tour (docs/58). Type is honoured on create only: content is typed BY type, so changing it in place is refused with 409.

type User

type User struct {
	ID             int      `json:"id"`
	Name           string   `json:"name"`
	Email          string   `json:"email"`
	CurrentTeam    *Team    `json:"current_team"`
	CurrentProject *Project `json:"current_project"`
}

User is the whoami payload.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL