Skip to content

Stripe

Stripe integration supports one-time payments (PaymentIntents), saved cards for recurring billing, and refunds.

Getting Started — Step by Step

flowchart TB
    A["1. Create Stripe Account"] --> B["2. Get API Keys"]
    B --> C["3. Get API Key from Payments Service"]
    C --> D["4. Configure Stripe Credentials"]
    D --> E["5. Set Webhook URL"]
    E --> F["6. Make Your First Payment"]

    style A fill:#e3f2fd
    style F fill:#e8f5e9

Step 1: Create a Stripe Account

  1. Go to Stripe Dashboard
  2. Create an account and verify your email

Step 2: Get API Keys

  1. Go to DevelopersAPI Keys
  2. Copy your Secret key (sk_test_... for sandbox, sk_live_... for production)
  3. Optionally, set up a webhook endpoint in Stripe Dashboard → Webhooks to get a Webhook signing secret (whsec_...)

Test mode

Use sk_test_ keys and Stripe test cards for development.

Step 3: Get an API Key from Payments Service

make createapikey
# Scopes: payments:read,payments:write,merchant:read,merchant:write,webhooks:read

Step 4: Configure Stripe Credentials

PUT /v1/merchant/providers
X-API-Key: sk_live_your_key
Content-Type: application/json
{
  "provider": "stripe",
  "stripe": {
    "secret_key": "sk_test_your_stripe_secret_key",
    "webhook_secret": "whsec_your_webhook_signing_secret"
  }
}

Step 5: Set Your Webhook URL

PUT /v1/merchant/webhook
X-API-Key: sk_live_your_key
{
  "webhook_url": "https://yourapp.com/webhooks/payments"
}

Step 6: Make Your First Payment

POST /v1/payments
X-API-Key: sk_live_your_key
Idempotency-Key: test-stripe-001
{
  "amount": 10.00,
  "currency": "USD",
  "provider": "stripe",
  "payment_method": "pm_card_visa"
}

Test payment methods

In test mode, use pm_card_visa, pm_card_mastercard, or pm_card_declined to simulate different outcomes.


Payment Flow

sequenceDiagram
    participant Merchant
    participant API as Payments API
    participant Stripe
    participant Webhook as Merchant Webhook

    Merchant->>API: POST /v1/payments<br/>{ provider: "stripe", amount: 50.00 }
    API->>Stripe: POST /v1/payment_intents<br/>(with merchant's secret_key)
    Stripe-->>API: { id: "pi_...", status: "succeeded" }
    API-->>Merchant: { status: "completed", provider_ref: "pi_..." }

    Note over Stripe,API: Stripe also sends webhook callback
    Stripe->>API: POST /v1/webhooks/stripe<br/>(Stripe-Signature header)
    API->>API: Verify signature + dedup
    API->>Webhook: POST merchant_url<br/>{ type: "payment.completed" }

Create Payment

Request

POST /v1/payments
X-API-Key: sk_live_...
Idempotency-Key: order-123
{
  "amount": 50.00,
  "currency": "USD",
  "provider": "stripe",
  "payment_method": "pm_card_visa",
  "return_url": "https://merchant.com/return"
}
Field Type Required Description
amount decimal Amount to charge (> 0)
currency string 3-letter ISO code (e.g. USD, KES)
provider string Must be stripe
payment_method string Stripe pm_ token from client-side
return_url string Redirect URL after 3DS authentication
saved_card_id UUID Use a previously saved card

Response

{
  "success": true,
  "data": {
    "id": "a1b2c3d4-...",
    "merchant_id": "m1m2m3-...",
    "amount": "50.00",
    "currency": "USD",
    "provider": "stripe",
    "status": "completed",
    "provider_ref": "pi_3abc...",
    "idempotency_key": "order-123",
    "created_at": "2025-01-01T12:00:00Z"
  }
}

Status Values

Status Meaning
completed Payment succeeded (succeeded on Stripe)
pending Requires action (3DS) or processing
failed Payment method declined or error

Saved Cards (Recurring)

Save a Card

sequenceDiagram
    participant Frontend
    participant API as Payments API
    participant Stripe

    Frontend->>Stripe: Stripe.js collects card<br/>→ pm_card_visa
    Frontend->>API: POST /v1/payments/cards<br/>{ payment_method_id: "pm_..." }
    API->>Stripe: POST /v1/customers
    Stripe-->>API: { id: "cus_..." }
    API->>Stripe: POST /v1/payment_methods/pm_.../attach
    API-->>Frontend: { last4: "4242", brand: "visa" }

Request

POST /v1/payments/cards
X-API-Key: sk_live_...
{
  "payment_method_id": "pm_1abc...",
  "customer_email": "user@example.com",
  "customer_name": "Jane Doe"
}

Response

{
  "success": true,
  "data": {
    "id": "card-uuid-...",
    "provider": "stripe",
    "brand": "visa",
    "last4": "4242",
    "exp_month": 12,
    "exp_year": 2027,
    "is_default": true,
    "created_at": "2025-01-01T12:00:00Z"
  }
}

Charge a Saved Card

POST /v1/payments
X-API-Key: sk_live_...
Idempotency-Key: subscription-may-2025
{
  "amount": 29.99,
  "currency": "USD",
  "provider": "stripe",
  "saved_card_id": "card-uuid-..."
}

The payment is processed off-session — no customer interaction needed.

List & Delete Cards

GET /v1/payments/cards          # List all saved cards
DELETE /v1/payments/cards/{id}  # Detach from Stripe + deactivate

Refund

POST /v1/refunds
X-API-Key: sk_live_...
{
  "payment_id": "a1b2c3d4-...",
  "amount": 25.00
}
Field Type Required Description
payment_id UUID Original payment to refund
amount decimal Partial refund amount. Omit for full refund

Response

{
  "success": true,
  "data": {
    "id": "refund-uuid-...",
    "payment_id": "a1b2c3d4-...",
    "status": "completed",
    "provider_ref": "re_1abc...",
    "amount": "25.00",
    "created_at": "2025-01-01T12:00:00Z"
  }
}

Inbound Webhook (Stripe → Us)

Stripe sends events to POST /v1/webhooks/stripe with a Stripe-Signature header.

Verification: t=timestamp,v1=hmac — timestamp must be within 5 minutes.

Events handled:

Stripe Event Our Status
payment_intent.succeeded completed
payment_intent.payment_failed failed
charge.refunded refunded

Viewing Stripe Transactions

List and filter all Stripe transactions:

GET /v1/payments?provider=stripe&status=completed
GET /v1/payments?provider=stripe&min_amount=100&currency=USD
GET /v1/payments?provider=stripe&since=2025-06-01T00:00:00Z

See Payments API → List & Filter for all available filters.