Skip to content

Integrations

Stripe SDK: get started

The complete Stripe API through typed application or agent clients

Use an ordinary App, or an Agent when the workload needs agent identity. Alter builds provider requests from a reviewed contract and applies the same connection authorization, policy, approvals, and audit records as raw requests.

Terminal window
npm install @alter-ai/sdk @alter-ai/stripe
# Python (installs core automatically)
pip install alter-sdk-stripe

The provider package includes only Stripe types and response schemas and pins its contract version.

Configure Stripe for Stripe Connect OAuth, or store a Stripe API key as a managed secret, and retain the grant ID. Both connection kinds call the same methods. Alter supplies the credential; it never belongs in operation input. A Connect grant is read_only or read_write for the whole account, and a restricted key carries its own per-resource permissions; Stripe enforces both.

import { App } from "@alter-ai/sdk";
import { StripeIntegration } from "@alter-ai/stripe";
const app = new App({ apiKey: process.env.ALTER_API_KEY! });
try {
const client = new StripeIntegration(app, { grantId: process.env.STRIPE_GRANT_ID! });
const result = await (await client.balance.getBalance({})).wait();
console.log(result.bodyJson());
} finally {
await app.close();
}
from alter_sdk import App
from alter_sdk_stripe import StripeIntegration
async def first_call(api_key: str, grant_id: str):
async with App(api_key=api_key) as app:
client = StripeIntegration(app, {"grant_id": grant_id})
call = await client.balance.get_balance({})
result = await call.wait()
return result.body_json()

Contract 2026-10-28 contains every operation in Stripe’s official OpenAPI document. The API reference links every operation to its complete input fields, response models, TypeScript and Python examples, and policy identity. Browse by resource under this provider’s API reference in the Integrations sidebar, or download the pinned OpenAPI specification. The Developer Portal provider view and alter integrations operations stripe --version 2026-10-28 also expose the schemas.

Every operation is sent with Stripe-Version: 2026-09-30.endive, the API version the pinned document describes, so a call behaves as the contract says whatever the account’s default API version is. Generated calls pin the Alter contract version. Stripe’s own product, role, scope and subscription requirements still apply. There is no silent version fallback and no automatic write retry or pagination.

Every POST accepts Stripe’s Idempotency-Key header (headers: { "Idempotency-Key": … }, up to 255 characters). Send one on every write, and send the same key when retrying a write whose outcome is unknown (a timeout or a dropped connection): Stripe returns the first result for a repeated key for 24 hours instead of charging, paying out or transferring twice. Alter never retries a write itself.

Terminal window
alter integrations execute stripe stripe.getbalance \
--version 2026-10-28 --grant "$STRIPE_GRANT_ID" --input '{}' --wait

Arguments use native path, query, headers, and body containers. Stripe takes form-encoded bodies, not JSON: the input is a JSON object with Stripe’s own field names, and Alter sends it as application/x-www-form-urlencoded with Stripe’s bracketed keys (metadata[order], items[0][price], expand[0]). Structured query parameters (created[gte], expand[0]) are encoded the same way. An empty string unsets a field, as Stripe documents; null is not a form value and is refused, and so is an object key containing [ or ] (Stripe would read it as different nesting). A whole number written as a float (1000.0) is sent as 1000, and no number is sent in exponent form. Parameters of a DELETE (such as prorate and invoice_now when cancelling a subscription) go in query, where Stripe’s own SDKs send them. SDK methods preserve provider field names, decimal lexemes and large integers as strings when necessary. HTTP 204 returns null / None from the typed decoder. Binary responses use bodyBytes() / body_bytes(); the CLI can save them with --output-file.

A policy rule can require approval for any operation. The call returns a pending approval; wait() resolves once the approver decides, and resume(approvalId) picks a pending approval up after a restart. Approval cards show the operation, its contract version and the request input the sensitivity review marked safe to display.

Every binary input is a JSON object with filename, content_type, and content_base64. One operation uploads: files.postFiles / files.post_files sends the file as a file part and every other field as a text part under its bracketed name (file_link_data[create]). It and the quote PDF (quotes.getQuotesQuotePdf, read with bodyBytes() / body_bytes()) are served from files.stripe.com; a managed-secret connection needs that host in its allowed hosts beside api.stripe.com (the command sets the whole list, so name both): alter managed-secrets set-allowed-hosts <secret> --host api.stripe.com --host files.stripe.com, or the secret’s Allowed hosts in the Developer Portal. Downloading a file’s contents (/v1/files/{file}/contents) is not in Stripe’s API document, so it is not a managed operation. A raw request to it is still classified as the read operation GetFilesFileContents, so operation and family rules apply to it; the contents can be an identity document. The shared proxy accepts up to 5 MiB of serialized input; base64 adds overhead, so accepted file bytes are smaller than that ceiling.

Uploads run like any other write, with or without file_link_data: a file and a file link that downloads it let no one sign in to Stripe, so neither is refused as a credential. Operation and family rules (write) govern them. An upload whose purpose is a brand icon or logo, platform terms of service, a Terminal app package or a reader splash screen is held for approval and shown like any other upload. Every other purpose (customer signatures and dispute evidence, which carry a customer’s personal data, identity and verification documents, account requirements, tax forms, PCI documents, Issuing regulatory reports, Terminal Wi-Fi certificates and keys) is classified sensitive: under an approval rule it is held encrypted and the approver sees the file only as its name and size ([file: name.pdf, 2.3 MB]), never its contents.

Every operation’s policy decision (its families, whether it hands over a credential, its sensitive request fields and the parameters a rule can read) was reviewed against Stripe’s API reference page for that operation, and a new operation without a review fails generation. The per-operation families are in the Stripe connection’s policy table.

  • read is only for an operation that changes nothing, including a POST that creates nothing (previewing an invoice). Every other operation carries write; a removal, a void, an expiry and a cancel that cannot be resumed also carry delete.
  • payment marks anything that moves money or changes what is charged, owed or paid out, or where money comes from or goes: charges, captures and refunds, payouts, transfers, top-ups, Treasury movements, PaymentIntents and SetupIntents, payment methods and customer payment sources, customers (deleting one cancels its active subscriptions), invoices from creation on, invoice items and credit notes, subscriptions, their items and schedules, quotes, coupons, promotion codes and trial offers, Checkout Sessions and Payment Links, credit grants and meter events, Issuing cards, cardholders (their spending controls limit every card they hold), authorizations and disputes, a connected account’s payout bank account, payout settings and rejection, and the test helpers that move money. A read that can return full card or bank numbers is payment read: an Issuing card, and Treasury financial accounts (their ABA account numbers).
  • send marks anything that makes Stripe email or notify someone, or deliver data to a third party: receipt_email on charges, PaymentIntents and their captures, refund instructions emails, invoices that are emailed when finalized or sent, credit notes (emailed by default), quotes, subscriptions and subscription item changes billed by send_invoice (prorations and final invoices are emailed), sources that email their owner, submitting dispute evidence to the bank or card network, and forwarding requests.
  • admin marks account-level configuration and trust: connected accounts, their payout bank accounts, persons and capabilities, account and login links, account and customer sessions, app installs and secrets, webhook endpoints, Apple Pay and payment method domains, the customer portal, Terminal and card design configurations, Radar value lists, tax IDs, registrations and settings, tokens and ephemeral keys.

Parameter rules can read amount, currency, destination (the connected account, bank account or payment method money goes to), customer, payment_method and recipients (the addresses Stripe emails, such as receipt_email) on the writes that move money or make Stripe write to someone, each from every documented field that carries it (transfer_data[destination] and destination, customer and customer_account, a credit note’s amount, refund_amount, credit_amount, out_of_band_amount and line amounts). When the request carries the value in a form a rule cannot read (an inline payment_method_data, a confirmation_token, an invoice revised from_invoice, a legacy object destination, or two fields that disagree), a rule on that parameter fails closed. A projected operation still carries every other documented top-level field unread, and refuses an undocumented one. A structured field (metadata, shipping, expand) is never readable by a rule. Amounts spread over nested line items (Checkout Sessions, subscriptions, invoices, quotes) are not one value, so those operations are governed by their families and by operation rules.

5 operations leave the caller holding a credential usable outside Alter, so Alter refuses them by default on every connection with credential_minting_refused, before any call reaches Stripe:

OperationTypeScriptPythonWhat the caller would hold
stripe.getappsinstallsapps.getAppsInstallsapps.get_apps_installsthe OAuth authorization codes of app installs
stripe.getappsinstallsidapps.getAppsInstallsIdapps.get_apps_installs_idthe OAuth authorization code of an app install
stripe.getappssecretsapps.getAppsSecretsapps.get_apps_secretsthe stored third-party credentials of a Stripe App, whose payload this listing returns when expanded
stripe.getappssecretsfindapps.getAppsSecretsFindapps.get_apps_secrets_findthe stored third-party credential of a Stripe App, whose payload this lookup returns when expanded
stripe.postappsinstallsapps.postAppsInstallsapps.post_apps_installsthe OAuth authorization code of the new install, redeemable for tokens on the installing account

The methods stay in the SDK. An organization admin who needs one allows it with a credential_minting rule naming provider stripe and the operation, outright or behind an approval; see Allow an operation that hands over a credential:

Terminal window
echo '{
"mode": "allow",
"provider": "stripe",
"operations": ["stripe.postappsinstalls"]
}' | alter policy rules create --type credential_minting --agent <agent-id> \
--body - --name "Install the reporting app" --yes

Files and file links (share URLs that only download a file), a new webhook endpoint’s signing secret, ephemeral keys (limited to one customer or card for a client SDK), Terminal connection tokens (they only connect a reader) and the Issuing card read are not logins, so they are not refused. Alter never stores their secrets in a captured payload, and an Issuing card’s number and CVC are masked. Login links, account and onboarding links, and the single-session client secrets of account, customer, Checkout, billing portal, Financial Connections and Identity sessions, PaymentIntents and SetupIntents are one-time handoffs to a browser that cannot call the Stripe API as the account, so they are not refused. Card, bank and PII tokens are single-use references that only the account’s own key can redeem.

Payload capture follows the application’s capture setting, on managed and raw proxied calls alike: credentials are removed, every field Alter’s reviewed inventory for the provider marks sensitive is masked in requests and responses, including fields it locates only by operation, and binary bodies, calls that can return a credential and calls carrying raw card data are never stored. Metadata audit is unchanged. Under an approval rule, raw card data is refused with sensitive_input_not_retained, the code Stripe calls have always returned for it: a card number, CVC, network token, magnetic-stripe track data or encrypted card in a card or card_present hash; a card dictionary under source or external_account; a CVC re-collection; an Issuing PIN; and the same as form fields such as card[number] or source[number]. Send a PaymentMethod, token or card id instead. Bank account, routing, sort, BSB, institution and transit numbers and IBANs, government ID numbers and the last four digits of SSNs, dates of birth, tax and VAT ID values, passwords, client secrets, App secret payloads and the token-creation envelopes that carry bank or personal details are held for approval, encrypted, and masked for the approver, including when they are sent as raw form fields such as bank_account[account_number] (see Sensitive input in approvals). Stripe object ids, tokens created client-side, File ids, amounts and enums are shown as sent.

Stripe documents no successful response that reports a failure; errors use HTTP error statuses with an error object, so there are no fault rules.

The pinned official source (Stripe’s v1 API document, release v2594), its hash, the generated methods and the policy mapping are checked together. Scheduled checks save upstream candidates and report additions, removals and schema changes; they never replace a published contract automatically. Existing contract versions remain available for installed SDKs and pending approvals.

Stripe has no separate sandbox host: test mode uses the same API with a test key or a Connect grant made in test mode.

Persist call.approvalId (TypeScript) or call.approval_id (Python), then construct a fresh provider client and call resume(savedId), followed by wait(). The stored approval selects the operation; this installed package verifies its provider and contract version before attaching the response validator. Mismatches raise ManagedOperationError, never silently decode using another contract. See persist-and-resume examples.

Policy operation fields also accept the published SDK function IDs listed by alter integrations operations stripe. Use when.operation for a json_match or conditional require_approval rule, or match.operations for content_match (including redaction and step-up). Conditional approval can also use when.match.operations with parameter conditions. alter policy simulate --operation <function-id> tests that exact function.

Managed calls carry a server-verified function identity. Alter still evaluates policy against the actual method, URL and body after building the request from the authorized connection. Existing endpoint, method, host, catalog-operation and family rules continue to apply unchanged. A raw call can share an endpoint with several SDK functions and matches all of them; a function name never grants permission or bypasses existing restrictions.

For example, this rule requires approval before any payout is created:

{
"effect": "require_approval",
"when": { "operation": "stripe.postpayouts" },
"approval": { "approvers": ["reviewer@example.com"] }
}

Save it with alter policy rules create --app <app-id> --grant <grant-id> --type require_approval --body @rule.json, or select the function in the portal.

Report an issue with this page

Necessary

Required for sign-in, security, authorization, and remembering your choices.

Always active

Analytics

Helps us understand which product and documentation features are useful.

Performance diagnostics

Uses performance tracing and privacy-masked session replay to diagnose problems.

You can change these choices at any time from Cookie settings.