<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[iTech Publication - Medium]]></title>
        <description><![CDATA[iTech Publication is an online platform for technical articles, software tutorials, and other technical information. - Medium]]></description>
        <link>https://medium.com/itech-publication?source=rss----3f55f0c0371---4</link>
        <image>
            <url>https://cdn-images-1.medium.com/proxy/1*TGH72Nnw24QL3iV9IOm4VA.png</url>
            <title>iTech Publication - Medium</title>
            <link>https://medium.com/itech-publication?source=rss----3f55f0c0371---4</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Thu, 12 Nov 2026 02:19:51 GMT</lastBuildDate>
        <atom:link href="https://medium.com/feed/itech-publication" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com/" rel="hub"/>
        <item>
            <title><![CDATA[Open Table Formats for Data Engineering: A Beginner’s Guide]]></title>
            <link>https://medium.com/itech-publication/open-table-formats-for-data-engineering-a-beginners-guide-a07d17439164?source=rss----3f55f0c0371---4</link>
            <guid isPermaLink="false">https://medium.com/p/a07d17439164</guid>
            <category><![CDATA[data-engineering]]></category>
            <category><![CDATA[delta-lake]]></category>
            <category><![CDATA[open-table-format]]></category>
            <category><![CDATA[apache-hudi]]></category>
            <category><![CDATA[apache-iceberg]]></category>
            <dc:creator><![CDATA[Adarsh Uppin]]></dc:creator>
            <pubDate>Fri, 30 Oct 2026 21:59:53 GMT</pubDate>
            <atom:updated>2026-10-30T21:59:51.782Z</atom:updated>
            <content:encoded><![CDATA[<p>What they are, why they exist, and how to start using them, with no prior lakehouse knowledge required.</p><p>An open table format is a set of rules for organising data files on cheap storage( like Amazon S3) so that they behave like proper database table. You get reliable updates, safe schema changes and “undo” features, while your data stays in open file formats that many tools can read. The best known open table formats are Apache Iceberg, Delta Lake and Apache Hudi.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*sMWbh86qCqhPt6MxD3PrqQ.png" /><figcaption>Image Generated by AI</figcaption></figure><h4>Start with the problem</h4><p>Modern data platforms often store data as files, usually in a columnar format called Parquet, sitting in cloud storage. This is cheap and flexible, and almost every analytics tool can read it. The approach is often called a data lake. But files in folder are not a database. Here is what goes wrong:</p><ul><li>Half-finished writes: If a job fails midway, readers may see some new files but not others, so the numbers are wrong.</li><li>No safe Updates: Files can’t be edited in place. Changing or deleting one row means finding and rewriting the right files yourself.</li><li>Two writers collide: If two jobs write at the same time, nothing stops them from overwriting each other.</li><li>Slow Discovery: To answer “ which files belong to this table?”, a tool has to list every file in the folder, which gets slow with millions of files.</li><li>Painful schema changes: Adding, renaming or removing a column can leave old and new files out of sync.</li></ul><h4>How an open table format works</h4><p>Almost every open table format follows the same four ideas:</p><ul><li>Data fils stay as they are. Your rows are still stored in Parquet files. They never edited in place.</li><li>Metadata Describes the table. Extra files record the table’s schema, how it is partitioned, which data files currently belong to it and statistics about each file.</li><li>Each change creates a new version. Writing data produces new files and a new snapshot: a record of exactly which files make up the table at that moment. Old snapshots remain until you remove them.</li><li>Commits are atomic. A job writes its new files first and only then makes them visible in a single all-or-nothing step. Readers see either the old version or the new one, never something in between. If two jobs try to commit at once, one notices the conflict and retries oor fails safely.</li></ul><h4>The benefits</h4><ul><li>ACID transactions: Changes either fully happen or don’t happen at all, and concurrent users don’t see other’s unfinished work.</li><li>Updates, deletes and merges: You can change individual rows with normal SQL.</li><li>Schema Evolution: Add or Rename columns without rewriting everything.</li><li>Time Travel: Query an earlier version of the table or rollback a mistake.</li><li>Faster Queries: Engines use the metadata and file statistics to skip files that can’t contain the data they need, instead of scanning everything.</li></ul><h4>Do you need one?</h4><p>An open table format is a good fit when:</p><ul><li>Your data lives in cloud object storage and you need to update or delete rows.</li><li>Several jobs or people read and write the same tables.</li><li>You want auditability, rollbacks or the ability to change schemas safely.</li><li>You want several tools or engines to share the same data.</li></ul><p>It may be overkill if you only append small static files that a single job reads, or if your data already lives happily in a traditional database or warehouse that meets your needs.</p><p>Open Table formats take the cheap, flexible world of data files and give it the reliability of a database: safe concurrent writes, row-level changes, schema evolution and time travel. They work by adding a layer of metadata that tracks exactly which files make up a table at each points in time and by committing changes atomically.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=a07d17439164" width="1" height="1" alt=""><hr><p><a href="https://medium.com/itech-publication/open-table-formats-for-data-engineering-a-beginners-guide-a07d17439164">Open Table Formats for Data Engineering: A Beginner’s Guide</a> was originally published in <a href="https://medium.com/itech-publication">iTech Publication</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[NumPy Beyond Basics: Broadcasting, Boolean Masking, Fancy Indexing and Powerful Array Techniques]]></title>
            <link>https://medium.com/itech-publication/numpy-beyond-basics-broadcasting-boolean-masking-fancy-indexing-and-powerful-array-techniques-5ea384971922?source=rss----3f55f0c0371---4</link>
            <guid isPermaLink="false">https://medium.com/p/5ea384971922</guid>
            <category><![CDATA[boolean-masking]]></category>
            <category><![CDATA[python]]></category>
            <category><![CDATA[fancy-indexing]]></category>
            <category><![CDATA[broadcasting]]></category>
            <category><![CDATA[numpy]]></category>
            <dc:creator><![CDATA[Adarsh Uppin]]></dc:creator>
            <pubDate>Tue, 08 Sep 2026 01:48:39 GMT</pubDate>
            <atom:updated>2026-09-08T01:48:37.776Z</atom:updated>
            <content:encoded><![CDATA[<p>Numpy is the backbone of the numerical computing in Python and is widely used in Data Science, Machine Learning and Scientific Computations. While many developers are familiar with basic array operations, Numpy becomes truly powerful when you start using its advanced features.</p><p>In this article, we’ll explore these NumPy techniques along with concepts like Advanced Broadcasting, Views vs Copies, and Stride tricks to help you write more efficient numerical code in Python.</p><blockquote><strong>Vectorization</strong></blockquote><p>This is the feature which answers why numpy is fast and also forms a builiding blocks for features like Broadcasting and Boolean Masking.</p><p>Vectorization means performing operations on <strong>entire arrays instead of loops</strong>.</p><pre>// Traditional python approach<br><br>import numpy as np<br>arr=np.arange(10000)<br><br>result=[]<br>for x in arr:<br>      result.append(x*2)</pre><pre>//NumPy Vectorized Version <br>result = arr * 2<br><br>//NumPy performs this in compiled C code, making it much faster.</pre><h3>Broadcasting</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*8uc1uNh67dG4_boVs-sP-g.png" /><figcaption>Image Generated with AI</figcaption></figure><p>Broadcasting is a mechanism in Numpy that allows arrays of different shapes to perform arithmetic operations together without explicitly reshaping or copying data. <br>In simple terms, Numpy automatically expands the smaller array across the larger array so that element-wise operations like addition, subtraction or multiplication can be performed. <br>This eliminates the need of manual loops or repetitive data, making computations both faster and more memory-efficient.</p><pre>//Broadcasting is even more powerful when working with <br>//multi-dimensional arrays.<br>matrix = np.array([<br>    [1, 2, 3],<br>    [4, 5, 6]<br>])<br><br>vector = np.array([10, 20, 30])<br><br>result = matrix + vector<br>print(result)<br><br>//Output<br>[[11 22 33]<br> [14 25 36]]</pre><h3>Boolean Masking</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*BQ4hypNax5aBAmvTSIJPgg.png" /><figcaption>Image Generated with AI</figcaption></figure><p>Numpy allows to select, filter or modify elements in an array based on a condition, this technique is Boolean Masking. Numpy allows you to generate a boolean array(True/ False) by applying a specific condition to entire array at once. This Boolean array acts as mask that determines which elements need to be selected. <br>Boolean masking supports creation of multi conditioned arrays. This can be practically used in Data Cleaning steps.</p><pre>//Boolean masking is widely used in data preprocessing and cleaning.<br>import numpy as np<br>data = np.array([120, 150, -1, 200, -5, 180])<br><br>clean_data = data[(data&gt;=0) &amp; (data &lt;200)]<br><br>print(clean_data)</pre><pre>//modifying using boolean masking <br>import numpy as np<br>arr=np.array([10,30,48,-2,-5,1000])<br><br>arr[arr&gt;15]=0<br><br>print(arr) // prints [10,0,0,-2,-5]</pre><h3>Fancy Indexing</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*MAxAyYgY_WJeYI1QCnvAeg.png" /><figcaption>Image Generated with AI</figcaption></figure><p>Fancy Indexing allows you to <strong>select specific elements from an array using lists or arrays of indices</strong>. Unlike slicing the Fancy Indexing allows to select non- consecutive elements effortlessly.<br>It works efficiently with multi-dimensional array and also extracts the subsets quickly.</p><pre>import numpy as np<br>arr=np.array([10,30,-34,4,67])<br><br>idx=[1,0,4]<br>result=arr[idx]<br>print(result) //[30,10,67]</pre><pre>// Fancy Indexing with Multi-dimensional arrays<br>matrix = np.array([<br>    [10, 20],<br>    [30, 40],<br>    [50, 60]<br>])<br><br>rows=[0,1,2]<br>cols[0,1,1]<br><br>result=matrix[rows,cols]<br>print(result) // [10,40,60]</pre><p><strong>Slicing vs Fancy Indexing<br></strong>Fancy Indexing is usually used for selecting the non -contiguous elements from an array. Where as Slicing is used for selecting contiguous elements of an array. <br>Fancy Indexing returns <strong>the copy of the original array.</strong> On the other hand, Slicing returns the<strong> view of the original array </strong>meaning both the arrays share same memory.</p><h3>Where Function</h3><p>The np.where() function is used for <strong>conditional selection in NumPy arrays</strong>. It works like a <strong>vectorized if–else statement</strong>, allowing you to apply a condition to every element in an array and return values based on whether the condition is <strong>True or False</strong>.</p><pre>//The basic syntax:<br>np.where(condition, value_if_true, value_if_false)</pre><p>Instead of writing loops and conditional statements for each element, np.where() lets NumPy handle the operation <strong>efficiently across the entire array</strong>.</p><pre>//It can be used for Data categorization<br>import numpy as np<br>scores=np.array([45, 72, 88, 33, 60])<br><br>result = np.where(scores &gt;= 50, &quot;Pass&quot;, &quot;Fail&quot;)<br>print(result)</pre><h3>NumPy Views vs Copies</h3><p>One important concept in NumPy that many beginners miss is the difference between <strong>views</strong> and <strong>copies</strong> of arrays. Understanding this helps you avoid <strong>unexpected bugs and unnecessary memory usage</strong>.</p><p>Copy: A <strong>copy</strong> creates a completely new array in memory. Changes to the copied array <strong>do not affect the original array</strong>.</p><pre>import numpy as np<br><br>arr = np.array([1, 2, 3, 4])<br><br>copy_arr = arr.copy()<br><br>copy_arr[0] = 100<br><br>print(&quot;Original:&quot;, arr)<br>print(&quot;Copy:&quot;, copy_arr)</pre><p>View: A <strong>view</strong> does not create new memory. Instead, it <strong>references the same underlying data</strong>.</p><pre>arr = np.array([1, 2, 3, 4])<br><br>view_arr = arr.view()<br><br>view_arr[0] = 100<br><br>print(&quot;Original:&quot;, arr)<br>print(&quot;View:&quot;, view_arr)</pre><p>Checking if an array is view</p><pre>print(view_arr.base)<br>//If .base is not None, the array is a view of another array.</pre><h3>Conclusion</h3><p>NumPy is much more than just arrays. Features like <strong>broadcasting, boolean masking, fancy indexing, and vectorization</strong> make it a powerful tool for numerical computing.</p><p>Mastering these techniques allows developers and data scientists to write <strong>high-performance code with minimal effort</strong>.</p><p>If you’re working with <strong>data analysis, machine learning, or scientific computing</strong>, these NumPy concepts are essential tools in your toolkit.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=5ea384971922" width="1" height="1" alt=""><hr><p><a href="https://medium.com/itech-publication/numpy-beyond-basics-broadcasting-boolean-masking-fancy-indexing-and-powerful-array-techniques-5ea384971922">NumPy Beyond Basics: Broadcasting, Boolean Masking, Fancy Indexing and Powerful Array Techniques</a> was originally published in <a href="https://medium.com/itech-publication">iTech Publication</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Parquet Files Explained: Why Every Data Engineer should Use]]></title>
            <link>https://medium.com/itech-publication/parquet-files-explained-why-every-data-engineer-should-use-f06313457846?source=rss----3f55f0c0371---4</link>
            <guid isPermaLink="false">https://medium.com/p/f06313457846</guid>
            <category><![CDATA[python]]></category>
            <category><![CDATA[big-data]]></category>
            <category><![CDATA[apache-parquet]]></category>
            <category><![CDATA[data-science]]></category>
            <category><![CDATA[data-engineering]]></category>
            <dc:creator><![CDATA[Adarsh Uppin]]></dc:creator>
            <pubDate>Wed, 02 Sep 2026 14:47:10 GMT</pubDate>
            <atom:updated>2026-09-02T14:47:09.193Z</atom:updated>
            <content:encoded><![CDATA[<p>If you’ve worked with data for more than a few months, you’ve probably heard someone say “just save it as Parquet.” But why? What makes this file format so special that it has become the default in Data Engineering, Analytics, and Machine Learning pipelines? <br>This article skips the marketing fluff and gets into mechanics — with actual code, actual file sizes, and actual query times.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*DrUHQrGJEueRgC3UJ8kiVg.png" /><figcaption>Image Generated with AI</figcaption></figure><h4>What is Parquet, Really?</h4><p>Apache Parquet is a columnar storage file format. That one word — columnar — explains almost everything about why it’s fast. <br>Traditional formats like CSV and JSON are row-oriented: they store data record by record, the way you’d type it into a spreadsheet.</p><pre>//Traditional formats<br>id, name, age, city<br>1, Alice, 29, NYC<br>2, Bob, 34, LA<br>3, Carol, 41, SF<br><br>//Parquet flips this and stores data by column by column:<br>id: [1,2,3]<br>name: [Alice, Bob, Carol]<br>age: [29, 34, 41]<br>city:[NYC, LA, SF]</pre><h4>Why Columnar Storage Wins</h4><ol><li><strong>You only read what you need. </strong>If your query is SELECT <em>age</em> FROM <em>users</em>, a row-based format still has to scan every row, pulling in <em>id</em>, <em>name</em>, and <em>city</em> you never asked for. Parquet reads only <em>age</em> column.</li><li><strong>Compression gets dramatically better.</strong> A column of <em>ages</em> (29, 34, 41, 29, 34…) is far more repetitive and compressible than a mixed row of strings and numbers. Parquet applies type-specific encoding (dictionary encoding, run-length encoding, bit-packing) on top of compression codes like Snappy, Gzip or Zstd.</li><li><strong>Predictive pushdown.</strong> Parquet stores min/ max statistics per column chunk, so query engines can skip entire blocks of data without reading them — e.g., “this row-group’s max age is 25, skip it if I am filtering for age &gt; 30.”</li><li><strong>Schema is embedded. </strong>Unlike CSV, a Parquet file knows its own column types. No more guessing whether “007” is a string or an integer.</li></ol><h4>Parquet vs CSV vs JSON vs Avro — The Real Comparison</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*0euI_QqsWVTYbXmpH2AJTg.jpeg" /><figcaption>Image Generated with AI</figcaption></figure><h4>Hands-On: Let’s Prove It With Numbers</h4><p>Let’s stop talking and generate some real data. I’ll create a 1-million- row dataset and compare file size and query speed across formats.</p><h4>Setup</h4><pre>import pandas as pd <br>import numpy as np <br>import time<br>import os <br><br># this will generate  1 million rows of real data <br>np.random.seed(42)<br>n=1_000_000<br>df=pd.DataFrame({<br>    &quot;user_id&quot;: np.arange(n),<br>    &quot;age&quot;: np.random.randint(18,80,n),<br>    &quot;country&quot;: np.random.choice([&quot;US&quot;, &quot;UK&quot;, &quot;IN&quot;, &quot;DE&quot;, &quot;BR&quot;],n),<br>    &quot;signup_date&quot;: pd.date_range(&quot;2020-01-01&quot;,periods=n,freq=&quot;min&quot;),<br>    &quot;purchase_amount&quot;: np.round(np.random.uniform(5,500,n),2),<br>})<br>df.to_csv(&quot;data.csv&quot;,index=False)<br>df.to_json(&quot;data.json&quot;,orient=&quot;records&quot;, lines=True)<br>df.to_parquet(&quot;data.parquet&quot;,engine=&quot;pyarrow&quot;, compression=&quot;snappy&quot;)<br><br>for f in [&quot;data.csv&quot;, &quot;data.json&quot;, &quot;data.parquet&quot;]:<br>    size_mb=os.path.getsize(f)/(1024*1024)<br>    print(f&quot;{f}: {size_mb:.2f} MB&quot;)</pre><pre>#Typical Output<br><br>data.csv: 52.10 MB<br>data.json: 98.40 MB<br>data.parquet: 11.30 MB <br><br># Numbers may change </pre><h4>Query Speed: Reading a Single Column</h4><p>CSV has to parse the entire file line by line even though we only wanted one column. Parquet jumps straight to th ecolumn’s byte range on disk. That’s roughly a 20x speedup — and the gap grows as the dataset grows.</p><pre>start=time.time()<br>pd.read_csv(&quot;data.csv&quot;,usecols=[&quot;purchase_amount&quot;])<br>print(f&quot;CSV: {time.time()-start:.3f}s&quot;)<br><br>start=time.time()<br>pd.read_parquet(&quot;data.parquet&quot;,usecols=[&quot;purchase_amount&quot;])<br>print(f&quot;Parquet: {time.time()-start:.3f}s&quot;)<br><br>**********************<br>#Typical output<br>CSV: 0.480s<br>Parquet: 0.021s</pre><h4>Filtering With Predicate Pushdown</h4><p>This is Parquet’s real superpower for big data. Using pyArrow, filters can be applied while reading, so unnecessary data is never ever loaded into memory. <br>There is no CSV equivalent to this. With CSV you must read everything into memory first, then filter with pandas. With Parquet, the filtering happens at the storage layer.</p><pre>import pyarrow.parquet as pq<br>import pyarrow.dataset as ds<br><br>dataset=ds.dataset(&quot;data.parquet&quot;, format=&quot;parquet&quot;)<br><br>table =dataset.to_table(<br>  filter=(ds.field(&quot;country&quot;)==&quot;IN&quot;) &amp; (ds.field(&quot;age&quot;)&gt;40),<br>  columns=[&quot;user_id&quot;, &quot;age&quot;, &quot;country&quot;]<br>)<br><br>print(table.num_rows)</pre><h4>When Parquet Is Not the Right Choice</h4><ol><li>Frequent small writes/streaming inserts — Parquet files are meant to be written once and read many times. Constantly appending single rows is inefficient; use a row-based format (Avro) or a database instead, then batch-convert to Parquet periodically.</li><li>Human debugging — You can’t <em>cat</em> a parquet file and read it. You need a tool (parquet-tools, pandas, DuckDB) to inspect it.</li><li>Small datasets (a few KB-MB) — the overhead of Parquet’s metadata and schema isn’t worth it for a 200- row config file. CSV or JSON is simpler.</li><li>Nested/ Rapidly changing schemas from external APIs — JSON is often more convinient during ingestion, then converted to Parquet afterward.</li></ol><h4>Final Thoughts</h4><p>Parquet isn’t just a “a faster CSV.” It’s a fundamentally different way of thinking about how data sits on disk — optimized for the reality that most analytical queries touch a handful of columns and millions of rows, not the other way around. <br>If you are still defaulting to CSV for anything beyond a quick export, the numbers above make a pretty strong case for switching. Try it on your own dataset — the size and speed difference is usually immediate and obvious.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=f06313457846" width="1" height="1" alt=""><hr><p><a href="https://medium.com/itech-publication/parquet-files-explained-why-every-data-engineer-should-use-f06313457846">Parquet Files Explained: Why Every Data Engineer should Use</a> was originally published in <a href="https://medium.com/itech-publication">iTech Publication</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Integrating Meta’s WhatsApp Cloud API]]></title>
            <link>https://medium.com/itech-publication/integrating-metas-whatsapp-cloud-api-094e54616657?source=rss----3f55f0c0371---4</link>
            <guid isPermaLink="false">https://medium.com/p/094e54616657</guid>
            <category><![CDATA[erp-solutions]]></category>
            <category><![CDATA[itech-publication]]></category>
            <category><![CDATA[whatsapp-cloud-api]]></category>
            <category><![CDATA[odoo-erp]]></category>
            <category><![CDATA[technology]]></category>
            <dc:creator><![CDATA[Tech Bytes by Kris]]></dc:creator>
            <pubDate>Mon, 13 Jul 2026 22:13:38 GMT</pubDate>
            <atom:updated>2026-07-13T22:13:37.011Z</atom:updated>
            <content:encoded><![CDATA[<h4>How I Integrated WhatsApp with Odoo (Step by Step Tutorial)</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*ymcjZ3y63BdJrBz4.png" /></figure><p>If you have ever tried to navigate the Meta Developer Ecosystem, you know it can feel like a maze. Between Business Portfolios, App Scopes, and Webhook handshakes, things can get confusing quickly.</p><p>Recently, I took on the challenge of integrating <strong>Meta’s WhatsApp Cloud API</strong> with an <strong>Odoo ERP backend</strong> for an enterprise use case (<strong>Ipawa Tech Solutions</strong>). The goal was to build a seamless communication pipeline where client WhatsApp messages route directly into Odoo’s CRM and project chatter, and automated service updates route back to the client.</p><p>It was a journey filled with classic Meta redirects, hidden settings If you are trying to wire up this integration yourself, here is the exact, error-free roadmap of how I did it so you can get it right on the first try.</p><h3>The Big Picture Workflow</h3><p>Before diving into the code and configurations, it helps to understand how these tools talk to each other:</p><pre>+-----------------------+                    +-------------------------+<br>  |  Meta Developer App   | &lt;--- Webhook ----&gt; |    Odoo ERP Backend     |<br>  | (WhatsApp Cloud API)  |                    | (WhatsApp Module/Apps)  |<br>  +-----------------------+                    +-------------------------+<br>              ^                                             ^<br>              | (Sandbox Mode)                              |<br>              v                                             v<br>     [Verified Test Phone]                        [Contacts &amp; Discuss App]</pre><h3>Phase 1: Navigating the Meta Developer Maze</h3><p>The journey started on the <a href="https://developers.facebook.com/"><strong>Meta for Developers</strong></a> platform.</p><h3>1. Creating the App Blueprint</h3><p>First, I created a new application. Meta forces you to choose a use case framework right out of the gate. For this integration, select <strong>Connect with customers through WhatsApp</strong>.</p><h3>2. The Business Portfolio Link</h3><p>During creation, you have to link the app to a <strong>Meta Business Portfolio</strong>. If your UI boots you out to your personal Facebook feed after clicking create (a classic Meta glitch!), don’t panic. Simply head back to developers.facebook.com, click <strong>My Apps</strong> in the top right, and your newly created app workspace will be waiting for you.</p><h3>3. Activating the WhatsApp Product</h3><p>Inside the app dashboard:</p><ul><li>Navigate to <strong>Use cases</strong> in the left sidebar.</li><li>Find the WhatsApp card and click <strong>Set Up</strong>.</li><li><em>Pro Tip:</em> If the dashboard screen looks completely blank after setting it up, click <strong>Quickstart</strong> right above <em>API Setup</em> to run Meta’s 1-minute initialization wizard. This forces the cloud environment to spin up.</li></ul><p>Once initialized, navigate to <strong>WhatsApp &gt; API Setup</strong>. Keep this tab open — this is your goldmine for credentials.</p><h3>Phase 2: Preparing the Odoo Engine</h3><p>With the Meta keys ready, it was time to jump into the Odoo backend.</p><h3>1. Installing the Dependencies</h3><p>By default, Odoo’s settings won’t show WhatsApp configurations until the underlying application module is active.</p><ul><li>Head to the Odoo <strong>Apps</strong> dashboard.</li><li>Clear the default “Apps” search filter, type WhatsApp, and hit the purple <strong>Activate/Install</strong> button.</li></ul><h3>2. Mapping the API Credentials</h3><p>Once the module finishes installing, go to <strong>Settings</strong>, search for WhatsApp in the top utility bar, and click → Configure WhatsApp Business Accounts. Click <strong>New</strong> to open a clean provider profile.</p><p>This is where the magic happens. I mapped the credentials from the Meta Developer tab into Odoo using this exact matrix:</p><p><strong>Odoo Configuration FieldMeta Developer Workspace Source LocationAccount Name</strong>Ipawa Tech Solutions (or your custom business name)<strong>App ID</strong>Prominently displayed at the very top header bar of your Meta App.<strong>App Secret</strong>Go to <strong>App settings &gt; Basic</strong> on Meta. Click <em>Show</em> (requires your FB password).<strong>Token</strong>The <strong>Temporary Access Token</strong> sitting at the top of the <em>API Setup</em> panel.<strong>Phone Number ID</strong>Found under Step 1 of the Meta <em>API Setup</em> page.<strong>WhatsApp Business Account ID</strong>Found directly below the Phone Number ID in Step 1.</p><p>With everything filled out, I hit <strong>Test Credentials</strong> in the bottom left. When that connection status icon flashes green, it’s an incredibly satisfying feeling!</p><h3>Phase 3: The Webhook Handshake (Two-Way Sync)</h3><p>Getting Odoo to send messages is only half the battle. We also need Odoo to <em>receive</em> messages when a customer replies. This requires a secure Webhook handshake.</p><p>Once Odoo successfully tests the credentials, it automatically generates two unique values at the bottom of the form: a <strong>Callback URL</strong> and a <strong>Verification Token</strong>.</p><ol><li>Copy those values and switch back to the <strong>Meta Developer tab</strong>.</li><li>On the left sidebar under WhatsApp, click <strong>Configuration</strong>.</li><li>In the <strong>Webhooks</strong> section, click <strong>Edit</strong>, paste the URL and token from Odoo, and click <strong>Verify and Save</strong>.</li></ol><blockquote><em>⚠️ </em><strong><em>The Crucial Step Most People Miss:</em></strong><em> After saving the webhook, a list of Webhook fields will appear. Look for the field named </em><em>messages and click </em><strong><em>Subscribe</em></strong><em>. If you don’t turn this on, Meta will never forward incoming client messages back to your Odoo database!</em></blockquote><h3>Phase 4: Overcoming Sandbox Restrictions &amp; Live Testing</h3><p>Because my Meta application is still in <strong>Development Mode</strong>, Meta locks down the environment to prevent accidental spam. Testing required navigating two explicit safety rules:</p><h3>1. Whitelisting the Test Number</h3><p>The sandbox will <em>only</em> talk to phone numbers you explicitly authorize. On the Meta <strong>API Setup</strong> page, find the <strong>To</strong> field dropdown under Step 1, click <strong>Manage phone number list</strong>, add your personal phone number, and type in the verification code Meta sends you via WhatsApp.</p><h3>2. Synchronizing Business Templates</h3><p>Meta prohibits businesses from sending arbitrary, plain-text messages to open a new conversation thread. You must use a pre-approved template.</p><ul><li>In Odoo, inside your WhatsApp Provider profile, click the 🔄 Synchronize Templates button at the top left.</li><li>Odoo instantly fetches Meta’s default sandbox templates (like the standard welcome greeting) and updates their status to <strong>Approved</strong>.</li></ul><h3>3. Firing the Live Test!</h3><p>With everything wired:</p><ol><li>I opened the Odoo <strong>Contacts</strong> app and created a test contact using my verified personal number (formatted with the country code, e.g., +254...).</li><li>Clicked the inline <strong>WhatsApp</strong> action icon on the contact file.</li><li>Selected the newly synchronized welcome template and hit <strong>Send</strong>.</li></ol><p>Within seconds, my phone buzzed with the template message!</p><p>To test the inbound loop, I texted back: <em>“Systems are live!”</em>. I went over to the Odoo <strong>Discuss</strong> app, and there it was — a brand new live chat thread containing my text response, completely integrated into the ERP ecosystem.</p><h3>Key Takeaways From This Build</h3><ol><li><strong>Mind the Token Expiration:</strong> Temporary developer tokens provided by Meta expire every <strong>24 hours</strong>. For a production environment, you’ll need to upgrade to a Permanent Access Token via a Meta System User profile.</li><li><strong>Subscribing is Key:</strong> A green webhook test configuration doesn’t mean data is flowing. Never forget to manually subscribe to the messages event webhook field.</li><li><strong>Architecture Matters:</strong> Keeping business logic inside Odoo while offloading the communication transport layer to Meta keeps the architecture incredibly clean and scalable.</li></ol><p>Building this integration taught me exactly how rigid, yet powerful, enterprise API frameworks can be. Next up on my radar: configuring Odoo’s automated sales workflows so that when a new customer completes an order, it auto-generates developer tasks and drops an update directly to their WhatsApp.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*DXLXqiNMBZMi26n2.png" /></figure><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=094e54616657" width="1" height="1" alt=""><hr><p><a href="https://medium.com/itech-publication/integrating-metas-whatsapp-cloud-api-094e54616657">Integrating Meta’s WhatsApp Cloud API</a> was originally published in <a href="https://medium.com/itech-publication">iTech Publication</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Building an End-to-End Geospatial Data Pipeline with Python]]></title>
            <description><![CDATA[<div class="medium-feed-item"><p class="medium-feed-image"><a href="https://medium.com/itech-publication/building-an-end-to-end-geospatial-data-pipeline-with-python-448d29ea1a12?source=rss----3f55f0c0371---4"><img src="https://cdn-images-1.medium.com/max/801/1*RMKRf-9wMQP3ktTYVJQQ0A.png" width="801"></a></p><p class="medium-feed-snippet">From Raw CSV Files to an Analysis-Ready Map Dataset</p><p class="medium-feed-link"><a href="https://medium.com/itech-publication/building-an-end-to-end-geospatial-data-pipeline-with-python-448d29ea1a12?source=rss----3f55f0c0371---4">Continue reading on iTech Publication »</a></p></div>]]></description>
            <link>https://medium.com/itech-publication/building-an-end-to-end-geospatial-data-pipeline-with-python-448d29ea1a12?source=rss----3f55f0c0371---4</link>
            <guid isPermaLink="false">https://medium.com/p/448d29ea1a12</guid>
            <category><![CDATA[geospatial]]></category>
            <category><![CDATA[gis]]></category>
            <category><![CDATA[itech-publication]]></category>
            <category><![CDATA[data-pipeline]]></category>
            <category><![CDATA[python]]></category>
            <dc:creator><![CDATA[Vishali]]></dc:creator>
            <pubDate>Mon, 29 Jun 2026 04:13:06 GMT</pubDate>
            <atom:updated>2026-06-29T04:13:05.965Z</atom:updated>
        </item>
        <item>
            <title><![CDATA[Common Spatial Data Engineering Tasks]]></title>
            <description><![CDATA[<div class="medium-feed-item"><p class="medium-feed-image"><a href="https://medium.com/itech-publication/common-spatial-data-engineering-tasks-138a1ca3043b?source=rss----3f55f0c0371---4"><img src="https://cdn-images-1.medium.com/max/648/1*Jl026ow73V_-PE7Xe-oHTQ.png" width="648"></a></p><p class="medium-feed-snippet">Raster Data Processing Using Python Libraries</p><p class="medium-feed-link"><a href="https://medium.com/itech-publication/common-spatial-data-engineering-tasks-138a1ca3043b?source=rss----3f55f0c0371---4">Continue reading on iTech Publication »</a></p></div>]]></description>
            <link>https://medium.com/itech-publication/common-spatial-data-engineering-tasks-138a1ca3043b?source=rss----3f55f0c0371---4</link>
            <guid isPermaLink="false">https://medium.com/p/138a1ca3043b</guid>
            <category><![CDATA[rasterio]]></category>
            <category><![CDATA[itech-publication]]></category>
            <category><![CDATA[spatial-engineering]]></category>
            <category><![CDATA[spatial-data-engineering]]></category>
            <category><![CDATA[gis]]></category>
            <dc:creator><![CDATA[Vishali]]></dc:creator>
            <pubDate>Sun, 14 Jun 2026 21:01:08 GMT</pubDate>
            <atom:updated>2026-06-14T21:29:13.271Z</atom:updated>
        </item>
        <item>
            <title><![CDATA[How to Download Topographic Data from OpenTopography]]></title>
            <description><![CDATA[<div class="medium-feed-item"><p class="medium-feed-image"><a href="https://medium.com/itech-publication/how-to-download-topographic-data-from-opentopography-4c733f0d058c?source=rss----3f55f0c0371---4"><img src="https://cdn-images-1.medium.com/max/975/1*QsuQkaXIAS-J8hgba5EWSg.png" width="975"></a></p><p class="medium-feed-snippet">Digital Elevation Models (DEMs) and LiDAR data are essential for a wide range of applications, including hydrological modeling, watershed&#x2026;</p><p class="medium-feed-link"><a href="https://medium.com/itech-publication/how-to-download-topographic-data-from-opentopography-4c733f0d058c?source=rss----3f55f0c0371---4">Continue reading on iTech Publication »</a></p></div>]]></description>
            <link>https://medium.com/itech-publication/how-to-download-topographic-data-from-opentopography-4c733f0d058c?source=rss----3f55f0c0371---4</link>
            <guid isPermaLink="false">https://medium.com/p/4c733f0d058c</guid>
            <category><![CDATA[raster]]></category>
            <category><![CDATA[itech-publication]]></category>
            <category><![CDATA[lidar]]></category>
            <category><![CDATA[topographic-maps]]></category>
            <category><![CDATA[gis]]></category>
            <dc:creator><![CDATA[Vishali]]></dc:creator>
            <pubDate>Sun, 07 Jun 2026 22:12:27 GMT</pubDate>
            <atom:updated>2026-06-07T22:12:26.698Z</atom:updated>
        </item>
        <item>
            <title><![CDATA[Determining the potential for solar power generation.]]></title>
            <description><![CDATA[<div class="medium-feed-item"><p class="medium-feed-image"><a href="https://medium.com/itech-publication/determining-the-potential-for-solar-power-generation-454bf9240606?source=rss----3f55f0c0371---4"><img src="https://cdn-images-1.medium.com/max/2600/1*A-hZGZhDHuiyBb-40z0beQ.jpeg" width="6000"></a></p><p class="medium-feed-snippet">Using Solar Radiation toolset available in ArcGIS Pro</p><p class="medium-feed-link"><a href="https://medium.com/itech-publication/determining-the-potential-for-solar-power-generation-454bf9240606?source=rss----3f55f0c0371---4">Continue reading on iTech Publication »</a></p></div>]]></description>
            <link>https://medium.com/itech-publication/determining-the-potential-for-solar-power-generation-454bf9240606?source=rss----3f55f0c0371---4</link>
            <guid isPermaLink="false">https://medium.com/p/454bf9240606</guid>
            <category><![CDATA[solar-potential]]></category>
            <category><![CDATA[arcgis]]></category>
            <category><![CDATA[solar-energy]]></category>
            <category><![CDATA[esri]]></category>
            <category><![CDATA[arcgis-pro]]></category>
            <dc:creator><![CDATA[Vishali]]></dc:creator>
            <pubDate>Sun, 18 Feb 2024 21:08:12 GMT</pubDate>
            <atom:updated>2025-07-01T14:17:24.688Z</atom:updated>
        </item>
        <item>
            <title><![CDATA[The Government’s Controversial Nuclear Waste Mound Plan Sparks Concerns.]]></title>
            <description><![CDATA[<div class="medium-feed-item"><p class="medium-feed-image"><a href="https://medium.com/itech-publication/governments-controversial-nuclear-waste-mound-plan-sparks-concerns-1cd748dde5b8?source=rss----3f55f0c0371---4"><img src="https://cdn-images-1.medium.com/max/1647/1*Fwr8NabECjul0QcbJWrI1g.png" width="1647"></a></p><p class="medium-feed-snippet">Is the Near Surface Disposal Facility (NSDF) at Chalk River Laboratories a Permanent Solution for Low-Level Radioactive Waste?</p><p class="medium-feed-link"><a href="https://medium.com/itech-publication/governments-controversial-nuclear-waste-mound-plan-sparks-concerns-1cd748dde5b8?source=rss----3f55f0c0371---4">Continue reading on iTech Publication »</a></p></div>]]></description>
            <link>https://medium.com/itech-publication/governments-controversial-nuclear-waste-mound-plan-sparks-concerns-1cd748dde5b8?source=rss----3f55f0c0371---4</link>
            <guid isPermaLink="false">https://medium.com/p/1cd748dde5b8</guid>
            <category><![CDATA[nsdf]]></category>
            <category><![CDATA[indigenous]]></category>
            <category><![CDATA[deep-river]]></category>
            <category><![CDATA[radioactive-waste]]></category>
            <category><![CDATA[chalkriver]]></category>
            <dc:creator><![CDATA[Vishali]]></dc:creator>
            <pubDate>Sun, 18 Feb 2024 21:06:41 GMT</pubDate>
            <atom:updated>2024-06-19T18:10:35.393Z</atom:updated>
        </item>
        <item>
            <title><![CDATA[Are the reduced supply and increased demand from immigration the only reason for escalating Toronto…]]></title>
            <description><![CDATA[<div class="medium-feed-item"><p class="medium-feed-image"><a href="https://medium.com/itech-publication/are-the-reduced-supply-and-increased-demand-from-immigration-the-only-reason-for-escalating-toronto-12c6643a1fe6?source=rss----3f55f0c0371---4"><img src="https://cdn-images-1.medium.com/max/2600/1*eTJZNsSYUVm2cCxcBTknnw.jpeg" width="2920"></a></p><p class="medium-feed-snippet">Do High-skilled immigrant preferences and opportune landlords have a role in this?</p><p class="medium-feed-link"><a href="https://medium.com/itech-publication/are-the-reduced-supply-and-increased-demand-from-immigration-the-only-reason-for-escalating-toronto-12c6643a1fe6?source=rss----3f55f0c0371---4">Continue reading on iTech Publication »</a></p></div>]]></description>
            <link>https://medium.com/itech-publication/are-the-reduced-supply-and-increased-demand-from-immigration-the-only-reason-for-escalating-toronto-12c6643a1fe6?source=rss----3f55f0c0371---4</link>
            <guid isPermaLink="false">https://medium.com/p/12c6643a1fe6</guid>
            <category><![CDATA[itech-publication]]></category>
            <category><![CDATA[spatial-analysis]]></category>
            <category><![CDATA[gis]]></category>
            <category><![CDATA[toronto-real-estate]]></category>
            <category><![CDATA[rental]]></category>
            <dc:creator><![CDATA[Vishali]]></dc:creator>
            <pubDate>Thu, 09 Mar 2023 15:14:29 GMT</pubDate>
            <atom:updated>2023-03-12T13:59:59.056Z</atom:updated>
        </item>
    </channel>
</rss>