Pular para o conteúdo

Integrar

API

Leia e crie propostas do seu servidor com a chave secreta.

Nesta página

Visão geral

ItemValor
Endereçohttps://api.lafra.app
Versão/v1
FormatoJSON (pedidos e respostas), em UTF-8
AutenticaçãoChave secreta no cabeçalho Authorization
Limite60 pedidos por minuto por chave
NavegadorNão: a API não libera as respostas para páginas da web (sem CORS)

A API lê e cria propostas da empresa dona da chave. Ela nunca enxerga dados de outra empresa. As respostas vêm com Cache-Control: no-store. Valores em dinheiro são inteiros em centavos (1840000 = R$ 18.400,00), na moeda da empresa.

Autenticação

Mande a chave secreta em todo pedido, no cabeçalho Authorization, com a palavra Bearer:

Terminal
curl https://api.lafra.app/v1/propostas \
  -H "Authorization: Bearer sk_live_SUA_CHAVE_SECRETA"
  • sk_live_… é a de Produção; sk_test_…, a de Teste. Cada uma tem 30 símbolos depois do prefixo.
  • A chave é gerada em Propostas › Integração › Chaves de API (dono e administradores). Ela aparece inteira uma vez só; a Lafra guarda apenas uma impressão dela (SHA-256), não a chave.
  • Chave ausente, com formato errado, trocada ou revogada: 401 {"erro":"chave_invalida"}.
  • Empresa sem plano ativo: 403 {"erro":"sem_plano"}.

Nos exemplos abaixo, a chave está na variável de ambiente LAFRA_CHAVE. Guarde-a assim no seu servidor, nunca no código. Segurança.

Listar propostas

GET/v1/propostas

As propostas da empresa (as excluídas não aparecem), da mais nova para a mais antiga.

ParâmetroTipoDescrição
statustexto, opcionalSó as deste status: rascunho, enviada, aprovada, recusada, vencida ou substituida.
limiteinteiro, opcionalDe 1 a 100. Padrão: 50.
depoisuuid, opcionalO proximo da página anterior. Paginação.
Terminal
curl "https://api.lafra.app/v1/propostas?status=enviada&limite=20" \
  -H "Authorization: Bearer $LAFRA_CHAVE"
200 OK
{
  "propostas": [
    {
      "id": "0b7c9a52-3d1e-4f6a-9c1b-2e8f5d4a7b10",
      "codigo": "PR-0042",
      "titulo": "SPT – Construtora Quincas Borba",
      "cliente": "Construtora Quincas Borba",
      "status": "enviada",
      "valor_total": 1840000,
      "criada_em": "2026-10-27T13:05:12.481+00:00",
      "enviada_em": "2026-10-27",
      "valida_ate": "2026-11-11",
      "link": "https://lafra.app/p/5f2d8c1e-7a44-4b9e-8e0d-3c6b1a9f2e77"
    }
  ],
  "proximo": "0b7c9a52-3d1e-4f6a-9c1b-2e8f5d4a7b10"
}

Ler uma proposta

GET/v1/propostas/{id}

Uma proposta pelo id (o da lista ou o da criação). A resposta é o objeto proposta. Proposta que não existe, excluída ou de outra empresa: 404 {"erro":"nao_encontrada"}.

Terminal
curl https://api.lafra.app/v1/propostas/0b7c9a52-3d1e-4f6a-9c1b-2e8f5d4a7b10 \
  -H "Authorization: Bearer $LAFRA_CHAVE"

Criar uma proposta

POST/v1/propostas

Cria uma proposta em elaboração (status rascunho), que a equipe revisa e envia pelo app. O corpo pode ser JSON (Content-Type: application/json) ou formulário (application/x-www-form-urlencoded, o -d do curl), com até 16 KB.

CampoObrigatórioRegras
clientesimNome do cliente, até 120 letras.
servicosimCódigo do serviço (lista), entre os que a empresa oferece em Configurações › Serviços e preços.
furossimQuantidade de pontos, de 1 a 999.
profundidade_mnos serviços por metroProfundidade de cada ponto em metros, maior que 0 e até 200, com até 2 casas (aceita vírgula). Vale para spt, trado, rotativa, poco, piezometro e cpt; nos outros é ignorada.
enderecosimEndereço da obra, até 300 letras.
titulonãoAté 160 letras. Sem ele: “<serviço> – <cliente>” (ex.: “SPT – Construtora Quincas Borba”).
Terminal · JSON
curl https://api.lafra.app/v1/propostas \
  -H "Authorization: Bearer $LAFRA_CHAVE" \
  -H "Content-Type: application/json" \
  -d '{
    "cliente": "Construtora Quincas Borba",
    "servico": "spt",
    "furos": 4,
    "profundidade_m": 18,
    "endereco": "Rua do Ouvidor, 50, Centro, Rio de Janeiro - RJ",
    "titulo": "SPT do edifício Humanitas"
  }'
Terminal · formulário
curl https://api.lafra.app/v1/propostas \
  -H "Authorization: Bearer $LAFRA_CHAVE" \
  -d cliente="Construtora Quincas Borba" \
  -d servico=spt -d furos=4 -d profundidade_m=18 \
  -d endereco="Rua do Ouvidor, 50, Centro, Rio de Janeiro - RJ"
201 Created
HTTP/1.1 201 Created

{
  "id": "6d1f0e3a-8b2c-4c7d-a5e9-1f4b7c2d9a30",
  "codigo": "PR-0043",
  "status": "rascunho"
}

O que a Lafra monta

  • Um item do serviço com os pontos e a profundidade, pelo preço de Configurações › Serviços e preços (com nota fiscal).
  • O cliente: se a empresa já tem um cadastrado com o mesmo nome (sem diferença de maiúsculas), é ele; senão, um contato novo com esse nome. Cliente da lista negra é recusado com 400 {"erro":"cliente_bloqueado","campo":"cliente"}.
  • O histórico da proposta registra “Criada pela API”, e a chamada aparece na Atividade recente da Integração.
  • O codigo segue o modelo de código da empresa em Configurações › Serviços e preços (ex.: PR-0001); trate-o como texto livre.

No modo Teste

Com a sk_test_…, nada é gravado: a resposta é 200 com o que seria criado e "simulada": true. As mesmas regras dos campos valem.

200 OK
HTTP/1.1 200 OK

{
  "simulada": true,
  "status": "rascunho",
  "titulo": "SPT do edifício Humanitas",
  "cliente": "Construtora Quincas Borba",
  "valor_total": 1840000
}

O objeto proposta

CampoTipoDescrição
iduuidIdentificador da proposta.
codigotextoO código que a empresa vê (ex.: PR-0042).
titulotexto
clientetextoNome do cliente.
statustextorascunho, enviada, aprovada, recusada, vencida (enviada que passou da validade) ou substituida (trocada por uma versão nova).
valor_totalinteiroTotal em centavos, a mesma conta do Resumo da proposta.
criada_emdata e hora (ISO 8601)
enviada_emdata ou nullDia do envio ao cliente.
valida_atedata ou nullEnvio + validade da proposta (em dias corridos).
linktexto ou nullA página da proposta para o cliente; null enquanto está em elaboração.

Paginação

A lista vem em páginas de até limite propostas. Quando há mais, proximo traz um id: mande-o em depois para pegar a página seguinte. Na última página, proximo é null. Um depois que não é uma proposta da empresa dá 400 com "campo":"depois".

Terminal · todas as páginas (com jq)
depois=""
while :; do
  r=$(curl -s "https://api.lafra.app/v1/propostas?limite=100${depois:+&depois=$depois}" \
    -H "Authorization: Bearer $LAFRA_CHAVE")
  echo "$r" | jq -c '.propostas[]'
  depois=$(echo "$r" | jq -r '.proximo // empty')
  [ -z "$depois" ] && break
done

Limites de uso

  • 60 pedidos por minuto por chave. Acima disso, 429 {"erro":"limite"} com o cabeçalho Retry-After: 60 (segundos). Espere e tente de novo.
  • Corpo do POST até 16 KB (acima, 413).
  • Até 100 propostas por página.

Erros

Todo erro vem em JSON com o código em erro (e, nos dados inválidos, o primeiro campo errado em campo):

Resposta
HTTP/1.1 400 Bad Request

{ "erro": "dados_invalidos", "campo": "furos" }
HTTPerroQuando
400dados_invalidosUm parâmetro ou campo errado; campo diz qual.
400cliente_bloqueadoO cliente está na lista negra da empresa.
401chave_invalidaSem chave, chave em formato errado, trocada ou revogada.
403sem_planoA empresa está sem plano ativo.
404nao_encontradaA proposta não existe ou não é desta empresa.
404nao_encontradoO endereço não existe na API.
405metodoPedido OPTIONS (de navegador).
413grande_demaisCorpo maior que 16 KB.
415formatoCorpo que não é JSON (objeto) nem formulário.
429limiteMais de 60 pedidos no minuto; veja Retry-After.
500falhaErro do lado da Lafra. Tente de novo; se continuar, fale com o suporte.

Versões

A versão vai no caminho: hoje só existe a /v1. Toda mudança na API é anotada em Novidades. Uma boa prática: faça o seu código ignorar campos que ele não conhece nas respostas.

Hoje a API tem só as propostas (listar, ler e criar). Para receber as solicitações do site, use o webhook.