<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: capcom6</title>
    <description>The latest articles on DEV Community by capcom6 (@capcom6).</description>
    <link>https://dev.to/capcom6</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F762977%2Ff0530be6-7977-42a9-9f17-1c15c032f944.png</url>
      <title>DEV Community: capcom6</title>
      <link>https://dev.to/capcom6</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/capcom6"/>
    <language>en</language>
    <item>
      <title>tnfy.link - What's about ID?</title>
      <dc:creator>capcom6</dc:creator>
      <pubDate>Tue, 14 Jan 2025 00:00:17 +0000</pubDate>
      <link>https://dev.to/capcom6/tnfylink-whats-about-id-dlj</link>
      <guid>https://dev.to/capcom6/tnfylink-whats-about-id-dlj</guid>
      <description>&lt;p&gt;Hello everyone!&lt;/p&gt;

&lt;p&gt;Welcome to the second part of my series about &lt;a href="https://tnfy.link" rel="noopener noreferrer"&gt;tnfy.link&lt;/a&gt; — yet another URL shortener! In this post, we’ll dive into the fascinating process of generating short links. While this might sound straightforward, choosing the right method for link generation comes with unique challenges.&lt;/p&gt;

&lt;p&gt;At its core, generating a short link involves creating a short, unique ID for each long URL. The ID should meet several criteria:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Be &lt;strong&gt;unique&lt;/strong&gt; to avoid conflicts.&lt;/li&gt;
&lt;li&gt;Be &lt;strong&gt;short enough&lt;/strong&gt; for practical use.&lt;/li&gt;
&lt;li&gt;Be &lt;strong&gt;easy to type&lt;/strong&gt; without introducing errors.&lt;/li&gt;
&lt;li&gt;Be &lt;strong&gt;unpredictable&lt;/strong&gt; to prevent guessing.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;After researching various approaches, I identified four main methods for generating short links. Let’s explore them in detail.&lt;/p&gt;




&lt;h3&gt;
  
  
  1. Random Bytes
&lt;/h3&gt;

&lt;p&gt;The simplest method involves generating random bytes and encoding them. However, it’s important to understand the difference between pseudo-random and cryptographically secure random numbers.&lt;/p&gt;

&lt;h4&gt;
  
  
  Pseudo-Random Numbers
&lt;/h4&gt;

&lt;p&gt;The &lt;a href="https://pkg.go.dev/math/rand" rel="noopener noreferrer"&gt;&lt;code&gt;math/rand&lt;/code&gt;&lt;/a&gt; package in Go provides a pseudo-random number generator (PRNG). With the same seed (an initial value), it produces the same sequence of numbers. While this is sufficient for many applications, it’s not suitable for secure or unpredictable link generation.&lt;/p&gt;

&lt;h4&gt;
  
  
  Cryptographically Secure Random Numbers
&lt;/h4&gt;

&lt;p&gt;For more secure random numbers, the &lt;a href="https://pkg.go.dev/crypto/rand" rel="noopener noreferrer"&gt;&lt;code&gt;crypto/rand&lt;/code&gt;&lt;/a&gt; package is ideal. It generates truly random and unpredictable values by leveraging system noise. For example, electromagnetic noise captured at the physical level can be used. This ensures high entropy, but keep in mind that virtual machines may rely on their host for random data, which could slow down generation in high-load environments.&lt;/p&gt;

&lt;h4&gt;
  
  
  Encoding Random Bytes
&lt;/h4&gt;

&lt;p&gt;Random bytes alone aren’t suitable for URLs, so they must be encoded. Here are the most common encoding methods:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Integer&lt;/strong&gt;: Converts bytes to an integer. Easy to type but may result in longer IDs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;HEX&lt;/strong&gt;: Encodes bytes in hexadecimal (0-9, A-F). Case-insensitive and typo-resistant.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Base64&lt;/strong&gt;: Encodes bytes with characters A-Z, a-z, 0-9, &lt;code&gt;+&lt;/code&gt;, &lt;code&gt;/&lt;/code&gt;, and &lt;code&gt;=&lt;/code&gt;. However, it’s case-sensitive and prone to typos.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Base58&lt;/strong&gt;: Similar to Base64 but excludes confusing characters (e.g., &lt;code&gt;I&lt;/code&gt;, &lt;code&gt;l&lt;/code&gt;, &lt;code&gt;O&lt;/code&gt;, &lt;code&gt;0&lt;/code&gt;). This makes it more user-friendly. Examples include the implementations by Bitcoin, Ripple, and Flickr.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;For user-friendly short links, &lt;strong&gt;Base58&lt;/strong&gt; is often the best choice due to its balance of compactness and error resistance.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key Takeaways:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Random bytes are unique and unpredictable.&lt;/li&gt;
&lt;li&gt;Encoding methods like Base58 enhance usability.&lt;/li&gt;
&lt;li&gt;Cryptographically secure randomness ensures reliability.&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  2. Hashing
&lt;/h3&gt;

&lt;p&gt;Hashing involves generating a fixed-length value based on the input (e.g., the long URL). While it guarantees consistency—hashing the same input always produces the same output—it lacks randomness. This means multiple requests to shorten the same URL will yield identical IDs, which doesn’t meet the unpredictability requirement.&lt;/p&gt;

&lt;p&gt;Adding a random salt to the input before hashing can introduce variability, but at that point, using raw random bytes becomes simpler and more efficient.&lt;/p&gt;




&lt;h3&gt;
  
  
  3. UUID
&lt;/h3&gt;

&lt;p&gt;UUIDs (Universally Unique Identifiers) are widely used for generating unique values. While they are effective, their default format is too long for short links. However, re-encoding UUIDs (e.g., in Base58) can reduce their size.&lt;/p&gt;

&lt;p&gt;An alternative to UUID is &lt;a href="https://github.com/ai/nanoid" rel="noopener noreferrer"&gt;NanoID&lt;/a&gt;, which generates shorter strings (21 characters by default) by using a customizable alphabet. This allows you to optimize IDs for readability and error resistance.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why Not Use UUID?&lt;/strong&gt;&lt;br&gt;
UUIDs are ultimately based on random bytes, so there’s no significant advantage over generating raw random values directly.&lt;/p&gt;




&lt;h3&gt;
  
  
  4. Sequence
&lt;/h3&gt;

&lt;p&gt;Random values can occasionally result in duplicates, especially under high load or with shorter IDs. While tnfy.link isn’t designed for high-load scenarios, it’s still worth considering potential issues.&lt;/p&gt;

&lt;p&gt;Using a &lt;strong&gt;sequential counter&lt;/strong&gt; ensures uniqueness by design. Tools like Redis can implement a distributed counter with the &lt;code&gt;INCR&lt;/code&gt; command. However, sequential IDs are predictable. Combining a sequence with random bytes addresses this issue, ensuring both uniqueness and unpredictability.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Random Value + Incrementing Sequence&lt;/strong&gt;: If two instances generate the same random value, the sequence ensures uniqueness.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: Including a sequential component in your IDs might reveal the total number of links generated, which could be undesirable in some contexts.&lt;/p&gt;




&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;In this post, we explored various methods to generate short links:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Random bytes&lt;/strong&gt;: Simple and effective, especially with secure encoding like Base58.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hashing&lt;/strong&gt;: Reliable but lacks randomness for this use case.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;UUID/NanoID&lt;/strong&gt;: Great alternatives but add unnecessary complexity compared to raw random bytes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sequence&lt;/strong&gt;: Solves collisions but increases ID length.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For most use cases, &lt;strong&gt;random bytes with Base58 encoding&lt;/strong&gt; are sufficient. To handle collisions in high-load scenarios, combining random bytes with a sequential component is a robust option. While this isn’t yet implemented in the current version of &lt;a href="https://github.com/tnfy-link/backend" rel="noopener noreferrer"&gt;tnfy.link’s backend&lt;/a&gt;, I plan to add it as an optional feature in the future.&lt;/p&gt;

&lt;p&gt;Thanks for reading! I’d love to hear your thoughts and experiences with link generation. Share your feedback in the comments below!&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Related Post&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
If you’re interested in learning more about my projects, check out my article on &lt;a href="https://dev.to/capcom6/sms-gateway-for-android-a-simple-and-private-sms-gateway-for-your-projects-1c0m"&gt;SMS Gateway for Android&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>go</category>
      <category>programming</category>
      <category>backend</category>
    </item>
    <item>
      <title>tnfy.link - One more shortener?</title>
      <dc:creator>capcom6</dc:creator>
      <pubDate>Tue, 24 Dec 2024 03:00:00 +0000</pubDate>
      <link>https://dev.to/capcom6/tnfylink-one-more-shortener-3ck7</link>
      <guid>https://dev.to/capcom6/tnfylink-one-more-shortener-3ck7</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Because English is not my native language I've used some AI-tools to improve the text, you can find original version &lt;a href="https://dev.to/capcom6/tnfylink-one-more-shortener-original-3f53?preview=ee99d3b14fa15773d9bb4ba5d9b3ccabb6c82231f4834b82ac855396cf518b95443063fc0f624dcde1a09b5085d88807290b958b6bb1cb8f3f58a544"&gt;here&lt;/a&gt;. I appreciate your feedback which version you like more.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Hello, everyone!  &lt;/p&gt;

&lt;h3&gt;
  
  
  The Beginning
&lt;/h3&gt;

&lt;p&gt;This story begins with a simple task: I needed to create posts containing a link to a service I didn’t control and track the number of clicks on that link.  &lt;/p&gt;

&lt;p&gt;The first thing I did was turn to Google and search for URL shortener services. I found plenty of options. However, some were overly complicated, others included ads or required registration, and some were frustratingly slow. None of them fit my requirements.  &lt;/p&gt;

&lt;p&gt;I also came across several Open Source projects on GitHub. But then I thought: I’m a developer too. Why not create my own URL shortener—simple, functional, and tailored to my needs?  &lt;/p&gt;




&lt;h3&gt;
  
  
  What Should I Use?
&lt;/h3&gt;

&lt;p&gt;Having prior experience with &lt;a href="https://go.dev/" rel="noopener noreferrer"&gt;Go&lt;/a&gt; and &lt;a href="https://gofiber.io" rel="noopener noreferrer"&gt;Fiber&lt;/a&gt;, choosing my web stack was easy. Initially, I experimented with &lt;a href="https://huma.rocks" rel="noopener noreferrer"&gt;&lt;strong&gt;Huma&lt;/strong&gt;&lt;/a&gt;, but I encountered some limitations, such as restricted support for sub-routers. Since my project only required a few REST endpoints (where Huma excels), I decided to stick with raw Fiber.  &lt;/p&gt;

&lt;p&gt;Next came the question of storage—for mapping short and long links and storing statistics. Since I wasn’t planning a high-traffic service, I could use any solution: RDBMS, NoSQL, or key-value storage.  &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I prefer self-hosted solutions, so SaaS like Firebase was off the table. If this series interests you, I’ll write a post about the deployment process.  &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I value simplicity. Storing a short-long link pair sounded like a “key-value” use case, so I chose &lt;strong&gt;Redis&lt;/strong&gt;.  &lt;/p&gt;

&lt;p&gt;Some may think I picked Redis for its speed. You’re partly right, but not entirely. Yes, Redis is fast because it stores everything in RAM, and redirects in my service took less than 1 ms. However, users’ requests must still travel to and from the server, which often adds 50–100 ms or more to the response time. In most cases, Redis’ performance advantage is negligible to end-users.  &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note: While response times impact user experience, they also affect the service itself. Faster response times reduce resource consumption, enabling higher requests per second (RPS).  &lt;/p&gt;
&lt;/blockquote&gt;




&lt;h3&gt;
  
  
  The Storage
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;I’ll describe the steps I took during development. Some initial ideas weren’t optimal, and I’ll explain why.  &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Since I chose Redis, my options were limited to its data types. RAM is finite, so I decided to add a TTL (Time to Live) of 7 days for links, with flexibility to adjust later.  &lt;/p&gt;

&lt;p&gt;Initially, Redis’ &lt;strong&gt;String&lt;/strong&gt; type seemed ideal. Keys like &lt;code&gt;links:&amp;lt;id&amp;gt;&lt;/code&gt; could store target URLs as values. Commands like &lt;code&gt;SET&lt;/code&gt; with &lt;code&gt;NX&lt;/code&gt; (to prevent overwriting) and &lt;code&gt;EX&lt;/code&gt; (to set TTL) provided a straightforward solution.  &lt;/p&gt;

&lt;p&gt;However, what if I wanted to store additional metadata in the future, such as a creation date or user ID? I could create separate keys (&lt;code&gt;links:&amp;lt;id&amp;gt;:createdDate&lt;/code&gt;, &lt;code&gt;links:&amp;lt;id&amp;gt;:userId&lt;/code&gt;, etc.), but managing TTL across multiple keys would become cumbersome and error-prone.  &lt;/p&gt;

&lt;p&gt;Thankfully, Redis’ &lt;strong&gt;Hash&lt;/strong&gt; data type solved this issue. With hashes, I could store all link-related data under one key (&lt;code&gt;links:&amp;lt;id&amp;gt;:meta&lt;/code&gt;) and set fields with &lt;a href="https://redis.io/docs/latest/commands/hset/" rel="noopener noreferrer"&gt;&lt;code&gt;HSET&lt;/code&gt;&lt;/a&gt;. TTL could be applied to the entire key using &lt;a href="https://redis.io/docs/latest/commands/expire/" rel="noopener noreferrer"&gt;&lt;code&gt;EXPIRE&lt;/code&gt;&lt;/a&gt;, ensuring consistency.  &lt;/p&gt;

&lt;p&gt;But there was a catch: Redis hashes lack an &lt;code&gt;NX&lt;/code&gt; option to prevent collisions. Checking for key existence with &lt;code&gt;EXISTS&lt;/code&gt; before &lt;code&gt;HSET&lt;/code&gt; isn’t reliable in concurrent environments. A distributed lock could help, but it would reduce write throughput.  &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Even without high throughput requirements, I needed to plan for potential load increases.  &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Redis 7.4 introduced a better solution: the &lt;a href="https://redis.io/docs/latest/commands/hexpire/" rel="noopener noreferrer"&gt;&lt;code&gt;HEXPIRE&lt;/code&gt;&lt;/a&gt; command. It allows TTL to be set on individual hash fields, which was perfect for this use case.  &lt;/p&gt;

&lt;p&gt;Here’s my final approach:  &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Generate an ID and attempt to save the ID-URL pair in an index hash (&lt;code&gt;links:index&lt;/code&gt;) using &lt;code&gt;HSETNX links:index &amp;lt;id&amp;gt; &amp;lt;target&amp;gt;&lt;/code&gt;. If the result is &lt;code&gt;0&lt;/code&gt;, there’s a collision.
&lt;/li&gt;
&lt;li&gt;If successful, set metadata using &lt;code&gt;HSET links:&amp;lt;id&amp;gt;:meta key1 value1 key2 value2 ...&lt;/code&gt;.
&lt;/li&gt;
&lt;li&gt;Set TTL for the &lt;code&gt;&amp;lt;id&amp;gt;&lt;/code&gt; field in &lt;code&gt;links:index&lt;/code&gt; using &lt;code&gt;HEXPIRE links:index &amp;lt;id&amp;gt; &amp;lt;ttl&amp;gt;&lt;/code&gt;, and for the metadata with &lt;code&gt;EXPIRE links:&amp;lt;id&amp;gt;:meta &amp;lt;ttl&amp;gt;&lt;/code&gt;.
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Steps 2 and 3 can be &lt;a href="https://redis.io/docs/latest/develop/use/pipelining/" rel="noopener noreferrer"&gt;pipelined&lt;/a&gt; to minimize round-trips to Redis.  &lt;/p&gt;

&lt;h4&gt;
  
  
  Data Model
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;links
  | index - HASH
      | &amp;lt;id&amp;gt; -&amp;gt; target URL
  | &amp;lt;id&amp;gt;
      | meta - HASH
          | targetUrl -&amp;gt; target URL
          | createdAt -&amp;gt; created at date
          | validUntil -&amp;gt; valid until date
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;Today, we began engineering a new URL shortener and discussed one critical component: link storage.  &lt;/p&gt;

&lt;p&gt;If this project interests you, the next part will explore ID generation and possibly start writing code.  &lt;/p&gt;

&lt;p&gt;I’d love to hear your thoughts and feedback on this project! The service is currently in alpha, but feel free to try it out.  &lt;/p&gt;

&lt;p&gt;The source code is available on GitHub: &lt;a href="https://github.com/tnfy-link" rel="noopener noreferrer"&gt;tnfy-link&lt;/a&gt;. Documentation will be updated as the service approaches beta.  &lt;/p&gt;

&lt;p&gt;Thanks for reading!  &lt;/p&gt;

</description>
      <category>redis</category>
      <category>webdev</category>
      <category>tutorial</category>
      <category>programming</category>
    </item>
    <item>
      <title>SMS Gateway for Android™: A Simple and Private SMS Gateway for Your Projects</title>
      <dc:creator>capcom6</dc:creator>
      <pubDate>Fri, 20 Dec 2024 04:22:48 +0000</pubDate>
      <link>https://dev.to/capcom6/sms-gateway-for-android-a-simple-and-private-sms-gateway-for-your-projects-1c0m</link>
      <guid>https://dev.to/capcom6/sms-gateway-for-android-a-simple-and-private-sms-gateway-for-your-projects-1c0m</guid>
      <description>&lt;p&gt;In the world of digital communications, SMS remains a vital channel for authentication, notifications, and instant alerts. &lt;strong&gt;SMS Gateway&lt;/strong&gt; is a solution that allows you to quickly and easily integrate SMS functionality into your projects by using an Android smartphone as a gateway.&lt;/p&gt;

&lt;p&gt;It was created by a developer, for developers, with a focus on &lt;strong&gt;ease of use&lt;/strong&gt;, &lt;strong&gt;data privacy&lt;/strong&gt;, and the principles of open-source software. There’s no UI—just an API. What else could a developer need?&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;From Idea to Implementation&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;SMS Gateway started as a personal project but quickly found demand among other users. Today, its primary goals are &lt;strong&gt;simplicity&lt;/strong&gt; and &lt;strong&gt;privacy&lt;/strong&gt;. These goals are achieved while keeping costs minimal and ensuring the product remains completely free and open source.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Three Modes of Operation&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;The app operates in three modes, all sharing the same API:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;a href="https://docs.sms-gate.app/getting-started/local-server/" rel="noopener noreferrer"&gt;Local&lt;/a&gt;&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
REST API runs directly on the Android device, enabling operation without the need for an external server. This mode allows entirely offline operation within a local network, ensuring enhanced privacy without requiring internet access.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;a href="https://docs.sms-gate.app/getting-started/public-cloud-server/" rel="noopener noreferrer"&gt;Cloud&lt;/a&gt;&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
If direct access to the device is not possible, requests are routed through a shared server. This mode is free to use unless message volumes impact other users. For enhanced privacy, end-to-end encryption is available.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;a href="https://docs.sms-gate.app/getting-started/private-server/" rel="noopener noreferrer"&gt;Private&lt;/a&gt;&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
For maximum security, you can deploy your own server instance. In this mode, your messages never leave your infrastructure. While push notifications still rely on the Cloud server, no message content is ever shared.  &lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;And because the app is open source, you can even build &lt;a href="https://docs.sms-gate.app/getting-started/custom-gateway/" rel="noopener noreferrer"&gt;your own version of the service&lt;/a&gt; to suit your specific needs.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Webhooks for Incoming Messages&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;SMS Gateway can be used not only to send messages but also to receive incoming SMS messages directly to your backend. Webhooks make it easy to process incoming messages in real time without storing them on third-party servers.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;How It Works&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;When an SMS is received, the app sends a POST request to the configured webhook URL. The payload includes details like:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Sender’s phone number
&lt;/li&gt;
&lt;li&gt;Message content
&lt;/li&gt;
&lt;li&gt;Timestamp
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Developers can use this to process responses, trigger automated workflows, or store the data securely.&lt;/p&gt;

&lt;p&gt;Learn more in the &lt;a href="https://docs.sms-gate.app/features/webhooks/" rel="noopener noreferrer"&gt;webhook documentation&lt;/a&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Why Choose SMS Gateway?&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Here are several key advantages that make SMS Gateway stand out among competitors:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;No Registration&lt;/strong&gt;: You don’t need to provide an email or phone number to start using the application.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Privacy&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;Supports end-to-end encryption, private servers, and webhooks sent directly from the device for maximum privacy.
&lt;/li&gt;
&lt;li&gt;All message data on the Cloud server is hashed within 15 minutes after the app acknowledges receipt of the queued message.
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Simple Setup&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;Start with the Cloud server—all you need is an Android device running the app.
&lt;/li&gt;
&lt;li&gt;Deploy a Private server with a &lt;a href="https://github.com/android-sms-gateway/server/tree/master/deployments/docker-compose-proxy" rel="noopener noreferrer"&gt;single command using Docker&lt;/a&gt; if you need more privacy.
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Webhooks Support&lt;/strong&gt;: Real-time delivery of incoming SMS directly to your system with privacy-first features.
&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Multiple SIMs Support&lt;/strong&gt;: Use devices with multiple SIM cards to manage different numbers easily. You can specify SIM usage explicitly or enable the SIM rotation feature.
&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Developer Tools&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;A CLI utility for sending SMS directly from the command line.
&lt;/li&gt;
&lt;li&gt;Libraries for popular programming languages: Go, Python, JavaScript/TypeScript, PHP.
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;And all of this is completely free.&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Technical Stack&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;SMS Gateway is built using:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Go for the backend
&lt;/li&gt;
&lt;li&gt;Kotlin for the Android app
&lt;/li&gt;
&lt;li&gt;MariaDB for data storage
&lt;/li&gt;
&lt;li&gt;Docker Swarm for orchestration
&lt;/li&gt;
&lt;li&gt;Terraform for infrastructure automation
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Usage Examples&lt;/strong&gt;
&lt;/h2&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;REST API Example&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Send an SMS using the local REST API:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST &lt;span class="nt"&gt;-u&lt;/span&gt; &amp;lt;username&amp;gt;:&amp;lt;password&amp;gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{ "message": "Hello, doctors!", "phoneNumbers": ["+19162255887", "+19162255888"] }'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  https://api.sms-gate.app/3rdparty/v1/message
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Replace &lt;code&gt;&amp;lt;username&amp;gt;&lt;/code&gt; and &lt;code&gt;&amp;lt;password&amp;gt;&lt;/code&gt; with the credentials available on the Home tab of the Android app.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;CLI Utility Example&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Send SMS using the &lt;a href="https://docs.sms-gate.app/integration/cli/" rel="noopener noreferrer"&gt;CLI utility&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Send a message&lt;/span&gt;
smsgate send &lt;span class="nt"&gt;--phone&lt;/span&gt; &lt;span class="s1"&gt;'+19162255887'&lt;/span&gt; &lt;span class="s1"&gt;'Hello, Dr. Turk!'&lt;/span&gt;

&lt;span class="c"&gt;# Send a message to multiple numbers&lt;/span&gt;
smsgate send &lt;span class="nt"&gt;--phone&lt;/span&gt; &lt;span class="s1"&gt;'+19162255887'&lt;/span&gt; &lt;span class="nt"&gt;--phone&lt;/span&gt; &lt;span class="s1"&gt;'+19162255888'&lt;/span&gt; &lt;span class="s1"&gt;'Hello, doctors!'&lt;/span&gt;
&lt;span class="c"&gt;# or&lt;/span&gt;
smsgate send &lt;span class="nt"&gt;--phones&lt;/span&gt; &lt;span class="s1"&gt;'+19162255887,+19162255888'&lt;/span&gt; &lt;span class="s1"&gt;'Hello, doctors!'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  &lt;strong&gt;Who Is This For?&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;SMS Gateway is ideal for:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Small and medium businesses&lt;/strong&gt; needing quick and affordable SMS integration.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Developers&lt;/strong&gt; seeking a flexible, secure, and open-source solution.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Privacy enthusiasts&lt;/strong&gt; who want to avoid relying on third-party cloud services.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Limitations&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;The app is &lt;strong&gt;not for you&lt;/strong&gt; if your goal is to send large batches of messages, such as for advertisements or spam campaigns. Although it includes features to mitigate mobile operator restrictions, SMS Gateway is designed for legitimate, low-volume use cases. For bulk messaging, consider specialized services.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Conclusion&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;SMS Gateway&lt;/strong&gt; prioritizes user privacy and convenience. With no registration required, flexible configuration options, and completely free access, it’s a reliable solution for any SMS-related tasks.  &lt;/p&gt;

&lt;p&gt;With its seamless setup, focus on privacy, robust webhook support, and open-source principles, &lt;strong&gt;SMS Gateway&lt;/strong&gt; is the ultimate tool for integrating SMS functionality into your applications.  &lt;/p&gt;

&lt;p&gt;Ready to try it out? Start now: &lt;a href="https://sms-gate.app" rel="noopener noreferrer"&gt;SMS Gateway&lt;/a&gt; or contact me via comments.&lt;/p&gt;

</description>
      <category>android</category>
      <category>go</category>
      <category>sms</category>
      <category>api</category>
    </item>
  </channel>
</rss>
