Custom Framework Integration
Build payment capabilities into any agentic framework using the AgentPay payment kernel.
Overview
This guide shows you how to integrate AgentPay's payment capabilities into any agent framework using our REST API and SDKs. Whether you're building with custom frameworks, existing platforms, or proprietary systems, these patterns will help you add autonomous payment functionality.
Integration Patterns
1. REST API Integration
The most flexible way to integrate with any framework:
Authentication
All API requests require authentication using your API key:
curl -H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
https://api.agentpay.ai/v1/payments
Core API Endpoints
Send Payment
POST /v1/payments
Content-Type: application/json
Authorization: Bearer YOUR_API_KEY
{
"to": "recipient_wallet_address",
"amount": 10.00,
"currency": "USD",
"memo": "Payment for services"
}
Check Balance
GET /v1/wallet/balance
Authorization: Bearer YOUR_API_KEY
Payment History
GET /v1/payments/history?limit=50&offset=0
Authorization: Bearer YOUR_API_KEY
Create Invoice
POST /v1/invoices
Content-Type: application/json
Authorization: Bearer YOUR_API_KEY
{
"amount": 25.00,
"currency": "USD",
"description": "API access fee",
"expires_at": "2024-02-01T00:00:00Z"
}
2. SDK Integration
Use our SDKs for easier integration:
Python Framework Example
from agentpay import AgentPaySDK
import asyncio
class PaymentCapableAgent:
def __init__(self, api_key: str):
self.agentpay = AgentPaySDK(api_key=api_key)
async def send_payment(self, recipient: str, amount: float, currency: str = "USD"):
"""Send payment with error handling"""
try:
result = await self.agentpay.payments.send(
to=recipient,
amount=amount,
currency=currency
)
return {"success": True, "transaction_id": result["id"]}
except Exception as e:
return {"success": False, "error": str(e)}
async def check_funds(self, required_amount: float):
"""Check if sufficient funds are available"""
balance = await self.agentpay.wallet.get_balance()
return balance["amount"] >= required_amount
async def payment_workflow(self, recipient: str, amount: float):
"""Complete payment workflow with validation"""
# Check funds
if not await self.check_funds(amount):
return {"error": "Insufficient funds"}
# Send payment
result = await self.send_payment(recipient, amount)
# Log transaction
if result["success"]:
await self.log_payment(result["transaction_id"])
return result
JavaScript/Node.js Framework Example
const { AgentPaySDK } = require('@agentpay/sdk');
class PaymentAgent {
constructor(apiKey) {
this.agentpay = new AgentPaySDK({ apiKey });
}
async executePayment(recipient, amount, currency = 'USD') {
try {
// Validate payment
const balance = await this.agentpay.wallet.getBalance();
if (balance.amount < amount) {
throw new Error('Insufficient funds');
}
// Send payment
const result = await this.agentpay.payments.send({
to: recipient,
amount: amount,
currency: currency
});
return { success: true, transactionId: result.id };
} catch (error) {
return { success: false, error: error.message };
}
}
async createPaymentIntent(amount, description) {
return await this.agentpay.invoices.create({
amount: amount,
currency: 'USD',
description: description
});
}
}
3. Webhook Integration
Handle payment events in your framework:
from flask import Flask, request, jsonify
import hmac
import hashlib
app = Flask(__name__)
@app.route('/webhooks/agentpay', methods=['POST'])
def handle_payment_webhook():
# Verify webhook signature
signature = request.headers.get('X-AgentPay-Signature')
if not verify_webhook_signature(request.data, signature):
return jsonify({'error': 'Invalid signature'}), 401
event = request.json
if event['type'] == 'payment.completed':
handle_payment_completed(event['data'])
elif event['type'] == 'payment.failed':
handle_payment_failed(event['data'])
return jsonify({'status': 'received'})
def verify_webhook_signature(payload, signature):
expected = hmac.new(
WEBHOOK_SECRET.encode(),
payload,
hashlib.sha256
).hexdigest()
return hmac.compare_digest(f"sha256={expected}", signature)
Error Handling Patterns
Retry Logic
import asyncio
from typing import Optional
async def robust_payment(
agent: PaymentCapableAgent,
recipient: str,
amount: float,
max_retries: int = 3
) -> dict:
"""Payment with exponential backoff retry"""
for attempt in range(max_retries):
try:
result = await agent.send_payment(recipient, amount)
if result["success"]:
return result
except Exception as e:
if attempt == max_retries - 1:
return {"success": False, "error": f"Failed after {max_retries} attempts: {str(e)}"}
# Exponential backoff
await asyncio.sleep(2 ** attempt)
return {"success": False, "error": "Max retries exceeded"}
Transaction Validation
async def validate_and_send_payment(
agent: PaymentCapableAgent,
recipient: str,
amount: float
) -> dict:
"""Validate payment before sending"""
# Validate recipient address
if not is_valid_wallet_address(recipient):
return {"error": "Invalid recipient address"}
# Validate amount
if amount <= 0:
return {"error": "Amount must be positive"}
# Check balance
if not await agent.check_funds(amount):
return {"error": "Insufficient funds"}
# Send payment
return await agent.send_payment(recipient, amount)
def is_valid_wallet_address(address: str) -> bool:
"""Validate wallet address format"""
return address.startswith('0x') and len(address) == 42
Framework-Specific Examples
Custom Agent Loop
class AutonomousPaymentAgent:
def __init__(self, api_key: str):
self.agentpay = AgentPaySDK(api_key=api_key)
self.running = False
async def agent_loop(self):
"""Main agent execution loop with payment capabilities"""
self.running = True
while self.running:
# Check for payment requests
pending_payments = await self.get_pending_payments()
for payment in pending_payments:
await self.process_payment_request(payment)
# Check balance periodically
await self.monitor_wallet_balance()
await asyncio.sleep(10) # Check every 10 seconds
async def process_payment_request(self, payment_request):
"""Process individual payment request"""
result = await self.agentpay.payments.send(
to=payment_request['recipient'],
amount=payment_request['amount']
)
# Update request status
await self.update_payment_status(payment_request['id'], result)
This flexible approach allows you to integrate AgentPay's payment capabilities into any agent framework while maintaining full control over the implementation details.
SDK Options
JavaScript/TypeScript SDK
npm install @paystabl/sdk
Basic Integration:
import { PayStablAgent } from '@paystabl/sdk';
class MyCustomAgent {
private paystabl: PayStablAgent;
constructor(agentId: string, config: AgentConfig) {
this.paystabl = new PayStablAgent({
agentId,
apiKey: config.payStablApiKey,
network: config.network || 'base-sepolia'
});
}
async callPaidAPI(url: string, options: RequestOptions = {}) {
try {
// Attempt payment and get headers
const payment = await this.paystabl.pay_api_endpoint({
url,
method: options.method || 'GET',
data: options.body,
headers: options.headers
});
// Make actual API call with payment header
const response = await fetch(url, {
...options,
headers: {
...options.headers,
'X-Payment': payment.xPaymentHeader
}
});
return {
data: await response.json(),
payment: payment.receipt
};
} catch (error) {
throw new PaymentError(error.message, error.code);
}
}
async payOtherAgent(toAgentId: string, amount: string, purpose: string) {
return await this.paystabl.pay_agent({
fromAgentId: this.agentId,
toAgentId,
amount,
purpose
});
}
}
Python SDK
pip install paystabl-python
Basic Integration:
from paystabl import PayStablAgent
import requests
class CustomPythonAgent:
def __init__(self, agent_id: str, api_key: str):
self.agent_id = agent_id
self.paystabl = PayStablAgent(
agent_id=agent_id,
api_key=api_key,
network="base-sepolia"
)
def call_paid_api(self, url: str, method="GET", data=None, headers=None):
try:
# Get payment authorization
payment = self.paystabl.pay_api_endpoint(
url=url,
method=method,
data=data,
headers=headers
)
# Make request with payment header
response = requests.request(
method=method,
url=url,
headers={
**(headers or {}),
"X-Payment": payment["xPaymentHeader"]
},
json=data
)
return {
"data": response.json(),
"payment": payment["receipt"]
}
except Exception as e:
raise PaymentException(f"Payment failed: {str(e)}")
def pay_agent(self, to_agent_id: str, amount: str, purpose: str):
return self.paystabl.pay_agent(
from_agent_id=self.agent_id,
to_agent_id=to_agent_id,
amount=amount,
purpose=purpose
)
Go SDK
go get github.com/paystabl/paystabl-go
Basic Integration:
package main
import (
"github.com/paystabl/paystabl-go"
"net/http"
"bytes"
"encoding/json"
)
type CustomGoAgent struct {
AgentID string
PayStabl *paystabl.Client
}
func NewCustomGoAgent(agentID, apiKey string) *CustomGoAgent {
client := paystabl.NewClient(apiKey, paystabl.Config{
Network: "base-sepolia",
})
return &CustomGoAgent{
AgentID: agentID,
PayStabl: client,
}
}
func (a *CustomGoAgent) CallPaidAPI(url, method string, body interface{}) (*APIResponse, error) {
// Get payment authorization
payment, err := a.PayStabl.PayAPIEndpoint(paystabl.APIPaymentRequest{
AgentID: a.AgentID,
URL: url,
Method: method,
Data: body,
})
if err != nil {
return nil, err
}
// Prepare request
var reqBody bytes.Buffer
if body != nil {
json.NewEncoder(&reqBody).Encode(body)
}
req, err := http.NewRequest(method, url, &reqBody)
if err != nil {
return nil, err
}
// Add payment header
req.Header.Set("X-Payment", payment.XPaymentHeader)
req.Header.Set("Content-Type", "application/json")
// Execute request
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
return nil, err
}
defer resp.Body.Close()
var result APIResponse
json.NewDecoder(resp.Body).Decode(&result)
return &result, nil
}
func (a *CustomGoAgent) PayAgent(toAgentID, amount, purpose string) (*paystabl.PaymentReceipt, error) {
return a.PayStabl.PayAgent(paystabl.AgentPaymentRequest{
FromAgentID: a.AgentID,
ToAgentID: toAgentID,
Amount: amount,
Purpose: purpose,
})
}
Integration Patterns
Event-Driven Architecture
Integrate PayStabl with event-driven agent systems:
import { EventEmitter } from 'events';
class EventDrivenAgent extends EventEmitter {
constructor(agentId: string) {
super();
this.paystabl = new PayStablAgent({ agentId });
this.setupPaymentHandlers();
}
setupPaymentHandlers() {
// Handle payment requests
this.on('api_payment_needed', async (event) => {
try {
const payment = await this.paystabl.pay_api_endpoint(event.payload);
this.emit('payment_completed', {
originalEvent: event,
payment
});
} catch (error) {
this.emit('payment_failed', {
originalEvent: event,
error
});
}
});
// Handle agent-to-agent payments
this.on('agent_payment_needed', async (event) => {
try {
const payment = await this.paystabl.pay_agent(event.payload);
this.emit('agent_payment_completed', {
originalEvent: event,
payment
});
} catch (error) {
this.emit('agent_payment_failed', {
originalEvent: event,
error
});
}
});
}
async processTask(task) {
// Emit payment event when needed
if (task.requiresPaidAPI) {
this.emit('api_payment_needed', {
id: task.id,
payload: {
url: task.apiUrl,
method: 'POST',
data: task.parameters
}
});
}
}
}
// Usage
const agent = new EventDrivenAgent('event_agent_001');
agent.on('payment_completed', (event) => {
console.log('Payment successful, continuing with task...');
// Continue processing with payment header
});
agent.on('payment_failed', (event) => {
console.log('Payment failed, trying alternative...');
// Handle failure gracefully
});
Plugin Architecture
Create a PayStabl plugin for existing agent frameworks:
interface AgentPlugin {
name: string;
version: string;
initialize(agent: any): void;
destroy(): void;
}
class PayStablPlugin implements AgentPlugin {
name = 'paystabl';
version = '1.0.0';
private paystabl: PayStablAgent;
private agent: any;
initialize(agent: any) {
this.agent = agent;
this.paystabl = new PayStablAgent({
agentId: agent.id,
apiKey: agent.config.payStablApiKey
});
// Add payment methods to agent
agent.payForAPI = this.payForAPI.bind(this);
agent.payAgent = this.payAgent.bind(this);
agent.checkBalance = this.checkBalance.bind(this);
// Hook into agent's request pipeline
if (agent.addRequestMiddleware) {
agent.addRequestMiddleware(this.paymentMiddleware.bind(this));
}
}
async paymentMiddleware(request: any, next: Function) {
// Automatically handle 402 responses
const response = await next(request);
if (response.status === 402) {
console.log('402 Payment Required detected, processing payment...');
const payment = await this.paystabl.pay_api_endpoint({
url: request.url,
method: request.method,
data: request.body,
headers: request.headers
});
// Retry request with payment header
request.headers['X-Payment'] = payment.xPaymentHeader;
return await next(request);
}
return response;
}
async payForAPI(url: string, options = {}) {
return await this.paystabl.pay_api_endpoint({
url,
...options
});
}
async payAgent(toAgentId: string, amount: string, purpose: string) {
return await this.paystabl.pay_agent({
fromAgentId: this.agent.id,
toAgentId,
amount,
purpose
});
}
async checkBalance() {
return await this.paystabl.getBalance();
}
destroy() {
// Cleanup resources
this.paystabl = null;
this.agent = null;
}
}
// Register plugin with your framework
AgentFramework.registerPlugin(new PayStablPlugin());
Microservices Architecture
Integrate PayStabl in a microservices environment:
// Payment Service
class PaymentMicroservice {
private paystabl: PayStablAgent;
constructor() {
this.paystabl = new PayStablAgent({
agentId: 'payment_service',
apiKey: process.env.PAYSTABL_API_KEY
});
}
async handleAPIPayment(req: PaymentRequest): Promise<PaymentResponse> {
try {
const payment = await this.paystabl.pay_api_endpoint({
url: req.url,
method: req.method,
data: req.data,
headers: req.headers
});
return {
success: true,
xPaymentHeader: payment.xPaymentHeader,
receipt: payment.receipt
};
} catch (error) {
return {
success: false,
error: error.message,
code: error.code
};
}
}
async handleAgentPayment(req: AgentPaymentRequest): Promise<PaymentResponse> {
try {
const payment = await this.paystabl.pay_agent({
fromAgentId: req.fromAgentId,
toAgentId: req.toAgentId,
amount: req.amount,
purpose: req.purpose
});
return {
success: true,
txHash: payment.txHash,
receipt: payment.xPayStablReceipt
};
} catch (error) {
return {
success: false,
error: error.message,
code: error.code
};
}
}
}
// Agent Service (uses Payment Service)
class AgentMicroservice {
private paymentService: PaymentServiceClient;
constructor() {
this.paymentService = new PaymentServiceClient('http://payment-service:3000');
}
async processTask(task: Task) {
if (task.requiresPayment) {
// Call payment microservice
const paymentResult = await this.paymentService.requestAPIPayment({
url: task.apiUrl,
method: 'POST',
data: task.parameters
});
if (paymentResult.success) {
// Use payment header for API call
const response = await fetch(task.apiUrl, {
method: 'POST',
headers: {
'X-Payment': paymentResult.xPaymentHeader,
'Content-Type': 'application/json'
},
body: JSON.stringify(task.parameters)
});
return await response.json();
} else {
throw new Error(`Payment failed: ${paymentResult.error}`);
}
}
}
}
Framework-Specific Examples
Custom React Agent UI
import React, { useState, useEffect } from 'react';
import { PayStablAgent } from '@paystabl/sdk';
interface AgentUIProps {
agentId: string;
apiKey: string;
}
export const AgentPaymentUI: React.FC<AgentUIProps> = ({ agentId, apiKey }) => {
const [paystabl, setPaystabl] = useState<PayStablAgent | null>(null);
const [balance, setBalance] = useState<string>('0');
const [transactions, setTransactions] = useState<any[]>([]);
useEffect(() => {
const agent = new PayStablAgent({ agentId, apiKey });
setPaystabl(agent);
// Load initial data
agent.getBalance().then(setBalance);
agent.getTransactions().then(setTransactions);
}, [agentId, apiKey]);
const handleAPIPayment = async (url: string) => {
if (!paystabl) return;
try {
const payment = await paystabl.pay_api_endpoint({ url });
// Update UI with payment result
setTransactions(prev => [...prev, payment.receipt]);
// Make actual API call
const response = await fetch(url, {
headers: { 'X-Payment': payment.xPaymentHeader }
});
return await response.json();
} catch (error) {
console.error('Payment failed:', error);
}
};
return (
<div className="agent-payment-ui">
<div className="balance">
Balance: ${balance}
</div>
<div className="transactions">
<h3>Recent Transactions</h3>
{transactions.map(tx => (
<div key={tx.txHash} className="transaction">
{tx.amount} - {tx.purpose}
</div>
))}
</div>
<button onClick={() => handleAPIPayment('https://api.example.com/data')}>
Pay for Premium Data
</button>
</div>
);
};
Custom Django Agent Backend
# models.py
from django.db import models
from paystabl import PayStablAgent
class Agent(models.Model):
agent_id = models.CharField(max_length=100, unique=True)
name = models.CharField(max_length=200)
api_key = models.CharField(max_length=500)
created_at = models.DateTimeField(auto_now_add=True)
def get_paystabl_client(self):
return PayStablAgent(
agent_id=self.agent_id,
api_key=self.api_key
)
class PaymentLog(models.Model):
agent = models.ForeignKey(Agent, on_delete=models.CASCADE)
amount = models.DecimalField(max_digits=10, decimal_places=2)
purpose = models.CharField(max_length=500)
tx_hash = models.CharField(max_length=200)
created_at = models.DateTimeField(auto_now_add=True)
# views.py
from django.http import JsonResponse
from django.views import View
from .models import Agent, PaymentLog
class PaymentView(View):
def post(self, request, agent_id):
try:
agent = Agent.objects.get(agent_id=agent_id)
paystabl = agent.get_paystabl_client()
data = json.loads(request.body)
if data['type'] == 'api_payment':
result = paystabl.pay_api_endpoint(
url=data['url'],
method=data.get('method', 'GET'),
data=data.get('payload')
)
# Log the payment
PaymentLog.objects.create(
agent=agent,
amount=result['receipt']['amount'],
purpose=f"API payment to {data['url']}",
tx_hash=result['receipt']['txHash']
)
return JsonResponse({
'success': True,
'payment_header': result['xPaymentHeader'],
'receipt': result['receipt']
})
elif data['type'] == 'agent_payment':
result = paystabl.pay_agent(
from_agent_id=agent_id,
to_agent_id=data['to_agent_id'],
amount=data['amount'],
purpose=data['purpose']
)
# Log the payment
PaymentLog.objects.create(
agent=agent,
amount=data['amount'],
purpose=data['purpose'],
tx_hash=result['txHash']
)
return JsonResponse({
'success': True,
'tx_hash': result['txHash'],
'receipt': result['xPayStablReceipt']
})
except Exception as e:
return JsonResponse({
'success': False,
'error': str(e)
}, status=400)
FastAPI Integration
from fastapi import FastAPI, HTTPException, BackgroundTasks
from pydantic import BaseModel
from paystabl import PayStablAgent
import asyncio
app = FastAPI(title="Agent Payment API")
class APIPaymentRequest(BaseModel):
agent_id: str
url: str
method: str = "GET"
data: dict = None
headers: dict = None
class AgentPaymentRequest(BaseModel):
from_agent_id: str
to_agent_id: str
amount: str
purpose: str
class PaymentService:
def __init__(self):
self.agents = {}
def get_agent(self, agent_id: str) -> PayStablAgent:
if agent_id not in self.agents:
self.agents[agent_id] = PayStablAgent(
agent_id=agent_id,
api_key=os.getenv('PAYSTABL_API_KEY')
)
return self.agents[agent_id]
payment_service = PaymentService()
@app.post("/api/pay/endpoint")
async def pay_api_endpoint(request: APIPaymentRequest):
try:
agent = payment_service.get_agent(request.agent_id)
result = await agent.pay_api_endpoint(
url=request.url,
method=request.method,
data=request.data,
headers=request.headers
)
return {
"success": True,
"payment_header": result["xPaymentHeader"],
"receipt": result["receipt"]
}
except Exception as e:
raise HTTPException(status_code=400, detail=str(e))
@app.post("/api/pay/agent")
async def pay_agent(request: AgentPaymentRequest):
try:
agent = payment_service.get_agent(request.from_agent_id)
result = await agent.pay_agent(
from_agent_id=request.from_agent_id,
to_agent_id=request.to_agent_id,
amount=request.amount,
purpose=request.purpose
)
return {
"success": True,
"tx_hash": result["txHash"],
"receipt": result["xPayStablReceipt"]
}
except Exception as e:
raise HTTPException(status_code=400, detail=str(e))
@app.get("/api/agent/{agent_id}/balance")
async def get_balance(agent_id: str):
try:
agent = payment_service.get_agent(agent_id)
balance = await agent.get_balance()
return {
"agent_id": agent_id,
"balance": balance
}
except Exception as e:
raise HTTPException(status_code=400, detail=str(e))
Testing Your Integration
Unit Tests
// payment.test.ts
import { PayStablAgent } from '@paystabl/sdk';
import { jest } from '@jest/globals';
describe('PayStabl Integration', () => {
let agent: PayStablAgent;
beforeEach(() => {
agent = new PayStablAgent({
agentId: 'test_agent',
apiKey: 'test_key',
network: 'base-sepolia'
});
});
test('should handle API payment successfully', async () => {
const mockPayment = {
xPaymentHeader: 'mock_header',
receipt: {
txHash: 'mock_tx',
amount: '1.00'
}
};
jest.spyOn(agent, 'pay_api_endpoint').mockResolvedValue(mockPayment);
const result = await agent.pay_api_endpoint({
url: 'https://test-api.com',
method: 'GET'
});
expect(result.xPaymentHeader).toBe('mock_header');
expect(result.receipt.amount).toBe('1.00');
});
test('should handle payment failures gracefully', async () => {
jest.spyOn(agent, 'pay_api_endpoint').mockRejectedValue(
new Error('Insufficient funds')
);
await expect(agent.pay_api_endpoint({
url: 'https://test-api.com'
})).rejects.toThrow('Insufficient funds');
});
});
Integration Tests
# test_integration.py
import pytest
from paystabl import PayStablAgent
import asyncio
@pytest.fixture
def test_agent():
return PayStablAgent(
agent_id="test_agent_integration",
api_key=os.getenv('PAYSTABL_TEST_API_KEY'),
network="base-sepolia"
)
@pytest.mark.asyncio
async def test_end_to_end_api_payment(test_agent):
# Test with a real test API that supports x402
result = await test_agent.pay_api_endpoint(
url="https://test-402-api.paystabl.com/premium-data",
method="GET"
)
assert result["xPaymentHeader"] is not None
assert result["receipt"]["txHash"] is not None
assert float(result["receipt"]["amount"]) > 0
@pytest.mark.asyncio
async def test_agent_to_agent_payment(test_agent):
# Test payment between test agents
result = await test_agent.pay_agent(
from_agent_id="test_agent_integration",
to_agent_id="test_recipient_agent",
amount="0.10",
purpose="Integration test payment"
)
assert result["status"] == "success"
assert result["txHash"] is not None
Best Practices
Error Handling
class RobustPaymentHandler {
private paystabl: PayStablAgent;
private retryPolicy: RetryPolicy;
constructor(agentId: string, config: PaymentConfig) {
this.paystabl = new PayStablAgent({ agentId, ...config });
this.retryPolicy = config.retryPolicy || this.defaultRetryPolicy;
}
async handlePaymentWithRetry(paymentFn: () => Promise<any>): Promise<any> {
let lastError: Error;
for (let attempt = 1; attempt <= this.retryPolicy.maxAttempts; attempt++) {
try {
return await paymentFn();
} catch (error) {
lastError = error;
if (this.isRetryableError(error) && attempt < this.retryPolicy.maxAttempts) {
const delay = this.calculateDelay(attempt);
await this.sleep(delay);
continue;
}
throw error;
}
}
throw lastError;
}
private isRetryableError(error: any): boolean {
const retryableCodes = ['NETWORK_ERROR', 'TIMEOUT', 'RATE_LIMITED'];
return retryableCodes.includes(error.code);
}
private calculateDelay(attempt: number): number {
return Math.min(1000 * Math.pow(2, attempt - 1), 30000); // Exponential backoff
}
private sleep(ms: number): Promise<void> {
return new Promise(resolve => setTimeout(resolve, ms));
}
}
Configuration Management
interface PaymentConfig {
agentId: string;
apiKey: string;
network: 'mainnet' | 'base-## Deployment Considerations
### Docker Integration
```dockerfile
# Dockerfile for custom agent with PayStabl
FROM node:18-alpine
WORKDIR /app
# Install dependencies
COPY package*.json ./
RUN npm ci --only=production
# Copy application code
COPY . .
# Environment variables
ENV NODE_ENV=production
ENV PAYSTABL_API_KEY=""
ENV AGENT_ID=""
# Health check
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
CMD node healthcheck.js
EXPOSE 3000
CMD ["npm", "start"]
Kubernetes Deployment
# k8s-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: custom-payment-agent
spec:
replicas: 3
selector:
matchLabels:
app: custom-payment-agent
template:
metadata:
labels:
app: custom-payment-agent
spec:
containers:
- name: agent
image: your-registry/custom-payment-agent:latest
ports:
- containerPort: 3000
env:
- name: PAYSTABL_API_KEY
valueFrom:
secretKeyRef:
name: paystabl-secrets
key: api-key
- name: AGENT_ID
value: "k8s-payment-agent"
resources:
requests:
memory: "256Mi"
cpu: "100m"
limits:
memory: "512Mi"
cpu: "500m"
livenessProbe:
httpGet:
path: /health
port: 3000
initialDelaySeconds: 30
periodSeconds: 10
---
apiVersion: v1
kind: Secret
metadata:
name: paystabl-secrets
type: Opaque
data:
api-key: <base64-encoded-api-key>