Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .release-please-manifest.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{
".": "0.129.0"
".": "0.130.0"
}
13 changes: 13 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,18 @@
# Changelog

## [0.130.0](https://github.com/kernel/kernel-python-sdk/compare/v0.129.0...v0.130.0) (2026-10-24)


### Features

* Fall back to aliases after network token enrollment failures ([5930892](https://github.com/kernel/kernel-python-sdk/commit/5930892a91a3f212f27dfdaab4412bf972a4973f))


### Bug Fixes

* continue offset pagination past empty pages ([80908e4](https://github.com/kernel/kernel-python-sdk/commit/80908e4a5fae05aedc1db65f67b70a34781273d2))
* follow offset cursors in either direction ([bfcfa9a](https://github.com/kernel/kernel-python-sdk/commit/bfcfa9aac5a1420fced2960757ce80f197be257a))

## [0.129.0](https://github.com/kernel/kernel-python-sdk/compare/v0.128.0...v0.129.0) (2026-10-21)


Expand Down
2 changes: 2 additions & 0 deletions api.md
Original file line number Diff line number Diff line change
Expand Up @@ -602,6 +602,8 @@ from kernel.types.vaults import (
KernelCredentialVaultItemState,
KernelWalletState,
KernelWalletVaultItemSpec,
LinkShippingAddress,
LinkUserInfo,
ManagedAuthCredentialVaultField,
ManagedAuthCredentialVaultItemSpec,
ManagedAuthCredentialVaultItemSpecInput,
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[project]
name = "kernel"
version = "0.129.0"
version = "0.130.0"
description = "The official Python library for the kernel API"
dynamic = ["readme"]
license = "Apache-2.0"
Expand Down
2 changes: 1 addition & 1 deletion src/kernel/_version.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.

__title__ = "kernel"
__version__ = "0.129.0" # x-release-please-version
__version__ = "0.130.0" # x-release-please-version
16 changes: 14 additions & 2 deletions src/kernel/pagination.py
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ def has_next_page(self) -> bool:
if has_more is not None and has_more is False:
return False

return super().has_next_page()
return self.next_page_info() is not None

@override
def next_page_info(self) -> Optional[PageInfo]:
Expand All @@ -133,6 +133,12 @@ def next_page_info(self) -> Optional[PageInfo]:
if next_offset == 0:
return None

# Cursors can move in either direction. Stop only when the server repeats
# the cursor and would re-request the same page.
request_offset = self._options.params.get("offset")
if isinstance(request_offset, int) and next_offset == request_offset:
return None

return PageInfo(params={"offset": next_offset})

@classmethod
Expand Down Expand Up @@ -165,7 +171,7 @@ def has_next_page(self) -> bool:
if has_more is not None and has_more is False:
return False

return super().has_next_page()
return self.next_page_info() is not None

@override
def next_page_info(self) -> Optional[PageInfo]:
Expand All @@ -184,6 +190,12 @@ def next_page_info(self) -> Optional[PageInfo]:
if next_offset == 0:
return None

# Cursors can move in either direction. Stop only when the server repeats
# the cursor and would re-request the same page.
request_offset = self._options.params.get("offset")
if isinstance(request_offset, int) and next_offset == request_offset:
return None

return PageInfo(params={"offset": next_offset})

@classmethod
Expand Down
10 changes: 6 additions & 4 deletions src/kernel/resources/vaults/items.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ def retrieve(
key: str,
*,
id_or_name: str,
expand: List[Literal["payment_methods"]] | Omit = omit,
expand: List[Literal["payment_methods", "link_user_info", "link_shipping_addresses"]] | Omit = omit,
wait: int | Omit = omit,
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
# The extra values given here take precedence over values defined on the client or passed to this method.
Expand Down Expand Up @@ -746,7 +746,8 @@ def perform_operation(
prefix or glob matching. When an item allows omitting it, the browser must have
exactly one open page.

timeout_ms: Total operation deadline in milliseconds, not a per-field timeout.
timeout_ms: Ignored. Fill sets no operation deadline; typing pace adapts to the length of
the values instead. Accepted for compatibility.

extra_headers: Send extra headers

Expand Down Expand Up @@ -1447,7 +1448,7 @@ async def retrieve(
key: str,
*,
id_or_name: str,
expand: List[Literal["payment_methods"]] | Omit = omit,
expand: List[Literal["payment_methods", "link_user_info", "link_shipping_addresses"]] | Omit = omit,
wait: int | Omit = omit,
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
# The extra values given here take precedence over values defined on the client or passed to this method.
Expand Down Expand Up @@ -2127,7 +2128,8 @@ async def perform_operation(
prefix or glob matching. When an item allows omitting it, the browser must have
exactly one open page.

timeout_ms: Total operation deadline in milliseconds, not a per-field timeout.
timeout_ms: Ignored. Fill sets no operation deadline; typing pace adapts to the length of
the values instead. Accepted for compatibility.

extra_headers: Send extra headers

Expand Down
2 changes: 2 additions & 0 deletions src/kernel/types/vaults/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from __future__ import annotations

from .vault_item import VaultItem as VaultItem
from .link_user_info import LinkUserInfo as LinkUserInfo
from .vault_item_event import VaultItemEvent as VaultItemEvent
from .kernel_card_state import KernelCardState as KernelCardState
from .vault_item_action import VaultItemAction as VaultItemAction
Expand All @@ -18,6 +19,7 @@
from .vault_payment_method import VaultPaymentMethod as VaultPaymentMethod
from .card_vault_item_state import CardVaultItemState as CardVaultItemState
from .credential_vault_item import CredentialVaultItem as CredentialVaultItem
from .link_shipping_address import LinkShippingAddress as LinkShippingAddress
from .vault_fill_field_param import VaultFillFieldParam as VaultFillFieldParam
from .wallet_vault_item_spec import WalletVaultItemSpec as WalletVaultItemSpec
from .vault_fill_field_result import VaultFillFieldResult as VaultFillFieldResult
Expand Down
31 changes: 30 additions & 1 deletion src/kernel/types/vaults/card_vault_item_spec.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
"LinkCardVaultItemSpec",
"LinkCardVaultItemSpecLineItem",
"LinkCardVaultItemSpecLineItemTotal",
"LinkCardVaultItemSpecRecurring",
"LinkCardVaultItemSpecTotal",
"AgentCardCardVaultItemSpec",
]
Expand Down Expand Up @@ -47,6 +48,18 @@ class LinkCardVaultItemSpecLineItem(BaseModel):
url: Optional[str] = None


class LinkCardVaultItemSpecRecurring(BaseModel):
"""Recurring terms for a subscription or other repeated purchase.

The amount becomes the spending limit for each period of interval_count intervals, for example every 2 weeks. The merchant schedules charges. The card stays ready after each charge until it expires or is deleted; do not create a new card each period. Deleting the card, its wallet or its vault first cancels the credential with Link, so later charges decline; if Link cannot be reached, deletion returns 409 provider_revocation_pending and should be retried. Deletion does not cancel the subscription with the merchant. Recurring terms cannot be changed once the card is authorized.
"""

interval: Literal["day", "week", "month", "year"]

interval_count: Optional[int] = None
"""Number of intervals per period. Link defaults it to 1."""


class LinkCardVaultItemSpecTotal(BaseModel):
amount: int
"""Total amount in minor currency units."""
Expand All @@ -63,7 +76,10 @@ class LinkCardVaultItemSpec(BaseModel):
"""

amount: int
"""Integer amount in minor currency units, at most 50000."""
"""Integer amount in minor currency units, at most 50000.

With recurring, the spending limit per period, not a lifetime total.
"""

context: str

Expand All @@ -89,6 +105,19 @@ class LinkCardVaultItemSpec(BaseModel):

metadata: Optional[Dict[str, str]] = None

recurring: Optional[LinkCardVaultItemSpecRecurring] = None
"""Recurring terms for a subscription or other repeated purchase.

The amount becomes the spending limit for each period of interval_count
intervals, for example every 2 weeks. The merchant schedules charges. The card
stays ready after each charge until it expires or is deleted; do not create a
new card each period. Deleting the card, its wallet or its vault first cancels
the credential with Link, so later charges decline; if Link cannot be reached,
deletion returns 409 provider_revocation_pending and should be retried. Deletion
does not cancel the subscription with the merchant. Recurring terms cannot be
changed once the card is authorized.
"""

totals: Optional[List[LinkCardVaultItemSpecTotal]] = None


Expand Down
31 changes: 30 additions & 1 deletion src/kernel/types/vaults/card_vault_item_spec_param.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
"LinkCardVaultItemSpec",
"LinkCardVaultItemSpecLineItem",
"LinkCardVaultItemSpecLineItemTotal",
"LinkCardVaultItemSpecRecurring",
"LinkCardVaultItemSpecTotal",
"AgentCardCardVaultItemSpec",
]
Expand Down Expand Up @@ -47,6 +48,18 @@ class LinkCardVaultItemSpecLineItem(TypedDict, total=False):
url: str


class LinkCardVaultItemSpecRecurring(TypedDict, total=False):
"""Recurring terms for a subscription or other repeated purchase.

The amount becomes the spending limit for each period of interval_count intervals, for example every 2 weeks. The merchant schedules charges. The card stays ready after each charge until it expires or is deleted; do not create a new card each period. Deleting the card, its wallet or its vault first cancels the credential with Link, so later charges decline; if Link cannot be reached, deletion returns 409 provider_revocation_pending and should be retried. Deletion does not cancel the subscription with the merchant. Recurring terms cannot be changed once the card is authorized.
"""

interval: Required[Literal["day", "week", "month", "year"]]

interval_count: int
"""Number of intervals per period. Link defaults it to 1."""


class LinkCardVaultItemSpecTotal(TypedDict, total=False):
amount: Required[int]
"""Total amount in minor currency units."""
Expand All @@ -63,7 +76,10 @@ class LinkCardVaultItemSpec(TypedDict, total=False):
"""

amount: Required[int]
"""Integer amount in minor currency units, at most 50000."""
"""Integer amount in minor currency units, at most 50000.

With recurring, the spending limit per period, not a lifetime total.
"""

context: Required[str]

Expand All @@ -89,6 +105,19 @@ class LinkCardVaultItemSpec(TypedDict, total=False):

metadata: Dict[str, str]

recurring: LinkCardVaultItemSpecRecurring
"""Recurring terms for a subscription or other repeated purchase.

The amount becomes the spending limit for each period of interval_count
intervals, for example every 2 weeks. The merchant schedules charges. The card
stays ready after each charge until it expires or is deleted; do not create a
new card each period. Deleting the card, its wallet or its vault first cancels
the credential with Link, so later charges decline; if Link cannot be reached,
deletion returns 409 provider_revocation_pending and should be retried. Deletion
does not cancel the subscription with the merchant. Recurring terms cannot be
changed once the card is authorized.
"""

totals: Iterable[LinkCardVaultItemSpecTotal]


Expand Down
2 changes: 1 addition & 1 deletion src/kernel/types/vaults/credential_account_vault_item.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ class AvailableExpansion(BaseModel):

description: str

type: Literal["payment_methods"]
type: Literal["payment_methods", "link_user_info", "link_shipping_addresses"]


class AvailableOperation(BaseModel):
Expand Down
2 changes: 1 addition & 1 deletion src/kernel/types/vaults/credential_vault_item.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ class AvailableExpansion(BaseModel):

description: str

type: Literal["payment_methods"]
type: Literal["payment_methods", "link_user_info", "link_shipping_addresses"]


class AvailableOperation(BaseModel):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,4 +57,8 @@ class FillVaultItemOperationRequestParam(TypedDict, total=False):
"""

timeout_ms: int
"""Total operation deadline in milliseconds, not a per-field timeout."""
"""Ignored.

Fill sets no operation deadline; typing pace adapts to the length of the values
instead. Accepted for compatibility.
"""
6 changes: 5 additions & 1 deletion src/kernel/types/vaults/item_perform_operation_params.py
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,11 @@ class FillVaultItemOperationRequest(TypedDict, total=False):
"""

timeout_ms: int
"""Total operation deadline in milliseconds, not a per-field timeout."""
"""Ignored.
Fill sets no operation deadline; typing pace adapts to the length of the values
instead. Accepted for compatibility.
"""


class OnePasswordRequestAccessVaultItemOperationRequest(TypedDict, total=False):
Expand Down
2 changes: 1 addition & 1 deletion src/kernel/types/vaults/item_retrieve_params.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
class ItemRetrieveParams(TypedDict, total=False):
id_or_name: Required[str]

expand: List[Literal["payment_methods"]]
expand: List[Literal["payment_methods", "link_user_info", "link_shipping_addresses"]]
"""Live fields advertised by `available_expansions` to include in `expanded`."""

wait: int
Expand Down
7 changes: 5 additions & 2 deletions src/kernel/types/vaults/kernel_card_state.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,11 @@ class KernelCardState(BaseModel):
"requested", "pending_authorization", "ready", "consumed", "expired", "declined", "recovery_required"
]
"""
pending_authorization on a Visa purchase waits for the cardholder to approve it
through the spend_approval action; an unused link expires after 30 minutes.
pending_authorization waits for cardholder approval on Visa purchases or fresh
security-code collection on alias-mode purchases through the spend_approval
action; an unused link expires after 30 minutes. Alias-mode cards become ready
after collection and expire at the temporary security-code alias deadline, by
default five minutes later. An expired alias purchase requires a new card.
recovery_required means verification, approving the purchase or issuing the
one-time code has an unresolved outcome. A server-classified initial attestation
failure before intent dispatch may advertise restart_verification to prepare a
Expand Down
2 changes: 1 addition & 1 deletion src/kernel/types/vaults/kernel_card_vault_item_spec.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
class KernelCardVaultItemSpec(BaseModel):
"""One live purchase with a Kernel-enrolled card.

Authorization obtains an agentic network token number, expiry and one-time 3-digit code. They are stored encrypted for the fill operation, which types them only on merchant_url's origin; the merchant's own checkout submits the payment. The one-time code is valid until the item's expires_at; fill and submit checkout before then. Mastercard purchases need no cardholder approval. A Visa purchase returns a spend_approval action: the cardholder approves it with a Visa passkey, and Kernel registers a Visa intent for one transaction up to the amount before issuing the code. For supported cards whose network cannot be enrolled for agentic tokens, authorize prepares checkout details without issuing a one-time code. The card can be filled into one checkout before its expires_at, one hour after authorization. Fill types those details on merchant_url's origin. The amount, merchant_url and merchant_country are recorded but do not restrict payment requests sent by the browser. Card updates are not supported; delete and create a new item instead.
Authorization obtains an agentic network token number, expiry and one-time 3-digit code. They are stored encrypted for the fill operation, which types them only on merchant_url's origin; the merchant's own checkout submits the payment. The one-time code is valid until the item's expires_at; fill and submit checkout before then. Mastercard purchases need no cardholder approval. A Visa purchase returns a spend_approval action: the cardholder approves it with a Visa passkey, and Kernel registers a Visa intent for one transaction up to the amount before issuing the code. For supported cards whose network cannot be enrolled for agentic tokens, authorize returns pending_authorization with a spend_approval action to collect a fresh security code in a hosted field. Once collected, the card is ready and can be filled before its expires_at, by default five minutes after collection. An expired card requires a new purchase. Fill types those details on merchant_url's origin. The amount, merchant_url and merchant_country are recorded but do not restrict payment requests sent by the browser. Card updates are not supported; delete and create a new item instead.
"""

amount: int
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
class KernelCardVaultItemSpecParam(TypedDict, total=False):
"""One live purchase with a Kernel-enrolled card.

Authorization obtains an agentic network token number, expiry and one-time 3-digit code. They are stored encrypted for the fill operation, which types them only on merchant_url's origin; the merchant's own checkout submits the payment. The one-time code is valid until the item's expires_at; fill and submit checkout before then. Mastercard purchases need no cardholder approval. A Visa purchase returns a spend_approval action: the cardholder approves it with a Visa passkey, and Kernel registers a Visa intent for one transaction up to the amount before issuing the code. For supported cards whose network cannot be enrolled for agentic tokens, authorize prepares checkout details without issuing a one-time code. The card can be filled into one checkout before its expires_at, one hour after authorization. Fill types those details on merchant_url's origin. The amount, merchant_url and merchant_country are recorded but do not restrict payment requests sent by the browser. Card updates are not supported; delete and create a new item instead.
Authorization obtains an agentic network token number, expiry and one-time 3-digit code. They are stored encrypted for the fill operation, which types them only on merchant_url's origin; the merchant's own checkout submits the payment. The one-time code is valid until the item's expires_at; fill and submit checkout before then. Mastercard purchases need no cardholder approval. A Visa purchase returns a spend_approval action: the cardholder approves it with a Visa passkey, and Kernel registers a Visa intent for one transaction up to the amount before issuing the code. For supported cards whose network cannot be enrolled for agentic tokens, authorize returns pending_authorization with a spend_approval action to collect a fresh security code in a hosted field. Once collected, the card is ready and can be filled before its expires_at, by default five minutes after collection. An expired card requires a new purchase. Fill types those details on merchant_url's origin. The amount, merchant_url and merchant_country are recorded but do not restrict payment requests sent by the browser. Card updates are not supported; delete and create a new item instead.
"""

amount: Required[int]
Expand Down
53 changes: 53 additions & 0 deletions src/kernel/types/vaults/link_shipping_address.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.

from typing import Optional

from ..._models import BaseModel

__all__ = ["LinkShippingAddress", "Address"]


class Address(BaseModel):
"""Link's nullable postal address fields.
Omitted from the shipping address when Link reports null.
"""

administrative_area: Optional[str] = None
"""State, province or region."""

country_code: Optional[str] = None

dependent_locality: Optional[str] = None

line_1: Optional[str] = None

line_2: Optional[str] = None

locality: Optional[str] = None
"""City or town."""

name: Optional[str] = None

postal_code: Optional[str] = None

sorting_code: Optional[str] = None


class LinkShippingAddress(BaseModel):
"""
One entry of Link's `GET /shipping_addresses` response, passed through as Link reports it. Kernel never stores it.
"""

id: str
"""Link shipping address ID."""

is_default: bool

nickname: Optional[str] = None

address: Optional[Address] = None
"""Link's nullable postal address fields.
Omitted from the shipping address when Link reports null.
"""
Loading
Loading