API reference

Every governed operation this deployment exposes, with an example call. Public developer docs — like the build guide.

47 governed operations

Every operation is the same over MCP (the tools the Rubicon agent calls) and HTTP (POST /v1/call/<op>). Each accepts dry_run:true (the default) to validate shape without writing. Apps import the SDK same-origin from /sdk/rubicon.mjs and never hardcode a host.

Recruiting operations 31

The governed recruiting pipeline — create a project, ingest source material, define & approve criteria, discover and review prospects, run surveys, and draft outreach. Writes and decisions are attributed to the acting actor.

op_create_projectWritecreate a recruiting project

Create the project boundary that scopes source material, criteria, prospects, forms, drafts and responses.

Example call
POST /v1/call/op_create_project
{
  "inputs": {
    "client_name": "Example",
    "name": "Example"
  },
  "idempotency_key": "REPLACE-WITH-A-UNIQUE-KEY-PER-CALL",
  "dry_run": true
}
op_ingest_source_materialWriteingest project source material

Store immutable email, note, document or transcript artifacts with hashes and provenance.

Example call
POST /v1/call/op_ingest_source_material
{
  "inputs": {
    "project_id": "00000000-0000-0000-0000-000000000000",
    "artifacts": [
      {
        "kind": "email",
        "content": "content"
      }
    ]
  },
  "idempotency_key": "REPLACE-WITH-A-UNIQUE-KEY-PER-CALL",
  "dry_run": true
}
prep_for_define_target_criteriaPrepprepare source material for target criteria

Pure read that snapshots artifact evidence and parse warnings; it makes no targeting decision.

Example call
POST /v1/call/prep_for_define_target_criteria
{
  "inputs": {
    "project_id": "00000000-0000-0000-0000-000000000000"
  },
  "idempotency_key": "REPLACE-WITH-A-UNIQUE-KEY-PER-CALL",
  "dry_run": true
}
op_create_target_criteriaWritecreate a target-criteria version

Persist an editable, versioned target-criteria proposal for a later approval to attest against.

Example call
POST /v1/call/op_create_target_criteria
{
  "inputs": {
    "project_id": "00000000-0000-0000-0000-000000000000",
    "criteria": [
      {
        "dimension": "title",
        "values": [
          "values"
        ],
        "priority": "must"
      }
    ]
  },
  "idempotency_key": "REPLACE-WITH-A-UNIQUE-KEY-PER-CALL",
  "dry_run": true
}
prep_for_approve_target_criteriaPrepprepare a criteria version for approval

Pure read of the exact criteria version, source citations and prohibited-targeting flags.

Example call
POST /v1/call/prep_for_approve_target_criteria
{
  "inputs": {
    "criteria_version_id": "00000000-0000-0000-0000-000000000000"
  },
  "idempotency_key": "REPLACE-WITH-A-UNIQUE-KEY-PER-CALL",
  "dry_run": true
}
op_approve_target_criteriaDecisionapprove target criteria

Record an approve/reject decision on one immutable criteria version, attributed to the acting actor (human or named AI) with schema-validated evidence.

Example call
POST /v1/call/op_approve_target_criteria
{
  "inputs": {
    "criteria_version_id": "00000000-0000-0000-0000-000000000000",
    "verdict": "approve",
    "rationale": "rationale"
  },
  "idempotency_key": "REPLACE-WITH-A-UNIQUE-KEY-PER-CALL",
  "dry_run": true
}
prep_for_plan_lead_searchPrepprepare a lead-search plan

Compile a capability-aware Google-first query plan from approved criteria without searching.

Example call
POST /v1/call/prep_for_plan_lead_search
{
  "inputs": {
    "project_id": "00000000-0000-0000-0000-000000000000",
    "criteria_version_id": "00000000-0000-0000-0000-000000000000"
  },
  "idempotency_key": "REPLACE-WITH-A-UNIQUE-KEY-PER-CALL",
  "dry_run": true
}
op_create_search_planDecisionapprove a lead-search plan

Persist a reproducible query plan; the acting actor's acceptance or edits are recorded as an attributed, evidence-backed decision.

Example call
POST /v1/call/op_create_search_plan
{
  "inputs": {
    "project_id": "00000000-0000-0000-0000-000000000000",
    "criteria_version_id": "00000000-0000-0000-0000-000000000000",
    "provider": {
      "kind": "google",
      "search_mode": "web"
    },
    "query_variants": [
      {
        "query": "query"
      }
    ]
  },
  "idempotency_key": "REPLACE-WITH-A-UNIQUE-KEY-PER-CALL",
  "dry_run": true
}
op_discover_leadsExternaldiscover prospects

Execute an approved lead-search plan. Google web search is the only enabled MVP provider.

Example call
POST /v1/call/op_discover_leads
{
  "inputs": {
    "search_plan_id": "00000000-0000-0000-0000-000000000000"
  },
  "idempotency_key": "REPLACE-WITH-A-UNIQUE-KEY-PER-CALL",
  "dry_run": true
}
prep_for_review_prospectsPrepprepare prospects for review

Deduplicate and annotate prospects with evidence, suppression state and criterion matches.

Example call
POST /v1/call/prep_for_review_prospects
{
  "inputs": {
    "project_id": "00000000-0000-0000-0000-000000000000"
  },
  "idempotency_key": "REPLACE-WITH-A-UNIQUE-KEY-PER-CALL",
  "dry_run": true
}
op_review_prospectsDecisionreview prospects

Record a yes/maybe/no decision per prospect, attributed to the acting actor with evidence. No deletes: rejected prospects remain attributable.

Example call
POST /v1/call/op_review_prospects
{
  "inputs": {
    "project_id": "00000000-0000-0000-0000-000000000000",
    "decisions": [
      {
        "prospect_id": "00000000-0000-0000-0000-000000000000",
        "verdict": "yes",
        "rationale": "rationale"
      }
    ]
  },
  "idempotency_key": "REPLACE-WITH-A-UNIQUE-KEY-PER-CALL",
  "dry_run": true
}
op_find_potential_participantsExternalfind potential participants (Exa)

Search Exa for LinkedIn people (+ the existing panel), dedupe by identity, store each in the global panel, link them to the project as 'candidate', and RANK by a relevance score — Exa's within-query rank DOMINATES (its top-10 surface at the top; each result carries `rank` + `source_query`), keyword fit is a secondary steer, rank-less panel token-matches are capped below clean top Exa hits, and retired/student/homonym penalties sink noise (each candidate carries `flags` for the reviewer). BEST-USE PLAYBOOK: (1) write each query as a PERSON not a topic — 'master plumbers who install digital mixing valves', not 'digital mixing valves'; (2) Exa caps ~100/query and does NOT paginate, so get volume from MANY facet-varied queries — fan a broad persona by STATE/DISTRICT, a NICHE persona by descriptive TITLE — and the op dedupes; (3) use ~25 results/query (default), not 100 — relevance is front-loaded; (4) pass exclude_terms for known homonyms. Expect ~50-70% strong matches, so ALWAYS review (candidate→matched) before outreach. Returns full profiles + real Exa cost.

Example call
POST /v1/call/op_find_potential_participants
{
  "inputs": {
    "project_id": "00000000-0000-0000-0000-000000000000",
    "queries": [
      "queries"
    ]
  },
  "idempotency_key": "REPLACE-WITH-A-UNIQUE-KEY-PER-CALL",
  "dry_run": true
}
op_resolve_participant_contactExternalresolve participant work emails

Resolve work emails for one or more recruits IN PARALLEL through a gated pipeline: Exa grounded answer (exact published email + the company's DOCUMENTED format + mail domain, assembled deterministically when no exact address exists) → hard gates (MX/deliverability, no role accounts like info@, no freemail; a gate kill returns unresolved with the reason in `flags`) → free SMTP RCPT verification (never sends; auto-disabled where port 25 is blocked). `confidence` is COMPUTED from `checks` (mx/name_match/format_consistent/...), never the LLM's self-report; `corroborated` means the local part matches THIS person's name. Cached unless force:true. Returns per-recruit results + total cost. Run it ON DEMAND for the people you're actually pursuing. An evidence-only Parallel fallback (~$0.005/run) automatically covers anyone the fast pipeline leaves unresolved.

Example call
POST /v1/call/op_resolve_participant_contact
{
  "inputs": {
    "recruit_ids": [
      "recruit_ids"
    ]
  },
  "idempotency_key": "REPLACE-WITH-A-UNIQUE-KEY-PER-CALL",
  "dry_run": true
}
op_set_participant_statusDecisionmatch / maybe / reject participants for a project

Record a researcher's per-participant verdict for ONE project: matched, maybe or rejected (+ optional comment), attributed to the acting actor. This is the approve-the-matches gate. Reversible — call again to change a verdict. A rejection is scoped to this project; the recruit stays in the panel for others.

Example call
POST /v1/call/op_set_participant_status
{
  "inputs": {
    "project_id": "00000000-0000-0000-0000-000000000000",
    "updates": [
      {
        "recruit_id": "00000000-0000-0000-0000-000000000000",
        "status": "matched"
      }
    ]
  },
  "idempotency_key": "REPLACE-WITH-A-UNIQUE-KEY-PER-CALL",
  "dry_run": true
}
op_add_outreach_draftWritesave outreach drafts for participants

Save one outreach draft (subject + body + optional link) for a batch of participants in a project. The text is a MERGE TEMPLATE — tokens like {{first_name}}, {{company}}, {{title}}, {{link}} are filled per recruit from their profile; a token with no value is left blank and reported. One draft per (project, recruit); re-saving replaces it. It never sends mail.

Example call
POST /v1/call/op_add_outreach_draft
{
  "inputs": {
    "project_id": "00000000-0000-0000-0000-000000000000",
    "recruit_ids": [
      "recruit_ids"
    ],
    "subject": "subject",
    "body_text": "body_text"
  },
  "idempotency_key": "REPLACE-WITH-A-UNIQUE-KEY-PER-CALL",
  "dry_run": true
}
prep_for_configure_qualificationPrepprepare a short qualification form

Build a candidate one-to-three-question form context and renderer feasibility assessment.

Example call
POST /v1/call/prep_for_configure_qualification
{
  "inputs": {
    "project_id": "00000000-0000-0000-0000-000000000000",
    "criteria_version_id": "00000000-0000-0000-0000-000000000000",
    "transport": "hosted_link"
  },
  "idempotency_key": "REPLACE-WITH-A-UNIQUE-KEY-PER-CALL",
  "dry_run": true
}
op_set_qualification_formDecisionapprove a qualification form

Create an immutable form version whose approval is attributed to the acting actor with schema-validated evidence. Hosted links are MVP; Gmail AMP remains gated.

Example call
POST /v1/call/op_set_qualification_form
{
  "inputs": {
    "project_id": "00000000-0000-0000-0000-000000000000",
    "title": "Example",
    "transport": "hosted_link",
    "questions": [
      {
        "prompt": "prompt",
        "type": "single_select"
      }
    ]
  },
  "idempotency_key": "REPLACE-WITH-A-UNIQUE-KEY-PER-CALL",
  "dry_run": true
}
prep_for_draft_outreachPrepprepare approved prospects for outreach drafting

Return review-approved prospects, form state, suppression flags and prior drafts/replies.

Example call
POST /v1/call/prep_for_draft_outreach
{
  "inputs": {
    "project_id": "00000000-0000-0000-0000-000000000000",
    "form_id": "00000000-0000-0000-0000-000000000000"
  },
  "idempotency_key": "REPLACE-WITH-A-UNIQUE-KEY-PER-CALL",
  "dry_run": true
}
op_draft_outreachWritesave outbound email drafts

Persist versioned email content tied to a prospect and qualification form; it never sends mail.

Example call
POST /v1/call/op_draft_outreach
{
  "inputs": {
    "project_id": "00000000-0000-0000-0000-000000000000",
    "form_id": "00000000-0000-0000-0000-000000000000",
    "drafts": [
      {
        "prospect_id": "00000000-0000-0000-0000-000000000000",
        "subject": "subject",
        "body_text": "body_text"
      }
    ]
  },
  "idempotency_key": "REPLACE-WITH-A-UNIQUE-KEY-PER-CALL",
  "dry_run": true
}
prep_for_approve_outreachPrepprepare outbound drafts for approval

Return the exact content, recipient provenance, suppression state and form renderer status.

Example call
POST /v1/call/prep_for_approve_outreach
{
  "inputs": {
    "project_id": "00000000-0000-0000-0000-000000000000"
  },
  "idempotency_key": "REPLACE-WITH-A-UNIQUE-KEY-PER-CALL",
  "dry_run": true
}
op_approve_outreachDecisionapprove outbound drafts

Record an approve/reject decision for every outward-facing message, attributed to the acting actor with schema-validated evidence.

Example call
POST /v1/call/op_approve_outreach
{
  "inputs": {
    "project_id": "00000000-0000-0000-0000-000000000000",
    "decisions": [
      {
        "draft_id": "00000000-0000-0000-0000-000000000000",
        "verdict": "approve",
        "rationale": "rationale"
      }
    ]
  },
  "idempotency_key": "REPLACE-WITH-A-UNIQUE-KEY-PER-CALL",
  "dry_run": true
}
capture_hosted_form_submissionOpcapture a hosted-form response

Narrow public endpoint using an opaque, expiring, one-time delivery token. It is not a general MCP browser call.

Example call
POST /v1/call/capture_hosted_form_submission
{
  "inputs": {},
  "dry_run": true
}
ingest_gmail_replyOpingest a targeted Gmail reply

Webhook/poll worker ingestion keyed by Gmail message ID; mailbox-wide trawling is out of scope.

Example call
POST /v1/call/ingest_gmail_reply
{
  "inputs": {
    "delivery_id": "00000000-0000-0000-0000-000000000000",
    "gmail_message_id": "00000000-0000-0000-0000-000000000000"
  },
  "idempotency_key": "REPLACE-WITH-A-UNIQUE-KEY-PER-CALL",
  "dry_run": true
}
prep_for_review_responsesPrepprepare responses for researcher review

Correlate form and targeted Gmail replies to prospects, drafts and qualification versions.

Example call
POST /v1/call/prep_for_review_responses
{
  "inputs": {
    "project_id": "00000000-0000-0000-0000-000000000000"
  },
  "idempotency_key": "REPLACE-WITH-A-UNIQUE-KEY-PER-CALL",
  "dry_run": true
}
op_triage_responsesDecisiontriage qualification responses

Record a qualify/decline/follow-up/opt-out decision, attributed to the acting actor with evidence. Qualified people are handed to Vidlet for scheduling.

Example call
POST /v1/call/op_triage_responses
{
  "inputs": {
    "project_id": "00000000-0000-0000-0000-000000000000",
    "decisions": [
      {
        "response_id": "00000000-0000-0000-0000-000000000000",
        "verdict": "qualified",
        "rationale": "rationale"
      }
    ]
  },
  "idempotency_key": "REPLACE-WITH-A-UNIQUE-KEY-PER-CALL",
  "dry_run": true
}
op_create_surveyWritecreate a survey

Create a named survey inside a project. A project may hold many surveys; the survey is the boundary reusable questions attach to.

Example call
POST /v1/call/op_create_survey
{
  "inputs": {
    "project_id": "00000000-0000-0000-0000-000000000000",
    "name": "Example"
  },
  "idempotency_key": "REPLACE-WITH-A-UNIQUE-KEY-PER-CALL",
  "dry_run": true
}
op_create_survey_questionWriteadd a reusable survey question

Add a reusable question primitive to a survey — a prompt, an ordered number, a declared answer_type and a free-form answer_mode (text box, slider, date-range, dropdown — anything) plus arbitrary config. Call repeatedly to build the survey.

Example call
POST /v1/call/op_create_survey_question
{
  "inputs": {
    "survey_id": "00000000-0000-0000-0000-000000000000",
    "prompt": "prompt",
    "question_number": 1,
    "answer_type": "answer_type",
    "answer_mode": "answer_mode",
    "required": true
  },
  "idempotency_key": "REPLACE-WITH-A-UNIQUE-KEY-PER-CALL",
  "dry_run": true
}
op_set_survey_statusWriteopen or close a survey

Set a survey active or closed. A closed survey rejects new questions, embeds and answers; reopen it to resume. Freezes a survey once you start fielding it.

Example call
POST /v1/call/op_set_survey_status
{
  "inputs": {
    "survey_id": "00000000-0000-0000-0000-000000000000",
    "status": "active"
  },
  "idempotency_key": "REPLACE-WITH-A-UNIQUE-KEY-PER-CALL",
  "dry_run": true
}
op_publish_surveyWritepublish a survey to a hosted link

Mint (or return) the survey's stable Rubicon-hosted public link — no email required. Anyone with the link fills the hosted form (or the survey's custom page) and answers stream in with their self-entered email. regenerate:true revokes the old link and mints a new one.

Example call
POST /v1/call/op_publish_survey
{
  "inputs": {
    "survey_id": "00000000-0000-0000-0000-000000000000",
    "expires_in_days": 90,
    "regenerate": false
  },
  "idempotency_key": "REPLACE-WITH-A-UNIQUE-KEY-PER-CALL",
  "dry_run": true
}
op_set_survey_pageWriteset a bespoke survey page

Attach a custom-designed HTML page to a survey; Rubicon hosts it at the survey's public/form links in place of the default renderer. Contract: the page submits to the RELATIVE URL 'form-submit' with fields q<question_number> (+ respondent_email on shared links). Empty page_html clears back to the default.

Example call
POST /v1/call/op_set_survey_page
{
  "inputs": {
    "survey_id": "00000000-0000-0000-0000-000000000000"
  },
  "idempotency_key": "REPLACE-WITH-A-UNIQUE-KEY-PER-CALL",
  "dry_run": true
}
op_answer_surveyOpanswer a survey question

PUBLIC ingress: anyone (a hosted form or an embedded email link) may submit one validated answer, which streams into the dedicated survey-answers store. Intentionally outside the actor-auth model; not callable as an MCP tool.

Example call
POST /v1/call/op_answer_survey
{
  "inputs": {
    "survey_id": "00000000-0000-0000-0000-000000000000",
    "question_number": 1,
    "answer": "example"
  },
  "idempotency_key": "REPLACE-WITH-A-UNIQUE-KEY-PER-CALL",
  "dry_run": true
}

App building & platform 16

The company-agnostic lifecycle every Rubicon app is built and run on: deploy from source, patch in place, roll back, inspect activity, and read or write durable app state.

list_appsReadList the apps you can see — each with its live URL, status and version.

List the apps you can see — each with its live URL, status and version.

Example call
POST /v1/call/list_apps
{
  "inputs": {},
  "dry_run": true
}
get_appReadOne app's metadata: status, active version, owner and description.

One app's metadata: status, active version, owner and description.

Example call
POST /v1/call/get_app
{
  "inputs": {},
  "dry_run": true
}
get_app_contextReadEverything an editor needs before changing an app: source, contract, recent activity.

Everything an editor needs before changing an app: source, contract, recent activity.

Example call
POST /v1/call/get_app_context
{
  "inputs": {},
  "dry_run": true
}
get_app_sourceReadRead an app's current source bundle (client + server + manifest).

Read an app's current source bundle (client + server + manifest).

Example call
POST /v1/call/get_app_source
{
  "inputs": {},
  "dry_run": true
}
get_app_activityReadAn app's recent governed calls — the audit trail behind what it did.

An app's recent governed calls — the audit trail behind what it did.

Example call
POST /v1/call/get_app_activity
{
  "inputs": {},
  "dry_run": true
}
list_app_versionsReadEvery deployed version of an app, newest first (for rollback).

Every deployed version of an app, newest first (for rollback).

Example call
POST /v1/call/list_app_versions
{
  "inputs": {},
  "dry_run": true
}
deploy_app_sourceWriteCreate or replace an app from source; the build typechecks against this API.

Create or replace an app from source; the build typechecks against this API.

Example call
POST /v1/call/deploy_app_source
{
  "inputs": {},
  "dry_run": true
}
update_app_sourceWritePatch an existing app in place and cut a new version.

Patch an existing app in place and cut a new version.

Example call
POST /v1/call/update_app_source
{
  "inputs": {},
  "dry_run": true
}
set_app_statusWriteMove an app between development / beta / production.

Move an app between development / beta / production.

Example call
POST /v1/call/set_app_status
{
  "inputs": {},
  "dry_run": true
}
rollback_appWriteInstantly restore a previous version of an app.

Instantly restore a previous version of an app.

Example call
POST /v1/call/rollback_app
{
  "inputs": {},
  "dry_run": true
}
promote_app_versionWriteMake an app's staged candidate the live version (atomic compare-and-set).

Make an app's staged candidate the live version (atomic compare-and-set).

Example call
POST /v1/call/promote_app_version
{
  "inputs": {},
  "dry_run": true
}
discard_app_versionWriteDrop an app's staged candidate without touching the live version.

Drop an app's staged candidate without touching the live version.

Example call
POST /v1/call/discard_app_version
{
  "inputs": {},
  "dry_run": true
}
exercise_appWriteDrive an app's own routes server-side to prove it works end-to-end.

Drive an app's own routes server-side to prove it works end-to-end.

Example call
POST /v1/call/exercise_app
{
  "inputs": {},
  "dry_run": true
}
capsule_state_getReadRead a value from an app's durable key/value state.

Read a value from an app's durable key/value state.

Example call
POST /v1/call/capsule_state_get
{
  "inputs": {},
  "dry_run": true
}
capsule_state_setWriteWrite a value into an app's durable key/value state.

Write a value into an app's durable key/value state.

Example call
POST /v1/call/capsule_state_set
{
  "inputs": {},
  "dry_run": true
}
list_modelsReadThe inference models available to apps, plus the current default.

The inference models available to apps, plus the current default.

Example call
POST /v1/call/list_models
{
  "inputs": {},
  "dry_run": true
}