How to Integrate CrewAI for payments with FastAPI for startups
Connecting CrewAI for payments with FastAPI gives you a clean way to expose payment-capable AI agents behind normal HTTP endpoints. For startups, that means you can turn an agent into a billing-aware service: quote a payment flow, validate intent, trigger charge actions, and return structured results your product can use.
The useful part is not “AI plus API” in the abstract. It’s the ability to put a payment workflow behind FastAPI, then let CrewAI coordinate the steps an agent needs to complete safely.
Prerequisites
- •Python 3.10+
- •A FastAPI project set up with
uvicorn - •CrewAI installed in your environment
- •Payment provider credentials configured for the provider you use with CrewAI
- •Environment variables ready for secrets:
- •
CREWAI_API_KEY - •
PAYMENT_PROVIDER_API_KEY
- •
- •Basic familiarity with:
- •
FastAPI - •async Python
- •JSON request/response handling
- •
Install the core packages:
pip install fastapi uvicorn crewai pydantic python-dotenv
Integration Steps
1) Set up your FastAPI app and load credentials
Keep secrets out of code. Use environment variables and load them at startup.
from fastapi import FastAPI
from dotenv import load_dotenv
import os
load_dotenv()
app = FastAPI()
CREWAI_API_KEY = os.getenv("CREWAI_API_KEY")
PAYMENT_PROVIDER_API_KEY = os.getenv("PAYMENT_PROVIDER_API_KEY")
if not CREWAI_API_KEY or not PAYMENT_PROVIDER_API_KEY:
raise RuntimeError("Missing required API keys")
This gives you a clean base for wiring the agent into your API layer.
2) Define request/response models for payment operations
Use Pydantic models so your agent endpoint accepts predictable input and returns structured output.
from pydantic import BaseModel, Field
from typing import Optional
class PaymentRequest(BaseModel):
customer_id: str = Field(..., examples=["cus_123"])
amount: float = Field(..., gt=0)
currency: str = Field(default="USD")
description: Optional[str] = None
class PaymentResponse(BaseModel):
status: str
transaction_id: Optional[str] = None
message: str
This is important because agent outputs can be messy unless you force structure at the boundary.
3) Create a CrewAI agent and task for payment handling
CrewAI’s core pattern is Agent + Task + Crew. In a payments flow, keep the agent narrow: it should decide what to do, not own business logic.
from crewai import Agent, Task, Crew, Process
payment_agent = Agent(
role="Payments Operations Agent",
goal="Validate payment requests and prepare safe payment execution steps",
backstory="You handle payment workflows for a startup SaaS product.",
verbose=True,
)
def build_payment_task(customer_id: str, amount: float, currency: str, description: str | None):
return Task(
description=(
f"Prepare a payment action for customer {customer_id}. "
f"Amount: {amount} {currency}. "
f"Description: {description or 'N/A'}."
),
expected_output="A concise JSON-like summary with approval status and next action.",
agent=payment_agent,
)
def run_payment_crew(customer_id: str, amount: float, currency: str, description: str | None):
task = build_payment_task(customer_id, amount, currency, description)
crew = Crew(
agents=[payment_agent],
tasks=[task],
process=Process.sequential,
verbose=True,
)
return crew.kickoff()
This keeps CrewAI responsible for reasoning around the request while your app controls execution.
4) Expose a FastAPI endpoint that triggers the CrewAI workflow
Now wire the route. The endpoint receives JSON, passes it to CrewAI, and returns a structured response.
from fastapi import HTTPException
@app.post("/payments/intent", response_model=PaymentResponse)
async def create_payment_intent(payload: PaymentRequest):
try:
result = run_payment_crew(
customer_id=payload.customer_id,
amount=payload.amount,
currency=payload.currency,
description=payload.description,
)
return PaymentResponse(
status="accepted",
transaction_id=None,
message=str(result),
)
except Exception as e:
raise HTTPException(status_code=500, detail=f"Payment workflow failed: {e}")
If you want actual charge execution after validation, keep that in a separate service call after the crew returns an approved decision.
5) Add a real payment provider call after agent approval
The production pattern is simple: CrewAI decides whether the request is valid; your payment SDK executes the charge. Here’s an example using Stripe-style logic.
import stripe
stripe.api_key = PAYMENT_PROVIDER_API_KEY
def execute_charge(customer_id: str, amount: float, currency: str):
return stripe.PaymentIntent.create(
amount=int(amount * 100),
currency=currency.lower(),
customer=customer_id,
automatic_payment_methods={"enabled": True},
)
@app.post("/payments/charge", response_model=PaymentResponse)
async def charge_customer(payload: PaymentRequest):
try:
crew_result = run_payment_crew(
customer_id=payload.customer_id,
amount=payload.amount,
currency=payload.currency,
description=payload.description,
)
if "approved" not in str(crew_result).lower():
return PaymentResponse(
status="rejected",
message=f"Agent rejected request: {crew_result}",
)
intent = execute_charge(payload.customer_id, payload.amount, payload.currency)
return PaymentResponse(
status="success",
transaction_id=intent["id"],
message="Charge created successfully",
)
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))
That split matters. The agent reasons; your backend enforces policy and hits the payment provider.
Testing the Integration
Start the server:
uvicorn main:app --reload
Then test with curl:
curl -X POST "http://127.0.0.1:8000/payments/charge" \
-H "Content-Type: application/json" \
-d '{
"customer_id": "cus_123",
"amount": 49.99,
"currency": "USD",
"description": "Startup subscription"
}'
Expected output:
{
"status": "success",
"transaction_id": "pi_3Qexample123",
"message": "Charge created successfully"
}
If you’re still validating logic only, you may see:
{
"status": "accepted",
"transaction_id": null,
"message": "...agent output..."
}
Real-World Use Cases
- •Subscription billing assistants that validate plan changes before creating invoices or charges.
- •Collections workflows where an agent checks overdue accounts and triggers safe retry logic through your API.
- •Marketplace payout orchestration where CrewAI coordinates payout eligibility checks before calling your payment provider.
The main pattern is stable: FastAPI owns transport and auth; CrewAI owns workflow reasoning; your payment SDK owns money movement. Keep those boundaries tight and you get something startup teams can ship without turning payments into an unmaintainable agent demo.
Keep learning
- •The complete AI Agents Roadmap — my full 8-step breakdown
- •Free: The AI Agent Starter Kit — PDF checklist + starter code
- •Work with me — I build AI for banks and insurance companies
By Cyprian Aarons, AI Consultant at Topiax.
Want the complete 8-step roadmap?
Grab the free AI Agent Starter Kit — architecture templates, compliance checklists, and a 7-email deep-dive course.
Get the Starter Kit