Bo Kendell AI API

The AI API from Bo Kendell — 5 operation(s) for ai.

Operations 5

POST /api/v1/ai/chat/stream Stream an AI chat response #
POST /api/v1/ai/demo/homepage Homepage live-MCP demo (public, no auth) #
POST /api/v1/ai/demo/mcp-trace /mcp/try multi-tool trace demo (public, no auth) #
GET /api/v1/ai/tools List AI chat tools (public registry) #
POST /api/v1/ai/tools/send-email-to-bo Send an email to Bo from the AI chat tool #

Work with this as data

Every API here is available over the APIs.io API and to AI agents over MCP.

MCP server

One button, every client — Claude, Cursor, VS Code and the rest.

https://apis.io/mcp

Tools for apis

7 MCP tools reach this
  • find_apisBrowse and filter every API in the catalog.
  • get_api_artifactsOne API's artifacts, grouped by type.
  • get_openapiThe primary OpenAPI for this API.
  • find_similar_apisAPIs that look like this one.
  • apis_io_searchSTART HERE — APIs, providers and tags for one query, each with its total.
  • resolveTurn a domain, URL or GitHub org into the provider it belongs to.
  • find_cohortsEvery scored population of providers in the catalog.
All 92 tools →

Call it yourself

curl for this page
This API
curl "https://apis.io/api/v1/apis/bokendell-com:bokendell-com-ai-api"
All apis
curl "https://apis.io/api/v1/apis?limit=25"

Discovery needs no key. Ratings and market analysis are Pro.

Get an API key

Free tier, no form to fill in. Signing in shares your email address with us — we store it to create your key and to recognise you if you sign in with another provider. See our Privacy Policy and Terms.

A second provider on the same verified email joins the account you already have.

OpenAPI Specification

bokendell-com-ai-api-openapi.yml Raw ↑
openapi: 3.2.0
info:
  title: Portfolio AI API
  version: 1.0.0
  description: 'Portfolio oRPC + REST API

    ## Versioning and deprecation


    The version is in the URL path (`/api/v1/...`). A breaking change ships as a new path segment (`/api/v2`); anything additive lands in place.


    Nothing is removed silently. When an operation is scheduled for removal its responses start carrying a `Deprecation` header (draft-ietf-httpapi-deprecation-header) on the day the decision takes effect, and an RFC 8594 `Sunset` header once a removal date is committed — always at least 90 days out. Both are declared in `components.headers`, so an agent can watch for them mechanically rather than trusting this paragraph.


    Every 4xx and 5xx body is the `Error` schema: a machine-readable `code`, a human-readable `message`, and a `data` object repeating the code and HTTP status. Input-validation failures additionally carry raw Zod `issues`.'
servers:
- url: https://api.bokendell.com
security:
- cookieAuth: []
tags:
- name: AI
paths:
  /api/v1/ai/chat/stream:
    post:
      operationId: v1.ai.chat.stream
      summary: Stream an AI chat response
      description: 'Streams an AI-generated reply as an event stream for the given UI-message history, with optional model override, current-page context, and web search. Rate limited per client. Stateless: send the full message history on every turn.'
      tags:
      - AI
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                messages:
                  type: array
                  minItems: 1
                  items: {}
                threadId:
                  type: string
                id:
                  type: string
                clientId:
                  type: string
                model:
                  type: string
                currentPage:
                  type: string
                pages:
                  type: array
                  maxItems: 5
                  items:
                    type: string
                    maxLength: 200
                webSearch:
                  type: boolean
              required:
              - messages
      responses:
        '200':
          description: OK
          content:
            text/event-stream:
              schema:
                oneOf:
                - type: object
                  properties:
                    event:
                      const: message
                    data: {}
                    id:
                      type: string
                    retry:
                      type: number
                  required:
                  - event
                - type: object
                  properties:
                    event:
                      const: done
                    data: {}
                    id:
                      type: string
                    retry:
                      type: number
                  required:
                  - event
                - type: object
                  properties:
                    event:
                      const: error
                    data: {}
                    id:
                      type: string
                    retry:
                      type: number
                  required:
                  - event
        '401':
          description: UNAUTHORIZED — 401
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '403':
          description: FORBIDDEN — 403
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '404':
          description: NOT_FOUND — 404
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '409':
          description: CONFLICT — 409
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '422':
          description: INPUT_VALIDATION_FAILED — 422
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '429':
          description: TOO_MANY_REQUESTS — 429
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
  /api/v1/ai/demo/homepage:
    post:
      operationId: v1.ai.demo.homepage
      summary: Homepage live-MCP demo (public, no auth)
      description: Streams a portfolio-agent response for the homepage live-MCP demo widget, creating a throwaway session id per call. Rate limited per client; use `stream` for the full chat experience.
      tags:
      - AI
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                messages:
                  type: array
                  minItems: 1
                  items: {}
                model:
                  type: string
                pages:
                  type: array
                  maxItems: 5
                  items:
                    type: string
                    maxLength: 200
                webSearch:
                  type: boolean
              required:
              - messages
      responses:
        '200':
          description: OK
          content:
            text/event-stream:
              schema:
                oneOf:
                - type: object
                  properties:
                    event:
                      const: message
                    data: {}
                    id:
                      type: string
                    retry:
                      type: number
                  required:
                  - event
                - type: object
                  properties:
                    event:
                      const: done
                    data: {}
                    id:
                      type: string
                    retry:
                      type: number
                  required:
                  - event
                - type: object
                  properties:
                    event:
                      const: error
                    data: {}
                    id:
                      type: string
                    retry:
                      type: number
                  required:
                  - event
        '401':
          description: UNAUTHORIZED — 401
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '403':
          description: FORBIDDEN — 403
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '404':
          description: NOT_FOUND — 404
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '409':
          description: CONFLICT — 409
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '422':
          description: INPUT_VALIDATION_FAILED — 422
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '429':
          description: TOO_MANY_REQUESTS — 429
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
  /api/v1/ai/demo/mcp-trace:
    post:
      operationId: v1.ai.demo.mcpTrace
      summary: /mcp/try multi-tool trace demo (public, no auth)
      description: Streams a response from the guide agent behind the /mcp/try page, which demonstrates multi-tool MCP call traces. Same throwaway-session, rate-limited behavior as the homepage demo.
      tags:
      - AI
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                messages:
                  type: array
                  minItems: 1
                  items: {}
                model:
                  type: string
                pages:
                  type: array
                  maxItems: 5
                  items:
                    type: string
                    maxLength: 200
                webSearch:
                  type: boolean
              required:
              - messages
      responses:
        '200':
          description: OK
          content:
            text/event-stream:
              schema:
                oneOf:
                - type: object
                  properties:
                    event:
                      const: message
                    data: {}
                    id:
                      type: string
                    retry:
                      type: number
                  required:
                  - event
                - type: object
                  properties:
                    event:
                      const: done
                    data: {}
                    id:
                      type: string
                    retry:
                      type: number
                  required:
                  - event
                - type: object
                  properties:
                    event:
                      const: error
                    data: {}
                    id:
                      type: string
                    retry:
                      type: number
                  required:
                  - event
        '401':
          description: UNAUTHORIZED — 401
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '403':
          description: FORBIDDEN — 403
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '404':
          description: NOT_FOUND — 404
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '409':
          description: CONFLICT — 409
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '422':
          description: INPUT_VALIDATION_FAILED — 422
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '429':
          description: TOO_MANY_REQUESTS — 429
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
  /api/v1/ai/tools:
    get:
      operationId: v1.ai.tools.list
      summary: List AI chat tools (public registry)
      description: Returns the catalog of tools the portfolio AI agent can call — id, category, JSON-schema input definition, example input and output, and a suggested prompt per tool. Static metadata only; nothing is executed.
      tags:
      - AI
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: array
                items:
                  type: object
                  properties:
                    id:
                      type: string
                    category:
                      enum:
                      - read
                      - action
                      type: string
                    description:
                      type: string
                    inputSchema:
                      type: object
                      properties:
                        type:
                          const: object
                        properties:
                          type: object
                          propertyNames:
                            type: string
                          additionalProperties:
                            type: object
                            properties:
                              type:
                                type: string
                              description:
                                type: string
                              format:
                                type: string
                              enum:
                                type: array
                                items:
                                  type: string
                            required:
                            - type
                        required:
                          type: array
                          items:
                            type: string
                      required:
                      - type
                      - properties
                      - required
                    exampleInput: {}
                    exampleOutput: {}
                    suggestedPrompt:
                      type: string
                  required:
                  - id
                  - category
                  - description
                  - inputSchema
                  - suggestedPrompt
        '401':
          description: UNAUTHORIZED — 401
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '403':
          description: FORBIDDEN — 403
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '404':
          description: NOT_FOUND — 404
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '409':
          description: CONFLICT — 409
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '422':
          description: INPUT_VALIDATION_FAILED — 422
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '429':
          description: TOO_MANY_REQUESTS — 429
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
  /api/v1/ai/tools/send-email-to-bo:
    post:
      operationId: v1.ai.tools.sendEmailToBo
      summary: Send an email to Bo from the AI chat tool
      description: Actually delivers an email to the site owner with the given subject, body, and visitor details — a real action, not a demo. Rate limited per session and IP; the body should be written as the visitor, not the agent.
      tags:
      - AI
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                subject:
                  type: string
                  minLength: 1
                  maxLength: 140
                  description: The email subject line
                body:
                  type: string
                  minLength: 10
                  maxLength: 4000
                  description: The email body (plain text). Should be written as the visitor, not the agent.
                visitorName:
                  type: string
                  minLength: 1
                  maxLength: 120
                  description: The visitor's display name so Bo knows who the email is from.
                replyTo:
                  type: string
                  format: email
                  description: Optional reply-to email address. If the visitor shares one, include it so Bo can respond.
              required:
              - subject
              - body
              - visitorName
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  message:
                    type: string
                  emailId:
                    type: string
                required:
                - success
                - message
        '401':
          description: UNAUTHORIZED — 401
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '403':
          description: FORBIDDEN — 403
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '404':
          description: NOT_FOUND — 404
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '409':
          description: CONFLICT — 409
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '422':
          description: INPUT_VALIDATION_FAILED — 422
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '429':
          description: TOO_MANY_REQUESTS — 429
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
components:
  schemas:
    Error:
      type: object
      title: Error
      description: Every 4xx and 5xx response body. `code` is the machine-readable discriminator; `message` is human-readable and safe to surface. The HTTP status is on the response itself and repeated at `data.httpStatus`.
      required:
      - code
      - message
      - data
      properties:
        code:
          type: string
          description: Machine-readable error code, e.g. NOT_FOUND. Matches `data.code`.
          examples:
          - NOT_FOUND
          - BAD_REQUEST
          - UNAUTHORIZED
          - INTERNAL_SERVER_ERROR
        message:
          type: string
          description: Human-readable explanation.
        data:
          type: object
          description: Structured detail. Always carries `code` and `httpStatus`; typed errors declared by an operation spread their own fields in alongside.
          required:
          - code
          - httpStatus
          properties:
            code:
              type: string
              description: Repeats the top-level `code`.
            httpStatus:
              type: integer
              description: Repeats the response's HTTP status.
            errorCode:
              type: string
              description: The originating domain error code, when the failure came from a domain service.
            details:
              type:
              - object
              - 'null'
              description: Domain-supplied detail, when present.
            path:
              type: string
              description: Dotted procedure path that failed.
          additionalProperties: true
        issues:
          type: array
          description: Raw Zod issues. Present only on input-validation failures.
          items:
            type: object
            additionalProperties: true
  securitySchemes:
    cookieAuth:
      type: apiKey
      in: cookie
      name: better-auth.session_token
      description: Better Auth session cookie