Skip to main content
POST
/
api
/
v2
/
FlexOCR
/
Extract
/
Json
Extração de Dados - FlexExtractor
curl --request POST \
  --url https://hml.flexextractor.com.br/api/v2/FlexOCR/Extract/Json \
  --header 'Authorization: <authorization>' \
  --header 'Content-Type: application/json' \
  --data '
{
  "imageBase64": "<string>",
  "typealias": "<string>",
  "cpf": "<string>"
}
'
import requests

url = "https://hml.flexextractor.com.br/api/v2/FlexOCR/Extract/Json"

payload = {
"imageBase64": "<string>",
"typealias": "<string>",
"cpf": "<string>"
}
headers = {
"Authorization": "<authorization>",
"Content-Type": "application/json"
}

response = requests.post(url, json=payload, headers=headers)

print(response.text)
const options = {
method: 'POST',
headers: {Authorization: '<authorization>', 'Content-Type': 'application/json'},
body: JSON.stringify({imageBase64: '<string>', typealias: '<string>', cpf: '<string>'})
};

fetch('https://hml.flexextractor.com.br/api/v2/FlexOCR/Extract/Json', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));
<?php

$curl = curl_init();

curl_setopt_array($curl, [
CURLOPT_URL => "https://hml.flexextractor.com.br/api/v2/FlexOCR/Extract/Json",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'imageBase64' => '<string>',
'typealias' => '<string>',
'cpf' => '<string>'
]),
CURLOPT_HTTPHEADER => [
"Authorization: <authorization>",
"Content-Type: application/json"
],
]);

$response = curl_exec($curl);
$err = curl_error($curl);

curl_close($curl);

if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}
package main

import (
"fmt"
"strings"
"net/http"
"io"
)

func main() {

url := "https://hml.flexextractor.com.br/api/v2/FlexOCR/Extract/Json"

payload := strings.NewReader("{\n \"imageBase64\": \"<string>\",\n \"typealias\": \"<string>\",\n \"cpf\": \"<string>\"\n}")

req, _ := http.NewRequest("POST", url, payload)

req.Header.Add("Authorization", "<authorization>")
req.Header.Add("Content-Type", "application/json")

res, _ := http.DefaultClient.Do(req)

defer res.Body.Close()
body, _ := io.ReadAll(res.Body)

fmt.Println(string(body))

}
HttpResponse<String> response = Unirest.post("https://hml.flexextractor.com.br/api/v2/FlexOCR/Extract/Json")
.header("Authorization", "<authorization>")
.header("Content-Type", "application/json")
.body("{\n \"imageBase64\": \"<string>\",\n \"typealias\": \"<string>\",\n \"cpf\": \"<string>\"\n}")
.asString();
require 'uri'
require 'net/http'

url = URI("https://hml.flexextractor.com.br/api/v2/FlexOCR/Extract/Json")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Post.new(url)
request["Authorization"] = '<authorization>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"imageBase64\": \"<string>\",\n \"typealias\": \"<string>\",\n \"cpf\": \"<string>\"\n}"

response = http.request(request)
puts response.read_body
{
  "ocrResult": {
    "typeRecognized": "RG",
    "digitalDocument": false,
    "fields": [
      {
        "name": "NOME",
        "value": "JOÃO DA SILVA",
        "boundingBox": [83, 56, 92, 206],
        "confidence": 98
      },
      {
        "name": "RG",
        "value": "12.345.678-9",
        "boundingBox": [95, 58, 102, 155],
        "confidence": 95
      },
      {
        "name": "CPF",
        "value": "123.456.789-01",
        "boundingBox": [133, 79, 140, 149],
        "confidence": 92
      },
      {
        "name": "DATA_NASCIMENTO",
        "value": "15/03/1990",
        "boundingBox": [145, 82, 152, 178],
        "confidence": 100
      },
      {
        "name": "NOME_PAI",
        "value": "JOSÉ DA SILVA",
        "boundingBox": [165, 88, 172, 220],
        "confidence": 89
      },
      {
        "name": "NOME_MAE",
        "value": "MARIA DA SILVA",
        "boundingBox": [185, 91, 192, 225],
        "confidence": 94
      },
      {
        "name": "DATA_EXPEDICAO",
        "value": "20/01/2015",
        "boundingBox": [205, 95, 212, 165],
        "confidence": 97
      },
      {
        "name": "ORGAO_EXPEDIDOR",
        "value": "SSP/SP",
        "boundingBox": [215, 98, 222, 145],
        "confidence": 100
      }
    ],
    "statistics": {
      "convert": 901,
      "ocr1": 2370,
      "ocr2": 0,
      "parse": 1294
    }
  },
  "isSuccesful": true,
  "statusCode": 200,
  "timestamp": "2025-01-09T11:01:39.6009905-03:00"
}
{
  "ocrResult": {
    "typeRecognized": "CNH",
    "digitalDocument": true,
    "fields": [
      {
        "name": "NOME",
        "value": "MARIA SANTOS",
        "boundingBox": [75, 45, 85, 198],
        "confidence": 99
      },
      {
        "name": "CPF",
        "value": "987.654.321-00",
        "boundingBox": [95, 52, 102, 156],
        "confidence": 100
      },
      {
        "name": "REGISTRO_CNH",
        "value": "12345678901",
        "boundingBox": [110, 58, 118, 175],
        "confidence": 98
      },
      {
        "name": "DATA_NASCIMENTO",
        "value": "22/08/1985",
        "boundingBox": [125, 62, 132, 168],
        "confidence": 97
      },
      {
        "name": "CATEGORIA",
        "value": "AB",
        "boundingBox": [140, 68, 145, 95],
        "confidence": 100
      },
      {
        "name": "DATA_PRIMEIRA_HABILITACAO",
        "value": "10/05/2005",
        "boundingBox": [155, 72, 162, 172],
        "confidence": 95
      },
      {
        "name": "DATA_VALIDADE",
        "value": "22/08/2030",
        "boundingBox": [170, 78, 177, 168],
        "confidence": 99
      }
    ],
    "statistics": {
      "convert": 654,
      "ocr1": 1875,
      "ocr2": 0,
      "parse": 987
    }
  },
  "isSuccesful": true,
  "statusCode": 200,
  "timestamp": "2025-01-09T14:23:15.4521098-03:00"
}
{
  "isSuccesful": false,
  "statusCode": 401,
  "timestamp": "2025-01-09T11:05:22.1234567-03:00",
  "error": "Unauthorized: Invalid or expired token"
}
{
  "isSuccesful": false,
  "statusCode": 400,
  "timestamp": "2025-01-09T11:07:45.9876543-03:00",
  "error": "Invalid image format. Supported formats: PDF, JPG, PNG"
}

Visão Geral

A API FlexOCR Extract permite extrair informações de documentos de forma automática utilizando OCR (Reconhecimento Ótico de Caracteres) com inteligência artificial. Envie a imagem do documento em Base64 e receba os dados estruturados em JSON.

OCR Inteligente

Reconhecimento automático com IA

Múltiplos Documentos

Suporte para RG, CNH, CPF e mais

Classificação Automática

Identifica o tipo do documento automaticamente

Dados Estruturados

Retorna campos com coordenadas e confiança

Fluxo de Extração

1

Autenticação

Obtenha um access_token válido via /api/v2/Security/GetToken
2

Preparar Imagem

Converta o documento para Base64 (PDF, JPG, PNG)
3

Enviar Requisição

POST com imagem Base64 e tipo de documento (opcional)
4

Receber Dados Extraídos

API retorna campos identificados com nome, valor e confiança

Authentication

Authorization
string
required
Bearer token obtido via /api/v2/Security/GetTokenFormato: Bearer {access_token}Exemplo: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...

Request Body

Use o playground “Try It” à direita para testar a API diretamente! →
imageBase64
string
required
Imagem do documento codificada em Base64Formatos aceitos: PDF, JPG, JPEG, PNGTamanho máximo recomendado: 10MBExemplo:
"JVBERi0xLjMNCiXi48/TDQoyIDAgb2J....AAAAAAAAAAA"
Para melhor precisão, use imagens com:
  • Resolução mínima de 300 DPI
  • Boa iluminação
  • Documento completo e legível
  • Sem cortes ou reflexos
typealias
string
Tipo do documento a ser processado. Se não informado, o sistema identifica automaticamente.Valores aceitos:
TipoDescrição
RGRegistro Geral (Identidade)
CNHCarteira Nacional de Habilitação
CPFCadastro de Pessoa Física
CE_CEMIGConta de Energia CEMIG
PASSAPORTEPassaporte brasileiro
CTPSCarteira de Trabalho
Exemplo: "RG"
Informar o tipo correto melhora a precisão e velocidade da extração
cpf
string
CPF relacionado ao documento (opcional). Usado para validação cruzada.Formato: Apenas números (11 dígitos)Exemplo: "12345678901"
O CPF informado pode ser usado para validar dados extraídos do documento

Response

ocrResult
object
required
Objeto contendo os resultados da extração OCR
isSuccesful
boolean
required
Indica se a extração foi bem-sucedida
  • true: Dados extraídos com sucesso
  • false: Erro na extração (verifique campo error)
statusCode
integer
required
Código HTTP de status da operaçãoValores comuns:
  • 200: Sucesso
  • 400: Requisição inválida
  • 401: Token inválido ou expirado
  • 500: Erro interno no servidor
timestamp
string
required
Data e hora da extração (formato ISO 8601)Exemplo: "2025-01-09T11:01:39.6009905-03:00"
requestUri
string
URI da requisição (quando disponível)
error
string
Mensagem de erro (presente apenas quando isSuccesful: false)Exemplos:
  • "Invalid image format"
  • "Image too large"
  • "Unable to recognize document type"
{
  "ocrResult": {
    "typeRecognized": "RG",
    "digitalDocument": false,
    "fields": [
      {
        "name": "NOME",
        "value": "JOÃO DA SILVA",
        "boundingBox": [83, 56, 92, 206],
        "confidence": 98
      },
      {
        "name": "RG",
        "value": "12.345.678-9",
        "boundingBox": [95, 58, 102, 155],
        "confidence": 95
      },
      {
        "name": "CPF",
        "value": "123.456.789-01",
        "boundingBox": [133, 79, 140, 149],
        "confidence": 92
      },
      {
        "name": "DATA_NASCIMENTO",
        "value": "15/03/1990",
        "boundingBox": [145, 82, 152, 178],
        "confidence": 100
      },
      {
        "name": "NOME_PAI",
        "value": "JOSÉ DA SILVA",
        "boundingBox": [165, 88, 172, 220],
        "confidence": 89
      },
      {
        "name": "NOME_MAE",
        "value": "MARIA DA SILVA",
        "boundingBox": [185, 91, 192, 225],
        "confidence": 94
      },
      {
        "name": "DATA_EXPEDICAO",
        "value": "20/01/2015",
        "boundingBox": [205, 95, 212, 165],
        "confidence": 97
      },
      {
        "name": "ORGAO_EXPEDIDOR",
        "value": "SSP/SP",
        "boundingBox": [215, 98, 222, 145],
        "confidence": 100
      }
    ],
    "statistics": {
      "convert": 901,
      "ocr1": 2370,
      "ocr2": 0,
      "parse": 1294
    }
  },
  "isSuccesful": true,
  "statusCode": 200,
  "timestamp": "2025-01-09T11:01:39.6009905-03:00"
}
{
  "ocrResult": {
    "typeRecognized": "CNH",
    "digitalDocument": true,
    "fields": [
      {
        "name": "NOME",
        "value": "MARIA SANTOS",
        "boundingBox": [75, 45, 85, 198],
        "confidence": 99
      },
      {
        "name": "CPF",
        "value": "987.654.321-00",
        "boundingBox": [95, 52, 102, 156],
        "confidence": 100
      },
      {
        "name": "REGISTRO_CNH",
        "value": "12345678901",
        "boundingBox": [110, 58, 118, 175],
        "confidence": 98
      },
      {
        "name": "DATA_NASCIMENTO",
        "value": "22/08/1985",
        "boundingBox": [125, 62, 132, 168],
        "confidence": 97
      },
      {
        "name": "CATEGORIA",
        "value": "AB",
        "boundingBox": [140, 68, 145, 95],
        "confidence": 100
      },
      {
        "name": "DATA_PRIMEIRA_HABILITACAO",
        "value": "10/05/2005",
        "boundingBox": [155, 72, 162, 172],
        "confidence": 95
      },
      {
        "name": "DATA_VALIDADE",
        "value": "22/08/2030",
        "boundingBox": [170, 78, 177, 168],
        "confidence": 99
      }
    ],
    "statistics": {
      "convert": 654,
      "ocr1": 1875,
      "ocr2": 0,
      "parse": 987
    }
  },
  "isSuccesful": true,
  "statusCode": 200,
  "timestamp": "2025-01-09T14:23:15.4521098-03:00"
}
{
  "isSuccesful": false,
  "statusCode": 401,
  "timestamp": "2025-01-09T11:05:22.1234567-03:00",
  "error": "Unauthorized: Invalid or expired token"
}
{
  "isSuccesful": false,
  "statusCode": 400,
  "timestamp": "2025-01-09T11:07:45.9876543-03:00",
  "error": "Invalid image format. Supported formats: PDF, JPG, PNG"
}

Campos Extraídos por Tipo de Documento

Campos Comuns Extraídos:

CampoDescriçãoExemplo
NOMENome completo”JOÃO DA SILVA”
RGNúmero do RG”12.345.678-9”
CPFNúmero do CPF”123.456.789-01”
DATA_NASCIMENTOData de nascimento”15/03/1990”
NOME_PAINome do pai”JOSÉ DA SILVA”
NOME_MAENome da mãe”MARIA DA SILVA”
DATA_EXPEDICAOData de expedição”20/01/2015”
ORGAO_EXPEDIDORÓrgão expedidor”SSP/SP”
NATURALIDADECidade/UF de nascimento”SÃO PAULO/SP”
Os campos extraídos podem variar conforme o modelo do RG (antigo ou novo)

Campos Comuns Extraídos:

CampoDescriçãoExemplo
NOMENome completo”MARIA SANTOS”
CPFNúmero do CPF”987.654.321-00”
REGISTRO_CNHNúmero de registro”12345678901”
DATA_NASCIMENTOData de nascimento”22/08/1985”
CATEGORIACategoria da CNH”AB”
DATA_PRIMEIRA_HABILITACAOData da 1ª habilitação”10/05/2005”
DATA_VALIDADEData de validade”22/08/2030”
NOME_PAINome do pai”JOSÉ SANTOS”
NOME_MAENome da mãe”ANA SANTOS”
LOCAL_NASCIMENTOLocal de nascimento”RIO DE JANEIRO/RJ”
RGNúmero do RG”98.765.432-1”
CNH digital possui campo digitalDocument: true

Campos Comuns Extraídos:

CampoDescriçãoExemplo
NOMENome completo”CARLOS OLIVEIRA”
CPFNúmero do CPF”111.222.333-44”
DATA_NASCIMENTOData de nascimento”05/12/1978”
SITUACAO_CADASTRALSituação do CPF”REGULAR”

Campos Comuns Extraídos:

CampoDescriçãoExemplo
NOME_CLIENTENome do cliente”JOÃO DA SILVA”
CPF_CNPJCPF ou CNPJ”123.456.789-01”
NUMERO_INSTALACAONº da instalação”123456789”
ENDERECOEndereço completo”RUA EXEMPLO, 123”
VENCIMENTOData de vencimento”15/02/2025”
VALOR_TOTALValor da conta”R$ 250,00”
MES_REFERENCIAMês de referência”JAN/2025”
Use typealias: "CE_CEMIG" para contas da CEMIG

Exemplos de Código

# Primeiro, obtenha o token
TOKEN=$(curl -X POST "https://hml.flexextractor.com.br/api/v2/Security/GetToken" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "username=seu_username" \
  -d "password=sua_senha" | jq -r '.access_token')

# Depois, extraia dados do documento
curl -X POST "https://hml.flexextractor.com.br/api/v2/FlexOCR/Extract/Json" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "typealias": "RG",
    "imageBase64": "JVBERi0xLjMNCiXi48/TDQoyIDAgb2J..."
  }'
const axios = require('axios');
const fs = require('fs');

// Função auxiliar para converter imagem para Base64
function imageToBase64(filePath) {
  const imageBuffer = fs.readFileSync(filePath);
  return imageBuffer.toString('base64');
}

// Função principal de extração
async function extractDocumentData(accessToken, imagePath, docType = null) {
  const imageBase64 = imageToBase64(imagePath);

  const requestBody = {
    imageBase64: imageBase64
  };

  // Adiciona tipo de documento se informado
  if (docType) {
    requestBody.typealias = docType;
  }

  try {
    const response = await axios.post(
      'https://hml.flexextractor.com.br/api/v2/FlexOCR/Extract/Json',
      requestBody,
      {
        headers: {
          'Authorization': `Bearer ${accessToken}`,
          'Content-Type': 'application/json'
        }
      }
    );

    const { ocrResult, isSuccesful, statusCode } = response.data;

    if (isSuccesful) {
      console.log('✓ Extração realizada com sucesso!');
      console.log(`Tipo reconhecido: ${ocrResult.typeRecognized}`);
      console.log(`Campos extraídos: ${ocrResult.fields.length}`);
      console.log('\nDados extraídos:');

      ocrResult.fields.forEach(field => {
        console.log(`  ${field.name}: ${field.value} (confiança: ${field.confidence}%)`);
      });

      return ocrResult;
    } else {
      console.error('✗ Erro na extração:', response.data.error);
      return null;
    }
  } catch (error) {
    console.error('✗ Erro na requisição:', error.response?.data || error.message);
    throw error;
  }
}

// Uso
const token = 'seu_access_token_aqui';
extractDocumentData(token, './documento_rg.jpg', 'RG');
import requests
import base64
import json

def image_to_base64(file_path: str) -> str:
    """Converte imagem para Base64"""
    with open(file_path, 'rb') as image_file:
        return base64.b64encode(image_file.read()).decode('utf-8')

def extract_document_data(access_token: str, image_path: str, doc_type: str = None):
    """
    Extrai dados de documento usando FlexExtractor

    Args:
        access_token: Token de autenticação
        image_path: Caminho do arquivo de imagem
        doc_type: Tipo do documento (RG, CNH, etc) - opcional

    Returns:
        dict: Dados extraídos do documento
    """
    url = "https://hml.flexextractor.com.br/api/v2/FlexOCR/Extract/Json"

    # Converte imagem para Base64
    image_base64 = image_to_base64(image_path)

    # Monta corpo da requisição
    payload = {
        "imageBase64": image_base64
    }

    if doc_type:
        payload["typealias"] = doc_type

    headers = {
        'Authorization': f'Bearer {access_token}',
        'Content-Type': 'application/json'
    }

    try:
        response = requests.post(url, json=payload, headers=headers)
        response.raise_for_status()

        result = response.json()

        if result['isSuccesful']:
            ocr_result = result['ocrResult']
            print(f"✓ Extração realizada com sucesso!")
            print(f"Tipo reconhecido: {ocr_result['typeRecognized']}")
            print(f"Campos extraídos: {len(ocr_result['fields'])}")
            print("\nDados extraídos:")

            for field in ocr_result['fields']:
                print(f"  {field['name']}: {field['value']} "
                      f"(confiança: {field['confidence']}%)")

            return ocr_result
        else:
            print(f"✗ Erro na extração: {result.get('error')}")
            return None

    except requests.exceptions.RequestException as e:
        print(f"✗ Erro na requisição: {e}")
        raise

# Uso
if __name__ == "__main__":
    token = "seu_access_token_aqui"
    data = extract_document_data(token, "./documento_rg.jpg", "RG")
import java.io.*;
import java.net.http.*;
import java.net.*;
import java.nio.file.*;
import java.util.*;
import com.google.gson.*;

public class FlexExtractorClient {

    private static final String EXTRACT_URL =
        "https://hml.flexextractor.com.br/api/v2/FlexOCR/Extract/Json";

    // Classe para resposta OCR
    public static class OcrField {
        public String name;
        public String value;
        public int[] boundingBox;
        public int confidence;
    }

    public static class OcrResult {
        public String typeRecognized;
        public boolean digitalDocument;
        public List<OcrField> fields;
        public Map<String, Integer> statistics;
    }

    public static class ExtractResponse {
        public OcrResult ocrResult;
        public boolean isSuccesful;
        public int statusCode;
        public String timestamp;
        public String error;
    }

    // Converte imagem para Base64
    private static String imageToBase64(String filePath) throws IOException {
        byte[] fileContent = Files.readAllBytes(Paths.get(filePath));
        return Base64.getEncoder().encodeToString(fileContent);
    }

    // Extrai dados do documento
    public static ExtractResponse extractDocumentData(
            String accessToken,
            String imagePath,
            String docType) throws Exception {

        String imageBase64 = imageToBase64(imagePath);

        // Monta JSON do request
        Map<String, String> requestBody = new HashMap<>();
        requestBody.put("imageBase64", imageBase64);

        if (docType != null && !docType.isEmpty()) {
            requestBody.put("typealias", docType);
        }

        Gson gson = new Gson();
        String jsonBody = gson.toJson(requestBody);

        HttpClient client = HttpClient.newHttpClient();
        HttpRequest request = HttpRequest.newBuilder()
            .uri(URI.create(EXTRACT_URL))
            .header("Authorization", "Bearer " + accessToken)
            .header("Content-Type", "application/json")
            .POST(HttpRequest.BodyPublishers.ofString(jsonBody))
            .build();

        HttpResponse<String> response = client.send(request,
            HttpResponse.BodyHandlers.ofString());

        ExtractResponse result = gson.fromJson(
            response.body(),
            ExtractResponse.class
        );

        if (result.isSuccesful) {
            System.out.println("✓ Extração realizada com sucesso!");
            System.out.println("Tipo: " + result.ocrResult.typeRecognized);
            System.out.println("Campos: " + result.ocrResult.fields.size());
            System.out.println("\nDados extraídos:");

            for (OcrField field : result.ocrResult.fields) {
                System.out.printf("  %s: %s (confiança: %d%%)\n",
                    field.name, field.value, field.confidence);
            }
        } else {
            System.err.println("✗ Erro: " + result.error);
        }

        return result;
    }

    public static void main(String[] args) {
        try {
            String token = "seu_access_token_aqui";
            extractDocumentData(token, "./documento_rg.jpg", "RG");
        } catch (Exception e) {
            System.err.println("Erro: " + e.getMessage());
        }
    }
}
<?php

function imageToBase64($filePath) {
    $imageData = file_get_contents($filePath);
    return base64_encode($imageData);
}

function extractDocumentData($accessToken, $imagePath, $docType = null) {
    $url = 'https://hml.flexextractor.com.br/api/v2/FlexOCR/Extract/Json';

    // Converte imagem para Base64
    $imageBase64 = imageToBase64($imagePath);

    // Monta payload
    $payload = [
        'imageBase64' => $imageBase64
    ];

    if ($docType) {
        $payload['typealias'] = $docType;
    }

    $ch = curl_init($url);
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_HTTPHEADER, [
        'Authorization: Bearer ' . $accessToken,
        'Content-Type: application/json'
    ]);

    $response = curl_exec($ch);
    $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    curl_close($ch);

    $result = json_decode($response, true);

    if ($result['isSuccesful']) {
        $ocrResult = $result['ocrResult'];
        echo "✓ Extração realizada com sucesso!\n";
        echo "Tipo: {$ocrResult['typeRecognized']}\n";
        echo "Campos: " . count($ocrResult['fields']) . "\n\n";
        echo "Dados extraídos:\n";

        foreach ($ocrResult['fields'] as $field) {
            echo "  {$field['name']}: {$field['value']} ";
            echo "(confiança: {$field['confidence']}%)\n";
        }

        return $ocrResult;
    } else {
        echo "✗ Erro: {$result['error']}\n";
        return null;
    }
}

// Uso
$token = 'seu_access_token_aqui';
extractDocumentData($token, './documento_rg.jpg', 'RG');
?>
package main

import (
    "bytes"
    "encoding/base64"
    "encoding/json"
    "fmt"
    "io"
    "net/http"
    "os"
)

type OcrField struct {
    Name        string  `json:"name"`
    Value       string  `json:"value"`
    BoundingBox []int   `json:"boundingBox"`
    Confidence  int     `json:"confidence"`
}

type OcrResult struct {
    TypeRecognized   string               `json:"typeRecognized"`
    DigitalDocument  bool                 `json:"digitalDocument"`
    Fields           []OcrField           `json:"fields"`
    Statistics       map[string]int       `json:"statistics"`
}

type ExtractResponse struct {
    OcrResult   OcrResult `json:"ocrResult"`
    IsSuccesful bool      `json:"isSuccesful"`
    StatusCode  int       `json:"statusCode"`
    Timestamp   string    `json:"timestamp"`
    Error       string    `json:"error,omitempty"`
}

func imageToBase64(filePath string) (string, error) {
    data, err := os.ReadFile(filePath)
    if err != nil {
        return "", err
    }
    return base64.StdEncoding.EncodeToString(data), nil
}

func extractDocumentData(accessToken, imagePath, docType string) (*ExtractResponse, error) {
    url := "https://hml.flexextractor.com.br/api/v2/FlexOCR/Extract/Json"

    imageBase64, err := imageToBase64(imagePath)
    if err != nil {
        return nil, err
    }

    payload := map[string]string{
        "imageBase64": imageBase64,
    }

    if docType != "" {
        payload["typealias"] = docType
    }

    jsonData, err := json.Marshal(payload)
    if err != nil {
        return nil, err
    }

    req, err := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
    if err != nil {
        return nil, err
    }

    req.Header.Set("Authorization", "Bearer "+accessToken)
    req.Header.Set("Content-Type", "application/json")

    client := &http.Client{}
    resp, err := client.Do(req)
    if err != nil {
        return nil, err
    }
    defer resp.Body.Close()

    body, err := io.ReadAll(resp.Body)
    if err != nil {
        return nil, err
    }

    var result ExtractResponse
    if err := json.Unmarshal(body, &result); err != nil {
        return nil, err
    }

    if result.IsSuccesful {
        fmt.Println("✓ Extração realizada com sucesso!")
        fmt.Printf("Tipo: %s\n", result.OcrResult.TypeRecognized)
        fmt.Printf("Campos: %d\n\n", len(result.OcrResult.Fields))
        fmt.Println("Dados extraídos:")

        for _, field := range result.OcrResult.Fields {
            fmt.Printf("  %s: %s (confiança: %d%%)\n",
                field.Name, field.Value, field.Confidence)
        }
    } else {
        fmt.Printf("✗ Erro: %s\n", result.Error)
    }

    return &result, nil
}

func main() {
    token := "seu_access_token_aqui"
    _, err := extractDocumentData(token, "./documento_rg.jpg", "RG")
    if err != nil {
        fmt.Printf("Erro: %v\n", err)
    }
}

Boas Práticas

Recomendações:
  • Resolução: Mínimo 300 DPI, ideal 600 DPI
  • Formato: PDF para documentos digitalizados, JPG/PNG para fotos
  • Iluminação: Uniforme, sem sombras ou reflexos
  • Foco: Imagem nítida, sem desfoque
  • Enquadramento: Documento completo, sem cortes
  • Tamanho: Máximo 10MB por imagem
Evite:
  • Imagens desfocadas ou tremidas
  • Flash direto (causa reflexos)
  • Documentos dobrados ou amassados
  • Baixa resolução (< 150 DPI)
  • Imagens muito comprimidas (qualidade baixa)
Otimização de Requisições:
  • Reutilize o access_token enquanto válido
  • Implemente cache de resultados quando aplicável
  • Processe em lote quando possível
  • Use compressão de imagem antes de Base64
Monitoramento:
  • Registre tempos de resposta (campo statistics)
  • Monitore taxa de sucesso (isSuccesful)
  • Acompanhe níveis de confiança médios
  • Configure alertas para falhas recorrentes
Exemplo de estatísticas:
{
  "statistics": {
    "convert": 901,   // Conversão: ~1s
    "ocr1": 2370,     // OCR principal: ~2.4s
    "ocr2": 0,        // OCR secundário: não usado
    "parse": 1294     // Parsing: ~1.3s
  }
  // Total: ~4.5 segundos
}
Interpretando Confidence:
Nível%Ação Recomendada
Excelente95-100Aceitar automaticamente
Bom85-94Aceitar com revisão opcional
Regular70-84Revisar manualmente
Baixo< 70Solicitar nova imagem
Validação de Dados:
function validateExtractedData(fields) {
  const warnings = [];

  fields.forEach(field => {
    // Verifica confiança baixa
    if (field.confidence < 70) {
      warnings.push(`${field.name}: confiança baixa (${field.confidence}%)`);
    }

    // Validações específicas
    if (field.name === 'CPF') {
      if (!isValidCPF(field.value)) {
        warnings.push(`CPF inválido: ${field.value}`);
      }
    }

    if (field.name === 'DATA_NASCIMENTO') {
      if (!isValidDate(field.value)) {
        warnings.push(`Data inválida: ${field.value}`);
      }
    }
  });

  return warnings;
}
Erros Comuns:
StatusCodeErroSolução
401Token inválidoRenove o token
400Imagem inválidaVerifique formato e tamanho
413Imagem muito grandeReduza o tamanho (< 10MB)
500Erro no servidorTente novamente com backoff
Implementação de Retry:
import time

def extract_with_retry(token, image, max_attempts=3):
    for attempt in range(max_attempts):
        try:
            result = extract_document_data(token, image)
            if result['isSuccesful']:
                return result
        except Exception as e:
            if attempt < max_attempts - 1:
                wait_time = 2 ** attempt  # Backoff exponencial
                print(f"Tentativa {attempt + 1} falhou. "
                      f"Aguardando {wait_time}s...")
                time.sleep(wait_time)
            else:
                raise

    return None
Proteção de Dados:
  1. Imagens:
    • Criptografe imagens em trânsito (HTTPS)
    • Não armazene Base64 em logs
    • Delete imagens após processamento
    • Implemente controle de acesso
  2. Dados Extraídos:
    • Dados pessoais são sensíveis (LGPD)
    • Criptografe armazenamento
    • Implemente auditoria de acesso
    • Defina política de retenção
  3. Tokens:
    • Use HTTPS obrigatoriamente
    • Nunca logue tokens completos
    • Renove periodicamente
    • Implemente timeout de sessão
Exemplo de sanitização:
function sanitizeForLog(data) {
  return {
    typeRecognized: data.ocrResult?.typeRecognized,
    fieldsCount: data.ocrResult?.fields?.length,
    timestamp: data.timestamp,
    success: data.isSuccesful
    // Não inclui valores dos campos (dados pessoais)
  };
}