<?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: Asher</title>
    <description>The latest articles on DEV Community by Asher (@_7629404d81d3a6c5ee43).</description>
    <link>https://dev.to/_7629404d81d3a6c5ee43</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%2F4153334%2F77ed162e-0a5d-4834-b055-94d33d0fe57a.png</url>
      <title>DEV Community: Asher</title>
      <link>https://dev.to/_7629404d81d3a6c5ee43</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/_7629404d81d3a6c5ee43"/>
    <language>en</language>
    <item>
      <title>Building a Customizable QR Code API with Rust</title>
      <dc:creator>Asher</dc:creator>
      <pubDate>Thu, 01 Oct 2026 02:05:10 +0000</pubDate>
      <link>https://dev.to/_7629404d81d3a6c5ee43/building-a-customizable-qr-code-api-with-rust-pcb</link>
      <guid>https://dev.to/_7629404d81d3a6c5ee43/building-a-customizable-qr-code-api-with-rust-pcb</guid>
      <description>&lt;p&gt;I've been building small APIs lately, mostly as a way to learn by actually shipping things instead of just reading about them.&lt;/p&gt;

&lt;p&gt;One of the projects I ended up spending more time on than I expected was a QR Code API.&lt;/p&gt;

&lt;p&gt;At first, the idea was pretty simple:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Send some data → get a QR code.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That should be straightforward, right?&lt;/p&gt;

&lt;p&gt;Well, it was, until I started thinking about all the things I wanted to customize.&lt;/p&gt;

&lt;p&gt;What if I want a gradient instead of a single color?&lt;br&gt;
What if I want the corners to look different from the rest of the QR code?&lt;br&gt;
What if I want SVG instead of PNG?&lt;br&gt;
What if I need to decode a QR code somewhere in my application later?&lt;/p&gt;

&lt;p&gt;So I kept adding things, and the project gradually turned into more than just a basic QR generator.&lt;/p&gt;

&lt;p&gt;I recently published it on RapidAPI, so I wanted to share what I built and a little bit of what I learned along the way.&lt;/p&gt;
&lt;h2&gt;
  
  
  What does it do?
&lt;/h2&gt;

&lt;p&gt;The API supports both &lt;strong&gt;QR code generation&lt;/strong&gt; and &lt;strong&gt;QR code decoding/validation&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;For generation, you can customize several parts of the QR code, including:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;PNG, JPEG, WebP, and SVG output&lt;/li&gt;
&lt;li&gt;Custom gradients&lt;/li&gt;
&lt;li&gt;Separate gradients for the QR body, corner squares, and corner dots&lt;/li&gt;
&lt;li&gt;Different body/module shapes&lt;/li&gt;
&lt;li&gt;Different dot styles&lt;/li&gt;
&lt;li&gt;URL or Base64 input&lt;/li&gt;
&lt;li&gt;Different response types depending on the endpoint&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can also use structured QR data such as Wi-Fi, email, telephone, SMS, geolocation, and contact information through the appropriate request fields.&lt;/p&gt;

&lt;p&gt;The goal wasn't really to build the biggest QR platform possible.&lt;/p&gt;

&lt;p&gt;I just wanted something flexible enough that I could use it in projects where a basic black-and-white QR code wasn't quite enough.&lt;/p&gt;


&lt;h2&gt;
  
  
  A simple Rust example
&lt;/h2&gt;

&lt;p&gt;Since the API itself is written in Rust, I thought it would be more useful to show the examples in Rust too.&lt;/p&gt;

&lt;p&gt;The API is just a REST API, so of course you can call it from other languages as well.&lt;/p&gt;

&lt;p&gt;Here's a minimal request using &lt;code&gt;reqwest&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;reqwest&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Client&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;serde_json&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nd"&gt;#[tokio::main]&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="nb"&gt;Box&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;dyn&lt;/span&gt; &lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;error&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Error&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Client&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;
        &lt;span class="nf"&gt;.post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"https://qr-code125.p.rapidapi.com/qr"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;.header&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"X-RapidAPI-Key"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"YOUR_RAPIDAPI_KEY"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;.json&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nd"&gt;json!&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
            &lt;span class="s"&gt;"data"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"https://example.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s"&gt;"format"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"png"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s"&gt;"size"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;512&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s"&gt;"response_type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"base64"&lt;/span&gt;
        &lt;span class="p"&gt;}))&lt;/span&gt;
        &lt;span class="nf"&gt;.send&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="k"&gt;.await&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;body&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="nf"&gt;.text&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="k"&gt;.await&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"{}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nf"&gt;Ok&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;&lt;code&gt;Cargo.toml&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight toml"&gt;&lt;code&gt;&lt;span class="nn"&gt;[dependencies]&lt;/span&gt;
&lt;span class="py"&gt;tokio&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="py"&gt;version&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="py"&gt;features&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"full"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="py"&gt;reqwest&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="py"&gt;version&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"0.13"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="py"&gt;features&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"json"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="py"&gt;serde_json&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"1"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It returns base64 output. And if you decode that, you will get like this QR:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F4dy0evmvfqo0a0ajw363.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F4dy0evmvfqo0a0ajw363.png" alt=" " width="512" height="512"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The basic request is intentionally small. Most of the other parameters are optional customization.&lt;/p&gt;

&lt;p&gt;You can also use RapidAPI's &lt;strong&gt;Copy Code&lt;/strong&gt; feature from the playground to get the request in other languages.&lt;/p&gt;




&lt;h2&gt;
  
  
  Customization
&lt;/h2&gt;

&lt;p&gt;This is where the project became much more interesting for me.&lt;/p&gt;

&lt;p&gt;Generating a normal QR code isn't particularly complicated.&lt;/p&gt;

&lt;p&gt;The fun part was figuring out how much of the visual appearance I could expose without making the API completely confusing.&lt;/p&gt;

&lt;p&gt;For example, the QR body and the corner elements can have separate gradients.&lt;/p&gt;

&lt;p&gt;Conceptually:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;QR body
  └── gradient A

Corner squares
  └── gradient B

Corner dots
  └── gradient C
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can also change the shape of the QR modules and dots.&lt;/p&gt;

&lt;p&gt;That means the same data can produce very different-looking QR codes.&lt;/p&gt;

&lt;p&gt;I initially thought the styling part would be relatively small.&lt;/p&gt;

&lt;p&gt;It wasn't.&lt;/p&gt;

&lt;p&gt;Once you combine different shapes, gradients, corner styles, output formats, and error-correction settings, the number of possible combinations grows pretty quickly.&lt;/p&gt;

&lt;p&gt;That's probably one of the more interesting parts of building something like this: the normal case is easy, but edge cases tend to show up everywhere.&lt;/p&gt;




&lt;h2&gt;
  
  
  A more customized request
&lt;/h2&gt;

&lt;p&gt;Here's a more complete example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;reqwest&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Client&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;serde_json&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nd"&gt;#[tokio::main]&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="nb"&gt;Box&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;dyn&lt;/span&gt; &lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;error&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Error&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Client&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;
    &lt;span class="nf"&gt;.post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"https://qr-code125.p.rapidapi.com/qr"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;.header&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"X-RapidAPI-Key"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"YOUR_RAPIDAPI_KEY"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;.json&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nd"&gt;json!&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="s"&gt;"format"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"png"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;            &lt;span class="c1"&gt;// svg, png, jpeg, webp&lt;/span&gt;
        &lt;span class="s"&gt;"size"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;512&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;                &lt;span class="c1"&gt;// 512 ~ 4096&lt;/span&gt;
        &lt;span class="s"&gt;"margin"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;                &lt;span class="c1"&gt;// 0 ~ 10&lt;/span&gt;
        &lt;span class="s"&gt;"error_correction"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"H"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;    &lt;span class="c1"&gt;// L, M, Q, H&lt;/span&gt;
        &lt;span class="s"&gt;"style"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"extra_rounded"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;   &lt;span class="c1"&gt;// square, dots, rounded, classy,&lt;/span&gt;
                                    &lt;span class="c1"&gt;// classy_rounded, extra_rounded&lt;/span&gt;
        &lt;span class="s"&gt;"shape"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"square"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;          &lt;span class="c1"&gt;// square, circle&lt;/span&gt;

        &lt;span class="c1"&gt;// Use either `data` or `type` + `payload`.&lt;/span&gt;
        &lt;span class="s"&gt;"data"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"Hello world"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

        &lt;span class="c1"&gt;// Example:&lt;/span&gt;
        &lt;span class="c1"&gt;// "type": "sms",&lt;/span&gt;
        &lt;span class="c1"&gt;// "payload": {&lt;/span&gt;
        &lt;span class="c1"&gt;//     "phone": "+821012345678",&lt;/span&gt;
        &lt;span class="c1"&gt;//     "message": "hello"&lt;/span&gt;
        &lt;span class="c1"&gt;// },&lt;/span&gt;

        &lt;span class="s"&gt;"foreground_color"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"#000000"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s"&gt;"background_color"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"#FFFFFF"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

        &lt;span class="s"&gt;"gradient_type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"linear"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="c1"&gt;// linear, radial&lt;/span&gt;
        &lt;span class="s"&gt;"gradient_direction"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s"&gt;"gradient_start"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"#7DD3FC"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s"&gt;"gradient_end"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"#3B82F6"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

        &lt;span class="s"&gt;"corner_dot"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"dot"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s"&gt;"corner_dot_gradient_type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"linear"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s"&gt;"corner_dot_gradient_direction"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s"&gt;"corner_dot_gradient_start"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"#7DD3FC"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s"&gt;"corner_dot_gradient_end"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"#3B82F6"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="c1"&gt;// "corner_dot_color": "#3B82F6",&lt;/span&gt;

        &lt;span class="s"&gt;"corner_square"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"dot"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="c1"&gt;// "corner_square_gradient_type": "linear",&lt;/span&gt;
        &lt;span class="c1"&gt;// "corner_square_gradient_direction": 0,&lt;/span&gt;
        &lt;span class="c1"&gt;// "corner_square_gradient_start": "#7DD3FC",            &lt;/span&gt;
        &lt;span class="c1"&gt;// "corner_square_gradient_end": "#3B82F6",&lt;/span&gt;
        &lt;span class="s"&gt;"corner_square_color"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"#7DD3FC"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

        &lt;span class="s"&gt;"response_type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"base64"&lt;/span&gt;   &lt;span class="c1"&gt;// json, base64, direct&lt;/span&gt;
    &lt;span class="p"&gt;}))&lt;/span&gt;
    &lt;span class="nf"&gt;.send&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;.await&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;body&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="nf"&gt;.text&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="k"&gt;.await&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"{}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nf"&gt;Ok&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;It returns base64 output. And if you decode that, you will get like this QR:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F0l7evlf4tz3t17sq8zf5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F0l7evlf4tz3t17sq8zf5.png" alt=" " width="512" height="512"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;One thing to keep in mind is that some options are endpoint-specific, so the API playground is still the best place to check the currently available parameters.&lt;/p&gt;




&lt;h2&gt;
  
  
  Output formats
&lt;/h2&gt;

&lt;p&gt;The API supports several output formats:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;PNG
JPEG
WebP
SVG
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;SVG is useful when you want the QR code to scale without losing quality.&lt;/p&gt;

&lt;p&gt;WebP can be useful for web applications where file size matters.&lt;/p&gt;

&lt;p&gt;I wanted to keep the output format flexible instead of forcing every use case into the same image format.&lt;/p&gt;




&lt;h2&gt;
  
  
  Decoding QR codes
&lt;/h2&gt;

&lt;p&gt;At some point while building the generator, I realized that generating QR codes wasn't the only thing I wanted the API to do.&lt;/p&gt;

&lt;p&gt;There are also cases where an application receives a QR image and needs to figure out what's inside it.&lt;/p&gt;

&lt;p&gt;So I added decoding and validation endpoints as well.&lt;/p&gt;

&lt;p&gt;The general workflow looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;QR image
   ↓
Upload / provide image data
   ↓
Decode
   ↓
Extract QR contents
   ↓
Validate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This can be useful for applications where users upload QR images and your backend needs to inspect them automatically.&lt;/p&gt;




&lt;h2&gt;
  
  
  URL and Base64 input
&lt;/h2&gt;

&lt;p&gt;Another small thing I wanted to support was different ways of passing image data.&lt;/p&gt;

&lt;p&gt;Depending on the endpoint, you can work with a URL or Base64-encoded data.&lt;/p&gt;

&lt;p&gt;That means you don't always have to save an image somewhere first just to send it to the API.&lt;/p&gt;

&lt;p&gt;For backend applications, that can make the integration a little simpler.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Rust?
&lt;/h2&gt;

&lt;p&gt;I mainly chose Rust because I wanted to build something real with it, rather than another small toy project.&lt;/p&gt;

&lt;p&gt;Once image processing, API handling, and error cases started coming together, it turned out to be a pretty good project for learning.&lt;/p&gt;

&lt;p&gt;I ended up working on things like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;HTTP API design&lt;/li&gt;
&lt;li&gt;Image processing&lt;/li&gt;
&lt;li&gt;Encoding and decoding&lt;/li&gt;
&lt;li&gt;Request handling&lt;/li&gt;
&lt;li&gt;Error handling&lt;/li&gt;
&lt;li&gt;API deployment&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The original idea was small, but it kept growing as I found more things I wanted to support.&lt;/p&gt;

&lt;p&gt;That's probably my favorite part of building side projects: the final project rarely looks exactly like the thing you originally imagined.&lt;/p&gt;




&lt;h2&gt;
  
  
  What I learned
&lt;/h2&gt;

&lt;p&gt;One thing I learned from this project is that adding features is easy compared to deciding which features actually matter.&lt;/p&gt;

&lt;p&gt;It's surprisingly easy to keep adding another option:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Maybe someone will need this."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And then another one.&lt;/p&gt;

&lt;p&gt;And another one.&lt;/p&gt;

&lt;p&gt;At some point you have a lot of flexibility, but also a much more complicated API.&lt;/p&gt;

&lt;p&gt;So one thing I want to improve next is the balance between flexibility and simplicity.&lt;/p&gt;

&lt;p&gt;I'd also like to add more examples for different languages and make the documentation easier to navigate.&lt;/p&gt;




&lt;h2&gt;
  
  
  Who is this API for?
&lt;/h2&gt;

&lt;p&gt;I think there are a few situations where an API like this can be useful:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Generating QR codes dynamically in a web application&lt;/li&gt;
&lt;li&gt;Creating QR codes from user input&lt;/li&gt;
&lt;li&gt;Generating QR assets for emails, documents, or product pages&lt;/li&gt;
&lt;li&gt;Adding QR functionality to an existing SaaS&lt;/li&gt;
&lt;li&gt;Decoding QR images uploaded by users&lt;/li&gt;
&lt;li&gt;Validating QR-related input on the backend&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The idea is simply to handle the QR generation or decoding through an API instead of implementing that functionality from scratch inside the application.&lt;/p&gt;




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

&lt;p&gt;I've published the API on RapidAPI:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://rapidapi.com/haruato12/api/qr-code125" rel="noopener noreferrer"&gt;https://rapidapi.com/haruato12/api/qr-code125&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can try the endpoints directly from the playground and experiment with the available parameters.&lt;/p&gt;

&lt;p&gt;I'm still working on the project, so I'm particularly interested in feedback from other developers.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;Was the API easy to understand?&lt;/li&gt;
&lt;li&gt;Are there parameters that feel confusing?&lt;/li&gt;
&lt;li&gt;Is there a QR-related feature that would make it more useful?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I'm trying to avoid adding features just for the sake of adding them, so real-world feedback would be much more useful.&lt;/p&gt;

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

</description>
      <category>rust</category>
      <category>api</category>
      <category>showdev</category>
    </item>
  </channel>
</rss>
