Bike4Mind API

Programmatic access to the Bike4Mind API

Operations 88

POST /api/chat Send a chat message #
POST /api/v1/agent-executions Start an agent execution #
GET /api/v1/agent-executions/{id} Get an agent execution #
GET /api/sessions/{id} Get a session #
PUT /api/sessions/{id} Update a session #
DELETE /api/sessions/{id} Delete a session #
POST /api/v1/sessions/{id}/clone Clone a session #
POST /api/ai/v1/tools Execute a server-side tool #
POST /api/ai/v1/completions Create a chat completion #
POST /api/ai/tts Synthesize speech from text #
POST /api/ai/music Generate background music #
POST /api/ai/sound-effects Generate a sound effect #
GET /api/v1/me Get the authenticated caller #
GET /api/v1/credits Get the caller's credit balance #
GET /api/v1/models List models #
POST /api/v1/image-generations Generate an image #
POST /api/v1/image-edits Edit an image #
POST /api/v1/files Start a file upload #
GET /api/v1/files List files #
GET /api/v1/files/{id} Get a file #
PATCH /api/v1/files/{id} Update a file #
DELETE /api/v1/files/{id} Delete a file #
POST /api/v1/embeddings Create embeddings #
POST /api/v1/text-refinements Refine text #
POST /api/v1/decisions Answer typed questions with probabilities #
GET /api/v1/decision-models List the decision models you can use #
GET /api/v1/quests/{id} Get a quest #
GET /api/v1/quests/{id}/files List quest files #
POST /api/v1/sessions Create a session #
GET /api/v1/sessions List sessions #
GET /api/v1/data-lakes List data lakes #
GET /api/v1/data-lakes/{id} Get a data lake #
GET /api/v1/data-lakes/{id}/files/{file_id} Get a data lake file #
POST /api/v1/data-lakes/{id}/files/{file_id} Add a file to a data lake #
DELETE /api/v1/data-lakes/{id}/files/{file_id} Remove a file from a data lake #
POST /api/v1/data-lakes/{id}/search Search a data lake #
POST /api/v1/video-generations/{id}/cancel Cancel a video generation #
POST /api/v1/video-generations Start a video generation #
GET /api/v1/video-generations List your video generations #
GET /api/v1/video-generations/{id} Get a video generation #
GET /api/v1/video-models List the video models you can use #
POST /api/v1/music-generations/{id}/cancel Cancel a music generation #
POST /api/v1/music-generations Start a music generation #
GET /api/v1/music-generations List your music generations #
GET /api/v1/music-generations/{id} Get a music generation #
GET /api/v1/music-models List the music models you can use #
GET /api/v1/voice/voices List voices #
POST /api/v1/voice/sessions Start a voice session #
POST /api/v1/voice/sessions/{id}/end End a voice session #
GET /api/v1/whats-new List release notes #
GET /api/v1/whats-new/media/{id}/{asset} Get release note media #
GET /api/v1/projects List projects #
POST /api/v1/projects Create a project #
GET /api/v1/projects/{id} Get a project #
PATCH /api/v1/projects/{id} Update a project #
DELETE /api/v1/projects/{id} Delete a project #
GET /api/v1/artifacts List artifacts #
POST /api/v1/artifacts Create an artifact #
GET /api/v1/artifacts/{id} Get an artifact #
PATCH /api/v1/artifacts/{id} Update an artifact #
DELETE /api/v1/artifacts/{id} Delete an artifact #
GET /api/v1/artifacts/{id}/versions List artifact versions #
GET /api/v1/artifacts/{id}/versions/{version} Get an artifact version #
POST /api/v1/transcriptions/uploads Start a transcription upload #
POST /api/v1/transcriptions Transcribe audio #
GET /api/v1/agents List agents #
POST /api/v1/agents Create an agent #
GET /api/v1/agents/{id} Get an agent #
PATCH /api/v1/agents/{id} Update an agent #
DELETE /api/v1/agents/{id} Delete an agent #
POST /api/v1/agents/{id}/generate-avatar Generate an agent avatar #
POST /api/v1/agents/{id}/generate-description Generate an agent description #
POST /api/v1/agents/{id}/generate-system-prompt Generate an agent system prompt #
POST /api/v1/agents/{id}/enhance-field Enhance an agent personality field #
GET /api/v1/skills/market/claude-marketplace.json Get an organization's Claude Code plugin marketplace #
GET /api/v1/skills/market/{id}/claude-plugin.zip Download a Skill Market listing as a Claude Code plugin #
GET /api/v1/skills/market/bundles/{id}/claude-plugin.zip Download a Skill Market bundle as a Claude Code plugin #
GET /api/v1/skills/market/listings Browse Skill Market listings #
POST /api/v1/skills/market/listings Publish a skill to the Skill Market #
GET /api/v1/skills/market/listings/{id} Get a Skill Market listing #
DELETE /api/v1/skills/market/listings/{id} Withdraw a Skill Market listing #
GET /api/v1/skills/market/listings/mine List your Skill Market listings #
POST /api/v1/skills/market/listings/{id}/versions Submit a new version of a Skill Market listing #
POST /api/v1/skills/market/listings/{id}/import Import a Skill Market listing #
POST /api/v1/skills/market/versions/{vid}/rescan Rescan a Skill Market version #
GET /api/v1/skills/market/review-queue List Skill Market versions awaiting review #
POST /api/v1/skills/market/versions/{vid}/review Approve or reject a held Skill Market version #
POST /api/v1/slack/messages Post a Slack message #

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/bike4mind-com:bike4mind-api"
All apis
curl "https://apis.io/api/v1/apis?limit=25"

Calls without X-API-Key need no key. Calls with it need a paid plan — get a key.

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

bike4mind-com-openapi.json Raw ↑
{
  "openapi": "3.1.0",
  "info": {
    "title": "Bike4Mind API",
    "version": "21.0.0",
    "description": "Programmatic access to the Bike4Mind API. Schemas are generated from the same Zod definitions that validate requests at runtime, so this spec cannot drift from the implementation - with one documented exception: a `pollResult` schema (see the `x-poll-result` extension) describes a handoff response's outcome on a plain, non-contract endpoint, so it is hand-maintained against that handler rather than runtime-validated, and can drift if the handler changes without a matching schema update.\n\n## Getting started\n1. Create a key in the web app under **Profile > API Keys** (pick a scope preset).\n2. Make a first call: `GET /api/v1/me` with `Authorization: Bearer b4m_live_<key>`. It needs only the `me:read` scope, spends no credits, and returns your identity, plan tier and credit balance.\n3. Read the rest of this page for the behaviour shared across endpoints: rate limits, credits, errors and async jobs.\n\nEndpoints are grouped by tag: **AI** (chat, completions, embeddings, agent runs, tools, quest polling), **Images**, **Audio**, **Videos**, **Music**, **Transcriptions**, **Sessions**, **Artifacts**, **Files**, **Projects**, **Agents**, **Data Lakes**, **Skills** and **Account**.\n\n## Authentication\nSend an API key as `Authorization: Bearer b4m_live_<key>` (canonical), `x-api-key: b4m_live_<key>` (legacy), or `Authorization: ApiKey b4m_live_<key>`. A JWT access token is also accepted in the `Authorization: Bearer` header.\n\n## Scopes\nAPI keys carry `resource:action` scopes. The documented scopes are:\n- `notebooks:read`\n- `notebooks:write`\n- `files:read`\n- `files:write`\n- `ai:generate`\n- `ai:decide`\n- `ai:chat`\n- `projects:read`\n- `projects:write`\n- `agents:read`\n- `agents:write`\n- `me:read`\n- `marketing-reports:read`\n- `marketing-reports:write`\n- `hearth:read`\n- `hearth:write`\n- `datalake:read`\n- `datalake:write`\n- `datalake:share`\n- `datalake:query`\n- `overwatch:read`\n- `skills:read`\n- `skills:write`\n- `skills:review`\n- `bob:read`\n- `bob:run`\n- `slack:post`\n\nPer-operation required scopes are published via the `x-required-scopes` extension. Semantics are OR: a key needs ANY ONE of an operation's listed scopes, not all of them. Operations with no `x-required-scopes` enforce no scope (e.g. the JWT-only tools endpoint).\n\n## Rate limits\nEach API key has a per-minute and a per-day request ceiling, by default 60 requests/minute and 1000 requests/day (a key can be minted with its own ceilings). Responses from rate-limited operations carry the current state of both windows (the streaming completions endpoint sends them only on an API-key `429`):\n- `X-RateLimit-Limit-Minute`\n- `X-RateLimit-Remaining-Minute`\n- `X-RateLimit-Reset-Minute`\n- `X-RateLimit-Limit-Day`\n- `X-RateLimit-Remaining-Day`\n- `X-RateLimit-Reset-Day`\n\nReset values are Unix epoch seconds. Exceeding a ceiling returns `429` with a `Retry-After` header; wait that long before retrying. This includes `POST /api/ai/v1/completions`, which rate-limits before it opens its event stream. `GET /api/v1/me`, `GET /api/v1/credits`, `GET /api/v1/models`, `GET /api/v1/video-models`, `GET /api/v1/music-models`, the `GET` list endpoints for `/api/v1/sessions`, `/api/v1/video-generations` and `/api/v1/music-generations`, and the poll endpoints listed under Async jobs are exempt from the per-day ceiling: a poll consumes no daily slot, and only the per-minute limit applies. A request refused at the route scope gate (`403`) or for a bad key (`401`) never reaches the limiter and carries no rate-limit headers.\n\n## Credits\nGeneration endpoints spend credits from the balance shown at `credits.balance` on `GET /api/v1/me` (the caller's personal ledger). A key without `me:read` reads the same number from `GET /api/v1/credits`, which accepts `ai:chat`, `ai:generate` and `ai:decide` too. A synchronous call that cannot be paid for fails with `422` and `errorCode: \"insufficient_credits\"`. On a queued job the same code arrives on the polled result instead (see Async jobs), so check both places.\n\n## Errors\nError bodies use one envelope, the `ErrorResponse` schema: `{ \"error\": string, \"request_id\"?: string }`, plus an `errorCode` on failures a client is expected to branch on (`insufficient_credits`, `spend_cap_exceeded`, `provider_not_configured`, ...). A deprecated `name` field may also appear until its sunset date; do not rely on it. Branch on the HTTP status and `errorCode`, never on the `error` prose. A few operations declare a bespoke error shape for a specific status (e.g. the `500` of the tools endpoint and the `413` of text-to-speech); each operation lists the statuses it can return and the body for each.\n\nThe shared statuses: a malformed JSON body is `400`, a body that fails schema validation is `422`, a missing or invalid credential is `401`, a valid key without the required scope is `403`, an unknown resource is `404` and an exceeded rate limit is `429`. A `401` carrying `errorCode: \"provider_rejected\"` means the upstream provider refused the provider key the request used - the platform key by default, or your own stored provider key when you configured one - so your API key itself was accepted.\n\n## Async jobs\nWork that is not provably fast is queued and polled rather than held open:\n- **Chat** (`POST /api/chat`) and **image generation/editing** (`POST /api/v1/image-generations`, `POST /api/v1/image-edits`) return a quest. Poll `GET /api/v1/quests/{id}` until `status` is `done` or `stopped`; chat text arrives in `reply`, generated images in `images`, edited images in `files[].url`. Check for failure before reading results: a job that ends `done` with `type: \"error\"` failed (the reason is in `reply`), and a job that ends `stopped` also failed even when `type` is not `\"error\"` (its `reply` carries an explanation, not an answer). The outcome schema of each of these quest handoffs is linked from its response via the `x-poll-result` extension. Chat also accepts `wait: true` to block until the reply is ready.\n- **Agent runs** (`POST /api/v1/agent-executions`) return `202`. Poll `GET /api/v1/agent-executions/{id}` until `status` is `completed`, `failed` or `aborted`.\n- **Video generation** (`POST /api/v1/video-generations`) returns `202`. Poll `GET /api/v1/video-generations/{id}` until `state` is `succeeded`, `failed`, `blocked` or `cancelled`.\n- **Music generation** (`POST /api/v1/music-generations`) returns `202`. Poll `GET /api/v1/music-generations/{id}` until `state` is `succeeded`, `failed`, `blocked` or `cancelled`.\n- **File uploads** (`POST /api/v1/files`) return a presigned `upload_url`; after the `PUT`, poll `GET /api/v1/files/{id}` until `moderation_status` is `clean` before passing the id elsewhere.\n- **Audio** endpoints are synchronous and return the result directly.\n- **Transcriptions** (`POST /api/v1/transcriptions`) are synchronous too: after the upload, one call returns the text. Long audio can outlast the request timeout and fail with a `504`; see that endpoint for the limit.\n\nPoll with a backoff of a few seconds: each poll counts against the per-minute limit.\n\n## Versioning\nNew endpoints live under `/api/v1`. Published endpoints are forward-only: a live URL is never renamed or removed, and a breaking change ships as a new path while the old one keeps working. Nothing published is removed silently - a deprecated field or endpoint is marked `deprecated` in this spec with a sunset date in its description, and keeps working until that date.\n\n## CORS\nThe spec (`/api/v1/openapi.json`) is served publicly with permissive CORS. The API endpoints themselves are called server-to-server with a secret key and are not intended for browser CORS use.\n\n## Correlation\nEvery response carries an `X-Request-ID` header (echoed as `request_id`/`requestId` in bodies and events) for log correlation.",
    "contact": {
      "name": "Bike4Mind",
      "url": "https://your-deployment.example.com"
    },
    "license": {
      "name": "Proprietary"
    }
  },
  "servers": [
    {
      "url": "https://your-deployment.example.com",
      "description": "Production"
    },
    {
      "url": "https://staging.your-deployment.example.com",
      "description": "Staging"
    },
    {
      "url": "http://localhost:3000",
      "description": "Local dev"
    }
  ],
  "components": {
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "description": "Canonical auth. Send `Authorization: Bearer b4m_live_<key>`. A JWT access token is also accepted in this header; a token beginning with `b4m_` is treated as an API key, anything else as a JWT."
      },
      "apiKeyAuth": {
        "type": "apiKey",
        "in": "header",
        "name": "x-api-key",
        "description": "Legacy auth. Send `x-api-key: b4m_live_<key>`. Equivalent to `bearerAuth` for API keys."
      },
      "jwtAuth": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "JWT",
        "description": "JWT access token only. Send `Authorization: Bearer <access_token>`. API keys are NOT accepted here."
      }
    },
    "schemas": {
      "ErrorResponse": {
        "type": "object",
        "properties": {
          "error": {
            "type": "string",
            "description": "Human-readable error message."
          },
          "request_id": {
            "type": "string",
            "description": "Correlation id, mirrors the X-Request-ID header."
          },
          "name": {
            "type": "string",
            "deprecated": true,
            "description": "Deprecated, sunset 2026-12-01. The `name` of whatever the server threw - usually one of our own error classes (`NotFoundError`, `UnprocessableEntityError`, ...), but on an unhandled 500 it can be a library or driver class name instead. Unstable by nature: these are internal names we rename at will, and the set is open. Documented only so the wire and this spec agree for the deprecation window; it is removed on the sunset date. Branch on the HTTP status, not on this."
          }
        },
        "required": [
          "error"
        ],
        "example": {
          "error": "Missing or invalid toolName",
          "request_id": "abc-123"
        }
      },
      "sendChatMessage200PollResult": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "pending",
              "stopped",
              "running",
              "done"
            ]
          },
          "type": {
            "type": "string",
            "enum": [
              "message",
              "oob",
              "error",
              "system",
              "voice_transcript"
            ]
          },
          "errorCode": {
            "type": "string",
            "enum": [
              "insufficient_credits",
              "spend_cap_exceeded"
            ]
          },
          "reply": {
            "type": [
              "string",
              "null"
            ]
          },
          "replies": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "fallbackInfo": {
            "type": "object",
            "properties": {
              "primaryModel": {
                "type": "string"
              },
              "primaryModelName": {
                "type": "string"
              },
              "fallbackModel": {
                "type": "string"
              },
              "fallbackModelName": {
                "type": "string"
              },
              "reason": {
                "type": "string"
              }
            },
            "required": [
              "primaryModel",
              "primaryModelName",
              "fallbackModel",
              "fallbackModelName"
            ]
          }
        },
        "required": [
          "id"
        ],
        "description": "Outcome fields of the quest polled at `GET /api/v1/quests/{id}` after this ACK. A finished turn that failed is `status: \"done\"` with `type: \"error\"` and the failure text in `reply`, so a caller reading `reply` alone cannot tell a failure from an answer - check `type` first, and also treat a terminal `status: \"stopped\"` (a missing session, a user-cancelled turn) as failure even though it never sets `type`. `errorCode` is an optional refinement of `type: \"error\"`, present only for a classified billing failure; credit exhaustion arrives here as `insufficient_credits`, the same vocabulary the synchronous 422s on `/api/ai/music`, `/api/ai/sound-effects` and `/api/ai/tts` use. `QUEST_ERROR_CODES` publishes a second member, `spend_cap_exceeded`, but no current throw site on this endpoint raises it as a quest errorCode: its only one, the embed chat route's pre-flight 422, fires outside the process try/catch that would classify it onto the quest. Most `type: \"error\"` turns - an abort, a provider timeout or overload - have NO `errorCode`; its absence does not mean success, only that the failure is unclassified. A recovered stuck quest that still has renderable content is not a failure at all: it keeps `type: \"message\"` even though it did not finish, so a caller gets the content rather than an error. `fallbackInfo` is present only when the requested model failed and another model produced the reply: `fallbackModel` answered, `primaryModel` is what was asked for, and `reason` is the error from the first failed attempt on the requested model. The poll body carries further fields not modelled here, including `images`, `files`, `toolPayloads`, `promptMeta`, and the attachment report (`attachmentNotices`/`attachmentDelivery`) - only the outcome subset is modelled here.",
        "example": {
          "id": "664f1c2b9a1e4d0012ab34cd",
          "status": "done",
          "type": "error",
          "errorCode": "insufficient_credits",
          "reply": "You're out of credits. This request needs about 12 credits, but only 3 are available."
        }
      },
      "generateImage200PollResult": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "pending",
              "stopped",
              "running",
              "done"
            ]
          },
          "type": {
            "type": "string",
            "enum": [
              "message",
              "oob",
              "error",
              "system",
              "voice_transcript"
            ]
          },
          "errorCode": {
            "type": "string",
            "enum": [
              "insufficient_credits",
              "spend_cap_exceeded"
            ]
          },
          "reply": {
            "type": [
              "string",
              "null"
            ]
          },
          "replies": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "fallbackInfo": {
            "type": "object",
            "properties": {
              "primaryModel": {
                "type": "string"
              },
              "primaryModelName": {
                "type": "string"
              },
              "fallbackModel": {
                "type": "string"
              },
              "fallbackModelName": {
                "type": "string"
              },
              "reason": {
                "type": "string"
              }
            },
            "required": [
              "primaryModel",
              "primaryModelName",
              "fallbackModel",
              "fallbackModelName"
            ]
          },
          "sessionId": {
            "type": "string"
          },
          "images": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        },
        "required": [
          "id",
          "sessionId"
        ],
        "description": "The quest polled at `GET /api/v1/quests/{id}` after this ACK. The render is finished once `status` is `\"done\"`: on success `images` holds the rendered images; a render that FAILED is `type: \"error\"` with the reason in `reply`, never a 4xx. That covers credit exhaustion (tagged `errorCode: \"insufficient_credits\"`, the same vocabulary as the synchronous 422s on the audio endpoints), a provider error, a reference image that is missing, not an image, or still in moderation, and the combined FLUX.2 input-image limit after attachments are resolved. Check `type` before reading `images`; `errorCode` is absent on unclassified failures, so its absence does not mean success.",
        "example": {
          "id": "664f1c2b9a1e4d0012ab34cd",
          "sessionId": "664f1c2b9a1e4d0012ab34aa",
          "status": "done",
          "type": "message",
          "images": [
            "3f6c1a52-9d1e-4b7a-8c2f-5e0d4a9b1c7e.png"
          ]
        }
      },
      "editImage200PollResult": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "pending",
              "stopped",
              "running",
              "done"
            ]
          },
          "type": {
            "type": "string",
            "enum": [
              "message",
              "oob",
              "error",
              "system",
              "voice_transcript"
            ]
          },
          "errorCode": {
            "type": "string",
            "enum": [
              "insufficient_credits",
              "spend_cap_exceeded"
            ]
          },
          "reply": {
            "type": [
              "string",
              "null"
            ]
          },
          "replies": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "fallbackInfo": {
            "type": "object",
            "properties": {
              "primaryModel": {
                "type": "string"
              },
              "primaryModelName": {
                "type": "string"
              },
              "fallbackModel": {
                "type": "string"
              },
              "fallbackModelName": {
                "type": "string"
              },
              "reason": {
                "type": "string"
              }
            },
            "required": [
              "primaryModel",
              "primaryModelName",
              "fallbackModel",
              "fallbackModelName"
            ]
          },
          "sessionId": {
            "type": "string"
          },
          "images": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        },
        "required": [
          "id",
          "sessionId"
        ],
        "description": "The quest polled at `GET /api/v1/quests/{id}` after this ACK. The render is finished once `status` is `\"done\"`: on success `images` holds the rendered images; a render that FAILED is `type: \"error\"` with the reason in `reply`, never a 4xx. That covers credit exhaustion (tagged `errorCode: \"insufficient_credits\"`, the same vocabulary as the synchronous 422s on the audio endpoints), a provider error, a reference image that is missing, not an image, or still in moderation, and the combined FLUX.2 input-image limit after attachments are resolved. Check `type` before reading `images`; `errorCode` is absent on unclassified failures, so its absence does not mean success.",
        "example": {
          "id": "664f1c2b9a1e4d0012ab34cd",
          "sessionId": "664f1c2b9a1e4d0012ab34aa",
          "status": "done",
          "type": "message",
          "images": [
            "3f6c1a52-9d1e-4b7a-8c2f-5e0d4a9b1c7e.png"
          ]
        }
      },
      "sendChatMessageResponse200": {
        "anyOf": [
          {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "status": {
                "type": "string"
              },
              "message_received": {
                "type": "boolean"
              },
              "timestamp": {
                "type": "string"
              },
              "model": {
                "type": "string"
              },
              "sessionId": {
                "type": "string"
              },
              "message": {
                "type": "string"
              },
              "type": {
                "type": "string",
                "enum": [
                  "message",
                  "oob",
                  "error",
                  "system",
                  "voice_transcript"
                ]
              },
              "errorCode": {
                "type": "string",
                "enum": [
                  "insufficient_credits",
                  "spend_cap_exceeded"
                ]
              },
              "tools": {
                "type": "object",
                "properties": {
                  "toolMode": {
                    "type": "string",
                    "enum": [
                      "fast",
                      "smart"
                    ]
                  },
                  "autoSelectedTools": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  },
                  "effectiveTools": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  },
                  "unrecognizedTools": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  }
                },
                "required": [
                  "effectiveTools"
                ]
              },
              "tracking_info": {
                "type": "object",
                "properties": {
                  "quest_id": {
                    "type": "string"
                  },
                  "check_status_url": {
                    "type": "string"
                  },
                  "poll_url": {
                    "type": "string"
                  }
                },
                "required": [
                  "quest_id",
                  "check_status_url"
                ]
              },
              "response": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "responses": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              "toolPayloads": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "type": {
                      "type": "string"
                    },
                    "payload": {}
                  },
                  "required": [
                    "type"
                  ]
                }
              },
              "createdAt": {
                "anyOf": [
                  {
                    "type": "string",
                    "format": "date-time"
                  },
                  {
                    "type": "string",
                    "format": "date-time"
                  }
                ]
              },
              "promptDetails": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "source": {
                      "type": "string",
                      "enum": [
                        "hardcoded",
                        "admin",
                        "user",
                        "project",
                        "session",
                        "org",
                        "caller"
                      ]
                    },
                    "name": {
                      "type": "string"
                    },
                    "tokenCount": {
                      "type": "number"
                    },
                    "wasIncluded": {
                      "type": "boolean"
                    },
                    "exclusionReason": {
                      "type": "string",
                      "enum": [
                        "duplicate",
                        "disabled",
                        "token_limit"
                      ]
                    }
                  },
                  "required": [
                    "source",
                    "name",
                    "tokenCount",
                    "wasIncluded"
                  ]
                }
              },
              "promptText": {
                "type": "object",
                "properties": {
                  "blocks": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "source": {
                          "type": "string",
                          "enum": [
                            "hardcoded",
                            "admin",
                            "user",
                            "project",
                            "session",
                            "org",
                            "caller"
                          ]
                        },
                        "name": {
                          "type": "string"
                        },
                        "text": {
                          "type": "string"
                        },
                        "redacted": {
                          "type": "boolean"
                        },
                        "placement": {
                          "type": "string",
                          "enum": [
                            "system",
                            "user_turn",
                            "mixed"
                          ]
                        }
                      },
                      "required": [
                        "source",
                        "name",
                        "redacted",
                        "placement"
                      ]
                    }
                  },
                  "sizeCapped": {
                    "type": "boolean"
                  }
                },
                "required": [
                  "blocks",
                  "sizeCapped"
                ]
              },
              "performance": {
                "type": "object",
                "properties": {
                  "total_ms": {
                    "type": "number"
                  },
                  "phases": {
                    "type": "object",
                    "additionalProperties": {
                      "type": "number"
                    }
                  },
                  "pipeline_phases": {
                    "type": "object",
                    "additionalProperties": {
                      "type": "number"
                    }
                  }
                },
                "required": [
                  "total_ms",
                  "phases"
                ]
              }
            },
            "required": [
              "id",
              "status",
              "message_received",
              "timestamp",
              "model",
              "type",
              "tracking_info",
              "response",
              "responses",
              "toolPayloads",
              "createdAt",
              "performance"
            ]
          },
          {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "status": {
                "type": "string"
              },
              "message_received": {
                "type": "boolean"
              },
              "timestamp": {
                "type": "string"
              },
              "model": {
                "type": "string"
              },
              "sessionId": {
                "type": "string"
              },
              "message": {
                "type": "string"
              },
              "type": {
                "type": "string",
                "enum": [
                  "message",
                  "oob",
                  "error",
                  "system",
                  "voice_transcript"
                ]
              },
              "errorCode": {
                "type": "string",
                "enum": [
                  "insufficient_credits",
                  "spend_cap_exceeded"
                ]
              },
              "tools": {
                "type": "object",
                "properties": {
                  "toolMode": {
                    "type": "string",
                    "enum": [
                      "fast",
                      "smart"
                    ]
                  },
                  "autoSelectedTools": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  },
                  "effectiveTools": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  },
                  "unrecognizedTools": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  }
                },
                "required": [
                  "effectiveTools"
                ]
              },
              "tracking_info": {
                "type": "object",
                "properties": {
                  "quest_id": {
                    "type": "string"
                  },
                  "check_status_url": {
                    "type": "string"
                  },
                  "poll_url": {
                    "type": "string"
                  }
                },
                "required": [
                  "quest_id",
                  "check_status_url"
                ]
              }
            },
            "required": [
              "id",
              "status",
              "message_received",
              "timestamp",
              "model",
              "tracking_info"
            ]
          }
        ]
      },
      "ScopeForbiddenResponse": {
        "type": "object",
        "properties": {
          "error": {
            "type": "string"
          },
          "request_id": {
            "type": "string"
          },
          "name": {
            "type": "string",
            "deprecated": true,
            "description": "Deprecated, sunset 2026-12-01. The `name` of whatever the server threw - usually one of our own error classes (`NotFoundError`, `UnprocessableEntityError`, ...), but on an unhandled 500 it can be a library or driver class name instead. Unstable by nature: these are internal names we rename at will, and the set is open. Documented only so the wire and this spec agree for the deprecation window; it is removed on the sunset date. Branch on the HTTP status, not on this."
          },
          "required_scopes": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "API key scopes this route accepts. Holding any one of them satisfies it."
          },
          "also_required_scopes": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "API key scopes this route also requires. Every one must be held, on top of `required_scopes`."
          }
        },
        "required": [
          "error"
        ]
      },
      "sendChatMessageResponse422": {
        "type": "object",
        "properties": {
          "error": {
            "type": "string"
          },
          "request_id": {
            "type": "string"
          },
          "name": {
            "type": "string",
            "deprecated": true,
            "description": "Deprecated, sunset 2026-12-01. The `name` of whatever the server threw - usually

# --- truncated at 32 KB (1699 KB total) ---
# Full source: https://artifacts.apis.io/bike4mind-com/openapi/bike4mind-com-openapi.json