Skip to main content

Stripe Payments ExecModule

Overview

StripeModule connects a ValkyrAI workflow to Stripe API v1 without placing API keys in workflow configuration. It supports bounded charge reads and explicit customer, charge, subscription, and refund writes. All write operations require a caller-supplied idempotency key, and financial writes also require an explicit confirmation flag.

The module is registered as:

com.valkyrlabs.workflow.modules.payment.StripeModule

This guide covers StripeModule. The separate legacy Stripe Checkout Session guide covers StripeCheckoutModule.

Usage

  1. Bind a READY Stripe IntegrationAccount to the module's normalized auth configuration.
  2. Select one supported operation.
  3. Provide the operation-specific inputs.
  4. For every write, provide a stable idempotency_key that is not reused with different parameters.
  5. For create_charge, create_subscription, or refund, set confirm_financial_action to true only after the workflow has approved that exact action.
  6. Execute the workflow and inspect status, data or items, attempts, and request_id.

Inputs

InputRequiredDescription
operationYescreate_charge, create_customer, create_subscription, refund, list_charges, or get_charge.
amountBy operationSmallest-currency-unit amount for create_charge; optional partial amount for refund. Range: 1–99,999,999.
currencyFor chargeThree-letter currency code. Default: usd.
customer_idFor charge/subscriptionStripe customer ID beginning with cus_.
price_idFor subscriptionStripe Price ID beginning with price_.
charge_idFor get/refundStripe Charge ID beginning with ch_.
emailFor customerBounded customer email address.
nameNoCustomer display name, at most 256 characters.
descriptionNoCharge or customer description, at most 500 characters.
quantityNoSubscription item quantity from 1 through 999. Default: 1.
reasonNoRefund reason: duplicate, fraudulent, or requested_by_customer.
limitNoCharge page size from 1 through 100. Default: 25.
starting_afterNoCharge cursor from a previous next_cursor.
idempotency_keyEvery writeStable caller correlation key, 1–255 characters.
confirm_financial_actionFinancial writesMust be true for charge, subscription, and refund writes.

Raw auth, api_key, apiKey, secretKey, secret_key, mock, and test fields are rejected before provider execution.

Outputs

OutputDescription
statussuccess or error.
operationNormalized operation name.
dataAllowlisted fields from one Stripe resource.
resource_idValidated Stripe resource ID for a single-resource success.
itemsAllowlisted charge summaries for list_charges.
countNumber of charge summaries in this page.
has_moreWhether Stripe reports another page.
next_cursorLast returned charge ID when another page exists.
request_idStripe Request-Id, when supplied, for support correlation.
attemptsHTTP attempt count. Write operations always report one attempt.
errorSafe object containing code, message, retryable, and optional httpStatus.

The module does not return raw provider bodies. Returned resource maps include only bounded identity, status, amount, currency, customer, time, and state fields relevant to workflow decisions.

IntegrationAccount Requirements

The bound IntegrationAccount must:

  • have status READY;
  • store a Stripe restricted key (rk_test_… or rk_live_…) or secret key (sk_test_… or sk_live_…) in the apiKey SecureField;
  • use least-privilege Stripe permissions for the configured operations;
  • expose no credential through module inputs, configuration JSON, logs, output, or error text.

Restricted keys are preferred when their resource permissions cover the workflow. Test-mode and live-mode access are determined by the bound key; a workflow flag cannot switch modes.

Configuration

stripeAccount is the only authentication configuration. The remaining normalized fields mirror the inputs above, plus safe_read_retries:

ConfigurationDefaultConstraint
safe_read_retries10–2 retries, GET operations only.
limit251–100 charges per page.
quantity11–999 subscription items.
currencyusdExactly three letters.

The provider destination is fixed to https://api.stripe.com/v1. Redirects are disabled, response bodies are capped at 2 MiB, and network calls use bounded connect, read, write, and total timeouts.

Operations

list_charges

Reads one bounded page from /v1/charges. Supply starting_after from the previous next_cursor to continue. Safe reads may retry HTTP 408, 429, 500, 502, 503, or 504 within the configured bound.

get_charge

Reads one charge by charge_id and validates that the response contains a ch_ resource ID.

create_customer

Creates one Stripe customer from a bounded email, optional name, and optional description. A stable idempotency_key is required. The module sends exactly one POST attempt.

create_charge

Creates one charge for an existing customer_id. amount, currency, idempotency_key, and confirm_financial_action=true are required. The module sends exactly one POST attempt.

create_subscription

Creates one subscription for a customer_id and price_id, with bounded quantity. It sets Stripe payment_behavior=default_incomplete, requires an idempotency key plus explicit financial confirmation, and sends one POST attempt.

refund

Creates one full or partial refund for charge_id. Optional reason is allowlisted. The operation requires an idempotency key plus explicit financial confirmation and sends one POST attempt.

Errors and Failure Modes

CodeMeaningRecovery
VALIDATION_ERRORMissing or malformed input, forbidden raw auth/mock field, missing idempotency key, or missing financial confirmation.Correct the named input. No provider request was sent.
UNSUPPORTED_OPERATIONThe requested operation is outside the allowlist.Select one documented operation.
INTEGRATION_ACCOUNT_REQUIREDNo Stripe account is bound.Bind a Stripe IntegrationAccount.
INTEGRATION_ACCOUNT_NOT_READYThe account is not exactly READY.Repair or reauthorize the account before retrying.
STRIPE_HTTP_<status>Stripe returned a non-success response.Use request_id for diagnosis. Reconcile writes by idempotency key before retrying.
NETWORK_ERRORThe request failed before a verified response.Reads may retry automatically. Treat writes as ambiguous and reconcile Stripe state first.
RESPONSE_TOO_LARGEStripe exceeded the 2 MiB response cap.Narrow the request or page size.
INVALID_PROVIDER_RESPONSEA successful response lacked the expected resource shape or ID.Inspect Stripe using request_id; do not assume the write failed.

Credential values and raw Stripe error bodies are never included in the output. A transient write response is marked non-retryable because provider commit state may be ambiguous.

Example

Create one approved subscription:

{
"operation": "create_subscription",
"customer_id": "cus_P3d9Example",
"price_id": "price_1PExample",
"quantity": 1,
"idempotency_key": "order-42-subscription-v1",
"confirm_financial_action": true
}

Expected normalized result:

{
"status": "success",
"operation": "create_subscription",
"resource_id": "sub_1PExample",
"data": {
"id": "sub_1PExample",
"object": "subscription",
"status": "incomplete",
"customer": "cus_P3d9Example",
"livemode": false
},
"attempts": 1,
"request_id": "req_Example"
}

Notes

  • Pagination is explicit: list_charges returns at most 100 items and a next_cursor when has_more is true.
  • Only GET operations retry, and only for bounded transient statuses or transport failures.
  • Writes use one HTTP attempt even if safe_read_retries is set.
  • Stripe idempotency keys reduce duplicate writes, but callers must keep the same parameters for a key and reconcile ambiguous responses before retrying.
  • Refunds can be financially destructive and cannot be dry-run. The confirmation flag authorizes only the exact otherwise-valid request; it does not bypass validation or IntegrationAccount checks.
  • Provider execution is not validated by the repository test suite because no live Stripe credential is used. Request construction, validation, retry boundaries, response mapping, catalog discovery, and secret redaction are tested deterministically.