Review simulations (async)

Trigger and read App Store rejection-risk predictions.

Updated 2026-07-10
4 min read

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

bash
GET /api/v1/projects/:projectId/simulations?review_type=metadata&status=completed&limit=20

# Scope: review:simulate

Latest simulation (convenience)

bash
GET /api/v1/projects/:projectId/simulations/latest?review_type=metadata

# Returns the most recent completed simulation. 404 if none. Scope: review:simulate

Trigger a metadata simulation

bash
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

bash
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:simulate

Or 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: 2 when 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_version and rulepack_store: the rulepack version and store (appstore or play) 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, status of pass / fail / unverified / na, severity, guideline_number), independent of whether the check produced a finding.
  • ai_review_ran: false when the CLI ran with --static-only or found no AI provider key. The report is still complete: checks and 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.

bash
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.