Today, we’re learning about the latest technological discovery. The concept is straightforward: I want to have automated reminders that pop up on my iPhone. What seems to be an easy task, considering services like IFTTT (“If this then that”) and a lot of similar services have been around for ages, is a pain in the ass once you need customization and try to use apps and scripts to customize them.
Fortunately, I found ntfy.sh. It is exactly what I was looking for: Run a cron job on my server that triggers a script that delivers a notification to a specific device. But let’s start from the beginning, so you can enjoy my dumb journey until I found the Holy Grail.
Table of Contents
The Problem
My wife doesn’t drink enough water per day. Using her age, height, and weight, we calculated her daily water intake to be between 2 and 2.7 liters. That’s a fact. However, facts are only as good as the person paying attention to them. Without notifications, my wife “forgets” to drink the required amount.
Hey, I’m a programmer. I can do this. Super easy! 😎 Well, it wasn’t, at least at first.
The task is very clear: My wife needs to drink a certain amount of water per day. Program something that reminds her of this: Push notifications. I immediately started playing around with iOS’ Shortcuts, which can be a pretty powerful tool for all kinds of automations and actions. Before I started, I had to set up some guidelines:
- Drink in 30-minutes intervals
- Drink like this during her working hours
- Her working hours are 09:00 to 18:00.
The (wrong) Solution
Still sounds easy, right? I fumbled around with Shortcuts, downloaded extensions for the app, and an entirely different app that should take care of this, for free, without bloat, just a simple schedule to show push notifications on her iPhone.
As you can guess, it didn’t work. Either they were bloated to a full fitness app, or required a subscription from the App Store. All that, just for a regular reminder in the form of simple push notifications. That can not be so difficult!
Well, it is. And at the same time, it’s not. See, cron jobs on servers are exactly built for purposes like these; repeated execution of a script within a set timeframe. That’s good—but what about the script? How do I send the push notifications to my wife’s device to remind her to drink water every 30 minutes?
Aside from expensive or bloated software, there was one key element that none of them had: customized intervals throughout the day. I think very highly of iOS’ and macOS’ Shortcuts app, but after hours of tinkering around (a native solution is always the best), I simply couldn’t find an automation that sends out push notifications every 30 minutes from Monday to Friday.
Apple’s annoying Push Notifications API
As I already wrote, the schedule and intervals can be easily handled by a single cron job. But what script allows a random user to send notifications to another random user’s device? iOS phones have an integrated so-called Apple Push Notifications API (APNs) for exactly this. It’s remote notification infrastructure connecting your servers to iOS, iPadOS, macOS, watchOS, and tvOS devices. The pipeline is simple as hell:
Server sends uses APN to contact the device → Device reacts.
Simple in theory, nightmarish in practice. Because Apples’ API has some architectural design flaws. Here’s a list of what I mean:
- Certifications expire and stop the process altogether
- Requires two separate environments
- APNs demand HTTP/2 but enforce a narrow cipher suite
- Background push limitations
- 4 KB payload limit (!)
- No push history
This is certainly not the only reason why it’s difficult to manage in a non-public setting. Apple built a system that works beautifully until something goes wrong, at which point you’re left with HTTP status codes and existential questions about why you chose mobile development. And, of course, the notifications, the heart of all this, don’t arrive.
My first try was a Python script. I created a class with a lot of methods to check everything:
- Is today a weekend?
- Is it within the timeframe?
- Does the timezone play along?
I ended up with a pretty verbose Python script that only lacked one thing: sending push notifications. Awesome.
ntfy: An Open-Source Gem
That’s when I discovered a service that does exactly that, triggering notifications on specific devices as needed. It comes with a mobile app to receive the actual notifications and a web interface that lets you sort of register a “client list,” for lack of a better word. They call it “topics,” so I’ll stick to that name from hereon.
Workflow:
- My wife downloads the app
- I subscribe her app to listen to one specific topic for incoming notifications
- And then let cron do the job.
The service is called ntfy, and it’s so simple that once I found out about it, I rm -rf *‘d my entire previous Python project out of sheer frustration after spending hours trying to bend the knee. The new script, also written in Python but can also be programmed in PHP, Go, JavaScript, and other programming languages, is now a single .py file with an offensively few lines:
import requests
requests.post("https://ntfy.sh/mytopic",
data="Backup successful 😀".encode(encoding='utf-8'))PythonThere, that’s it. Import your requests module, trigger a web-hook on the server, and ntfy does the rest. And that’s not all: it’s entirely open-source, and you can host it yourself if you have a web server, which I, of course, did. But let’s talk about that later.
Let’s Build a Simple Script
So, let’s build my wife’s drinking reminder together. It’s so easy: the only thing you need is the minimalist app on your Android or iOS device and a unique name for the topic the device has subscribed to.
The easiest solution, as I said, is to install the app. It’s called “ntfy” and costs: nothing. No trial period or some other bullshit. You can download it for Android from the Google Play Store and for iOS from the Apple App Store.
Once the app is installed, it shows: nothing:


In order to receive notifications, you must subscribe to the “topic.” That’s easily done by tapping the + sign in the top-right corner and giving the topic a unique name. For testing purposes, we’ll use wife-water-reminder:


Now we’re subscribed to a topic. You can tap to see the history of all push notifications, which is currently empty. Regarding the pixelated part of the server URL: I mentioned that I am self-hosting this service, and I’d like to keep that domain private. Sorry!
Your “Topic” is your Pipeline
However, this won’t concern you if you use ntfy.sh’s online service. Open the app on its website—you don’t even have to sign up for this—and click “Subscribe to topic,” which, you might’ve witnessed before, is in German, because I am German, and German is the best language on the planet. End of the discussion!

Then, enter your topic. This must be the same as set on your mobile device.

Once you hit “Subscribe,” the interface displays a narrow input field at the bottom—your message. At this point, it makes sense to simply test our connection by sending a test message. If everything went well, you’ll now, after a few seconds’ delay, receive one of the push notifications that displays on your device like any other notification (ignore the pixelated part before the topic). If you click it, you’ll be taken to the history page, where we now have 1 notification stored.


Well, what can I say—that’s it! You have now successfully used the Apple Push Notification API to send a notification from a remote server directly to your phone. Let that and how easy it was sink in before you start reading part two of this How-To-Guide.










![Click to show full size for Fixing “Apple could not verify [some app] is free of malware that may harm your Mac or compromise your privacy.” Move to trash? I don’t think so Fixing “Apple could not verify [some app] is free of malware that may harm your Mac or compromise your privacy.” Move to trash? I don’t think so](https://blog.kolja-nolte.com/wp-content/uploads/macbook-pro-css.jpg)
