HOME

WarrenGHolley.com API Documentation.

A dead-simple REST API, as proof-of-concept.
Hosted by GUnicrorn via proxy from NGinx, run by Python/FLASK, in a 'uv' environment.

Endpoints:
/api/api - Returns an object describing the current time, and the current stack of books on my bedside table.
/api/say_hi - Flashes an LED on the Raspberry Pi's GPIO at me. Configurable duration & frequency.

Example Usage: (Bash)
curl https://warrengholley.com/api/api
curl https://warrengholley.com/api/say_hi -d '{"duration": "1m","period":"3s"}' -H 'Content-Type: application/json'
curl https://warrengholley.com/api/say_hi -d '{"duration": "1m","period":"3s","message":"Hi!"}' -H 'Content-Type: application/json'

Example Usage: (html)
https://warrengholley.com/api/api
https://warrengholley.com/api/say_hi?duration=1m&period=2s
https://warrengholley.com/api/say_hi?duration=1m&period=2s&message=Hi from an API user!


/say_hi Arguments:
"duration":"\d\c" - Eg: "duration":"22s" - Flashes the light for 22 seconds.
"period":"\d\c" - Eg: "period":"4s" - Switches the light state every 2 seconds (4*1000ms/2)
"message":String - Eg: "message":"Hello!" - Just leaves a message in the logfile. Input should be well sanitized to prevent injection, but please feel free to brick the system if I've missed a critical cleaning error. (It'd teach me a lesson -and- be funny.)

\d - Integer: Duration. The number of seconds/minutes/hours to flash the light for.
\c - Character: Unit. s=Seconds, m=Minutes, h=Hours.

/say_hi Constraints:
Duration has a max of 5 minutes to prevent someone entering 2e12 years.
Period has a minimum input of 1s.

/api Returned Arguments
Current_Book: String - Includes the Title and Author.
Current_Time_UTC: String - ISO-8601 timestamp of the current UTC time.

The book is randomly selected from a 2-table, 4-row SQLite database, as all APIs need a database. Apparently.


Changelog
2025-02-20 - Oh god. I found a buzzer in my electronics box. 'say_hi' will now beep -and- flash at me until I decide that it was a -horrible- idea.
2025-02-28 - Finally got around to deploying this joke.
2025-03-01 - Added an optional 'message' arg to the say_hi endpoint, as I didn't get around to doing the de-Proxying today.
2025-04-01 - Removed. The. Buzzer.
2025-04-09 - This nonsense is now up on Github, as well as the Blinkenlight code.

Coming features:
Might add a 'Frequency' arg or 'ms' unit to see if I can get some Persistence-of-vision dimming on the LED.
Or an 'on-time'/'off-time' PWM dimming system? I have no clue how the GPIO will handle high-freqency switching from a python-interface.
Definitely need rate limiting somewhere.
Need to yell at Nginx to unmask user-IPs, as they're somewhat obfuscated from CloudFlare.
Probably need API-keys, just because they seem to be in-vogue at the moment.
Spin off the message optional argument into a different endpoint.

Deprecated:
/api/ban_me - Gives your IP address a 2 minute ban. An experiment with Fail2Ban that I decided to add while I was in the code.
- Cloudflare proxying makes remote IP's require an extra few steps to be visible for logging. Far too much work for this joke.
- Still should, for security, banning, & yelling-at-Andrew-because-he-sent-me-500-'say-hi' requests