openapi: 3.1.0
info:
  title: Osmaura Prospect API
  version: 2.0.0
  description: >-
    Retrieve tenant-scoped, human-reviewed prospect editions. Version 2 keeps
    source-backed data separate from analyst conclusions and includes source
    coverage, official links, and reproducible record locators. Only explicitly
    published editions are visible.
servers:
  - url: https://dashboard.osmaura.com
security:
  - bearerAuth: []
paths:
  /v2/prospects:
    get:
      operationId: getProspects
      summary: Get a published prospect edition
      description: >-
        Returns the latest complete prospect edition unless a date is supplied.
        Dossiers are returned inline and rank is analysis.ranking.rank.
      parameters:
        - $ref: "#/components/parameters/EditionDate"
        - $ref: "#/components/parameters/IfNoneMatch"
      responses:
        "200":
          description: Published prospect edition.
          headers:
            ETag:
              schema: {type: string}
            Cache-Control:
              schema: {type: string, example: "private, max-age=300"}
          content:
            application/json:
              schema: {$ref: "#/components/schemas/ProspectEdition"}
        "304": {description: The edition has not changed.}
        "400": {$ref: "#/components/responses/BadRequest"}
        "401": {$ref: "#/components/responses/Unauthorized"}
        "402": {$ref: "#/components/responses/SubscriptionRequired"}
        "404": {$ref: "#/components/responses/NotFound"}
        "503": {$ref: "#/components/responses/Unavailable"}
  /v2/prospect-editions:
    get:
      operationId: listProspectEditions
      summary: List published prospect-edition history
      parameters:
        - $ref: "#/components/parameters/EditionLimit"
      responses:
        "200":
          description: Published editions, newest first.
          content:
            application/json:
              schema:
                type: object
                additionalProperties: false
                required: [editions]
                properties:
                  editions:
                    type: array
                    items: {$ref: "#/components/schemas/EditionSummary"}
        "401": {$ref: "#/components/responses/Unauthorized"}
        "402": {$ref: "#/components/responses/SubscriptionRequired"}
        "503": {$ref: "#/components/responses/Unavailable"}
  /v1/signals:
    get:
      deprecated: true
      operationId: getLegacySignals
      summary: Get a compact legacy signal edition
      description: Existing integrations may continue using this endpoint.
      parameters:
        - $ref: "#/components/parameters/EditionDate"
        - $ref: "#/components/parameters/IfNoneMatch"
      responses:
        "200":
          description: Published compact signal edition.
          content:
            application/json:
              schema: {$ref: "#/components/schemas/LegacyEdition"}
        "304": {description: The edition has not changed.}
        "400": {$ref: "#/components/responses/BadRequest"}
        "401": {$ref: "#/components/responses/Unauthorized"}
        "402": {$ref: "#/components/responses/SubscriptionRequired"}
        "404": {$ref: "#/components/responses/NotFound"}
        "503": {$ref: "#/components/responses/Unavailable"}
  /v1/signal-editions:
    get:
      deprecated: true
      operationId: listLegacySignalEditions
      summary: List compact legacy edition history
      parameters:
        - $ref: "#/components/parameters/EditionLimit"
      responses:
        "200":
          description: Published editions, newest first.
          content:
            application/json:
              schema:
                type: object
                additionalProperties: false
                required: [editions]
                properties:
                  editions:
                    type: array
                    items: {$ref: "#/components/schemas/EditionSummary"}
        "401": {$ref: "#/components/responses/Unauthorized"}
        "402": {$ref: "#/components/responses/SubscriptionRequired"}
        "503": {$ref: "#/components/responses/Unavailable"}
components:
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: API key
      description: Tenant-scoped production read key.
  parameters:
    EditionDate:
      name: date
      in: query
      required: false
      description: Edition date in YYYY-MM-DD format.
      schema: {type: string, format: date}
    IfNoneMatch:
      name: If-None-Match
      in: header
      required: false
      schema: {type: string}
    EditionLimit:
      name: limit
      in: query
      required: false
      schema: {type: integer, minimum: 1, maximum: 90, default: 30}
  responses:
    BadRequest:
      description: Invalid request.
      content: {application/json: {schema: {$ref: "#/components/schemas/Error"}}}
    Unauthorized:
      description: Missing, invalid, or revoked API key.
      content: {application/json: {schema: {$ref: "#/components/schemas/Error"}}}
    SubscriptionRequired:
      description: An active organization subscription is required.
      content: {application/json: {schema: {$ref: "#/components/schemas/Error"}}}
    NotFound:
      description: No published edition exists for the requested date.
      content: {application/json: {schema: {$ref: "#/components/schemas/Error"}}}
    Unavailable:
      description: Account-access verification is temporarily unavailable.
      content: {application/json: {schema: {$ref: "#/components/schemas/Error"}}}
  schemas:
    ProspectEdition:
      type: object
      additionalProperties: false
      required: [object, schema_version, edition_date, revision, published_at, count, prospects]
      properties:
        object: {type: string, const: prospect_edition}
        schema_version: {type: string, const: "2.0"}
        edition_date: {type: string, format: date}
        revision: {type: integer, minimum: 1}
        published_at: {type: string, format: date-time}
        count: {type: integer, minimum: 1, maximum: 100}
        prospects:
          type: array
          minItems: 1
          maxItems: 100
          items: {$ref: "#/components/schemas/ProspectDossier"}
    EditionSummary:
      type: object
      additionalProperties: false
      required: [edition_date, published_at, revision, count]
      properties:
        edition_date: {type: string, format: date}
        published_at: {type: string, format: date-time}
        revision: {type: integer, minimum: 1}
        count: {type: integer, minimum: 1, maximum: 100}
    ProspectDossier:
      type: object
      additionalProperties: false
      description: >-
        The five-field prospect contract. Observed facts and deterministic
        statistics live under data; interpretation lives under analysis.
      required: [id, prospect, data, analysis, coverage]
      properties:
        id: {type: string, minLength: 1}
        prospect: {$ref: "#/components/schemas/ProspectIdentity"}
        data: {$ref: "#/components/schemas/ProspectData"}
        analysis: {$ref: "#/components/schemas/ProspectAnalysis"}
        coverage: {$ref: "#/components/schemas/Coverage"}
    ProspectIdentity:
      type: object
      additionalProperties: false
      required: [type, name, legal_names, domain, locations, identifiers, current_employment]
      properties:
        type: {enum: [organization, person]}
        name: {type: string, minLength: 1}
        legal_names:
          type: array
          items: {type: string}
        domain: {type: [string, "null"]}
        locations:
          type: array
          items: {$ref: "#/components/schemas/Location"}
        identifiers:
          type: object
          description: Source and warehouse identifiers; unknown values are null.
          additionalProperties: true
        current_employment:
          oneOf:
            - {type: "null"}
            - {$ref: "#/components/schemas/CurrentEmployment"}
    Location:
      type: object
      additionalProperties: false
      required: [city, state, country]
      properties:
        city: {type: [string, "null"]}
        state: {type: [string, "null"]}
        country: {type: [string, "null"]}
    CurrentEmployment:
      type: object
      additionalProperties: false
      required: [employer, role, location]
      properties:
        employer: {type: [string, "null"]}
        role: {type: [string, "null"]}
        location: {type: [string, "null"]}
    ProspectData:
      type: object
      description: >-
        Source data and deterministic statistics grouped by real-world domain.
        Empty arrays do not imply a checked no-match; consult coverage.sources.
      additionalProperties: true
      required: [dol_oflc, uscis, dhs, government_business, company, contacts]
      properties:
        dol_oflc: {$ref: "#/components/schemas/DolData"}
        uscis:
          type: object
          additionalProperties: true
          required: [h1b_employer_hub]
          properties:
            h1b_employer_hub: {$ref: "#/components/schemas/DataCollection"}
        dhs:
          type: object
          additionalProperties: true
          required: [everify]
          properties:
            everify: {$ref: "#/components/schemas/DataCollection"}
        government_business: {$ref: "#/components/schemas/GovernmentBusinessData"}
        company: {$ref: "#/components/schemas/CompanyData"}
        professional: {$ref: "#/components/schemas/ProfessionalData"}
        contacts:
          type: array
          items: {$ref: "#/components/schemas/Contact"}
    DolData:
      type: object
      additionalProperties: true
      required: [lca, perm, pwd]
      properties:
        lca: {$ref: "#/components/schemas/DataCollection"}
        perm: {$ref: "#/components/schemas/DataCollection"}
        pwd: {$ref: "#/components/schemas/DataCollection"}
    DataCollection:
      type: object
      additionalProperties: true
      description: A source-specific record collection and its deterministic aggregates.
      properties:
        statistics:
          type: object
          additionalProperties: true
        by_fiscal_year:
          type: array
          items: {type: object, additionalProperties: true}
        records:
          type: array
          items: {$ref: "#/components/schemas/FactualRecord"}
        source: {$ref: "#/components/schemas/Source"}
    GovernmentBusinessData:
      type: object
      additionalProperties: true
      properties:
        sec_filings: {$ref: "#/components/schemas/FactualRecordArray"}
        contracts: {$ref: "#/components/schemas/FactualRecordArray"}
        grants: {$ref: "#/components/schemas/FactualRecordArray"}
        trademarks: {$ref: "#/components/schemas/FactualRecordArray"}
        corporate_records: {$ref: "#/components/schemas/FactualRecordArray"}
        regulatory_records: {$ref: "#/components/schemas/FactualRecordArray"}
        warn_notices: {$ref: "#/components/schemas/FactualRecordArray"}
        enforcement: {$ref: "#/components/schemas/FactualRecordArray"}
    CompanyData:
      type: object
      additionalProperties: true
      properties:
        funding_events: {$ref: "#/components/schemas/FactualRecordArray"}
        recent_developments: {$ref: "#/components/schemas/FactualRecordArray"}
        job_postings: {$ref: "#/components/schemas/FactualRecordArray"}
        locations: {$ref: "#/components/schemas/FactualRecordArray"}
        reported_metrics: {$ref: "#/components/schemas/FactualRecordArray"}
    ProfessionalData:
      type: object
      additionalProperties: true
      description: Present for person prospects when relevant.
      properties:
        employment: {$ref: "#/components/schemas/FactualRecordArray"}
        education: {$ref: "#/components/schemas/FactualRecordArray"}
        publications: {$ref: "#/components/schemas/FactualRecordArray"}
        patents: {$ref: "#/components/schemas/FactualRecordArray"}
        open_source: {$ref: "#/components/schemas/FactualRecordArray"}
        awards: {$ref: "#/components/schemas/FactualRecordArray"}
        judging_and_review: {$ref: "#/components/schemas/FactualRecordArray"}
        standards: {$ref: "#/components/schemas/FactualRecordArray"}
        speaking: {$ref: "#/components/schemas/FactualRecordArray"}
        media: {$ref: "#/components/schemas/FactualRecordArray"}
    FactualRecordArray:
      type: array
      items: {$ref: "#/components/schemas/FactualRecord"}
    FactualRecord:
      type: object
      additionalProperties: true
      required: [id, source]
      properties:
        id: {type: string, minLength: 1}
        source: {$ref: "#/components/schemas/Source"}
    Source:
      type: object
      additionalProperties: true
      required: [publisher, official_page_url, record_locator, retrieved_at]
      properties:
        publisher: {type: string, minLength: 1}
        official_page_url: {type: string, format: uri}
        dataset:
          oneOf:
            - {type: "null"}
            - {$ref: "#/components/schemas/Dataset"}
        record_locator:
          type: object
          additionalProperties: true
        retrieved_at: {type: string, format: date-time}
    Dataset:
      type: object
      additionalProperties: false
      required: [filename, download_url, record_layout_url, data_through]
      properties:
        filename: {type: [string, "null"]}
        download_url: {type: [string, "null"], format: uri}
        record_layout_url: {type: [string, "null"], format: uri}
        data_through: {type: [string, "null"], format: date}
    Contact:
      type: object
      additionalProperties: false
      required: [id, name, role, channels, evidence_ids]
      properties:
        id: {type: string, minLength: 1}
        name: {type: string, minLength: 1}
        role: {type: [string, "null"]}
        channels:
          type: array
          items: {$ref: "#/components/schemas/ContactChannel"}
        evidence_ids:
          type: array
          items: {type: string}
    ContactChannel:
      type: object
      additionalProperties: false
      required: [type, value, source_url, as_of, current_status, outreach_suitability, consent_status, suppression_reason]
      properties:
        type: {enum: [email, phone, linkedin, github, company_form, other]}
        value: {type: [string, "null"]}
        source_url: {type: [string, "null"], format: uri}
        as_of: {type: [string, "null"], format: date}
        current_status: {enum: [verified_current, verified_historical, unverified, unknown]}
        outreach_suitability: {enum: [ready, permission_first, identity_only, suppress]}
        consent_status: {enum: [consented, unknown, not_applicable, opted_out]}
        suppression_reason: {type: [string, "null"]}
    ProspectAnalysis:
      type: object
      additionalProperties: false
      required:
        - generated_at
        - analysis_version
        - ranking
        - summary
        - why_now
        - counsel_analysis
        - lead_factors
        - counterevidence
        - context_only
        - recommended_approach
        - limitations
        - evidence_accounting
      properties:
        generated_at: {type: string, format: date-time}
        analysis_version: {type: string, minLength: 1}
        ranking: {$ref: "#/components/schemas/Ranking"}
        summary: {type: string, minLength: 1}
        why_now: {$ref: "#/components/schemas/WhyNow"}
        counsel_analysis: {$ref: "#/components/schemas/CounselAnalysis"}
        lead_factors:
          type: array
          items: {$ref: "#/components/schemas/AnalysisFinding"}
        counterevidence:
          type: array
          items: {$ref: "#/components/schemas/AnalysisFinding"}
        context_only:
          type: array
          items: {$ref: "#/components/schemas/AnalysisFinding"}
        recommended_approach: {$ref: "#/components/schemas/RecommendedApproach"}
        eligibility_screen:
          type: [object, "null"]
          additionalProperties: true
          description: Evidence screen only; never a legal conclusion.
        limitations:
          type: array
          items: {type: string}
        evidence_accounting: {$ref: "#/components/schemas/EvidenceAccounting"}
    Ranking:
      type: object
      additionalProperties: false
      required: [rank, disposition, disposition_reason, scores, confidence]
      properties:
        rank: {type: integer, minimum: 1}
        disposition: {enum: [qualified, nurture, monitor, suppress]}
        disposition_reason: {type: string, minLength: 1}
        scores: {$ref: "#/components/schemas/Scores"}
        confidence: {type: number, minimum: 0, maximum: 1}
    Scores:
      type: object
      additionalProperties: false
      required: [evidence_strength, why_now_strength, commercial_readiness, counsel_opportunity, mobility_intent, overall_rank]
      properties:
        evidence_strength: {type: number, minimum: 0, maximum: 100}
        why_now_strength: {type: number, minimum: 0, maximum: 100}
        commercial_readiness: {type: number, minimum: 0, maximum: 100}
        counsel_opportunity: {type: [number, "null"], minimum: 0, maximum: 100}
        mobility_intent: {type: [number, "null"], minimum: 0, maximum: 100}
        overall_rank: {type: number, minimum: 0, maximum: 100}
    WhyNow:
      type: object
      additionalProperties: false
      required: [narrative, trigger_date, urgency_window, evidence_ids]
      properties:
        narrative: {type: string, minLength: 1}
        trigger_date: {type: [string, "null"], format: date}
        urgency_window: {type: string, minLength: 1}
        evidence_ids:
          type: array
          items: {type: string}
    CounselAnalysis:
      type: object
      additionalProperties: false
      required: [classification, narrative, scope, filings_reviewed, named_counsel_filings, confidence, evidence_ids, caveat]
      properties:
        classification:
          enum: [observed_pro_se, no_named_counsel, incumbent_identified, fragmented_or_transitioning, possible_undisclosed_adviser, unknown, not_applicable]
        narrative: {type: string, minLength: 1}
        scope: {$ref: "#/components/schemas/CounselScope"}
        filings_reviewed: {type: [integer, "null"], minimum: 0}
        named_counsel_filings: {type: [integer, "null"], minimum: 0}
        confidence: {type: number, minimum: 0, maximum: 1}
        evidence_ids:
          type: array
          items: {type: string}
        caveat: {type: string, minLength: 1}
    CounselScope:
      type: object
      additionalProperties: false
      required: [programs, from, through]
      properties:
        programs:
          type: array
          items: {type: string}
        from: {type: [string, "null"], format: date}
        through: {type: [string, "null"], format: date}
    AnalysisFinding:
      type: object
      additionalProperties: false
      required: [finding, effect_on_lead, explanation, strength, evidence_ids]
      properties:
        finding: {type: string, minLength: 1}
        effect_on_lead: {enum: [supports, weakens, limits_inference, context]}
        explanation: {type: string, minLength: 1}
        strength: {enum: [strong, moderate, weak, contextual]}
        evidence_ids:
          type: array
          items: {type: string}
    RecommendedApproach:
      type: object
      additionalProperties: false
      required: [narrative, recommended_contact_id]
      properties:
        narrative: {type: string, minLength: 1}
        recommended_contact_id: {type: [string, "null"]}
    EvidenceAccounting:
      type: object
      additionalProperties: false
      required:
        - records_reviewed
        - records_supporting_lead
        - records_weakening_lead
        - records_providing_context_only
        - records_used_for_identity_or_contact
        - unaddressed_record_ids
      properties:
        records_reviewed: {type: integer, minimum: 0}
        records_supporting_lead: {type: integer, minimum: 0}
        records_weakening_lead: {type: integer, minimum: 0}
        records_providing_context_only: {type: integer, minimum: 0}
        records_used_for_identity_or_contact: {type: integer, minimum: 0}
        unaddressed_record_ids:
          type: array
          items: {type: string}
    Coverage:
      type: object
      additionalProperties: false
      required: [generated_at, data_through, sources, identity_warnings, known_gaps]
      properties:
        generated_at: {type: string, format: date-time}
        data_through: {type: string, format: date}
        sources:
          type: array
          items: {$ref: "#/components/schemas/SourceCoverage"}
        identity_warnings:
          type: array
          items: {type: string}
        known_gaps:
          type: array
          items: {type: string}
    SourceCoverage:
      type: object
      additionalProperties: false
      required: [source, status, data_through, checked_at, record_count, query, limitations]
      properties:
        source: {type: string, minLength: 1}
        status: {enum: [matched, checked_no_match, not_applicable, not_checked, source_unavailable]}
        data_through: {type: [string, "null"], format: date}
        checked_at: {type: [string, "null"], format: date-time}
        record_count: {type: [integer, "null"], minimum: 0}
        query:
          type: object
          additionalProperties: true
        limitations:
          type: array
          items: {type: string}
    LegacyEdition:
      type: object
      additionalProperties: false
      required: [object, edition_date, revision, published_at, count, signals]
      properties:
        object: {type: string, const: signal_edition}
        edition_date: {type: string, format: date}
        revision: {type: integer, minimum: 1}
        published_at: {type: string, format: date-time}
        count: {type: integer, minimum: 1, maximum: 100}
        signals:
          type: array
          items: {$ref: "#/components/schemas/LegacySignal"}
    LegacySignal:
      type: object
      additionalProperties: true
      required: [id, rank, type, company, rationale, contacts, evidence]
      properties:
        id: {type: string}
        rank: {type: integer, minimum: 1}
        type: {type: string}
        company: {type: object, additionalProperties: true}
        rationale: {type: object, additionalProperties: true}
        contacts: {type: array, items: {type: object, additionalProperties: true}}
        evidence: {type: array, items: {type: object, additionalProperties: true}}
    Error:
      type: object
      additionalProperties: false
      required: [error]
      properties:
        error:
          type: object
          additionalProperties: false
          required: [code, message]
          properties:
            code: {type: string}
            message: {type: string}
