Skip to content

Quickstart: End-to-End Assessment Lifecycle

Quickstart: End-to-End Assessment Lifecycle

Section titled “Quickstart: End-to-End Assessment Lifecycle”

Complete walkthrough: create an organization, provision API keys, run an assessment through the full SCF-based lifecycle.

  • Standard API key with * scope (full access)
  • curl and jq installed
  • API base URL (production: https://standard-api.bekaa.eu)
Terminal window
# Set these once
export API_KEY="standard_live_..."
export TENANT_ID="your-tenant-uuid"
export BASE="https://standard-api.bekaa.eu/api/v1"
export AUTH="-H 'Authorization: Bearer $API_KEY' -H 'x-standard-tenant-id: $TENANT_ID'"

Terminal window
curl -s -X POST "$BASE/organizations" \
-H "Authorization: Bearer $API_KEY" \
-H "x-standard-tenant-id: $TENANT_ID" \
-H "Content-Type: application/json" \
-d '{"name": "Acme Corp", "slug": "acme-corp"}' | jq .

Expected:

{
"data": {
"organization_id": "uuid",
"tenant_id": "uuid",
"name": "Acme Corp",
"slug": "acme-corp",
"status": "active"
}
}
Terminal window
export ORG_ID="<organization_id from response>"

Terminal window
curl -s -X POST "$BASE/organizations/$ORG_ID/api-keys" \
-H "Authorization: Bearer $API_KEY" \
-H "x-standard-tenant-id: $TENANT_ID" \
-H "Content-Type: application/json" \
-d '{"name": "CI/CD Key", "scopes": ["assessments:read", "assessments:write", "scf:read"]}' | jq .

Expected: Returns the full key (only shown once) + masked key + scopes.


Terminal window
curl -s "$BASE/scf/versions/latest" \
-H "Authorization: Bearer $API_KEY" \
-H "x-standard-tenant-id: $TENANT_ID" | jq .
Terminal window
export SCF_VERSION_ID="<id from response>"

Pre-condition: Organization exists, SCF version exists.

Terminal window
curl -s -X POST "$BASE/assessments" \
-H "Authorization: Bearer $API_KEY" \
-H "x-standard-tenant-id: $TENANT_ID" \
-H "Content-Type: application/json" \
-d "{\"organization_id\": \"$ORG_ID\", \"name\": \"Q2 2026 SOC2 Assessment\", \"scf_version_id\": \"$SCF_VERSION_ID\"}" | jq .

Expected: Assessment in draft state.

Terminal window
export ASSESSMENT_ID="<id from response>"

Pre-condition: Assessment exists in draft state.

Terminal window
curl -s -X POST "$BASE/assessments/$ASSESSMENT_ID/documents" \
-H "Authorization: Bearer $API_KEY" \
-H "x-standard-tenant-id: $TENANT_ID" \
-F "file=@./evidence/security-policy.pdf" \
-F "description=Information Security Policy v3.1" | jq .

Pre-condition: At least one document uploaded.

Terminal window
curl -s -X POST "$BASE/assessments/$ASSESSMENT_ID/transitions" \
-H "Authorization: Bearer $API_KEY" \
-H "x-standard-tenant-id: $TENANT_ID" \
-H "Content-Type: application/json" \
-d '{"next_state": "documents_uploaded", "reason": "Evidence uploaded"}' | jq .

💡 Tip: Use GET /assessments/{id}/available-transitions to check which states are valid next.


Terminal window
# Transition through: documents_ingested → scf_pre_analysis_ready → framework_selected
# Each requires its own prerequisites to be met
curl -s -X POST "$BASE/assessments/$ASSESSMENT_ID/transitions" \
-H "Authorization: Bearer $API_KEY" \
-H "x-standard-tenant-id: $TENANT_ID" \
-H "Content-Type: application/json" \
-d '{"next_state": "framework_selected", "reason": "SOC2 framework selected"}' | jq .

Pre-condition: Assessment in framework_selected state.

Terminal window
curl -s -X POST "$BASE/assessments/$ASSESSMENT_ID/soa/draft" \
-H "Authorization: Bearer $API_KEY" \
-H "x-standard-tenant-id: $TENANT_ID" \
-H "Content-Type: application/json" \
-d '{}' | jq .
Terminal window
export SOA_VERSION_ID="<id from response>"

Terminal window
# Submit for review
curl -s -X POST "$BASE/soa/$SOA_VERSION_ID/submit-review" \
-H "Authorization: Bearer $API_KEY" \
-H "x-standard-tenant-id: $TENANT_ID" | jq .
# Approve (requires human approval gate)
curl -s -X POST "$BASE/soa/$SOA_VERSION_ID/approve" \
-H "Authorization: Bearer $API_KEY" \
-H "x-standard-tenant-id: $TENANT_ID" \
-H "Content-Type: application/json" \
-d '{"gate": "soa"}' | jq .

Pre-condition: SoA approved → assessment in soa_approved state.

Terminal window
curl -s -X POST "$BASE/assessments/$ASSESSMENT_ID/gap-analysis/draft" \
-H "Authorization: Bearer $API_KEY" \
-H "x-standard-tenant-id: $TENANT_ID" \
-H "Content-Type: application/json" \
-d '{}' | jq .
Terminal window
export GAP_VERSION_ID="<id from response>"
Terminal window
curl -s -X POST "$BASE/gap-analysis/$GAP_VERSION_ID/findings" \
-H "Authorization: Bearer $API_KEY" \
-H "x-standard-tenant-id: $TENANT_ID" \
-H "Content-Type: application/json" \
-d '{
"scf_control_id": "<control-uuid>",
"status": "partially_implemented",
"severity": "medium",
"description": "Access control policy exists but lacks periodic review schedule"
}' | jq .

Pre-condition: Gap analysis approved.

Terminal window
curl -s -X POST "$BASE/assessments/$ASSESSMENT_ID/poam/draft" \
-H "Authorization: Bearer $API_KEY" \
-H "x-standard-tenant-id: $TENANT_ID" \
-H "Content-Type: application/json" \
-d '{}' | jq .

Pre-condition: All artifacts approved (SoA, Gap Analysis, Maturity, POA&M).

Terminal window
curl -s -X POST "$BASE/assessments/$ASSESSMENT_ID/reports/draft" \
-H "Authorization: Bearer $API_KEY" \
-H "x-standard-tenant-id: $TENANT_ID" \
-H "Content-Type: application/json" \
-d '{}' | jq .

draft → documents_uploaded → documents_ingested → scf_pre_analysis_ready
→ framework_selected → scope_drafted → soa_drafted → soa_under_review
→ soa_approved → soa_ingested → evidence_analysis_ready
→ gap_analysis_drafted → gap_analysis_under_review → gap_analysis_approved
→ maturity_assessed → maturity_under_review → maturity_approved
→ poam_drafted → poam_under_review → poam_approved
→ report_generated → closed

Approval Gates: SoA, Gap Analysis, Maturity Assessment, POA&M, Report.

Each approval gate requires a human decision via POST /assessments/{id}/approvals.