Miscall Auto Reply workflow [Improvements] Feedback is welcomed

I made a demo version of the miscall auto-reply workflow two days back and figured out a few things after my first demo.

A 2-minute pause + re-check before texting - If someone calls, hangs up, and calls right back and actually gets through, they still get a “sorry we missed you” text a few seconds later.

Fixed it by adding a 2-minute pause before texting, then rechecking the call status with Twilio right before sending. If it shows they connected some other way in that window, it skips the text entirely instead of sending it blind.

Second thing: a landline number test. Had to add a second webhook that listens for Twilio’s delivery status callback separately, and only update the log once that comes back, so now a failed delivery gets flagged with the actual error code instead of quietly sitting there marked sent.

Where it’s at now:

  • Webhook trigger
  • Normalise caller fields across providers
  • Guard check for empty/malformed payloads
  • Wait 2 minutes → re-check the call → skip the text if they connected anyway
  • Weekend check → distinct message
  • Business hours check → during vs after hours message
  • Log to Sheets (phone, call ID, message SID, delivery status — starts as “pending”)
  • Delivery status webhook → updates that same row once Twilio confirms what happened

Some features like webhook auth are next on the list, and I don’t have great answers for more features, so if anyone has any feedback, do let me know.

JSON is attached below.

Missed Call Auto-Reply Iteration 2.json (16.7 KB)

Hi Kashish, this is a solid approach, especially the 2-minute delay with the second call-status check. That small change prevents a lot of false “missed call” messages and makes the workflow much more reliable.

I’ve built similar Twilio and voice automation workflows in n8n where we handle call events, status callbacks, retries, business hours, and CRM updates. One thing I’d also consider is adding idempotency using the Call SID (or a unique key) so duplicate webhooks can’t trigger duplicate messages, plus webhook signature validation for security.

Nice work. I’d be interested to see how you handle edge cases like voicemail, busy, and abandoned calls as you continue building it.

:telephone_receiver: Book a quick call:Calendly - Automaxion

Hey Kashish! I had a look at the JSON and I thought that after the wait you’re checking the original CallSid, but if someone hangs up and calls back, the second call gets a new ID while the first one is still sitting there as no-answer.
So I think you could still end up sending the missed call text even if they called back and actually got through. May be worth checking for calls from the same number during those two minutes but maybe you’ve already tested that part ^^ Either way nice automation!

Lupel’s catch is the one I would fix first, and it is worth being precise about why. After the wait you re-check the original CallSid, but a caller who rings back creates a second call with its own SID. The first call stays no-answer forever, so the guard can never see the successful one and the text goes out anyway. Querying the Calls list filtered by From and a start time inside your window, then skipping when any of them completed with a duration above zero, is what actually closes it.

Two things about the delivery-status half that will bite later. Twilio retries status callbacks and they can arrive out of order, so sent can land after delivered for the same message. If the row simply takes whatever arrived last, a delivered message can end up displayed as queued. Rank the statuses and only ever move forward, keyed on the MessageSid.

The other is the Sheets write itself. Looking up the row and then updating it is a read followed by a write, and two callbacks arriving together can both read the same row index before either writes. On a quiet line you will never see it. On a busy morning you get a row overwritten with the wrong message status. Appending an event row per callback and computing current status when you read is the version that does not race.

On webhook auth, since it is next on your list: Twilio signs requests with X-Twilio-Signature over the full URL plus the sorted POST body, so validate that rather than a shared secret in a query string. The signature check breaks if anything rewrites the URL in front of n8n, which is worth knowing before you spend an evening on it.