How I Built an RFID Access Thing Using NodeMCU and FastAPI

Adithya nAdithya n
5 min read

So a while back I got curious about how those RFID office entry systems work.
Like, you scan a card and it logs you in or opens a door or something.

I had a NodeMCU (ESP8266) lying around, an RC522 RFID module, and some free time, so I just started messing around.


The Goal Was Simple

  • Scan a card

  • Get its UID

  • Send it to a backend

  • Store it somewhere


That turned into this project:
RFID reader + NodeMCU → sends UID to a FastAPI backend → logs it in a database
Only I (with my admin card) can register new users let’s see that part in Part 2 of this blog 😉

I built it for fun. For learning.
And honestly, for me from 14 months ago, who had no clue how hardware and backend could talk to each other.


What I Used

ThingWhy
NodeMCU (ESP8266)Small Wi-Fi board, perfect for simple IoT stuff
RC522 RFID moduleReads the UID of cards and tags
FastAPILightweight and fast Python backend
PostgresqlTo store the access logs
Arduino IDEFor flashing code to NodeMCU
PyCharmFor backend code, because why not

How It Works (In Plain Words)

  • I scan a card on the RC522

  • NodeMCU reads the UID

  • It sends the UID as JSON to my FastAPI backend (over Wi-Fi)

  • The backend checks if the UID exists in the database

  • If yes → it logs the time and whether it’s a login/logout

  • If not → shows “UID not found” in serial


System Flow Diagram

Here’s a simple overview of how everything connects:

From scanning an RFID card to logging it in a database this is how the system works end-to-end.


Wiring the RC522 to NodeMCU

RC522 PinNodeMCU
SDAD8
SCKD5
MOSID7
MISOD6
RSTD0
GNDGND
3.3V3.3V

Warning: Don’t connect RC522 to 5V it’ll die. I nearly did that lol.


NodeMCU Code: Scanning RFID and Sending to Backend

Once the NodeMCU connects to Wi-Fi, it waits for an RFID card to be scanned.
When a card is detected, it reads the UID, converts it to a string, and sends it to my FastAPI backend using a simple HTTP POST request.

Here’s the main part of the code:

if (mfrc522.PICC_IsNewCardPresent() && mfrc522.PICC_ReadCardSerial()) {
  String uidString = "";
  for (byte i = 0; i < mfrc522.uid.size; i++) {
    uidString += String(mfrc522.uid.uidByte[i] < 0x10 ? "0" : "");
    uidString += String(mfrc522.uid.uidByte[i], HEX);
  }
  uidString.toUpperCase();

  sendUidToServer(uidString);
}

And this is how the UID gets sent to the backend:

WiFiClient client;
HTTPClient http;
http.begin(client, serverUrl);
http.addHeader("Content-Type", "application/json");

String jsonData = "{\"rfid_uid\":\"" + uid + "\"}";
int httpResponseCode = http.POST(jsonData);

If the backend responds, I print it on the Serial Monitor just to confirm everything’s working.

See the NodeMCU code here

FastAPI Backend: Receiving and Logging UID

My FastAPI app has two endpoints:

  • POST /create_user → To manually register a card with a name & number

  • POST /access → The NodeMCU hits this to log each scan

Here’s the /access endpoint:

@app.post("/access")
def accesslogs(deets: AccessGive, db: Session = Depends(get_db)):
    return access.verify_user(db, deets)

The verify_user() function checks if the UID exists in the database. If it does, it logs the user as either logging in or out depending on their last access.

Here’s a simplified version of the logic:

if not latest_log or latest_log.is_active == False:
    is_active = True   # Logging IN
else:
    is_active = False  # Logging OUT

It then stores this in the database along with a timestamp, so I know who accessed, when, and whether they were coming in or going out.

See the full Backend code here

I'm using SQLAlchemy + PostgreSQL.
When a UID is scanned, the backend:

  • Checks if UID exists in the users table

  • If it does → logs the time + whether they’re logging in or out

  • If not → responds with “UID not registered”


Flow Summary

  • I register users manually using Swagger UI or Postman

  • NodeMCU just scans cards and hits the API

  • Backend does the rest no SD cards, no spreadsheets just logs in a DB


What I Learned

  • How to read RFID UID using MFRC522

  • How to connect NodeMCU to Wi-Fi and send HTTP requests

  • How to create simple APIs with FastAPI

  • How to store and query stuff using SQLAlchemy

Also learned how to mess up C++ syntax in Arduino 10 times before it finally compiled 😅


What’s Next?

  • Add a proper “admin mode” where scanning a master card lets me register new users from the scanner itself

  • Maybe add a buzzer and LED for feedback

  • Will write Part 2 for that once it works


Final Thoughts

This was just a weekend thing that turned into a fun learning project.
If you’ve ever wanted to connect a microcontroller with a Python backend, this is a great way to try it out.

It’s not fancy, but it works and I built it myself.


1
Subscribe to my newsletter

Read articles from Adithya n directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Adithya n
Adithya n