How I Built an RFID Access Thing Using NodeMCU and FastAPI

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
Thing | Why |
NodeMCU (ESP8266) | Small Wi-Fi board, perfect for simple IoT stuff |
RC522 RFID module | Reads the UID of cards and tags |
FastAPI | Lightweight and fast Python backend |
Postgresql | To store the access logs |
Arduino IDE | For flashing code to NodeMCU |
PyCharm | For 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 Pin | NodeMCU |
SDA | D8 |
SCK | D5 |
MOSI | D7 |
MISO | D6 |
RST | D0 |
GND | GND |
3.3V | 3.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.
FastAPI Backend: Receiving and Logging UID
My FastAPI app has two endpoints:
POST /create_user
→ To manually register a card with a name & numberPOST /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.
I'm using SQLAlchemy + PostgreSQL.
When a UID is scanned, the backend:
Checks if UID exists in the
users
tableIf 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.
Subscribe to my newsletter
Read articles from Adithya n directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
