DEV Community

Dakota Liu
Dakota Liu

Posted on

A $0 AI Summary API: Free Tokens, Free Server, and a Working Walkthrough

Spoiler: you don't need a credit card to ship a real AI service today. I just deployed a document-summary API using MonkeyCode's free model quota and their free server option. The whole thing took about thirty minutes — including debugging one silly bug that taught me more than the happy path ever would.

Disclosure: This article was prepared as part of MonkeyCode's product outreach.

Before we dive in: I'm not here to sell you magic. The free tier is real — 10 million tokens at the time of writing — but it comes with constraints. You'll hit rate limits, cold starts, and occasional 5xx errors. That's fine. The point of this tutorial is to show you how to build something that survives those constraints without burning your wallet.

What we're building

A FastAPI service with one endpoint: POST /summarize. It takes a chunk of text, sends it to the free model behind MonkeyCode, and returns a clean summary. Along the way, we add three things that most tutorials skip: a timeout, a retry, and a tiny cache.

Why these three? Because free endpoints are not perfect. And your users don't care about your excuses.

Step 0: Project structure

Keep it simple. One folder, five files.

summary-api/
├── app.py
├── llm.py
├── requirements.txt
└── .env
Enter fullscreen mode Exit fullscreen mode

Then install dependencies:

pip install fastapi uvicorn python-dotenv requests
Enter fullscreen mode Exit fullscreen mode

Step 1: The LLM client with teeth

Here's the part most tutorials skip: actual error handling. Free model endpoints can be slow or flaky, so we need a timeout and a retry loop.

# llm.py
import os
import time
import requests

API_URL = os.getenv("MONKEYCODE_API_URL")  # e.g. "https://your-provider.example/v1/chat/completions"
API_KEY = os.getenv("MONKEYCODE_API_KEY")

def summarize(text: str) -> str:
    headers = {
        "Authorization": f"Bearer {API_KEY}",
        "Content-Type": "application/json"
    }
    payload = {
        "model": os.getenv("MONKEYCODE_MODEL", "default"),
        "messages": [
            {"role": "system", "content": "You summarize text in under 100 words."},
            {"role": "user", "content": text[:4000]}
        ],
        "temperature": 0.3,
        "max_tokens": 150
    }

    for attempt in range(3):
        try:
            resp = requests.post(API_URL, json=payload, headers=headers, timeout=15)
            resp.raise_for_status()
            return resp.json()["choices"][0]["message"]["content"]
        except Exception as e:
            if attempt == 2:
                raise RuntimeError(f"LLM call failed: {e}")
            time.sleep(2 * attempt)
Enter fullscreen mode Exit fullscreen mode

Notice I truncated the input to 4000 characters. That's a conscious trade-off: free tokens are precious, and a summary doesn't need the whole novel.

Step 2: FastAPI endpoint with a cache

Now the web layer. I added a tiny in-memory cache so repeated requests don't burn your quota again.

# app.py
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
import hashlib
import llm

app = FastAPI()
cache = {}

class TextIn(BaseModel):
    text: str

@app.post("/summarize")
def summarize(req: TextIn):
    key = hashlib.sha256(req.text.encode()).hexdigest()
    if key in cache:
        return {"summary": cache[key], "cached": True}

    try:
        result = llm.summarize(req.text)
    except Exception as e:
        raise HTTPException(status_code=502, detail=str(e))

    cache[key] = result
    return {"summary": result, "cached": False}
Enter fullscreen mode Exit fullscreen mode

Run it locally first:

uvicorn app:app --port 8000
Enter fullscreen mode Exit fullscreen mode

Then test:

curl -X POST http://localhost:8000/summarize \
  -H "Content-Type: application/json" \
  -d '{"text": "FastAPI is a modern Python web framework used to build APIs. It is built on Starlette and Pydantic, enabling automatic request validation and interactive docs."}'
Enter fullscreen mode Exit fullscreen mode

You should see a JSON response with a summary and "cached": false. Run the same command again — now it should say "cached": true. That's your first win.

Step 3: Push it to the free server

MonkeyCode's free server option is the perfect companion for this experiment. I won't paste the exact deploy command here because it changes as the project evolves — check their README. The general flow is:

  1. Set MONKEYCODE_API_URL, MONKEYCODE_API_KEY, and MONKEYCODE_MODEL as environment variables.
  2. Expose port 8000 (or whatever port the server expects via $PORT).
  3. Use uvicorn app:app --host 0.0.0.0 --port $PORT as the start command.

If your free server is a plain Linux box, the same commands work. Do not overthink it.

Step 4: Verify on the public URL

Once deployed, hit the public endpoint from your terminal:

curl -X POST https://your-free-server.example/summarize \
  -H "Content-Type: application/json" \
  -d '{"text": "MonkeyCode is an open-source project offering free model access and free server resources for developers who want to experiment without opening their wallets."}'
Enter fullscreen mode Exit fullscreen mode

A successful response means the whole pipeline is alive. Now you have a public AI endpoint that costs you exactly $0.

The one bug that made me smile

I forgot to set max_tokens on my first attempt. The summary came back with 500 words because the free model assumed I wanted an essay. After adding max_tokens: 150, the output became sane. Why did this take me ten minutes to debug? Because I trusted the model's judgment more than my own. Rookie move.

Limitations you should accept (before reading further)

  • The 10M token quota is generous but not infinite. Use caching aggressively.
  • Free servers may have cold starts — don't build a latency-sensitive product on top of this.
  • The model is a shared free tier, so expect occasional rate limits. My retry loop handles those gracefully.
  • Don't send sensitive or personal data to any free LLM endpoint. Read the privacy policy.

Who should not use this approach? Anyone building a production SaaS for paying customers. This stack is for experiments, prototypes, internal tools, and learning. That's valuable, though. Not every good idea deserves a paid instance on day one.

Final thoughts

Free infrastructure has finally reached the point where a competent developer can go from zero to a working AI API in an afternoon. MonkeyCode's open-source project is a legitimate part of that shift. The repo has the actual details on tokens, server options, and usage limits — my walkthrough just gives you the engineering glue.

Try it. Build a small bot, a summary plugin, a daily digest. The cheapest lesson is usually the best one.

Top comments (0)