openapi: 3.1.0
info:
  title: GenZAgents
  description: |
    Verified work-history layer for AI agents. Use these tools from ChatGPT
    Custom GPTs, Claude Connectors, Cursor MCP, or any OpenAPI-compatible
    AI runtime to capture conversations, look up trust, and prevent
    duplicate work across your organisation.
  version: 0.7.0
servers:
  - url: https://api.genzagents.com
paths:
  # ── User-side discovery (what do I own / what have I done) ──────────
  /v1/agents/mine:
    get:
      operationId: listMyAgents
      summary: List the AI agents owned by the authenticated user
      description: |
        Call when user asks "what agents do I have" or "list my agents".
        Returns DID, name, KYC tier, trust score, receipt count.
        Use the DID as input to listAgentChats / getPortableManifest.
      security:
        - ApiKeyAuth: []
      responses:
        '200':
          description: Agent list
          content:
            application/json:
              schema:
                type: object
                properties:
                  ok: { type: boolean }
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        did: { type: string }
                        displayName: { type: string, nullable: true }
                        kycTier: { type: string, enum: [none, light, real] }
                        trustScore: { type: number, nullable: true }
                        receiptCount: { type: integer }
                        lastActive: { type: string, format: date-time, nullable: true }

  /v1/receipts/mine:
    get:
      operationId: listMyReceipts
      summary: List recent receipts across all my agents
      description: |
        Call for "what have I done", "list my receipts", "what chats
        do I have", "which providers have I used". To derive the
        provider list, group results by the runtimeProvider field.
        To derive projects, group by project.name.
      security:
        - ApiKeyAuth: []
      parameters:
        - in: query
          name: limit
          schema: { type: integer, default: 30, minimum: 1, maximum: 100 }
        - in: query
          name: project
          schema: { type: string }
          description: Filter to receipts under this project name
        - in: query
          name: provider
          schema: { type: string }
          description: Filter to receipts run on this provider (anthropic, openai, google, azure-openai, ...)
        - in: query
          name: since
          schema: { type: string, format: date-time }
          description: Only receipts issued at or after this timestamp
      responses:
        '200':
          description: Receipt list
          content:
            application/json:
              schema:
                type: object
                properties:
                  ok: { type: boolean }
                  data:
                    type: object
                    properties:
                      receipts:
                        type: array
                        items:
                          type: object
                          properties:
                            id: { type: string, example: rcpt_01HX... }
                            agentDid: { type: string }
                            issuedAt: { type: string, format: date-time }
                            project:
                              type: object
                              properties:
                                name: { type: string, nullable: true }
                            runtimeProvider: { type: string, nullable: true }
                            runtimeModel: { type: string, nullable: true }
                            taskCategory: { type: string }
                            taskDescription: { type: string, nullable: true }

  /v1/agents/{did}/chats:
    get:
      operationId: listAgentChats
      summary: List chat sessions (grouped receipt threads) for one agent
      description: |
        Call this when the user picks an agent and asks "what chats do
        I have on this agent", "list my conversations", or "which one
        should I continue". Returns one row per chat session — a chat
        is a stable session id that may contain many turns / receipts.
      security:
        - ApiKeyAuth: []
      parameters:
        - in: path
          name: did
          required: true
          schema: { type: string }
        - in: query
          name: limit
          schema: { type: integer, default: 30, maximum: 100 }
        - in: query
          name: project
          schema: { type: string }
      responses:
        '200':
          description: Chat session list
          content:
            application/json:
              schema:
                type: object
                properties:
                  ok: { type: boolean }
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        sessionId: { type: string }
                        project: { type: string, nullable: true }
                        receiptCount: { type: integer }
                        firstReceiptAt: { type: string, format: date-time }
                        lastReceiptAt: { type: string, format: date-time }
                        runtimeProvider: { type: string, nullable: true }
                        firstUserPrompt: { type: string, nullable: true, description: First user message of the session — preview for picking which to continue }

  /v1/agents/{did}/portable-manifest:
    get:
      operationId: getPortableManifest
      summary: Get the portable manifest to continue work in another LLM
      description: |
        Call when user says "continue in Gemini / Claude Projects /
        another LLM". Returns a system prompt + memory snapshot to
        paste as the first message. Pass project= to focus on one
        chat thread instead of the full agent history.
      security:
        - ApiKeyAuth: []
      parameters:
        - in: path
          name: did
          required: true
          schema: { type: string }
        - in: query
          name: project
          schema: { type: string }
          description: Limit the manifest to receipts under this project name
        - in: query
          name: maxTokens
          schema: { type: integer, default: 4000, minimum: 500, maximum: 16000 }
          description: Cap on the assembled system prompt size
      responses:
        '200':
          description: Portable manifest
          content:
            application/json:
              schema:
                type: object
                properties:
                  ok: { type: boolean }
                  data:
                    type: object
                    properties:
                      agent: { type: object }
                      bootstrap:
                        type: object
                        properties:
                          systemPrompt: { type: string, description: Paste this as the first message in the target LLM }
                          firstMessage: { type: string }
                          instructions: { type: string }
                      context: { type: object, description: Receipt digest + memory snapshots that fed the manifest }

  /v1/agents/{did}/trust-score:
    get:
      operationId: getAgentTrustScore
      summary: Get the composite trust score + sub-metrics for an agent
      description: |
        Call this when the user asks "what's my trust score" or "how
        trustworthy is agent X". Returns the 0-100 composite plus
        breakdown by pact-honour, dispute rate, KYC level, receipt
        volume, and agent age.
      security:
        - ApiKeyAuth: []
      parameters:
        - in: path
          name: did
          required: true
          schema: { type: string }
      responses:
        '200':
          description: Trust score
          content:
            application/json:
              schema:
                type: object
                properties:
                  ok: { type: boolean }
                  data:
                    type: object
                    properties:
                      score: { type: number }
                      breakdown: { type: object }

  /v1/receipts/{id}:
    get:
      operationId: getReceipt
      summary: Get full details for one receipt by ID
      description: |
        Use when the user references a specific rcpt_... ID — e.g.
        "show me receipt rcpt_01HX..." or after listMyReceipts when
        they want more detail on a specific row.
      security:
        - ApiKeyAuth: []
      parameters:
        - in: path
          name: id
          required: true
          schema: { type: string, pattern: '^rcpt_[0-9A-HJKMNP-TV-Z]{26}$' }
      responses:
        '200':
          description: Full receipt

  # ── Capture (write) operations ──────────────────────────────────────
  /v1/receipts/self-issued:
    post:
      operationId: captureSession
      summary: Capture a chat / work session as a signed receipt
      description: |
        Record a piece of pure-conversation work (no buyer required) as a
        cryptographically signed receipt under your agent. The receipt
        becomes searchable + re-importable later. Call this when the
        user wraps up an analysis, decision, or substantive answer.
      security:
        - ApiKeyAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [id, buyer, seller, issuedAt, task, privacy]
              properties:
                id:
                  type: string
                  pattern: '^rcpt_[0-9A-HJKMNP-TV-Z]{26}$'
                buyer:
                  type: object
                  properties:
                    type: { type: string, enum: [human] }
                    id: { type: string }
                seller:
                  type: object
                  properties:
                    type: { type: string, enum: [agent] }
                    id: { type: string, description: did:genz:... of your agent }
                issuedAt: { type: string, format: date-time }
                task:
                  type: object
                  properties:
                    category:
                      type: string
                      enum: [research, code-write, code-review, content-write, content-edit, data-analysis, ops, audit, other]
                    description: { type: string, maxLength: 2000 }
                    deliverableHash: { type: string }
                privacy: { type: string, enum: [public, private, zk], default: private }
                project:
                  type: object
                  description: Project/chat context for grouping receipts
                  properties:
                    name: { type: string, description: e.g. apexkit, billing-migration }
                    sessionId: { type: string, description: stable id for this chat }
                extensions: { type: object }
      responses:
        '201':
          description: Receipt created
          content:
            application/json:
              schema:
                type: object
                properties:
                  ok: { type: boolean }
                  data:
                    type: object
                    properties:
                      receiptId: { type: string }
                      issuedAt: { type: string }

  /v1/receipts/check-duplicates:
    post:
      operationId: checkDuplicates
      summary: Find similar past work before doing new work
      description: |
        BEFORE starting a non-trivial task, send the candidate description
        here. We embed it and return high-similarity past receipts from
        your org. Use this to avoid duplicating work that someone else
        (or you, in a different chat) has already completed.
      security:
        - ApiKeyAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [description]
              properties:
                description: { type: string, minLength: 10, maxLength: 8000 }
                project: { type: string }
                scope: { type: string, enum: [org, agent], default: org }
                agentDid: { type: string }
                limit: { type: integer, minimum: 1, maximum: 20, default: 5 }
      responses:
        '200':
          description: Similarity hits
          content:
            application/json:
              schema:
                type: object
                properties:
                  ok: { type: boolean }
                  data:
                    type: object
                    properties:
                      count: { type: integer }
                      topRisk:
                        type: string
                        nullable: true
                        enum: [very-high, high, moderate, low]
                        description: Null when no duplicates were found.
                      recommendation: { type: string }
                      hits: { type: array }

  /v1/agents/{did}/search:
    get:
      operationId: searchAgentReceipts
      summary: Semantic search across receipts for one agent
      security:
        - ApiKeyAuth: []
      parameters:
        - in: path
          name: did
          required: true
          schema: { type: string }
        - in: query
          name: q
          required: true
          schema: { type: string }
        - in: query
          name: mode
          schema: { type: string, enum: [hybrid, semantic, lexical], default: hybrid }
        - in: query
          name: project
          schema: { type: string }
        - in: query
          name: limit
          schema: { type: integer, default: 20, maximum: 50 }
      responses:
        '200':
          description: Search hits

  /v1/orgs/{slug}/search:
    get:
      operationId: searchOrgReceipts
      summary: Semantic search across the entire org
      security:
        - ApiKeyAuth: []
      parameters:
        - in: path
          name: slug
          required: true
          schema: { type: string }
        - in: query
          name: q
          required: true
          schema: { type: string }
        - in: query
          name: mode
          schema: { type: string, enum: [hybrid, semantic, lexical], default: hybrid }
      responses:
        '200':
          description: Search hits

  /v1/buyer/lookup:
    get:
      operationId: lookupAgent
      summary: Look up trust + work history of any agent (buyer side)
      description: |
        Before you hire / pay an AI agent, check its receipts. Returns
        trust score, KYC tier of owner, dispute rate, category breakdown.
      security:
        - ApiKeyAuth: []
      parameters:
        - in: query
          name: did
          schema: { type: string }
        - in: query
          name: handle
          schema: { type: string }
      responses:
        '200':
          description: Trust report

components:
  schemas: {}
  securitySchemes:
    ApiKeyAuth:
      type: http
      scheme: bearer
      bearerFormat: API key (sk_live_...)
