Endpoints

Startup research API

GET /healthHealth check
GET /v1/pingAuth check
GET /v1/billingCurrent prepaid credit balance and write pricing
POST /v1/billing/top-upsCreate a Stripe-hosted top-up checkout session
GET /v1/api-keysList API keys for the current workspace
POST /v1/api-keysCreate a new API key
POST /v1/api-keys/:apiKeyId/rotateRotate an existing API key and return the new secret once
POST /v1/api-keys/:apiKeyId/revokeRevoke an API key
GET /v1/chat/threadsList saved case summaries for the current workspace
GET /v1/chat/threads/:threadIdRead one case, including messages, reports, and research runs
POST /v1/chat/threadsCreate a new case and return the first assistant reply. Never auto-starts research.
POST /v1/chat/threads/:threadId/messagesContinue an existing case. Never auto-starts research.
POST /v1/chat/threads/:threadId/research-runsExplicitly queue a research run for the current anamnesis snapshot
POST /mcpRemote streamable HTTP MCP endpoint
Access

API key scopes

readGET /v1/ping, case reads, billing reads, and MCP resource reads
writeEverything in read plus case chat writes and research runs. Chat turns spend a fixed 1 credit per successful turn by default; research runs spend a fixed upfront credit amount.
adminFull access, including top-ups and API key management
Billing

GET /v1/billing

Pricing is prepaid: $1 buys 10 credits. Chat turns cost 1 credit per successful turn by default, and research runs cost 30 credits upfront. Failed research runs are refunded automatically.

JSON
{
  "chatTurnBillingMode": "fixed",
  "chatTurnMaxReserveCredits": 1,
  "creditBalance": 240,
  "currency": "usd",
  "managementScope": "admin",
  "pricePer100CreditsUsd": 10,
  "researchRunBillingMode": "fixed",
  "researchRunPriceCredits": 30,
  "topUpEndpoint": "https://api.console.94.159.109.116.nip.io/v1/billing/top-ups",
  "topUpOptions": [
    {
      "creditQuantity": 30,
      "usdQuantity": 3
    },
    {
      "creditQuantity": 50,
      "usdQuantity": 5
    },
    {
      "creditQuantity": 100,
      "usdQuantity": 10
    }
  ]
}
Create top-up session
curl https://api.console.94.159.109.116.nip.io/v1/billing/top-ups \
  -X POST \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "usdQuantity": 5,
    "successUrl": "https://client.example.com/billing/success",
    "cancelUrl": "https://client.example.com/billing/cancel"
  }'
Keys

/v1/api-keys

Use an admin key to mint, rotate, and revoke machine credentials without using the console UI.

Create key
curl https://api.console.94.159.109.116.nip.io/v1/api-keys \
  -X POST \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Automation key",
    "scopes": ["read", "write"]
  }'
Smoke response

GET /v1/ping

JSON
{
  "creditBalance": 240,
  "ok": true
}
Start

POST /v1/chat/threads

Returns 202 Accepted with a complete assistant reply, the updated case state, and the latest anamnesis and gap assessment. This route never auto-starts research, even if the case is already ready.

cURL
curl https://api.console.94.159.109.116.nip.io/v1/chat/threads \
  -X POST \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "message": "Idea: AI copilot for insurance brokers in Southeast Asia. It drafts proposals, compares policy options, and speeds up manual broker workflows."
  }'
202 JSON
{
  "assistantMessage": {
    "id": "msg_...",
    "role": "assistant",
    "status": "complete"
  },
  "anamnesis": {
    "ideaSummary": "AI copilot for insurance brokers"
  },
  "creditBalance": 239,
  "gapAssessment": {
    "readinessStatus": "ready"
  },
  "latestCompletedReportId": null,
  "reportStaleness": {
    "isStale": false
  },
  "thread": {
    "id": "thread_...",
    "messageCount": 2
  },
  "userMessage": {
    "id": "msg_...",
    "role": "user",
    "status": "complete"
  }
}

If the workspace has no credits left, the same route returns 402 Payment Required.

402 JSON
{
  "error": "Insufficient credits",
  "creditBalance": 0,
  "requiredCredits": 1
}
Continue

POST /v1/chat/threads/:threadId/messages

Also returns 202 Accepted with the complete assistant reply and the refreshed case snapshot. Use the refreshed case state to decide whether to start research explicitly.

cURL
curl https://api.console.94.159.109.116.nip.io/v1/chat/threads/<thread_id>/messages \
  -X POST \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "message": "Now compare it against manual broker workflow and legacy SaaS competitors."
  }'
Read

GET /v1/chat/threads/:threadId

Read the canonical case state, including anamnesis, gap assessment, messages, reports, and research run status.

cURL
curl https://api.console.94.159.109.116.nip.io/v1/chat/threads/<thread_id> \
  -H "Authorization: Bearer $API_KEY"

Completed n8n reports are exposed on thread.reports[].reportJson. The surrounding report record also carries identifiers like id, runId, and upstreamRequestId.

thread.reports[].reportJson
{
  "verdict": "TEST CHEAP",
  "confidence": "Medium",
  "idea": "AI concierge for travel planning",
  "why_it_can_fly": [
    "Trip planning is fragmented and repetitive for frequent travelers",
    "A concierge MVP can be tested without deep booking infrastructure",
    "The product can deliver value on the first session"
  ],
  "why_it_can_crash": [
    "Retention may collapse after the first trip is planned",
    "Travel incumbents already own parts of the workflow",
    "Users may default to free planning tools"
  ],
  "risk_map": {
    "demand": { "level": "Medium", "reason": "The pain is real, but urgency depends on trip frequency." },
    "monetization": { "level": "High", "reason": "Users may not pay unless the time savings feel obvious." },
    "technical": { "level": "Low", "reason": "The MVP is mostly orchestration and prompting." },
    "app_store": { "level": "Medium", "reason": "Travel assistance is viable, but automation claims should stay grounded." },
    "competition": { "level": "High", "reason": "TripIt, Wanderlog, and Google Travel already own trust and habit." },
    "retention": { "level": "High", "reason": "Trip planning is episodic, so repeat usage is not guaranteed." }
  },
  "overall_risk": "Medium",
  "competitors": [
    {
      "app_name": "TripIt",
      "threat_level": "High",
      "why": "Strong brand and habit around itinerary organization.",
      "app_store_link": "https://apps.apple.com/us/app/tripit-travel-planner/id311035142"
    }
  ],
  "differentiation": "Real-time AI concierge that turns rough intent into a ready day plan fast.",
  "main_risk": "Users may like the first output but not return often enough to support paid retention.",
  "validate_first": "Will travelers trust and reuse AI-generated itineraries enough to pay?",
  "cheapest_test": "Sell a manual concierge itinerary service behind a landing page and fulfill with AI plus human review.",
  "dont_do_now": "Do not build booking and full travel infrastructure before repeat usage exists.",
  "potential": "Niche",
  "recommendation": "Test this with a manual concierge MVP first. If users do not come back for a second trip or refuse to pay for faster planning, kill it early."
}
Research

POST /v1/chat/threads/:threadId/research-runs

Starts research for the current anamnesis snapshot. New work returns 202 Accepted; exact matching completed reports can return 200 OK with the reused result immediately instead of queueing a new paid run. In the console UI, this is the same explicit action exposed as the Start research button under the ready-state assistant reply.

cURL
curl https://api.console.94.159.109.116.nip.io/v1/chat/threads/<thread_id>/research-runs \
  -X POST \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "force": false
  }'
202 JSON
{
  "anamnesisSnapshot": {
    "ideaSummary": "AI copilot for insurance brokers"
  },
  "balance": 210,
  "gapAssessment": {
    "readinessStatus": "ready"
  },
  "reportStaleness": {
    "isStale": false
  },
  "runId": "run_...",
  "thread": {
    "id": "thread_..."
  }
}
MCP

/mcp

Remote MCP over streamable HTTP with the same bearer API keys. The current server exposes two tools and three read resources. Public deployments should expose this endpoint over HTTPS.

send_messageCreate a case when threadId is omitted, otherwise append to an existing case and return the updated snapshot. Never auto-starts research.
start_researchExplicitly start research for an existing case and either queue a new run or return an exact matching completed report immediately
https://api.console.94.159.109.116.nip.io/billingResource with the current balance, pricing, and top-up options
https://api.console.94.159.109.116.nip.io/chat/threadsResource listing case summaries for the current workspace
https://api.console.94.159.109.116.nip.io/chat/threads/{threadId}Resource template for one case with messages, reports, anamnesis, and research runs
Generic config
{
  "mcpServers": {
    "startup-research": {
      "type": "streamable-http",
      "url": "https://api.console.94.159.109.116.nip.io/mcp",
      "headers": {
        "Authorization": "Bearer $API_KEY"
      }
    }
  }
}
TOML config
[mcp_servers.startup-research]
url = "https://api.console.94.159.109.116.nip.io/mcp"
http_headers = { Authorization = "Bearer sk_live_or_test_api_key" }

MCP does not return synthetic pending handles. send_message returns the updated case state immediately and leaves research idle. start_research returns the accepted run plus current balance and gap assessment.

send_message result
{
  "assistantMessage": {
    "id": "msg_...",
    "role": "assistant",
    "status": "complete"
  },
  "creditBalance": 239,
  "gapAssessment": {
    "readinessStatus": "ready"
  },
  "thread": {
    "id": "thread_..."
  },
  "userMessage": {
    "id": "msg_...",
    "role": "user",
    "status": "complete"
  }
}
start_research result
{
  "anamnesisSnapshot": {
    "ideaSummary": "AI copilot for insurance brokers"
  },
  "balance": 210,
  "gapAssessment": {
    "readinessStatus": "ready"
  },
  "runId": "run_...",
  "thread": {
    "id": "thread_..."
  }
}
Tool error
{
  "code": "insufficient_credits",
  "message": "Insufficient credits. Read https://api.console.94.159.109.116.nip.io/billing for the current balance before retrying."
}