<?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: Waqas Ahmed Waseer</title>
    <description>The latest articles on DEV Community by Waqas Ahmed Waseer (@samii).</description>
    <link>https://dev.to/samii</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.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4158545%2F521d6181-362e-4d67-98ca-7e6872c3b7ff.png</url>
      <title>DEV Community: Waqas Ahmed Waseer</title>
      <link>https://dev.to/samii</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/samii"/>
    <language>en</language>
    <item>
      <title>Self-host your own WhatsApp API with WaSphere and Docker</title>
      <dc:creator>Waqas Ahmed Waseer</dc:creator>
      <pubDate>Sat, 03 Oct 2026 09:21:57 +0000</pubDate>
      <link>https://dev.to/samii/self-host-your-own-whatsapp-api-with-wasphere-and-docker-5flf</link>
      <guid>https://dev.to/samii/self-host-your-own-whatsapp-api-with-wasphere-and-docker-5flf</guid>
      <description>&lt;p&gt;Paying per message for the WhatsApp Business API gets expensive fast, and the approval process is slow. If you want a WhatsApp API you fully own — your server, your data, no per-message fees — self-hosting is the answer.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://wasphere.com" rel="noopener noreferrer"&gt;WaSphere&lt;/a&gt; is an open-source (MIT), self-hosted WhatsApp API and developer platform I built for exactly this. It gives you multi-session WhatsApp, a REST API, HMAC-signed webhooks, 14 message types, and a realtime team inbox — all deployed with one &lt;code&gt;docker compose up -d&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;In this tutorial I'll take you from zero to sending your first WhatsApp message through your own API in about 10 minutes.&lt;/p&gt;

&lt;h2&gt;
  
  
  What you get
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Multi-session&lt;/strong&gt; — run many WhatsApp numbers from one deployment, each with its own API key scope and webhook endpoint. QR-based pairing in seconds.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;REST API&lt;/strong&gt; — send across 14 message types: text, image, video, audio/voice notes, documents, stickers, GIFs, view-once media, buttons, lists, polls, reactions, locations, and contact cards.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;HMAC-signed webhooks&lt;/strong&gt; — every delivery is signed (&lt;code&gt;X-WaSphere-Signature: v1,sha256=&amp;lt;hmac&amp;gt;&lt;/code&gt; over &lt;code&gt;{timestamp}.{rawBody}&lt;/code&gt;), with per-webhook secrets, retries, and SSRF-guarded delivery.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Realtime team inbox&lt;/strong&gt; — a two-pane inbox in the dashboard with roles, a contact book CRM, tags/notes, and CSV import/export.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Security-first&lt;/strong&gt; — scoped API keys (12 permission scopes), Argon2id-hashed keys, AES-256-GCM encrypted secrets, and a full audit log.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Anti-ban controls&lt;/strong&gt; — per-session send delays, typing simulation, and rate limits.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The architecture is two cleanly separated services: a Next.js dashboard with a NestJS API, and a WA Server (NestJS + Baileys) that isolates the WhatsApp engine.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Docker Engine 24+ and Docker Compose v2&lt;/li&gt;
&lt;li&gt;A server or your local machine (for a public deployment, bring your own reverse proxy for TLS)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Step 1 — Deploy
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/wasphere/wasphere.git
&lt;span class="nb"&gt;cd &lt;/span&gt;wasphere
&lt;span class="nb"&gt;cp&lt;/span&gt; .env.example .env
&lt;span class="c"&gt;# Set the secrets in .env — generate each with: openssl rand -hex 32&lt;/span&gt;
docker compose up &lt;span class="nt"&gt;-d&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Open &lt;code&gt;http://localhost:3004&lt;/code&gt;, register the first (admin) account, then go to Settings → WA Server and set the URL to &lt;code&gt;http://wa-server:3001&lt;/code&gt; plus your &lt;code&gt;WA_TOKEN&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2 — Connect a number
&lt;/h2&gt;

&lt;p&gt;In the dashboard, create a session and scan the QR code with WhatsApp. The session goes active instantly — no approval process, no waiting.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3 — Send your first message
&lt;/h2&gt;

&lt;p&gt;Create a scoped API key in the dashboard, then:&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 https://wa.your-domain.com/api/messages/send &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Authorization: Bearer wsk_your_key"&lt;/span&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;'{
    "session": "my-business",
    "to": "15551234567",
    "text": "Hello from my own WhatsApp API!"
  }'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Response: &lt;code&gt;200 OK&lt;/code&gt; with a &lt;code&gt;messageId&lt;/code&gt;. That's it — you're sending WhatsApp messages from your own infrastructure.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4 — Receive webhooks
&lt;/h2&gt;

&lt;p&gt;Register a webhook:&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 https://api.your-domain.com/workspaces/&lt;span class="o"&gt;{&lt;/span&gt;workspaceId&lt;span class="o"&gt;}&lt;/span&gt;/webhooks &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Authorization: Bearer wsk_your_key"&lt;/span&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;'{ "name": "my-app", "url": "https://my-app.com/webhook/wa", "events": ["message.received"] }'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Verify the signature in your receiver (Node.js):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;crypto&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;crypto&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;verify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;secret&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;signature&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;x-wasphere-signature&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt; &lt;span class="c1"&gt;// v1,sha256=&amp;lt;hmac&amp;gt;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;timestamp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;x-wasphere-timestamp&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;expected&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;v1,sha256=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;crypto&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createHmac&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;sha256&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;secret&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;timestamp&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;.&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;rawBody&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;digest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;hex&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;crypto&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;timingSafeEqual&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Buffer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;signature&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nx"&gt;Buffer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;expected&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This pattern works great for automation — I use it with n8n workflows for order notifications and support routing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why self-host instead of the Business API?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Cost&lt;/strong&gt; — no per-message fees; you pay for your server.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Control&lt;/strong&gt; — your sessions and contacts never leave your infrastructure.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No approval queues&lt;/strong&gt; — connect a number and start building.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hackable&lt;/strong&gt; — it's MIT licensed. Fork it, extend it, ship it.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The full source is on GitHub: &lt;a href="https://github.com/wasphere/wasphere" rel="noopener noreferrer"&gt;github.com/wasphere/wasphere&lt;/a&gt;. There's a seeded live demo at &lt;a href="https://demo.wasphere.com" rel="noopener noreferrer"&gt;demo.wasphere.com&lt;/a&gt;, and full docs on &lt;a href="https://wasphere.com" rel="noopener noreferrer"&gt;wasphere.com&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you self-host your messaging stack, give the repo a star — and let me know what you build with it.&lt;/p&gt;

</description>
      <category>docker</category>
      <category>opensource</category>
      <category>whatsapp</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>How I actually test AI tools before recommending them</title>
      <dc:creator>Waqas Ahmed Waseer</dc:creator>
      <pubDate>Sat, 03 Oct 2026 05:27:45 +0000</pubDate>
      <link>https://dev.to/samii/how-i-actually-test-ai-tools-before-recommending-them-1eih</link>
      <guid>https://dev.to/samii/how-i-actually-test-ai-tools-before-recommending-them-1eih</guid>
      <description>&lt;p&gt;There's a new AI tool launching every day, and most "reviews" online are just reworded press releases. When someone asks me whether a tool is worth trying, I don't answer from the landing page — I test it myself first. Here's the process I follow.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. I start with a real task, not the demo.&lt;/strong&gt;&lt;br&gt;
Marketing demos always look smooth. So I pick one actual job I'd normally do — drafting a post, summarizing research, debugging a snippet — and run the tool through it. If it can't handle my real workflow, the demo doesn't matter.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. I check where the data goes.&lt;/strong&gt;&lt;br&gt;
Before signing up with anything more than an email, I look at the privacy policy and settings. Does it train on my inputs? Can I delete my data? A good tool makes this easy to find.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. I compare it against what I already use.&lt;/strong&gt;&lt;br&gt;
New doesn't mean better. I'll run the same task in the new tool and in my current one, side by side, and note where each wins on speed, accuracy, and cost.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. I give it a week, not an hour.&lt;/strong&gt;&lt;br&gt;
First impressions lie. I use the tool for at least a week in normal work before I form an opinion worth sharing.&lt;/p&gt;

&lt;p&gt;Only tools that survive all four steps make it into what I publish — you can read my full comparisons at &lt;a href="https://techriseups.com" rel="noopener noreferrer"&gt;TechRiseUPS&lt;/a&gt;. If a tool doesn't earn a recommendation, I say that too. Being honest when something isn't worth your time is the whole point.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>productivity</category>
      <category>tools</category>
    </item>
    <item>
      <title>Hello DEV — I run TechRiseUps, an independent tech news &amp; AI tool comparison site</title>
      <dc:creator>Waqas Ahmed Waseer</dc:creator>
      <pubDate>Sat, 03 Oct 2026 00:13:24 +0000</pubDate>
      <link>https://dev.to/samii/hello-dev-i-run-techriseups-an-independent-tech-news-ai-tool-comparison-site-cdl</link>
      <guid>https://dev.to/samii/hello-dev-i-run-techriseups-an-independent-tech-news-ai-tool-comparison-site-cdl</guid>
      <description>&lt;p&gt;Hey DEV! I'm Samii, and I run &lt;a href="https://techriseups.com" rel="noopener noreferrer"&gt;TechRiseUps&lt;/a&gt; — an independent tech news site covering AI &amp;amp; ML, startups, cloud, developer tools, SEO, and honest side-by-side tool comparisons, plus a free Monday tech brief.&lt;/p&gt;

&lt;p&gt;A bit about why I started it: I was spending hours every week comparing AI tools for my own work (writing, SEO, research) and kept running into sponsored "top 10" lists that all said the same thing. So I started publishing the comparisons I wished existed — hands-on, opinionated, and free of affiliate fluff.&lt;/p&gt;

&lt;p&gt;What I'm working on right now:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Honest AI writing-tool comparisons (ChatGPT vs Claude vs Gemini vs DeepSeek, free-tier limits included)&lt;/li&gt;
&lt;li&gt;Startup stories and practical SEO / dev-tool coverage&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What I'd love from this community: I'm always looking for tools worth testing and topics worth covering. If there's an AI tool or dev workflow you think deserves an honest review, tell me in the comments.&lt;/p&gt;

&lt;p&gt;Glad to be here — and happy to trade notes on AI tooling, SEO, or tech publishing.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>seo</category>
      <category>news</category>
      <category>startup</category>
    </item>
  </channel>
</rss>
