How to Integrate Next.js for payments with Vercel AI SDK for AI agents
Why this integration matters
If you’re building AI agents that can take action, you need two things: a reliable payment surface and a model runtime that can reason over user intent. Next.js for payments gives you the checkout and billing flow, while Vercel AI SDK gives you the agent loop, tool calling, and streaming responses.
The useful pattern here is simple: the agent decides when a payment is needed, Next.js handles the transaction, and the agent confirms the result back to the user. That’s how you build subscription upgrades, one-off purchases, invoice settlement flows, and paywalled agent actions without stuffing payment logic into your model layer.
Prerequisites
- •Python 3.10+
- •A Next.js app with a payments endpoint already exposed
- •A Vercel AI SDK-backed agent endpoint available over HTTP
- •API keys for:
- •your payment provider used by the Next.js app
- •Vercel AI SDK / model provider
- •
requestsinstalled in your Python environment - •Basic knowledge of:
- •REST APIs
- •JSON payloads
- •tool/function calling in AI agents
Install the Python dependency:
pip install requests
Integration Steps
1) Define the payment contract your agent will call
Keep the contract explicit. Your Python agent should not guess what the checkout API expects.
from dataclasses import dataclass
from typing import Any, Dict
@dataclass
class PaymentRequest:
customer_id: str
amount_cents: int
currency: str = "usd"
description: str = "AI agent initiated payment"
def to_payload(self) -> Dict[str, Any]:
return {
"customerId": self.customer_id,
"amountCents": self.amount_cents,
"currency": self.currency,
"description": self.description,
}
Use this shape to match whatever your Next.js route expects. In practice, this is usually a POST /api/payments/checkout or POST /api/payments/create-intent route backed by Stripe or another processor.
2) Call the Next.js payment route from Python
Your Python service should treat Next.js as the system of record for payments. That keeps billing logic in one place.
import os
import requests
NEXTJS_PAYMENT_URL = os.environ["NEXTJS_PAYMENT_URL"]
NEXTJS_API_KEY = os.environ["NEXTJS_API_KEY"]
def create_payment_intent(payment_request):
headers = {
"Authorization": f"Bearer {NEXTJS_API_KEY}",
"Content-Type": "application/json",
}
response = requests.post(
f"{NEXTJS_PAYMENT_URL}/api/payments/create-intent",
json=payment_request.to_payload(),
headers=headers,
timeout=30,
)
response.raise_for_status()
return response.json()
A typical response should include something like:
- •
paymentIntentId - •
clientSecret - •
status
If your Next.js app uses Stripe Checkout instead of Payment Intents, swap this route for a session creation endpoint and return the checkout URL.
3) Wrap payments as a tool in your Vercel AI SDK agent
The Vercel AI SDK side should expose a tool that can decide whether to trigger payment. The Python service can then call that tool endpoint or mirror its schema.
import os
import requests
VERCEL_AI_URL = os.environ["VERCEL_AI_URL"]
VERCEL_AI_API_KEY = os.environ["VERCEL_AI_API_KEY"]
def run_agent(user_message: str):
payload = {
"model": "gpt-4.1-mini",
"messages": [
{"role": "system", "content": "You are an assistant that can request payments when needed."},
{"role": "user", "content": user_message},
],
"tools": [
{
"type": "function",
"name": "create_payment_intent",
"description": "Create a payment intent through the billing system.",
"parameters": {
"type": "object",
"properties": {
"customer_id": {"type": "string"},
"amount_cents": {"type": "integer"},
"currency": {"type": "string"},
"description": {"type": "string"},
},
"required": ["customer_id", "amount_cents"],
},
}
],
}
headers = {
"Authorization": f"Bearer {VERCEL_AI_API_KEY}",
"Content-Type": "application/json",
}
response = requests.post(
f"{VERCEL_AI_URL}/v1/agent/run",
json=payload,
headers=headers,
timeout=60,
)
response.raise_for_status()
return response.json()
In a real Vercel AI SDK implementation, this maps to tool calling via tools, tool, or equivalent server action patterns depending on your stack. The important part is that the model does not directly charge cards; it requests a tool execution.
4) Execute the tool call and pass results back to the agent
Once the agent asks for payment, execute it through Next.js and feed the result back into the conversation state.
def handle_agent_payment_flow(user_message: str):
agent_response = run_agent(user_message)
if agent_response.get("tool_call"):
tool_args = agent_response["tool_call"]["arguments"]
payment_request = PaymentRequest(
customer_id=tool_args["customer_id"],
amount_cents=tool_args["amount_cents"],
currency=tool_args.get("currency", "usd"),
description=tool_args.get("description", ""),
)
payment_result = create_payment_intent(payment_request)
follow_up_payload = {
"model": "gpt-4.1-mini",
"messages": [
{"role": "assistant", "content": agent_response["message"]},
{
"role": "tool",
"name": "create_payment_intent",
"content": str(payment_result),
},
],
}
return follow_up_payload
return agent_response
This pattern keeps state transitions clean:
- •user asks for something billable
- •model requests payment via tool call
- •Next.js creates or confirms payment
- •model responds with confirmation or next steps
5) Confirm webhook status before finalizing access
Do not trust only synchronous responses. Payment processors are async under load, so verify status through webhooks or polling before granting access.
import time
def wait_for_payment_confirmation(payment_intent_id: str):
for _ in range(10):
response = requests.get(
f"{NEXTJS_PAYMENT_URL}/api/payments/{payment_intent_id}",
headers={"Authorization": f"Bearer {NEXTJS_API_KEY}"},
timeout=15,
)
response.raise_for_status()
data = response.json()
if data.get("status") == "succeeded":
return data
time.sleep(2)
raise TimeoutError("Payment was not confirmed in time")
In production, prefer webhooks over polling. Use polling only as a fallback for short-lived orchestration flows.
Testing the Integration
Run a simple end-to-end test that triggers an intentional paid action.
if __name__ == "__main__":
result = handle_agent_payment_flow(
"Charge customer cus_12345 $19.99 for premium report access"
)
print(result)
Expected output:
{
'model': 'gpt-4.1-mini',
'messages': [
{'role': 'assistant', 'content': 'I can process that request.'},
{'role': 'tool', 'name': 'create_payment_intent', 'content': "{'paymentIntentId': 'pi_abc123', 'status': 'requires_confirmation'}"}
]
}
If you wire webhook confirmation correctly, the final user-facing message should be closer to:
Payment received. Premium report access is now enabled.
Real-World Use Cases
- •Paid document generation
- •An insurance claims assistant charges before generating detailed loss summaries or settlement letters.
- •Subscription upgrades
- •A banking copilot uses an agent to explain plan differences and triggers checkout when the user chooses an upgrade.
- •Usage-based workflows
- •An internal ops agent bills per high-cost action like KYC checks, credit pulls, or compliance report exports.
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