Principal Boas práticas na construção de Eddies Como transformar seu Google Sheets em uma API consultável pelo Eddie

Como transformar seu Google Sheets em uma API consultável pelo Eddie

Última atualização em May 21, 2026

Quando usar

  • Você tem dados em uma planilha Google Sheets que precisa ler/criar/atualizar/deletar via HTTP
  • Você quer substituir uma API real por algo mais simples para casos pequenos ou MVPs
  • Você quer expor dados gerenciáveis por times não técnicos diretamente para o Eddie consumir

Pré-requisitos

  • Conta Google com acesso ao Google Sheets
  • Planilha com cabeçalho na primeira linha e dados estruturados
  • Permissão para publicar Web Apps no Google Apps Script com a sua conta

A aba da planilha não pode ter nome com acentos (, ´ ~ ^). Use nomes simples (ex: Clientes, Pedidos).


Sobre este artigo

Esta solução transforma sua planilha do Google Sheets em uma API web dinâmica, permitindo que você (ou seus clientes) leiam, criem, atualizem e deletem dados via requisições HTTP. Tudo rodando no Google Apps Script gratuitamente — sem servidores complexos.

Com essa API, você pode:

  • Ler todos os dados

  • Buscar registros específicos

  • Adicionar novas linhas

  • Atualizar linhas existentes

  • Deletar linhas

Tudo via GET e POST simples.


Passo a passo

Etapa 1 — Copiar o código completo da API

Cole o script abaixo no Google Apps Script:

/**
 * API Planilha Google – Versão FINAL CORRIGIDA
 * Busca com igualdade exata (===)
 * Lógica de métodos corrigida
 */
const PLANILHA_ID = '[PLANILHA_ID]';
const SHEET_NAME = '[ABA_SHEET_NAME]';
const CACHE_TTL = 10 * 60 * 1000; // 10 minutos

let cache = { data: [], headers: [], lastUpdate: 0 };

// Entradas da Web App
function doGet(e) { return handleRequest(e, 'GET'); }
function doPost(e) { return handleRequest(e, 'POST'); }

function handleRequest(e, httpMethod) {
  let payload = {};

  // Lê o body JSON (apenas em POST)
  if (httpMethod === 'POST' && e.postData && e.postData.type === 'application/json') {
    try {
      payload = JSON.parse(e.postData.contents || '{}');
    } catch (err) {
      return jsonResponse({ status: 'error', message: 'JSON inválido no body' });
    }
  }

  // Atualiza cache se necessário
  if (Date.now() - cache.lastUpdate > CACHE_TTL) {
    refreshCache();
  }

  // Detecta método simulado (PATCH ou DELETE)
  const simulatedMethod = (payload._method || e.parameter.method || '').toUpperCase();

  // GET → Lista tudo
  if (httpMethod === 'GET') {
    return jsonResponse({
      status: 'success',
      total: cache.data.length,
      data: cache.data
    });
  }

  // POST
  if (httpMethod === 'POST') {
    // PATCH simulado
    if (simulatedMethod === 'PATCH') {
      if (!payload.filter || !payload.updates) {
        return jsonResponse({ status: 'error', message: 'PATCH precisa de "filter" e "updates"' });
      }
      return jsonResponse(updateRow(payload.filter.column, payload.filter.value, payload.updates));
    }

    // DELETE simulado
    if (simulatedMethod === 'DELETE') {
      if (!payload.filter) {
        return jsonResponse({ status: 'error', message: 'DELETE precisa de "filter"' });
      }
      return jsonResponse(deleteRow(payload.filter.column, payload.filter.value));
    }

    // Busca com filtro (igualdade exata)
    if (payload.filter && payload.filter.column && payload.filter.value !== undefined) {
      const col = payload.filter.column.trim();
      const val = payload.filter.value.toString();

      const resultados = cache.data.filter(row =>
        String(row[col] || '') === val
      );

      return jsonResponse({
        status: 'success',
        found: resultados.length > 0,
        total: resultados.length,
        data: resultados
      });
    }

    // Criação de nova linha
    if (Object.keys(payload).length > 0) {
      return jsonResponse(createRow(payload));
    }

    return jsonResponse({ status: 'error', message: 'Body vazio ou inválido para POST' });
  }

  return jsonResponse({ status: 'error', message: 'Método HTTP não suportado' });
}

// Atualiza cache
function refreshCache() {
  const sheet = SpreadsheetApp.openById(PLANILHA_ID).getSheetByName(SHEET_NAME);
  const [header, ...rows] = sheet.getDataRange().getValues();

  const headers = header.map(h => String(h).trim());
  const data = rows.map(row => {
    const obj = {};
    headers.forEach((h, i) => obj[h] = row[i]);
    return obj;
  });

  cache = { data, headers, lastUpdate: Date.now() };
}

// Cria nova linha
function createRow(obj) {
  const sheet = SpreadsheetApp.openById(PLANILHA_ID).getSheetByName(SHEET_NAME);
  const headers = cache.headers;

  const invalidos = Object.keys(obj).filter(k => !headers.includes(k));
  if (invalidos.length > 0) {
    return { status: 'error', message: `Campos inválidos: ${invalidos.join(', ')}` };
  }

  const novaLinha = headers.map(h => obj[h] !== undefined ? obj[h] : '');
  sheet.appendRow(novaLinha);

  const novoObj = {};
  headers.forEach((h, i) => novoObj[h] = novaLinha[i]);
  cache.data.push(novoObj);

  return { status: 'success', message: 'Linha criada', data: novoObj };
}

// Atualiza linha (primeira ocorrência)
function updateRow(coluna, valor, updates) {
  const idx = cache.data.findIndex(row =>
    String(row[coluna] || '') === String(valor)
  );

  if (idx === -1) return { status: 'error', message: 'Linha não encontrada' };

  const sheet = SpreadsheetApp.openById(PLANILHA_ID).getSheetByName(SHEET_NAME);
  const headers = cache.headers;
  const linha = idx + 2;

  Object.keys(updates).forEach(chave => {
    if (headers.includes(chave)) {
      const col = headers.indexOf(chave) + 1;
      sheet.getRange(linha, col).setValue(updates[chave]);
      cache.data[idx][chave] = updates[chave];
    }
  });

  return { status: 'success', message: 'Linha atualizada', data: cache.data[idx] };
}

// Deleta linha
function deleteRow(coluna, valor) {
  const idx = cache.data.findIndex(row =>
    String(row[coluna] || '') === String(valor)
  );

  if (idx === -1) return { status: 'error', message: 'Linha não encontrada' };

  const sheet = SpreadsheetApp.openById(PLANILHA_ID).getSheetByName(SHEET_NAME);
  sheet.deleteRow(idx + 2);

  const deletado = cache.data.splice(idx, 1)[0];
  return { status: 'success', message: 'Linha deletada', deletedData: deletado };
}

// Resposta JSON
function jsonResponse(obj) {
  return ContentService
    .createTextOutput(JSON.stringify({ data: obj }, null, 2))
    .setMimeType(ContentService.MimeType.JSON);
}

Etapa 2 — Configurar as informações da planilha

Antes de salvar, substitua dois valores no código:

[PLANILHA_ID] — ID único da sua planilha

  • Abra sua planilha no navegador

  • Olhe a URL: https://docs.google.com/spreadsheets/d/ABC123XYZ456/edit#gid=0

  • O ID é a parte entre /d/ e /edit — no exemplo, ABC123XYZ456

  • Substitua [PLANILHA_ID] por esse valor (sem aspas extras)

Onde encontrar o ID da planilha

[ABA_SHEET_NAME] — Nome da aba da planilha

  • Na parte inferior da planilha, veja o nome da aba (padrão: Planilha1 ou Sheet1)

  • Use exatamente o nome que aparece (sensível a maiúsculas/minúsculas)

  • Sem acentos (evite , ´ ~ ^)

Onde ver o nome da aba


Etapa 3 — Abrir o editor de scripts e colar o código

  1. Na planilha aberta, clique em Extensões → Apps Script

    Acessar Apps Script

  2. Apague todo o código padrão (ex: function myFunction() {})

    Apagar código padrão

  3. Cole o código completo (com PLANILHA_ID e SHEET_NAME substituídos), clique em Salvar (disquete) e dê um nome ao projeto

    Salvar projeto


Etapa 4 — Publicar como Web App

  1. No editor, clique em Implantar → Nova implantação

  2. Clique em Selecionar tipo → Aplicativo da web

  3. Preencha:

    • Executar como: Eu (sua conta)

    • Quem tem acesso: Qualquer pessoa

  4. Clique em Implantar

  5. Autorize as permissões (pode pedir confirmação — clique em Avançado → Ir para o projeto → Permitir)

  6. Copie a URL do aplicativo web (ex: https://script.google.com/macros/s/.../exec) — essa é a sua API

    URL do Web App


Como usar a API (exemplos)

Substitua SUA_URL_AQUI pela URL copiada na etapa 4. Para POST, sempre inclua o header Content-Type: application/json.

Listar todos os dados (GET)

curl "SUA_URL_AQUI"

Resposta:

{
  "data": {
    "status": "success",
    "total": 2,
    "data": [
      { "id": "1", "nome": "João Silva", "email": "[email protected]", "saldo": 1500 },
      { "id": "2", "nome": "Maria Oliveira", "email": "[email protected]", "saldo": 3200 }
    ]
  }
}

Buscar com filtro (POST)

curl -X POST "SUA_URL_AQUI" \
  -H "Content-Type: application/json" \
  -d '{ "filter": { "column": "id", "value": "1" } }'

Adicionar nova linha (POST)

curl -X POST "SUA_URL_AQUI" \
  -H "Content-Type: application/json" \
  -d '{ "id": "3", "nome": "Carlos Santos", "email": "[email protected]", "saldo": 5000 }'

Atualizar linha existente (POST com _method: PATCH)

curl -X POST "SUA_URL_AQUI" \
  -H "Content-Type: application/json" \
  -d '{
    "_method": "PATCH",
    "filter": { "column": "id", "value": "3" },
    "updates": { "nome": "Carlos Santos Atualizado", "saldo": 6000 }
  }'

Deletar linha (POST com _method: DELETE)

curl -X POST "SUA_URL_AQUI" \
  -H "Content-Type: application/json" \
  -d '{ "_method": "DELETE", "filter": { "column": "id", "value": "3" } }'

Conclusão

Pronto! Agora você tem uma API funcional rodando no Google Apps Script gratuitamente, pronta para ser consumida pelo Eddie via blocos HTTP Request.

Se precisar de ajuda, o time de suporte da Cloud Humans está disponível para acelerar suas integrações.


Observações