Building a Telegram bot that tracks new Tesla vehicles on inventory

Published in code, product, creative on September 02nd, 2023.

This project started from a personal challenge, in a period when Tesla was offering relevant discounts for certain models in their inventory.

...to see if I can build an app that tracks Tesla's inventory movements.

There are generally two ways through which you can purchase a Tesla:

  1. place an order directly on their website: choose your model, customise the vehicle, then wait the for delivery

  2. track the inventory online and acquire a vehicle as soon as one becomes available: stick with the available specs and take delivery soon after

The latter usually comes with pretty sweet discounts as well, on top of the shorter delivery times.


Offering discounts for vehicles available on stock seems to have become a recurring practice at the end of a quarter, as it helps Tesla boost their financials & keep shareholders happy. In such periods, the fight for vehicles is as intense as it can get. 

People are ordering discounted vehicles in a matter of minutes after becoming available on stock.

So I thought... that must be a lot of clicks & time spent on page refreshes that one would have invest to chase the cars online. What if there would be a way to get automatically notified whenever a new vehicle becomes available? And with that notification, to receive also the main specs associated and the link you can use for the purchase, should you decide for it?

Introducing: Tesla Inventory Alerts

I thought I could leverage my skills & navigate a couple of uncertainties to make this service happen. The plan was to create an app that would:

  • send notifications for every discounted vehicle added on stock

  • provide daily reports with top discounts

  • include all vehicle models to date: S, 3, XY

  • support localised messages for different countries

  • provide direct links to the order page on Tesla's website

Having browsed Tesla's website prior, I've discovered that they actually have a public API that, when queried on certain parameters, can return the full list of vehicles available at a given moment of time for specific markets.

That was the starting point for getting the data I'd needed. Less than 2 weeks later, the prototype was ready.

The technical concept

Architecture & dependencies

I've decided to build a headless application in Laravel as my main layer for the logic. Getting data from Tesla's API, maintaining it, wrapping it as notifications and pushing it to Telegram was supposed to take place from one single point.

There was no use for a custom domain, as visitors were not to be expected on the server itself, but what I had to account for was the possibility of running scheduled tasks and keeping queue workers alive with a process control system like Supervisor and a Redis server as the queue driver. For a more advanced configuration, but in the same time simplicity, I've also opted to use Laravel's Horizon go-to package.

To deliver notifications I had to learn more about Telegram's Bot API and their documentation was the starting point.

Last but not least, I had everything set up as a Github repository to trace my work, setup a future CI/CD pipeline and document everything, in case I'd ever open the project publicly.

Pulling in data

Once the system was in place, the first task was to setup the requests to Tesla's API for getting the inventory data. I wanted to build this as a scalable system, being reusable for any country in the world and without technical limitations. To achieve this, I've defined the logic to use environment variables that I could easily swap and the application would by default adapt the calls to get the vehicles data. 

Think of it like this: I was able to configure any given amount of countries, languages, coordinates & models (yup, I know for this one Tesla only has 4 available to date, but the idea remains) and the application would iterate through all of them, getting the entire data set in a structured way. My plan was to launch the bot with Romania, as one country in the beginning, and to add more into the list soon after.

The database table that was supposed to store the vehicles is not rocket science, but I've defined it in a way that it can collect & properly store the information while easily allowing me to differentiate between multiple countries & languages. It was very important to deliver localised notifications. 

For certain attributes, I've ended up using either getters or setters so that I can dynamically adapt a raw format to changing needs in the logic. Then, on top of the data that I was pulling, I also had to compute parts of it myself to be able to deliver further functions to subscribers: the discount value or rate for a vehicle is such an example, as this is not provided by Tesla's API.

At this stage it was set, I was able to fetch inventory data based on scheduled tasks and dispatch jobs to import or process the information in my database.

Tracking inventory movements

With data being fetched, it was supposed to be an easy path towards the next point, sending notifications to Telegram. Before that, I wanted though to build an extra feature that was supposed to deliver a daily report with the vehicles having the highest discounts.

It would turn out a poor experience if the report sent out today would contain vehicles that were actually sold the hours prior, right?

So this was the juicy stuff: how can I know which vehicles have been acquired and are not available anymore?

An inverted query was the solution I came up with. I've used soft deletes to flag the vehicles stored in they application that were not present anymore in the response from the inventory request. To optimise the process, I've went for flipping the collection of vehicles into an associative array with the VIN number as key and filtering out the vehicles from the API request. That provided me the list of vehicles which should be deleted.

In the end, for every request to Tesla's API, I was either:

  • including new records in my database

  • keeping or updating existing ones, if changed

  • removing the records in the database that were not available anymore

Pushing notifications to Telegram

Being the first time working with the Telegram API, I've began this phase with several Google searches and by checking out the available documentation... so doing research, so to say. 

My steps were laid out as follows:

  • create a Telegram bot: this can be achieved through the BotFather, a bot which gives life to other bots

  • establish a channel: goes without saying, this should be done directly via Telegram

  • invite the bot into the channel and assign it the proper permissions so it can post

  • send a POST request to the Telegram API, with the bot and the channel IDs as part of the main parameters

A trial & error attempts later, after sending test requests from Insomnia to Telegram, everything was working.

Remember the scalability concept I talked about earlier? For every country that I had configured in the application, I was able to dynamically configure the bot & channel IDs further.

Deployment & CI

Last but not least, after my local tests where fully functioning, I've configured the repository onto a server and implemented a deployment pipeline via Github Actions. Every time I'd release a new version of the codebase, the pipeline would trigger and deploy the app.

Even with a low-moderate complexity of the application and being a sole developer, I had still decided to configure static analysis with Larastan and code style checking job with Laravel Pint via Github Actions, to catch potential issues or development misalignments.

Going for the release

That's where I had to use my Photoshop skills and create some attractive banner images that I could use for promotion. After leaving the app work for a few days post-deployment, to make sure no unforeseen issues appear, I've made the concept public.

Starting from one country, I've searched all the Tesla groups that I could find for Romania in either Facebook, Whatsapp or Telegram and I've published one message about the bot there. To some surprise, it was quite a welcomed concept, as the Romanian Telegram channel got more than 250 subscribers in the first few days after launch.

So that's the story of this project. 

Where can you access it

If you're interested in discovering the Bot in action, you can check out the links below. Each one takes you to an individual country channel in Telegram, where the bot publishes regular messages with the vehicles for that region.

More countries may come up soon.