Skip to main content

Retrieve results with one-time tokens

POST /evaluate returns a single-use, short-lived JWT (result_token) you can present to GET /results/{token} once to fetch the full sanitised evaluation results. This is the lightest-weight delivery path for one-off integrations.

When to use this

  • One-off CLI tools and CI jobs that submit + wait + grab results in one process.
  • Lightweight serverless functions that don't want to keep state.
  • Anywhere you'd rather not parse evaluations and scenarios responses separately.

When not to use this

  • Long-running consumers where the 15-minute TTL is a risk. Use webhooks.
  • Anywhere you may want to refetch results later. Use GET /scenarios/{id}/results (idempotent, cacheable).

Token properties

PropertyValue
TTL900 seconds (15 minutes)
Single-useYes — the first successful call consumes the token
Bound toThe specific evaluation_id that produced it
AuthToken in path; no Authorization header required
HMACNot required on GET /results/{token}

Happy path

# 1. Submit. Save the token and evaluation_id.
RESP=$(curl -sS -X POST "$BASE/evaluate" \
-H "Authorization: Bearer $API_KEY" \
-H "X-FB-Signature: $(sign POST $PREFIX/evaluate $BODY)" \
-H "Content-Type: application/json" \
-d "$BODY")
EVAL_ID=$(echo "$RESP" | jq -r .data.evaluation_id)
TOKEN=$(echo "$RESP" | jq -r .data.result_token)

# 2. Poll lightweight status (bounded — ~4 minutes at 2s cadence).
MAX_ATTEMPTS=120
for ((attempt=1; attempt<=MAX_ATTEMPTS; attempt++)); do
S=$(curl -sS "$BASE/evaluations/$EVAL_ID" \
-H "Authorization: Bearer $API_KEY" \
-H "X-FB-Signature: $(sign GET $PREFIX/evaluations/$EVAL_ID '')" | jq -r .data.status)
case "$S" in complete|error) break ;; esac
if [[ "$attempt" -eq "$MAX_ATTEMPTS" ]]; then
echo "Timed out waiting for evaluation $EVAL_ID" >&2
exit 1
fi
sleep 2
done

# 3. Single-fetch with the token.
curl -sS "$BASE/results/$TOKEN" | jq

Status responses

If the backing evaluation is not yet complete when you call /results/{token}:

{
"ok": true,
"data": {
"status": "processing",
"message": "Results not yet available"
}
}

In this case the token is not consumed. Wait until GET /evaluations/{id} reports complete, then call /results/{token} once.

If the evaluation is complete:

{
"ok": true,
"data": {
"scenarios": [
{
"scenario_id": "4729318",
"name": "Lead sync to CRM",
"violations": [],
"module_summary": [],
"evaluated_codes": ["SEC-1", "SEC-5"],
"passing_count": 4,
"failing_count": 1
}
]
}
}

Errors

StatuserrorCauseRecommended action
400Malformed tokenToken payload missing subRe-submit via POST /evaluate
401Invalid, expired, or already-used result tokenTTL passed, token consumed, or signature mismatchSwitch to GET /evaluations/{id} then GET /scenarios/{id}/results
404Evaluation not foundReferenced evaluation deletedRe-submit

Fallback to polling

If the token expires before you fetch:

# Status...
curl -sS "$BASE/evaluations/$EVAL_ID" \
-H "Authorization: Bearer $API_KEY" \
-H "X-FB-Signature: $(sign GET $PREFIX/evaluations/$EVAL_ID '')"

# ...then per-scenario detail (idempotent, no token).
curl -sS "$BASE/scenarios/4729318/results" \
-H "Authorization: Bearer $API_KEY" \
-H "X-FB-Signature: $(sign GET $PREFIX/scenarios/4729318/results '')"

Next steps