Stripe

The Stripe integration enables payment processing, subscription management, and invoicing in your ContractSpec applications. All Stripe operations are type-safe, policy-enforced, and automatically logged.

Setup

Add your Stripe credentials to your environment variables:

# .env
STRIPE_SECRET_KEY=sk_test_...
STRIPE_PUBLISHABLE_KEY=pk_test_...
STRIPE_WEBHOOK_SECRET=whsec_...

Get your API keys from the Stripe Dashboard.

Available capabilities

Payment Intents

capabilityId: stripe-create-payment-intent
provider:
  type: stripe
  operation: createPaymentIntent

inputs:
  amount:
    type: number
    description: "Amount in cents"
  currency:
    type: string
    default: "usd"
  customerId:
    type: string
    optional: true
  metadata:
    type: object
    optional: true

outputs:
  paymentIntentId:
    type: string
  clientSecret:
    type: string
  status:
    type: string

Customers

capabilityId: stripe-create-customer
provider:
  type: stripe
  operation: createCustomer

inputs:
  email:
    type: string
  name:
    type: string
    optional: true
  metadata:
    type: object
    optional: true

outputs:
  customerId:
    type: string
  email:
    type: string

Subscriptions

capabilityId: stripe-create-subscription
provider:
  type: stripe
  operation: createSubscription

inputs:
  customerId:
    type: string
  priceId:
    type: string
  trialDays:
    type: number
    optional: true

outputs:
  subscriptionId:
    type: string
  status:
    type: string
  currentPeriodEnd:
    type: timestamp

Webhooks

ContractSpec automatically handles Stripe webhooks. Configure your webhook endpoint in the Stripe Dashboard:

https://your-app.com/api/webhooks/stripe

Subscribe to these events:

  • payment_intent.succeeded
  • payment_intent.payment_failed
  • customer.subscription.created
  • customer.subscription.updated
  • customer.subscription.deleted

Example workflow

Here's a complete payment workflow using Stripe:

workflowId: process-payment
version: 1.0.0

steps:
  - id: create-customer
    capability: stripe-create-customer
    inputs:
      email: ${input.customerEmail}
      name: ${input.customerName}
    onSuccess: create-payment-intent
    onFailure: notify-error

  - id: create-payment-intent
    capability: stripe-create-payment-intent
    inputs:
      amount: ${input.amount}
      currency: "usd"
      customerId: ${steps.create-customer.output.customerId}
    onSuccess: send-payment-link
    onFailure: notify-error

  - id: send-payment-link
    capability: send-email
    inputs:
      to: ${input.customerEmail}
      template: "payment-link"
      data:
        clientSecret: ${steps.create-payment-intent.output.clientSecret}
        amount: ${input.amount}

  - id: notify-error
    capability: send-email
    inputs:
      to: "admin@example.com"
      template: "payment-error"
      data:
        error: ${error.message}

Testing

Use Stripe's test cards for development:

Card NumberScenario
4242 4242 4242 4242Successful payment
4000 0000 0000 9995Insufficient funds
4000 0000 0000 0002Card declined

Best practices

  • Always use test mode during development
  • Verify webhook signatures to prevent fraud
  • Handle idempotency for payment operations
  • Store customer IDs for recurring payments
  • Use metadata to link Stripe objects to your application records
  • Monitor failed payments and retry logic