Pular para o conteúdo
GedFlow

Começar a usar a API

Do zero à primeira chamada: peça a integração, guarde o token e faça a primeira busca no acervo.

Para: Desenvolvedores dos sistemas da prefeitura

A API REST do GedFlow permite que outros sistemas da prefeitura (tributário, protocolo, portal da transparência, sistema de obras) consultem o acervo digital, baixem documentos e cadastrem novos documentos, sem ninguém precisar abrir o painel.

Este guia leva você do zero à primeira resposta em poucos minutos. Os detalhes de cada assunto ficam nas páginas seguintes desta seção.

O que você precisa saber antes#

  • Endereço base: https://gedflow.com.br/api/v1
  • Formato: JSON em UTF-8, nas requisições e nas respostas. Envie sempre Accept: application/json.
  • Autenticação: token Bearer no cabeçalho Authorization.
  • Identificadores: todo recurso é identificado por um ULID de 26 caracteres (ex.: 01JB7Q4ZK3M2X8V5N6P9R1T0SA). Números internos nunca aparecem na API.
  • Datas: ISO 8601 com fuso (ex.: 2026-09-14T13:05:22+00:00). Datas sem hora no formato AAAA-MM-DD.
  • Referência completa e interativa: /docs/api, gerada a partir do próprio código, sempre atualizada.

Passo 1: peça a integração ao administrador da prefeitura#

Quem cria a integração é o administrador da prefeitura, no painel dela, em Integrações > Nova integração. Não existe cadastro de desenvolvedor por conta própria: o acesso é sempre concedido pela prefeitura, que é a dona dos dados.

Combine com ele:

  1. O nome do sistema (ex.: "Sistema tributário").
  2. Os escopos, ou seja, o que o sistema pode fazer: ler, buscar, consultar por campo, baixar, cadastrar, receber avisos. Peça só o necessário. Veja Escopos e recorte.
  3. O recorte: quais setores e quais classes do plano de classificação o sistema enxerga.
  4. Os IPs liberados do seu servidor (recomendado).
  5. O endereço do webhook, se o seu sistema precisar ser avisado quando um documento mudar. Veja Webhooks.

O passo a passo do lado da prefeitura está em Integrações com outros sistemas.

Passo 2: guarde o token#

Ao salvar a integração, o painel mostra o token uma única vez. Ele tem este formato:

12|q8Zr3VxK0bN7yTfP2mWcL5sHdA9uJ4eGiR6oYkQ1

O administrador copia e entrega a você por um canal seguro. Guarde em um cofre de segredos ou em variável de ambiente, nunca no código-fonte nem no repositório.

Passo 3: confira quem você é#

A chamada GET /me é o "alô, testando" da API. Ela devolve a prefeitura e, para integrações, os escopos do token.

curl https://gedflow.com.br/api/v1/me \
  -H "Authorization: Bearer $GEDFLOW_TOKEN" \
  -H "Accept: application/json"
{
  "id": "01JB7Q4ZK3M2X8V5N6P9R1T0SA",
  "name": "Integração: Sistema tributário",
  "tenant": { "id": "01J9ZC0W5E8Y3B6N2K7M4P1QXD", "name": "Prefeitura de Exemplo" },
  "integration": {
    "id": "01JB7Q4ZJ8T5R2W9X3V6N1M0KC",
    "name": "Sistema tributário",
    "scopes": ["documents:read", "search", "lookup"]
  }
}

Passo 4: a primeira busca#

A busca procura nos metadados e no texto reconhecido (OCR) das páginas. Exige o escopo search. Use aspas para a expressão exata.

curl#

curl --get https://gedflow.com.br/api/v1/search \
  -H "Authorization: Bearer $GEDFLOW_TOKEN" \
  -H "Accept: application/json" \
  --data-urlencode 'q="alvará de funcionamento"' \
  --data-urlencode "per_page=10"

PHP (Guzzle)#

<?php

use GuzzleHttp\Client;

$client = new Client([
    'base_uri' => 'https://gedflow.com.br/api/v1/',
    'headers' => [
        'Authorization' => 'Bearer '.getenv('GEDFLOW_TOKEN'),
        'Accept' => 'application/json',
    ],
    'timeout' => 30,
]);

$response = $client->get('search', ['query' => ['q' => '"alvará de funcionamento"', 'per_page' => 10]]);
$result = json_decode((string) $response->getBody(), true, flags: JSON_THROW_ON_ERROR);

foreach ($result['data'] as $hit) {
    printf("%s  %s (página %s)\n", $hit['document']['code'], $hit['document']['title'], $hit['page'] ?? '-');
}

Python (requests)#

import os
import requests

session = requests.Session()
session.headers.update({
    "Authorization": f"Bearer {os.environ['GEDFLOW_TOKEN']}",
    "Accept": "application/json",
})

response = session.get(
    "https://gedflow.com.br/api/v1/search",
    params={"q": '"alvará de funcionamento"', "per_page": 10},
    timeout=30,
)
response.raise_for_status()

for hit in response.json()["data"]:
    print(hit["document"]["code"], hit["document"]["title"], hit["page"])

A resposta#

{
  "data": [
    {
      "document": {
        "id": "01J9ZD3H7K2M5N8P1Q4R6S9T0V",
        "code": "000123",
        "title": "Alvará de funcionamento: Padaria Pão Quente",
        "subject": "alvará; funcionamento; comércio",
        "author": "Secretaria da Fazenda",
        "produced_at": "2018-03-12",
        "produced_at_precision": "day",
        "produced_place": "Exemplo/SP",
        "confidentiality": "public",
        "status": "authenticated",
        "document_type": { "id": "01J9ZC4A1B2C3D4E5F6G7H8J9K", "name": "Alvará de funcionamento" },
        "classification": { "code": "005.02.01", "name": "Licenciamento de atividades", "final_destination": "permanent" },
        "sector": { "id": "01J9ZC2X9Y8W7V6U5T4S3R2Q1P", "name": "Fiscalização de Posturas" },
        "custom_fields": { "inscricao": "01.02.003", "cpf_requerente": "•••" },
        "created_at": "2026-08-20T14:02:11+00:00",
        "updated_at": "2026-09-14T13:05:22+00:00"
      },
      "page": 1,
      "snippet": "... concede o alvará de funcionamento ao estabelecimento ..."
    }
  ],
  "meta": { "total": 1, "page": 1, "per_page": 10 }
}
  • page é a página do arquivo onde o texto foi encontrado (pode vir null quando o acerto foi nos metadados).
  • snippet é um trecho em texto puro, sem HTML.
  • Campos sensíveis aparecem como ••• se a integração não tiver o escopo sensitive.

Paginação#

As listas usam page (a partir de 1) e per_page (padrão 20, máximo 100).

Lista de documentos (GET /documents) segue o formato padrão de coleção paginada, com data, links e meta:

{
  "data": [ { "id": "01J9ZD3H7K2M5N8P1Q4R6S9T0V", "title": "..." } ],
  "links": {
    "first": "https://gedflow.com.br/api/v1/documents?page=1",
    "last": "https://gedflow.com.br/api/v1/documents?page=8",
    "prev": null,
    "next": "https://gedflow.com.br/api/v1/documents?page=2"
  },
  "meta": { "current_page": 1, "from": 1, "last_page": 8, "path": "https://gedflow.com.br/api/v1/documents", "per_page": 20, "to": 20, "total": 156 }
}

Para percorrer tudo, siga links.next até ele vir null.

Busca (GET /search) devolve um meta mais enxuto: total, page e per_page. Calcule a última página com ceil(total / per_page).

Consulta por campo (GET /lookup) não é paginada: devolve até 100 documentos, os alterados mais recentemente primeiro.

Sincronizar só o que mudou#

Para manter uma cópia local dos metadados, use o filtro updated_since na lista de documentos. A lista vem ordenada da alteração mais recente para a mais antiga.

curl --get https://gedflow.com.br/api/v1/documents \
  -H "Authorization: Bearer $GEDFLOW_TOKEN" \
  -H "Accept: application/json" \
  --data-urlencode "updated_since=2026-09-01T00:00:00Z" \
  --data-urlencode "per_page=100"

Formato de erro#

Toda resposta de erro é JSON com um campo message, em português sempre que a regra é do GedFlow:

{ "message": "A integração não tem o escopo \"search\"." }

Erros de validação (422) trazem também errors, com a lista de problemas por campo:

{
  "message": "É obrigatória a indicação de um valor para o campo título.",
  "errors": {
    "title": ["É obrigatória a indicação de um valor para o campo título."]
  }
}
Código Quando acontece
200 / 201 Deu certo (201 quando algo foi criado).
204 Deu certo, sem conteúdo na resposta.
401 Token ausente, inválido, expirado ou integração revogada/inativa. Veja Autenticação.
403 O token é válido, mas falta escopo, o IP não está liberado ou o setor está fora do recorte.
404 O recurso não existe ou está fora do seu recorte (ex.: {"message": "Documento não encontrado."}). A API não revela a existência de documentos que você não pode ver.
409 Conflito: arquivo ainda em processamento, ou envio de um arquivo idêntico (mesmo SHA-256) a outro já existente.
422 Dados inválidos ou regra de negócio violada (a message explica qual).
429 Limite de requisições atingido. Espere o tempo de Retry-After. Veja Limites de uso.
5xx Falha do nosso lado. Tente de novo com espera crescente.

Próximos passos#