diff --git a/.spec-sha b/.spec-sha index 7dd08d4..567f72b 100644 --- a/.spec-sha +++ b/.spec-sha @@ -1 +1 @@ -6ace098c56527cf0a0e5018b67ec454412ee6926 +1e2fe608c41aefd1a51cd3701be42db3f41730c8 diff --git a/src/onepin/.fern/metadata.json b/src/onepin/.fern/metadata.json index 6f11267..da28c6e 100644 --- a/src/onepin/.fern/metadata.json +++ b/src/onepin/.fern/metadata.json @@ -30,7 +30,7 @@ } ] }, - "originGitCommit": "9e634eff3eb65ab32b4a77b6fee5e0d27aa126cf", + "originGitCommit": "8161f2e78f880139a10f4fbd560a506103452095", "originGitCommitIsDirty": false, "invokedBy": "ci", "ciProvider": "github" diff --git a/src/onepin/__init__.py b/src/onepin/__init__.py index 3fa3327..5543d6d 100644 --- a/src/onepin/__init__.py +++ b/src/onepin/__init__.py @@ -98,6 +98,7 @@ NumericOption, PaginationMeta, PlanLimits, + PlanLimitsCreditsRenewal, PlanTier, PortOut, PronunciationSuggestion, @@ -368,6 +369,7 @@ "OnepinClient": "._client", "PaginationMeta": ".types", "PlanLimits": ".types", + "PlanLimitsCreditsRenewal": ".types", "PlanTier": ".types", "PortOut": ".types", "PronunciationSuggestion": ".types", @@ -639,6 +641,7 @@ def __dir__(): "OnepinClient", "PaginationMeta", "PlanLimits", + "PlanLimitsCreditsRenewal", "PlanTier", "PortOut", "PronunciationSuggestion", diff --git a/src/onepin/dictionary/types/list_dictionary_entries_api_v1dictionary_get_request_language.py b/src/onepin/dictionary/types/list_dictionary_entries_api_v1dictionary_get_request_language.py index a062a7d..225635d 100644 --- a/src/onepin/dictionary/types/list_dictionary_entries_api_v1dictionary_get_request_language.py +++ b/src/onepin/dictionary/types/list_dictionary_entries_api_v1dictionary_get_request_language.py @@ -3,5 +3,6 @@ import typing ListDictionaryEntriesApiV1DictionaryGetRequestLanguage = typing.Union[ - typing.Literal["de-de", "en-gb", "en-us", "es-es", "fr-fr", "it-it", "ja-jp", "ko-kr", "pt-br", "zh-cn"], typing.Any + typing.Literal["de-de", "en-gb", "en-us", "es-es", "es-mx", "fr-fr", "ja-jp", "ko-kr", "pt-br", "pt-pt", "zh-cn"], + typing.Any, ] diff --git a/src/onepin/dictionary/types/search_dictionary_entries_api_v1dictionary_search_get_request_language_item.py b/src/onepin/dictionary/types/search_dictionary_entries_api_v1dictionary_search_get_request_language_item.py index 91bec6a..52ef385 100644 --- a/src/onepin/dictionary/types/search_dictionary_entries_api_v1dictionary_search_get_request_language_item.py +++ b/src/onepin/dictionary/types/search_dictionary_entries_api_v1dictionary_search_get_request_language_item.py @@ -3,5 +3,6 @@ import typing SearchDictionaryEntriesApiV1DictionarySearchGetRequestLanguageItem = typing.Union[ - typing.Literal["de-de", "en-gb", "en-us", "es-es", "fr-fr", "it-it", "ja-jp", "ko-kr", "pt-br", "zh-cn"], typing.Any + typing.Literal["de-de", "en-gb", "en-us", "es-es", "es-mx", "fr-fr", "ja-jp", "ko-kr", "pt-br", "pt-pt", "zh-cn"], + typing.Any, ] diff --git a/src/onepin/reference.md b/src/onepin/reference.md index 0271a82..ccdb161 100644 --- a/src/onepin/reference.md +++ b/src/onepin/reference.md @@ -2682,7 +2682,7 @@ client.voices.list()
-**search:** `typing.Optional[str]` — Full-text search against voice name, description, and tags. +**search:** `typing.Optional[str]` — Searches name, tags, and the voice's summary-derived descriptor text (closely tracks the served description; summary beyond 200 chars is not searched).
@@ -5316,9 +5316,14 @@ attempt a workflow run. `remaining` is a display convenience derived from settled ledger entries and may temporarily exceed `balance` while a workflow run holds an open reserve. `used` reflects credits consumed in the current billing period. `plan_grant` is the total monthly credit allowance for the -caller's plan, enabling a "X / Y used" display. `period_start` and -`period_end` mark the boundaries of the current billing window; free-tier -callers use a calendar-month boundary. +caller's plan, enabling a "X / Y used" display. `period_start` is the current +credit anchor and `period_end` is the next EXPECTED credit-reset boundary +(`period_start` + 1 month), or null when no reset is promised — Free/one-time, +unanchored, a canceling/ended entitlement, or a monthly renewal whose boundary +passed without confirmed payment. `period_end` is the expected boundary, not a +guaranteed grant time: monthly credits stay gated on successful Stripe payment. +For an annual subscriber this GET may perform idempotent maintenance, granting +any due intermediate monthly credits before returning; retries remain safe. diff --git a/src/onepin/types/__init__.py b/src/onepin/types/__init__.py index c2f5808..48dd18f 100644 --- a/src/onepin/types/__init__.py +++ b/src/onepin/types/__init__.py @@ -99,6 +99,7 @@ from .numeric_option import NumericOption from .pagination_meta import PaginationMeta from .plan_limits import PlanLimits + from .plan_limits_credits_renewal import PlanLimitsCreditsRenewal from .plan_tier import PlanTier from .port_out import PortOut from .pronunciation_suggestion import PronunciationSuggestion @@ -295,6 +296,7 @@ "NumericOption": ".numeric_option", "PaginationMeta": ".pagination_meta", "PlanLimits": ".plan_limits", + "PlanLimitsCreditsRenewal": ".plan_limits_credits_renewal", "PlanTier": ".plan_tier", "PortOut": ".port_out", "PronunciationSuggestion": ".pronunciation_suggestion", @@ -515,6 +517,7 @@ def __dir__(): "NumericOption", "PaginationMeta", "PlanLimits", + "PlanLimitsCreditsRenewal", "PlanTier", "PortOut", "PronunciationSuggestion", diff --git a/src/onepin/types/api_error_detail.py b/src/onepin/types/api_error_detail.py index 8b6b8eb..1c95971 100644 --- a/src/onepin/types/api_error_detail.py +++ b/src/onepin/types/api_error_detail.py @@ -9,6 +9,8 @@ class ApiErrorDetail(UniversalBaseModel): field: str message: str + line_numbers: typing.Optional[typing.List[int]] = None + min_chars: typing.Optional[int] = None if IS_PYDANTIC_V2: model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 diff --git a/src/onepin/types/balance_response.py b/src/onepin/types/balance_response.py index 18e36c6..6a77746 100644 --- a/src/onepin/types/balance_response.py +++ b/src/onepin/types/balance_response.py @@ -13,7 +13,26 @@ class BalanceResponse(UniversalBaseModel): Per-user credit balance + period anchor (consumed by GET /users/me/credits). """ - balance: int + balance: int = pydantic.Field() + """ + Total spendable credits = monthly_balance + free_balance. + """ + + monthly_balance: typing.Optional[int] = pydantic.Field(default=None) + """ + Expiring bucket: the current paid cycle's allowance, replaced each renewal. 0 on Free. + """ + + free_balance: typing.Optional[int] = pydantic.Field(default=None) + """ + Lifetime bucket: the one-time Free grant. Never expires; spent last (after monthly). + """ + + free_grant: typing.Optional[int] = pydantic.Field(default=None) + """ + All-time ceiling of the lifetime free bucket. + """ + used: typing.Optional[int] = pydantic.Field(default=None) """ Ledger-derived credits used in the current billing period. @@ -24,10 +43,28 @@ class BalanceResponse(UniversalBaseModel): Ledger-derived settled credits remaining for display only. Excludes in-flight open reserves, so this may exceed `balance` while a workflow is executing. Use `balance` for gate decisions. """ - period_start: typing.Optional[dt.datetime] = None - period_end: typing.Optional[dt.datetime] = None + period_start: typing.Optional[dt.datetime] = pydantic.Field(default=None) + """ + Start of the current credit period (the stored credit anchor). Null on Free/unanchored accounts. + """ + + period_end: typing.Optional[dt.datetime] = pydantic.Field(default=None) + """ + Next EXPECTED credit-reset boundary (`period_start` + 1 calendar month), or null when no reset is currently promised: Free/one-time or unanchored accounts, a canceling/ended entitlement with no future grant, or a monthly renewal whose boundary has already passed without confirmed payment. This is the expected boundary, not a guaranteed grant time — monthly credits (including an annual subscription's renewal) stay gated on successful Stripe payment and may become available shortly after this time. An annual subscription's intermediate monthly boundaries are deterministic and are granted on access. Distinct from `CustomerSubscriptionResponse.current_period_end`, which remains the Stripe billing/entitlement boundary and must not be used as the credit-refresh time. + """ + plan_grant: int plan_tier: PlanTier + overage_rate_cents_per_credit: typing.Optional[float] = None + overage_cents: typing.Optional[int] = pydantic.Field(default=None) + """ + Overage billed so far this billing cycle, in cents. + """ + + credits_absorbed: typing.Optional[float] = pydantic.Field(default=None) + """ + Total credits discounted by floor-rounding this billing period. + """ if IS_PYDANTIC_V2: model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 diff --git a/src/onepin/types/estimate_response.py b/src/onepin/types/estimate_response.py index d17cae6..bdede5b 100644 --- a/src/onepin/types/estimate_response.py +++ b/src/onepin/types/estimate_response.py @@ -22,6 +22,9 @@ class EstimateResponse(UniversalBaseModel): current_balance: int deficit_at_max: int can_run: bool + overage_rate_cents_per_credit: typing.Optional[float] = None + will_incur_overage: typing.Optional[bool] = None + estimated_overage_cents: typing.Optional[int] = None if IS_PYDANTIC_V2: model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 diff --git a/src/onepin/types/plan_limits.py b/src/onepin/types/plan_limits.py index 71c2c19..95d541c 100644 --- a/src/onepin/types/plan_limits.py +++ b/src/onepin/types/plan_limits.py @@ -4,6 +4,7 @@ import pydantic from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from .plan_limits_credits_renewal import PlanLimitsCreditsRenewal class PlanLimits(UniversalBaseModel): @@ -18,6 +19,9 @@ class PlanLimits(UniversalBaseModel): retention_days: typing.Optional[int] = None byok_enabled: typing.Optional[bool] = None auto_fix_enabled: typing.Optional[bool] = None + credits_renewal: typing.Optional[PlanLimitsCreditsRenewal] = None + downloads_enabled: typing.Optional[bool] = None + overage_rate_cents_per_credit: typing.Optional[float] = None if IS_PYDANTIC_V2: model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 diff --git a/src/onepin/types/plan_limits_credits_renewal.py b/src/onepin/types/plan_limits_credits_renewal.py new file mode 100644 index 0000000..29af1b6 --- /dev/null +++ b/src/onepin/types/plan_limits_credits_renewal.py @@ -0,0 +1,5 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +PlanLimitsCreditsRenewal = typing.Union[typing.Literal["monthly", "one_time"], typing.Any] diff --git a/src/onepin/types/voice_out.py b/src/onepin/types/voice_out.py index c4e7610..3f736aa 100644 --- a/src/onepin/types/voice_out.py +++ b/src/onepin/types/voice_out.py @@ -73,11 +73,6 @@ class VoiceOut(UniversalBaseModel): Freeform keyword tags for filtering and search. """ - descriptor: typing.Optional[str] = pydantic.Field(default=None) - """ - Short one-line voice personality descriptor. - """ - uses_count: typing.Optional[int] = pydantic.Field(default=None) """ Number of times this voice has been used in workflow runs across the platform. diff --git a/src/onepin/types/voice_similar_out.py b/src/onepin/types/voice_similar_out.py index d20d6fe..bc97998 100644 --- a/src/onepin/types/voice_similar_out.py +++ b/src/onepin/types/voice_similar_out.py @@ -73,11 +73,6 @@ class VoiceSimilarOut(UniversalBaseModel): Freeform keyword tags for filtering and search. """ - descriptor: typing.Optional[str] = pydantic.Field(default=None) - """ - Short one-line voice personality descriptor. - """ - uses_count: typing.Optional[int] = pydantic.Field(default=None) """ Number of times this voice has been used in workflow runs across the platform. diff --git a/src/onepin/types/workflow_run_detail_out.py b/src/onepin/types/workflow_run_detail_out.py index f018add..8d4d115 100644 --- a/src/onepin/types/workflow_run_detail_out.py +++ b/src/onepin/types/workflow_run_detail_out.py @@ -36,6 +36,11 @@ class WorkflowRunDetailOut(UniversalBaseModel): has_export: typing.Optional[bool] = None triggered_by: typing.Optional[TriggeredByOut] = None credits: typing.Optional[int] = None + credits_absorbed: typing.Optional[float] = pydantic.Field(default=None) + """ + Credits discounted by floor-rounding for this run. This is the sub-credit remainder above the charged (floored) credits; charged credits plus this value reconstructs true cost only for fully covered, uncapped runs. Returns 0 for unsettled or legacy runs. + """ + definition_snapshot: typing.Optional[typing.Dict[str, typing.Any]] = None if IS_PYDANTIC_V2: diff --git a/src/onepin/types/workflow_run_outputs_out.py b/src/onepin/types/workflow_run_outputs_out.py index 73c4dcb..41e5554 100644 --- a/src/onepin/types/workflow_run_outputs_out.py +++ b/src/onepin/types/workflow_run_outputs_out.py @@ -11,6 +11,11 @@ class WorkflowRunOutputsOut(UniversalBaseModel): run_id: str run_status: str credits: typing.Optional[int] = None + credits_absorbed: typing.Optional[float] = pydantic.Field(default=None) + """ + Credits discounted by floor-rounding for this run. This is the sub-credit remainder above the charged (floored) credits; charged credits plus this value reconstructs true cost only for fully covered, uncapped runs. Returns 0 for unsettled or legacy runs. + """ + outputs: typing.List[WorkflowRunSinkOutputOut] if IS_PYDANTIC_V2: diff --git a/src/onepin/users/client.py b/src/onepin/users/client.py index 4de6674..e2a5d91 100644 --- a/src/onepin/users/client.py +++ b/src/onepin/users/client.py @@ -42,9 +42,14 @@ def get_my_credits(self, *, request_options: typing.Optional[RequestOptions] = N settled ledger entries and may temporarily exceed `balance` while a workflow run holds an open reserve. `used` reflects credits consumed in the current billing period. `plan_grant` is the total monthly credit allowance for the - caller's plan, enabling a "X / Y used" display. `period_start` and - `period_end` mark the boundaries of the current billing window; free-tier - callers use a calendar-month boundary. + caller's plan, enabling a "X / Y used" display. `period_start` is the current + credit anchor and `period_end` is the next EXPECTED credit-reset boundary + (`period_start` + 1 month), or null when no reset is promised — Free/one-time, + unanchored, a canceling/ended entitlement, or a monthly renewal whose boundary + passed without confirmed payment. `period_end` is the expected boundary, not a + guaranteed grant time: monthly credits stay gated on successful Stripe payment. + For an annual subscriber this GET may perform idempotent maintenance, granting + any due intermediate monthly credits before returning; retries remain safe. Parameters ---------- @@ -276,9 +281,14 @@ async def get_my_credits( settled ledger entries and may temporarily exceed `balance` while a workflow run holds an open reserve. `used` reflects credits consumed in the current billing period. `plan_grant` is the total monthly credit allowance for the - caller's plan, enabling a "X / Y used" display. `period_start` and - `period_end` mark the boundaries of the current billing window; free-tier - callers use a calendar-month boundary. + caller's plan, enabling a "X / Y used" display. `period_start` is the current + credit anchor and `period_end` is the next EXPECTED credit-reset boundary + (`period_start` + 1 month), or null when no reset is promised — Free/one-time, + unanchored, a canceling/ended entitlement, or a monthly renewal whose boundary + passed without confirmed payment. `period_end` is the expected boundary, not a + guaranteed grant time: monthly credits stay gated on successful Stripe payment. + For an annual subscriber this GET may perform idempotent maintenance, granting + any due intermediate monthly credits before returning; retries remain safe. Parameters ---------- diff --git a/src/onepin/users/raw_client.py b/src/onepin/users/raw_client.py index 6da6376..d86b812 100644 --- a/src/onepin/users/raw_client.py +++ b/src/onepin/users/raw_client.py @@ -39,9 +39,14 @@ def get_my_credits( settled ledger entries and may temporarily exceed `balance` while a workflow run holds an open reserve. `used` reflects credits consumed in the current billing period. `plan_grant` is the total monthly credit allowance for the - caller's plan, enabling a "X / Y used" display. `period_start` and - `period_end` mark the boundaries of the current billing window; free-tier - callers use a calendar-month boundary. + caller's plan, enabling a "X / Y used" display. `period_start` is the current + credit anchor and `period_end` is the next EXPECTED credit-reset boundary + (`period_start` + 1 month), or null when no reset is promised — Free/one-time, + unanchored, a canceling/ended entitlement, or a monthly renewal whose boundary + passed without confirmed payment. `period_end` is the expected boundary, not a + guaranteed grant time: monthly credits stay gated on successful Stripe payment. + For an annual subscriber this GET may perform idempotent maintenance, granting + any due intermediate monthly credits before returning; retries remain safe. Parameters ---------- @@ -385,9 +390,14 @@ async def get_my_credits( settled ledger entries and may temporarily exceed `balance` while a workflow run holds an open reserve. `used` reflects credits consumed in the current billing period. `plan_grant` is the total monthly credit allowance for the - caller's plan, enabling a "X / Y used" display. `period_start` and - `period_end` mark the boundaries of the current billing window; free-tier - callers use a calendar-month boundary. + caller's plan, enabling a "X / Y used" display. `period_start` is the current + credit anchor and `period_end` is the next EXPECTED credit-reset boundary + (`period_start` + 1 month), or null when no reset is promised — Free/one-time, + unanchored, a canceling/ended entitlement, or a monthly renewal whose boundary + passed without confirmed payment. `period_end` is the expected boundary, not a + guaranteed grant time: monthly credits stay gated on successful Stripe payment. + For an annual subscriber this GET may perform idempotent maintenance, granting + any due intermediate monthly credits before returning; retries remain safe. Parameters ---------- diff --git a/src/onepin/voices/client.py b/src/onepin/voices/client.py index 8ad7f77..b9e6cf4 100644 --- a/src/onepin/voices/client.py +++ b/src/onepin/voices/client.py @@ -107,7 +107,7 @@ def list( Repeat for OR search : typing.Optional[str] - Full-text search against voice name, description, and tags. + Searches name, tags, and the voice's summary-derived descriptor text (closely tracks the served description; summary beyond 200 chars is not searched). sort : typing.Optional[typing.Sequence[ListVoicesRequestSortItem]] Repeat for multi-sort. Pairs with `order` index-wise. @@ -556,7 +556,7 @@ async def list( Repeat for OR search : typing.Optional[str] - Full-text search against voice name, description, and tags. + Searches name, tags, and the voice's summary-derived descriptor text (closely tracks the served description; summary beyond 200 chars is not searched). sort : typing.Optional[typing.Sequence[ListVoicesRequestSortItem]] Repeat for multi-sort. Pairs with `order` index-wise. diff --git a/src/onepin/voices/raw_client.py b/src/onepin/voices/raw_client.py index ecfef41..fc0752b 100644 --- a/src/onepin/voices/raw_client.py +++ b/src/onepin/voices/raw_client.py @@ -103,7 +103,7 @@ def list( Repeat for OR search : typing.Optional[str] - Full-text search against voice name, description, and tags. + Searches name, tags, and the voice's summary-derived descriptor text (closely tracks the served description; summary beyond 200 chars is not searched). sort : typing.Optional[typing.Sequence[ListVoicesRequestSortItem]] Repeat for multi-sort. Pairs with `order` index-wise. @@ -685,7 +685,7 @@ async def list( Repeat for OR search : typing.Optional[str] - Full-text search against voice name, description, and tags. + Searches name, tags, and the voice's summary-derived descriptor text (closely tracks the served description; summary beyond 200 chars is not searched). sort : typing.Optional[typing.Sequence[ListVoicesRequestSortItem]] Repeat for multi-sort. Pairs with `order` index-wise. diff --git a/src/onepin/voices/types/list_voices_request_language_item.py b/src/onepin/voices/types/list_voices_request_language_item.py index 535d427..d2a3d6f 100644 --- a/src/onepin/voices/types/list_voices_request_language_item.py +++ b/src/onepin/voices/types/list_voices_request_language_item.py @@ -3,5 +3,6 @@ import typing ListVoicesRequestLanguageItem = typing.Union[ - typing.Literal["de-de", "en-gb", "en-us", "es-es", "fr-fr", "it-it", "ja-jp", "ko-kr", "pt-br", "zh-cn"], typing.Any + typing.Literal["de-de", "en-gb", "en-us", "es-es", "es-mx", "fr-fr", "ja-jp", "ko-kr", "pt-br", "pt-pt", "zh-cn"], + typing.Any, ]