<?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: Mediavox</title>
    <description>The latest articles on DEV Community by Mediavox (@mediavox).</description>
    <link>https://dev.to/mediavox</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%2F3974744%2F48a07730-8901-4ea2-ae7a-10b20541171c.png</url>
      <title>DEV Community: Mediavox</title>
      <link>https://dev.to/mediavox</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/mediavox"/>
    <language>en</language>
    <item>
      <title>Building a Document Intelligence Pipeline with Person Correlation in n8n (LATAM-ready)</title>
      <dc:creator>Mediavox</dc:creator>
      <pubDate>Sat, 25 Jul 2026 18:14:58 +0000</pubDate>
      <link>https://dev.to/mediavox/building-a-document-intelligence-pipeline-with-person-correlation-in-n8n-latam-ready-425g</link>
      <guid>https://dev.to/mediavox/building-a-document-intelligence-pipeline-with-person-correlation-in-n8n-latam-ready-425g</guid>
      <description>&lt;h2&gt;
  
  
  The Problem
&lt;/h2&gt;

&lt;p&gt;You have thousands of documents: medical records, contracts, invoices, IDs. Each contains a person — but they're isolated. Upload a patient's history today, their lab results tomorrow, and their insurance claim next week — and there's no automatic way to say "these all belong to the same person."&lt;/p&gt;

&lt;p&gt;In Latin America this is worse: the same person might appear as CC 1006702172 (Colombia), or with dots (1.006.702.172), or prefixed ("CC 1006702172"), or in a different document type altogether (NIT for companies, RUT in Chile, CURP in Mexico).&lt;/p&gt;

&lt;h2&gt;
  
  
  The Solution: Person Correlation in n8n
&lt;/h2&gt;

&lt;p&gt;We built a document intelligence pipeline that:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Classifies&lt;/strong&gt; any document automatically (30+ types: medical records, contracts, invoices, IDs, insurance forms)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Extracts&lt;/strong&gt; structured entities via template NER (not just generic — specific fields per document type)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Identifies&lt;/strong&gt; the main person and normalizes their ID across LATAM formats&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Correlates&lt;/strong&gt; all documents by person — automatically&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  How it works in n8n
&lt;/h3&gt;

&lt;p&gt;Install the community node:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Settings &amp;gt; Community Nodes &amp;gt; n8n-nodes-mediavox
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then build your workflow:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 1: Upload document&lt;/strong&gt;&lt;br&gt;
&lt;/p&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;"product"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"DocumentPower"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"method"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"document.analyze"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"params"&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;"file"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"{{$binary.data.data}}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"file_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;"{{$binary.data.fileName}}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"post_process"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"health"&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;p&gt;&lt;strong&gt;Step 2: Check the response&lt;/strong&gt;&lt;br&gt;
&lt;/p&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;"document_type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"epicrisis"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"persona"&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;"1006702172"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"tipo_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;"CC"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"nombre"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"LAURA VANESSA OROZCO DAZA"&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_documentos"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"tipos_documento"&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="nl"&gt;"epicrisis"&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="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"incapacidad"&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;"receta"&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;"laboratorio"&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="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"documentos_relacionados"&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="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="mi"&gt;25&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"tipo"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"epicrisis"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"fecha"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2026-02-15"&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="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="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"tipo"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"incapacidad"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"fecha"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2026-02-20"&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;"health"&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;"servicio_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;56&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"diagnostico"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"K35.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"confidence"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;1.0&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;p&gt;&lt;strong&gt;Step 3: Get the full patient record&lt;/strong&gt;&lt;br&gt;
&lt;/p&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;"product"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"HealthPower"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"method"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"health.patient_record"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"params"&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;"tipoId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"CC"&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;"1006702172"&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;p&gt;Returns ALL documents + clinical services for that person, chronologically ordered.&lt;/p&gt;

&lt;h2&gt;
  
  
  Multi-Country ID Normalization
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;PersonIdExtractor&lt;/code&gt; handles:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Country&lt;/th&gt;
&lt;th&gt;ID Types&lt;/th&gt;
&lt;th&gt;Format variations&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Colombia&lt;/td&gt;
&lt;td&gt;CC, TI, CE, NIT&lt;/td&gt;
&lt;td&gt;With/without dots, with/without prefix&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Mexico&lt;/td&gt;
&lt;td&gt;CURP, RFC&lt;/td&gt;
&lt;td&gt;18-char alphanumeric&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Chile&lt;/td&gt;
&lt;td&gt;RUT&lt;/td&gt;
&lt;td&gt;With/without dots and dash&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Peru&lt;/td&gt;
&lt;td&gt;DNI&lt;/td&gt;
&lt;td&gt;8 digits&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Brazil&lt;/td&gt;
&lt;td&gt;CPF&lt;/td&gt;
&lt;td&gt;With/without dots and dash&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;All normalized to a clean string before correlation. "1.006.702.172" and "CC 1006702172" and "1006702172" all resolve to the same person.&lt;/p&gt;

&lt;h2&gt;
  
  
  force_reanalyze: Re-process Without Duplicates
&lt;/h2&gt;

&lt;p&gt;Templates improve over time. When you add new extraction fields, you want to re-process existing documents without creating duplicates:&lt;br&gt;
&lt;/p&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;"params"&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;"file"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&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;"file_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;"historia_clinica.pdf"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"force_reanalyze"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&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;p&gt;Response: &lt;code&gt;vault_status: "reanalyzed"&lt;/code&gt; — the existing document is UPDATED with fresh NER results.&lt;/p&gt;

&lt;h2&gt;
  
  
  Ready-to-Use Workflow Templates
&lt;/h2&gt;

&lt;p&gt;We have 13 templates ready to import:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Patient Record Lookup&lt;/strong&gt; — Input patient ID → full correlated record&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Clinical Document Ingest + Risk Score&lt;/strong&gt; — Upload PDF → classify → extract → risk&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Invoice Analysis&lt;/strong&gt; — Extract NIT, items, totals, ask follow-up questions&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Phishing Detection&lt;/strong&gt; — Analyze messages → resolve URLs → route by verdict&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;KYC Onboarding&lt;/strong&gt; — Sanctions + ID validation → approve/review/reject&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Download them at: &lt;a href="https://mediavox.co/mvdevportal/integrations/n8n" rel="noopener noreferrer"&gt;https://mediavox.co/mvdevportal/integrations/n8n&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Links
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;npm:&lt;/strong&gt; &lt;a href="https://www.npmjs.com/package/n8n-nodes-mediavox" rel="noopener noreferrer"&gt;https://www.npmjs.com/package/n8n-nodes-mediavox&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Docs &amp;amp; Playground:&lt;/strong&gt; &lt;a href="https://mediavox.co/mvdevportal" rel="noopener noreferrer"&gt;https://mediavox.co/mvdevportal&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;API Reference (200+ endpoints):&lt;/strong&gt; &lt;a href="https://mediavox.co/mvdevportal/reference" rel="noopener noreferrer"&gt;https://mediavox.co/mvdevportal/reference&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>ai</category>
      <category>programming</category>
      <category>productivity</category>
      <category>automation</category>
    </item>
    <item>
      <title>Extracting structured data from invoices and contracts with one API call</title>
      <dc:creator>Mediavox</dc:creator>
      <pubDate>Sat, 25 Jul 2026 18:13:52 +0000</pubDate>
      <link>https://dev.to/mediavox/extracting-structured-data-from-invoices-and-contracts-with-one-api-call-n5p</link>
      <guid>https://dev.to/mediavox/extracting-structured-data-from-invoices-and-contracts-with-one-api-call-n5p</guid>
      <description>&lt;h1&gt;
  
  
  Extracting structured data from invoices and contracts with one API call
&lt;/h1&gt;

&lt;p&gt;I've been working on a document analysis API and wanted to share a pattern that saved me from writing custom parsers for every document type my clients throw at me.&lt;/p&gt;

&lt;h2&gt;
  
  
  The problem
&lt;/h2&gt;

&lt;p&gt;If you work with LATAM businesses, you know the pain: invoices in PDF (sometimes scanned), contracts in Word, receipts as phone photos. Every client has a different format. Building regex parsers for each one is a nightmare that breaks every time the layout changes slightly.&lt;/p&gt;

&lt;h2&gt;
  
  
  The approach
&lt;/h2&gt;

&lt;p&gt;Instead of building N parsers, I use a single multimodal AI endpoint that:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Receives the file (PDF, image, DOCX — up to 20MB)&lt;/li&gt;
&lt;li&gt;Classifies the document type automatically&lt;/li&gt;
&lt;li&gt;Extracts named entities (vendor, amounts, dates, line items)&lt;/li&gt;
&lt;li&gt;Returns a structured JSON response&lt;/li&gt;
&lt;li&gt;Keeps a session open for follow-up questions&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Code (Python)
&lt;/h2&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="c1"&gt;# Upload and analyze in one call
&lt;/span&gt;&lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;invoice.pdf&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;rb&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;:&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;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&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://mediavox.co/mvai/api/v1/documents/analyze&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;files&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;file&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;f&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="p"&gt;{&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;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;your_key_here&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;question&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;Extract: vendor name, tax ID, invoice number, date, line items with quantities and prices, subtotal, tax, total.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;60&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;response&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="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;answer&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;       &lt;span class="c1"&gt;# Human-readable summary
&lt;/span&gt;&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;entities&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;     &lt;span class="c1"&gt;# Structured: [{type: "vendor", value: "..."}]
&lt;/span&gt;&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;document_type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="c1"&gt;# "factura", "contrato", "recibo"...
&lt;/span&gt;&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;session_id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;   &lt;span class="c1"&gt;# For follow-up questions
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Follow-up questions (same session)
&lt;/h2&gt;

&lt;p&gt;The session persists the document context, so you can ask clarifying questions without re-uploading:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;follow_up&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;post&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://mediavox.co/mvai/api/v1/chat&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;json&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;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;your_key_here&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;question&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;What are the payment terms?&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;session_id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;session_id&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="p"&gt;)&lt;/span&gt;

&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;follow_up&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;answer&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="c1"&gt;# "Payment terms: 30 days net. Due date: August 15, 2026."
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The AI answers from the document only — no hallucinations from external knowledge.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I got from a real scanned receipt
&lt;/h2&gt;

&lt;p&gt;Input: a crumpled photo of a Colombian restaurant receipt (low light, tilted)&lt;br&gt;
&lt;/p&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;"document_type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"recibo"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"entities"&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="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"vendor"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Restaurante El Portal"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"confidence"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;0.94&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="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"tax_id"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"901234567-8"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"confidence"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;0.91&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="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"total"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"98700"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"confidence"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;0.97&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="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"tax"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"15800"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"confidence"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;0.89&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="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"date"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2026-06-28"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"confidence"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;0.95&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;"integrity"&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;"subtotal_matches_items"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"tax_calculation_correct"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&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;p&gt;The &lt;code&gt;integrity&lt;/code&gt; check catches arithmetic mismatches automatically — useful for expense auditing.&lt;/p&gt;

&lt;h2&gt;
  
  
  n8n integration
&lt;/h2&gt;

&lt;p&gt;If you use n8n, there's a community node (&lt;code&gt;n8n-nodes-mediavox&lt;/code&gt;) that wraps all of this. Or use HTTP Request nodes directly — the API is straightforward REST.&lt;/p&gt;

&lt;p&gt;I published a ready-to-use workflow template: &lt;a href="https://mediavox.co/mvdevportal/static/n8n/documentpower-analyze-invoice.json" rel="noopener noreferrer"&gt;Extract invoice details and ask follow-ups&lt;/a&gt; — import it and replace the file path.&lt;/p&gt;

&lt;h2&gt;
  
  
  When this works well
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Invoices (any format from any LATAM country)&lt;/li&gt;
&lt;li&gt;Contracts (extract parties, dates, clauses, amounts)&lt;/li&gt;
&lt;li&gt;Medical documents (procedures, diagnoses, patient IDs)&lt;/li&gt;
&lt;li&gt;Receipts and expense reports&lt;/li&gt;
&lt;li&gt;Any document where you need structured data but can't predict the exact layout&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Limitations (being honest)
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Handwritten documents: accuracy drops to ~70%&lt;/li&gt;
&lt;li&gt;Documents &amp;gt;50 pages: works but slower (20-30s)&lt;/li&gt;
&lt;li&gt;Tables with merged cells: sometimes misaligns rows&lt;/li&gt;
&lt;li&gt;Non-Spanish/English documents: not optimized yet&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;Free tier: 100 requests/month. Enough to test with real documents.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;API docs: &lt;a href="https://mediavox.co/mvdevportal" rel="noopener noreferrer"&gt;mediavox.co/mvdevportal&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;n8n node: &lt;code&gt;n8n-nodes-mediavox&lt;/code&gt; on npm&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;em&gt;Built this for LATAM businesses dealing with messy paperwork. If you're processing documents in Spanish/Portuguese and tired of custom parsers, this might save you time.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>programming</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Detecting brand impersonation in Spanish SMS — the position trick</title>
      <dc:creator>Mediavox</dc:creator>
      <pubDate>Mon, 22 Jun 2026 23:06:04 +0000</pubDate>
      <link>https://dev.to/mediavox/detecting-brand-impersonation-in-spanish-sms-the-position-trick-16me</link>
      <guid>https://dev.to/mediavox/detecting-brand-impersonation-in-spanish-sms-the-position-trick-16me</guid>
      <description>&lt;h1&gt;
  
  
  Detecting brand impersonation in Spanish SMS — the position trick
&lt;/h1&gt;

&lt;p&gt;Phishing in Latin America has a pattern most detection systems miss: &lt;strong&gt;where&lt;/strong&gt; the brand name appears in the message matters.&lt;/p&gt;

&lt;h2&gt;
  
  
  The insight
&lt;/h2&gt;

&lt;p&gt;In legitimate bank notifications, the brand appears at the &lt;strong&gt;end&lt;/strong&gt; as a signature:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Su transferencia por $500,000 fue exitosa. — Tu Banco
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In phishing, the brand appears at the &lt;strong&gt;beginning&lt;/strong&gt; as a fake sender identity:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Tu Banco: Su cuenta sera bloqueada en 24h. Verifique: bit.ly/xyz
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This single heuristic (brand at position 0-2 words = impersonation pattern) catches ~70% of LATAM phishing messages before any URL analysis.&lt;/p&gt;

&lt;h2&gt;
  
  
  Implementation (simplified)
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="nf"&gt;IsBrandImpersonation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;knownBrands&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;firstSegment&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Split&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="sc"&gt;' '&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sc"&gt;':'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sc"&gt;'-'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;ToLowerInvariant&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;knownBrands&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Any&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; 
        &lt;span class="n"&gt;firstSegment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Contains&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ToLowerInvariant&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;Real implementation adds:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Levenshtein distance for typosquatting ("Banamex" → "Banamx", "Nequi" → "Nequii")&lt;/li&gt;
&lt;li&gt;Alias matching (263+ brands across CO, MX, PE, CL, EC, AR)&lt;/li&gt;
&lt;li&gt;Position scoring (start = 0.9, middle = 0.3, end/signature = 0.1)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Combining with other signals
&lt;/h2&gt;

&lt;p&gt;Brand position alone isn't enough. We stack 7 signals in a single pass:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Signal&lt;/th&gt;
&lt;th&gt;Weight&lt;/th&gt;
&lt;th&gt;Cost&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Brand at start (impersonation)&lt;/td&gt;
&lt;td&gt;0.25&lt;/td&gt;
&lt;td&gt;Free&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Domain age &amp;lt; 7 days&lt;/td&gt;
&lt;td&gt;0.20&lt;/td&gt;
&lt;td&gt;1 RDAP call&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;URL shortener → suspicious domain&lt;/td&gt;
&lt;td&gt;0.20&lt;/td&gt;
&lt;td&gt;1 redirect follow&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Spanish urgency language&lt;/td&gt;
&lt;td&gt;0.15&lt;/td&gt;
&lt;td&gt;Free (regex)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Safe Browsing match&lt;/td&gt;
&lt;td&gt;0.10&lt;/td&gt;
&lt;td&gt;1 API call&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Phone number not official&lt;/td&gt;
&lt;td&gt;0.05&lt;/td&gt;
&lt;td&gt;DB lookup&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CTA pattern detected&lt;/td&gt;
&lt;td&gt;0.05&lt;/td&gt;
&lt;td&gt;Free (regex)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Combined confidence &amp;gt; 75% = fraudulent verdict.&lt;/p&gt;

&lt;h2&gt;
  
  
  Results
&lt;/h2&gt;

&lt;p&gt;Processing 10K+ real messages (crowdsourced from users across LATAM):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;94% accuracy on fraudulent messages&lt;/li&gt;
&lt;li&gt;2% false positive rate (legitimate marketing that starts with brand)&lt;/li&gt;
&lt;li&gt;&amp;lt; 200ms p95 response time&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The false positives are almost always marketing SMS that mimic phishing patterns — which is a problem for the brands themselves.&lt;/p&gt;

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



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST https://mediavox.co/mvapi/api/v1/security/threats/analyze &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"X-API-Key: your-key"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"message": "TuBanco: Detectamos actividad inusual. Verifica tu cuenta: bit.ly/tb-verify"}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Free tier: 500 analyses/month. No credit card.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;We built this for Latin America because English-focused tools don't understand Spanish urgency patterns, regional brand aliases, or the specific phishing templates used in CO/MX/PE/CL. If you're building for LATAM, happy to chat about what we've learned.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>security</category>
      <category>programming</category>
      <category>npl</category>
    </item>
    <item>
      <title>Building a fraud detection and data quality API for Latin America</title>
      <dc:creator>Mediavox</dc:creator>
      <pubDate>Mon, 08 Jun 2026 19:50:00 +0000</pubDate>
      <link>https://dev.to/mediavox/building-a-fraud-detection-and-data-quality-api-for-latin-america-31dm</link>
      <guid>https://dev.to/mediavox/building-a-fraud-detection-and-data-quality-api-for-latin-america-31dm</guid>
      <description>&lt;p&gt;If you've built anything for Latin America, you know the pain:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;2M+ phishing SMS per month in Colombia alone — in Spanish, targeting local banks and fintechs&lt;/li&gt;
&lt;li&gt;Names like "INVERSIONES DEMO S.A.S." that need to be split into company name + legal suffix + country&lt;/li&gt;
&lt;li&gt;Addresses like "Cra 7 # 32-16 Of 2301" that geocoding services can't parse without local context&lt;/li&gt;
&lt;li&gt;Phone numbers with country codes that don't match the user's declared country&lt;/li&gt;
&lt;li&gt;Sanctions screening that can't fuzzy-match "José García" vs "JOSE GARCIA LOPEZ" (accents, middle names, order)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The existing tools (phone validators, safe browsing APIs, breach databases) work for the US. They don't understand that a brand name at the start of an SMS is an impersonation pattern in LATAM, or that "S.A.S." means the input is a Colombian company, not a person.&lt;/p&gt;

&lt;h2&gt;
  
  
  What we built
&lt;/h2&gt;

&lt;p&gt;A REST API designed for Spanish-speaking Latin America. Five capabilities under one API key:&lt;/p&gt;




&lt;h3&gt;
  
  
  1. Security — Detect fraud in real time
&lt;/h3&gt;

&lt;p&gt;The biggest pain in LATAM right now. Phishing via SMS, WhatsApp, and email targeting banks, telcos, and fintechs.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Analyze a suspicious message&lt;/span&gt;
curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST https://mediavox.co/mvapi/api/v1/security/threats/analyze &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"X-API-Key: your-key"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"message": "Su cuenta sera bloqueada. Verifique en bit.ly/xyz"}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Response:&lt;br&gt;
&lt;/p&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;"verdict"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"fraudulent"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"confidence"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;95&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"signals"&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;"urgencyScore"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;0.85&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"brandDetected"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"urlAnalysis"&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;"finalDomain"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"entidad-verify.tk"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"domainAgeDays"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"safeBrowsing"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"malicious"&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;"phones"&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;"ctaFound"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&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;p&gt;What it checks in a single call:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;263+ LATAM brands&lt;/strong&gt; with impersonation detection (position-aware: brand at start = sender pattern)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Domain age&lt;/strong&gt; via RDAP (domains &amp;lt; 7 days = almost always fraud)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Redirect chain resolution&lt;/strong&gt; (follows bit.ly → final destination, up to 10 hops)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Safe browsing check&lt;/strong&gt; (known malicious domains database)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Urgency patterns&lt;/strong&gt; in Spanish ("será bloqueada", "últimas horas", "activa ya")&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Phone extraction&lt;/strong&gt; with official number verification&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;CTA detection&lt;/strong&gt; (suspicious call-to-action patterns)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Also available: sanctions screening (OFAC, UN, EU, PEP — 65K+ entities with Spanish fuzzy matching), brand registration for monitoring, and a crowdsourced threat feed that grows with every analysis.&lt;/p&gt;




&lt;h3&gt;
  
  
  2. DataTools — Clean your data
&lt;/h3&gt;

&lt;p&gt;Every company in LATAM has dirty data. Names misspelled, emails that bounce, addresses that geocoding services can't understand.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Standardize a name (handles Spanish, 60K+ dictionary)&lt;/span&gt;
curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST https://mediavox.co/mvapi/api/v1/datatools/names/standardize &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"X-API-Key: your-key"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"text": "INVERSIONES DEMO S.A.S."}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Response:&lt;br&gt;
&lt;/p&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;"standardized"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Inversiones Demo"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"company"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"company_info"&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;"legal_suffix"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"SAS"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"legal_suffix_full"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Sociedad por Acciones Simplificada"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"country_detected"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"CO"&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;p&gt;Available endpoints:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;names/standardize&lt;/strong&gt; — 60K+ name dictionary, gender detection, legal suffix separation for 6 countries (CO, MX, PE, CL, EC, AR)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;emails/validate&lt;/strong&gt; — disposable detection, typo correction, MX record verification&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;addresses/standardize&lt;/strong&gt; — Colombian address parsing + geocoding + DANE/INEGI/UBIGEO official codes&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;domains/validate&lt;/strong&gt; — brand identification, DNS resolution, registration data&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;quality-score&lt;/strong&gt; — cross-field coherence (email vs name, phone prefix vs country, disposable email with real data)&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  3. Compliance — KYC in one call
&lt;/h3&gt;

&lt;p&gt;If you're a fintech, bank, or insurance company in LATAM, regulatory compliance isn't optional. Sarlaft (Colombia), UIF (Mexico), SBS (Peru) all require screening.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Screen an entity against global sanctions lists&lt;/span&gt;
curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST https://mediavox.co/mvapi/api/v1/security/sanctions/check &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"X-API-Key: your-key"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"name": "Jose Garcia Lopez", "country": "CO"}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Screens against OFAC, UN, EU, Interpol, and local PEP lists. Spanish fuzzy matching handles accents, name order variations, and abbreviations.&lt;/p&gt;

&lt;p&gt;The compliance bundle (one call) combines: sanctions check + name standardization + document ID validation + quality score.&lt;/p&gt;




&lt;h3&gt;
  
  
  4. Finance — LATAM tax and banking
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Validate a Colombian tax ID (NIT)&lt;/span&gt;
curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST https://mediavox.co/mvapi/api/v1/finance/tax-id/validate &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"X-API-Key: your-key"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"document_id": "900534082", "country": "CO"}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Validates tax IDs (NIT Colombia, RFC Mexico, RUT Chile, RUC Peru, RUC Ecuador), verifies bank account formats, and categorizes financial transactions.&lt;/p&gt;




&lt;h3&gt;
  
  
  5. Recognition — OCR with structure
&lt;/h3&gt;

&lt;p&gt;Extract text from documents (invoices, IDs, contracts) with computer vision, then apply NER to pull structured entities: tax IDs, amounts, dates, company names, addresses.&lt;/p&gt;




&lt;h2&gt;
  
  
  How it works under the hood
&lt;/h2&gt;

&lt;p&gt;Three things make this different from wrapping existing APIs:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Self-improving dictionaries.&lt;/strong&gt; The more the API is used, the more accurate it becomes. Day one: 90%+ accuracy on names, cities, and brands across 6 LATAM countries. With traffic: approaches 99% as the system learns from every request.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Native Spanish NLP.&lt;/strong&gt; Not a translation layer on top of English tools. Built from scratch for ñ, accents, regional variations, and the specific patterns of Latin American fraud (urgency language, impersonation positions, local brand aliases).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Crowdsourced intelligence.&lt;/strong&gt; A free public bot (WhatsApp + Telegram) lets citizens verify suspicious messages. Every analysis enriches the threat feed. Every report strengthens detection. API customers benefit from intelligence generated organically by real users — without lifting a finger.&lt;/p&gt;




&lt;h2&gt;
  
  
  Beyond the API — The full ecosystem
&lt;/h2&gt;

&lt;p&gt;mediaAPI is one piece. The same platform offers three more products for different use cases:&lt;/p&gt;

&lt;h3&gt;
  
  
  Turing AI — Embeddable AI assistant
&lt;/h3&gt;

&lt;p&gt;Drop an intelligent chatbot into any website with one script tag. It connects to your actual data (CRM, invoices, inventory) and answers questions with real numbers — not generic AI responses.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://mediavox.co/mvai/mediavox-turing.js?v=2.5"&lt;/span&gt; 
        &lt;span class="na"&gt;data-key=&lt;/span&gt;&lt;span class="s"&gt;"your-key"&lt;/span&gt; &lt;span class="na"&gt;data-theme=&lt;/span&gt;&lt;span class="s"&gt;"light"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Features: RAG with your own content, function calling against your database, multi-tenant (one setup, many clients), feedback loop that improves over time. Supports Spanish natively.&lt;/p&gt;

&lt;p&gt;Use case: Your customer asks "When is my next payment due?" → Turing queries your billing system and answers with the actual date and amount.&lt;/p&gt;

&lt;h3&gt;
  
  
  DocumentPower — Document intelligence
&lt;/h3&gt;

&lt;p&gt;Upload contracts, invoices, IDs, or any document. The system extracts structured entities (amounts, dates, tax IDs, names, companies) using NER, then indexes everything for semantic search.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Upload and extract entities&lt;/span&gt;
curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST https://mediavox.co/mvai/api/v1/documents/upload &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"X-Turing-Key: your-key"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-F&lt;/span&gt; &lt;span class="s2"&gt;"file=@contract.pdf"&lt;/span&gt;

&lt;span class="c"&gt;# Search across all your documents&lt;/span&gt;
curl &lt;span class="s2"&gt;"https://mediavox.co/mvai/api/v1/documents/search?query=penalty+clause"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Use case: A compliance team uploads 500 supplier contracts. Later, they search "penalty clauses above $10K" and get instant results with page citations.&lt;/p&gt;

&lt;h3&gt;
  
  
  Sales Copilot — AI for field sales via WhatsApp
&lt;/h3&gt;

&lt;p&gt;A sales rep sends a WhatsApp voice note or text: "Send 5 boxes of motor oil to Store #47". The AI identifies the product, the client, checks inventory and pricing, and creates the order — no app needed.&lt;/p&gt;

&lt;p&gt;Built for LATAM distribution (TAT/retail channel). Handles Spanish product synonyms, voice transcription, and integrates with existing ERP inventory.&lt;/p&gt;

&lt;p&gt;Use case: 900 sales reps × 30 daily store visits = 27,000 orders/month processed by AI, zero manual data entry.&lt;/p&gt;




&lt;h2&gt;
  
  
  n8n integration
&lt;/h2&gt;

&lt;p&gt;If you use n8n, there's a community node:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install &lt;/span&gt;n8n-nodes-mediavox
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;48+ operations across all products. Drop it into any workflow — validate data before loading to your CRM, screen suppliers against sanctions lists, detect fraud in incoming messages. No code required.&lt;/p&gt;




&lt;h2&gt;
  
  
  Pricing
&lt;/h2&gt;

&lt;p&gt;Free tier available (no credit card required). Paid plans for higher volume. Check the developer portal for current pricing.&lt;/p&gt;




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

&lt;ol&gt;
&lt;li&gt;Register at the developer portal (10 seconds, no credit card)&lt;/li&gt;
&lt;li&gt;Get your API key&lt;/li&gt;
&lt;li&gt;Start calling endpoints&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The interactive playground lets you test every endpoint with your own data before writing a single line of code.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>security</category>
      <category>webdev</category>
      <category>latam</category>
    </item>
  </channel>
</rss>
