Setelah memahami konsep dasar dan anatomi aplikasi, saatnya praktik. Kita akan membangun task-tracker-api — REST API sederhana untuk mencatat task — dari nol, dimulai dengan penyimpanan in-memory (data hilang tiap restart). Ini sengaja disederhanakan dulu, karena fokus artikel ini murni pada mekanisme dasar FastAPI: mendefinisikan endpoint, membaca parameter, dan menjalankan server. Validasi yang lebih ketat dan database sungguhan akan menyusul di dua artikel berikutnya.
Target artikel ini: aplikasi FastAPI yang jalan lokal, punya endpoint untuk melihat dan membuat task, dan bisa dieksplorasi lewat dokumentasi interaktif bawaan.
Setup Project
Langkah-langkahnya:
mkdir task-tracker-api
cd task-tracker-api
python3 -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
pip install fastapi "uvicorn[standard]"
uvicorn[standard] menyertakan beberapa dependency opsional (seperti watchfiles untuk auto-reload) yang akan sering kita pakai selama development.
Endpoint Pertama: Health Check
Buat file main.py:
from fastapi import FastAPI
app = FastAPI(title="Task Tracker API")
@app.get("/health")
def health_check():
return {"status": "ok"}
Jalankan servernya:
uvicorn main:app --reload
Beberapa hal yang perlu dipahami dari perintah ini:
main:app — artinya "cari objek bernama app di file main.py". Kalau file atau nama objeknya beda, sesuaikan.--reload — server otomatis restart tiap kali kita menyimpan perubahan kode. Sangat membantu selama development, tapi jangan dipakai di production.Buka http://localhost:8000/health di browser — akan muncul {"status":"ok"}. Lalu buka http://localhost:8000/docs — inilah dokumentasi interaktif (Swagger UI) yang dibahas di artikel sebelumnya, sudah otomatis muncul tanpa kita menulis dokumentasi apa pun.
Menyiapkan "Database" In-Memory
Untuk sementara, kita simpan task di list Python biasa. Tambahkan ini di main.py, di bawah baris app = FastAPI(...):
tasks = [
{"id": 1, "title": "Belajar konsep FastAPI", "done": False},
{"id": 2, "title": "Bikin endpoint pertama", "done": False},
]
next_id = 3
Ini murni untuk keperluan belajar — datanya akan hilang tiap kali server di-restart. Di Bagian 5 nanti, kita ganti ini dengan database sungguhan.
Endpoint GET — Path Parameter dan Query Parameter
Tambahkan tiga endpoint berikut:
from fastapi import HTTPException
@app.get("/api/tasks")
def list_tasks(done: bool | None = None):
if done is None:
return tasks
return [t for t in tasks if t["done"] == done]
@app.get("/api/tasks/{task_id}")
def get_task(task_id: int):
for task in tasks:
if task["id"] == task_id:
return task
raise HTTPException(status_code=404, detail="Task not found")
Perhatikan dua hal yang sudah dibahas konsepnya di artikel sebelumnya, sekarang kita lihat langsung praktiknya:
list_tasks(done: bool | None = None) — done bukan bagian dari path, jadi otomatis jadi query parameter opsional. Coba akses /api/tasks?done=true dan /api/tasks?done=false di browser, bandingkan hasilnya dengan /api/tasks biasa.get_task(task_id: int) — task_id muncul di path ({task_id}), jadi ini path parameter, wajib berupa angka. Coba akses /api/tasks/abc — FastAPI otomatis menolak dengan error validasi, karena abc bukan int.raise HTTPException(status_code=404, ...) — cara eksplisit menghentikan eksekusi dan mengembalikan error dengan status code tertentu. Kita akan bahas ini lebih dalam di artikel berikutnya.Endpoint POST — Menerima Request Body
Sekarang endpoint untuk membuat task baru. Ini butuh Pydantic model untuk mendefinisikan bentuk data yang diharapkan:
from pydantic import BaseModel
class TaskCreate(BaseModel):
title: str
@app.post("/api/tasks", status_code=201)
def create_task(payload: TaskCreate):
global next_id
task = {"id": next_id, "title": payload.title, "done": False}
tasks.append(task)
next_id += 1
return task
Simpan, biarkan --reload mengurus restart otomatis. Sekarang buka /docs, cari section POST /api/tasks, klik "Try it out", isi title, lalu klik Execute. Perhatikan tiga hal:
{"title": "..."}, karena membaca skema dari TaskCreate.title atau hapus field-nya sama sekali — FastAPI otomatis menolak dengan status 422, sebelum kode create_task kita sempat dijalankan.Tes Manual dengan curl
Selain lewat /docs, kita juga bisa tes dari terminal:
curl http://localhost:8000/api/tasks
curl -X POST http://localhost:8000/api/tasks \
-H "Content-Type: application/json" \
-d '{"title": "Deploy ke production"}'
curl http://localhost:8000/api/tasks/999
Perintah terakhir akan mengembalikan {"detail":"Task not found"} dengan status 404 — persis seperti yang kita definisikan di get_task.
Rangkuman File main.py
Setelah semua langkah di atas, main.py kita berisi: setup aplikasi, data in-memory, tiga endpoint (GET /health, GET /api/tasks, GET /api/tasks/{id}), dan satu endpoint POST /api/tasks. Di dua artikel berikutnya, kode ini akan tumbuh: validasi jadi lebih ketat, lalu dipecah jadi beberapa file terpisah begitu kita menyambungkannya ke database sungguhan.
Rangkuman
Kita baru saja membangun API pertama dengan FastAPI: endpoint GET dan POST, path parameter, query parameter, request body lewat Pydantic model, dan eksplorasi lewat dokumentasi interaktif otomatis. Tidak ada satu baris kode dokumentasi yang kita tulis manual — semuanya digenerate dari kode yang sama yang kita jalankan.