Skip to main content

ducto.interface.models module

Pydantic schemas for credit store operations.

All store methods accept and return typed Pydantic models rather than raw dicts — validation at the boundary, clarity in the call sites.

class ducto.interface.models.AddCreditsResult(, transaction_id: str, user_id: str, amount: int, new_balance: int, lifetime_purchased: int = 0)

Bases: BaseModel

Result of adding credits to a user’s account.

amount : int

lifetime_purchased : int

model_config = {}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

new_balance : int

transaction_id : str

user_id : str

class ducto.interface.models.AddTeamMemberResult(, team_id: str = '', user_id: str = '', role: str = 'member')

Bases: BaseModel

Result of adding a team member.

model_config = {}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

role : str

team_id : str

user_id : str

class ducto.interface.models.AggregateStatsRow(, total_credits_consumed: int = 0, active_users: int = 0, avg_daily_spend: int = 0, top_model: str = '', top_user: str = '')

Bases: BaseModel

Aggregate statistics across all users in a time window.

active_users : int

avg_daily_spend : int

model_config = {}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

top_model : str

top_user : str

total_credits_consumed : int

class ducto.interface.models.AllowanceResult(, plan_id: str, allowance_remaining: int, period_start: str, period_end: str)

Bases: BaseModel

Result of checking plan allowance.

allowance_remaining : int

model_config = {}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

period_end : str

period_start : str

plan_id : str

class ducto.interface.models.BalanceResult(, user_id: str, balance: int = 0, lifetime_purchased: int = 0)

Bases: BaseModel

Current credit balance for a user.

balance : int

lifetime_purchased : int

model_config = {}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

user_id : str

class ducto.interface.models.CapCheckResult(, capped: bool = False, current_spend: int = 0, cap_limit: int = 0, action: str | None = None, model: str | None = None)

Bases: BaseModel

Result of checking a spend cap.

action : str | None

cap_limit : int

capped : bool

current_spend : int

model : str | None

model_config = {}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class ducto.interface.models.CheckFeatureResult(, user_id: str, feature: str, value: Any = None, has_feature: bool = False)

Bases: BaseModel

Result of checking a user’s feature entitlement.

feature : str

has_feature : bool

model_config = {}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

user_id : str

value : Any

class ducto.interface.models.CreateTeamResult(, team_id: str = '', name: str = '')

Bases: BaseModel

Result of creating a team.

model_config = {}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

name : str

team_id : str

class ducto.interface.models.CreditMetadata(, input_tokens: int | None = None, output_tokens: int | None = None, model: str | None = None, reference_type: str | None = None, reference_id: str | None = None, idempotency_key: str | None = None, fixed_job: str | None = None, **extra_data: Any)

Bases: BaseModel

Flexible metadata attached to credit transactions.

Known fields are typed; arbitrary extras pass through to JSONB.

fixed_job : str | None

idempotency_key : str | None

input_tokens : int | None

model : str | None

model_config = {'extra': 'allow'}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

output_tokens : int | None

reference_id : str | None

reference_type : str | None

class ducto.interface.models.DailySpendRow(, date: str = '', total_spend: int = 0, transaction_count: int = 0)

Bases: BaseModel

Daily spend aggregation in a time window.

date : str

model_config = {}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

total_spend : int

transaction_count : int

class ducto.interface.models.DeductionResult(, transaction_id: str, user_id: str, amount: int, balance_after: int, idempotent: bool = False, error: str | None = None)

Bases: BaseModel

Result of deducting credits after an operation completes.

amount is negative for deductions, positive for refunds.

amount : int

balance_after : int

error : str | None

idempotent : bool

model_config = {}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

transaction_id : str

user_id : str

class ducto.interface.models.GetUserPlanResult(*, user_id: str, plan_id: str | None = None, plan_name: str | None = None, free_allowance: int = 0, features: dict[str, ~typing.Any]=)

Bases: BaseModel

Result of fetching a user’s current plan.

features : dict[str, Any]

free_allowance : int

model_config = {}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

plan_id : str | None

plan_name : str | None

user_id : str

class ducto.interface.models.PlanDefinition(, id: str, name: str, free_allowance: Annotated[int, Ge(ge=0)] = 0, rate_overrides: dict[str, str] | None = None, features: dict[str, Any] | None = None)

Bases: BaseModel

Definition of a subscription plan with free allowance and rate overrides.

features : dict[str, Any] | None

free_allowance : int

id : str

model_config = {}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

name : str

rate_overrides : dict[str, str] | None

class ducto.interface.models.PricingConfigData(*, version: ~typing.Literal[1] = 1, models: dict[str, str], tools: dict[str, str] = , search: dict[str, str] = , cache: dict[str, str] = , fixed: dict[str, int] = , min_balance: int = 5, plans: dict[str, ~ducto.interface.models.PlanDefinition] | None = None)

Bases: BaseModel

Pricing configuration schema.

Mirrors the YAML config structure used by PricingEngine. Unified format with optional plan definitions.

cache : dict[str, str]

fixed : dict[str, int]

min_balance : int

model_config = {}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

models : dict[str, str]

plans : dict[str, PlanDefinition] | None

search : dict[str, str]

tools : dict[str, str]

version : Literal[1]

class ducto.interface.models.PricingConfigHistoryItem(, id: str, version: int, label: str | None = None, active: bool = False, created_at: str = '')

Bases: BaseModel

Lightweight summary for pricing version listing.

active : bool

created_at : str

id : str

label : str | None

model_config = {}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

version : int

class ducto.interface.models.PricingConfigResult(, id: str, config: PricingConfigData, version: int = 1, label: str | None = None)

Bases: BaseModel

Versioned pricing configuration fetched from the store.

config : PricingConfigData

id : str

label : str | None

model_config = {}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

version : int

class ducto.interface.models.RefundResult(, refund_transaction_id: str, original_transaction_id: str, user_id: str, amount: int = 0, new_balance: int = 0, error: str | None = None)

Bases: BaseModel

Result of refunding a credit deduction.

amount : int

error : str | None

model_config = {}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

new_balance : int

original_transaction_id : str

refund_transaction_id : str

user_id : str

class ducto.interface.models.ReserveResult(, reservation_id: str, user_id: str, amount: int, balance: int = 0, reserved_total: int = 0, error: str | None = None)

Bases: BaseModel

Result of reserving credits for an operation.

amount : int

balance : int

error : str | None

model_config = {}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

reservation_id : str

reserved_total : int

user_id : str

class ducto.interface.models.SetUserPlanResult(, user_id: str, plan_id: str)

Bases: BaseModel

Result of assigning a plan to a user.

model_config = {}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

plan_id : str

user_id : str

class ducto.interface.models.SetupResult(*, tables_created: list[str] = , rpcs_created: list[str] = , errors: list[str] = )

Bases: BaseModel

Report of what the setup step created or updated.

errors : list[str]

model_config = {}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

rpcs_created : list[str]

property success : bool

tables_created : list[str]

class ducto.interface.models.SpendByModelRow(, model: str = '', total_spend: int = 0, transaction_count: int = 0)

Bases: BaseModel

Aggregated spend for a single model in a time window.

model : str

model_config = {}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

total_spend : int

transaction_count : int

class ducto.interface.models.SpendByUserRow(, user_id: str = '', total_spend: int = 0, transaction_count: int = 0)

Bases: BaseModel

Aggregated spend for a single user in a time window.

model_config = {}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

total_spend : int

transaction_count : int

user_id : str

class ducto.interface.models.SpendCap(, user_id: str = '', type: Literal['daily', 'monthly'] = 'daily', model: str | None = None, limit: Annotated[int, Ge(ge=0)] = 0, action: Literal['deny', 'warn', 'notify'] = 'deny')

Bases: BaseModel

Configuration for a per-user spend cap.

action : Literal['deny', 'warn', 'notify']

cap_type : Literal['daily', 'monthly']

limit : int

model : str | None

model_config = {}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

user_id : str

class ducto.interface.models.SweepResult(, expired_count: int = 0, expired_amount: int = 0, dry_run: bool = False)

Bases: BaseModel

Result of sweeping expired credits.

dry_run : bool

expired_amount : int

expired_count : int

model_config = {}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class ducto.interface.models.Team(, team_id: str = '', name: str = '', balance: int = 0, member_count: int = 0, created_at: str = '')

Bases: BaseModel

A team with a shared credit balance pool.

balance : int

created_at : str

member_count : int

model_config = {}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

name : str

team_id : str

class ducto.interface.models.TeamBalanceResult(, team_id: str = '', name: str = '', balance: int = 0, member_count: int = 0)

Bases: BaseModel

Result of fetching team balance.

balance : int

member_count : int

model_config = {}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

name : str

team_id : str

class ducto.interface.models.TeamDeductionResult(, transaction_id: str = '', team_id: str = '', user_id: str = '', amount: int = 0, team_balance_after: int = 0, error: str | None = None)

Bases: BaseModel

Result of deducting credits from a team pool.

amount : int

error : str | None

model_config = {}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

team_balance_after : int

team_id : str

transaction_id : str

user_id : str

class ducto.interface.models.TeamMember(, user_id: str = '', role: str = '', spend_cap: int | None = None, total_spent: int = 0)

Bases: BaseModel

A member of a team with optional spend cap.

model_config = {}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

role : str

spend_cap : int | None

total_spent : int

user_id : str

class ducto.interface.models.TopUserRow(, user_id: str = '', total_spend: int = 0)

Bases: BaseModel

Top-spending user in a time window.

model_config = {}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

total_spend : int

user_id : str