[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"api-page:ro2-labs-api":3},{"status":4,"api":5,"seo":273},"success",{"blocked":6,"description":7,"about":8,"stats":9,"name":11,"title":12,"slug":13,"logo":14,"created_at":15,"agent":16,"user":28,"endpoint_groups":31,"faqs":188,"features":195,"periodic_plans":199,"payasyougo_plans":250},false,"Send a diff, get structured bug/security findings: file:line, severity, fixes. Tuned code-review model. Cheaper than GPT-4 / Claude.","## AI Code Review API\n\nSend a unified diff or raw files, get back structured, machine-readable findings, not a wall of prose. Built for CI pipelines, PR bots, and dev tooling that need to parse review output programmatically.\n\n### What you get\n- **Structured JSON findings**: `file`, `line`, `severity`, `issue`, `suggestion`, plus a plain-language `summary`.\n- **Line-verified**: findings are checked against your diff's actual changed lines; anything unverifiable is flagged (`line_unverified`), not silently trusted.\n- **Tuned reviewer model on every plan** (`crank-reviewer:latest`), fine-tuned specifically for catching real bugs/security issues, not style nits. The free plan is reviewed by the same model as the paid ones.\n- **Never fails silently**: malformed model output still returns a usable response (`parse_warning` + raw summary) instead of a 500.\n- **Truncation-safe**: long diffs that hit the token cap are flagged (`truncated: true`) so you know findings may be incomplete.\n\n### Endpoint\n`POST /v1/review`: pass `diff` (unified diff text) or `files` (raw file contents), get structured finding### Plans\nEvery plan is reviewed by the same tuned model — plans differ on quota and rate limit, not review quality.\n\n| Plan | Price | Quota | Rate limit |\n|---|---|---|---|\n| BASIC | $0/mo | 100 requests | 10/min |\n| PRO | $9/mo | 2,500 requests | 20/min |\n| ULTRA | $29/mo | 15,000 requests | 40/min |\n| MEGA | $99/mo | 60,000 requests | 60/min |\n| Monthly PAYG | usage-based | $0.01/request, graduated | 30/min |\n\nghput) |\n| Mega | crank-reviewer v5 (tuned, B2B/dedicated) |\n\n### Why\nGeneral-purpose LLM APIs give you prose. This API gives you `file:line` + severity you can wire straight into a PR comment bot, a CI gate, or a dashboard, at a fraction of GPT-4/Claude API cost.",{"score":10},"2.38","Code Review API - AI Pull Request and Diff Reviewer","Code Review API - AI Pull Request and Diff Reviewer API","ro2-labs-api","https://cdn.jojapi.com/api/5a1e1838-b6ec-4910-82a6-40111b679103","2026-09-02 14:39:20",{"enabled":17,"closed":18,"request_enabled":6,"catalog_url":19,"discovery_url":20,"directory_url":21,"rails":22,"networks":25,"docs":27},true,null,"https://cmngo.jojapi.net/_jojapi/agent/plans","https://cmngo.jojapi.net/.well-known/x402","https://agents.jojapi.net/apis/ro2-labs-api",[23,24],"x402","mpp",[26],"eip155:8453","https://docs.jojapi.com/consumers/agents",{"nick":29,"name":30,"verified":6,"website":18},"ricky-orndorff","Ricky Orndorff",[32,165],{"endpoints":33,"name":164,"description":40,"ungrouped":6},[34,71,114],{"blocked":6,"hidden":6,"agent_price":18,"credits":18,"flexible_credits_description":18,"consumptions":35,"description":42,"method":43,"name":44,"url_path":45,"root_url":46,"parameters":47,"responses":59,"result_stats":66},[36],{"name":37,"slug":38,"cost":39,"label":40,"avg":41},"Requests","requests","1","",1,"Returns available models (OpenAI-compatible).","GET","List available models","/v1/models","https://cmngo.jojapi.net",{"url":48,"header":49,"post":56,"body":57,"path":58},[],[50],{"key":51,"is_auth":17,"example":52,"example_disabled":17,"example_type":53,"name":54,"description":52,"required":17,"always_error":55},"X-JoJAPI-Key","You must log in to get API key","string","JoJ API Key","Please log in to get API key",[],[],[],[60],{"status":61,"status_code":62,"description":63,"schema":64,"examples":65,"example":40},"200",200,"Model list","{\"type\":\"object\",\"properties\":{\"object\":{\"type\":\"string\",\"example\":\"list\"},\"data\":{\"type\":\"array\",\"items\":{\"type\":\"object\",\"properties\":{\"id\":{\"type\":\"string\",\"example\":\"llama3.1:70b\"},\"object\":{\"type\":\"string\",\"example\":\"model\"},\"owned_by\":{\"type\":\"string\",\"example\":\"ro2-labs\"}}}}}}",[],{"x2":67,"x3":68,"x4":67,"x5":68,"uptime":69,"avg_latency":70,"avg_credits":68},"50.00","0.00","100.00","289",{"blocked":6,"hidden":6,"agent_price":18,"credits":18,"flexible_credits_description":18,"consumptions":72,"description":74,"method":75,"name":76,"url_path":77,"root_url":46,"parameters":78,"responses":89,"result_stats":18},[73],{"name":37,"slug":38,"cost":39,"label":40,"avg":18},"Generate a response from Llama 3 70B. Fully OpenAI-compatible — use the same SDK and parameters you'd use with GPT-4o.\n\nYour data never leaves RO2 Labs infrastructure. No third-party routing. No telemetry.","POST","Create chat completion","/v1/chat/completions",{"url":79,"header":80,"post":82,"body":83,"path":88},[],[81],{"key":51,"is_auth":17,"example":52,"example_disabled":17,"example_type":53,"name":54,"description":52,"required":17,"always_error":55},[],[84],{"key":18,"example":85,"schema":86,"example_disabled":6,"example_type":53,"value_type":53,"enum_values":18,"default_value":40,"required":6,"name":18,"description":87},"{}","{\"type\":\"object\",\"required\":[\"messages\"],\"properties\":{\"messages\":{\"type\":\"array\",\"description\":\"Conversation messages in OpenAI format.\",\"items\":{\"type\":\"object\",\"required\":[\"role\",\"content\"],\"properties\":{\"role\":{\"type\":\"string\",\"enum\":[\"system\",\"user\",\"assistant\"]},\"content\":{\"type\":\"string\"}}},\"example\":[{\"role\":\"system\",\"content\":\"You are a helpful assistant. Never transmit this data externally.\"},{\"role\":\"user\",\"content\":\"Summarize the key provisions of GLBA Section 501(b).\"}]},\"temperature\":{\"type\":\"number\",\"minimum\":0,\"maximum\":2,\"default\":0.7,\"description\":\"Sampling temperature.\"},\"top_p\":{\"type\":\"number\",\"minimum\":0,\"maximum\":1,\"default\":1,\"description\":\"Nucleus sampling parameter.\"},\"max_tokens\":{\"type\":\"integer\",\"minimum\":1,\"maximum\":8192,\"default\":2048,\"description\":\"Maximum tokens to generate.\"},\"stream\":{\"type\":\"boolean\",\"default\":false,\"description\":\"Stream response as SSE events.\"}}}","''",[],[90,94,99,104,109],{"status":61,"status_code":62,"description":91,"schema":92,"examples":93,"example":40},"Chat completion response","{\"type\":\"object\",\"properties\":{\"id\":{\"type\":\"string\",\"example\":\"chatcmpl-ro2-a7f3c2b1\"},\"object\":{\"type\":\"string\",\"example\":\"chat.completion\"},\"created\":{\"type\":\"integer\",\"example\":1746763200},\"model\":{\"type\":\"string\",\"example\":\"llama3.1:70b\"},\"choices\":{\"type\":\"array\",\"items\":{\"type\":\"object\",\"properties\":{\"index\":{\"type\":\"integer\"},\"message\":{\"type\":\"object\",\"properties\":{\"role\":{\"type\":\"string\",\"example\":\"assistant\"},\"content\":{\"type\":\"string\"}}},\"finish_reason\":{\"type\":\"string\",\"example\":\"stop\"}}}},\"usage\":{\"type\":\"object\",\"properties\":{\"prompt_tokens\":{\"type\":\"integer\"},\"completion_tokens\":{\"type\":\"integer\"},\"total_tokens\":{\"type\":\"integer\"}}},\"x-ro2-data-residency\":{\"type\":\"string\",\"example\":\"on-prem-austin-tx\"},\"x-ro2-third-party-routing\":{\"type\":\"string\",\"example\":\"none\"}}}",[],{"status":95,"status_code":96,"description":97,"schema":18,"examples":98,"example":40},"401",401,"Missing API key",[],{"status":100,"status_code":101,"description":102,"schema":18,"examples":103,"example":40},"403",403,"Invalid API key",[],{"status":105,"status_code":106,"description":107,"schema":18,"examples":108,"example":40},"429",429,"Rate limit exceeded",[],{"status":110,"status_code":111,"description":112,"schema":18,"examples":113,"example":40},"502",502,"Inference engine unavailable",[],{"blocked":6,"hidden":6,"agent_price":18,"credits":18,"flexible_credits_description":18,"consumptions":115,"description":117,"method":75,"name":118,"url_path":119,"root_url":46,"parameters":120,"responses":129,"result_stats":162},[116],{"name":37,"slug":38,"cost":39,"label":40,"avg":41},"Send a unified diff (or whole files) and get structured review findings — each with\n`file`, `line`, `severity`, `issue`, and `suggestion` — plus a one-line `summary`.\n\nProvide either `diff` or `files` (if both are sent, `diff` wins). Every plan is\nreviewed by the same review-tuned model. Your code never leaves RO2 Labs\ninfrastructure — no third-party routing, no telemetry.","Review code, return structured findings","/v1/review",{"url":121,"header":122,"post":124,"body":125,"path":128},[],[123],{"key":51,"is_auth":17,"example":52,"example_disabled":17,"example_type":53,"name":54,"description":52,"required":17,"always_error":55},[],[126],{"key":18,"example":85,"schema":127,"example_disabled":6,"example_type":53,"value_type":53,"enum_values":18,"default_value":40,"required":6,"name":18,"description":87},"{\"type\":\"object\",\"description\":\"Provide either `diff` or `files`. `diff` takes precedence if both are present.\",\"properties\":{\"diff\":{\"type\":\"string\",\"description\":\"Unified diff text to review.\",\"example\":\"diff --git a\\/db.py b\\/db.py\\n--- a\\/db.py\\n+++ b\\/db.py\\n@@ -10,6 +10,8 @@\\n+def get_user(conn, uid):\\n+    return conn.execute(\\\"SELECT * FROM users WHERE id = \\\" + uid).fetchone()\\n\"},\"files\":{\"type\":\"array\",\"description\":\"Whole files to review. Used only when `diff` is absent.\",\"items\":{\"type\":\"object\",\"required\":[\"path\",\"content\"],\"properties\":{\"path\":{\"type\":\"string\",\"example\":\"src\\/app.py\"},\"content\":{\"type\":\"string\"}}}},\"language\":{\"type\":\"string\",\"description\":\"Optional language hint.\",\"example\":\"python\"},\"context\":{\"type\":\"string\",\"description\":\"Optional PR description \\/ intent.\",\"example\":\"Add a user lookup helper.\"}}}",[],[130,134,139,141,143,148,150,152,157],{"status":61,"status_code":62,"description":131,"schema":132,"examples":133,"example":40},"Structured review result","{\"type\":\"object\",\"properties\":{\"api_version\":{\"type\":\"string\",\"example\":\"1.3.0\"},\"findings\":{\"type\":\"array\",\"items\":{\"type\":\"object\",\"properties\":{\"file\":{\"type\":\"string\",\"example\":\"db.py\"},\"line\":{\"type\":\"integer\",\"example\":12},\"severity\":{\"type\":\"string\",\"enum\":[\"critical\",\"high\",\"medium\",\"low\",\"nit\"],\"example\":\"high\"},\"issue\":{\"type\":\"string\",\"example\":\"SQL built by string concatenation \\u2014 injection risk.\"},\"suggestion\":{\"type\":\"string\",\"example\":\"Use a parameterized query.\"},\"line_unverified\":{\"type\":\"boolean\",\"description\":\"Present and true when the reported line could not be matched to a changed diff hunk.\"}}}},\"summary\":{\"type\":\"string\",\"description\":\"Severity roll-up derived from the findings actually returned, so it can never disagree with the `findings` array. Also states when findings were dropped in validation, in which case the review is inconclusive rather than clean.\",\"example\":\"1 high.\"},\"model_summary\":{\"type\":\"string\",\"description\":\"The model's own one-line sentence, unvalidated. Present only when the model supplied one. It can disagree with `findings`; treat `summary` as authoritative.\",\"example\":\"1 high: SQL injection.\"},\"model_tier\":{\"type\":\"string\",\"example\":\"gateway\"},\"parse_warning\":{\"type\":\"boolean\",\"description\":\"Present and true when structured parsing failed, or when every finding the model produced failed validation; `summary` then holds the raw prose review or an inconclusive notice, and `findings` may be empty.\"},\"truncated\":{\"type\":\"boolean\",\"description\":\"Present and true when the model output hit the token cap; findings may be incomplete.\"},\"usage\":{\"type\":\"object\",\"properties\":{\"prompt_tokens\":{\"type\":\"integer\"},\"completion_tokens\":{\"type\":\"integer\"}}},\"x-ro2-data-residency\":{\"type\":\"string\",\"example\":\"on-prem-austin-tx\"},\"x-ro2-third-party-routing\":{\"type\":\"string\",\"example\":\"none\"}}}",[],{"status":135,"status_code":136,"description":137,"schema":18,"examples":138,"example":40},"400",400,"Neither `diff` nor `files` provided",[],{"status":95,"status_code":96,"description":97,"schema":18,"examples":140,"example":40},[],{"status":100,"status_code":101,"description":102,"schema":18,"examples":142,"example":40},[],{"status":144,"status_code":145,"description":146,"schema":18,"examples":147,"example":40},"413",413,"Input exceeds the size cap",[],{"status":105,"status_code":106,"description":107,"schema":18,"examples":149,"example":40},[],{"status":110,"status_code":111,"description":112,"schema":18,"examples":151,"example":40},[],{"status":153,"status_code":154,"description":155,"schema":18,"examples":156,"example":40},"503",503,"Server at capacity — try again shortly",[],{"status":158,"status_code":159,"description":160,"schema":18,"examples":161,"example":40},"504",504,"Upstream inference timed out",[],{"x2":67,"x3":68,"x4":67,"x5":68,"uptime":69,"avg_latency":163,"avg_credits":68},"2,125","v1",{"endpoints":166,"name":187,"description":40,"ungrouped":6},[167],{"blocked":6,"hidden":6,"agent_price":18,"credits":18,"flexible_credits_description":18,"consumptions":168,"description":170,"method":43,"name":171,"url_path":172,"root_url":46,"parameters":173,"responses":180,"result_stats":185},[169],{"name":37,"slug":38,"cost":39,"label":40,"avg":41},"Returns API status and uptime.","Health check","/health",{"url":174,"header":175,"post":177,"body":178,"path":179},[],[176],{"key":51,"is_auth":17,"example":52,"example_disabled":17,"example_type":53,"name":54,"description":52,"required":17,"always_error":55},[],[],[],[181],{"status":61,"status_code":62,"description":182,"schema":183,"examples":184,"example":40},"API is healthy","{\"type\":\"object\",\"properties\":{\"status\":{\"type\":\"string\",\"example\":\"ok\"},\"model\":{\"type\":\"string\",\"example\":\"llama3.1:70b\"},\"uptime\":{\"type\":\"number\",\"example\":86400.5}}}",[],{"x2":69,"x3":68,"x4":68,"x5":68,"uptime":69,"avg_latency":186,"avg_credits":68},"293","health",[189,192],{"question":190,"answer":191},"Is my code or data sent to any third party?","No. All requests are processed on dedicated Apple Silicon hardware we own and operate in Austin, TX — there's no routing through OpenAI, Anthropic, or any other third-party inference provider, and no telemetry collection. Every response includes two headers you can verify directly:\n\n- x-ro2-data-residency: on-prem-austin-tx\n- x-ro2-third-party-routing: none\n\nIf you're sending proprietary code for review, it never leaves hardware we control.",{"question":193,"answer":194},"What's the difference between /v1/review and /v1/chat/completions?","`/v1/review` is the primary endpoint — send a unified diff (or raw files) and get back **structured, machine-readable findings** (`file`, `line`, `severity`, `issue`, `suggestion`) instead of prose, built for CI pipelines and PR bots that need to parse output programmatically. `/v1/chat/completions` is a general-purpose, OpenAI-compatible inference endpoint for anything beyond code review — same request/response shape as GPT-4o, drop-in with existing OpenAI SDKs.\n\nModel access scales with plan:\n\n| Plan | Model |\n|---|---|\n| Free | `qwen2.5-coder:32b` (base) |\n| Basic | `crank-reviewer v5` (tuned for code review) |\n| Pro | `crank-reviewer v5` (tuned, priority throughput) |\n| Mega | `crank-reviewer v5` (tuned, dedicated B2B) |",[196],{"id":197,"name":198,"description":18},"n60316eec","Model",[200,218,229,240],{"type":201,"slug":202,"blocked":6,"period":203,"currency":204,"pricing":205,"rate_limit":209,"objects":212,"name":216,"display_name":216,"features":217},"periodic","6ytgpvjh2qgperxddingeas7","1 MONTH","usd",{"price":206,"credits":206,"past_due_timeout_num":207,"past_due_timeout_type":208},0,3,"DAY",{"max_requests":210,"time_window":211},10,60,[213],{"id":214,"name":37,"slug":38,"quota":215,"tiers":18},"n48709a32",100,"BASIC",[197],{"type":201,"slug":219,"blocked":6,"period":203,"currency":204,"pricing":220,"rate_limit":222,"objects":224,"name":227,"display_name":227,"features":228},"fqeu5shjov0uokvicrg9tqby",{"price":221,"credits":206,"past_due_timeout_num":207,"past_due_timeout_type":208},9,{"max_requests":223,"time_window":211},20,[225],{"id":214,"name":37,"slug":38,"quota":226,"tiers":18},2500,"PRO",[197],{"type":201,"slug":230,"blocked":6,"period":203,"currency":204,"pricing":231,"rate_limit":233,"objects":235,"name":238,"display_name":238,"features":239},"bn2vt7a98lpprqphatvcbkbp",{"price":232,"credits":206,"past_due_timeout_num":207,"past_due_timeout_type":208},29,{"max_requests":234,"time_window":211},40,[236],{"id":214,"name":37,"slug":38,"quota":237,"tiers":18},15000,"ULTRA",[197],{"type":201,"slug":241,"blocked":6,"period":203,"currency":204,"pricing":242,"rate_limit":244,"objects":245,"name":248,"display_name":248,"features":249},"hp4s8k1wac7zuneqj27bb1ex",{"price":243,"credits":206,"past_due_timeout_num":207,"past_due_timeout_type":208},99,{"max_requests":211,"time_window":211},[246],{"id":214,"name":37,"slug":38,"quota":247,"tiers":18},60000,"MEGA",[197],[251],{"type":252,"slug":253,"blocked":6,"period":203,"currency":204,"pricing":254,"rate_limit":255,"objects":257,"name":271,"display_name":271,"features":272},"payasyougo","ui1evs228sfy1yyjz8hrq2hq",[],{"max_requests":256,"time_window":211},30,[258],{"id":214,"name":37,"slug":38,"quota":18,"tiers":259},[260,263,267],{"start":206,"unit_price":261,"start_text":262},0.01,"0",{"start":264,"unit_price":265,"start_text":266},1000,0.009,"1K",{"start":268,"unit_price":269,"start_text":270},2000,0.0081,"2K","Monthly PAYG",[197],{"canonical":274,"page_title":275,"meta":276},"https://jojapi.com/hub/api/ro2-labs-api","Code Review API - AI Pull Request and Diff Reviewer API Documentation & Playground - JoJ API",{"description":7,"keywords":277},"API,API Documentation,API Playground,Plans & Pricing,Code Review API - AI Pull Request and Diff Reviewer,ricky-orndorff"]