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
- type APIKey
- type Campaign
- type CampaignEdge
- type CampaignNode
- type Catalog
- type Client
- func (c *Client) ApplyCampaign(ctx context.Context, projectID string, spec Campaign) (*Campaign, error)
- func (c *Client) ApplyCohort(ctx context.Context, projectID string, spec Cohort) (*Cohort, error)
- func (c *Client) ApplyExperiment(ctx context.Context, projectID string, spec Experiment) (*Experiment, error)
- func (c *Client) ApplyFlag(ctx context.Context, projectID string, spec Flag) (*Flag, error)
- func (c *Client) ApplyInsight(ctx context.Context, projectID, slug string, spec Insight) (*Insight, error)
- func (c *Client) ApplyUnit(ctx context.Context, projectID string, spec Unit) (*Unit, error)
- func (c *Client) Campaign(ctx context.Context, projectID, slug string) (*Campaign, error)
- func (c *Client) Campaigns(ctx context.Context, projectID string) ([]Campaign, error)
- func (c *Client) Catalog(ctx context.Context, projectID string) (*Catalog, error)
- func (c *Client) Cohort(ctx context.Context, projectID, slug string) (*Cohort, error)
- func (c *Client) Cohorts(ctx context.Context, projectID string) ([]Cohort, error)
- func (c *Client) Context(ctx context.Context) (*Context, error)
- func (c *Client) CreateIdentitySecret(ctx context.Context, projectID, kid string) (*IdentitySecret, error)
- func (c *Client) CreateKey(ctx context.Context, projectID, kind, label string) (*APIKey, error)
- func (c *Client) CreateProject(ctx context.Context, teamID int, name, timezone string) (*Project, error)
- func (c *Client) DeleteCampaign(ctx context.Context, projectID, slug string) error
- func (c *Client) DeleteCohort(ctx context.Context, projectID, slug string) error
- func (c *Client) DeleteExperiment(ctx context.Context, projectID, key string) error
- func (c *Client) DeleteFlag(ctx context.Context, projectID, key string) error
- func (c *Client) DeleteInsight(ctx context.Context, projectID, slug string) error
- func (c *Client) DeleteUnit(ctx context.Context, projectID, slug string) error
- func (c *Client) DisableIdentitySecret(ctx context.Context, projectID string, id int) (*IdentitySecret, error)
- func (c *Client) Events(ctx context.Context, projectID string, filters url.Values) (*EventsPage, error)
- func (c *Client) Experiment(ctx context.Context, projectID, key string) (*Experiment, error)
- func (c *Client) Experiments(ctx context.Context, projectID string) ([]Experiment, error)
- func (c *Client) Flag(ctx context.Context, projectID, key string) (*Flag, error)
- func (c *Client) Flags(ctx context.Context, projectID string) ([]Flag, error)
- func (c *Client) IdentitySecrets(ctx context.Context, projectID string) ([]IdentitySecret, error)
- func (c *Client) Insight(ctx context.Context, projectID, slug string) (*Insight, error)
- func (c *Client) Insights(ctx context.Context, projectID string) ([]Insight, error)
- func (c *Client) Keys(ctx context.Context, projectID string) ([]APIKey, error)
- func (c *Client) LivetailTicket(ctx context.Context, projectID string) (*LivetailTicket, error)
- func (c *Client) MaterializeCohort(ctx context.Context, projectID, slug string) (*Cohort, error)
- func (c *Client) Project(ctx context.Context, projectID string) (*Project, error)
- func (c *Client) Projects(ctx context.Context, teamID int) ([]Project, error)
- func (c *Client) SwitchProject(ctx context.Context, projectID string) (*Context, error)
- func (c *Client) SwitchTeam(ctx context.Context, teamID int) (*Context, error)
- func (c *Client) Teams(ctx context.Context) ([]Team, error)
- func (c *Client) Unit(ctx context.Context, projectID, slug string) (*Unit, error)
- func (c *Client) Units(ctx context.Context, projectID string) ([]Unit, error)
- func (c *Client) Whoami(ctx context.Context) (*User, error)
- type Cohort
- type Context
- type Event
- type EventsPage
- type Experiment
- type Flag
- type IdentitySecret
- type Insight
- type LiveEvent
- type LivetailTicket
- type Project
- type Team
- type Unit
- type User
Constants ¶
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 (*Client) ApplyCohort ¶ added in v0.2.0
func (*Client) ApplyExperiment ¶ added in v0.2.0
func (c *Client) ApplyExperiment(ctx context.Context, projectID string, spec Experiment) (*Experiment, 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) Cohorts ¶ added in v0.2.0
Cohorts lists a project's config-as-code cohorts. Cohorts created in the panel carry no slug and are not returned here.
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) 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 (*Client) DeleteCohort ¶ added in v0.2.0
func (*Client) DeleteExperiment ¶ added in v0.2.0
func (*Client) DeleteFlag ¶ added in v0.2.0
func (*Client) DeleteInsight ¶ added in v0.2.0
DeleteInsight removes a saved insight by slug.
func (*Client) DeleteUnit ¶ added in v0.2.0
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 (*Client) Experiments ¶ added in v0.2.0
func (*Client) Flags ¶ added in v0.2.0
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
IdentitySecrets lists a project's identity-verification secrets. The secret value itself is never returned here — only kid, timestamps and revoked state.
func (*Client) Insights ¶ added in v0.2.0
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) LivetailTicket ¶ added in v0.2.0
LivetailTicket mints a short-lived ticket for the live-tail websocket.
func (*Client) MaterializeCohort ¶ added in v0.2.0
MaterializeCohort recomputes membership now instead of waiting out the sweep.
func (*Client) SwitchProject ¶
SwitchProject sets the active project (and pulls its team along).
func (*Client) SwitchTeam ¶
SwitchTeam sets the active team.
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 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.