openapi: 3.1.0
info:
  title: Clow Ecosystem API
  version: "1.0"
  description: |
    Public API for the Clow ecosystem — bot interaction data, ARM metrics,
    marketplace listings, and $Clow token economy endpoints.

    **Base URL:** `https://api.clow.ai/v1`

    **Authentication:** Bearer token (API key from your Sovereign or Enterprise dashboard).

    **Rate limits:**
    - Sovereign tier: 1,000 requests/hour
    - Enterprise tier: 10,000 requests/hour, burst to 500 req/s
    - All limits are per API key, sliding window.

    **SDKs:** Node.js (`npm install @clow/sdk`), Python (`pip install clow-sdk`)
  contact:
    name: Clow API Support
    url: https://github.com/dnzengou/clow
    email: api@clow.ai
  license:
    name: MIT
    url: https://github.com/dnzengou/clow/blob/main/LICENSE

servers:
  - url: https://api.clow.ai/v1
    description: Production
  - url: https://api-staging.clow.ai/v1
    description: Staging (mirrors production data with 24h lag)

security:
  - BearerAuth: []

tags:
  - name: Bots
    description: Bot interaction data — starts, sessions, commands
  - name: ARM Metrics
    description: Acquire/Retain/Monetize analytics
  - name: SkillOpt
    description: EvoMetaClaw trajectory ingest + aggregate flywheel metrics
  - name: Marketplace
    description: Agent listings, reviews, revenue data
  - name: Token
    description: $Clow token economy — balances, streaks, staking
  - name: Webhooks
    description: Register and manage webhook endpoints

paths:

  # ── SkillOpt (EvoMetaClaw moat) ───────────────────────────────────────────

  /webhook/skillopt/trajectory:
    post:
      tags: [SkillOpt]
      summary: Ingest a user interaction trajectory
      description: |
        The moat endpoint. Each Clow bot POSTs the trajectory of every skill
        execution here. Trajectories are appended to JSONL and used for
        weekly LoRA fine-tunes on top-quartile outcomes.

        Enforces client-side PII redaction — raw user IDs must be hashed
        before submission.
      security:
        - WebhookSecret: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/Trajectory"
      responses:
        "200":
          description: Trajectory stored
          content:
            application/json:
              schema:
                type: object
                properties:
                  status: { type: string, enum: [stored] }
                  trajectory_id: { type: string }
                  step_count: { type: integer }
        "400":
          description: Missing required fields
        "401":
          description: Invalid webhook secret

  /metrics/trajectories:
    get:
      tags: [SkillOpt]
      summary: Aggregate SkillOpt flywheel metrics
      description: |
        Aggregate counts across all trajectory JSONL files. Used by
        evo-metaclaw.js weekly review and by the ARM dashboard.
      security:
        - WebhookSecret: []
      responses:
        "200":
          description: Flywheel metrics
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/TrajectoryMetrics"

  # ── Bots ──────────────────────────────────────────────────────────────────

  /bots:
    get:
      tags: [Bots]
      summary: List all Clow bots
      description: Returns metadata for all 6 Clow Telegram bots.
      responses:
        "200":
          description: Bot list
          content:
            application/json:
              schema:
                type: object
                properties:
                  bots:
                    type: array
                    items:
                      $ref: '#/components/schemas/Bot'
              example:
                bots:
                  - id: chaincypher
                    handle: "@chaincypher_bot"
                    domain: crypto-security
                    telegram_url: "https://t.me/chaincypher_bot"
                    active_users_30d: 1240
                    starts_total: 8921

  /bots/{botId}/stats:
    get:
      tags: [Bots]
      summary: Bot usage statistics
      parameters:
        - name: botId
          in: path
          required: true
          schema:
            type: string
            enum: [chaincypher, wandersync, gigclow, deeptechx, investclawd, productization]
        - name: period
          in: query
          schema:
            type: string
            enum: [7d, 30d, 90d]
            default: 30d
      responses:
        "200":
          description: Bot stats for the requested period
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/BotStats'

  /bots/{botId}/starts:
    get:
      tags: [Bots]
      summary: Bot /start events (time series)
      description: Daily /start event counts for the specified bot and period.
      parameters:
        - name: botId
          in: path
          required: true
          schema:
            type: string
        - name: from
          in: query
          schema:
            type: string
            format: date
            example: "2026-06-01"
        - name: to
          in: query
          schema:
            type: string
            format: date
            example: "2026-06-30"
        - name: breakdown
          in: query
          schema:
            type: string
            enum: [source, referrer, utm_campaign]
            description: Optional breakdown dimension
      responses:
        "200":
          description: Time series of /start events
          content:
            application/json:
              schema:
                type: object
                properties:
                  total:
                    type: integer
                  series:
                    type: array
                    items:
                      type: object
                      properties:
                        date:
                          type: string
                          format: date
                        count:
                          type: integer
                        breakdown:
                          type: object

  # ── ARM Metrics ───────────────────────────────────────────────────────────

  /metrics/arm:
    get:
      tags: [ARM Metrics]
      summary: Full ARM dashboard snapshot
      description: |
        Returns a real-time ARM snapshot across all three pillars.
        Powers the arm-dashboard.html live metrics.
      responses:
        "200":
          description: ARM snapshot
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ArmSnapshot'

  /metrics/acquire:
    get:
      tags: [ARM Metrics]
      summary: Acquire metrics
      parameters:
        - name: period
          in: query
          schema:
            type: string
            enum: [today, 7d, 30d]
            default: today
      responses:
        "200":
          description: Acquire metrics
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AcquireMetrics'

  /metrics/retain:
    get:
      tags: [ARM Metrics]
      summary: Retain / cohort metrics
      responses:
        "200":
          description: Retention metrics
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/RetainMetrics'

  /metrics/monetize:
    get:
      tags: [ARM Metrics]
      summary: Monetize / revenue metrics
      responses:
        "200":
          description: Revenue metrics
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/MonetizeMetrics'

  # ── Marketplace ───────────────────────────────────────────────────────────

  /marketplace/listings:
    get:
      tags: [Marketplace]
      summary: List marketplace agents
      parameters:
        - name: framework
          in: query
          schema:
            type: string
            enum: [picoclaw, nanoclaw, openclaw, entclaw, zeroclaw]
        - name: category
          in: query
          schema:
            type: string
        - name: page
          in: query
          schema:
            type: integer
            default: 1
        - name: per_page
          in: query
          schema:
            type: integer
            default: 20
            maximum: 100
      responses:
        "200":
          description: Paginated list of marketplace listings
          content:
            application/json:
              schema:
                type: object
                properties:
                  total:
                    type: integer
                  page:
                    type: integer
                  listings:
                    type: array
                    items:
                      $ref: '#/components/schemas/MarketplaceListing'

  /marketplace/listings/{listingId}:
    get:
      tags: [Marketplace]
      summary: Get a single listing
      parameters:
        - name: listingId
          in: path
          required: true
          schema:
            type: string
      responses:
        "200":
          description: Listing detail
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/MarketplaceListing'

  /marketplace/listings/{listingId}/revenue:
    get:
      tags: [Marketplace]
      summary: Revenue for your own listing (developer only)
      description: Returns monthly revenue breakdowns for listings you own. Requires the API key to be the listing owner.
      parameters:
        - name: listingId
          in: path
          required: true
          schema:
            type: string
        - name: months
          in: query
          schema:
            type: integer
            default: 3
      responses:
        "200":
          description: Revenue breakdown
          content:
            application/json:
              schema:
                type: object
                properties:
                  listing_id:
                    type: string
                  currency:
                    type: string
                    example: USD
                  months:
                    type: array
                    items:
                      type: object
                      properties:
                        month:
                          type: string
                          example: "2026-06"
                        gross_revenue:
                          type: number
                        developer_share:
                          type: number
                        ecosystem_share:
                          type: number
                        subscribers:
                          type: integer

  # ── Token ─────────────────────────────────────────────────────────────────

  /token/balance/{userId}:
    get:
      tags: [Token]
      summary: Get $Clow balance for a user
      parameters:
        - name: userId
          in: path
          required: true
          schema:
            type: string
      responses:
        "200":
          description: Token balance
          content:
            application/json:
              schema:
                type: object
                properties:
                  user_id:
                    type: string
                  clow_balance:
                    type: number
                  staked:
                    type: number
                  streak_days:
                    type: integer
                  streak_multiplier:
                    type: number
                  governance_score:
                    type: number

  /token/credit:
    post:
      tags: [Token]
      summary: Credit $Clow to a user (developer agents)
      description: |
        Marketplace agents use this endpoint to credit $Clow to users
        on meaningful interactions. Requires a marketplace developer API key.
        Rate limited per agent to prevent inflation.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [user_id, amount, action]
              properties:
                user_id:
                  type: string
                amount:
                  type: number
                  minimum: 0.1
                  maximum: 10
                  description: CLOW to credit (0.1–10 per interaction, rate-limited)
                action:
                  type: string
                  description: The interaction type (e.g., "analysis", "scan", "match")
                agent_id:
                  type: string
                  description: Your marketplace listing ID
      responses:
        "200":
          description: Credit applied
          content:
            application/json:
              schema:
                type: object
                properties:
                  credited:
                    type: number
                  new_balance:
                    type: number
                  transaction_id:
                    type: string
        "429":
          description: Rate limit exceeded for this agent/user pair

  # ── Webhooks ──────────────────────────────────────────────────────────────

  /webhooks:
    get:
      tags: [Webhooks]
      summary: List registered webhooks
      responses:
        "200":
          description: Webhook list
          content:
            application/json:
              schema:
                type: object
                properties:
                  webhooks:
                    type: array
                    items:
                      $ref: '#/components/schemas/Webhook'

    post:
      tags: [Webhooks]
      summary: Register a webhook
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [url, events]
              properties:
                url:
                  type: string
                  format: uri
                events:
                  type: array
                  items:
                    type: string
                    enum:
                      - bot.start
                      - bot.command
                      - subscription.created
                      - subscription.upgraded
                      - subscription.cancelled
                      - token.credit
                      - marketplace.listing.approved
                      - marketplace.revenue.paid
                secret:
                  type: string
                  description: Optional HMAC secret for signature verification
      responses:
        "201":
          description: Webhook created
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Webhook'

  /webhooks/{webhookId}:
    delete:
      tags: [Webhooks]
      summary: Delete a webhook
      parameters:
        - name: webhookId
          in: path
          required: true
          schema:
            type: string
      responses:
        "204":
          description: Deleted

# ── Components ───────────────────────────────────────────────────────────────

components:
  securitySchemes:
    BearerAuth:
      type: http
      scheme: bearer
      description: API key from your Sovereign or Enterprise dashboard. Format: `Authorization: Bearer clow_live_...`
    WebhookSecret:
      type: apiKey
      in: header
      name: X-Webhook-Secret
      description: Shared secret used by bots and internal cron jobs to authenticate webhook calls.

  schemas:

    Trajectory:
      type: object
      required: [user_hash, bot_name, session_id, steps]
      properties:
        user_hash:
          type: string
          description: SHA-256 of Telegram user_id with rotatable salt. Never send raw user_id.
          example: "sha256:9a3f2c1e..."
        bot_name:
          type: string
          enum: [chaincypher, wandersync, gigclow, deeptechx, investclawd, productization]
        session_id:
          type: string
          example: "sess_01k4n7x9"
        steps:
          type: array
          minItems: 1
          maxItems: 100
          items:
            type: object
            properties:
              role: { type: string, enum: [user, assistant, tool] }
              name: { type: string }
              content: { type: string }
              result_summary: { type: string }
        outcome:
          type: string
          enum: [success, error, abandoned, paid, referred, unknown]
          default: unknown
        metadata:
          type: object
          properties:
            tier: { type: string, enum: [free, pro, sovereign, enterprise] }
            utm_source: { type: string }
            utm_campaign: { type: string }
            prev_bot: { type: string }
            session_duration_ms: { type: integer }

    TrajectoryMetrics:
      type: object
      properties:
        total_trajectories: { type: integer }
        unique_users: { type: integer }
        by_bot:
          type: object
          additionalProperties: { type: integer }
        days_of_data: { type: integer }

    Bot:
      type: object
      properties:
        id:
          type: string
          example: chaincypher
        handle:
          type: string
          example: "@chaincypher_bot"
        domain:
          type: string
          example: crypto-security
        telegram_url:
          type: string
          format: uri
        active_users_30d:
          type: integer
        starts_total:
          type: integer

    BotStats:
      type: object
      properties:
        bot_id:
          type: string
        period:
          type: string
        starts:
          type: integer
        unique_users:
          type: integer
        commands_total:
          type: integer
        clow_credited:
          type: number
        cross_referral_starts:
          type: integer
        retention_d7:
          type: number
          description: Fraction (0.0–1.0)
        retention_d30:
          type: number

    ArmSnapshot:
      type: object
      properties:
        timestamp:
          type: string
          format: date-time
        acquire:
          $ref: '#/components/schemas/AcquireMetrics'
        retain:
          $ref: '#/components/schemas/RetainMetrics'
        monetize:
          $ref: '#/components/schemas/MonetizeMetrics'

    AcquireMetrics:
      type: object
      properties:
        new_bot_starts_today:
          type: integer
        new_bot_starts_7d:
          type: integer
        x_followers:
          type: integer
        x_followers_delta_7d:
          type: integer
        github_stars:
          type: integer
        github_stars_delta_7d:
          type: integer
        waitlist_signups_today:
          type: integer
        waitlist_signups_total:
          type: integer
        top_channel:
          type: string
          description: UTM source with most starts today

    RetainMetrics:
      type: object
      properties:
        d7_retention:
          type: number
          description: D7 retention rate across all bots (0.0–1.0)
        d30_retention:
          type: number
        active_streaks_7plus:
          type: integer
        active_streaks_30plus:
          type: integer
        d7_emails_sent_today:
          type: integer
        d7_email_click_rate:
          type: number

    MonetizeMetrics:
      type: object
      properties:
        mrr:
          type: number
          description: Monthly Recurring Revenue in USD
        mrr_delta_mom:
          type: number
          description: MRR change vs last month
        subscribers_total:
          type: integer
        subscribers_by_tier:
          type: object
          properties:
            free:
              type: integer
            pro:
              type: integer
            sovereign:
              type: integer
            enterprise:
              type: integer
        new_paid_today:
          type: integer
        churn_today:
          type: integer
        arpu:
          type: number
        marketplace_gmv_mtd:
          type: number

    MarketplaceListing:
      type: object
      properties:
        id:
          type: string
        name:
          type: string
        description:
          type: string
        author:
          type: string
        framework:
          type: string
          enum: [picoclaw, nanoclaw, openclaw, entclaw, zeroclaw]
        category:
          type: string
        open_source:
          type: boolean
        tiers:
          type: array
          items:
            type: object
            properties:
              name:
                type: string
              price_monthly:
                type: number
        rating:
          type: number
          minimum: 0
          maximum: 5
        review_count:
          type: integer
        installs_total:
          type: integer
        created_at:
          type: string
          format: date-time

    Webhook:
      type: object
      properties:
        id:
          type: string
        url:
          type: string
          format: uri
        events:
          type: array
          items:
            type: string
        created_at:
          type: string
          format: date-time
        last_delivery:
          type: string
          format: date-time
        status:
          type: string
          enum: [active, disabled, failing]
