Build your own API in Python: a private link-saver for every device
Spot a good link on your phone, save it with one tap, find it later on your laptop. Build linkstash, your own private link-saver with tags, search and an API key, using FastAPI and SQLite. It writes its own documentation, ships with tests, and finishes online behind HTTPS for your phone and automations to use.
- A small web page that uses your API, and a clear understanding of CORS (the browser rule that trips everyone up)
- Nine tests that check every route in under a second, and a server setup with HTTPS, auto-restart and nightly backups
- A starter kit with every file, so you can compare yours or skip the typing
- Level 0 done: Install anything from GitHub, safely and The terminal survival kit.
- uv, the Python installer from Level 0 (Install any free tool from GitHub shows the one-line install). Check with
uv --version. It downloads Python 3.12 and about 45MB of packages for you. - A little Python: functions, dicts and lists. You don't need to know FastAPI or SQL. Every file is complete and explained.
- A code editor. VS Code ↗ is free; Notepad works at a push.
- For step 7 only: a small Linux server and a domain. A 1GB server is plenty: DigitalOcean's ↗ 1GB Basic Droplet is $6 a month plus VAT, and Run n8n 24/7 on a £5 server compares Hetzner, Vultr and DigitalOcean. Domains start at a few pounds a year. Steps 1 to 6 are completely free.
Set up the project and see your first /docs page
uv makes a clean project folder with its own Python and packages, so nothing clashes with anything else on your PC. Two minutes later you have a live API with its own documentation page.
Here's what you're building. linkstash saves web links with a title, tags and a note. Other programs (a script, a web page, an automation, your phone) talk to it over HTTP:
POST /linkssaves a linkGET /linkslists them, with?tag=,?q=(search) and pagingGET /links/3,PATCH /links/3andDELETE /links/3read, edit and delete oneGET /healthtells a monitor it's alive. Everything under/linksneeds your API key.
TipShort on time? Steps 1 to 4 give you a working, key-protected API with its own /docs page in about an hour. Steps 5 to 7 (a web page, tests, going online) can wait for another evening; the starter kit has every file for them.Every file is in the starter kit: linkstash.zip (105KB). You can unzip it and follow along, or type each file as you go. Typing is slower but you'll learn more. Either way, start by making the project:
Terminaluv init --bare --python 3.12 linkstash cd linkstash uv add "fastapi[standard]" pydantic-settings--baremakes just apyproject.toml(the project's settings file) and nothing else.fastapi[standard]is FastAPI plus the extras its install guide ↗ recommends: thefastapicommand, the Uvicorn web server and the httpx client.pydantic-settingsis already among those extras, but you'll import it yourself, so it's listed by name. uv puts everything in a.venvfolder and records exact versions inuv.lock.Open
pyproject.tomlin your editor and add the last two lines, so thefastapicommand always knows where your app lives. The FastAPI CLI docs ↗ recommend this over typing a file name each time:pyproject.toml[project] name = "linkstash" version = "0.1.0" requires-python = ">=3.12" dependencies = [ "fastapi[standard]>=0.143.0", "pydantic-settings>=2.15.0", ] [tool.fastapi] entrypoint = "main:app"Now the smallest possible FastAPI app, straight from FastAPI's first steps ↗. Save it as
main.pyin thelinkstashfolder:main.py (for now)from fastapi import FastAPI app = FastAPI() @app.get("/") async def root(): return {"message": "Hello World"}Start the development server:
Terminaluv run fastapi devOutput⚡️ Starting FastAPI in development mode 🐍 Using import string: main:app 🌐 Server started at http://127.0.0.1:8000 Documentation at http://127.0.0.1:8000/docs Logs: INFO: Will watch for changes in these directories: ['C:\\Users\\you\\linkstash'] INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) INFO: Started reloader process [37696] using WatchFiles INFO: Started server process [26332] INFO: Waiting for application startup. INFO: Application startup complete.Open 127.0.0.1:8000 ↗ in your browser, then 127.0.0.1:8000/docs ↗. That second page is the interactive documentation FastAPI builds from your code. It updates itself every time you add an endpoint.
Two things about
fastapi dev: it restarts by itself when you save a .py file, and it only listens on127.0.0.1, so nothing else on your network can reach it. Press Ctrl + C in the terminal to stop it.
{"message":"Hello World"} and the /docs page lists GET /.If it breaks'uv' is not recognised + 3 more
'uv' is not recognised
winget install --id=astral-sh.uv -e on Windows, brew install uv on a Mac), then close the terminal and open a new one.'Could not find a default file to run, please provide an explicit path'
main.py. Run cd linkstash and check with dir (Windows) or ls (Mac and Linux).'error while attempting to bind on address' (port 8000 is in use)
uv run fastapi dev --port 8001.The page says 'This site can't be reached'
Application startup complete, and that the address is exactly http://127.0.0.1:8000.