Review simulations (async)
Trigger and read App Store rejection-risk predictions.
Forvibe's OTC ("On The Curve") engine predicts App Store rejection risk with a hybrid pipeline: a deterministic rule engine (30 automated Apple guideline checks, runs via the CLI without an AI key) plus an AI reviewer pass calibrated on 190+ real App Review rejections. Three review types exist (codebase, metadata, combined). The Public API can read all three and trigger metadata simulations directly. Codebase / combined runs still need the Forvibe dashboard or macOS app because they require uploading the actual project files.
Metadata simulation requires a paid plan (Indie Dev, Startup, or Enterprise). Returns 402 PAID_PLAN_REQUIRED on free plans. Cost: 50 credits per run.
List simulations
GET /api/v1/projects/:projectId/simulations?review_type=metadata&status=completed&limit=20
# Scope: review:simulateLatest simulation (convenience)
GET /api/v1/projects/:projectId/simulations/latest?review_type=metadata
# Returns the most recent completed simulation. 404 if none. Scope: review:simulateTrigger a metadata simulation
POST /api/v1/projects/:projectId/simulations/metadata
Content-Type: application/json
{
"version_id": "..." // optional listing version to attach the simulation to
}
# Scope: review:simulate
# Returns 202 + { job_id, status: "pending", type: "review_simulation", poll_url }Read a completed simulation
GET /api/v1/simulations/:simulationId
# Richer than the unified /jobs/:id view. Includes:
# - metadata_review (per-field compliance scan)
# - codebase_review (if a codebase or combined run)
# - combined_findings (cross-reference issues)
# - overall_summary (rejection risk score, suggested fixes)
# Scope: review:simulateOr poll via the unified job surface: GET /api/v1/jobs/:simulationId. The job_id and simulation_id are the same UUID.
Codebase review v2 fields (optional additions)
CLI versions from 2.0.0 onward submit additional fields inside codebase_review. All are optional and additive: older reports simply omit them and remain fully valid forever, so treat every field below as possibly absent, never as false or zero.
report_schema_version:2when present. Absent on any report submitted before the v2 CLI.engine_version: the CLI version that produced the report, e.g.2.0.0.rulepack_versionandrulepack_store: the rulepack version and store (appstoreorplay) the static engine evaluated against.app_profile: the structured facts the static engine extracted, including detected SDKs, Info.plist / manifest signals, and capabilities.checks: every deterministic rule evaluation (rule_id,statusofpass/fail/unverified/na,severity,guideline_number), independent of whether the check produced a finding.ai_review_ran:falsewhen the CLI ran with--static-onlyor found no AI provider key. The report is still complete:checksand any deterministic findings are present, just without the AI behavioral pass.
Static-only mode
The CLI's static rule engine needs no network beyond the rulepack fetch and no AI key. Running with --static-only skips the AI behavioral pass entirely; the deterministic engine still runs in full.
npx @forvibe/cli review --static-only --send
# No ANTHROPIC_API_KEY / OPENAI_API_KEY / GEMINI_API_KEY needed.
# Every rule in the rulepack is still evaluated; ai_review_ran is false
# on the resulting codebase_review.Findings for a static-only report all carry detection: "static". Reports submitted before the v2 CLI don't set detection at all; treat its absence the same way you treat the other v2 fields' absence.