diff --git a/.github/tests/update-coverage-security.test.mjs b/.github/tests/update-coverage-security.test.mjs index 5c43c6fa..707ebd44 100644 --- a/.github/tests/update-coverage-security.test.mjs +++ b/.github/tests/update-coverage-security.test.mjs @@ -61,10 +61,12 @@ test('changes are restricted to the allowlist before validation', () => { assert.ok(jobs.generate.indexOf(snapshot) < jobs.generate.indexOf(verify)); assert.match(snapshot, /mcp-update-disallowed-paths\.sh/); assert.match(snapshot, /git reset -q --hard\n\s+git clean -fdq/); - assert.match(snapshot, /MAIN_SHA: \$\{\{ steps\.prepare\.outputs\.main_sha \}\}/); - assert.match(snapshot, /git reset -q --soft "\$MAIN_SHA"\n\s+git add -A/); + assert.match(snapshot, /AGENT_BASE: \$\{\{ steps\.prepare\.outputs\.agent_base \}\}/); + assert.match(snapshot, /git reset -q --soft "\$AGENT_BASE"\n\s+git add -A/); const prepare = step('generate', 'Prepare update branch and SDK diff'); assert.match(prepare, /main_sha=\$\(git rev-parse origin\/main\)/); + assert.match(prepare, /git rebase origin\/main; then[\s\S]*else\n\s+echo "rebased=true"/); + assert.match(prepare, /agent_base=\$\(git rev-parse HEAD\)[\s\S]*agent_base_tree=/); // Only a branch without human commits may be regenerated from main. assert.match( prepare, @@ -107,6 +109,14 @@ test('publishing runs in a separate job that never executes repository code', () assert.match(apply, /git apply --index "\$RUNNER_TEMP\/mcp-coverage-update\/changes\.patch"/); assert.match(apply, /mcp-update-disallowed-paths\.sh/); assert.match(apply, /100644\|100755\|000000/); + // Publishing rebuilds the exact head the changes were validated on, so human + // commits on the update branch are never squashed or dropped. + assert.match( + apply, + /if \[\[ "\$REBASED" == true \]\]; then\n\s+git switch -c \S+ "\$UPDATE_SHA"\n\s+git rebase -q "\$MAIN_SHA"/, + ); + assert.match(apply, /"\$\(git rev-parse 'HEAD\^\{tree\}'\)" != "\$AGENT_BASE_TREE"[\s\S]*exit 1/); + assert.ok(apply.indexOf('AGENT_BASE_TREE') < apply.indexOf('git apply --index')); const mint = jobs.publish.indexOf(step('publish', 'Generate MCP repository token')); assert.ok(jobs.publish.indexOf(apply) < mint); assert.doesNotMatch(jobs.publish.slice(0, mint).join(''), /GH_TOKEN:/); diff --git a/.github/workflows/update-mcp-coverage.yml b/.github/workflows/update-mcp-coverage.yml index bab066cc..33d39ec7 100644 --- a/.github/workflows/update-mcp-coverage.yml +++ b/.github/workflows/update-mcp-coverage.yml @@ -61,6 +61,8 @@ jobs: changed: ${{ steps.snapshot.outputs.changed }} main_sha: ${{ steps.prepare.outputs.main_sha }} update_sha: ${{ steps.prepare.outputs.update_sha }} + rebased: ${{ steps.prepare.outputs.rebased }} + agent_base_tree: ${{ steps.prepare.outputs.agent_base_tree }} env: SDK_VERSION: ${{ needs.sdk-version.outputs.version }} SDK_SHA: ${{ needs.sdk-version.outputs.sha }} @@ -126,10 +128,16 @@ jobs: fi echo "::warning::$UPDATE_BRANCH conflicts with main; regenerating it from main." git switch -C "$UPDATE_BRANCH" origin/main + else + echo "rebased=true" >> "$GITHUB_OUTPUT" fi else git switch -c "$UPDATE_BRANCH" origin/main fi + # The agent's changes are published on top of this head, so human + # commits on the update branch keep their content and authorship. + echo "agent_base=$(git rev-parse HEAD)" >> "$GITHUB_OUTPUT" + echo "agent_base_tree=$(git rev-parse 'HEAD^{tree}')" >> "$GITHUB_OUTPUT" old_version=$(jq -er '.dependencies["@onkernel/sdk"]' package.json) if [[ "$old_version" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]] && @@ -221,9 +229,9 @@ jobs: id: snapshot working-directory: mcp env: - MAIN_SHA: ${{ steps.prepare.outputs.main_sha }} + AGENT_BASE: ${{ steps.prepare.outputs.agent_base }} run: | - git reset -q --soft "$MAIN_SHA" + git reset -q --soft "$AGENT_BASE" git add -A git diff --cached --name-only --no-renames -z \ | bash ../.github/scripts/mcp-update-disallowed-paths.sh > "$RUNNER_TEMP/excluded-paths" @@ -276,6 +284,8 @@ jobs: SDK_VERSION: ${{ needs.sdk-version.outputs.version }} MAIN_SHA: ${{ needs.generate.outputs.main_sha }} UPDATE_SHA: ${{ needs.generate.outputs.update_sha }} + REBASED: ${{ needs.generate.outputs.rebased }} + AGENT_BASE_TREE: ${{ needs.generate.outputs.agent_base_tree }} UPDATE_BRANCH: mcp-coverage-update steps: - name: Checkout updater scripts @@ -302,7 +312,16 @@ jobs: run: | git config user.name 'kernel-internal[bot]' git config user.email '260533166+kernel-internal[bot]@users.noreply.github.com' - git switch -c "$UPDATE_BRANCH" "$MAIN_SHA" + if [[ "$REBASED" == true ]]; then + git switch -c "$UPDATE_BRANCH" "$UPDATE_SHA" + git rebase -q "$MAIN_SHA" + else + git switch -c "$UPDATE_BRANCH" "$MAIN_SHA" + fi + if [[ "$(git rev-parse 'HEAD^{tree}')" != "$AGENT_BASE_TREE" ]]; then + echo "::error::The rebuilt update branch differs from the one the changes were validated on." + exit 1 + fi git apply --index "$RUNNER_TEMP/mcp-coverage-update/changes.patch" git diff --cached --name-only --no-renames -z \ | bash ../.github/scripts/mcp-update-disallowed-paths.sh > "$RUNNER_TEMP/disallowed-paths" diff --git a/.release-please-manifest.json b/.release-please-manifest.json index f12fff58..94e69931 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.132.0" + ".": "0.133.0" } diff --git a/CHANGELOG.md b/CHANGELOG.md index d2eb9470..db2f0b32 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,14 @@ # Changelog +## [0.133.0](https://github.com/kernel/kernel-node-sdk/compare/v0.132.0...v0.133.0) (2026-10-28) + + +### Features + +* Forward Idempotency-Key on playwright and REPL execution ([6a0b6b5](https://github.com/kernel/kernel-node-sdk/commit/6a0b6b52fe3eb64c619c7c53d0f5f0d83013fb36)) +* Select 1Password fill pages by target and return stored-token grants ([1d60d43](https://github.com/kernel/kernel-node-sdk/commit/1d60d4398eda7c00432c14bab3264c739ecd9284)) +* Support multiple Kernel wallet payment methods and payment requests ([e338fed](https://github.com/kernel/kernel-node-sdk/commit/e338fedec0766e6f214cc0bec287c8819f402e0b)) + ## [0.132.0](https://github.com/kernel/kernel-node-sdk/compare/v0.131.0...v0.132.0) (2026-10-26) diff --git a/api.md b/api.md index eb8d1a1e..ea5699e2 100644 --- a/api.md +++ b/api.md @@ -512,6 +512,8 @@ Methods: Types: +- AddPaymentMethodVaultItemOperationRequest +- AddPaymentMethodVaultItemOperationResult - AgentcardCheckoutAuthorization - AgentcardCheckoutPreparation - AgentcardPreparedProcessor @@ -545,6 +547,7 @@ Types: - KernelCredentialVaultItemSpec - KernelCredentialVaultItemSpecInput - KernelCredentialVaultItemState +- KernelPaymentRequestVaultItemSpec - KernelWalletState - KernelWalletVaultItemSpec - LinkShippingAddress @@ -564,8 +567,13 @@ Types: - OnePasswordRecoverVaultItemOperationRequest - OnePasswordRequestAccessVaultItemOperationRequest - PasskeyVaultItemOperationResult +- PaymentRequestVaultItem +- PaymentRequestVaultItemSpec +- PaymentRequestVaultItemState - PrepareCheckoutVaultItemOperationRequest - RegisterPasskeyVaultItemOperationRequest +- RemovePaymentMethodVaultItemOperationRequest +- RemovePaymentMethodVaultItemOperationResult - RestartVerificationVaultItemOperationRequest - VaultCardAliases - VaultCardFillField diff --git a/package.json b/package.json index 9eab8937..f3f49712 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@onkernel/sdk", - "version": "0.132.0", + "version": "0.133.0", "description": "The official TypeScript library for the Kernel API", "author": "Kernel <>", "types": "dist/index.d.ts", diff --git a/src/client.ts b/src/client.ts index 217cf6ab..56af4ee9 100644 --- a/src/client.ts +++ b/src/client.ts @@ -462,6 +462,7 @@ export class Kernel { } this._options = options; + this.idempotencyHeader = 'Idempotency-Key'; this.apiKey = apiKey; this.projectID = projectID; diff --git a/src/resources/vaults/index.ts b/src/resources/vaults/index.ts index df2d91f0..603815db 100644 --- a/src/resources/vaults/index.ts +++ b/src/resources/vaults/index.ts @@ -2,6 +2,8 @@ export { Items, + type AddPaymentMethodVaultItemOperationRequest, + type AddPaymentMethodVaultItemOperationResult, type AgentcardCheckoutAuthorization, type AgentcardCheckoutPreparation, type AgentcardPreparedProcessor, @@ -35,6 +37,7 @@ export { type KernelCredentialVaultItemSpec, type KernelCredentialVaultItemSpecInput, type KernelCredentialVaultItemState, + type KernelPaymentRequestVaultItemSpec, type KernelWalletState, type KernelWalletVaultItemSpec, type LinkShippingAddress, @@ -54,8 +57,13 @@ export { type OnePasswordRecoverVaultItemOperationRequest, type OnePasswordRequestAccessVaultItemOperationRequest, type PasskeyVaultItemOperationResult, + type PaymentRequestVaultItem, + type PaymentRequestVaultItemSpec, + type PaymentRequestVaultItemState, type PrepareCheckoutVaultItemOperationRequest, type RegisterPasskeyVaultItemOperationRequest, + type RemovePaymentMethodVaultItemOperationRequest, + type RemovePaymentMethodVaultItemOperationResult, type RestartVerificationVaultItemOperationRequest, type VaultCardAliases, type VaultCardFillField, diff --git a/src/resources/vaults/items.ts b/src/resources/vaults/items.ts index 3b84df6e..f63d9c82 100644 --- a/src/resources/vaults/items.ts +++ b/src/resources/vaults/items.ts @@ -156,6 +156,12 @@ export class Items extends APIResource { * `failed` or `unknown`. Fill never submits the page, so it is safe to retry after * a failure, an `unknown` outcome, or a transport error. * + * Connected Kernel wallets may advertise add_payment_method, which returns a + * single-use hosted card_enrollment link for a card, and remove_payment_method, + * which removes one card without affecting the others. Both operations require + * vaults:write in addition to vaults:use on the vault for scoped API keys, and + * return 403 without both permissions. + * * @example * ```ts * const vaultItemOperationResponse = @@ -188,8 +194,10 @@ export class Items extends APIResource { * Provider-specific authorization requirements and retry behavior are described in * the item's request schema. Do not use credential items to store, collect, or * fill credit card data, including card numbers (PANs), security codes (CVV/CVC), - * or expiration dates. Use wallet and card item types for credit cards and payment - * checkout instead. + * or expiration dates. Use wallet, payment_request and card item types for credit + * cards and payment checkout instead. Where enabled, Link and Kernel purchases can + * be payment_request items parented by their wallet; card items remain supported + * for them and for AgentCard reusable cards. * * @example * ```ts @@ -206,6 +214,31 @@ export class Items extends APIResource { } } +/** + * Start hosted enrollment of a card in a connected Kernel wallet, including its + * first card, only when the wallet advertises add_payment_method. Returns a new + * payment method in pending_enrollment with a single-use card_enrollment URL for + * the cardholder. Card details go directly to the card vault and are never + * accepted by this API. Each call creates a separate link that expires after 30 + * minutes; a failed or expired enrollment does not affect the wallet's other + * payment methods. Scoped API keys require vaults:write in addition to vaults:use + * on this vault; otherwise the operation returns 403. + */ +export interface AddPaymentMethodVaultItemOperationRequest { + type: 'add_payment_method'; +} + +/** + * The payment method created in pending_enrollment. Deliver action.url to the + * cardholder; it is a single-use capability and must not be logged. Observe + * completion through the wallet's payment_methods expansion. + */ +export interface AddPaymentMethodVaultItemOperationResult { + payment_method: VaultPaymentMethod; + + type: 'add_payment_method'; +} + /** * The in-flight or most recent checkout authorization. Present while a checkout is * pending approval and after it settles. @@ -805,7 +838,9 @@ export namespace CredentialAccountVaultItem { | '1pw_fill' | '1pw_recover' | '1pw_update_access_token' - | 'webmcp_invoke'; + | 'webmcp_invoke' + | 'add_payment_method' + | 'remove_payment_method'; } } @@ -1183,7 +1218,9 @@ export namespace CredentialVaultItem { | '1pw_fill' | '1pw_recover' | '1pw_update_access_token' - | 'webmcp_invoke'; + | 'webmcp_invoke' + | 'add_payment_method' + | 'remove_payment_method'; } export interface OnePasswordAccessApprovalAction { @@ -1210,22 +1247,22 @@ export namespace CredentialVaultItem { * path fails, collect a Kernel-hosted credential item instead. Never automatically * retry an uncertain 1Password request. After an uncertain fill, inspect the page * to see the result of the fill. Do not use credential items for credit card data. - * Use wallet and card item types instead. Kernel credentials declare fields and - * may enter pending_collection. 1Password credentials either reference a connected - * credential_account or store a supplied access token and integration key - * encrypted on the item. They store no login values or selectors. Managed auth - * credentials reference a managed auth connection in the same project that already - * has a saved credential, and read it at fill time; they store no values. - * Repeating the original creation request returns the current item without + * Use wallet, payment_request and card item types instead. Kernel credentials + * declare fields and may enter pending_collection. 1Password credentials either + * reference a connected credential_account or store a supplied access token and + * integration key encrypted on the item. They store no login values or selectors. + * Managed auth credentials reference a managed auth connection in the same project + * that already has a saved credential, and read it at fill time; they store no + * values. Repeating the original creation request returns the current item without * overwriting later state. A different request at the same key returns 409. */ export interface CredentialVaultItemRequest { /** * Credential fields are for login and other non-payment credentials. Do not store, - * collect, or fill credit card data in credential items. Use wallet and card item - * types for credit cards and payment checkout instead. Field order is preserved in - * the user-facing collection form, so list fields in the same top-to-bottom order - * as the website. + * collect, or fill credit card data in credential items. Use wallet, + * payment_request and card item types for credit cards and payment checkout + * instead. Field order is preserved in the user-facing collection form, so list + * fields in the same top-to-bottom order as the website. */ spec: CredentialVaultItemSpecInput; @@ -1243,10 +1280,10 @@ export type CredentialVaultItemSpec = /** * Credential fields are for login and other non-payment credentials. Do not store, - * collect, or fill credit card data in credential items. Use wallet and card item - * types for credit cards and payment checkout instead. Field order is preserved in - * the user-facing collection form, so list fields in the same top-to-bottom order - * as the website. + * collect, or fill credit card data in credential items. Use wallet, + * payment_request and card item types for credit cards and payment checkout + * instead. Field order is preserved in the user-facing collection form, so list + * fields in the same top-to-bottom order as the website. */ export type CredentialVaultItemSpecInput = | KernelCredentialVaultItemSpecInput @@ -1453,8 +1490,25 @@ export interface KernelCardState { */ domains?: Array; + /** + * Whether payment_method_id can still fund this purchase. unavailable means the + * method is being removed or awaits recovery, so authorization, fill and + * confirmation are refused until it recovers. removed means the method was removed + * from its wallet, so this purchase can no longer be paid; create a new purchase + * with another method. Neither changes status, which still reports what already + * happened to this purchase. + */ + funding_status?: 'available' | 'unavailable' | 'removed'; + masks?: KernelCardState.Masks; + /** + * Wallet-scoped ID of the payment method funding this purchase. It is bound when + * the purchase is created and never changes; purchases created before payment + * methods could be selected report the wallet's default card, card. + */ + payment_method_id?: string; + status_reason?: string; } @@ -1534,6 +1588,15 @@ export interface KernelCardVaultItemSpec { * one-time code is issued for the merchant's country. */ merchant_country?: string; + + /** + * Wallet-scoped payment method ID from the wallet's payment_methods expansion. + * Omission selects the wallet's default card, ID card, for compatibility with + * existing requests; it never falls back to another method, and a wallet without a + * default card requires the ID. The purchase is bound to the method's enrolled + * card and network token, so later operations cannot switch funding. + */ + payment_method_id?: string; } export interface KernelCredentialVaultItemSpec { @@ -1554,10 +1617,10 @@ export interface KernelCredentialVaultItemSpec { /** * Credential fields are for login and other non-payment credentials. Do not store, - * collect, or fill credit card data in credential items. Use wallet and card item - * types for credit cards and payment checkout instead. Field order is preserved in - * the user-facing collection form, so list fields in the same top-to-bottom order - * as the website. + * collect, or fill credit card data in credential items. Use wallet, + * payment_request and card item types for credit cards and payment checkout + * instead. Field order is preserved in the user-facing collection form, so list + * fields in the same top-to-bottom order as the website. */ export interface KernelCredentialVaultItemSpecInput { /** @@ -1592,16 +1655,80 @@ export interface KernelCredentialVaultItemState { status: 'pending_collection' | 'ready'; } +/** + * One live purchase funded by the Kernel wallet payment method named by + * payment_method_id. The method must be active and eligible when the request is + * created. The purchase is bound to that method; later operations cannot switch + * funding, and removing the method makes the purchase unusable rather than moving + * it to another card. Approval, issuance, fill and the alias fallback behave as + * described for KernelCardVaultItemSpec. + */ +export interface KernelPaymentRequestVaultItemSpec { + /** + * Integer amount in minor currency units (at most 1000000), bound to the one-time + * code. + */ + amount: number; + + /** + * ISO 4217 code. Supported: aud, brl, cad, chf, czk, dkk, eur, gbp, hkd, inr, jpy, + * krw, mxn, nok, nzd, pln, sek, sgd, usd, zar. + */ + currency: string; + + merchant_name: string; + + /** + * Merchant checkout URL. Fill is allowed only on this URL's origin. + */ + merchant_url: string; + + /** + * Payment method ID from the wallet's payment_methods expansion. + */ + payment_method_id: string; + + provider: 'kernel'; + + /** + * Key of the Kernel wallet item that owns the payment method. + */ + wallet: string; + + /** + * Actual merchant category when known. Omit rather than invent a category. + */ + merchant_category?: string; + + /** + * Actual merchant MCC when known. Omit rather than invent a code. 0000 is not + * accepted. + */ + merchant_category_code?: string; + + /** + * The merchant's ISO 3166-1 alpha-2 country code. Required for Visa cards, whose + * one-time code is issued for the merchant's country. + */ + merchant_country?: string; +} + export interface KernelWalletState { provider: 'kernel'; /** - * pending_authorization asks the cardholder to use the card_enrollment action. - * connected means the card is stored; it can pay once payment_methods reports - * capabilities.single_use_card.eligible. reconnect_required asks the cardholder to - * use a new card_enrollment action after an uncertain enrollment was safely - * removed. degraded means the enrollment outcome is unknown and the wallet must be - * deleted before adding another card. + * connected means the wallet is usable. It holds zero or more cards as payment + * methods, listed by the payment_methods expansion, and each can pay once it + * reports capabilities.single_use_card.eligible. A wallet with no cards, before + * its first card or after its last is removed, is still connected. Where the + * wallet advertises add_payment_method and remove_payment_method, use them to + * manage cards. Otherwise the wallet enrolls one default card when created; until + * that card is enrolled the wallet reports pending_authorization with the card's + * card_enrollment action, or degraded when the card's enrollment outcome is + * unknown and the wallet must be deleted before adding another card. + * reconnect_required appears only on a wallet created before cards were payment + * methods and not yet upgraded. Reads preserve its stored state until the operator + * upgrade; payment and deletion requests are refused until then. */ status: 'pending_authorization' | 'connected' | 'reconnect_required' | 'degraded'; @@ -1609,17 +1736,21 @@ export interface KernelWalletState { } /** - * One card stored with Kernel-managed credentials. Creation returns a - * card*enrollment action: the cardholder enters the card and their email on a - * Kernel-hosted page, and the wallet connects once the card is stored. Kernel then - * enrolls it for an agentic network token when the issuer supports it. The card - * number never reaches Kernel. The connected wallet's payment_methods expansion - * lists the card; capabilities.single_use_card.eligible is false, with a - * network_token*\* reason, until the card has a network token, and authorize - * returns 400 for such a card unless Kernel supports checkout delivery without a - * network token for that card. In that case, fill types the checkout details. Visa - * purchases require the cardholder to complete a spend_approval action before - * Kernel issues a one-time code; Mastercard purchases need no hosted approval. + * Cards stored with Kernel-managed credentials, each a payment method of the + * wallet. Each card is enrolled through a card*enrollment action: the cardholder + * enters the card and their email on a Kernel-hosted page. Where the wallet + * advertises add_payment_method, creation returns an empty connected wallet and + * each card is enrolled with that operation. Otherwise creation returns the + * wallet's default card's card_enrollment action, and the wallet connects once + * that card is stored. Kernel then enrolls each card for an agentic network token + * when the issuer supports it. The card number never reaches Kernel. The connected + * wallet's payment_methods expansion lists the cards; + * capabilities.single_use_card.eligible is false, with a network_token*\* reason, + * until the card has a network token, and authorize returns 400 for such a card + * unless Kernel supports checkout delivery without a network token for that card. + * In that case, fill types the checkout details. Visa purchases require the + * cardholder to complete a spend_approval action before Kernel issues a one-time + * code; Mastercard purchases need no hosted approval. */ export interface KernelWalletVaultItemSpec { provider: 'kernel'; @@ -2087,8 +2218,9 @@ export interface OnePasswordCredentialVaultItemState { status: 'pending_authorization' | 'ready' | 'declined' | 'failed'; /** - * Non-secret broker state. Granted credential references stay encrypted - * server-side and can only be used by the fill operation. + * Non-secret broker state. Granted credential references are returned in resolved + * only for credentials with a customer-supplied access token; otherwise they stay + * encrypted server-side and can only be used by the fill operation. */ access_request?: OnePasswordCredentialVaultItemState.AccessRequest; @@ -2103,8 +2235,9 @@ export interface OnePasswordCredentialVaultItemState { export namespace OnePasswordCredentialVaultItemState { /** - * Non-secret broker state. Granted credential references stay encrypted - * server-side and can only be used by the fill operation. + * Non-secret broker state. Granted credential references are returned in resolved + * only for credentials with a customer-supplied access token; otherwise they stay + * encrypted server-side and can only be used by the fill operation. */ export interface AccessRequest { id: string; @@ -2149,6 +2282,14 @@ export namespace OnePasswordCredentialVaultItemState { * may omit entries; no entry IDs are invented. */ request?: AccessRequest.Request; + + /** + * Granted logins in the shape 1Password's getAccessRequestStatus returns. Present + * only for ready credentials with a customer-supplied access token, on single-item + * responses to callers that can use the vault. Each reference works only with that + * credential's access token and integration key. + */ + resolved?: Array; } export namespace AccessRequest { @@ -2201,15 +2342,28 @@ export namespace OnePasswordCredentialVaultItemState { } } } + + export interface Resolved { + /** + * 1Password credential reference. Pass it unchanged as resourcePath to the + * extension's fillCredential or to the 1Password SDK. + */ + reference: string; + + /** + * The requested entry this login satisfies, when known. + */ + entryId?: string; + } } } /** * Fill and submit an approved 1Password login in the selected browser page. The * page must share the selected entry's login origin. Supply entry_id when more - * than one approved entry matches the page origin. The extension selects fields; - * callers cannot supply selectors or secret values. Submission does not confirm - * website authentication. + * than one approved entry matches the page origin, and target_id when more than + * one open page has page_url. The extension selects fields; callers cannot supply + * selectors or secret values. Submission does not confirm website authentication. */ export interface OnePasswordFillVaultItemOperationRequest { /** @@ -2219,7 +2373,7 @@ export interface OnePasswordFillVaultItemOperationRequest { /** * Exact current top-level page URL. Must match exactly one open page in the - * browser. + * browser unless target_id is supplied. */ page_url: string; @@ -2231,6 +2385,14 @@ export interface OnePasswordFillVaultItemOperationRequest { */ entry_id?: string; + /** + * CDP target ID of the page to fill, such as tab.target_id from + * playwright.execute. Use it when several open pages have page_url. The page's + * current URL must equal page_url. Kernel brings the page to the front of its + * window before filling. + */ + target_id?: string; + timeout_ms?: number; } @@ -2310,6 +2472,283 @@ export interface PasskeyVaultItemOperationResult { rp_id?: string; } +/** + * One purchase from a Link or Kernel wallet, parented by that wallet. It has the + * same lifecycle, operations and fill behavior as a Link or Kernel card item. + * AgentCard reusable cards remain card items. + */ +export interface PaymentRequestVaultItem { + id: string; + + available_expansions: Array; + + available_operations: Array; + + created_at: string; + + /** + * Immutable item key assigned when the item is created. + */ + key: string; + + /** + * Live Link card request. Test-mode card creation is not supported. The spec can + * be changed with PATCH until the card is authorized at a checkout. Authorize it + * with the browser at final checkout: Kernel inspects the checkout through WebMCP + * and internally chooses a merchant-bound Link Pay Token when supported or a + * virtual card otherwise. Callers never receive or choose how the credential is + * delivered. + */ + spec: PaymentRequestVaultItemSpec; + + /** + * Issued Link cards retain encrypted card material for the fill operation. Link + * cards do not expose aliases or support egress substitution. + */ + state: PaymentRequestVaultItemState; + + type: 'payment_request'; + + updated_at: string; + + action?: VaultItemAction; + + expires_at?: string; +} + +export namespace PaymentRequestVaultItem { + /** + * Live data that can currently be requested by passing its type to the item GET + * expand parameter. + */ + export interface AvailableExpansion { + description: string; + + type: 'payment_methods' | 'link_user_info' | 'link_shipping_addresses'; + } + + /** + * An operation that is currently valid for this item. Read the description before + * invoking it through the item operations endpoint. + */ + export interface AvailableOperation { + description: string; + + type: + | 'authorize' + | 'restart_verification' + | 'confirm_transaction' + | 'collect' + | 'prepare_checkout' + | 'fill' + | 'arm_passkey' + | 'register_passkey' + | 'disarm_passkey' + | '1pw_create_access_request' + | '1pw_access_request_status' + | '1pw_fill' + | '1pw_recover' + | '1pw_update_access_token' + | 'webmcp_invoke' + | 'add_payment_method' + | 'remove_payment_method'; + } +} + +/** + * Live Link card request. Test-mode card creation is not supported. The spec can + * be changed with PATCH until the card is authorized at a checkout. Authorize it + * with the browser at final checkout: Kernel inspects the checkout through WebMCP + * and internally chooses a merchant-bound Link Pay Token when supported or a + * virtual card otherwise. Callers never receive or choose how the credential is + * delivered. + */ +export type PaymentRequestVaultItemSpec = + | PaymentRequestVaultItemSpec.LinkCardVaultItemSpec + | KernelPaymentRequestVaultItemSpec; + +export namespace PaymentRequestVaultItemSpec { + /** + * Live Link card request. Test-mode card creation is not supported. The spec can + * be changed with PATCH until the card is authorized at a checkout. Authorize it + * with the browser at final checkout: Kernel inspects the checkout through WebMCP + * and internally chooses a merchant-bound Link Pay Token when supported or a + * virtual card otherwise. Callers never receive or choose how the credential is + * delivered. + */ + export interface LinkCardVaultItemSpec { + /** + * Integer amount in minor currency units, at most 50000. With recurring, the + * spending limit per period, not a lifetime total. + */ + amount: number; + + context: string; + + currency: string; + + merchant_name: string; + + merchant_url: string; + + /** + * Payment-method ID returned by the referenced wallet's payment-method listing. + * The provider decides whether the selected funding method can satisfy the card + * request. + */ + payment_method_id: string; + + provider: 'link'; + + /** + * Connected Link wallet item key. + */ + wallet: string; + + line_items?: Array; + + metadata?: { [key: string]: string }; + + /** + * 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. + */ + recurring?: LinkCardVaultItemSpec.Recurring; + + totals?: Array; + } + + export namespace LinkCardVaultItemSpec { + export interface LineItem { + name: string; + + description?: string; + + image_url?: string; + + product_url?: string; + + quantity?: number; + + sku?: string; + + totals?: Array; + + /** + * Unit amount in minor currency units. + */ + unit_amount?: number; + + url?: string; + } + + export namespace LineItem { + export interface Total { + /** + * Total amount in minor currency units. + */ + amount: number; + + display_text: string; + + type: string; + } + } + + /** + * 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. + */ + export interface Recurring { + interval: 'day' | 'week' | 'month' | 'year'; + + /** + * Number of intervals per period. Link defaults it to 1. + */ + interval_count?: number; + } + + export interface Total { + /** + * Total amount in minor currency units. + */ + amount: number; + + display_text: string; + + type: string; + } + } +} + +/** + * Issued Link cards retain encrypted card material for the fill operation. Link + * cards do not expose aliases or support egress substitution. + */ +export type PaymentRequestVaultItemState = PaymentRequestVaultItemState.LinkCardState | KernelCardState; + +export namespace PaymentRequestVaultItemState { + /** + * Issued Link cards retain encrypted card material for the fill operation. Link + * cards do not expose aliases or support egress substitution. + */ + export interface LinkCardState { + provider: 'link'; + + /** + * recovery_required means an original provider operation has an unresolved outcome + * and the card cannot be used. Reads keep observing a known provider request and + * may clear the recovery. To continue, delete this card and create a new one; + * deleting cancels the original request when its ID is known and keeps the + * recovery evidence. The user may see an approval request for the original card + * and should approve only the new one. + */ + status: + | 'requested' + | 'pending_authorization' + | 'ready' + | 'consumed' + | 'expired' + | 'declined' + | 'recovery_required'; + + domains?: Array; + + masks?: LinkCardState.Masks; + + status_reason?: string; + } + + export namespace LinkCardState { + export interface Masks { + brand?: string; + + last4?: string; + + /** + * Last four digits of the network token presented to the merchant. + */ + token_last4?: string; + + [k: string]: string | undefined; + } + } +} + /** * Prepare an unused AgentCard card for a supported checkout. Deliver the returned * approval URL and keep the approval page open. Poll the item until @@ -2360,6 +2799,34 @@ export interface RegisterPasskeyVaultItemOperationRequest { field?: string; } +/** + * Remove one payment method from a Kernel wallet, only when the wallet advertises + * remove_payment_method. Removal deletes the stored card and blocks new purchases, + * fills and confirmations funded by it without affecting the wallet's other + * payment methods; the wallet stays connected even with no payment methods left. A + * purchase funded by the method with an unresolved outcome blocks removal with 409 + * purchase_unresolved. If the provider outcome is uncertain the method stays in + * removal_pending and keeps refusing payments; retry the removal later. Removal is + * not proof that a payment did not occur. Scoped API keys require vaults:write in + * addition to vaults:use on this vault; otherwise the operation returns 403. + */ +export interface RemovePaymentMethodVaultItemOperationRequest { + /** + * ID from the wallet's payment_methods expansion. + */ + payment_method_id: string; + + type: 'remove_payment_method'; +} + +export interface RemovePaymentMethodVaultItemOperationResult { + payment_method_id: string; + + status: 'removed'; + + type: 'remove_payment_method'; +} + /** * Explicitly prepare a fresh local verification session for the same Kernel Visa * purchase and connected wallet, only when restart_verification is advertised. @@ -2520,9 +2987,15 @@ export interface VaultFillFieldResult { | 'execution_failed'; } +/** + * One purchase from a Link or Kernel wallet, parented by that wallet. It has the + * same lifecycle, operations and fill behavior as a Link or Kernel card item. + * AgentCard reusable cards remain card items. + */ export type VaultItem = | VaultItem.WalletVaultItem | VaultItem.CardVaultItem + | PaymentRequestVaultItem | CredentialAccountVaultItem | CredentialVaultItem; @@ -2613,7 +3086,9 @@ export namespace VaultItem { | '1pw_fill' | '1pw_recover' | '1pw_update_access_token' - | 'webmcp_invoke'; + | 'webmcp_invoke' + | 'add_payment_method' + | 'remove_payment_method'; } /** @@ -2710,7 +3185,9 @@ export namespace VaultItem { | '1pw_fill' | '1pw_recover' | '1pw_update_access_token' - | 'webmcp_invoke'; + | 'webmcp_invoke' + | 'add_payment_method' + | 'remove_payment_method'; } } } @@ -2786,17 +3263,21 @@ export interface VaultItemEvent { /** * Authorization and preparation return the existing item shape. Fill and passkey * operations return value-free results; WebMCP invocation returns the tool's - * output. None persist transient outcomes on the item. + * output. None persist transient outcomes on the item. Payment-method operations + * return the affected wallet payment method. */ export type VaultItemOperationResponse = | VaultItemOperationResponse.WalletVaultItem | VaultItemOperationResponse.CardVaultItem + | PaymentRequestVaultItem | CredentialAccountVaultItem | CredentialVaultItem | FillVaultItemOperationResult | PasskeyVaultItemOperationResult | OnePasswordFillVaultItemOperationResult - | WebmcpInvokeVaultItemOperationResult; + | WebmcpInvokeVaultItemOperationResult + | AddPaymentMethodVaultItemOperationResult + | RemovePaymentMethodVaultItemOperationResult; export namespace VaultItemOperationResponse { export interface WalletVaultItem { @@ -2885,7 +3366,9 @@ export namespace VaultItemOperationResponse { | '1pw_fill' | '1pw_recover' | '1pw_update_access_token' - | 'webmcp_invoke'; + | 'webmcp_invoke' + | 'add_payment_method' + | 'remove_payment_method'; } /** @@ -2982,7 +3465,9 @@ export namespace VaultItemOperationResponse { | '1pw_fill' | '1pw_recover' | '1pw_update_access_token' - | 'webmcp_invoke'; + | 'webmcp_invoke' + | 'add_payment_method' + | 'remove_payment_method'; } } } @@ -2998,6 +3483,11 @@ export interface VaultPaymentMethod { display: VaultPaymentMethod.Display; + /** + * For Kernel wallets, true for the default card, ID card, which a Kernel card item + * that omits payment_method_id selects. Wallets created with payment methods + * enabled have no default card. + */ is_default: boolean; /** @@ -3009,6 +3499,27 @@ export interface VaultPaymentMethod { * Provider-neutral payment-method type normalized to lowercase. */ type: string; + + action?: VaultPaymentMethod.Action; + + /** + * Expiry of a pending enrollment link. + */ + expires_at?: string; + + /** + * Kernel wallets only. pending_enrollment means a card_enrollment link is open; + * active means the card is stored and can pay when + * capabilities.single_use_card.eligible is true; removal_pending means removal + * started but the provider outcome is unknown, so retry remove_payment_method; + * recovery_required means either an enrollment outcome is unknown (remove the + * method), or the stored card cannot be read (contact support; removal is refused + * with 409). Consult status_reason to distinguish these cases. Absent for other + * providers. + */ + status?: 'pending_enrollment' | 'active' | 'removal_pending' | 'recovery_required'; + + status_reason?: string; } export namespace VaultPaymentMethod { @@ -3035,6 +3546,19 @@ export namespace VaultPaymentMethod { last4?: string; } + + export interface Action { + name: 'card_enrollment'; + + url: string; + + /** + * Secret bearer capability for embedded card capture with @onkernel/vault-react. + * Present only for Kernel wallets; never for AgentCard. Treat it like the + * enrollment URL and do not log or persist it in browser storage. + */ + capture_token?: string; + } } export interface VaultWebmcpBinding { @@ -3301,6 +3825,7 @@ export interface ItemRetrieveParams { export type ItemUpdateParams = | ItemUpdateParams.CardVaultItemUpdateRequest + | ItemUpdateParams.PaymentRequestVaultItemUpdateRequest | ItemUpdateParams.CredentialVaultItemUpdateRequest; export declare namespace ItemUpdateParams { @@ -3326,6 +3851,28 @@ export declare namespace ItemUpdateParams { type?: 'card'; } + export interface PaymentRequestVaultItemUpdateRequest { + /** + * Path param + */ + id_or_name: string; + + /** + * Body param: Live Link card request. Test-mode card creation is not supported. + * The spec can be changed with PATCH until the card is authorized at a checkout. + * Authorize it with the browser at final checkout: Kernel inspects the checkout + * through WebMCP and internally chooses a merchant-bound Link Pay Token when + * supported or a virtual card otherwise. Callers never receive or choose how the + * credential is delivered. + */ + spec: PaymentRequestVaultItemSpec; + + /** + * Body param + */ + type: 'payment_request'; + } + export interface CredentialVaultItemUpdateRequest { /** * Path param @@ -3393,7 +3940,9 @@ export type ItemPerformOperationParams = | ItemPerformOperationParams.OnePasswordFillVaultItemOperationRequest | ItemPerformOperationParams.OnePasswordRecoverVaultItemOperationRequest | ItemPerformOperationParams.OnePasswordUpdateAccessTokenVaultItemOperationRequest - | ItemPerformOperationParams.WebmcpInvokeVaultItemOperationRequest; + | ItemPerformOperationParams.WebmcpInvokeVaultItemOperationRequest + | ItemPerformOperationParams.AddPaymentMethodVaultItemOperationRequest + | ItemPerformOperationParams.RemovePaymentMethodVaultItemOperationRequest; export declare namespace ItemPerformOperationParams { export interface AuthorizeVaultItemOperationRequest { @@ -3681,7 +4230,7 @@ export declare namespace ItemPerformOperationParams { /** * Body param: Exact current top-level page URL. Must match exactly one open page - * in the browser. + * in the browser unless target_id is supplied. */ page_url: string; @@ -3696,6 +4245,14 @@ export declare namespace ItemPerformOperationParams { */ entry_id?: string; + /** + * Body param: CDP target ID of the page to fill, such as tab.target_id from + * playwright.execute. Use it when several open pages have page_url. The page's + * current URL must equal page_url. Kernel brings the page to the front of its + * window before filling. + */ + target_id?: string; + /** * Body param */ @@ -3781,11 +4338,41 @@ export declare namespace ItemPerformOperationParams { */ timeout_sec?: number; } + + export interface AddPaymentMethodVaultItemOperationRequest { + /** + * Path param + */ + id_or_name: string; + + /** + * Body param + */ + type: 'add_payment_method'; + } + + export interface RemovePaymentMethodVaultItemOperationRequest { + /** + * Path param + */ + id_or_name: string; + + /** + * Body param: ID from the wallet's payment_methods expansion. + */ + payment_method_id: string; + + /** + * Body param + */ + type: 'remove_payment_method'; + } } export type ItemUpsertParams = | ItemUpsertParams.WalletVaultItemRequest | ItemUpsertParams.CardVaultItemRequest + | ItemUpsertParams.PaymentRequestVaultItemRequest | ItemUpsertParams.CredentialAccountVaultItemRequest | ItemUpsertParams.CredentialVaultItemRequest; @@ -3997,6 +4584,28 @@ export declare namespace ItemUpsertParams { type: 'card'; } + export interface PaymentRequestVaultItemRequest { + /** + * Path param + */ + id_or_name: string; + + /** + * Body param: Live Link card request. Test-mode card creation is not supported. + * The spec can be changed with PATCH until the card is authorized at a checkout. + * Authorize it with the browser at final checkout: Kernel inspects the checkout + * through WebMCP and internally chooses a merchant-bound Link Pay Token when + * supported or a virtual card otherwise. Callers never receive or choose how the + * credential is delivered. + */ + spec: PaymentRequestVaultItemSpec; + + /** + * Body param + */ + type: 'payment_request'; + } + export interface CredentialAccountVaultItemRequest { /** * Path param @@ -4022,10 +4631,10 @@ export declare namespace ItemUpsertParams { /** * Body param: Credential fields are for login and other non-payment credentials. - * Do not store, collect, or fill credit card data in credential items. Use wallet - * and card item types for credit cards and payment checkout instead. Field order - * is preserved in the user-facing collection form, so list fields in the same - * top-to-bottom order as the website. + * Do not store, collect, or fill credit card data in credential items. Use wallet, + * payment_request and card item types for credit cards and payment checkout + * instead. Field order is preserved in the user-facing collection form, so list + * fields in the same top-to-bottom order as the website. */ spec: CredentialVaultItemSpecInput; @@ -4038,6 +4647,8 @@ export declare namespace ItemUpsertParams { export declare namespace Items { export { + type AddPaymentMethodVaultItemOperationRequest as AddPaymentMethodVaultItemOperationRequest, + type AddPaymentMethodVaultItemOperationResult as AddPaymentMethodVaultItemOperationResult, type AgentcardCheckoutAuthorization as AgentcardCheckoutAuthorization, type AgentcardCheckoutPreparation as AgentcardCheckoutPreparation, type AgentcardPreparedProcessor as AgentcardPreparedProcessor, @@ -4071,6 +4682,7 @@ export declare namespace Items { type KernelCredentialVaultItemSpec as KernelCredentialVaultItemSpec, type KernelCredentialVaultItemSpecInput as KernelCredentialVaultItemSpecInput, type KernelCredentialVaultItemState as KernelCredentialVaultItemState, + type KernelPaymentRequestVaultItemSpec as KernelPaymentRequestVaultItemSpec, type KernelWalletState as KernelWalletState, type KernelWalletVaultItemSpec as KernelWalletVaultItemSpec, type LinkShippingAddress as LinkShippingAddress, @@ -4090,8 +4702,13 @@ export declare namespace Items { type OnePasswordRecoverVaultItemOperationRequest as OnePasswordRecoverVaultItemOperationRequest, type OnePasswordRequestAccessVaultItemOperationRequest as OnePasswordRequestAccessVaultItemOperationRequest, type PasskeyVaultItemOperationResult as PasskeyVaultItemOperationResult, + type PaymentRequestVaultItem as PaymentRequestVaultItem, + type PaymentRequestVaultItemSpec as PaymentRequestVaultItemSpec, + type PaymentRequestVaultItemState as PaymentRequestVaultItemState, type PrepareCheckoutVaultItemOperationRequest as PrepareCheckoutVaultItemOperationRequest, type RegisterPasskeyVaultItemOperationRequest as RegisterPasskeyVaultItemOperationRequest, + type RemovePaymentMethodVaultItemOperationRequest as RemovePaymentMethodVaultItemOperationRequest, + type RemovePaymentMethodVaultItemOperationResult as RemovePaymentMethodVaultItemOperationResult, type RestartVerificationVaultItemOperationRequest as RestartVerificationVaultItemOperationRequest, type VaultCardAliases as VaultCardAliases, type VaultCardFillField as VaultCardFillField, diff --git a/src/resources/vaults/vaults.ts b/src/resources/vaults/vaults.ts index 189c6487..7c3660be 100644 --- a/src/resources/vaults/vaults.ts +++ b/src/resources/vaults/vaults.ts @@ -3,6 +3,8 @@ import { APIResource } from '../../core/resource'; import * as ItemsAPI from './items'; import { + AddPaymentMethodVaultItemOperationRequest, + AddPaymentMethodVaultItemOperationResult, AgentcardCheckoutAuthorization, AgentcardCheckoutPreparation, AgentcardPreparedProcessor, @@ -45,6 +47,7 @@ import { KernelCredentialVaultItemSpec, KernelCredentialVaultItemSpecInput, KernelCredentialVaultItemState, + KernelPaymentRequestVaultItemSpec, KernelWalletState, KernelWalletVaultItemSpec, LinkShippingAddress, @@ -64,8 +67,13 @@ import { OnePasswordRecoverVaultItemOperationRequest, OnePasswordRequestAccessVaultItemOperationRequest, PasskeyVaultItemOperationResult, + PaymentRequestVaultItem, + PaymentRequestVaultItemSpec, + PaymentRequestVaultItemState, PrepareCheckoutVaultItemOperationRequest, RegisterPasskeyVaultItemOperationRequest, + RemovePaymentMethodVaultItemOperationRequest, + RemovePaymentMethodVaultItemOperationResult, RestartVerificationVaultItemOperationRequest, VaultCardAliases, VaultCardFillField, @@ -272,6 +280,8 @@ export declare namespace Vaults { export { Items as Items, + type AddPaymentMethodVaultItemOperationRequest as AddPaymentMethodVaultItemOperationRequest, + type AddPaymentMethodVaultItemOperationResult as AddPaymentMethodVaultItemOperationResult, type AgentcardCheckoutAuthorization as AgentcardCheckoutAuthorization, type AgentcardCheckoutPreparation as AgentcardCheckoutPreparation, type AgentcardPreparedProcessor as AgentcardPreparedProcessor, @@ -305,6 +315,7 @@ export declare namespace Vaults { type KernelCredentialVaultItemSpec as KernelCredentialVaultItemSpec, type KernelCredentialVaultItemSpecInput as KernelCredentialVaultItemSpecInput, type KernelCredentialVaultItemState as KernelCredentialVaultItemState, + type KernelPaymentRequestVaultItemSpec as KernelPaymentRequestVaultItemSpec, type KernelWalletState as KernelWalletState, type KernelWalletVaultItemSpec as KernelWalletVaultItemSpec, type LinkShippingAddress as LinkShippingAddress, @@ -324,8 +335,13 @@ export declare namespace Vaults { type OnePasswordRecoverVaultItemOperationRequest as OnePasswordRecoverVaultItemOperationRequest, type OnePasswordRequestAccessVaultItemOperationRequest as OnePasswordRequestAccessVaultItemOperationRequest, type PasskeyVaultItemOperationResult as PasskeyVaultItemOperationResult, + type PaymentRequestVaultItem as PaymentRequestVaultItem, + type PaymentRequestVaultItemSpec as PaymentRequestVaultItemSpec, + type PaymentRequestVaultItemState as PaymentRequestVaultItemState, type PrepareCheckoutVaultItemOperationRequest as PrepareCheckoutVaultItemOperationRequest, type RegisterPasskeyVaultItemOperationRequest as RegisterPasskeyVaultItemOperationRequest, + type RemovePaymentMethodVaultItemOperationRequest as RemovePaymentMethodVaultItemOperationRequest, + type RemovePaymentMethodVaultItemOperationResult as RemovePaymentMethodVaultItemOperationResult, type RestartVerificationVaultItemOperationRequest as RestartVerificationVaultItemOperationRequest, type VaultCardAliases as VaultCardAliases, type VaultCardFillField as VaultCardFillField, diff --git a/src/version.ts b/src/version.ts index cc27c45b..daf15132 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '0.132.0'; // x-release-please-version +export const VERSION = '0.133.0'; // x-release-please-version diff --git a/tests/index.test.ts b/tests/index.test.ts index decad6e3..a8582eba 100644 --- a/tests/index.test.ts +++ b/tests/index.test.ts @@ -465,6 +465,16 @@ describe('instantiate client', () => { }); }); +describe('idempotency', () => { + test.skip('key can be set per-request', async () => { + const client = new Kernel({ + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', + apiKey: 'My API Key', + }); + await client.deployments.create({}, { idempotencyKey: 'my-idempotency-key' }); + }); +}); + describe('request building', () => { const client = new Kernel({ apiKey: 'My API Key' });