Developer API

Call Rigor from your code

Production-quality deliverables from a single API call. Rigor classifies your task, builds a methodology-driven plan, and executes each step — returning a structured deliverable with sources, quality score, and cost breakdown. Base URL: https://plith.ai

Authentication

All API requests require an API key sent via the x-api-key header. The Authorization header is not read — requests without x-api-key return 401 missing_api_key.

x-api-key: plth_your_key_here

Keys are created at signup or via POST /api/keys. Your key identifies your organization — all workflows, billing, and data are scoped to it.

Anonymous mode (MCP only)

When connecting via MCP (Smithery, Claude Desktop, Cursor, etc.) without an API key, rigor_plan is available for evaluation against a demo org. Anonymous calls are rate-limited to 30 requests / minute and 500 requests / day per IP.

Quick start

1 · Get a key

POST/api/keys
curl -X POST https://plith.ai/api/keys \
  -H "Content-Type: application/json" \
  -d '{"email": "you@example.com", "name": "My Org"}'

// Response — store api_key immediately, it cannot be retrieved again
{
  "org_id": "a1b2c3d4-...",
  "api_key": "plth_live_xxxxxxxxxxxx...",
  "workspace_id": "ws_...",
  "email_verified": false,
  "credits": 2500,
  "message": "Store this key securely — it will not be shown again. Verify your email to unlock 2,500 bonus credits."
}

2 · Plan a workflow (free)

POST/api/rigor/plan
curl -X POST https://plith.ai/api/rigor/plan \
  -H "x-api-key: YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{"task_description": "Design a caching layer for our API gateway"}'

Returns a workflow_id and step sequence. No credits used.

3 · Execute

POST/api/rigor/execute
curl -X POST https://plith.ai/api/rigor/execute \
  -H "x-api-key: YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{"workflow_id": "wr_2a4b6c8d...", "delivery": {"method": "polling"}}'

4 · Get results

GET/api/rigor/status/wr_2a4b6c8d...
curl https://plith.ai/api/rigor/status/wr_2a4b6c8d... \
  -H "x-api-key: YOUR_KEY"

Returns progress during execution and the full deliverable when complete.

Credits & billing

Plith is metered in credits at 1,000 credits per USD. New organizations receive 2,500 free credits immediately on signup. Verify your email to unlock 2,500 bonus credits (5,000 total). No monthly stipend — credits never expire.

Credit packs

AmountCredits
$1010,000
$2525,000
$100100,000
$250250,000
Custom ($5–$10,000)1,000 credits per dollar

Purchase via POST /api/billing/checkout. Credits are deducted after each successful call; the amount deducted is reported as credits_used; your new balance as credits_remaining.

For Rigor workflows, credits accumulate server-side as steps execute. The pre-execution estimate appears in plan.cost; final usage is reported by GET /api/rigor/status as credits_used.

Rate limits

ScopeLimit
Rigor endpoints (per org, sliding window)120 req / min
/api/rigor/execute (per org, UTC day)1,000 req / day
Concurrent active workflows per orgFree: 1 · Pro: 3 · Team: 10 · Enterprise: unlimited
/api/rigor/workflows/actions120 req / min
Anonymous MCP (per IP)30 req / min, 500 / day
POST /api/keys (per IP)3 per 24 hours

Active workflows (counting toward the concurrent limit): queued, executing, step_executing, resuming, quality_review, interactive_waiting, pending_approval, pending_human_review. When a rate limit is exceeded, the response includes retry_after (seconds) and a Retry-After HTTP header.

POST /api/rigor/plan

POST/api/rigor/planAuth: x-api-key · Cost: Free

Classifies the task and builds a workflow plan without executing it. The plan is persisted so a subsequent /execute call can pass the workflow_id to skip re-classification.

Request body

FieldTypeRequiredDescription
task_descriptionstring (≥ 2 words)YesWhat you want produced. Be specific.
task_typestringNoHint to skip auto-classification.
available_mcp_connectionsobject[]NoEach: { id, label, server_url, capabilities }
preferencesobjectNoSee preferences fields below.
contextobjectNo{ additional_context: string }

preferences fields

FieldTypeDescription
rigor_level"quick" | "standard" | "thorough"Review depth. Default auto-detected.
max_budget_usdnumberBudget ceiling; triggers budget_below_estimate warning.
skip_frameworksstring[]Framework display names to exclude.
only_frameworksstring[]Restrict to these frameworks (mutex with skip).
add_frameworks(string | obj)[]Inject frameworks: { name, before_step }
require_approvalbooleanPause at pending_approval before the final step.
approval_before_stepnumber[]Zero-based step indices for approval gates. Out-of-range indices return 400 invalid_step_index.

Response (200)

{
  "ok": true,
  "plan": {
    "workflow_id": "wr_2a4b6c8d...",
    "classification": { "task_type": "solution_design", "value_class": "operational" },
    "sequence": [
      { "step": 1, "name": "Requirements Analysis", "estimated_credits": 80,  "priority_class": "must" },
      { "step": 2, "name": "Solution Design",        "estimated_credits": 240, "priority_class": "must" },
      { "step": 3, "name": "Assumption Verification","estimated_credits": 100, "priority_class": "should", "auto_added": true },
      { "step": 4, "name": "Review (Sonnet)",         "estimated_credits": 120, "priority_class": "must" }
    ],
    "cost": { "credits": 540, "usd": 0.54, "range": { "estimated_min": 400, "estimated_max": 680 } },
    "rigor_level": "standard",
    "warnings": [],
    "info": ["Review: Haiku + Sonnet"]
  }
}

Review step names carry the model label: "Review (Haiku)", "Review (Sonnet)", "Review (Opus)".

Errors: 401 unauthorized · 400 invalid_body · 400 missing_field · 400 invalid_task_description · 400 vague_task_description · 429 rate_limit_exceeded · 504 plan_timeout · 500 plan_error

POST /api/rigor/execute

POST/api/rigor/executeAuth: x-api-key · Cost: Variable

Executes a workflow end-to-end. Pass workflow_id to re-use a stored plan, or pass task_description to classify, plan, persist, and dispatch in a single call. Cost equals the plan's cost.credits. First Rigor workflow per org is free.

Delivery modes

ModeSet byReturns
sse (default)delivery.method: "sse" + Accept: text/event-streamEvent stream until completion or 290 s timeout
pollingdelivery.method: "polling"workflow_id + poll_url
webhookdelivery.method: "webhook" + HTTPS delivery.webhook_urlworkflow_id + webhook_secret (32-byte hex HMAC)
interactivemode: "interactive"Returns interactive_waiting; driven step-by-step via /step

SSE events

EventWhen
workflow_startedWorkflow metadata + steps preview
step_started · step_completed · step_skippedPer step
quality_reviewScore + summary after execution
workflow_completed · workflow_pending_approval · workflow_errorTerminal events
processingHeartbeat every 15 s while waiting
stream_timeoutStream closes at 290 s; workflow continues — poll status

Reconnect: each event carries an id: field of the form workflow_id:step_or_marker. To resume after a drop, resend the request with Last-Event-ID set to the last received id — missed events will be replayed.

GET /api/rigor/status/{workflow_id}

GET/api/rigor/status/{workflow_id}Auth: x-api-key · Cost: Free

Returns workflow state and results. Only the owning organization can read a workflow.

Status values

pending · planned · queued · executing · step_executing · resuming · quality_review · interactive_waiting · pending_approval · pending_human_review · approved · completed · failed · cancelled · timed_out · blocked · halted

{
  "ok": true,
  "workflow": {
    "workflow_id": "wr_2a4b6c8d...",
    "status": "completed",
    "task_type": "solution_design",
    "current_step": 5,
    "total_steps": 5,
    "quality_score": 92,
    "quality_review": {
      "score": 92,
      "summary": "Strong design with clear trade-offs.",
      "path_to_100": ["Add p50/p95/p99 latency targets per cache tier."]
    },
    "deliverable": { "title": "...", "sections": [{ "heading": "...", "content": "..." }] },
    "credits_used": 530,
    "error": null
  }
}

POST /api/rigor/approve

POST/api/rigor/approveAuth: x-api-key · Cost: Free
{
  "workflow_id": "wr_2a4b6c8d...",
  "decision": "approved",
  "notes": "OK to proceed",
  "agent_id": "my-review-bot"
}

Decision endpoint for workflows paused at pending_approval. On approval, the workflow automatically resumes. On rejection, the workflow is marked failed. Errors: 404 not_found · 409 invalid_status · 500 approve_failed

POST /api/rigor/resume

POST/api/rigor/resumeAuth: x-api-key · Cost: Variable
{
  "workflow_id": "wr_2a4b6c8d...",
  "revision_guidance": "Focus the rewrite on enterprise buyers; ignore SMB."
}

Resumes a workflow from the last completed step. Permitted source statuses: executing, failed, approved, blocked, timed_out, pending_approval. Uses an optimistic lock — concurrent resume calls return resume_conflict.

POST /api/rigor/step

POST/api/rigor/stepAuth: x-api-key · Cost: Variable
{
  "workflow_id": "wr_2a4b6c8d...",
  "action": "next",
  "feedback": "Focus on security implications."
}

Drives a workflow created with mode: "interactive". action accepts "next" | "skip" | "abort". Sessions expire after 30 minutes of inactivity. Errors: 409 invalid_status · 410 session_expired · 409 concurrent_step

GET /api/rigor/workflows

GET/api/rigor/workflowsAuth: x-api-key · Cost: Free

Lists workflows for the authenticated org with filtering and cursor-based pagination. Also returns a real-time concurrent-usage summary against your plan's concurrent workflow limit.

ParamTypeDescription
statusstringComma-separated (executing,queued).
task_typestringFilter by task type.
created_afterISO 8601After this time.
created_beforeISO 8601Before this time.
cursorstringOpaque cursor from prior pagination.cursor.
limitinteger1–100, default 20.

POST /api/rigor/workflows/actions

POST/api/rigor/workflows/actionsAuth: x-api-key · Cost: Free · 120/min
{
  "action": "cancel",
  "workflow_ids": ["wr_aaa...", "wr_bbb..."],
  "confirm": false,
  "force": false
}

Bulk workflow action endpoint. Currently supports action: "cancel". Two-phase: confirm: false (default) shows a preview, confirm: true executes. Max 20 workflow IDs per call.

GET /api/rigor/lineage/{workflowId}

GET/api/rigor/lineage/{workflowId}Auth: viewer · Cost: Free

Walks the prior_workflow_id chain backward and returns the full lineage, ordered oldest-first. Capped at 10 hops. Errors: 404 not_found · 422 chain_depth_exceeded

GET /api/rigor/templates

GET/api/rigor/templatesAuth: Public · Cost: Free
{
  "templates": [{
    "id": "uuid",
    "task_type": "solution_design",
    "template_name": "Solution Design",
    "template_prompt": "...",
    "placeholder_fields": ["system_name", "constraints"],
    "description": "Architecture and design document for a technical system.",
    "display_order": 1,
    "version": 1,
    "category": "Engineering"
  }]
}

Returns deliverable templates — 43 types across 8 categories. No auth required. Query: ?task_type= and/or ?category=.

POST /api/rigor/enhance

POST/api/rigor/enhanceAuth: Tier-conditional · Cost: Free / 270c
{ "task_description": "Design a caching layer", "tier": "llm" }

Scores and optionally enhances a task description. tier: "deterministic" (default) is free, rule-based, no auth. tier: "llm" uses an LLM for richer suggestions — 270 credits, requires x-api-key. Response includes score (0–100), suggestions[], and (for llm tier) enhanced_prompt — a rewritten task. Errors: 400 input_too_long (10,000 char max) · 500 enhance_error

POST /api/rigor/connections

POST/api/rigor/connectionsAuth: x-api-key · Cost: Free

Registers a new MCP server connection. Server URL is validated for SSRF safety at registration time. Credentials are encrypted at rest immediately and never returned. Returns 201 with connection.status: "pending". Call /test to promote to active.

FieldTypeRequiredDescription
labelstringYesHuman-readable name.
server_urlstringYesHTTPS URL.
auth_typestringYesbearer_token | api_key | oauth | none
transportstringNostreamable-http (default) or sse
auth_credentialobjectConditionalRequired when auth_type is not none.

GET /api/rigor/connections

GET/api/rigor/connectionsAuth: x-api-key · Cost: Free

Returns all connections registered for your organization. Credentials are never included. Status values: pending, active, error, revoked. capabilities is null until a connection test completes.

PATCH /api/rigor/connections/{id}

PATCH/api/rigor/connections/{id}Auth: admin · Cost: Free

Updates a registered connection. All fields optional.

POST /api/rigor/connections/{id}/test

POST/api/rigor/connections/{id}/testAuth: x-api-key · Cost: Free

Tests connectivity. Performs DNS-level SSRF check. On success, statusactive, last_tested_at recorded. On SSRF failure, statuserror and the response is 400.

DELETE /api/rigor/connections/{id}

DELETE/api/rigor/connections/{id}Auth: x-api-key · Cost: Free

Soft delete. Record retained for audit, status set to revoked, credentials cleared. Revoked connections cannot be used in workflow execution.

Connection security

ControlWhat it does
Credential encryptionAES-256-GCM at rest. Never returned in any response.
SSRF — registrationHTTPS only, no private IPs, no cloud metadata endpoints, no internal hostnames.
SSRF — testDNS resolved at test time; all A/AAAA records checked against blocklist.
Read-only enforcementOnly resources/read and resources/list are executed. tools/call, prompts/*, sampling/*, all writes are blocked regardless of server capabilities.
Org isolationEvery request filtered by your org ID, derived from your API key.
Content sanitizationExternal MCP content wrapped in containment framing, scanned for prompt-injection patterns.

Limits: max 10 connections per org · duplicate server_url rejected with 409 · HTTPS only.

MCP tools

Connect to Plith via MCP at https://plith.ai/api/mcp/rigor. Compatible with Claude Desktop, Cursor, Windsurf, Smithery, and any MCP-compatible client. Authenticate via the x-api-key header, or use anonymous mode (rate-limited: 30 req/min, 500 req/day per IP) for evaluation.

Discoverable tools

ToolDescription
rigor_planPlan a workflow without executing it (free). Available anonymously for evaluation.
rigor_executeExecute a planned or fresh workflow.
rigor_statusGet workflow progress and results.

Hidden tools

Callable but do not appear in tools/list:

ToolDescription
rigor_resumeResume a stalled or failed workflow.
rigor_approveApprove or reject a workflow pending human review.
rigor_stepDrive a single step of an interactive workflow.
rigor_connectionsManage MCP connections.

Plan-then-execute (recommended)

Plan first to see the step sequence and cost estimate. Execute only when satisfied.

# Step 1: Plan (free)
POST /api/rigor/plan
  { "task_description": "...", "preferences": { "rigor_level": "standard" } }
  → { plan: { workflow_id: "wr_...", sequence: [...], cost: { credits: 540 } } }

# Step 2: Execute with polling delivery
POST /api/rigor/execute
  { "workflow_id": "wr_...", "delivery": { "method": "polling" } }
  → { workflow_id: "wr_...", status: "queued", poll_url: "/api/rigor/status/wr_..." }

# Step 3: Poll until "completed"
GET /api/rigor/status/wr_...
  → { workflow: { status: "completed", deliverable: { ... } } }

Webhook delivery

Receive results pushed to your endpoint instead of polling. Store webhook_secret and verify incoming payloads via HMAC-SHA256.

POST /api/rigor/execute
  {
    "workflow_id": "wr_...",
    "delivery": {
      "method": "webhook",
      "webhook_url": "https://your-server.example.com/rigor-webhook"
    }
  }
  → { webhook_url: "...", webhook_status: "registered", webhook_secret: "..." }

Approval gate

Request a human decision before final steps execute.

# Plan with approval gate
POST /api/rigor/plan
  { "task_description": "...", "preferences": { "require_approval": true } }

# Execute — workflow will pause at pending_approval
POST /api/rigor/execute
  { "workflow_id": "wr_...", "delivery": { "method": "polling" } }

# Poll until status === "pending_approval", then approve
POST /api/rigor/approve
  { "workflow_id": "wr_...", "decision": "approved", "notes": "Looks good" }
  # workflow automatically resumes after approval

Interactive mode

Drive execution one step at a time. Sessions expire after 30 minutes of inactivity.

POST /api/rigor/execute
  { "task_description": "...", "mode": "interactive" }
  → { status: "interactive_waiting", sequence: [...] }

POST /api/rigor/step
  { "workflow_id": "wr_...", "action": "next" }
  → { status: "step_executing", poll_url: "..." }

Workflow chaining

Inherit context from a completed workflow into a new one. Chain depth limit: 10 links.

POST /api/rigor/execute
  {
    "task_description": "Implement the solution from the prior design",
    "prior_workflow_id": "wr_parent...",
    "context_fields": ["deliverable", "quality_review"]
  }

Worked example

A complete plan → execute → poll cycle for a Solution Design.

curl -X POST https://plith.ai/api/rigor/plan \
  -H "x-api-key: YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{"task_description": "Design a caching layer for our API"}'

# → plan.cost.credits = 560 · estimated cost shown before committing

curl -X POST https://plith.ai/api/rigor/execute \
  -H "x-api-key: YOUR_KEY" \
  -d '{"workflow_id": "wr_...", "delivery": {"method": "polling"}}'

# → status: queued · poll_url returned

curl https://plith.ai/api/rigor/status/wr_... \
  -H "x-api-key: YOUR_KEY"

# → status: completed · quality_score: 92 · credits_used: 545

Error reference

All endpoints return errors in this envelope:

{
  "error": {
    "code": "missing_field",
    "message": "workflow_id is required.",
    "request_id": "req_abc123def456...",
    "fix": "POST /api/rigor/plan with your task_description",
    "docs": "https://plith.ai/docs/errors#missing_field",
    "details": { "field": "workflow_id" }
  }
}

fix, docs, and details are included only when available. request_id is always present.

Auth

CodeHTTPSummary
missing_api_key401Provide x-api-key header.
invalid_api_key401Key not found or revoked.
forbidden403Resource belongs to a different org.

Validation

CodeHTTPSummary
invalid_body400Body must be valid JSON.
missing_field400<field> required.
invalid_task_description400Must contain at least 2 words.
vague_task_description400Classifier confidence too low.
input_too_long400Input exceeds maximum length.
invalid_step_index400approval_before_step index out of range.

Rate limiting

CodeHTTPSummary
rate_limit_exceeded429Wait per Retry-After header.
concurrent_limit_exceeded429Plan's concurrent workflow limit reached (Free: 1, Pro: 3, Team: 10).

Workflow state

CodeHTTPSummary
not_found404Workflow not found.
no_plan400Workflow has no plan.
insufficient_credits402Top up via /api/billing/checkout.
workspace_budget_exceeded402Adjust budget or reduce plan.
workflow_has_progress409Use /resume.
invalid_status409Action not allowed in current state.
duplicate_task409Identical task in last 5 min.
already_complete409Nothing to resume.
resume_conflict409Another resume in progress.
pending_human_review409Use /approve.

Chaining & connections

CodeHTTPSummary
prior_not_found404Prior workflow not found.
prior_not_terminal409Wait for prior to complete.
chain_depth_exceeded422Max 10 hops.
context_too_large422Use context_fields to restrict.
feature_not_enabled501MCP gateway disabled.
session_expired41030-min TTL — use /resume.
plan_timeout504Simplify or split the task.
provider_exhausted503All providers failed — retry.
internal_error500Retry; include request_id.

Response conventions

Every successful response includes:

FieldTypeDescription
request_idstringAlways req_ + 24 hex chars. Include when contacting support.
credits_usednumberCredits deducted by this request. 0 for free endpoints.
credits_remainingnumberOrg balance after this request.
fallback_behaviorstringWhat the system did when upstream was degraded — "none" when normal.

Rigor workflow endpoints (/plan, /execute, /status, /approve, /resume, /step) use product-specific response shapes and do not include credits_used / credits_remaining at the top level. Credit usage for workflows is reported via the status endpoint as workflow.credits_used.