{"openapi":"3.1.0","info":{"title":"RepScale Research API","version":"1.0.0","description":"B2B sales research API. Generates structured prospect briefs, recommends sales angles, and traces every claim back to its source. Functionally identical to RepScale's MCP server — pick whichever wire format your stack prefers. Same API keys, same rate limits, same telemetry across both surfaces.","contact":{"name":"RepScale","url":"https://repscale.ai"},"license":{"name":"Commercial","url":"https://repscale.ai/terms"}},"servers":[{"url":"https://app.repscale.ai","description":"Production"}],"security":[{"bearerAuth":[]},{"apiKeyHeader":[]}],"tags":[{"name":"research","description":"Generate and query research briefs. Briefs have a 7-day server-side cache and a 30-day TTL."}],"paths":{"/api/v1/research":{"post":{"tags":["research"],"summary":"Generate a research brief for a prospect","description":"Researches a B2B prospect for sales outreach. Returns a structured brief covering the company, the contact, recent business signals, and leadership context. Long-running call (60–120s on a cold cache) — the response is wrapped in an SSE keepalive stream. Each `data:` event is a JSON object containing the full brief on success or a structured error on failure; an `_status` field mirrors the HTTP status the synchronous JSON path would set. Server-side 7-day cache: repeat calls for the same name+company within 7 days return the cached brief with `cached: true` and consume no LLM budget.","operationId":"researchProspect","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResearchRequest"},"examples":{"minimal":{"summary":"Minimum viable input","value":{"name":"Jane Doe","company":"Acme Corp"}},"full":{"summary":"All optional fields populated","value":{"name":"Jane Doe","company":"Acme Corp","title":"VP of Operations","website":"https://acme.com","context":"Met at SaaStr 2025; mentioned fleet visibility pain."}}}}}},"responses":{"200":{"description":"SSE stream. Final `data:` frame carries the full brief JSON, identical to the MCP `research_prospect` tool body.","content":{"text/event-stream":{"schema":{"$ref":"#/components/schemas/ResearchBrief"}}}},"400":{"description":"Structured error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Structured error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Structured error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Structured error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/research/{id}/angles":{"get":{"tags":["research"],"summary":"Get the recommended sales angle for a brief","description":"Returns the angle (what to lead with), avoid (what NOT to do), and a recommended opening discovery question. Built deterministically from the stored brief — no LLM call. Idempotent. Output is tailored to the user's Sales Context profile when set; falls back to product-agnostic phrasing when not.","operationId":"getRecommendedAngle","parameters":[{"$ref":"#/components/parameters/BriefId"}],"responses":{"200":{"description":"Recommended angle, avoid list, and opening question.","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"description":"Structured error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Structured error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"410":{"description":"Structured error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Structured error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Structured error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/research/{id}/confidence":{"get":{"tags":["research"],"summary":"Explain a brief's confidence level","description":"Returns the current confidence level (low|medium|high) plus the limiting factors and what would raise it. Use to decide whether to escalate, gather more info, or proceed. Idempotent.","operationId":"explainConfidence","parameters":[{"$ref":"#/components/parameters/BriefId"}],"responses":{"200":{"description":"Confidence level + factors.","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"description":"Structured error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Structured error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"410":{"description":"Structured error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Structured error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Structured error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/research/{id}/adjacent":{"get":{"tags":["research"],"summary":"Suggest adjacent research candidates from a brief","description":"Re-ranks three kinds of adjacent candidates already in the brief: named leadership beyond the primary prospect, incumbent vendors (displacement targets), and initiatives worth deeper study. Does NOT fetch new data — this surfaces what's already in the brief, ranked. Business competitors are excluded (already in the brief's Competitive Landscape). Idempotent.","operationId":"suggestAdjacentResearch","parameters":[{"$ref":"#/components/parameters/BriefId"},{"name":"purpose","in":"query","required":false,"schema":{"type":"string","enum":["account_plan","meeting_prep","competitive_landscape"]},"description":"Optional hint about why the agent is asking. Shapes ranking."},{"name":"context","in":"query","required":false,"schema":{"type":"string","maxLength":2000},"description":"Optional per-call intent (max 2000 chars). E.g. 'focus on fleet-tech displacement angles'. Composes with the seller's Sales Context profile; distinctive keywords boost matching candidates' rankings."}],"responses":{"200":{"description":"Ranked candidate list grouped by category.","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"Structured error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Structured error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Structured error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"410":{"description":"Structured error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Structured error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Structured error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/research/{id}/cite":{"post":{"tags":["research"],"summary":"Look up the source for a specific claim","description":"Returns the underlying source (URL, excerpt, date) for a specific claim in a brief. Token-overlap fuzzy match against the capture-time claim → source map; agents don't need to reproduce exact strings. Returns a `support_score` (0.0 to 1.0) — anything under ~0.4 is weakly supported. Idempotent.","operationId":"citeSource","parameters":[{"$ref":"#/components/parameters/BriefId"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CiteRequest"},"example":{"claim":"Acme's Q3 revenue grew 40% YoY"}}}},"responses":{"200":{"description":"Best-match source attribution.","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"Structured error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Structured error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Structured error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"410":{"description":"Structured error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Structured error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Structured error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}},"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"rsk_live_*","description":"RepScale API key in the Authorization header: `Authorization: Bearer rsk_live_<key>`. Generate at https://repscale.ai/settings?tab=api-keys."},"apiKeyHeader":{"type":"apiKey","in":"header","name":"x-api-key","description":"Alternative header for clients that cannot set Authorization."}},"parameters":{"BriefId":{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"The brief_id returned by a prior POST /api/v1/research call."}},"schemas":{"Error":{"type":"object","required":["error","message","suggested_fix","retryable"],"properties":{"error":{"type":"string","description":"Machine-readable error code (snake_case).","examples":["invalid_input","brief_not_found","daily_limit_reached"]},"message":{"type":"string","description":"One-sentence description of what went wrong."},"suggested_fix":{"type":"string","description":"Concrete next step the caller can take."},"retryable":{"type":"boolean","description":"Whether retrying this exact call (perhaps after a delay) might succeed."}}},"ResearchRequest":{"type":"object","required":["name","company"],"additionalProperties":false,"properties":{"name":{"type":"string","minLength":1,"maxLength":200,"description":"Full name of the prospect (the person being sold to)."},"company":{"type":"string","minLength":1,"maxLength":300,"description":"The prospect's company name."},"title":{"type":"string","maxLength":200,"description":"The prospect's job title, if known. Improves the brief."},"website":{"type":"string","maxLength":300,"description":"The company's website URL. Used as the primary first-party source."},"context":{"type":"string","maxLength":5000,"description":"Any seed context the agent already has — LinkedIn bio, call notes, prior conversation. Treated as seed data, not repeated back."}}},"ResearchBrief":{"type":"object","description":"Full brief response. See the MCP tool description for research_prospect for the complete field-by-field contract.","properties":{"cached":{"type":"boolean"},"prospect":{"type":"object"},"contact_insights":{"type":["object","null"]},"company":{"type":"object"},"signals":{"type":"array","items":{"type":"object"}},"leadership_context":{"type":"array","items":{"type":"object"}},"unresolved_roles":{"type":"array","items":{"type":"object"}},"incumbent_vendors":{"type":"array","items":{"type":"object"}},"confidence":{"type":"string","enum":["low","medium","high"]},"confidence_reasoning":{"type":"string"},"generated_at":{"type":"string","format":"date-time"},"sources":{"type":"array","items":{"type":"string"}},"brief_id":{"type":"string","format":"uuid"},"next_actions_available":{"type":"array","items":{"type":"string"}}}},"CiteRequest":{"type":"object","required":["claim"],"additionalProperties":false,"properties":{"claim":{"type":"string","minLength":1,"maxLength":500,"description":"The claim to verify, as a short sentence. Example: 'Q3 revenue grew 40% YoY'."}}}}}}