<?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: Vivek Sagar</title>
    <description>The latest articles on DEV Community by Vivek Sagar (@vivek_sagar_03577d2d6d942).</description>
    <link>https://dev.to/vivek_sagar_03577d2d6d942</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%2F4233068%2F916f108b-0f9e-4f1d-b750-5238e45491c6.jpg</url>
      <title>DEV Community: Vivek Sagar</title>
      <link>https://dev.to/vivek_sagar_03577d2d6d942</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/vivek_sagar_03577d2d6d942"/>
    <language>en</language>
    <item>
      <title>Postman Is a Desktop App: Testing APIs When You're Not at Your Desk</title>
      <dc:creator>Vivek Sagar</dc:creator>
      <pubDate>Sun, 08 Nov 2026 04:01:01 +0000</pubDate>
      <link>https://dev.to/vivek_sagar_03577d2d6d942/postman-is-a-desktop-app-testing-apis-when-youre-not-at-your-desk-2ap6</link>
      <guid>https://dev.to/vivek_sagar_03577d2d6d942/postman-is-a-desktop-app-testing-apis-when-youre-not-at-your-desk-2ap6</guid>
      <description>&lt;p&gt;It's 11pm. Production is returning 502s on one endpoint and only one, and the person who noticed is asking you to confirm whether it's still happening.&lt;/p&gt;

&lt;p&gt;You are not at your laptop.&lt;/p&gt;

&lt;p&gt;This sounds like a small problem. It isn't, because every option you have at 11pm is bad in a different way.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Termux and curl.&lt;/strong&gt; Works fine. Becomes miserable the moment you need an auth header, a request body, or the same environment variables you used yesterday.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Wait until morning.&lt;/strong&gt; Correct, and completely useless to the person currently waiting on you.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A cloud request tunnel.&lt;/strong&gt; Sends production traffic and its auth headers through a third party's logs. I've done it. I don't love it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A public API playground.&lt;/strong&gt; Requires pasting an internal URL and a bearer token into someone else's website. I don't think any of us should do this, and the number of people who do it regularly is not the number who should.&lt;/p&gt;

&lt;p&gt;So I built the option I kept wishing for: a real API client that runs on the phone in my hand.&lt;/p&gt;

&lt;h2&gt;
  
  
  What it does
&lt;/h2&gt;

&lt;p&gt;It's called Taho. Android, Flutter, MIT.&lt;/p&gt;

&lt;p&gt;The client side is thorough, because that's the baseline and there's no point being interesting if the fundamentals are shaky:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;15 HTTP methods, including the WebDAV verbs — PROPFIND, LOCK, UNLOCK — that SOAP and XML services need and most clients quietly omit&lt;/li&gt;
&lt;li&gt;OAuth 2.1: authorization code with PKCE S256, client credentials, and automatic token refresh with rotation&lt;/li&gt;
&lt;li&gt;GraphQL with live subscriptions, not just queries and mutations&lt;/li&gt;
&lt;li&gt;Server-Sent Events, WebSockets with hex-dumped binary frames, and an MQTT client&lt;/li&gt;
&lt;li&gt;Environments with &lt;code&gt;{{variable}}&lt;/code&gt; autocomplete, where the secrets live in the Android Keystore rather than in preferences&lt;/li&gt;
&lt;li&gt;Import from cURL, Postman, OpenAPI, HAR, and Bruno&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The part I didn't expect to build
&lt;/h2&gt;

&lt;p&gt;I planned a security engine as a minor feature. Grade responses against OWASP-informed rules, flag what's missing, move on.&lt;/p&gt;

&lt;p&gt;I went back and forth on whether a letter grade was too crude. It's lossy — a &lt;strong&gt;B&lt;/strong&gt; doesn't tell you what was wrong, and reducing a security posture to a single letter feels like the kind of simplification that gets people killed.&lt;/p&gt;

&lt;p&gt;I shipped it anyway, for one reason: &lt;strong&gt;legibility.&lt;/strong&gt; A wall of findings scrolls past. A &lt;strong&gt;C&lt;/strong&gt; stops the scroll. And once you're looking at a C, you read the three findings underneath it, and you fix them. The grade is a hook for the detail, not a replacement for it.&lt;/p&gt;

&lt;p&gt;Two constraints I held to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Grading is per-response, not per-app.&lt;/strong&gt; One endpoint missing HSTS doesn't quietly poison the grade of eleven endpoints that are fine. That would have made the number meaningless.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The findings name themselves.&lt;/strong&gt; "Missing &lt;code&gt;Strict-Transport-Security&lt;/code&gt;" is actionable. "Security issue detected" is not.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It also does boundary testing — deliberately malformed input against each field of your own request — because finding that your server 500s on a null byte is cheaper in QA than in production.&lt;/p&gt;

&lt;h2&gt;
  
  
  The constraint that shaped everything
&lt;/h2&gt;

&lt;p&gt;There is no analytics SDK in the binary.&lt;/p&gt;

&lt;p&gt;Not "minimal", not "anonymous", not "opt-out". None. Usage events go to local preferences on a fixed allowlist that structurally cannot hold a URL, a header, a body, or a token. Capped at 2,000 entries. Deletable from settings. Never transmitted.&lt;/p&gt;

&lt;p&gt;I wanted this and I'd defend it anyway, but it has a cost I don't pretend doesn't exist: &lt;strong&gt;I am partly blind about what's broken.&lt;/strong&gt; I don't know which screen gets used, which feature gets ignored, or where people get stuck. When something breaks, the first report is usually a stranger's, and that's a worse feedback loop than any dashboard.&lt;/p&gt;

&lt;p&gt;That's the trade. A privacy stance that costs you your own product analytics is a real stance with a real bill, and if you take it you should know what you're paying.&lt;/p&gt;

&lt;p&gt;The account is optional, by the way. I only ask for one to bind a subscription across devices. You can use the whole app without it.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's next
&lt;/h2&gt;

&lt;p&gt;Scheduled monitors run through WorkManager and survive the app being killed. The first version alerted on every check, which trained me to mute it within a day — the fastest way to make a monitoring feature useless is to be annoying every thirty minutes. It now alerts only when something &lt;em&gt;changes&lt;/em&gt; state.&lt;/p&gt;

&lt;p&gt;There's also a headless CLI runner that exits non-zero on assertion failure, so the same collection definitions run in CI.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try it
&lt;/h2&gt;

&lt;p&gt;It's live on Google Play right now:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Google Play:&lt;/strong&gt; &lt;a href="https://play.google.com/store/apps/details?id=com.eternal.taho" rel="noopener noreferrer"&gt;https://play.google.com/store/apps/details?id=com.eternal.taho&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Website:&lt;/strong&gt; &lt;a href="https://taho.co.in" rel="noopener noreferrer"&gt;https://taho.co.in&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Free tier is genuinely usable — the paid tier is ₹299/mo or ₹2,499/yr, and it unlocks 90-day history, PDF audit reports, unlimited environments, and response diffing.&lt;/p&gt;

&lt;p&gt;If you find a bug, please say so in the comments. I read all of them, and I fixed a genuinely embarrassing one — every file picker in the app was unselectable for custom extensions — because someone here described the symptom better than I could.&lt;/p&gt;

</description>
      <category>android</category>
      <category>flutter</category>
      <category>api</category>
      <category>security</category>
    </item>
  </channel>
</rss>
