client

package module
v1.10.0 Latest Latest
Warning

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

Go to latest
Published: Sep 10, 2026 License: MIT Imports: 16 Imported by: 0

Documentation

Overview

Package client is the first-party Go client for a standalone flexitype service. It mirrors the embedded usecase surface — Types, Attributes, Values, Query, Relationships and the rest — over the versioned REST API, so code that talks to a remote flexitype reads almost the same as code that embeds it.

c, _ := client.New("https://flexitype.internal", client.WithToken(tok))
prod, err := c.Types().Create(ctx, client.CreateTypeInput{InternalName: "product", DisplayName: "Product"})
for row, err := range c.Query(ctx, "product", `price > 10`) { ... }

Conventions

A method that returns a pointer returns nil on error. Check the error, not the pointer. (Some methods used to return a pointer to a zero value alongside the error, so code that nil-checked instead of error-checking carried on with an empty id and zero timestamps — a bug that surfaced far from here.)

Retrying is opt-in, through WithRetry. It applies only to idempotent methods, so a POST that may already have been applied is never replayed. A 429 carries the server's Retry-After in APIError.RetryAfter, and the retry loop honours it over its own backoff.

Listing is forward-only keyset pagination. PageInfo.HasPreviousPage says a previous page exists but the API has no backward cursor; keep the cursors you visited, or use CursorStack.

The client depends only on the standard library.

Index

Constants

This section is empty.

Variables

View Source
var (
	ErrValidation          = &APIError{Code: CodeValidation}
	ErrNotFound            = &APIError{Code: CodeNotFound}
	ErrConflict            = &APIError{Code: CodeConflict}
	ErrArchived            = &APIError{Code: CodeArchived}
	ErrDependencyViolation = &APIError{Code: CodeDependencyViolation}
	ErrUnauthenticated     = &APIError{Code: CodeUnauthenticated}
	ErrForbidden           = &APIError{Code: CodeForbidden}
	ErrRateLimited         = &APIError{Code: CodeRateLimited}
	ErrInternal            = &APIError{Code: CodeInternal}
	ErrFeatureDisabled     = &APIError{Code: CodeFeatureDisabled}
	ErrCursorConflict      = &APIError{Code: CodeCursorConflict}
	ErrCursorExpired       = &APIError{Code: CodeCursorExpired}
)

Sentinels for errors.Is. Each matches an APIError with the corresponding code, so callers can branch without unwrapping:

if errors.Is(err, client.ErrNotFound) { ... }

Functions

This section is empty.

Types

type APIError

type APIError struct {
	// Status is the HTTP status code (0 for a sentinel).
	Status int
	// Code is the stable error code.
	Code ErrorCode
	// Message is the human-readable message.
	Message string
	// Details is the optional machine-readable context.
	Details map[string]any

	// RetryAfter is how long the server asked the caller to wait before
	// retrying, parsed from the Retry-After header. It is zero when the
	// server sent no hint. The server sets it on every throttle, and it was
	// dropped: callers saw RATE_LIMITED with no wait hint and either failed
	// outright or invented their own backoff.
	RetryAfter time.Duration
}

APIError is a structured error returned by the service. Details carries the machine-readable context the server attached (constraint names, field names, positions).

func (*APIError) Error

func (e *APIError) Error() string

Error implements error.

func (*APIError) Is

func (e *APIError) Is(target error) bool

Is lets errors.Is match by code, so a sentinel (ErrNotFound) matches any APIError carrying that code regardless of message, status or details.

type ActivityEntry

type ActivityEntry struct {
	ID         string          `json:"id"`
	TenantID   string          `json:"tenant_id"`
	Actor      string          `json:"actor"`
	Entity     string          `json:"entity"`
	EntityID   string          `json:"entity_id"`
	Action     string          `json:"action"`
	Before     json.RawMessage `json:"before,omitempty"`
	After      json.RawMessage `json:"after,omitempty"`
	OccurredAt time.Time       `json:"occurred_at"`
}

ActivityEntry is one audit-log record.

type ActivityService

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

ActivityService reads the audit log.

func (*ActivityService) All

All iterates every audit entry across pages.

func (*ActivityService) List

List returns one page of audit entries (newest first).

type AdminService

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

AdminService provisions tenants and service accounts (admin-scoped; database-backed deployments only).

func (*AdminService) AssignRoles added in v1.3.0

func (s *AdminService) AssignRoles(ctx context.Context, id string, in AssignRolesInput) error

AssignRoles replaces a service account's roles and per-account overrides. The server evicts the account's auth-cache entry, so a removed permission stops applying at once rather than at the end of the cache TTL.

func (*AdminService) CreateServiceAccount

func (s *AdminService) CreateServiceAccount(ctx context.Context, in CreateServiceAccountInput) (*ServiceAccount, error)

CreateServiceAccount provisions a service account and returns its one-time token.

func (*AdminService) CreateTenant

func (s *AdminService) CreateTenant(ctx context.Context, name string) (*Tenant, error)

CreateTenant provisions a tenant.

func (*AdminService) DeleteRole added in v1.3.0

func (s *AdminService) DeleteRole(ctx context.Context, tenant, name string) error

DeleteRole removes a role.

It is refused with ErrorCodeConflict while any account still names the role: a role that resolves to nothing grants no field permissions, and an empty permission map reads as unrestricted, so deleting a held role would hand out every attribute it was hiding. Reassign those accounts first with AssignRoles.

func (*AdminService) EffectiveAccount added in v1.3.0

func (s *AdminService) EffectiveAccount(ctx context.Context, id string) (*EffectiveAccount, error)

EffectiveAccount reports what an account can actually do: its own scopes unioned with its roles', and the merged per-attribute permissions.

ListServiceAccounts and ListRoles report what is STORED, which is what you edit. This reports what the enforcement path computes. A non-empty UnresolvedRoles is a fault: such an account is denied every attribute.

func (*AdminService) ListParkedOutbox added in v1.5.0

func (s *AdminService) ListParkedOutbox(ctx context.Context, filter ParkedFilter, opts ...ListOptions) (*Page[ParkedEnvelope], error)

ListParkedOutbox pages the tenant's parked outbox envelopes, oldest first. Admin scope. Alert on the flexitype_outbox_parked gauge, inspect the backlog here, and redrive before the parked retention deletes it.

func (*AdminService) ListRoles added in v1.3.0

func (s *AdminService) ListRoles(ctx context.Context, tenant string) ([]Role, error)

ListRoles returns one tenant's roles. tenant is required: the endpoint has no cross-tenant listing.

func (*AdminService) ListServiceAccounts

func (s *AdminService) ListServiceAccounts(ctx context.Context, tenant string) ([]ServiceAccount, error)

ListServiceAccounts returns one tenant's service accounts. tenant is required: the endpoint has no cross-tenant listing.

The query parameter is `tenant_name`. An earlier version sent `tenant`, which the server ignored, so the call answered "tenant_name is required" whether or not a tenant was passed.

func (*AdminService) ListTenants

func (s *AdminService) ListTenants(ctx context.Context) ([]Tenant, error)

ListTenants returns the provisioned tenants.

func (*AdminService) RedriveOutbox added in v1.5.0

func (s *AdminService) RedriveOutbox(ctx context.Context, filter ParkedFilter) (int, error)

RedriveOutbox returns the matching parked envelopes to the retry queue and reports how many it moved. Admin scope.

The redrive resets each envelope's attempt count — a fresh retry budget, as with the dead-letter redrive — and delivery restarts immediately. Consumers must dedupe on the envelope id, as with every redelivery. An empty filter redrives the tenant's whole parked backlog.

func (*AdminService) RevokeServiceAccount

func (s *AdminService) RevokeServiceAccount(ctx context.Context, id string) error

RevokeServiceAccount deletes a service account.

func (*AdminService) RotateServiceAccount

func (s *AdminService) RotateServiceAccount(ctx context.Context, id string) (*ServiceAccount, error)

RotateServiceAccount issues a new token for a service account.

func (*AdminService) SetTenantActive

func (s *AdminService) SetTenantActive(ctx context.Context, name string, active bool) (*Tenant, error)

SetTenantActive enables or disables a tenant.

func (*AdminService) UpsertRole added in v1.3.0

func (s *AdminService) UpsertRole(ctx context.Context, in UpsertRoleInput) (*Role, error)

UpsertRole creates or replaces a role.

type AppliedDefault added in v1.5.0

type AppliedDefault struct {
	AttributeDefinitionID string `json:"attribute_definition_id"`
	InternalName          string `json:"internal_name"`
	Value                 string `json:"value"`
}

AppliedDefault names one attribute an apply-defaults run seeded.

type AppliedDefaults added in v1.5.0

type AppliedDefaults struct {
	EntityID string           `json:"entity_id"`
	Applied  []AppliedDefault `json:"applied"`
	Skipped  int              `json:"skipped"`
}

AppliedDefaults reports what one apply-defaults run seeded. Skipped counts the declared defaults the entity already satisfied.

type AssignRolesInput added in v1.3.0

type AssignRolesInput struct {
	Roles            []string          `json:"roles"`
	FieldPermissions map[string]string `json:"field_permissions"`
}

AssignRolesInput replaces an account's roles and its own overrides. Both lists are replaced, so an empty slice clears them.

type AttributeDefinition

type AttributeDefinition struct {
	ID               string        `json:"id"`
	TenantID         string        `json:"tenant_id"`
	TypeDefinitionID string        `json:"type_definition_id"`
	InternalName     string        `json:"internal_name"`
	DisplayName      string        `json:"display_name"`
	Description      string        `json:"description,omitempty"`
	DataType         string        `json:"data_type"`
	Required         bool          `json:"required"`
	MultiValued      bool          `json:"multi_valued"`
	Unique           bool          `json:"unique"`
	Localizable      bool          `json:"localizable,omitempty"`
	Scopable         bool          `json:"scopable,omitempty"`
	UnitFamilyID     string        `json:"unit_family_id,omitempty"`
	DisplayUnit      string        `json:"display_unit,omitempty"`
	Computed         *ComputedSpec `json:"computed,omitempty"`
	Constraints      []Constraint  `json:"constraints"`
	DefaultValue     *DefaultValue `json:"default_value,omitempty"`
	Group            string        `json:"group,omitempty"`
	SortOrder        int           `json:"sort_order"`
	HelpText         string        `json:"help_text,omitempty"`
	Version          int           `json:"version"`
	CreatedAt        time.Time     `json:"created_at"`
	UpdatedAt        time.Time     `json:"updated_at"`
	ArchivedAt       *time.Time    `json:"archived_at,omitempty"`
}

AttributeDefinition is a typed, constrained attribute on a type.

type AttributeValue

type AttributeValue struct {
	ID                    string          `json:"id"`
	TenantID              string          `json:"tenant_id"`
	TypeDefinitionID      string          `json:"type_definition_id"`
	AttributeDefinitionID string          `json:"attribute_definition_id"`
	EntityID              string          `json:"entity_id"`
	Locale                string          `json:"locale,omitempty"`
	Channel               string          `json:"channel,omitempty"`
	Value                 json.RawMessage `json:"value"`
	DefinitionVersion     int             `json:"definition_version"`
	CreatedAt             time.Time       `json:"created_at"`
	UpdatedAt             time.Time       `json:"updated_at"`
	ArchivedAt            *time.Time      `json:"archived_at,omitempty"`
}

AttributeValue is one stored value. Value is the raw JSON payload (its shape follows the attribute's data type).

type AttributesService

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

AttributesService operates on attribute definitions.

func (*AttributesService) All

All iterates every attribute across pages.

func (*AttributesService) Archive

Archive soft-deletes an attribute definition.

func (*AttributesService) Create

Create creates an attribute definition.

func (*AttributesService) Get

Get loads one attribute definition.

func (*AttributesService) List

List returns one page of attribute definitions.

func (*AttributesService) Restore

Restore reverses an archive.

func (*AttributesService) Update

Update mutates an attribute definition.

func (*AttributesService) ValidateValue

func (s *AttributesService) ValidateValue(ctx context.Context, id string, value json.RawMessage) error

ValidateValue dry-runs a raw JSON value against an attribute — parse, type check and constraints, nothing persisted. It returns nil when valid and a *APIError (code VALIDATION) otherwise.

type ChangeSet

type ChangeSet struct {
	ID       string `json:"id"`
	TenantID string `json:"tenant_id"`
	// Name is the change-set's label. The server emits "name"; this field
	// was declared as "title", so it never populated and every change-set
	// read back with a blank label.
	Name            string          `json:"name"`
	State           string          `json:"state"`
	RequireApproval bool            `json:"require_approval"`
	Author          string          `json:"author,omitempty"`
	Approver        string          `json:"approver,omitempty"`
	Mutations       json.RawMessage `json:"mutations,omitempty"`
	PublishAt       *time.Time      `json:"publish_at,omitempty"`
	PublishedAt     *time.Time      `json:"published_at,omitempty"`
	CreatedAt       time.Time       `json:"created_at"`
	UpdatedAt       time.Time       `json:"updated_at"`

	// Title mirrors Name.
	//
	// Deprecated: the server has no "title" field and never sent one, so
	// this was always empty. It is populated from "name" so that code
	// written against it keeps compiling and now reads a real value. Use
	// Name; Title is removed in the next major version of this module.
	Title string `json:"-"`
}

ChangeSet is a staged batch of value edits moving through review.

func (*ChangeSet) UnmarshalJSON added in v1.3.0

func (c *ChangeSet) UnmarshalJSON(b []byte) error

UnmarshalJSON decodes a change-set and mirrors Name onto the deprecated Title field.

type ChangeSetsService

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

ChangeSetsService operates on staged change-sets.

func (*ChangeSetsService) AddMutation

func (s *ChangeSetsService) AddMutation(ctx context.Context, id string, m Mutation) (*ChangeSet, error)

AddMutation stages one value change on a draft change-set.

func (*ChangeSetsService) Approve

func (s *ChangeSetsService) Approve(ctx context.Context, id string) (*ChangeSet, error)

Approve approves a change-set in review (must be a different actor than the author).

func (*ChangeSetsService) Create

Create opens a change-set.

func (*ChangeSetsService) Get

func (s *ChangeSetsService) Get(ctx context.Context, id string) (*ChangeSet, error)

Get loads one change-set.

func (*ChangeSetsService) List

func (s *ChangeSetsService) List(ctx context.Context) ([]ChangeSet, error)

List returns the tenant's change-sets.

func (*ChangeSetsService) Publish

func (s *ChangeSetsService) Publish(ctx context.Context, id string) (*ChangeSet, error)

Publish applies an approved change-set's mutations now.

func (*ChangeSetsService) Reject

func (s *ChangeSetsService) Reject(ctx context.Context, id string) (*ChangeSet, error)

Reject rejects a change-set.

func (*ChangeSetsService) Submit

func (s *ChangeSetsService) Submit(ctx context.Context, id string) (*ChangeSet, error)

Submit moves a draft into review.

type Client

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

Client talks to a standalone flexitype service's REST API. It is safe for concurrent use.

func New

func New(baseURL string, opts ...Option) (*Client, error)

New builds a client for the service at baseURL (its root, e.g. "https://flexitype.internal:8080"); the "/api/v1" prefix is added automatically.

func (*Client) Activity

func (c *Client) Activity() *ActivityService

Activity returns audit-log operations.

func (*Client) Admin

func (c *Client) Admin() *AdminService

Admin returns tenant/service-account provisioning operations.

func (*Client) Attributes

func (c *Client) Attributes() *AttributesService

Attributes returns the attribute-definition operations.

func (*Client) ChangeSets

func (c *Client) ChangeSets() *ChangeSetsService

ChangeSets returns the change-management operations.

func (*Client) Dependencies

func (c *Client) Dependencies() *DependenciesService

Dependencies returns the attribute-dependency operations.

func (*Client) DownloadMedia

func (c *Client) DownloadMedia(ctx context.Context, objectKey string) ([]byte, string, error)

DownloadMedia streams a stored media object by its key, returning the bytes and content type.

func (*Client) Entities

func (c *Client) Entities() *EntitiesService

Entities returns the entity-level operations (browse, grid, import/export, media, revisions).

func (*Client) Events

func (c *Client) Events() *EventsService

Events returns event-feed operations.

func (*Client) Features

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

Features fetches the deployment's enabled capabilities.

func (*Client) GraphQL

func (c *Client) GraphQL(ctx context.Context, query string, variables map[string]any, dst any) error

GraphQL runs a read-only GraphQL query and unmarshals data into dst (pass a pointer). variables may be nil. Query-level errors are returned as an error.

func (*Client) MatchRules

func (c *Client) MatchRules() *MatchRulesService

MatchRules returns duplicate-detection operations.

func (*Client) PurgeTenant added in v1.3.0

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

PurgeTenant permanently hard-deletes the calling tenant's whole entity dataset. Admin scope. Irreversible, and scoped to the token's tenant — there is no cross-tenant form.

func (*Client) Query

func (c *Client) Query(ctx context.Context, typ, fql string, opts ...QueryOptions) iter.Seq2[EntitySummary, error]

Query runs an FQL query and iterates every matching entity across pages:

for row, err := range c.Query(ctx, "product", `price > 100`) {
    if err != nil { return err }
    ...
}

func (*Client) QueryPage

func (c *Client) QueryPage(ctx context.Context, typ, fql string, opts ...QueryOptions) (*Page[EntitySummary], error)

QueryPage runs one page of an FQL query over the given root type.

func (*Client) RecomputeComputed added in v1.3.0

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

RecomputeComputed re-materializes every computed attribute for the caller's tenant and returns how many entities were rewritten. Admin scope.

Run it after changing a formula, or to recover from a failed recompute.

func (*Client) Reindex

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

Reindex rebuilds the search projection for the caller's tenant, returning the number of entities reindexed. Requires the search index feature.

func (*Client) RelationshipDefinitions

func (c *Client) RelationshipDefinitions() *RelationshipDefinitionsService

RelationshipDefinitions returns relationship-definition operations.

func (*Client) Relationships

func (c *Client) Relationships() *RelationshipsService

Relationships returns relationship (link) operations.

func (*Client) Revisions

func (c *Client) Revisions() *RevisionsService

Revisions returns the entity-revision operations.

func (*Client) SavedViews

func (c *Client) SavedViews() *SavedViewsService

SavedViews returns the saved-view operations.

func (*Client) Schema

func (c *Client) Schema() *SchemaService

Schema returns schema import/export and template operations.

func (*Client) SignMediaURL added in v1.6.0

func (c *Client) SignMediaURL(ctx context.Context, objectKey string, ttl time.Duration) (*SignedMediaURL, error)

SignMediaURL mints a signed, expiring link to one stored object.

Media bytes sit behind the same authentication as everything else, and the token carries the tenant, so a public surface — a storefront, a catalogue page, an email — cannot link to an image: it has to proxy every request through a service holding a tenant credential. A signed link removes that proxy. It is redeemed at the returned URL with NO credential, because the signature is the credential.

Minting a link changes nothing, so this is a GET: a read-only credential — including a cross-tenant reader — can mint one.

ttl is how long the link lasts. Zero takes the service's short default; anything above its maximum is capped rather than refused. The caller must be able to read the object, and a deployment with no signing secret reports the capability as disabled (501, FEATURE_DISABLED).

func (*Client) Types

func (c *Client) Types() *TypesService

Types returns the type-definition operations.

func (*Client) UnitFamilies

func (c *Client) UnitFamilies() *UnitFamiliesService

UnitFamilies returns the quantity unit-family operations.

func (*Client) ValidateQuery

func (c *Client) ValidateQuery(ctx context.Context, typ, fql string) error

ValidateQuery parses and binds an FQL query without running it, returning a *APIError (code VALIDATION, with a "position" detail) when it is invalid.

func (*Client) Values

func (c *Client) Values() *ValuesService

Values returns the value operations.

func (*Client) Webhooks

func (c *Client) Webhooks() *WebhooksService

Webhooks returns webhook-subscription and delivery operations.

type CloneResult

type CloneResult struct {
	Type         TypeDefinition `json:"type"`
	Attributes   int            `json:"attributes"`
	Dependencies int            `json:"dependencies"`
}

CloneResult reports a clone's outcome.

type Completeness

type Completeness struct {
	EntityID         string             `json:"entity_id"`
	TypeDefinitionID string             `json:"type_definition_id"`
	Required         int                `json:"required"`
	Filled           int                `json:"filled"`
	Score            float64            `json:"score"`
	Missing          []MissingAttribute `json:"missing"`
}

Completeness scores one entity against its effective required schema.

type ComputedSpec

type ComputedSpec struct {
	Kind    string `json:"kind"` // formula | rollup
	Formula string `json:"formula,omitempty"`
}

ComputedSpec makes an attribute derived rather than stored.

type Condition

type Condition struct {
	Kind   string       `json:"kind"`
	Value  *TypedValue  `json:"value,omitempty"`
	Values []TypedValue `json:"values,omitempty"`
	Min    *TypedValue  `json:"min,omitempty"`
	Max    *TypedValue  `json:"max,omitempty"`
	// MinExclusive/MaxExclusive turn a range bound strict: min becomes
	// "greater than" and max becomes "less than".
	MinExclusive bool   `json:"min_exclusive,omitempty"`
	MaxExclusive bool   `json:"max_exclusive,omitempty"`
	Pattern      string `json:"pattern,omitempty"`
	// PatternSubstring opts a pattern condition out of anchoring.
	PatternSubstring bool     `json:"pattern_substring,omitempty"`
	Dynamic          *Dynamic `json:"dynamic,omitempty"`
	Op               string   `json:"op,omitempty"`
	// ContextKey names a caller-supplied fact to test instead of the source
	// attribute's value.
	ContextKey string `json:"context_key,omitempty"`
}

Condition is one dependency condition.

type Constraint

type Constraint struct {
	Kind    string       `json:"kind"`
	N       *int         `json:"n,omitempty"`
	Value   *TypedValue  `json:"value,omitempty"`
	Expr    string       `json:"expr,omitempty"`
	Values  []TypedValue `json:"values,omitempty"`
	MIME    []string     `json:"mime,omitempty"`
	MaxSize *int64       `json:"max_size,omitempty"`
}

Constraint is one attribute constraint. Only the fields relevant to Kind are set (n for lengths, value for min/max, expr for pattern, values for one_of, mime/max_size for media).

type CreateAttributeInput

type CreateAttributeInput struct {
	TypeDefinitionID string          `json:"type_definition_id"`
	InternalName     string          `json:"internal_name"`
	DisplayName      string          `json:"display_name"`
	Description      string          `json:"description,omitempty"`
	DataType         string          `json:"data_type"`
	Required         bool            `json:"required,omitempty"`
	MultiValued      bool            `json:"multi_valued,omitempty"`
	Unique           bool            `json:"unique,omitempty"`
	Localizable      bool            `json:"localizable,omitempty"`
	Scopable         bool            `json:"scopable,omitempty"`
	UnitFamilyID     string          `json:"unit_family_id,omitempty"`
	DisplayUnit      string          `json:"display_unit,omitempty"`
	Computed         json.RawMessage `json:"computed,omitempty"`
	Constraints      json.RawMessage `json:"constraints,omitempty"`
	DefaultValue     json.RawMessage `json:"default_value,omitempty"`
	Group            string          `json:"group,omitempty"`
	SortOrder        int             `json:"sort_order,omitempty"`
	HelpText         string          `json:"help_text,omitempty"`
}

CreateAttributeInput creates an attribute definition. Constraints, Computed and DefaultValue are raw JSON so any shape the server accepts passes through; build them with the Constraint / ComputedSpec / DefaultValue types or your own encoding.

type CreateChangeSetInput

type CreateChangeSetInput struct {
	Name            string  `json:"name"`
	RequireApproval bool    `json:"require_approval,omitempty"`
	PublishAt       *string `json:"publish_at,omitempty"` // RFC3339
}

CreateChangeSetInput opens a new change-set.

type CreateDependencyInput

type CreateDependencyInput struct {
	SourceAttributeID string          `json:"source_attribute_id"`
	TargetAttributeID string          `json:"target_attribute_id"`
	Conditions        json.RawMessage `json:"conditions,omitempty"`
	Effect            json.RawMessage `json:"effect,omitempty"`
	Description       string          `json:"description,omitempty"`

	// Version is the version the caller read, and applies to Update ONLY —
	// Create ignores it, because there is nothing to swap against. Set it on
	// an update to compare-and-swap: a write against a record somebody else
	// has since changed answers CONFLICT instead of overwriting it. Leave it
	// nil for last-write-wins.
	//
	// It lives on the create input because Update takes the same type; that is
	// the SDK's existing shape and changing it would break callers.
	Version *int `json:"version,omitempty"`
}

CreateDependencyInput creates a dependency. Conditions and Effect are raw JSON (arrays/objects matching the wire schema).

type CreateMatchRuleInput

type CreateMatchRuleInput struct {
	AttributeDefinitionID string  `json:"attribute_definition_id"`
	Strategy              string  `json:"strategy"`
	Threshold             float64 `json:"threshold,omitempty"`
}

CreateMatchRuleInput adds a duplicate-detection rule.

type CreateRelationshipDefinitionInput

type CreateRelationshipDefinitionInput struct {
	InternalName        string `json:"internal_name"`
	DisplayName         string `json:"display_name"`
	Description         string `json:"description,omitempty"`
	Kind                string `json:"kind,omitempty"` // directed (default) | symmetric
	ParentTypeID        string `json:"parent_type_id"`
	ChildTypeID         string `json:"child_type_id"`
	ParentLabel         string `json:"parent_label,omitempty"`
	ChildLabel          string `json:"child_label,omitempty"`
	ExtendsID           string `json:"extends_id,omitempty"`
	ParentVersionPolicy string `json:"parent_version_policy,omitempty"`
	ChildVersionPolicy  string `json:"child_version_policy,omitempty"`
	MinChildren         *int   `json:"min_children,omitempty"`
	MaxChildren         *int   `json:"max_children,omitempty"`
	MinParents          *int   `json:"min_parents,omitempty"`
	MaxParents          *int   `json:"max_parents,omitempty"`

	// Version is the version the caller read, and applies to Update ONLY —
	// Create ignores it, because there is nothing to swap against. Set it on
	// an update to compare-and-swap: a write against a record somebody else
	// has since changed answers CONFLICT instead of overwriting it. Leave it
	// nil for last-write-wins.
	//
	// It lives on the create input because Update takes the same type; that is
	// the SDK's existing shape and changing it would break callers.
	Version *int `json:"version,omitempty"`
}

CreateRelationshipDefinitionInput creates a relationship definition.

type CreateServiceAccountInput

type CreateServiceAccountInput struct {
	TenantName string   `json:"tenant_name"`
	Name       string   `json:"name"`
	Scopes     []string `json:"scopes,omitempty"`
	// Roles the account holds from the start.
	Roles []string `json:"roles,omitempty"`
	// FieldPermissions are per-account overrides. Roles are the normal way
	// to grant a permission set; use this for one account that differs.
	FieldPermissions map[string]string `json:"field_permissions,omitempty"`
}

CreateServiceAccountInput provisions a credential. The returned Token is shown once.

type CreateTypeInput

type CreateTypeInput struct {
	InternalName string `json:"internal_name"`
	DisplayName  string `json:"display_name"`
	Description  string `json:"description,omitempty"`
	ExtendsID    string `json:"extends_id,omitempty"`
}

CreateTypeInput creates a type definition. ExtendsID makes it a subtype.

type CreateUnitFamilyInput

type CreateUnitFamilyInput struct {
	Name     string             `json:"name"`
	BaseUnit string             `json:"base_unit"`
	Units    map[string]float64 `json:"units"`
}

CreateUnitFamilyInput creates a unit family. The base unit must be present in Units with factor 1.

type CursorStack added in v1.3.0

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

CursorStack remembers the cursor of each page a caller has visited, so a paged UI can step backwards over a forward-only keyset API.

PageInfo.HasPreviousPage says a previous page exists but the API offers no way to ask for it, so every paged UI has to keep this state itself. The admin console does, in its own composable; this is the same thing for Go callers.

A CursorStack is not safe for concurrent use: it belongs to one view.

var st client.CursorStack
page, err := c.Types().List(ctx, client.ListOptions{Cursor: st.Current()})
// forward:
st.Push(page.PageInfo)
// backward:
st.Pop()

func (*CursorStack) Current added in v1.3.0

func (s *CursorStack) Current() string

Current returns the cursor for the page the stack is on. It is "" on the first page, which is what a list call wants there.

func (*CursorStack) Depth added in v1.3.0

func (s *CursorStack) Depth() int

Depth is the zero-based index of the page the stack is on.

func (*CursorStack) Pop added in v1.3.0

func (s *CursorStack) Pop() (string, bool)

Pop steps back one page and returns that page's cursor. It reports false on the first page, where there is nothing to go back to.

func (*CursorStack) Push added in v1.3.0

func (s *CursorStack) Push(info PageInfo) (string, bool)

Push records that the caller moved forward, and returns the cursor for the next page. It reports false when info has no next page, leaving the stack untouched — so a Next button at the end of a list is a no-op rather than an empty page.

type DefaultValue

type DefaultValue struct {
	Static  *TypedValue `json:"static,omitempty"`
	Dynamic *Dynamic    `json:"dynamic,omitempty"`
}

DefaultValue is an attribute's default, static or dynamic.

type DependenciesService

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

DependenciesService operates on attribute dependencies.

func (*DependenciesService) All

All iterates every dependency across pages.

func (*DependenciesService) Archive

func (s *DependenciesService) Archive(ctx context.Context, id string) error

Archive soft-deletes a dependency.

func (*DependenciesService) Create

Create creates a dependency.

func (*DependenciesService) Get

Get loads one dependency.

func (*DependenciesService) List

func (s *DependenciesService) List(ctx context.Context, opts ...ListOptions) (*Page[Dependency], error)

List returns one page of dependencies.

func (*DependenciesService) Update

Update mutates a dependency.

type Dependency

type Dependency struct {
	ID                string      `json:"id"`
	TenantID          string      `json:"tenant_id"`
	SourceAttributeID string      `json:"source_attribute_id"`
	TargetAttributeID string      `json:"target_attribute_id"`
	Conditions        []Condition `json:"conditions"`
	Effect            Effect      `json:"effect"`
	Description       string      `json:"description,omitempty"`
	Version           int         `json:"version"`
	CreatedAt         time.Time   `json:"created_at"`
	UpdatedAt         time.Time   `json:"updated_at"`
	ArchivedAt        *time.Time  `json:"archived_at,omitempty"`
}

Dependency is a conditional-validation / cascading-picklist rule.

type Dynamic

type Dynamic struct {
	Kind   string `json:"kind"` // now | today | relative_time
	Period string `json:"period,omitempty"`
	Amount int    `json:"amount,omitempty"`
}

Dynamic is a dynamic (time-relative) value.

type Effect

type Effect struct {
	AllowedValues []TypedValue `json:"allowed_values,omitempty"`
	Constraints   []Constraint `json:"constraints,omitempty"`
	Required      *bool        `json:"required,omitempty"`
	// Enforce says when a Required override is enforced: "on_write" refuses a
	// write that leaves the value absent, "on_read" (the default) reports the
	// gap through the effective schema and completeness instead.
	Enforce string `json:"enforce,omitempty"`
}

Effect is a dependency's effect on its target.

type EffectiveAccount added in v1.3.0

type EffectiveAccount struct {
	ID       string `json:"id"`
	TenantID string `json:"tenant_id,omitempty"`
	Name     string `json:"name"`
	Active   bool   `json:"active"`
	// Roles are the names the account holds, as stored.
	Roles []string `json:"roles,omitempty"`
	// Scopes are the account's own scopes unioned with its roles'.
	Scopes []string `json:"scopes"`
	// FieldPermissions are the merged per-attribute levels.
	FieldPermissions map[string]string `json:"field_permissions,omitempty"`
	// UnresolvedRoles names roles the account holds that no longer exist.
	// A principal carrying one is denied every attribute.
	UnresolvedRoles []string `json:"unresolved_roles,omitempty"`
}

EffectiveAccount is an account's permissions after its roles are merged in.

type EffectiveAttribute

type EffectiveAttribute struct {
	Attribute  AttributeDefinition `json:"attribute"`
	DeclaredIn TypeDefinition      `json:"declared_in"`
}

EffectiveAttribute pairs an attribute with the type that declares it.

type EffectiveSchema

type EffectiveSchema struct {
	AttributeDefinitionID string `json:"attribute_definition_id"`
	EntityID              string `json:"entity_id"`
	// RequiredEnforcement says how Required is enforced: "on_write" refuses a
	// write that leaves the value absent, "on_read" reports the gap.
	RequiredEnforcement string            `json:"required_enforcement,omitempty"`
	Required            bool              `json:"required"`
	Restricted          bool              `json:"restricted"`
	AllowedValues       []json.RawMessage `json:"allowed_values,omitempty"`
}

EffectiveSchema is an attribute's dependency-resolved state for one entity.

type EntitiesService

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

EntitiesService operates at the entity level: browsing, the faceted grid, import/export, media, revisions and per-entity reads.

func (*EntitiesService) All

All iterates every entity of a type across pages.

func (*EntitiesService) ApplyDefaults added in v1.5.0

func (s *EntitiesService) ApplyDefaults(ctx context.Context, typeID, entityID string) (*AppliedDefaults, error)

ApplyDefaults seeds the declared defaults the entity does not hold, resolving a dynamic default at the moment of the call. An attribute that already holds a base-scope value is left alone, and a computed attribute is skipped.

func (*EntitiesService) AsOf

func (s *EntitiesService) AsOf(ctx context.Context, typeID, entityID, at string) ([]RevisionValue, error)

AsOf reads an entity's values as they stood at a timestamp (RFC3339). at is required; the server has no default point in time.

Use AsOfRevision when you also need the revision's id, seq or label.

func (*EntitiesService) AsOfRevision added in v1.3.0

func (s *EntitiesService) AsOfRevision(ctx context.Context, typeID, entityID, at string) (*EntityRevision, error)

AsOfRevision reads the whole revision an entity stood at, at a timestamp (RFC3339). at is required.

func (*EntitiesService) Completeness

func (s *EntitiesService) Completeness(ctx context.Context, typeID, entityID string) (*Completeness, error)

Completeness scores one entity against its effective required schema.

func (*EntitiesService) CreateRevision

func (s *EntitiesService) CreateRevision(ctx context.Context, typeID, entityID, label string) (*EntityRevision, error)

CreateRevision captures an entity's current values as a new revision.

func (*EntitiesService) EffectiveSchema

func (s *EntitiesService) EffectiveSchema(ctx context.Context, typeID, entityID, attributeID string) (*EffectiveSchema, error)

EffectiveSchema resolves one attribute's dependency-adjusted state for an entity (required, restricted, allowed values).

func (*EntitiesService) Export

func (s *EntitiesService) Export(ctx context.Context, typeID string, opts ...ExportOptions) (*ExportResult, error)

Export streams a type's entities as CSV and parses them into columns + rows.

func (*EntitiesService) Facets

func (s *EntitiesService) Facets(ctx context.Context, typeID string, attributes []string, query string) (*Facets, error)

Facets returns value counts for the chosen attributes over the current result set (optionally narrowed by an FQL query).

func (*EntitiesService) Grid

func (s *EntitiesService) Grid(ctx context.Context, typeID string, attributes []string, opts ...ListOptions) (*GridResult, error)

Grid projects the chosen attributes as columns for a page of entities.

func (*EntitiesService) Import

func (s *EntitiesService) Import(ctx context.Context, typeID string, in ImportInput) (*ImportReport, error)

Import loads a CSV into a type's entities and returns the run report.

func (*EntitiesService) List

func (s *EntitiesService) List(ctx context.Context, typeID string, opts ...ListEntitiesOptions) (*Page[EntitySummary], error)

List returns one page of a type's entities (newest-first).

func (*EntitiesService) Purge added in v1.3.0

func (s *EntitiesService) Purge(ctx context.Context, typeID, entityID string) (*PurgeReport, error)

Purge permanently hard-deletes one entity's data: values, revisions, links, search documents and media blobs. Admin scope.

This is the right-to-erasure primitive and it is irreversible — the rows are gone, not archived, and no revision retains the erased content. Check MediaBlobsFailed on the report: a blob store that refused a delete leaves objects behind, and only the report names them.

func (*EntitiesService) RelationshipRequirements

func (s *EntitiesService) RelationshipRequirements(ctx context.Context, typeID, entityID string) ([]RelationshipRequirement, error)

RelationshipRequirements reports an entity's unmet cardinality minimums.

func (*EntitiesService) Relationships

func (s *EntitiesService) Relationships(ctx context.Context, typeID, entityID string) ([]EntityLink, error)

Relationships returns an entity's links, with definitions and roles resolved.

func (*EntitiesService) Remove

func (s *EntitiesService) Remove(ctx context.Context, typeID, entityID string) error

Remove archives an entity's values and unlinks its relationships.

func (*EntitiesService) Revisions

func (s *EntitiesService) Revisions(ctx context.Context, typeID, entityID string) ([]EntityRevision, error)

Revisions lists an entity's captured revisions.

func (*EntitiesService) UploadMedia

func (s *EntitiesService) UploadMedia(ctx context.Context, typeID, entityID, attributeID, filename, mimeType string, file io.Reader) (*AttributeValue, error)

UploadMedia uploads a file against a media attribute and returns the stored value. mimeType may be empty (the server sniffs it).

func (*EntitiesService) Values

func (s *EntitiesService) Values(ctx context.Context, typeID, entityID string) ([]AttributeValue, error)

Values returns an entity's live values.

func (*EntitiesService) ValuesPreview added in v1.3.0

func (s *EntitiesService) ValuesPreview(ctx context.Context, typeID, entityID, changeSetID string) ([]AttributeValue, error)

ValuesPreview returns an entity's values with a draft change-set's staged mutations overlaid, so a reviewer sees what publishing would produce without touching live data.

The overlay exists on this per-entity endpoint only. ListValuesOptions once carried a ChangeSetID that it sent to the paginated /values endpoint, which does not read it — so a preview silently returned the LIVE values, and a reviewer could approve a diff that was never displayed. The option is gone; this is the supported way.

type EntityLink struct {
	Relationship Relationship           `json:"relationship"`
	Definition   RelationshipDefinition `json:"definition"`
	Role         string                 `json:"role"`
}

EntityLink is a relationship with its definition and the queried entity's role resolved.

type EntityRevision

type EntityRevision struct {
	ID               string          `json:"id"`
	TypeDefinitionID string          `json:"type_definition_id"`
	EntityID         string          `json:"entity_id"`
	Seq              int             `json:"seq"`
	Label            string          `json:"label,omitempty"`
	CreatedAt        time.Time       `json:"created_at"`
	Values           []RevisionValue `json:"values"`
}

EntityRevision is an immutable point-in-time snapshot of an entity's values.

type EntityScore

type EntityScore struct {
	EntityID string  `json:"entity_id"`
	Score    float64 `json:"score"`
	Filled   int     `json:"filled"`
	Required int     `json:"required"`
}

EntityScore is one entity's completeness inside a type aggregate.

type EntitySummary

type EntitySummary struct {
	EntityID         string    `json:"entity_id"`
	TypeDefinitionID string    `json:"type_definition_id"`
	ValueCount       int       `json:"value_count"`
	LastUpdatedAt    time.Time `json:"last_updated_at"`
}

EntitySummary is one entity in a list or query result.

type ErrorCode

type ErrorCode string

ErrorCode is a stable, machine-readable failure code the API returns.

const (
	CodeValidation          ErrorCode = "VALIDATION"
	CodeNotFound            ErrorCode = "NOT_FOUND"
	CodeConflict            ErrorCode = "CONFLICT"
	CodeArchived            ErrorCode = "ARCHIVED"
	CodeDependencyViolation ErrorCode = "DEPENDENCY_VIOLATION"
	CodeUnauthenticated     ErrorCode = "UNAUTHENTICATED"
	CodeForbidden           ErrorCode = "FORBIDDEN"
	CodeRateLimited         ErrorCode = "RATE_LIMITED"
	CodeInternal            ErrorCode = "INTERNAL"

	// CodeFeatureDisabled means the deployment does not run this optional
	// capability — search, the outbox, media storage, GraphQL. It is
	// permanent for that deployment, so retrying cannot help.
	CodeFeatureDisabled ErrorCode = "FEATURE_DISABLED"

	// CodeCursorConflict means another consumer committed the cursor first.
	// Re-read the cursor and retry from the position it now holds.
	CodeCursorConflict ErrorCode = "CURSOR_CONFLICT"

	// CodeCursorExpired means the position is older than the feed's
	// retention. Re-baseline: the events between the cursor and the feed's
	// oldest retained event are gone.
	CodeCursorExpired ErrorCode = "CURSOR_EXPIRED"
)

The error codes the service emits.

type EventPage added in v1.3.0

type EventPage struct {
	Events []FeedEvent `json:"items"`
	// NextCursor is the position to pass as After for the following page.
	//
	// It is an int64 because the feed's cursor is a sequence number, and the
	// server always emits it — declaring it a string made ListPage fail to
	// decode on EVERY call, including against an empty feed.
	NextCursor int64 `json:"next_cursor"`
}

EventPage is one page of the event feed plus the cursor to resume from.

The feed's next_cursor used to be discarded by the list helper, so a consumer could read the first page and had no supported way to ask for the next one.

type EventsService

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

EventsService reads the events feed and cursors (requires event delivery).

Streaming is out of scope for this SDK. GET /api/v1/events/stream serves server-sent events, which needs a long-lived connection with its own reconnect and backoff policy; that belongs to the consumer, not to a request/response client. Poll with ListPage and commit a cursor instead — the cursor gives at-least-once delivery across restarts, which a stream alone does not.

func (*EventsService) CommitCursor

func (s *EventsService) CommitCursor(ctx context.Context, consumer string, position, expected int64) error

CommitCursor advances a named consumer cursor with compare-and-swap on the expected previous position.

The wire fields are `position` and `expected`. They were `after_seq` and `expected_seq`, and the server decodes strictly, so every commit was a hard 422 — the cursor never advanced and the CURSOR_CONFLICT / CURSOR_EXPIRED recovery paths this endpoint exists for were unreachable.

func (*EventsService) GetCursor

func (s *EventsService) GetCursor(ctx context.Context, consumer string) (int64, error)

GetCursor reads a named consumer cursor's committed position.

The wire field is `position`, matching the server and api/openapi.yaml. It was `after_seq` here, which the server never writes, so this returned 0 on every call with a NIL error — indistinguishable from a fresh consumer's legitimate start, so a documented at-least-once consumer replayed the whole retained feed on every restart with nothing reporting a failure.

func (*EventsService) List

func (s *EventsService) List(ctx context.Context, opts ...ListEventsOptions) ([]FeedEvent, error)

List returns feed events after the given sequence.

func (*EventsService) ListPage added in v1.3.0

func (s *EventsService) ListPage(ctx context.Context, after int64, types []string, limit int) (*EventPage, error)

ListPage returns one page of the event feed, after the given position, and the cursor for the next page. limit 0 uses the server default.

after is the feed SEQUENCE to resume from — 0 for the beginning. It was typed as a string, which did not match the API and could not be produced from the page this method returns.

type ExportOptions

type ExportOptions struct {
	// Attributes chooses the columns (internal names); empty exports all.
	Attributes []string
	// Query (FQL) or EntityIDs restrict the rows; both empty exports all.
	Query     string
	EntityIDs []string
}

ExportOptions restrict which entities and columns export.

type ExportResult

type ExportResult struct {
	Columns []string
	Rows    [][]string
}

ExportResult is a parsed CSV export: a header and data rows.

type FacetBucket

type FacetBucket struct {
	Value string `json:"value"`
	Count int    `json:"count"`
}

FacetBucket is one distinct value and its count within a faceted column.

type Facets

type Facets struct {
	Facets map[string][]FacetBucket `json:"facets"`
	// Truncated reports that at least one attribute has more distinct values
	// than the buckets returned. Without it a partial bucket list is
	// indistinguishable from a complete one, so a filter sidebar shows
	// "3 materials" where there are 300.
	Truncated bool `json:"truncated,omitempty"`
}

Facets maps each requested attribute to its value buckets over the current result set.

type Features

type Features struct {
	Search        bool `json:"search"`
	Activity      bool `json:"activity"`
	SearchIndex   bool `json:"search_index"`
	EventDelivery bool `json:"event_delivery"`

	// MaxImportBytes and MaxMediaBytes are the deployment's upload ceilings.
	// They were compile-time constants the client could not discover, so a
	// bulk CSV load was sized against a guess and failed part-way through.
	// Chunk against these rather than assuming the defaults.
	MaxImportBytes int64 `json:"max_import_bytes"`
	MaxMediaBytes  int64 `json:"max_media_bytes"`
}

Features reports the deployment's enabled capabilities.

type FeedEvent

type FeedEvent struct {
	// Seq is the feed position. Pass the last one you processed as After.
	Seq           int64  `json:"seq"`
	ID            string `json:"id"`
	Type          string `json:"type"`
	AggregateType string `json:"aggregate_type,omitempty"`
	AggregateID   string `json:"aggregate_id,omitempty"`
	TenantID      string `json:"tenant_id,omitempty"`
	// TypeDefinitionID and EntityID address the entity the event concerns, so
	// a consumer routes on "entity E changed" without decoding Payload.
	//
	// They are empty for an event that concerns no entity (a schema change) or
	// more than one (a relationship link, which names two endpoints), and for
	// an event recorded before the server carried them.
	TypeDefinitionID string          `json:"type_definition_id,omitempty"`
	EntityID         string          `json:"entity_id,omitempty"`
	Actor            string          `json:"actor,omitempty"`
	OccurredAt       time.Time       `json:"occurred_at"`
	RecordedAt       time.Time       `json:"recorded_at,omitempty"`
	SchemaVersion    int             `json:"schema_version,omitempty"`
	Payload          json.RawMessage `json:"payload,omitempty"`
}

FeedEvent is one entry in the events feed.

The wire shape is NESTED: the server sends {"seq":N,"envelope":{...}}. This type was flat (feed_seq, id, type, …) and no key overlapped, so decoding produced the right NUMBER of events with every field zero and no error — a consumer dispatching on Type saw "" for ever. UnmarshalJSON maps the nested form onto these fields so callers keep one flat struct.

func (*FeedEvent) UnmarshalJSON added in v1.3.0

func (e *FeedEvent) UnmarshalJSON(data []byte) error

UnmarshalJSON decodes the server's {"seq":…,"envelope":{…}} shape.

type GridResult

type GridResult struct {
	Columns  []string  `json:"columns"`
	Rows     []GridRow `json:"rows"`
	PageInfo PageInfo  `json:"page_info"`
}

GridResult is a faceted grid page: chosen attribute values per entity.

type GridRow

type GridRow struct {
	EntityID string            `json:"entity_id"`
	Values   map[string]string `json:"values"`
}

GridRow is one entity's projected column values.

type ImportError

type ImportError struct {
	Row       int    `json:"row"`
	Column    string `json:"column,omitempty"`
	Attribute string `json:"attribute,omitempty"`
	Reason    string `json:"reason"`
}

ImportError points at one rejected import cell or row.

type ImportInput

type ImportInput struct {
	// CSV is the raw file content (a header row plus data rows).
	CSV io.Reader
	// KeyColumn names the CSV column holding each row's entity id.
	KeyColumn string
	// Mapping maps a CSV column name to an attribute internal name.
	Mapping map[string]string
	// Mode is "best_effort" (default) or "transactional".
	Mode string
	// DryRun validates every row and writes nothing.
	DryRun bool
}

ImportInput describes a CSV import against one type.

type ImportReport

type ImportReport struct {
	RowsTotal   int           `json:"rows_total"`
	RowsValid   int           `json:"rows_valid"`
	RowsWritten int           `json:"rows_written"`
	DryRun      bool          `json:"dry_run"`
	Mode        string        `json:"mode"`
	Errors      []ImportError `json:"errors"`
}

ImportReport summarizes an import run.

type KindCount

type KindCount struct {
	Created int `json:"created"`
	Skipped int `json:"skipped"`
}

KindCount tallies created vs skipped objects of one kind on import.

type LinkInput

type LinkInput struct {
	DefinitionID string `json:"relationship_definition_id"`
	ParentEntity string `json:"parent_entity_id"`
	ChildEntity  string `json:"child_entity_id"`
}

LinkInput creates one link between two entities.

type ListActivityOptions

type ListActivityOptions struct {
	ListOptions
	Entity   string
	EntityID string
	Actor    string
}

ListActivityOptions filters the audit log.

type ListAttributesOptions

type ListAttributesOptions struct {
	ListOptions
	TypeDefinitionID string
	InternalNames    []string
	DataTypes        []string
	IncludeArchived  bool
}

ListAttributesOptions filters an attribute listing.

type ListEntitiesOptions

type ListEntitiesOptions struct {
	ListOptions
	IncludeDescendants bool
}

ListEntitiesOptions filters an entity listing; IncludeDescendants folds in subtype rows.

type ListEventsOptions

type ListEventsOptions struct {
	After int64
	Types []string
	Limit int
}

ListEventsOptions pages the feed.

type ListOptions

type ListOptions struct {
	Limit  int    // page size; 0 uses the server default
	Cursor string // opaque keyset cursor; "" starts at the first page
	Total  bool   // request PageInfo.TotalCount
}

ListOptions are the pagination arguments common to every list call. The cursor is opaque and keyset-based, so pages stay stable under concurrent writes; the total is computed only when Total is set.

type ListRelationshipDefinitionsOptions

type ListRelationshipDefinitionsOptions struct {
	ListOptions
	TypeDefinitionID string
	IncludeArchived  bool
}

ListRelationshipDefinitionsOptions filters a definition listing.

type ListTypesOptions

type ListTypesOptions struct {
	ListOptions
	InternalNames   []string
	IncludeArchived bool
}

ListTypesOptions filters a type listing.

type ListValuesOptions added in v1.3.0

type ListValuesOptions struct {
	ListOptions
	// TypeDefinitionID narrows to one type's entities.
	TypeDefinitionID string
	// AttributeDefinitionID narrows to one attribute across entities — the
	// "who has a value for this field" query.
	AttributeDefinitionID string
	// EntityID narrows to one entity.
	EntityID string
	// IncludeArchived folds in soft-deleted values.
	IncludeArchived bool
}

ListValuesOptions filters a value listing. Every field is optional; with none set the call pages the tenant's whole value set.

type MatchCandidate

type MatchCandidate struct {
	EntityA string  `json:"entity_a"`
	EntityB string  `json:"entity_b"`
	ValueA  string  `json:"value_a"`
	ValueB  string  `json:"value_b"`
	Score   float64 `json:"score"`
}

MatchCandidate is a scored pair of possibly-duplicate entities.

type MatchRule

type MatchRule struct {
	ID                    string    `json:"id"`
	TenantID              string    `json:"tenant_id"`
	TypeDefinitionID      string    `json:"type_definition_id"`
	AttributeDefinitionID string    `json:"attribute_definition_id"`
	Strategy              string    `json:"strategy"`
	Threshold             float64   `json:"threshold"`
	CreatedAt             time.Time `json:"created_at"`
}

MatchRule is a per-type duplicate-detection rule.

type MatchRulesService

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

MatchRulesService operates on duplicate-detection rules by id. Create and list rules through Types().MatchRules / Types().CreateMatchRule.

func (*MatchRulesService) Delete

func (s *MatchRulesService) Delete(ctx context.Context, ruleID string) error

Delete removes a match rule.

func (*MatchRulesService) Dismiss

func (s *MatchRulesService) Dismiss(ctx context.Context, ruleID, entityA, entityB string) error

Dismiss records a candidate pair as not-a-duplicate so it never resurfaces.

func (*MatchRulesService) Scan

func (s *MatchRulesService) Scan(ctx context.Context, ruleID string) (*MatchScan, error)

Scan runs a rule and returns scored candidate duplicate pairs.

type MatchScan

type MatchScan struct {
	RuleID     string           `json:"rule_id"`
	Strategy   string           `json:"strategy"`
	Candidates []MatchCandidate `json:"candidates"`
	Truncated  bool             `json:"truncated"`
}

MatchScan is a rule's report of candidate duplicate pairs.

type MissingAttribute

type MissingAttribute struct {
	AttributeDefinitionID string `json:"attribute_definition_id"`
	InternalName          string `json:"internal_name"`
	DisplayName           string `json:"display_name"`
	Group                 string `json:"group,omitempty"`
}

MissingAttribute names a required attribute an entity has not filled.

type Mutation

type Mutation struct {
	Kind                  string          `json:"kind"` // set | remove
	AttributeDefinitionID string          `json:"attribute_definition_id"`
	EntityID              string          `json:"entity_id"`
	TypeDefinitionID      string          `json:"type_definition_id,omitempty"`
	Locale                string          `json:"locale,omitempty"`
	Channel               string          `json:"channel,omitempty"`
	Value                 json.RawMessage `json:"value,omitempty"`
}

Mutation is one staged value change inside a change-set.

type Option

type Option func(*Client)

Option configures a Client.

func WithHTTPClient

func WithHTTPClient(h *http.Client) Option

WithHTTPClient supplies a custom *http.Client (timeouts, transport, tracing), replacing the default client and its 30s per-request timeout. A nil argument is ignored.

func WithRetry added in v1.3.0

func WithRetry(p RetryPolicy) Option

WithRetry enables retrying with the given policy.

The paginating All(...) iterators are the sharp case: they issue many requests in tight succession, which is exactly the shape a per-account token bucket targets, so without retrying a bulk walk aborts part-way with no resumption point.

func WithToken

func WithToken(token string) Option

WithToken sets the service-account bearer token (ft_<account>_<secret>). Omit it only against a development service with authentication disabled.

func WithUserAgent

func WithUserAgent(ua string) Option

WithUserAgent overrides the User-Agent header.

type Page

type Page[T any] struct {
	Items    []T      `json:"items"`
	PageInfo PageInfo `json:"page_info"`
}

Page is one page of a list response.

type PageInfo

type PageInfo struct {
	// HasNextPage reports that NextCursor will fetch more.
	HasNextPage bool `json:"has_next_page"`

	// HasPreviousPage reports only that this is not the first page. It is
	// not a backward-paging capability: the API has no "before" cursor and
	// no direction, so there is nothing to call to go back.
	//
	// To offer a Back button, keep the cursors you have already used and
	// re-request one — CursorStack does exactly that.
	HasPreviousPage bool `json:"has_previous_page"`

	NextCursor *string `json:"next_cursor,omitempty"`
	TotalCount *int    `json:"total_count,omitempty"`
}

PageInfo describes a page's position in the full result set. TotalCount is present only when the request asked for it (ListOptions.Total).

type ParkedEnvelope added in v1.5.0

type ParkedEnvelope struct {
	ID            string    `json:"id"`
	EventType     string    `json:"event_type"`
	AggregateType string    `json:"aggregate_type"`
	AggregateID   string    `json:"aggregate_id"`
	Attempts      int       `json:"attempts"`
	LastError     string    `json:"last_error"`
	RecordedAt    time.Time `json:"recorded_at"`
	ParkedAt      time.Time `json:"parked_at"`
}

ParkedEnvelope is one outbox envelope that exhausted its dispatch retry budget and waits for an operator redrive. It is a committed change no consumer has seen: it is off the events feed and has no webhook deliveries until it is redriven.

type ParkedFilter added in v1.5.0

type ParkedFilter struct {
	EventType string
	ID        string
}

ParkedFilter narrows a parked listing or a redrive. Zero values mean "no constraint"; ID selects exactly one envelope.

type PurgeReport added in v1.3.0

type PurgeReport struct {
	// EntityID is set for a per-entity purge and empty for a tenant purge.
	EntityID          string   `json:"entity_id,omitempty"`
	ValuesPurged      int      `json:"values_purged"`
	RevisionsPurged   int      `json:"revisions_purged"`
	RelationshipsGone int      `json:"relationships_gone"`
	SearchDocsPurged  int      `json:"search_docs_purged"`
	MediaBlobsPurged  int      `json:"media_blobs_purged"`
	MediaBlobsFailed  int      `json:"media_blobs_failed"`
	UnpurgedBlobKeys  []string `json:"unpurged_blob_keys,omitempty"`
}

PurgeReport counts what a purge permanently removed. MediaBlobsFailed and UnpurgedBlobKeys are non-zero when blob storage refused a delete, so an operator can reconcile the remaining objects by hand.

type QueryOptions

type QueryOptions struct {
	ListOptions
	// Locale and Channel restrict scoped-attribute predicates to one scope;
	// zero matches base (unscoped) values.
	Locale  string
	Channel string
}

QueryOptions carry the FQL scope and pagination for a query.

type Relationship

type Relationship struct {
	ID             string     `json:"id"`
	TenantID       string     `json:"tenant_id"`
	DefinitionID   string     `json:"relationship_definition_id"`
	ParentEntityID string     `json:"parent_entity_id"`
	ChildEntityID  string     `json:"child_entity_id"`
	CreatedAt      time.Time  `json:"created_at"`
	UpdatedAt      time.Time  `json:"updated_at"`
	ArchivedAt     *time.Time `json:"archived_at,omitempty"`
}

Relationship is one live link between two entities.

type RelationshipDefinition

type RelationshipDefinition struct {
	ID                  string     `json:"id"`
	TenantID            string     `json:"tenant_id"`
	InternalName        string     `json:"internal_name"`
	DisplayName         string     `json:"display_name"`
	Description         string     `json:"description,omitempty"`
	Kind                string     `json:"kind"`
	ParentTypeID        string     `json:"parent_type_id"`
	ChildTypeID         string     `json:"child_type_id"`
	ParentLabel         string     `json:"parent_label,omitempty"`
	ChildLabel          string     `json:"child_label,omitempty"`
	AttributeSetID      string     `json:"attribute_set_id"`
	ExtendsID           string     `json:"extends_id,omitempty"`
	ParentVersionPolicy string     `json:"parent_version_policy"`
	ChildVersionPolicy  string     `json:"child_version_policy"`
	MinChildren         *int       `json:"min_children,omitempty"`
	MaxChildren         *int       `json:"max_children,omitempty"`
	MinParents          *int       `json:"min_parents,omitempty"`
	MaxParents          *int       `json:"max_parents,omitempty"`
	Version             int        `json:"version"`
	CreatedAt           time.Time  `json:"created_at"`
	UpdatedAt           time.Time  `json:"updated_at"`
	ArchivedAt          *time.Time `json:"archived_at,omitempty"`
}

RelationshipDefinition is a user-defined relationship type.

type RelationshipDefinitionsService

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

RelationshipDefinitionsService operates on relationship definitions.

func (*RelationshipDefinitionsService) Archive

Archive soft-deletes a relationship definition.

func (*RelationshipDefinitionsService) AttributeSets added in v1.3.0

func (s *RelationshipDefinitionsService) AttributeSets(ctx context.Context, id string) ([]string, error)

AttributeSets returns the attribute-set ids a relationship definition carries on its links.

func (*RelationshipDefinitionsService) Create

Create creates a relationship definition.

func (*RelationshipDefinitionsService) Get

Get loads one relationship definition.

func (*RelationshipDefinitionsService) List

List returns one page of relationship definitions.

func (*RelationshipDefinitionsService) Restore

Restore reverses an archive.

func (*RelationshipDefinitionsService) Update added in v1.3.0

Update mutates a relationship definition.

type RelationshipRequirement

type RelationshipRequirement struct {
	DefinitionID string `json:"definition_id"`
	Side         string `json:"side"`
	Required     int    `json:"required"`
	Current      int    `json:"current"`
}

RelationshipRequirement reports an unmet cardinality minimum for an entity.

type RelationshipsService

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

RelationshipsService operates on relationship instances (links).

func (*RelationshipsService) Get

Get loads one relationship.

Link creates a relationship between two entities.

func (*RelationshipsService) List

List returns one page of relationships.

func (s *RelationshipsService) Unlink(ctx context.Context, id string) error

Unlink archives a relationship.

type RetryPolicy added in v1.3.0

type RetryPolicy struct {
	// MaxAttempts counts the first try. 1 (or 0) disables retrying.
	MaxAttempts int
	// BaseDelay is the wait before the second attempt. Each further attempt
	// doubles it, up to MaxDelay.
	BaseDelay time.Duration
	// MaxDelay caps the backoff.
	MaxDelay time.Duration
	// Jitter scales the random part of each wait, as a fraction of the
	// computed delay (0.2 means ±20%). Without it, many clients throttled at
	// once retry in lockstep and throttle each other again.
	Jitter float64
	// RetryStatuses are the response statuses worth another attempt. A
	// status not listed here fails immediately, whatever its class.
	RetryStatuses []int
}

RetryPolicy controls whether and how a request is retried. The zero value retries nothing; build one with DefaultRetryPolicy and adjust it.

Retrying is opt-in because it is not safe in general: a POST that creates a resource may have succeeded before the connection broke, so replaying it can create a second one. Only idempotent methods are ever retried — GET, HEAD, PUT and DELETE — and a POST is left alone whatever the policy says.

func DefaultRetryPolicy added in v1.3.0

func DefaultRetryPolicy() RetryPolicy

DefaultRetryPolicy retries an idempotent request up to three times on 429 and on the transient 5xx statuses a proxy or a restarting server emits, with exponential backoff from 200ms to 5s and ±20% jitter.

A server-supplied Retry-After always wins over the computed delay: the server knows when its token bucket refills and the client does not.

type RevisionValue

type RevisionValue struct {
	AttributeDefinitionID string `json:"attribute_definition_id"`
	InternalName          string `json:"internal_name"`
	DisplayName           string `json:"display_name"`
	DataType              string `json:"data_type"`
	// Locale and Channel are the value's scope. Without them a localized
	// entity came back as N rows with identical InternalName and no way to
	// tell them apart.
	Locale  string `json:"locale,omitempty"`
	Channel string `json:"channel,omitempty"`
	// Value is the DISPLAY form: lossy for structured types, and what the
	// console and the diff show. A quantity renders as "10 kg", a media value
	// as its filename.
	Value string `json:"value"`
	// Typed is the self-describing round-trippable form, added on the server
	// precisely because Value is lossy. Read this to reconstruct a value.
	Typed json.RawMessage `json:"typed,omitempty"`
}

RevisionValue is one attribute's value captured in a revision.

type RevisionsService

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

RevisionsService operates on entity revisions by id.

func (*RevisionsService) Diff

func (s *RevisionsService) Diff(ctx context.Context, fromID, toID string) (json.RawMessage, error)

Diff returns the difference between two revisions of one entity as raw JSON (add/change/remove per attribute). Both ids are required.

The endpoint diffs revision against revision. An earlier signature took one id and sent no query, so the server answered "to (revision id) is required" on every call.

func (*RevisionsService) Get

Get loads one revision.

func (*RevisionsService) Restore

func (s *RevisionsService) Restore(ctx context.Context, id string) error

Restore rolls the entity back to a revision (replayed as normal writes, so events and activity fire).

type Role added in v1.3.0

type Role struct {
	ID          string   `json:"id"`
	TenantID    string   `json:"tenant_id,omitempty"`
	Name        string   `json:"name"`
	Description string   `json:"description,omitempty"`
	Scopes      []string `json:"scopes"`
	// FieldPermissions maps an attribute internal name to none, read or
	// write. An attribute that is not listed stays fully accessible.
	FieldPermissions map[string]string `json:"field_permissions,omitempty"`
}

Role is a named permission set that accounts in the same tenant hold.

type SavedView

type SavedView struct {
	ID       string   `json:"id"`
	TenantID string   `json:"tenant_id"`
	Name     string   `json:"name"`
	RootType string   `json:"root_type"`
	Query    string   `json:"query"`
	Columns  []string `json:"columns,omitempty"`
	// Sort is the view's ordering clause. It is part of what makes a saved
	// view reproducible, and had no field to land in.
	Sort      string    `json:"sort,omitempty"`
	CreatedAt time.Time `json:"created_at"`
	UpdatedAt time.Time `json:"updated_at"`
	// Version increments on every write. Send it back in SavedViewPatch to
	// compare-and-swap, so a concurrent edit answers 409 instead of being
	// silently overwritten.
	Version int `json:"version"`
}

SavedView persists a type + query + grid columns under a name.

type SavedViewInput

type SavedViewInput struct {
	Name     string `json:"name"`
	RootType string `json:"root_type"`
	Query    string `json:"query"`
	// Columns is always transmitted, as [] when nil.
	//
	// The server's sparse decoder reads "" as "clear" and null as "absent",
	// so a nil slice made Update neither a full replace nor sparse: it
	// cleared query and sort while leaving columns as stored. Sending an
	// explicit empty array makes the documented full-replace true for every
	// field.
	Columns []string `json:"columns"`
	Sort    string   `json:"sort"`

	// Version is the version the caller read. Set it to compare-and-swap: a
	// write against a view somebody else has since changed answers CONFLICT
	// instead of overwriting it. Leave it nil for last-write-wins.
	Version *int `json:"version,omitempty"`
}

SavedViewInput creates or fully replaces a saved view. Every field is sent, so a zero value clears the stored one — use SavedViewPatch to change some fields and leave the rest alone.

func (SavedViewInput) MarshalJSON added in v1.3.0

func (in SavedViewInput) MarshalJSON() ([]byte, error)

MarshalJSON transmits a nil Columns as [], so Update replaces every field.

type SavedViewPatch added in v1.3.0

type SavedViewPatch struct {
	Name     *string   `json:"name,omitempty"`
	RootType *string   `json:"root_type,omitempty"`
	Query    *string   `json:"query,omitempty"`
	Columns  *[]string `json:"columns,omitempty"`
	Sort     *string   `json:"sort,omitempty"`
	// Version is the version the caller read (SavedView.Version). Sending it
	// makes the patch a compare-and-swap: a view someone else edited in the
	// meantime answers 409 rather than being overwritten. Leaving it nil
	// keeps last-write-wins.
	Version *int `json:"version,omitempty"`
}

SavedViewPatch is a sparse update: a nil field is left as it is stored.

This exists because the full-replace form loses data on an unrelated edit. Renaming a view built in the console used to omit its sort order and clear it, and the SDK could not even read that field back.

type SavedViewsService

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

SavedViewsService operates on saved views.

func (*SavedViewsService) Create

Create creates a saved view.

func (*SavedViewsService) Delete

func (s *SavedViewsService) Delete(ctx context.Context, id string) error

Delete removes a saved view.

func (*SavedViewsService) Get

func (s *SavedViewsService) Get(ctx context.Context, id string) (*SavedView, error)

Get loads one saved view.

func (*SavedViewsService) List

func (s *SavedViewsService) List(ctx context.Context) ([]SavedView, error)

List returns the tenant's saved views.

func (*SavedViewsService) Patch added in v1.3.0

Patch changes only the fields set on in, leaving the rest as stored.

func (*SavedViewsService) Update

Update replaces every field of a saved view. A zero value in the input clears the stored value.

Use Patch for anything else — including a rename. Update is a full replace, so renaming with it clears the query, columns and sort unless the caller restates them, which is how a rename came to wipe a view's sort order.

type SchemaImportResult

type SchemaImportResult struct {
	Types                   KindCount `json:"types"`
	Attributes              KindCount `json:"attributes"`
	RelationshipDefinitions KindCount `json:"relationship_definitions"`
	Dependencies            KindCount `json:"dependencies"`
}

SchemaImportResult reports what a schema import created versus skipped.

type SchemaService

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

SchemaService moves a tenant's schema as a portable bundle and applies curated templates.

func (*SchemaService) ApplyTemplate

func (s *SchemaService) ApplyTemplate(ctx context.Context, name string) (*SchemaImportResult, error)

ApplyTemplate imports a curated template into the caller's tenant.

func (*SchemaService) Export

func (s *SchemaService) Export(ctx context.Context) (json.RawMessage, error)

Export gathers the caller's tenant schema into a portable, name-keyed bundle.

func (*SchemaService) Import

Import applies a bundle idempotently and reports what was created vs skipped.

func (*SchemaService) Template added in v1.3.0

func (s *SchemaService) Template(ctx context.Context, name string) (*SchemaTemplate, error)

Template loads one curated schema template, including its bundle.

func (*SchemaService) Templates

func (s *SchemaService) Templates(ctx context.Context) ([]SchemaTemplate, error)

Templates lists the curated starter schemas.

type SchemaTemplate

type SchemaTemplate struct {
	Name        string `json:"name"`
	Title       string `json:"title"`
	Description string `json:"description"`
	// Bundle is the template's schema payload, present when a single
	// template is fetched. Without it, Template returned exactly what
	// Templates already lists — its godoc promised "including its bundle",
	// which is the only reason to fetch one by name.
	Bundle json.RawMessage `json:"bundle,omitempty"`
}

SchemaTemplate is a curated starter schema's metadata.

type ServiceAccount

type ServiceAccount struct {
	ID       string   `json:"id"`
	TenantID string   `json:"tenant_id,omitempty"`
	Name     string   `json:"name"`
	Scopes   []string `json:"scopes"`
	// Roles the account holds. Its effective scopes are the union of Scopes
	// and every role's scopes.
	Roles []string `json:"roles,omitempty"`
	// FieldPermissions are this account's own overrides, which win over any
	// level a role grants. Keys are attribute internal names; values are
	// none, read or write.
	FieldPermissions map[string]string `json:"field_permissions,omitempty"`
	Token            string            `json:"token,omitempty"`
}

ServiceAccount is a provisioned credential. Token is set only at creation and rotation; it is never returned again.

type SetValueInput

type SetValueInput struct {
	AttributeDefinitionID string          `json:"attribute_definition_id"`
	EntityID              string          `json:"entity_id"`
	TypeDefinitionID      string          `json:"type_definition_id,omitempty"`
	Locale                string          `json:"locale,omitempty"`
	Channel               string          `json:"channel,omitempty"`
	Value                 json.RawMessage `json:"value"`
}

SetValueInput sets one value. Value is the raw JSON payload; its shape follows the attribute's data type (a decimal is a JSON string "9.99", a quantity is {"magnitude","unit"}, a bool is true). Locale/Channel apply to localizable/scopable attributes.

type SignedMediaURL added in v1.6.0

type SignedMediaURL struct {
	// URL is relative to the service root, e.g. "/media/signed/eyJ...".
	URL string `json:"url"`
	// ExpiresAt is when the link stops working.
	ExpiresAt time.Time `json:"expires_at"`
}

SignedMediaURL is a link anyone holding it can fetch, until it expires.

type SubscriptionInput

type SubscriptionInput struct {
	Name       string   `json:"name"`
	URL        string   `json:"url"`
	Secret     string   `json:"secret,omitempty"`
	EventTypes []string `json:"event_types,omitempty"`
	Active     *bool    `json:"active,omitempty"`
}

SubscriptionInput creates or updates a webhook subscription.

type Tenant

type Tenant struct {
	Name      string    `json:"name"`
	Active    bool      `json:"active"`
	CreatedAt time.Time `json:"created_at"`
}

Tenant is a provisioning tenant.

type TypeCompleteness

type TypeCompleteness struct {
	TypeDefinitionID string        `json:"type_definition_id"`
	Count            int           `json:"count"`
	Scored           int           `json:"scored"`
	Truncated        bool          `json:"truncated"`
	AverageScore     float64       `json:"average_score"`
	Complete         int           `json:"complete"`
	Incomplete       int           `json:"incomplete"`
	Entities         []EntityScore `json:"entities"`
}

TypeCompleteness aggregates completeness across a type's entities.

type TypeDefinition

type TypeDefinition struct {
	ID           string     `json:"id"`
	TenantID     string     `json:"tenant_id"`
	Kind         string     `json:"kind,omitempty"`
	ExtendsID    string     `json:"extends_id,omitempty"`
	InternalName string     `json:"internal_name"`
	DisplayName  string     `json:"display_name"`
	Description  string     `json:"description,omitempty"`
	Version      int        `json:"version"`
	CreatedAt    time.Time  `json:"created_at"`
	UpdatedAt    time.Time  `json:"updated_at"`
	ArchivedAt   *time.Time `json:"archived_at,omitempty"`
}

TypeDefinition is a soft type.

type TypedValue

type TypedValue struct {
	Type  string          `json:"type"`
	Value json.RawMessage `json:"value"`
}

TypedValue is the self-describing form used for constraint operands, condition operands and default/allowed values: {"type":"decimal","value":"9.99"}.

type TypesService

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

TypesService operates on type definitions.

func (*TypesService) All

All iterates every type definition across pages.

func (*TypesService) Archive

func (s *TypesService) Archive(ctx context.Context, id string) (*TypeDefinition, error)

Archive soft-deletes a type definition.

func (*TypesService) Attributes

func (s *TypesService) Attributes(ctx context.Context, id string, opts ...ListOptions) (*Page[AttributeDefinition], error)

Attributes lists a type's own (declared) attributes.

func (*TypesService) Children

func (s *TypesService) Children(ctx context.Context, id string) ([]TypeDefinition, error)

Children returns a type's direct subtypes.

func (*TypesService) Clone

func (s *TypesService) Clone(ctx context.Context, id, newInternalName, newDisplayName string) (*CloneResult, error)

Clone copies a type's attributes and intra-type dependencies into a fresh root type (not its values, not its hierarchy position).

func (*TypesService) Completeness

func (s *TypesService) Completeness(ctx context.Context, id string) (*TypeCompleteness, error)

Completeness aggregates completeness across a type's entities.

func (*TypesService) Create

Create creates a type definition.

func (*TypesService) CreateMatchRule

func (s *TypesService) CreateMatchRule(ctx context.Context, id string, in CreateMatchRuleInput) (*MatchRule, error)

CreateMatchRule adds a duplicate-detection rule to a type.

func (*TypesService) EffectiveAttributes

func (s *TypesService) EffectiveAttributes(ctx context.Context, id string) ([]EffectiveAttribute, error)

EffectiveAttributes returns the type's full effective schema (inherited attributes included), each tagged with the type that declares it.

func (*TypesService) Get

func (s *TypesService) Get(ctx context.Context, id string) (*TypeDefinition, error)

Get loads one type definition.

func (*TypesService) List

List returns one page of type definitions.

func (*TypesService) MatchRules

func (s *TypesService) MatchRules(ctx context.Context, id string) ([]MatchRule, error)

MatchRules lists the duplicate-detection rules for a type.

func (*TypesService) Restore

func (s *TypesService) Restore(ctx context.Context, id string) (*TypeDefinition, error)

Restore reverses an archive.

func (*TypesService) Update

Update mutates a type definition.

type UnitFamiliesService

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

UnitFamiliesService operates on quantity unit families.

func (*UnitFamiliesService) Create

Create creates a unit family.

func (*UnitFamiliesService) Delete

func (s *UnitFamiliesService) Delete(ctx context.Context, id string) error

Delete removes a unit family.

func (*UnitFamiliesService) Get

Get loads one unit family.

func (*UnitFamiliesService) List

List returns the tenant's unit families.

type UnitFamily

type UnitFamily struct {
	ID       string             `json:"id"`
	TenantID string             `json:"tenant_id"`
	Name     string             `json:"name"`
	BaseUnit string             `json:"base_unit"`
	Units    map[string]float64 `json:"units"`
}

UnitFamily is a set of units sharing a base with per-unit conversion factors.

type UpdateAttributeInput

type UpdateAttributeInput struct {
	DisplayName  string          `json:"display_name"`
	Description  string          `json:"description,omitempty"`
	Required     bool            `json:"required,omitempty"`
	MultiValued  bool            `json:"multi_valued,omitempty"`
	Unique       bool            `json:"unique,omitempty"`
	Localizable  bool            `json:"localizable,omitempty"`
	Scopable     bool            `json:"scopable,omitempty"`
	UnitFamilyID string          `json:"unit_family_id,omitempty"`
	DisplayUnit  string          `json:"display_unit,omitempty"`
	Computed     json.RawMessage `json:"computed,omitempty"`
	Constraints  json.RawMessage `json:"constraints,omitempty"`
	DefaultValue json.RawMessage `json:"default_value,omitempty"`
	Group        string          `json:"group,omitempty"`
	SortOrder    int             `json:"sort_order,omitempty"`
	HelpText     string          `json:"help_text,omitempty"`

	// Version is the version the caller read. Set it to compare-and-swap: a
	// write against a definition somebody else has since changed answers
	// CONFLICT instead of overwriting it. Leave it nil for last-write-wins.
	//
	// This request replaces the whole editable record, so a lost update loses
	// fields the later writer never looked at.
	Version *int `json:"version,omitempty"`
}

UpdateAttributeInput mutates an attribute definition.

type UpdateTypeInput

type UpdateTypeInput struct {
	DisplayName string `json:"display_name"`
	Description string `json:"description,omitempty"`

	// Version is the version the caller read. Set it to compare-and-swap: a
	// write against a record somebody else has since changed answers CONFLICT
	// instead of overwriting it. Leave it nil for last-write-wins.
	//
	// This request replaces the whole editable record, so a lost update loses
	// fields the later writer never looked at.
	Version *int `json:"version,omitempty"`
}

UpdateTypeInput mutates a type's display fields.

type UpsertRoleInput added in v1.3.0

type UpsertRoleInput struct {
	TenantName       string            `json:"tenant_name"`
	Name             string            `json:"name"`
	Description      string            `json:"description,omitempty"`
	Scopes           []string          `json:"scopes,omitempty"`
	FieldPermissions map[string]string `json:"field_permissions,omitempty"`
}

UpsertRoleInput creates or replaces a role. The write replaces the whole role rather than patching it, so the stored record is the full grant.

type ValuesService

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

ValuesService operates on attribute values.

func (*ValuesService) All added in v1.3.0

All iterates every matching value across pages.

func (*ValuesService) Get

Get loads one value by id.

func (*ValuesService) List added in v1.3.0

List returns one page of values, filtered by opts.

func (*ValuesService) Remove

func (s *ValuesService) Remove(ctx context.Context, id string) error

Remove archives one value by id.

func (*ValuesService) Set

Set writes one value (create or update; single-valued attributes upsert).

func (*ValuesService) SetBatch

func (s *ValuesService) SetBatch(ctx context.Context, in []SetValueInput) ([]AttributeValue, error)

SetBatch writes many values atomically in one unit of work.

type WebhookDelivery

type WebhookDelivery struct {
	ID             string    `json:"id"`
	SubscriptionID string    `json:"subscription_id"`
	EnvelopeID     string    `json:"envelope_id"`
	EventType      string    `json:"event_type"`
	FeedSeq        int64     `json:"feed_seq"`
	Status         string    `json:"status"`
	Attempts       int       `json:"attempts"`
	NextAttemptAt  time.Time `json:"next_attempt_at"`
	LastError      string    `json:"last_error,omitempty"`
	ResponseCode   int       `json:"response_code,omitempty"`
	CreatedAt      time.Time `json:"created_at"`
	UpdatedAt      time.Time `json:"updated_at"`
}

WebhookDelivery is one delivery attempt record.

type WebhookSubscription

type WebhookSubscription struct {
	ID         string    `json:"id"`
	Name       string    `json:"name"`
	URL        string    `json:"url"`
	EventTypes []string  `json:"event_types"`
	Active     bool      `json:"active"`
	CreatedAt  time.Time `json:"created_at"`
	UpdatedAt  time.Time `json:"updated_at"`
}

WebhookSubscription is a managed delivery endpoint.

type WebhooksService

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

WebhooksService manages webhook subscriptions and inspects deliveries (requires the outbox / event delivery feature).

func (*WebhooksService) Create

Create creates a subscription.

func (*WebhooksService) Delete

func (s *WebhooksService) Delete(ctx context.Context, id string) error

Delete removes a subscription.

func (*WebhooksService) Deliveries

func (s *WebhooksService) Deliveries(ctx context.Context, id, status string, opts ...ListOptions) (*Page[WebhookDelivery], error)

Deliveries returns a subscription's delivery log, newest first; status filters (e.g. "failed", "dead") when non-empty.

func (*WebhooksService) Get

Get loads one subscription.

func (*WebhooksService) List

List returns the tenant's webhook subscriptions.

func (*WebhooksService) Redeliver

func (s *WebhooksService) Redeliver(ctx context.Context, deliveryID string) error

Redeliver requeues a dead or delivered delivery.

func (*WebhooksService) RedeliverDead added in v1.3.0

func (s *WebhooksService) RedeliverDead(ctx context.Context, subscriptionID string) (int, error)

RedeliverDead returns every dead delivery to pending and reports how many it moved. An empty subscriptionID covers the whole tenant. Admin scope.

The per-delivery Redeliver is not a recovery path after an outage: the dead letters number in the thousands, and one call each is a script an operator has to write while the incident is still open.

func (*WebhooksService) Update

Update mutates a subscription: its URL, its event types, whether it is active, and its secret.

Only those four change. The API cannot rename a subscription, so a Name is REFUSED rather than dropped — silently ignoring it would report success for a rename that did not happen. Secret maps to the API's rotate_secret.

This method could not succeed before. It sent SubscriptionInput, whose name field carries no omitempty and whose secret field the API does not know under that name, into a handler that rejects an unknown field: every call returned VALIDATION "invalid request body". The signature is unchanged so no caller has to be edited — there is no working caller to break.

Jump to

Keyboard shortcuts

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