Trong bài viết này, mình sẽ chia sẻ kinh nghiệm thực chiến khi triển khai LangGraph lên production với hệ thống API Gateway audit hoàn chỉnh. Đây là những bài học xương máu từ các dự án thực tế mà mình đã triển khai cho khách hàng doanh nghiệp.

Bảng So Sánh Chi Phí và Hiệu Suất

Trước khi đi vào chi tiết kỹ thuật, chúng ta cùng xem bảng so sánh giữa các nhà cung cấp API AI hàng đầu hiện nay:

Nhà cung cấp Giá GPT-4.1 ($/MTok) Giá Claude Sonnet 4.5 ($/MTok) Độ trễ trung bình Hỗ trợ thanh toán
HolySheep AI $8.00 $15.00 <50ms WeChat, Alipay, Visa
API Chính thức (OpenAI) $60.00 $18.00 150-300ms Thẻ quốc tế
Relay Services (chuyển tiếp) $45-55 $15-17 100-200ms Hạn chế

Như các bạn thấy, HolySheep AI tiết kiệm được 85-90% chi phí so với API chính thức, đồng thời độ trễ thấp hơn đáng kể nhờ hạ tầng server tối ưu cho thị trường Châu Á.

Tại Sao Cần API Gateway Audit Cho LangGraph?

Khi triển khai LangGraph lên production, việc audit API là vô cùng quan trọng vì:

Kiến Trúc Hệ Thống

Mình recommend kiến trúc sau cho production deployment:

+------------------+     +------------------+     +------------------+
|   Client App     | --> |  API Gateway     | --> |   LangGraph      |
|  (Streamlit,     |     |  (Audit Layer)   |     |   Application    |
|   React, etc.)   |     |                  |     |                  |
+------------------+     +------------------+     +------------------+
                                |                         |
                                v                         v
                         +------------------+     +------------------+
                         |  Audit Database  |     |  HolySheep AI    |
                         |  (PostgreSQL)    |     |  API Gateway      |
                         +------------------+     +------------------+

Cài Đặt Môi Trường

# requirements.txt
langgraph==0.2.50
langchain-core==0.3.24
langchain-holysheep==0.1.2  # HolySheep LangChain Integration
fastapi==0.115.0
uvicorn==0.32.0
pydantic==2.9.2
python-dotenv==1.0.1
httpx==0.27.2
psycopg2-binary==2.9.9
redis==5.2.0
structlog==24.4.0
# .env.example

HolySheep AI Configuration

HOLYSHEEP_API_KEY=YOUR_HOLYSHEEP_API_KEY HOLYSHEEP_BASE_URL=https://api.holysheep.ai/v1

Application Settings

APP_NAME=langgraph-production APP_ENV=production LOG_LEVEL=INFO

Database

DATABASE_URL=postgresql://user:pass@localhost:5432/audit_db

Redis for rate limiting

REDIS_URL=redis://localhost:6379/0

Rate Limiting

RATE_LIMIT_REQUESTS=100 RATE_LIMIT_WINDOW=60 # seconds

Implement API Gateway Audit Layer

Đây là phần core của hệ thống - mình sẽ hướng dẫn chi tiết từng component:

1. Audit Models và Database Schema

# models/audit.py
from datetime import datetime
from enum import Enum
from typing import Optional, Dict, Any
from pydantic import BaseModel, Field
from sqlalchemy import Column, String, DateTime, Integer, Text, Boolean, JSON
from sqlalchemy.ext.declarative import declarative_base

Base = declarative_base()

class RequestStatus(str, Enum):
    SUCCESS = "success"
    RATE_LIMITED = "rate_limited"
    AUTH_FAILED = "auth_failed"
    ERROR = "error"
    TIMEOUT = "timeout"

class APIAuditLog(Base):
    __tablename__ = "api_audit_logs"
    
    id = Column(String(36), primary_key=True)
    timestamp = Column(DateTime, default=datetime.utcnow, index=True)
    client_ip = Column(String(45), index=True)
    api_key = Column(String(64), index=True)  # Hash of actual key
    endpoint = Column(String(255))
    method = Column(String(10))
    request_body = Column(Text, nullable=True)
    request_headers = Column(JSON)
    response_status = Column(Integer)
    response_body = Column(Text, nullable=True)
    response_time_ms = Column(Integer)
    tokens_used = Column(Integer, default=0)
    model = Column(String(100))
    cost_usd = Column(Float, default=0.0)
    status = Column(String(20))
    error_message = Column(Text, nullable=True)
    metadata = Column(JSON, nullable=True)

class APIKey(Base):
    __tablename__ = "api_keys"
    
    id = Column(String(36), primary_key=True)
    key_hash = Column(String(64), unique=True, index=True)
    key_prefix = Column(String(8))  # First 8 chars for display
    client_name = Column(String(255))
    created_at = Column(DateTime, default=datetime.utcnow)
    last_used = Column(DateTime, nullable=True)
    is_active = Column(Boolean, default=True)
    rate_limit = Column(Integer, default=100)  # requests per minute
    quota_monthly = Column(Integer, nullable=True)  # NULL = unlimited
    usage_this_month = Column(Integer, default=0)
    allowed_endpoints = Column(JSON, nullable=True)  # NULL = all allowed
    metadata = Column(JSON, nullable=True)

class RequestLog(BaseModel):
    id: str
    timestamp: datetime
    client_ip: str
    api_key_id: str
    endpoint: str
    method: str
    request_body: Optional[str] = None
    request_headers: Dict[str, Any]
    response_status: int
    response_time_ms: int
    tokens_used: int = 0
    model: Optional[str] = None
    cost_usd: float = 0.0
    status: RequestStatus
    error_message: Optional[str] = None
    metadata: Optional[Dict[str, Any]] = None

class RateLimitInfo(BaseModel):
    allowed: bool
    remaining: int
    reset_at: datetime
    limit: int

2. Audit Service Implementation

# services/audit_service.py
import hashlib
import time
import uuid
from datetime import datetime, timedelta
from typing import Optional, Dict, Any, Tuple
from contextlib import asynccontextmanager

import httpx
import redis.asyncio as redis
import structlog
from sqlalchemy.ext.asyncio import AsyncSession, create_async_engine, async_sessionmaker
from sqlalchemy import select, update

from models.audit import APIAuditLog, APIKey, RequestLog, RequestStatus, RateLimitInfo

logger = structlog.get_logger()

class AuditService:
    """Service xử lý audit logging và rate limiting"""
    
    def __init__(self, database_url: str, redis_url: str):
        self.engine = create_async_engine(database_url, echo=False)
        self.async_session = async_sessionmaker(self.engine, expire_on_commit=False)
        self.redis = redis.from_url(redis_url, decode_responses=True)
        self._http_client = httpx.AsyncClient(timeout=30.0)
    
    async def hash_api_key(self, api_key: str) -> str:
        """Hash API key để lưu trữ an toàn"""
        return hashlib.sha256(api_key.encode()).hexdigest()
    
    async def get_api_key_prefix(self, api_key: str) -> str:
        """Lấy prefix của API key để hiển thị"""
        return api_key[:8]
    
    async def validate_api_key(self, api_key: str) -> Tuple[bool, Optional[APIKey], str]:
        """
        Validate API key
        Returns: (is_valid, api_key_obj, error_message)
        """
        key_hash = await self.hash_api_key(api_key)
        
        async with self.async_session() as session:
            result = await session.execute(
                select(APIKey).where(
                    APIKey.key_hash == key_hash,
                    APIKey.is_active == True
                )
            )
            api_key_obj = result.scalar_one_or_none()
            
            if not api_key_obj:
                return False, None, "API key không hợp lệ hoặc đã bị vô hiệu hóa"
            
            # Update last used
            api_key_obj.last_used = datetime.utcnow()
            await session.commit()
            
            return True, api_key_obj, ""
    
    async def check_rate_limit(
        self, 
        api_key_id: str, 
        limit: int, 
        window_seconds: int = 60
    ) -> RateLimitInfo:
        """
        Kiểm tra và cập nhật rate limit
        Sử dụng sliding window algorithm
        """
        key = f"rate_limit:{api_key_id}"
        now = time.time()
        window_start = now - window_seconds
        
        # Remove old requests
        await self.redis.zremrangebyscore(key, 0, window_start)
        
        # Count current requests
        current_count = await self.redis.zcard(key)
        
        if current_count >= limit:
            # Get oldest request timestamp
            oldest = await self.redis.zrange(key, 0, 0, withscores=True)
            if oldest:
                reset_at = datetime.fromtimestamp(oldest[0][1] + window_seconds)
            else:
                reset_at = datetime.fromtimestamp(now + window_seconds)
            
            return RateLimitInfo(
                allowed=False,
                remaining=0,
                reset_at=reset_at,
                limit=limit
            )
        
        # Add current request
        await self.redis.zadd(key, {str(uuid.uuid4()): now})
        await self.redis.expire(key, window_seconds + 10)
        
        return RateLimitInfo(
            allowed=True,
            remaining=limit - current_count - 1,
            reset_at=datetime.fromtimestamp(now + window_seconds),
            limit=limit
        )
    
    async def log_request(
        self,
        api_key_id: str,
        endpoint: str,
        method: str,
        client_ip: str,
        request_body: Optional[str],
        request_headers: Dict[str, Any],
        response_status: int,
        response_time_ms: int,
        tokens_used: int,
        model: Optional[str],
        cost_usd: float,
        status: RequestStatus,
        error_message: Optional[str] = None,
        metadata: Optional[Dict[str, Any]] = None
    ) -> str:
        """Ghi log request vào database"""
        log_id = str(uuid.uuid4())
        
        # Hash API key for storage
        # Note: In real implementation, pass the original key here
        api_key_hash = await self.hash_api_key("")  # Placeholder
        
        async with self.async_session() as session:
            audit_log = APIAuditLog(
                id=log_id,
                timestamp=datetime.utcnow(),
                client_ip=client_ip,
                api_key=f"hashed:{api_key_id}",  # Store hash reference
                endpoint=endpoint,
                method=method,
                request_body=request_body[:10000] if request_body else None,  # Truncate
                request_headers=request_headers,
                response_status=response_status,
                response_time_ms=response_time_ms,
                tokens_used=tokens_used,
                model=model,
                cost_usd=cost_usd,
                status=status.value,
                error_message=error_message,
                metadata=metadata
            )
            session.add(audit_log)
            await session.commit()
        
        return log_id
    
    async def close(self):
        """Cleanup resources"""
        await self._http_client.aclose()
        await self.redis.close()
        await self.engine.dispose()

3. LangGraph Integration với HolySheep AI

# graph/langgraph_app.py
import os
from typing import TypedDict, Annotated, Sequence
from datetime import datetime

from langchain_core.messages import BaseMessage, HumanMessage, AIMessage
from langchain_core.language_models import BaseChatModel
from langchain_holysheep import ChatHolySheep  # HolySheep LangChain Integration
import structlog

logger = structlog.get_logger()

Environment variables

HOLYSHEEP_API_KEY = os.getenv("HOLYSHEEP_API_KEY", "YOUR_HOLYSHEEP_API_KEY") HOLYSHEEP_BASE_URL = "https://api.holysheep.ai/v1" # HolySheep API endpoint class AgentState(TypedDict): """State cho LangGraph agent""" messages: Annotated[Sequence[BaseMessage], "The messages in the conversation"] user_id: str session_id: str total_tokens: int total_cost: float def create_langgraph_agent(): """Tạo LangGraph agent với HolySheep AI""" # Initialize HolySheep LLM llm = ChatHolySheep( api_key=HOLYSHEEP_API_KEY, base_url=HOLYSHEEP_BASE_URL, model="gpt-4.1", # Hoặc claude-sonnet-4.5, deepseek-v3.2 temperature=0.7, max_tokens=4096, # Callback để track usage callbacks=[ TokenUsageCallback() # Implement callback để track usage ] ) # Định nghĩa các node trong graph def process_node(state: AgentState) -> AgentState: messages = state["messages"] # Gọi LLM với messages hiện tại response = llm.invoke(messages) return { **state, "messages": [*messages, response], } def audit_node(state: AgentState) -> AgentState: """Node audit - ghi log sau mỗi request""" logger.info( "audit_node", user_id=state["user_id"], session_id=state["session_id"], message_count=len(state["messages"]), total_tokens=state["total_tokens"], total_cost=state["total_cost"] ) return state # Build graph from langgraph.graph import StateGraph, END workflow = StateGraph(AgentState) workflow.add_node("process", process_node) workflow.add_node("audit", audit_node) workflow.set_entry_point("process") workflow.add_edge("process", "audit") workflow.add_edge("audit", END) return workflow.compile() class TokenUsageCallback: """Callback để track token usage từ HolySheep API""" def __init__(self): self.total_tokens = 0 self.prompt_tokens = 0 self.completion_tokens = 0 self.total_cost = 0.0 # HolySheep Pricing (2026) - USD per 1M tokens self.pricing = { "gpt-4.1": {"input": 2.0, "output": 8.0}, "claude-sonnet-4.5": {"input": 3.0, "output": 15.0}, "deepseek-v3.2": {"input": 0.14, "output": 0.42}, "gemini-2.5-flash": {"input": 0.30, "output": 2.50}, } def on_llm_end(self, response, **kwargs): """Called when LLM finishes generation""" usage = response.usage if usage: self.prompt_tokens += usage.prompt_tokens self.completion_tokens += usage.completion_tokens self.total_tokens += usage.total_tokens # Calculate cost dựa trên model model = kwargs.get("model", "gpt-4.1") pricing = self.pricing.get(model, {"input": 0, "output": 0}) cost = ( (usage.prompt_tokens / 1_000_000) * pricing["input"] + (usage.completion_tokens / 1_000_000) * pricing["output"] ) self.total_cost += cost logger.info( "token_usage", prompt_tokens=usage.prompt_tokens, completion_tokens=usage.completion_tokens, cost_usd=cost, model=model ) def reset(self): """Reset counters cho session mới""" self.total_tokens = 0 self.prompt_tokens = 0 self.completion_tokens = 0 self.total_cost = 0.0

Usage example

if __name__ == "__main__": agent = create_langgraph_agent() initial_state = { "messages": [HumanMessage(content="Xin chào, hãy giới thiệu về HolySheep AI")], "user_id": "user_123", "session_id": "session_456", "total_tokens": 0, "total_cost": 0.0 } result = agent.invoke(initial_state) print(f"Total cost: ${result['total_cost']:.4f}")

4. FastAPI Application với Middleware

# main.py
import os
import time
import json
from datetime import datetime
from typing import Optional
from contextlib import asynccontextmanager

from fastapi import FastAPI, Request, HTTPException, Depends, Header
from fastapi.middleware.cors import CORSMiddleware
from fastapi.responses import JSONResponse
from pydantic import BaseModel
import structlog

from services.audit_service import AuditService
from graph.langgraph_app import create_langgraph_agent, AgentState

Configuration

DATABASE_URL = os.getenv("DATABASE_URL", "postgresql+asyncpg://user:pass@localhost:5432/audit_db") REDIS_URL = os.getenv("REDIS_URL", "redis://localhost:6379/0")

Initialize services

audit_service: Optional[AuditService] = None langgraph_agent = None @asynccontextmanager async def lifespan(app: FastAPI): """Lifecycle manager""" global audit_service, langgraph_agent # Startup audit_service = AuditService(DATABASE_URL, REDIS_URL) langgraph_agent = create_langgraph_agent() logger.info("Application started") yield # Shutdown await audit_service.close() logger.info("Application shutdown") app = FastAPI( title="LangGraph Production API", version="1.0.0", lifespan=lifespan )

CORS middleware

app.add_middleware( CORSMiddleware, allow_origins=["*"], # Configure properly in production allow_credentials=True, allow_methods=["*"], allow_headers=["*"], )

Structured logging

structlog.configure( processors=[ structlog.processors.TimeStamper(fmt="iso"), structlog.processors.JSONRenderer() ] ) logger = structlog.get_logger()

Pydantic models

class ChatRequest(BaseModel): message: str user_id: str session_id: Optional[str] = None model: Optional[str] = "gpt-4.1" temperature: Optional[float] = 0.7 class ChatResponse(BaseModel): response: str session_id: str tokens_used: int cost_usd: float model: str

Dependencies

async def verify_api_key(x_api_key: str = Header(..., alias="X-API-Key")) -> str: """Dependency để verify API key""" is_valid, api_key_obj, error = await audit_service.validate_api_key(x_api_key) if not is_valid: raise HTTPException(status_code=401, detail=error) return api_key_obj.id

Middleware for audit logging

@app.middleware("http") async def audit_middleware(request: Request, call_next): """Middleware để log tất cả requests""" start_time = time.time() # Extract request info client_ip = request.client.host if request.client else "unknown" api_key = request.headers.get("X-API-Key", "") # Process request try: response = await call_next(request) status_code = response.status_code error_message = None except Exception as e: status_code = 500 error_message = str(e) response = JSONResponse( status_code=500, content={"detail": "Internal server error"} ) # Calculate response time response_time_ms = int((time.time() - start_time) * 1000) # Log to audit (async, non-blocking) try: await audit_service.log_request( api_key_id=api_key[:8], # Use prefix for identification endpoint=str(request.url.path), method=request.method, client_ip=client_ip, request_body=None, # Body logged separately if needed request_headers=dict(request.headers), response_status=status_code, response_time_ms=response_time_ms, tokens_used=0, model=None, cost_usd=0.0, status="success" if status_code < 400 else "error", error_message=error_message ) except Exception as e: logger.error("audit_log_failed", error=str(e)) return response

API Endpoints

@app.post("/v1/chat", response_model=ChatResponse) async def chat( request: ChatRequest, api_key_id: str = Depends(verify_api_key) ): """ Chat endpoint - sử dụng LangGraph agent với HolySheep AI """ # Check rate limit rate_info = await audit_service.check_rate_limit( api_key_id=api_key_id, limit=100, window_seconds=60 ) if not rate_info.allowed: raise HTTPException( status_code=429, detail={ "error": "Rate limit exceeded", "remaining": rate_info.remaining, "reset_at": rate_info.reset_at.isoformat(), "limit": rate_info.limit } ) # Create session ID if not provided session_id = request.session_id or f"{request.user_id}_{int(time.time())}" # Prepare state from langchain_core.messages import HumanMessage initial_state: AgentState = { "messages": [HumanMessage(content=request.message)], "user_id": request.user_id, "session_id": session_id, "total_tokens": 0, "total_cost": 0.0 } # Invoke agent result = await langgraph_agent.ainvoke(initial_state) # Extract response response_message = result["messages"][-1].content return ChatResponse( response=response_message, session_id=session_id, tokens_used=result.get("total_tokens", 0), cost_usd=result.get("total_cost", 0.0), model=request.model ) @app.get("/v1/usage") async def get_usage(api_key_id: str = Depends(verify_api_key)): """Get usage statistics cho API key""" # Implement query to get usage stats return { "api_key_id": api_key_id, "period": "current_month", "total_requests": 0, "total_tokens": 0, "total_cost_usd": 0.0 } @app.get("/health") async def health_check(): """Health check endpoint""" return { "status": "healthy", "timestamp": datetime.utcnow().isoformat(), "version": "1.0.0" } if __name__ == "__main__": import uvicorn uvicorn.run(app, host="0.0.0.0", port=8000)

Docker Deployment

# docker-compose.yml
version: '3.8'

services:
  app:
    build:
      context: .
      dockerfile: Dockerfile
    ports:
      - "8000:8000"
    environment:
      - HOLYSHEEP_API_KEY=${HOLYSHEEP_API_KEY}
      - DATABASE_URL=postgresql+asyncpg://postgres:postgres@db:5432/audit_db
      - REDIS_URL=redis://redis:6379/0
      - APP_ENV=production
    depends_on:
      - db
      - redis
    restart: unless-stopped
    deploy:
      resources:
        limits:
          memory: 2G
          cpus: '2'

  db:
    image: postgres:16-alpine
    environment:
      - POSTGRES_DB=audit_db
      - POSTGRES_USER=postgres
      - POSTGRES_PASSWORD=postgres
    volumes:
      - postgres_data:/var/lib/postgresql/data
      - ./init.sql:/docker-entrypoint-initdb.d/init.sql
    restart: unless-stopped

  redis:
    image: redis:7-alpine
    command: redis-server --appendonly yes
    volumes:
      - redis_data:/data
    restart: unless-stopped

  nginx:
    image: nginx:alpine
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf:ro
      - ./ssl:/etc/nginx/ssl:ro
    depends_on:
      - app
    restart: unless-stopped

volumes:
  postgres_data:
  redis_data:

Lỗi thường gặp và cách khắc phục

1. Lỗi "API key validation failed" - Mã 401

Nguyên nhân: API key không đúng format hoặc đã bị vô hiệu hóa

# Cách khắc phục:

1. Kiểm tra format API key

API_KEY = "YOUR_HOLYSHEEP_API_KEY" # Phải là key hợp lệ từ HolySheep

2. Verify key có tồn tại trong database

import hashlib key_hash = hashlib.sha256(API_KEY.encode()).hexdigest()

3. Check trong database:

SELECT * FROM api_keys WHERE key_hash = '...' AND is_active = true

4. Nếu key bị vô hiệu hóa, re-activate:

UPDATE api_keys SET is_active = true WHERE id = '...'

5. Log chi tiết để debug

logger.error( "api_key_validation_failed", key_prefix=API_KEY[:8], key_hash=key_hash, reason="invalid_or_disabled" )

2. Lỗi "Rate limit exceeded" - Mã 429

Nguyên nhân: Client gửi quá nhiều requests trong khoảng thời gian ngắn

# Cách khắc phục:

1. Kiểm tra rate limit config

RATE_LIMIT_REQUESTS = 100 # requests per window RATE_LIMIT_WINDOW = 60 # seconds

2. Implement exponential backoff

import asyncio import random async def call_with_retry(func, max_retries=3, base_delay=1.0): for attempt in range(max_retries): try: return await func() except HTTPException as e: if e.status_code == 429: delay = base_delay * (2 ** attempt) + random.uniform(0, 1) logger.warning( "rate_limit_retry", attempt=attempt + 1, delay_seconds=delay ) await asyncio.sleep(delay) else: raise raise HTTPException(status_code=429, detail="Rate limit exceeded after retries")

3. Monitor Redis rate limit keys

KEYS rate_limit:*

4. Tăng limit cho enterprise clients

UPDATE api_keys SET rate_limit = 1000 WHERE client_name LIKE '%enterprise%'

3. Lỗi "Connection timeout" hoặc "SSL verification failed"

Nguyên nhân: Vấn đề kết nối mạng hoặc SSL certificate

# Cách khắc phục:

1. Kiểm tra HolySheep API URL

HOLYSHEEP_BASE_URL = "https://api.holysheep.ai/v1" # Phải chính xác

2. Verify SSL certificate (trong môi trường dev)

import ssl import httpx

Disable SSL verify CHỈ trong development

KHÔNG BAO GIỜ làm điều này trong production!

context = ssl.create_default_context()

context.check_hostname = False # UNSAFE - chỉ dev

context.verify_mode = ssl.CERT_NONE # UNSAFE - chỉ dev

3. Test connection

async def test_connection(): async with httpx.AsyncClient() as client: try: response = await client.get( "https://api.holysheep.ai/v1/models", headers={"Authorization": f"Bearer {HOLYSHEEP_API_KEY}"}, timeout=10.0 ) logger.info("connection_success", status=response.status_code) except httpx.TimeoutException: logger.error("connection_timeout") # Retry hoặc failover except httpx.SSLError as e: logger.error("ssl_error", detail=str(e))

4. Kiểm tra firewall/network

- Whitelist: api.holysheep.ai

- Ports: 443 (HTTPS)

- DNS: Resolves correctly

4. Lỗi "Invalid model name"

Nguyên nhân: Model name không đúng với danh sách được hỗ trợ

# Cách khắc phục:

1. Danh sách models được hỗ trợ (2026)

SUPPORTED_MODELS = [ "gpt-4.1", # $8/MTok output "claude-sonnet-4.5", # $15/MTok output "deepseek-v3.2", # $0.42/MTok output "gemini-2.5-flash", # $2.50/MTok output ]

2. Validate model trước khi gọi

def validate_model(model: str) -> bool: return model in SUPPORTED_MODELS

3. Auto-fallback nếu model không hợp lệ

def get_valid_model(requested_model: str) -> str: if requested_model in SUPPORTED_MODELS: return requested_model # Fallback to gpt-4.1 logger.warning( "model_not_supported", requested=requested_model, fallback="gpt-4.1" ) return "gpt-4.1"

4. Cache danh sách models từ API

async def get_available_models(): async with httpx.AsyncClient() as client: response = await client.get( "https://api.holysheep.ai/v1/models", headers={"Authorization": f"Bearer {HOLYSHEEP_API_KEY}"} ) return [m["id"] for m in response.json()["data"]]

Best Practices Cho Production