Idempotência
Todo endpoint que grava uma ação deve receber um client_event_id. Esse identificador impede duplicidade quando o aplicativo reenviar o mesmo evento após timeout, perda de conexão ou resposta não recebida.
Resposta para evento já registrado
{
"success": true,
"msg": "Evento já registrado (idempotente).",
"data": {
"already_registered": true,
"client_event_id": "550e8400-e29b-41d4-a716-446655440000"
}
}
success=true ou already_registered=true significa que o evento pode ser retirado da fila de envio.
Tabelas locais
Dados do aparelho
CREATE TABLE app_dispositivo (
id INTEGER PRIMARY KEY AUTOINCREMENT,
device_id INTEGER,
device_name TEXT NOT NULL,
account_type TEXT NOT NULL DEFAULT 'utg',
id_utg INTEGER,
nome_utg TEXT,
id_programa INTEGER,
nome_programa TEXT,
ultima_validacao_em TEXT,
ultimo_login_online_em TEXT,
offline_ate TEXT,
criado_em TEXT NOT NULL,
atualizado_em TEXT
);
Fila de eventos
CREATE TABLE app_eventos_sync (
id INTEGER PRIMARY KEY AUTOINCREMENT,
client_event_id TEXT NOT NULL UNIQUE,
tipo_evento TEXT NOT NULL,
endpoint TEXT NOT NULL,
payload_json TEXT NOT NULL,
arquivo_local TEXT NULL,
status_sync TEXT NOT NULL DEFAULT 'pendente',
tentativas_envio INTEGER NOT NULL DEFAULT 0,
ultimo_erro TEXT NULL,
criado_em TEXT NOT NULL,
ultima_tentativa_em TEXT NULL,
enviado_em TEXT NULL
);
Geração do client_event_id
Usar uma biblioteca UUID compatível com React Native. Não usar Math.random() para eventos definitivos.
import * as Crypto from 'expo-crypto';
const clientEventId = Crypto.randomUUID();
Regra: o identificador é criado uma única vez, salvo no SQLite e reutilizado em todas as tentativas.
Armazenamento local
- SQLite: fila, dados do aparelho, cache e dados necessários para operação offline.
- FileSystem: fotos e arquivos aguardando envio.
- SecureStore: somente o
device_tokene dados sensíveis estritamente necessários. - Configurações locais: versão instalada,
last_sync_ate preferências não sensíveis.
Campos da requisição
| Campo | Obrigatório | Descrição |
|---|---|---|
app_version | Sim | Versão instalada no aparelho. |
last_sync_at | Não | Data e hora da última sincronização concluída. |
eventos | Não | Lista JSON de eventos pendentes gerados pela UTG. |
Como tratar a resposta
- Marcar como enviados somente os
client_event_idpresentes emeventos_confirmados. - Atualizar os dados locais do aparelho e da UTG.
- Atualizar
ultima_validacao_emeoffline_ate. - Substituir o cache pelos blocos recebidos em
dados_atualizados. - Atualizar
last_sync_atusandoserver_time. - Não apagar eventos não confirmados.
Exemplo de chamada cURL
curl -X POST "https://institutog10bio.com.br/router/action.php" \
-H "Content-Type: application/x-www-form-urlencoded; charset=UTF-8" \
-H "X-APP-KEY: SUA_APP_KEY" \
-H "X-DEVICE-TOKEN: SEU_DEVICE_TOKEN" \
--data-urlencode "action=apiG10bio_utg" \
--data-urlencode "f=sincronizacao_offline" \
--data-urlencode "app_version=1.0.0" \
--data-urlencode "last_sync_at=2026-07-29 15:30:00" \
--data-urlencode 'eventos=[]'