Bo Kendell Activity API

The Activity API from Bo Kendell — 6 operation(s) for activity.

Operations 6

GET /api/v1/activity Get combined portfolio activity #
GET /api/v1/activity/github/contributions Get GitHub contributions #
GET /api/v1/activity/github/events Get GitHub events #
GET /api/v1/activity/leetcode Get LeetCode stats #
GET /api/v1/activity/latest-commit Get latest authored commit #
GET /api/v1/activity/weekly-summary Get cached weekly commit summary #

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-activity-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-activity-api-openapi.yml Raw ↑
openapi: 3.2.0
info:
  title: Portfolio Activity 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: Activity
paths:
  /api/v1/activity:
    get:
      operationId: v1.activity.getCombined
      summary: Get combined portfolio activity
      description: Returns the GitHub contribution calendar (viewer repos including private when the token allows, windowed from the most recently started September), recent GitHub events, and LeetCode GraphQL solve stats in one payload, plus the GitHub username. Prefer the narrower `/activity/*` operations when only one source is needed.
      tags:
      - Activity
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  github:
                    type: object
                    properties:
                      contributions:
                        type: object
                        properties:
                          totalContributions:
                            type: integer
                            minimum: 0
                            maximum: 9007199254740991
                          weeks:
                            type: array
                            items:
                              type: object
                              properties:
                                days:
                                  type: array
                                  items:
                                    type: object
                                    properties:
                                      date:
                                        type: string
                                      count:
                                        type: integer
                                        minimum: 0
                                        maximum: 9007199254740991
                                      level:
                                        type: integer
                                        minimum: 0
                                        maximum: 4
                                    required:
                                    - date
                                    - count
                                    - level
                              required:
                              - days
                          windowLabel:
                            type: string
                        required:
                        - totalContributions
                        - weeks
                      events:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: string
                            type:
                              type: string
                            repo:
                              type: object
                              properties:
                                name:
                                  type: string
                                url:
                                  type: string
                              required:
                              - name
                              - url
                            payload:
                              type: object
                              properties:
                                action:
                                  type: string
                                ref:
                                  type: string
                                commits:
                                  type: array
                                  items:
                                    type: object
                                    properties:
                                      sha:
                                        type: string
                                      message:
                                        type: string
                                    required:
                                    - sha
                                    - message
                            createdAt:
                              type: string
                              format: date-time
                          required:
                          - id
                          - type
                          - repo
                          - payload
                          - createdAt
                      username:
                        type: string
                    required:
                    - contributions
                    - events
                    - username
                  leetcode:
                    anyOf:
                    - type: object
                      properties:
                        totalSolved:
                          type: integer
                          minimum: 0
                          maximum: 9007199254740991
                        totalQuestions:
                          type: integer
                          minimum: 0
                          maximum: 9007199254740991
                        easySolved:
                          type: integer
                          minimum: 0
                          maximum: 9007199254740991
                        easyTotal:
                          type: integer
                          minimum: 0
                          maximum: 9007199254740991
                        mediumSolved:
                          type: integer
                          minimum: 0
                          maximum: 9007199254740991
                        mediumTotal:
                          type: integer
                          minimum: 0
                          maximum: 9007199254740991
                        hardSolved:
                          type: integer
                          minimum: 0
                          maximum: 9007199254740991
                        hardTotal:
                          type: integer
                          minimum: 0
                          maximum: 9007199254740991
                        ranking:
                          type: integer
                          minimum: 0
                          maximum: 9007199254740991
                        acceptanceRate:
                          type: number
                          minimum: 0
                          maximum: 100
                        contributionPoints:
                          type: integer
                          minimum: 0
                          maximum: 9007199254740991
                        streak:
                          type: integer
                          minimum: 0
                          maximum: 9007199254740991
                      required:
                      - totalSolved
                      - totalQuestions
                      - easySolved
                      - easyTotal
                      - mediumSolved
                      - mediumTotal
                      - hardSolved
                      - hardTotal
                      - ranking
                      - acceptanceRate
                      - contributionPoints
                      - streak
                    - type: 'null'
                required:
                - github
                - leetcode
        '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/activity/github/contributions:
    get:
      operationId: v1.activity.getGithubContributions
      summary: Get GitHub contributions
      description: Returns the GitHub contribution calendar as a total count plus per-week daily counts from the most recently started September through now. Uses the authenticated viewer so private contributions the token can see are included. The shape needed to render a contribution heatmap.
      tags:
      - Activity
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  totalContributions:
                    type: integer
                    minimum: 0
                    maximum: 9007199254740991
                  weeks:
                    type: array
                    items:
                      type: object
                      properties:
                        days:
                          type: array
                          items:
                            type: object
                            properties:
                              date:
                                type: string
                              count:
                                type: integer
                                minimum: 0
                                maximum: 9007199254740991
                              level:
                                type: integer
                                minimum: 0
                                maximum: 4
                            required:
                            - date
                            - count
                            - level
                      required:
                      - days
                  windowLabel:
                    type: string
                required:
                - totalContributions
                - weeks
        '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/activity/github/events:
    get:
      operationId: v1.activity.getGithubEvents
      summary: Get GitHub events
      description: Returns recent GitHub events (pushes, pull requests, etc.) with the repo name and URL for each — a short recent-activity feed, not full commit history. Authenticated requests include private events the token can see. For the single most recent commit use `/activity/latest-commit`.
      tags:
      - Activity
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: array
                items:
                  type: object
                  properties:
                    id:
                      type: string
                    type:
                      type: string
                    repo:
                      type: object
                      properties:
                        name:
                          type: string
                        url:
                          type: string
                      required:
                      - name
                      - url
                    payload:
                      type: object
                      properties:
                        action:
                          type: string
                        ref:
                          type: string
                        commits:
                          type: array
                          items:
                            type: object
                            properties:
                              sha:
                                type: string
                              message:
                                type: string
                            required:
                            - sha
                            - message
                    createdAt:
                      type: string
                      format: date-time
                  required:
                  - id
                  - type
                  - repo
                  - payload
                  - createdAt
        '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/activity/leetcode:
    get:
      operationId: v1.activity.getLeetcodeStats
      summary: Get LeetCode stats
      description: 'Returns LeetCode progress from LeetCode''s public GraphQL API: solved counts per difficulty, ranking, acceptance rate, and streak. Returns null when the profile is missing or the request fails.'
      tags:
      - Activity
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                anyOf:
                - type: object
                  properties:
                    totalSolved:
                      type: integer
                      minimum: 0
                      maximum: 9007199254740991
                    totalQuestions:
                      type: integer
                      minimum: 0
                      maximum: 9007199254740991
                    easySolved:
                      type: integer
                      minimum: 0
                      maximum: 9007199254740991
                    easyTotal:
                      type: integer
                      minimum: 0
                      maximum: 9007199254740991
                    mediumSolved:
                      type: integer
                      minimum: 0
                      maximum: 9007199254740991
                    mediumTotal:
                      type: integer
                      minimum: 0
                      maximum: 9007199254740991
                    hardSolved:
                      type: integer
                      minimum: 0
                      maximum: 9007199254740991
                    hardTotal:
                      type: integer
                      minimum: 0
                      maximum: 9007199254740991
                    ranking:
                      type: integer
                      minimum: 0
                      maximum: 9007199254740991
                    acceptanceRate:
                      type: number
                      minimum: 0
                      maximum: 100
                    contributionPoints:
                      type: integer
                      minimum: 0
                      maximum: 9007199254740991
                    streak:
                      type: integer
                      minimum: 0
                      maximum: 9007199254740991
                  required:
                  - totalSolved
                  - totalQuestions
                  - easySolved
                  - easyTotal
                  - mediumSolved
                  - mediumTotal
                  - hardSolved
                  - hardTotal
                  - ranking
                  - acceptanceRate
                  - contributionPoints
                  - streak
                - type: 'null'
        '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/activity/latest-commit:
    get:
      operationId: v1.activity.getLatestCommit
      summary: Get latest authored commit
      description: Returns the most recent commit authored by the configured GitHub user across repos the API token can see (personal, org, and private when the token has repo scope), with sha, message, timestamp, and repo links. Returns null when there is no recent commit or GitHub is unavailable — a null result means no data is available, not a failure.
      tags:
      - Activity
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                anyOf:
                - type: object
                  properties:
                    sha:
                      type: string
                    fullSha:
                      type: string
                    message:
                      type: string
                    url:
                      type: string
                      format: uri
                    committedAt:
                      type: string
                    repoName:
                      type: string
                    repoUrl:
                      type: string
                      format: uri
                  required:
                  - sha
                  - fullSha
                  - message
                  - url
                  - committedAt
                  - repoName
                  - repoUrl
                - type: 'null'
        '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/activity/weekly-summary:
    get:
      operationId: v1.activity.getWeeklySummary
      summary: Get cached weekly commit summary
      description: Returns an AI-written markdown summary of the past week's commits, regenerated by a Sunday cron and served from cache with `ageMs` and `isStale` metadata. Returns null when the cache is empty or older than 14 days.
      tags:
      - Activity
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                anyOf:
                - type: object
                  properties:
                    markdown:
                      type: string
                    generatedAt:
                      type: string
                    commitCount:
                      type: integer
                      minimum: 0
                      maximum: 9007199254740991
                    sources:
                      type: array
                      items:
                        type: object
                        properties:
                          sha:
                            type: string
                          message:
                            type: string
                          url:
                            type: string
                            format: uri
                        required:
                        - sha
                        - message
                        - url
                    windowStart:
                      type: string
                    windowEnd:
                      type: string
                    ageMs:
                      type: integer
                      minimum: 0
                      maximum: 9007199254740991
                    isStale:
                      type: boolean
                  required:
                  - markdown
                  - generatedAt
                  - commitCount
                  - sources
                  - windowStart
                  - windowEnd
                  - ageMs
                  - isStale
                - type: 'null'
        '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