{"slug": "how-i-built-and-deployed-an-ai-vision-api-from-scratch-with-yolov8-and-fastapi", "title": "How I Built and Deployed an AI Vision API from Scratch with YOLOv8 and FastAPI", "summary": "A CS and Mathematics student from Ujjain, India, built and deployed LARA, a lightweight computer vision API that runs YOLOv8 nano on a CPU-only server, eliminating the need for GPUs. The API, built with FastAPI, Supabase, Razorpay, and Railway, allows developers to send an image and receive object detections with confidence scores and bounding boxes in a simple API call.", "body_md": "I am a CS and Mathematics student from Ujjain, India. A few months ago\n\nI was trying to learn computer vision and build real projects with it.\n\nThen I hit a wall.\n\nEvery tutorial, every library, every framework assumed you had an NVIDIA\n\nGPU. CUDA this. GPU memory that. \"Just spin up a cloud GPU instance\" —\n\nat $2-3 per hour, which adds up to hundreds of dollars per month.\n\nI have an Intel integrated graphics chip. 8GB RAM. No NVIDIA card. No\n\nbudget for cloud GPUs.\n\nI couldn't do the thing I wanted to learn.\n\nSo I decided to build the solution I wished existed.\n\n**LARA — Lightweight Adaptive Recognition API**\n\nA computer vision API where you send an image and get back detected\n\nobjects, confidence scores, and bounding box coordinates in one simple\n\nAPI call. The heavy AI computation runs on my server. You get the\n\nresults instantly. No GPU needed on your end. Ever.\n\nHere is all the code a developer needs to use LARA:\n\n``` python\nimport requests\n\nresponse = requests.post(\n    \"https://web-production-41d94.up.railway.app/detect\",\n    headers={\"x-api-key\": \"your-api-key\"},\n    files={\"file\": open(\"image.jpg\", \"rb\")}\n)\n\nprint(response.json())\n```\n\nThat's it. Three lines. You get back:\n\n```\n{\n  \"status\": \"success\",\n  \"count\": 2,\n  \"detections\": [\n    {\"label\": \"person\", \"confidence\": 0.92, \"box\": [10, 20, 150, 300]},\n    {\"label\": \"car\",    \"confidence\": 0.87, \"box\": [200, 50, 500, 400]}\n  ]\n}\n```\n\nHere is exactly what I used to build LARA:\n\n**AI Model — YOLOv8 nano**\n\nI chose YOLOv8 nano specifically because it is the smallest and fastest\n\nvariant of YOLOv8. It detects 80+ object classes accurately while being\n\nlight enough to run on a basic CPU server without timing out.\n\n**API Framework — FastAPI**\n\nFastAPI auto-generates beautiful API documentation, handles file uploads\n\ncleanly, and is fast enough for production workloads. It also generates\n\nOpenAPI specs automatically which made listing on RapidAPI easy.\n\n**Database — Supabase**\n\nThree tables: users, usage, billing. Every API call gets logged. Every\n\ndeveloper gets tracked. Supabase gave me a production-grade PostgreSQL\n\ndatabase with a clean Python client and Row Level Security — for free.\n\n**Payments — Razorpay**\n\nFor Indian developers and businesses. Razorpay handles the billing so\n\nI don't have to.\n\n**Hosting — Railway**\n\nDeployed via Docker. Railway auto-deploys every time I push to GitHub.\n\nThe entire deployment pipeline took about 30 minutes to set up.\n\nI started with a basic FastAPI app:\n\n``` python\nfrom fastapi import FastAPI, File, UploadFile, Header, HTTPException\nfrom PIL import Image\nfrom ultralytics import YOLO\nimport io\n\napp = FastAPI(title=\"LARA API\")\nmodel = YOLO(\"yolov8n.pt\")\n\n@app.post(\"/detect\")\nasync def detect(file: UploadFile = File(...), x_api_key: str = Header(...)):\n    contents = await file.read()\n    img = Image.open(io.BytesIO(contents)).convert(\"RGB\")\n    results = model(img, verbose=False)\n\n    detections = []\n    for box in results[0].boxes:\n        label = model.names[int(box.cls)]\n        confidence = round(float(box.conf), 3)\n        x1, y1, x2, y2 = [round(float(v)) for v in box.xyxy[0]]\n        detections.append({\n            \"label\": label,\n            \"confidence\": confidence,\n            \"box\": [x1, y1, x2, y2]\n        })\n\n    return {\"status\": \"success\", \"detections\": detections, \"count\": len(detections)}\n```\n\nI added API key validation and usage logging with Supabase:\n\n``` python\ndef get_user(api_key: str):\n    result = supabase.table(\"users\").select(\"*\").eq(\"api_key\", api_key).execute()\n    if result.data:\n        return result.data[0]\n    return None\n\ndef log_usage(api_key: str, endpoint: str):\n    supabase.table(\"usage\").insert({\n        \"api_key\": api_key,\n        \"endpoint\": endpoint,\n        \"timestamp\": datetime.now().isoformat()\n    }).execute()\n```\n\nYOLOv8 nano sometimes detects the same object twice with slightly\n\ndifferent bounding boxes. I implemented NMS (Non-Maximum Suppression)\n\nmanually to remove duplicates:\n\n```\nseen_boxes = []\nfor box in results[0].boxes:\n    x1, y1, x2, y2 = [round(float(v)) for v in box.xyxy[0]]\n\n    duplicate = False\n    for seen in seen_boxes:\n        sx1, sy1, sx2, sy2 = seen\n        inter_area = max(0, min(x2,sx2)-max(x1,sx1)) * max(0, min(y2,sy2)-max(y1,sy1))\n        union_area = (x2-x1)*(y2-y1) + (sx2-sx1)*(sy2-sy1) - inter_area\n        iou = inter_area / union_area if union_area > 0 else 0\n        if iou > 0.5:\n            duplicate = True\n            break\n\n    if not duplicate and confidence >= 0.3:\n        detections.append({...})\n        seen_boxes.append((x1, y1, x2, y2))\n```\n\nThe biggest challenge was the Linux server not having the display\n\nlibraries OpenCV needs. The fix was switching to\n\n`opencv-python-headless`\n\nand building with a proper Dockerfile:\n\n```\nFROM python:3.10-slim\nWORKDIR /app\nRUN apt-get update && apt-get install -y libglib2.0-0 libgl1 libxcb1\nCOPY requirements.txt .\nRUN pip install --no-cache-dir opencv-python-headless==4.10.0.84\nRUN pip install --no-cache-dir -r requirements.txt\nCOPY . .\nCMD [\"uvicorn\", \"main:app\", \"--host\", \"0.0.0.0\", \"--port\", \"8000\"]\n```\n\nIf you are a developer, student, or researcher who wants to add computer\n\nvision to your project without:\n\nLARA is for you.\n\nA parking management system. A security camera app. A retail analytics\n\ndashboard. A wildlife monitoring tool. All of these need object\n\ndetection. None of them should need a $3000 GPU setup to get started.\n\nRegister at the landing page and get your API key instantly — no credit\n\ncard, no waiting:\n\n👉 [https://lokendraparihar-9977.github.io/lara-landing](https://lokendraparihar-9977.github.io/lara-landing)\n\nFull API docs:\n\n👉 [https://web-production-41d94.up.railway.app/docs](https://web-production-41d94.up.railway.app/docs)\n\nFree tier includes 100 API calls/month. Paid plans start at ₹249/month\n\n(≈ $2.99) for 500 calls — cheaper than 30 minutes on a cloud GPU.\n\nI am building specialized models for:\n\nIf you have a use case you want LARA to support, let me know in the\n\ncomments. I am building this based on real developer needs.\n\n*Built by Lokendra Singh Parihar — CS + Mathematics student,\nVikram University, Ujjain, India.*", "url": "https://wpnews.pro/news/how-i-built-and-deployed-an-ai-vision-api-from-scratch-with-yolov8-and-fastapi", "canonical_source": "https://dev.to/lokendra_parihar/how-i-built-and-deployed-an-ai-vision-api-from-scratch-with-yolov8-and-fastapi-1i87", "published_at": "2026-08-18 12:53:49+00:00", "updated_at": "2026-08-18 13:14:56.287153+00:00", "lang": "en", "topics": ["computer-vision", "artificial-intelligence", "machine-learning", "developer-tools"], "entities": ["LARA", "YOLOv8", "FastAPI", "Supabase", "Razorpay", "Railway", "RapidAPI"], "alternates": {"html": "https://wpnews.pro/news/how-i-built-and-deployed-an-ai-vision-api-from-scratch-with-yolov8-and-fastapi", "markdown": "https://wpnews.pro/news/how-i-built-and-deployed-an-ai-vision-api-from-scratch-with-yolov8-and-fastapi.md", "text": "https://wpnews.pro/news/how-i-built-and-deployed-an-ai-vision-api-from-scratch-with-yolov8-and-fastapi.txt", "jsonld": "https://wpnews.pro/news/how-i-built-and-deployed-an-ai-vision-api-from-scratch-with-yolov8-and-fastapi.jsonld"}}