403Webshell
Server IP : 35.80.110.71  /  Your IP : 216.73.216.221
Web Server : Apache/2.4.58 (Ubuntu)
System : Linux ip-172-31-21-44 6.17.0-1019-aws #19~24.04.1-Ubuntu SMP Tue Jun 23 18:53:06 UTC 2026 x86_64
User : ubuntu ( 1000)
PHP Version : 8.3.31
Disable Function : NONE
MySQL : OFF  |  cURL : ON  |  WGET : ON  |  Perl : ON  |  Python : OFF  |  Sudo : ON  |  Pkexec : OFF
Directory :  /var/www/distill-web/public/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Command :


[ Back ]     

Current File : /var/www/distill-web/public/openapi.yaml
openapi: 3.1.0
info:
  title: Distill API
  version: 0.1.0
  summary: AI-assisted CRM data-cleanup. HubSpot duplicate detection via embeddings + clustering + reversible writes.
  description: |
    Distill connects to HubSpot, finds duplicate contacts via embeddings +
    string-similarity, surfaces them in a human-review queue, and writes
    reversible merges back through the HubSpot API. Production-shaped
    portfolio demo.

    Authentication is via `Authorization: Bearer dst_<prefix>_<secret>` API
    keys. Keys carry one of three scopes: `read`, `admin_read`, `admin_write`.
    Higher scopes include lower ones.

    All errors follow RFC 7807 problem-details. Responses are JSON.
  contact:
    name: Philip Rehberger
    url: https://distill.philiprehberger.com
  license:
    name: MIT
    identifier: MIT

servers:
  - url: https://api.distill.philiprehberger.com
    description: Production
  - url: http://localhost:8000
    description: Local development

security:
  - bearerAuth: []

paths:
  /v1/healthz:
    get:
      summary: Liveness probe
      operationId: healthCheck
      security: []
      responses:
        '200':
          description: Healthy
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Health'
  /v1/workspaces/current:
    get:
      summary: Current workspace context
      operationId: workspaceCurrent
      responses:
        '200':
          description: Workspace context
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: '#/components/schemas/Workspace'
  /v1/sync/status:
    get:
      summary: HubSpot sync status
      operationId: syncStatus
      responses:
        '200':
          description: Sync status
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SyncStatus'
  /v1/sync/start:
    post:
      summary: Trigger a full backfill from HubSpot
      operationId: syncStart
      responses:
        '202':
          description: Sync queued
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SyncRunRef'
  /v1/clusters:
    get:
      summary: List pending review clusters
      operationId: clustersList
      parameters:
        - in: query
          name: status
          schema:
            type: string
            enum: [pending, merged, rejected, skipped]
        - in: query
          name: min_similarity
          schema:
            type: number
            format: float
      responses:
        '200':
          description: Clusters
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ClusterList'
  /v1/clusters/{id}:
    get:
      summary: Cluster detail with members
      operationId: clusterShow
      parameters:
        - in: path
          name: id
          required: true
          schema:
            type: string
      responses:
        '200':
          description: Cluster detail
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: '#/components/schemas/Cluster'
  /v1/clusters/{id}/merge:
    post:
      summary: Confirm a merge
      operationId: clusterMerge
      parameters:
        - in: path
          name: id
          required: true
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/MergeRequest'
      responses:
        '202':
          description: Merge queued
  /v1/clusters/{id}/reject:
    post:
      summary: Reject a cluster (not-a-duplicate signal)
      operationId: clusterReject
      parameters:
        - in: path
          name: id
          required: true
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/RejectRequest'
      responses:
        '200':
          description: Rejected
  /v1/cluster/run:
    post:
      summary: Trigger a clustering pass
      operationId: clusterRun
      responses:
        '202':
          description: Queued
  /v1/merges:
    get:
      summary: Merge history
      operationId: mergesList
      responses:
        '200':
          description: Merge history
  /v1/merges/{id}/undo:
    post:
      summary: Reverse a merge
      operationId: mergeUndo
      parameters:
        - in: path
          name: id
          required: true
          schema:
            type: string
      responses:
        '202':
          description: Undo queued
  /v1/audit-log:
    get:
      summary: Audit trail
      operationId: auditLog
      responses:
        '200':
          description: Audit events

components:
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: dst_<prefix>_<secret>
  schemas:
    Health:
      type: object
      properties:
        healthy:
          type: boolean
        version:
          type: string
        checks:
          type: object
    Workspace:
      type: object
      properties:
        id:
          type: string
        name:
          type: string
        slug:
          type: string
        writes_enabled:
          type: boolean
        blocking_strategy:
          type: string
          enum: [domain, phone, name_company, any]
        similarity_threshold:
          type: number
          format: float
        auto_merge_enabled:
          type: boolean
        embedding_model:
          type: string
    SyncStatus:
      type: object
      properties:
        data:
          type: object
          properties:
            connected:
              type: boolean
            portal_id:
              type: string
              nullable: true
            last_full_sync_at:
              type: string
              format: date-time
              nullable: true
            last_incremental_sync_at:
              type: string
              format: date-time
              nullable: true
            webhook_subscribed:
              type: boolean
            recent_runs:
              type: array
              items:
                $ref: '#/components/schemas/SyncRun'
    SyncRun:
      type: object
      properties:
        id:
          type: string
        kind:
          type: string
          enum: [full_backfill, incremental, webhook_replay]
        status:
          type: string
          enum: [queued, running, finished, failed]
        contacts_seen:
          type: integer
        contacts_upserted:
          type: integer
        started_at:
          type: string
          format: date-time
          nullable: true
        finished_at:
          type: string
          format: date-time
          nullable: true
    SyncRunRef:
      type: object
      properties:
        data:
          type: object
          properties:
            sync_run_id:
              type: string
            status:
              type: string
    Cluster:
      type: object
      properties:
        id:
          type: string
        similarity:
          type: number
          format: float
        member_count:
          type: integer
        status:
          type: string
          enum: [pending, merged, rejected, skipped]
        blocking_strategy:
          type: string
        block_key:
          type: string
          nullable: true
        winner_hubspot_id:
          type: string
          nullable: true
        members:
          type: array
          items:
            type: object
            properties:
              hubspot_id:
                type: string
              email:
                type: string
                nullable: true
              first_name:
                type: string
                nullable: true
              last_name:
                type: string
                nullable: true
              company_name:
                type: string
                nullable: true
              phone_e164:
                type: string
                nullable: true
              updated_at_source:
                type: string
                format: date-time
                nullable: true
              owned_deals_count:
                type: integer
              owned_emails_count:
                type: integer
              owned_notes_count:
                type: integer
    ClusterList:
      type: object
      properties:
        data:
          type: array
          items:
            $ref: '#/components/schemas/Cluster'
    MergeRequest:
      type: object
      required: [winner_hubspot_id]
      properties:
        winner_hubspot_id:
          type: string
        strategy:
          type: string
          enum: [manual, newest_wins]
    RejectRequest:
      type: object
      required: [reason]
      properties:
        reason:
          type: string
          enum: [different_people, intentional_duplicate, needs_more_info, other]
        comment:
          type: string
          nullable: true
    Problem:
      type: object
      properties:
        type:
          type: string
        title:
          type: string
        status:
          type: integer
        detail:
          type: string
        errors:
          type: object
          additionalProperties: true

Youez - 2016 - github.com/yon3zu
LinuXploit