<?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: Khairul Muhtadin</title>
    <description>The latest articles on DEV Community by Khairul Muhtadin (@khmuhtadin).</description>
    <link>https://dev.to/khmuhtadin</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%2F3796665%2F6f5c9229-982f-48e5-8082-05353adb9bee.png</url>
      <title>DEV Community: Khairul Muhtadin</title>
      <link>https://dev.to/khmuhtadin</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/khmuhtadin"/>
    <language>en</language>
    <item>
      <title>Verified is not the same as listed: getting API Indonesia onto n8n.io/integrations</title>
      <dc:creator>Khairul Muhtadin</dc:creator>
      <pubDate>Thu, 29 Oct 2026 13:28:33 +0000</pubDate>
      <link>https://dev.to/khmuhtadin/verified-is-not-the-same-as-listed-getting-api-indonesia-onto-n8niointegrations-4dpa</link>
      <guid>https://dev.to/khmuhtadin/verified-is-not-the-same-as-listed-getting-api-indonesia-onto-n8niointegrations-4dpa</guid>
      <description>&lt;p&gt;&lt;em&gt;I build and run &lt;a href="https://apiindonesia.id" rel="noopener noreferrer"&gt;API Indonesia&lt;/a&gt;, a REST API for Indonesian public data. This is a short note on getting its n8n node listed.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;API Indonesia has had an n8n community node, &lt;code&gt;n8n-nodes-api-indonesia&lt;/code&gt;, since September. As of 29 October it also has a page on the n8n integrations directory: &lt;a href="https://n8n.io/integrations/api-indonesia/" rel="noopener noreferrer"&gt;n8n.io/integrations/api-indonesia&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Those two things sound like the same milestone. They were a month apart.&lt;/p&gt;

&lt;h2&gt;
  
  
  What verification gave us
&lt;/h2&gt;

&lt;p&gt;n8n approved the node for verification on 23 September, and it was published to n8n Cloud the next day. An update to version 0.3.0 was approved on 28 September.&lt;/p&gt;

&lt;p&gt;Verification is what makes a node installable from the nodes panel. An instance owner or admin searches for it, finds it under "More from the community", and installs it once for the whole instance. On n8n Cloud that is the only way to get a community node at all.&lt;/p&gt;

&lt;p&gt;So from late September the node was usable. It was not findable from the place most people start looking.&lt;/p&gt;

&lt;h2&gt;
  
  
  What it did not give us
&lt;/h2&gt;

&lt;p&gt;Searching "indonesia" on n8n.io/integrations returned zero results.&lt;/p&gt;

&lt;p&gt;The n8n community-nodes registry answered the question. Our record was published, verified, and carried the right version, but it had &lt;code&gt;isOfficialNode: false&lt;/code&gt; and no company name. The integrations directory only builds pages for nodes flagged as partner nodes. Verification and partner listing are separate states, and nothing in the verification emails mentions the second one.&lt;/p&gt;

&lt;p&gt;You can check your own node's state with one request:&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;-sg&lt;/span&gt; &lt;span class="s1"&gt;'https://api.n8n.io/api/community-nodes?filters[packageName][$eq]=YOUR-PACKAGE'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  | jq &lt;span class="s1"&gt;'.data[0].attributes | {npmVersion, isPublished, isOfficialNode, companyName}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The fix
&lt;/h2&gt;

&lt;p&gt;On 28 October I wrote to the n8n creators team, asked why a verified node was missing from the directory, and named Khaisa Studio as the company behind it. They routed it to the nodes team the same day.&lt;/p&gt;

&lt;p&gt;On 29 October the registry record flipped to &lt;code&gt;isOfficialNode: true&lt;/code&gt; and the page went live, describing the node as "built and maintained by our partners at API Indonesia and verified by n8n".&lt;/p&gt;

&lt;h2&gt;
  
  
  What is on the page, and what is not
&lt;/h2&gt;

&lt;p&gt;The node covers 31 resources and 106 operations: regions, prayer times, BMKG earthquakes and early warnings, Bank Indonesia exchange rates, public holidays, postal codes, schools, hospitals, halal and BPOM records, NIK and NPWP validation, Transjakarta, and more.&lt;/p&gt;

&lt;p&gt;The operations table on the n8n.io page currently shows only the region operations. The full list is in the &lt;a href="https://github.com/khmuhtadin/n8n-nodes-api-indonesia" rel="noopener noreferrer"&gt;README&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  If you ship an n8n node
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Treat verification and directory listing as two separate goals.&lt;/li&gt;
&lt;li&gt;Check &lt;code&gt;isOfficialNode&lt;/code&gt; and &lt;code&gt;companyName&lt;/code&gt; in the registry after you are verified. If they are empty, ask the n8n team. The listing does not appear on its own.&lt;/li&gt;
&lt;li&gt;Have a company name ready. The listing is attributed to a partner, not to a person.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>n8n</category>
      <category>api</category>
      <category>automation</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Indonesia Regions API: province, regency, district and village data</title>
      <dc:creator>Khairul Muhtadin</dc:creator>
      <pubDate>Thu, 29 Oct 2026 07:36:43 +0000</pubDate>
      <link>https://dev.to/khmuhtadin/indonesia-regions-api-province-regency-district-and-village-data-1ikb</link>
      <guid>https://dev.to/khmuhtadin/indonesia-regions-api-province-regency-district-and-village-data-1ikb</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Cross-posted from the API Indonesia blog. Original: &lt;a href="https://apiindonesia.id/en/blog/indonesia-regions-api-provinces-to-villages/" rel="noopener noreferrer"&gt;https://apiindonesia.id/en/blog/indonesia-regions-api-provinces-to-villages/&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I build and run API Indonesia (apiindonesia.id), a REST API for Indonesian public data. This post walks through the region data (38 provinces, 514 regencies/cities, 7,285 districts, 83,762 villages) and how to wire cascading address dropdowns to it, including the code snippets I use myself.&lt;/p&gt;

&lt;p&gt;Almost every app that has an address form, from e-commerce and HRIS to government apps, needs cascading region dropdowns: pick a province, then the regency/city appears automatically, then the district, then the kelurahan/desa (village). The problem is that the official Indonesian administrative region data (based on Kepmendagri, the Ministry of Home Affairs decree) is large and changes often because of regional splits (pemekaran). Hardcoding this data in your own app means you have to keep up the maintenance every time something changes.&lt;/p&gt;

&lt;p&gt;The Regions API (API Wilayah) from API Indonesia provides the entire administrative region hierarchy, province, regency/city, district, and kelurahan/desa (village), in one REST API you can just call, without storing a static dataset on your own server.&lt;/p&gt;

&lt;h2&gt;
  
  
  Data Coverage
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Provinces&lt;/strong&gt;: 38 provinces across Indonesia&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Regency/City&lt;/strong&gt; (kabupaten/kota): every regency and city under each province&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;District&lt;/strong&gt; (kecamatan): every district under each regency/city&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Kelurahan/Desa&lt;/strong&gt; (village): every kelurahan and desa under each district&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cross-level search&lt;/strong&gt;: search for a region name without knowing its level first&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Endpoint List
&lt;/h2&gt;

&lt;p&gt;Base URL: &lt;code&gt;https://use.apiindonesia.id/api/v1/wilayah&lt;/code&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Method&lt;/th&gt;
&lt;th&gt;Endpoint&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;GET&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/provinsi&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;List all provinces (paginated)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GET&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/provinsi/:id&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Details of one province&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GET&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/kabupaten?provinsi_id=&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;List regencies/cities in one province&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GET&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/kabupaten/:id&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Details of one regency/city&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GET&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/kecamatan?kabupaten_id=&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;List districts in one regency/city&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GET&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/kecamatan/:id&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Details of one district&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GET&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/kelurahan?kecamatan_id=&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;List kelurahan/desa in one district&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GET&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/kelurahan/:id&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Details of one kelurahan/desa&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GET&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/search?q=&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Search regions across all levels at once&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;All list endpoints support the &lt;code&gt;page&lt;/code&gt; and &lt;code&gt;per_page&lt;/code&gt; parameters (maximum 100 per page) and return a &lt;code&gt;meta&lt;/code&gt; object containing &lt;code&gt;total&lt;/code&gt;, &lt;code&gt;page&lt;/code&gt;, &lt;code&gt;per_page&lt;/code&gt;, and &lt;code&gt;total_pages&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Request Example
&lt;/h2&gt;

&lt;p&gt;Get the list of regencies/cities in West Java:&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="s2"&gt;"https://use.apiindonesia.id/api/v1/wilayah/kabupaten?provinsi_id=32"&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;"x-api-key: aip_live_xxx"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://use.apiindonesia.id/api/v1/wilayah/kabupaten?provinsi_id=32&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;x-api-key&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;API_INDONESIA_KEY&lt;/span&gt; &lt;span class="p"&gt;}&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="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;meta&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;res&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="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// [{ id, name, province_id, ... }, ...]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;

&lt;span class="n"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://use.apiindonesia.id/api/v1/wilayah/kabupaten&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;provinsi_id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;32&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;x-api-key&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;aip_live_xxx&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;res&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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;data&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Response Example
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"data"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"3273"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"KOTA BANDUNG"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"province_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"32"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"3204"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"KABUPATEN BANDUNG"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"province_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"32"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"meta"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"total"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;27&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"page"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"per_page"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"total_pages"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Building a Cascading Address Dropdown
&lt;/h2&gt;

&lt;p&gt;The most common pattern: keep the &lt;code&gt;provinsi_id&lt;/code&gt; the user selected in state, then call &lt;code&gt;/kabupaten?provinsi_id=&lt;/code&gt; every time the user changes province. Repeat the same pattern for districts and villages. Because each level has a consistent &lt;code&gt;id&lt;/code&gt; that works as a foreign key, you can store &lt;code&gt;province_id&lt;/code&gt;, &lt;code&gt;regency_id&lt;/code&gt;, &lt;code&gt;district_id&lt;/code&gt;, and &lt;code&gt;village_id&lt;/code&gt; directly in your own database without copying region names.&lt;/p&gt;

&lt;p&gt;If you need free-form address search (for example an autocomplete to find a village), use the &lt;code&gt;/search?q=&lt;/code&gt; endpoint, which searches all four levels at once and returns a &lt;code&gt;level&lt;/code&gt; field to mark the type of region.&lt;/p&gt;

&lt;p&gt;Tips for the &lt;code&gt;/search&lt;/code&gt; endpoint:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Send at least 3 characters before actually calling the API, so autocomplete results do not burn through your quota.&lt;/li&gt;
&lt;li&gt;Debounce user input for around 300ms before fetching.&lt;/li&gt;
&lt;li&gt;Use the &lt;code&gt;level&lt;/code&gt; field in the response to decide the icon or label in the dropdown (for example a "Kota" vs "Kabupaten" badge).&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Why Not Hardcode the Data Yourself?
&lt;/h2&gt;

&lt;p&gt;Many teams choose to copy an open-source region dataset into their database. That can work, but there is a risk of the data going stale after a regional split or a change to region codes, and you still have to build your own search and pagination endpoints. With the Regions API, the data always matches the latest region codes and you only need one API key to access every endpoint.&lt;/p&gt;

&lt;h2&gt;
  
  
  Combining with Other APIs
&lt;/h2&gt;

&lt;p&gt;Region data is only really complete when you pair it with other APIs in the same ecosystem:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Postal Code API&lt;/strong&gt;: after the user picks a kelurahan, fetch the matching postal codes via &lt;code&gt;/api/v1/kodepos/search?q=&lt;/code&gt; so the postal code field fills in automatically. Good for e-commerce checkout and onboarding forms.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;KBBI API&lt;/strong&gt;: if your app shows region names in its content (for example a regional news portal), validate the spelling of place names via &lt;code&gt;/api/v1/kbbi/word/:word&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;BI Exchange Rate API&lt;/strong&gt;: for logistics or e-commerce apps that show multi-currency prices per region, pair it with the official Bank Indonesia rates from &lt;code&gt;/api/v1/kurs-bi/latest&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All of these APIs use the same API key, so integration just means adding a base path, not creating a new account.&lt;/p&gt;

&lt;h2&gt;
  
  
  FAQ
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Does this data follow the latest regional changes?&lt;/strong&gt; Yes, the data follows the latest Kepmendagri region codes and is updated on the API side, so you do not need to patch your own dataset every time a region splits.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How many kelurahan/desa are available in total?&lt;/strong&gt; Every kelurahan and desa in Indonesia (more than 80 thousand) is available through the &lt;code&gt;/kelurahan&lt;/code&gt; endpoint with pagination.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Can I use it for autocomplete?&lt;/strong&gt; Yes. The &lt;code&gt;/search?q=&lt;/code&gt; endpoint searches all levels at once and works well for autocomplete with client-side debounce.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Is it free?&lt;/strong&gt; There is no monthly free allowance. New accounts get a one-time 3,000 credit bonus (Rp3,000) after email verification, and a successful request costs 2 credits, which is enough to build an MVP and test it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Start Now
&lt;/h2&gt;

&lt;p&gt;Get a free API key at &lt;a href="https://dashboard.apiindonesia.id/register" rel="noopener noreferrer"&gt;dashboard.apiindonesia.id/register&lt;/a&gt; and see the full parameter list at &lt;a href="https://docs.apiindonesia.id" rel="noopener noreferrer"&gt;docs.apiindonesia.id&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>tutorial</category>
      <category>indonesia</category>
      <category>api</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Text classification in n8n without a chat LLM: building a node for TypeSafe's Jev</title>
      <dc:creator>Khairul Muhtadin</dc:creator>
      <pubDate>Mon, 21 Sep 2026 10:27:56 +0000</pubDate>
      <link>https://dev.to/khmuhtadin/text-classification-in-n8n-without-a-chat-llm-building-a-node-for-typesafes-jev-5b2j</link>
      <guid>https://dev.to/khmuhtadin/text-classification-in-n8n-without-a-chat-llm-building-a-node-for-typesafes-jev-5b2j</guid>
      <description>&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%2Fjhpu1yim6vadnfwsfur7.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%2Fjhpu1yim6vadnfwsfur7.png" alt=" " width="772" height="626"&gt;&lt;/a&gt;&lt;/p&gt;


&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
    &lt;div class="c-embed__content"&gt;
        &lt;div class="c-embed__cover"&gt;
          &lt;a href="https://khmuhtadin.com/blog/i-built-an-n8n-node-for-jev-classification/" class="c-link align-middle" rel="noopener noreferrer"&gt;
            &lt;img alt="" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fkhmuhtadin.com%2Fimages%2Fblog%2Fjev-classification%2Fjev-routing-workflow.webp" height="478" class="m-0" width="800"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="c-embed__body"&gt;
        &lt;h2 class="fs-xl lh-tight"&gt;
          &lt;a href="https://khmuhtadin.com/blog/i-built-an-n8n-node-for-jev-classification/" rel="noopener noreferrer" class="c-link"&gt;
            I Built an n8n Node for Decisions, Not Text Generation - Khairul Muhtadin
          &lt;/a&gt;
        &lt;/h2&gt;
          &lt;p class="truncate-at-3"&gt;
            Why I built n8n-nodes-jev-classification for TypeSafe AI's Jev, how confidence-based routing works, and what I learned shipping it to npm.
          &lt;/p&gt;
        &lt;div class="color-secondary fs-s flex items-center"&gt;
            &lt;img alt="favicon" class="c-embed__favicon m-0 mr-2 radius-0" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fkhmuhtadin.com%2Ffavicon.svg" width="64" height="64"&gt;
          khmuhtadin.com
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;


</description>
      <category>n8n</category>
      <category>automation</category>
      <category>ai</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Databases for durable state (sticky note vs filing cabinet)</title>
      <dc:creator>Khairul Muhtadin</dc:creator>
      <pubDate>Tue, 18 Aug 2026 11:00:02 +0000</pubDate>
      <link>https://dev.to/khmuhtadin/databases-for-durable-state-sticky-note-vs-filing-cabinet-2h2m</link>
      <guid>https://dev.to/khmuhtadin/databases-for-durable-state-sticky-note-vs-filing-cabinet-2h2m</guid>
      <description>&lt;p&gt;Workflows forget. That is fine for drafts.&lt;/p&gt;

&lt;p&gt;It is fatal for orders, tickets, and retries. If state must survive the next run, sticky notes are not enough. You need a filing cabinet.&lt;/p&gt;

&lt;p&gt;Swipe for when to store durable state, a create-once flow, and three beginner rules so retries stop inventing duplicates.&lt;/p&gt;

&lt;p&gt;What is the one fact your flow keeps forgetting?&lt;/p&gt;

&lt;p&gt;Episode 17 of Ship with n8n: 20 builder skills.&lt;/p&gt;

</description>
      <category>automation</category>
      <category>ai</category>
      <category>productivity</category>
      <category>tools</category>
    </item>
    <item>
      <title>AI that stays under control (smart intern, not CEO)</title>
      <dc:creator>Khairul Muhtadin</dc:creator>
      <pubDate>Sun, 16 Aug 2026 11:00:00 +0000</pubDate>
      <link>https://dev.to/khmuhtadin/ai-that-stays-under-control-smart-intern-not-ceo-2nk8</link>
      <guid>https://dev.to/khmuhtadin/ai-that-stays-under-control-smart-intern-not-ceo-2nk8</guid>
      <description>&lt;p&gt;AI in n8n is not a magic coworker.&lt;/p&gt;

&lt;p&gt;It is a smart intern. Without a job description, tools limits, and stop rules, it will improvise in production.&lt;/p&gt;

&lt;p&gt;Swipe for the intern analogy, three rails before the model, and a support-triage flow where refunds still need a gate.&lt;/p&gt;

&lt;p&gt;Where does your agent still have unlimited tools?&lt;/p&gt;

&lt;p&gt;Episode 16 of Ship with n8n: 20 builder skills.&lt;/p&gt;

</description>
      <category>automation</category>
      <category>ai</category>
      <category>productivity</category>
      <category>tools</category>
    </item>
    <item>
      <title>Wait, schedule, and time (alarm vs kitchen timer)</title>
      <dc:creator>Khairul Muhtadin</dc:creator>
      <pubDate>Fri, 14 Aug 2026 11:00:00 +0000</pubDate>
      <link>https://dev.to/khmuhtadin/wait-schedule-and-time-alarm-vs-kitchen-timer-16oi</link>
      <guid>https://dev.to/khmuhtadin/wait-schedule-and-time-alarm-vs-kitchen-timer-16oi</guid>
      <description>&lt;p&gt;Time in n8n is not “hope it runs later”.&lt;/p&gt;

&lt;p&gt;An alarm starts the kitchen. A timer pauses mid-recipe. Mixing those two is how people get double fires and silent delays.&lt;/p&gt;

&lt;p&gt;Swipe for a beginner map of Schedule vs Wait, a polite API loop, and three rules so time stays boring.&lt;/p&gt;

&lt;p&gt;Do you need a clock, or just a pause?&lt;/p&gt;

&lt;p&gt;Episode 15 of Ship with n8n: 20 builder skills.&lt;/p&gt;

</description>
      <category>automation</category>
      <category>ai</category>
      <category>productivity</category>
      <category>tools</category>
    </item>
    <item>
      <title>Secrets that stay secret (your API key is a house key)</title>
      <dc:creator>Khairul Muhtadin</dc:creator>
      <pubDate>Wed, 12 Aug 2026 11:00:01 +0000</pubDate>
      <link>https://dev.to/khmuhtadin/secrets-that-stay-secret-your-api-key-is-a-house-key-2jj8</link>
      <guid>https://dev.to/khmuhtadin/secrets-that-stay-secret-your-api-key-is-a-house-key-2jj8</guid>
      <description>&lt;p&gt;Your API key is not “just config”.&lt;/p&gt;

&lt;p&gt;It is a house key. Leave it on the door and anyone walking by can open production.&lt;/p&gt;

&lt;p&gt;Swipe for a beginner map of n8n secrets: what counts as a secret, why hardcoding breaks you, and the simple habit that keeps keys in a vault instead of on the canvas.&lt;/p&gt;

&lt;p&gt;Where do your live keys live today: credentials, or still inside a node?&lt;/p&gt;

&lt;p&gt;Episode 14 of Ship with n8n: 20 builder skills.&lt;/p&gt;

</description>
      <category>automation</category>
      <category>ai</category>
      <category>productivity</category>
      <category>tools</category>
    </item>
    <item>
      <title>Loops that finish (empty checks, no double-loop)</title>
      <dc:creator>Khairul Muhtadin</dc:creator>
      <pubDate>Mon, 10 Aug 2026 11:00:00 +0000</pubDate>
      <link>https://dev.to/khmuhtadin/loops-that-finish-empty-checks-no-double-loop-14j</link>
      <guid>https://dev.to/khmuhtadin/loops-that-finish-empty-checks-no-double-loop-14j</guid>
      <description>&lt;p&gt;Loops feel powerful until one never ends.&lt;/p&gt;

&lt;p&gt;Missing exits, stacked pagination, side effects with no cap.&lt;/p&gt;

&lt;p&gt;Swipe for a batch that actually finishes — and the double-loop trap.&lt;/p&gt;

&lt;p&gt;Which loop in production would you not want running unsupervised tonight?&lt;/p&gt;

&lt;p&gt;Episode 13 of Ship with n8n: 20 builder skills.&lt;/p&gt;

</description>
      <category>automation</category>
      <category>ai</category>
      <category>productivity</category>
      <category>tools</category>
    </item>
    <item>
      <title>Branching without chaos (normalize first, then decide)</title>
      <dc:creator>Khairul Muhtadin</dc:creator>
      <pubDate>Sat, 08 Aug 2026 11:00:01 +0000</pubDate>
      <link>https://dev.to/khmuhtadin/branching-without-chaos-normalize-first-then-decide-1pek</link>
      <guid>https://dev.to/khmuhtadin/branching-without-chaos-normalize-first-then-decide-1pek</guid>
      <description>&lt;p&gt;Branching is where readable workflows go to die.&lt;/p&gt;

&lt;p&gt;Nested IFs, no fallback, different shapes per arm, then a hopeful Merge.&lt;/p&gt;

&lt;p&gt;Swipe for how I keep routes readable — normalize first, decide once, merge with a contract.&lt;/p&gt;

&lt;p&gt;How many nested IFs are in your messiest production flow?&lt;/p&gt;

&lt;p&gt;Episode 12 of Ship with n8n: 20 builder skills.&lt;/p&gt;

</description>
      <category>automation</category>
      <category>ai</category>
      <category>productivity</category>
      <category>tools</category>
    </item>
    <item>
      <title>Failure paths on purpose (happy path is half the design)</title>
      <dc:creator>Khairul Muhtadin</dc:creator>
      <pubDate>Thu, 06 Aug 2026 11:00:00 +0000</pubDate>
      <link>https://dev.to/khmuhtadin/failure-paths-on-purpose-happy-path-is-half-the-design-1ol5</link>
      <guid>https://dev.to/khmuhtadin/failure-paths-on-purpose-happy-path-is-half-the-design-1ol5</guid>
      <description>&lt;p&gt;Happy path is not a full design.&lt;/p&gt;

&lt;p&gt;If money or customer-facing steps can fail silently, you have hope — not production.&lt;/p&gt;

&lt;p&gt;Swipe for how I wire failure on purpose, without the full node lecture in the caption.&lt;/p&gt;

&lt;p&gt;Which of your critical workflows still fails quietly?&lt;/p&gt;

&lt;p&gt;Episode 11 of Ship with n8n: 20 builder skills.&lt;/p&gt;

</description>
      <category>automation</category>
      <category>ai</category>
      <category>productivity</category>
      <category>tools</category>
    </item>
    <item>
      <title>APIs in production (rate limits, retries, Arc A milestone)</title>
      <dc:creator>Khairul Muhtadin</dc:creator>
      <pubDate>Tue, 04 Aug 2026 11:00:00 +0000</pubDate>
      <link>https://dev.to/khmuhtadin/apis-in-production-rate-limits-retries-arc-a-milestone-3a8l</link>
      <guid>https://dev.to/khmuhtadin/apis-in-production-rate-limits-retries-arc-a-milestone-3a8l</guid>
      <description>&lt;p&gt;Connecting an API in the editor is easy.&lt;/p&gt;

&lt;p&gt;Surviving rate limits, expired tokens, and retries is the real skill.&lt;/p&gt;

&lt;p&gt;Swipe for batch+wait patterns, idempotent upserts, and an Arc A milestone check.&lt;/p&gt;

&lt;p&gt;Would your flakiest integration survive a token refresh right now?&lt;/p&gt;

&lt;p&gt;Episode 10 of Ship with n8n: 20 builder skills.&lt;/p&gt;

</description>
      <category>automation</category>
      <category>ai</category>
      <category>productivity</category>
      <category>tools</category>
    </item>
    <item>
      <title>Build n8n Workflows with Indonesian Public Data Using the API Indonesia Community Node</title>
      <dc:creator>Khairul Muhtadin</dc:creator>
      <pubDate>Fri, 24 Jul 2026 11:00:00 +0000</pubDate>
      <link>https://dev.to/khmuhtadin/build-n8n-workflows-with-indonesian-public-data-using-the-api-indonesia-community-node-e63</link>
      <guid>https://dev.to/khmuhtadin/build-n8n-workflows-with-indonesian-public-data-using-the-api-indonesia-community-node-e63</guid>
      <description>&lt;h1&gt;
  
  
  Build n8n Workflows with Indonesian Public Data Using the API Indonesia Community Node
&lt;/h1&gt;

&lt;p&gt;Using an API in n8n is easy. Rebuilding the same HTTP Request setup for every workflow is the repetitive part: URLs, headers, API keys, parameters, and response mapping.&lt;br&gt;
The API Indonesia community node packages that work into a native n8n node. Instead of starting from a generic HTTP Request node, you select a resource and operation, configure its fields, and continue building your workflow.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the node supports
&lt;/h2&gt;

&lt;p&gt;The node exposes Indonesian public-data resources such as administrative regions, prayer times, earthquakes, weather, exchange rates, public holidays, postal codes, schools, universities, and hospitals.&lt;br&gt;
It also includes Quran, Bible, KBBI, vehicle plates, minimum wages, halal certification, BPOM products, Hijri calendar data, astronomy, OJK investment products, early warnings, Bank Indonesia exchange rates, validators, and utility endpoints.&lt;/p&gt;

&lt;h2&gt;
  
  
  Install the community node
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Open n8n.&lt;/li&gt;
&lt;li&gt;Go to Settings, then Community Nodes.&lt;/li&gt;
&lt;li&gt;Select Install.&lt;/li&gt;
&lt;li&gt;Enter n8n-nodes-api-indonesia.
After installation, search for &lt;strong&gt;API Indonesia&lt;/strong&gt; when adding a node to a workflow.
## Create credentials once
Open the API Indonesia dashboard and create or copy an API key. Then, in n8n, create a credential of type &lt;strong&gt;API Indonesia API&lt;/strong&gt; and paste the key. Production keys start with aip_live_.
The default base URL is &lt;a href="https://use.apiindonesia.id" rel="noopener noreferrer"&gt;https://use.apiindonesia.id&lt;/a&gt;. You only need to change it when working against a development or staging environment.
## Example: retrieve the latest earthquakes
A minimal workflow can be:
&lt;strong&gt;Manual Trigger → API Indonesia → next action&lt;/strong&gt;
In the API Indonesia node, choose the &lt;strong&gt;Gempa&lt;/strong&gt; resource and the operation for the latest earthquakes. The node returns the latest records, ready to send to a chat alert, database, dashboard, or a filtering step.
That is the important difference from a demo-only integration: the node output is normal n8n data, so it can continue through the same workflow patterns you already use.
## Where this is useful
Use it when a workflow needs Indonesian public data without manually recreating a request every time. Examples include daily prayer-time notifications, earthquake alerts, regional onboarding forms, weather-aware operations, halal product discovery, and enrichment flows for education or healthcare data.
Start small. Pick one resource, run it from a Manual Trigger, inspect the output, then connect it to the next useful action.
## Resources
Community node package: &lt;a href="https://www.npmjs.com/package/n8n-nodes-api-indonesia" rel="noopener noreferrer"&gt;https://www.npmjs.com/package/n8n-nodes-api-indonesia&lt;/a&gt;
API documentation: &lt;a href="https://docs.apiindonesia.id/" rel="noopener noreferrer"&gt;https://docs.apiindonesia.id/&lt;/a&gt;
API key dashboard: &lt;a href="https://dashboard.apiindonesia.id/" rel="noopener noreferrer"&gt;https://dashboard.apiindonesia.id/&lt;/a&gt;
&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>automation</category>
      <category>api</category>
      <category>tutorial</category>
      <category>showdev</category>
    </item>
  </channel>
</rss>
