Unified.to
All articles

How to Integrate with Stripe API: A Step-by-Step Guide for Developers


March 10, 2026

A Stripe API integration lets your product process payments, manage subscriptions, create invoices, issue refunds, and synchronize billing data with Stripe accounts.

For SaaS companies selling into ecommerce, marketplaces, or subscription businesses, Stripe is often the financial backbone of the product.

Typical integrations include:

  • Creating payments and PaymentIntents
  • Managing customers and subscriptions
  • Generating invoices
  • Handling refunds
  • Synchronizing billing data
  • Listening to payment events via webhooks

But a production-grade Stripe integration involves more than sending a payment request. You need to design for idempotency, retries, pagination, webhook reliability, and multi-account platforms like Stripe Connect.

This guide covers:

  1. How to integrate directly with the Stripe API
  2. The operational complexity you will own
  3. How to integrate Stripe using Unified's Payment and Accounting APIs
  4. When to build direct vs use an integration layer

Direct Stripe API integration

Step 1: Understand the Stripe API model

Stripe provides a REST API with resource-oriented endpoints.

All endpoints are rooted under:

https://api.stripe.com

Requests use standard HTTP methods:

GET
POST
PUT
DELETE

Requests typically send form-encoded bodies, while responses are always JSON.

Stripe's documentation explains that each API request operates on a single object, meaning the API does not support bulk updates.

Stripe API reference: https://docs.stripe.com/api

Step 2: Authenticate using API keys

Stripe authenticates API requests using API keys.

Keys are generated in the Stripe dashboard and come in several types:

Key TypePrefixUsage
Publishablepk_test / pk_liveclient-side use
Secretsk_test / sk_liveserver-side API calls
Restrictedrk_limited permissions

Example authenticated request:

curl https://api.stripe.com/v1/customers \
  -u sk_test_...:

Important security practices:

  • Never expose secret keys in client-side code
  • Always store keys in environment variables
  • Only make requests over HTTPS

Stripe authentication docs: https://docs.stripe.com/api/authentication

Step 3: Use idempotency for safe retries

Stripe supports idempotent requests to prevent duplicate operations when retries occur.

You supply an Idempotency-Key header when creating or updating objects.

Example:

curl https://api.stripe.com/v1/customers \
  -H "Idempotency-Key: 3f41c9c3-3e55-4d78-a7c8" \
  -u sk_test_... \
  -d description="Example customer"

Stripe stores the result for that key for 24 hours, returning the same result if the request is retried.

Stripe idempotency docs: https://docs.stripe.com/api/idempotent_requests

Core Stripe operations

Stripe integrations typically revolve around several core resources.

Customers

Customers store billing and identity information for a user.

Create customer

POST /v1/customers

Common parameters:

  • name
  • email
  • phone
  • metadata

Example:

curl https://api.stripe.com/v1/customers \
  -u sk_test_... \
  -d name="Jenny Rosen" \
  -d email="jenny@example.com"

Stripe customers API: https://docs.stripe.com/api/customers

PaymentIntents

Stripe recommends using PaymentIntents instead of creating charges directly.

A PaymentIntent manages the full payment lifecycle.

Create payment intent

POST /v1/payment_intents

Required fields:

amount
currency

Common optional parameters:

customer
automatic_payment_methods[enabled]
payment_method
confirm

Example:

curl https://api.stripe.com/v1/payment_intents \
  -u sk_test_... \
  -d amount=2000 \
  -d currency=usd \
  -d automatic_payment_methods[enabled]=true

Stripe PaymentIntents docs: https://docs.stripe.com/api/payment_intents

Charges

The Charge object represents a completed payment.

Modern integrations typically do not create charges directly, because charges are generated automatically by PaymentIntents.

Retrieve charge:

GET /v1/charges/{charge_id}

Stripe charges docs: https://docs.stripe.com/api/charges

Invoices

Invoices allow billing customers manually or through subscriptions.

Create invoice

POST /v1/invoices

Key parameters:

customer
collection_method
due_date
auto_advance

Example:

curl https://api.stripe.com/v1/invoices \
  -u sk_test_... \
  -d customer=cus_123

Stripe invoices docs: https://docs.stripe.com/api/invoices

Subscriptions

Subscriptions power recurring billing.

Create subscription

POST /v1/subscriptions

Required parameters:

customer
items[0][price]

Example:

curl https://api.stripe.com/v1/subscriptions \
  -u sk_test_... \
  -d customer=cus_123 \
  -d items[0][price]=price_monthly

Stripe subscriptions docs: https://docs.stripe.com/api/subscriptions

Refunds

Refunds return funds from a charge or PaymentIntent.

Create refund

POST /v1/refunds

Example:

curl https://api.stripe.com/v1/refunds \
  -u sk_test_... \
  -d payment_intent=pi_123

Stripe refunds docs: https://docs.stripe.com/api/refunds

Products and prices

Stripe separates products from prices.

Products describe what is sold.

Prices define billing amount and frequency.

Create product:

POST /v1/products

Create price:

POST /v1/prices

Stripe product docs

https://docs.stripe.com/api/products

Stripe price docs

https://docs.stripe.com/api/prices

Stripe pagination

Stripe uses cursor-based pagination.

List endpoints accept:

limit
starting_after
ending_before

Example:

GET /v1/customers?limit=100

The response includes:

data
has_more
url

Stripe pagination docs

https://docs.stripe.com/api/pagination

Stripe search API

Stripe supports search endpoints for some objects.

Example:

GET /v1/customers/search

Query example:

email:'@example.com'

Important note:

Stripe search is eventually consistent, so it should not be used for read-after-write workflows.

Stripe search docs

https://docs.stripe.com/search

Stripe webhooks

Stripe webhooks notify your system when events occur.

Example events:

payment_intent.succeeded
invoice.paid
charge.refunded
customer.subscription.created

Webhook payloads contain:

id
type
created
data.object

Security requirements:

  • Verify signatures using the Stripe-Signature header
  • Use HTTPS endpoints
  • Treat events as idempotent

Stripe webhook docs

https://docs.stripe.com/webhooks

Stripe Connect for SaaS platforms

Stripe Connect enables platforms to process payments for multiple businesses.

Platforms create connected accounts, identified by:

acct_xxxxx

To act on behalf of a connected account, include:

Stripe-Account: acct_xxxxx

Example:

curl https://api.stripe.com/v1/payment_intents \
  -H "Stripe-Account: acct_123"

Stripe Connect docs

https://docs.stripe.com/connect

Where Stripe integrations become operationally complex

Direct Stripe integrations require handling:

  • payment state machines
  • idempotency and retries
  • webhook ordering and duplication
  • subscription lifecycle management
  • pagination across large datasets
  • multi-account routing (Stripe Connect)
  • API version upgrades
  • billing reconciliation

For a single billing integration this is manageable.

For multi-tenant SaaS products, this becomes real integration infrastructure.

Integrating Stripe via Unified

Unified normalizes Stripe into multiple API categories.

Stripe spans:

Payment
Accounting
Commerce
Authentication
Passthrough

Step 1: Configure OAuth redirect

When registering Stripe with Unified, set the OAuth callback to:

https://api.unified.to/oauth/code

EU region variant:

https://api-eu.unified.to/oauth/code

Unified manages the OAuth handshake and returns a connection_id used in API requests.

Step 2: Use Unified normalized objects

Unified maps Stripe resources to normalized objects.

Supported Stripe objects include:

Unified ObjectStripe Resource
paymentPaymentIntent / Charge
payoutPayout
refundRefund
subscriptionSubscription
accounting_contactCustomer
accounting_invoiceInvoice
commerce_itemProduct
commerce_itemvariantPrice

Unified Stripe object coverage

Payment

Methods

list
get
update
remove

List parameters

limit
offset
contact_id
updated_gte

Readable fields

id
contact_id
currency
payment_method
reference
total_amount
invoice_id
created_at
updated_at

Webhooks

Virtual
Native

Payout

Methods

list
get

Readable fields

id
status
currency
total_amount
created_at
updated_at

Webhooks

Virtual
Native

Refund

Methods

list
get

Readable fields

id
payment_id
currency
status
total_amount
created_at
updated_at

Webhooks

Virtual
Native

Subscription

Methods

list
get

Readable fields

id
status
interval
interval_unit
invoice_id
currency
current_period_start_at
current_period_end_at

Webhooks

Virtual
Native

Unified API examples

List customers:

GET /ticketing/{connection_id}/customer

Create customer:

POST /ticketing/{connection_id}/customer

List payments:

GET /payment/{connection_id}/payment

Create payment:

POST /payment/{connection_id}/payment

List invoices:

GET /accounting/{connection_id}/invoice

Create invoice:

POST /accounting/{connection_id}/invoice

Unified webhooks

Unified supports two webhook types.

Native webhooks

Forward events directly from Stripe.

Examples:

payment_intent.succeeded
invoice.paid
charge.refunded
customer.subscription.updated

Virtual webhooks

When providers lack native webhook support, Unified polls for changes and emits events.

Webhook payload includes:

data
webhook metadata
nonce
sig256
type

Possible types:

INITIAL-PARTIAL
INITIAL-COMPLETE
VIRTUAL
NATIVE

Unified passthrough

When Stripe features are not normalized, use passthrough.

Supported methods:

GET
POST
PUT
DELETE

Passthrough forwards the request to the Stripe API using the existing connection authentication.

Use cases:

  • creating refunds with custom options
  • managing Stripe products or prices
  • calling beta Stripe APIs

Direct vs Unified: when to choose each

Build directly with Stripe if

  • Stripe is a core product feature
  • you need full control over PaymentIntent flows
  • you rely heavily on Stripe Connect
  • you need advanced billing features

Use Unified if

  • Stripe is one of several payment providers
  • you want normalized billing objects
  • you want webhook handling abstracted
  • you want to reduce integration maintenance

Final thoughts

Stripe is one of the most powerful payment APIs available.

But a production integration involves much more than sending a payment request.

The real complexity appears in:

  • idempotent request handling
  • webhook reliability
  • subscription lifecycle management
  • multi-account routing
  • API versioning
  • large-scale billing operations

Design your Stripe integration around PaymentIntents, webhooks, and idempotency from day one.

If Stripe is one of many billing integrations your product must support, a normalized integration layer can significantly reduce engineering overhead.

→ Start your 30-day free trial

→ Book a demo

All articles