Pular para o conteúdo

GET /v1/export/decisions

Faça streaming de cada decisão de uma janela como JSON-Lines (NDJSON), uma linha por linha, terminado por uma única linha de trailer inline que carrega um checksum SHA-256 sobre o body. Projetado como o “matador de lock-in”: você pode sair a qualquer momento, com todos os dados que a Floopy usou para otimizar em seu nome.

GET https://api.floopy.ai/v1/export/decisions
Authorization: Bearer <your-floopy-api-key>
  • Permissão: read_permission.
  • Flag de plano: has_audit_api e plan_features.log_retention_days >= 30. Disponível nos planos Pro e Enterprise.
  • Atrás do kill switch de canary por organização.
FieldTypeRequiredConstraintsDefault
fromISO8601YesInício inclusivo.
toISO8601YesFim inclusivo. to - from ≤ 90 dias.
formatstringNoAtualmente apenas jsonl. Qualquer outro valor retorna 415.jsonl

Uma checagem pré-execução de contagem estimada de linhas rejeita exports cujo conjunto de resultados excederia floopy_export_max_rows (default 5_000_000) com 400 estimated_payload_too_large.

  • Content-Type: application/x-ndjson
  • Um objeto JSON por linha, formato idêntico a GET /v1/decisions/{request_id} (com a projeção fixa EXPORT_FIELDS — bodies nunca são exportados).
  • A última linha é um trailer JSONL inline que carrega metadados de integridade e agregação.

Quando qualquer decisão na janela teve used_shared_pool_prior == true, a resposta também carrega:

Floopy-Aggregation-Notice: contains-shared-pool-influenced-decisions

Isso é uma dica — o sinal autoritativo vive no campo aggregation_signal_present do trailer.

A última linha do stream é o trailer. Ela é detectada pela chave marcadora literal _floopy_export_trailer: true.

{
"_floopy_export_trailer": true,
"outcome": "completed",
"row_count": 12345,
"byte_count": 18234567,
"checksum_sha256": "5f4dcc3b5aa765d61d8327deb882cf99b8adb1c1d2c95b4f9e2c3a4d5e6f7a8b",
"aggregation_signal_present": false
}
FieldTypeDescription
_floopy_export_trailerbooleanSempre true. Use esta chave como marcador para a linha do trailer.
outcomestringcompleted, deadline_exceeded, error, ou client_disconnect.
row_countintegerNúmero de linhas de dados enviadas antes do trailer.
byte_countintegerNúmero de bytes do body enviados antes do trailer (apenas linhas de dados).
checksum_sha256hex stringSHA-256 sobre os bytes do body que precedem o trailer (cada linha de dado incluindo seu \n terminador).
aggregation_signal_presentbooleantrue se pelo menos uma linha carregou used_shared_pool_prior == true.

O checksum é calculado sobre os bytes do body descomprimidos excluindo a própria linha do trailer. Um mismatch no lado do consumidor indica uma transferência truncada ou corrupção em trânsito.

Um consumidor pode verificar a integridade localmente separando a linha do trailer, recalculando o SHA-256 sobre o restante e comparando.

Terminal window
RESPONSE=$(curl -s \
-H "Authorization: Bearer $FLOOPY_API_KEY" \
"https://api.floopy.ai/v1/export/decisions?from=$FROM&to=$TO")
# The trailer is the last line containing the marker key.
TRAILER_LINE=$(echo "$RESPONSE" | tail -n 1)
BODY=$(echo "$RESPONSE" | sed '$d') # all but the last line
CLAIMED=$(echo "$TRAILER_LINE" | jq -r '.checksum_sha256')
COMPUTED=$(printf '%s\n' "$BODY" | shasum -a 256 | awk '{print $1}')
if [ "$CLAIMED" = "$COMPUTED" ]; then
echo "OK"
else
echo "TAMPERED — claimed=$CLAIMED computed=$COMPUTED"
exit 1
fi
echo "outcome=$(echo "$TRAILER_LINE" | jq -r '.outcome') rows=$(echo "$TRAILER_LINE" | jq -r '.row_count')"

Notas:

  • No Linux substitua shasum -a 256 por sha256sum.
  • O gateway termina cada linha de dado com \n, e printf '%s\n' re-anexa um único newline final para que o recálculo combine com o que o gateway hashou.
  • Se o outcome do trailer for deadline_exceeded, error, ou client_disconnect, o export foi interrompido. O checksum continua válido para o body efetivamente entregue, mas o dataset está incompleto; reemita a requisição com uma janela mais estreita.
Statuserror codeQuando
400invalid_rangefrom/to ausentes, ou from >= to.
400range_too_wideto - from > 90 days.
400estimated_payload_too_largeA estimativa pré-execução de linhas excede floopy_export_max_rows.
403plan_required (feature: "audit_api" ou "audit_api_retention")O plano não tem a flag ou não atinge o piso de retenção de 30 dias.
404not_foundKill switch desligado para esta organização, ou endpoint não montado. Bytes idênticos por design.
415unsupported_formatformat diferente de jsonl.
429export_in_progressOutro export já está em execução para esta organização; carrega retry_after_seconds e Retry-After.
5xxinternalFalha upstream.
Terminal window
FROM="2026-04-01T00:00:00Z"
TO="2026-05-01T00:00:00Z"
curl -s -H "Authorization: Bearer $FLOOPY_API_KEY" \
"https://api.floopy.ai/v1/export/decisions?from=$FROM&to=$TO" \
> decisions.jsonl
tail -n 1 decisions.jsonl | jq .
  • Um export concorrente por organização. A próxima chamada retorna 429 export_in_progress até o export em andamento finalizar (ou o deadline de 30 minutos disparar).
  • Deadline de tempo de parede de 30 minutos. Quando disparado, o trailer carrega outcome: "deadline_exceeded". A linha do log de auditoria registra aborted_quota.
  • Projeção fixa de campos. Exports usam uma allowlist fixa de colunas — bodies (request_body, response_body) nunca são exportados.
  • Um único start a cada 5 minutos por organização além do lock, para manter a taxa de início limitada.