Mint a key
Returned once, never stored. Expires after 90 days. Cannot be revoked individually; mint one per integration.
API
Any writing tool, script-coverage service, or production workflow can call the same review this site uses. There is no account: press the button, get a key, and run a live review from this page. Anonymous calls work too, at lower limits.
Keys are stateless HMAC tokens signed with a secret held in Google Secret Manager, so verification is a signature check with no key store. Every response carries data.disclaimer as a required field and meta.gate with the thresholds that were evaluated. Errors use one envelope: { ok:false, error:{ code, message, fix, docs } }.
Returned once, never stored. Expires after 90 days. Cannot be revoked individually; mint one per integration.
Runs the real pipeline with your key: deterministic triggers, Google Agent Search retrieval, the GuidanceContextReviewer on Vertex AI Agent Engine (or in-process ADK, recorded in meta.agent_runtime), and Model Armor on the answer. Nothing is cached.
Mint a key first, or run anonymously at the standard limit.
Request
curl -X POST "$BASE/v1/review" -H "content-type: application/json" -d '{"preset_id":"guidance-case","region":"US"}'
Response
—
Python
import requests
BASE = ""
key = requests.post(f"{BASE}/v1/keys").json()["data"]["api_key"]
r = requests.post(
f"{BASE}/v1/review",
headers={"Authorization": f"Bearer {key}"},
json={"screenplay": open("draft.fountain").read(), "region": "US"},
)
review = r.json()
print(review["meta"]["gate"]) # which thresholds passed and failed
for note in review["data"]["grounded_flags"]:
for clause in note["clauses"]:
print(note["heading"], clause["publisher"], clause["source_url"])
print(review["data"]["disclaimer"]) # required field on every response
JavaScript
const BASE = "";
const { data: { api_key } } = await (await fetch(`${BASE}/v1/keys`, { method: "POST" })).json();
const res = await fetch(`${BASE}/v1/review?format=markdown`, {
method: "POST",
headers: { "content-type": "application/json", "x-api-key": api_key },
body: JSON.stringify({ preset_id: "responsible-depiction", region: "US" }),
});
console.log(await res.text()); // a Markdown report, disclaimer firstReference
| Route | What it does | Key |
|---|---|---|
POST /v1/review | Review a screenplay (screenplay or preset_id, optional region). ?format=markdown returns a downloadable report. Returns scenes, trigger candidates, grounded notes with cited clauses, the ADK explanation, writer controls, resources, disclaimer, and meta.gate. | Optional · 6/min anonymous, 30/min keyed |
POST /v1/review/stream | The same review as newline-delimited JSON progress events (parsed, retrieving, retrieved, explaining, explained, complete) ending with result or error. This is what the workbench uses. | Same as review |
POST /v1/report | Render a Markdown report from a review payload you already hold. No model call. | No |
GET /v1/presets, /v1/presets/{id}, /v1/presets/{id}/download | The demo library and downloads in fountain, txt, or json. | No |
GET /v1/evidence | The research behind the guidance: 14 verified records with DOI and PMID, findings, and the trigger classes each bears on. Retrieved per note as grounded_flags[].evidence. | No |
GET /v1/guidance | The approved corpus with provenance and corpus_version. | No |
GET /v1/resources?region= | Region-aware support resources. | No |
GET /v1/eval/latest | The deterministic-layer benchmark, computed live from the shipped 48 cases, with failures listed. | No |
POST /v1/keys, GET /v1/keys/self | Mint a key; inspect the identity and limits of the key you send. | — |
GET /v1/stack, /health, /health/integrations | Which Google Cloud and Replit services are answering right now, with evidence. | No |
POST /v1/exports, GET /v1/exports/{id} | Store a review result only when asked. Replit App Storage on Replit; a temporary file elsewhere. | Optional |
GET/POST/DELETE /v1/decisions, GET /v1/me | Saved writer decisions for a signed-in Replit Auth user. Never stores screenplay text. | Replit Auth |
Full OpenAPI: /docs · /openapi.json. Limits are per minute per caller. Anonymous callers keep working when keys are unavailable. Retention: nothing is stored by default; exports and decisions are explicit. Logged per review: request id, caller tier, counts, model, latency. Never logged: screenplay text, prompts, generated prose.
{
"ok": true,
"data": { "scenes": [...], "grounded_flags": [...], "trigger_candidates": [...],
"grounding_status": "available", "writer_controls": [...],
"resources": [...], "disclaimer": "...", "decision_owner": "writer",
"overall_score": null },
"meta": { "request_id": "req_…", "latency_ms": 8420, "verdict": "notes",
"caller": { "tier": "keyed", "key_id": "…" },
"gate": { "passed": ["deterministic_candidate_present", …], "failed": [] },
"model_versions": { "gemini": "gemini-2.5-flash", "google_adk": "2.7.1" },
"corpus_version": "…", "abstained_because": null }
}{
"ok": false,
"error": { "code": "rate_limited",
"message": "review allows 6 requests per minute for this caller.",
"fix": "Wait and retry, or POST /v1/keys for a key with 5x this limit.",
"docs": "/docs" },
"meta": { "request_id": "req_…" }
}Codes are stable strings: validation_error, invalid_api_key, rate_limited, grounding_failed, agent_review_failed, sign_in_required, api_keys_unavailable. Failures fail closed: no note is ever fabricated from model memory.