Migrate from API v1 to v2
API v2 replaces v1 as the documented, actively developed API. v1 keeps working for existing integrations, but it no longer receives new features and is scheduled for retirement in January 2027.
This guide lists the changes required to move a v1 integration to v2 before that date.
The v1 reference remains available until v1 is retired.
What stays the same
- Authentication. Send
Authorization: Api-Key <your-api-key>, exactly as in v1. Existing API keys keep working; you don't need to re-issue them. - Base URL.
https://app.biel.ai. - Public project access. Read operations on public projects still work without an API key.
- Search. Request parameters and the response shape of the search endpoint are unchanged; only the base path changes.
Endpoint mapping
Every v1 endpoint has a direct v2 replacement.
| v1 endpoint | v2 endpoint |
|---|---|
POST /api/v1/chats/ | POST /api/v2/projects/{slug}/chats/ |
GET /api/v1/projects/{slug}/ | GET /api/v2/projects/{slug}/ |
GET /api/v1/projects/{slug}/search/ | GET /api/v2/projects/{slug}/search/ |
GET /api/v1/projects/{slug}/sources/ | GET /api/v2/projects/{slug}/sources/ |
POST /api/v1/projects/{slug}/sources/ | POST /api/v2/projects/{slug}/sources/ |
DELETE /api/v1/projects/{slug}/sources/{source_uuid}/ | DELETE /api/v2/projects/{slug}/sources/{source_uuid}/ |
POST /api/v1/projects/{slug}/sources/sync/ | POST /api/v2/projects/{slug}/sync/ |
Permission renames
v2 renames API key permissions to a consistent <resource>_<action> scheme.
| v1 permission | v2 permission |
|---|---|
project_read | projects_read |
project_search | search |
project_sources_read | sources_read |
project_sources_create | sources_create |
project_sources_delete | sources_delete |
project_sync | sync_create |
chat_create | chats_create |
Keys created before v2 may carry the legacy names. They remain valid as aliases of their v2 equivalents, so no key rotation is needed.
Breaking changes
Send a message: project moved to the path
Sending a message now happens under the project, at POST /api/v2/projects/{slug}/chats/. Remove project_slug from the request body and put the slug in the URL instead. The rest of the body (message, chat_uuid, url, email, think_mode, metadata) and the 200/201 response are unchanged.
curl -X POST https://app.biel.ai/api/v1/chats/ \
-H "Authorization: Api-Key $BIEL_API_KEY" \
-H "Content-Type: application/json" \
-d '{"project_slug": "my-project", "message": "How do I install the widget?"}'
curl -X POST https://app.biel.ai/api/v2/projects/my-project/chats/ \
-H "Authorization: Api-Key $BIEL_API_KEY" \
-H "Content-Type: application/json" \
-d '{"message": "How do I install the widget?"}'
Get project: settings grouped under config
The v1 response returned all settings as top-level fields. In v2, feature settings are grouped under a config object, and the response adds identity and lifecycle fields (slug, uuid, name, is_private, last_sync, created_at, updated_at).
| v1 field | v2 field |
|---|---|
initial_message | config.chat.initial_message |
suggested_questions | config.chat.suggested_questions |
think_mode | config.chat.think_mode |
filters | config.search.filters |
mcp_enabled | config.mcp.enabled |
mcp_server_name | config.mcp.server_name |
mcp_metadata_tag | config.mcp.metadata_tag |
whitelabel | whitelabel (unchanged) |
uuid is the public project identifier that the embeddable widget takes in its project attribute.
Get project: new settings with no v1 equivalent
The config object also carries settings that v1 did not have. A v1 integration that reads or writes project settings will encounter them for the first time in v2.
| v2 field | Description |
|---|---|
config.prompt.use_default | Whether the built-in system prompt is used. |
config.prompt.version | Version of the built-in assistant prompt. |
config.prompt.extend | Custom instructions appended to the built-in prompt, or used on their own when use_default is false. |
config.chat.actions | Call-to-action buttons the chat widget renders alongside answers. Each has name, button_text, and url. |
config.chat.actions is read-only. Read-only fields are returned in responses but rejected in requests, so an integration that reads a project and sends the whole object back to update it gets a validation error. Send only the fields you want to change.
Sync: new path and asynchronous response
Sync is its own resource in v2, no longer nested under sources.
- The endpoint moves from
POST /api/v1/projects/{slug}/sources/sync/toPOST /api/v2/projects/{slug}/sync/. - v2 returns
202 Acceptedwith a sync run summary (uuid,status, timestamps) instead of the v1200with a message. PollGET /api/v2/projects/{slug}/sync/or read the project'slast_syncfield to track completion. - Calling the endpoint while a sync is already running cancels the in-progress run and starts a fresh one. v1 returned
400in that case. If your integration relied on the400to avoid duplicate syncs, check the sync status before triggering a new run.
Add source: 201 status and typed sources
- Adding a source with
POST /api/v2/projects/{slug}/sources/returns201 Createdinstead of200 OK. - The
sourcesarray in the response now contains typed source objects with auuid, which you can poll throughGET /api/v2/projects/{slug}/sources/{source_uuid}/to track ingestion.
List sources: paginated response and new source types
-
v1 returned a bare JSON array of sources. v2 returns a paginated object, so read the sources from
resultsinstead of iterating the response directly.Field Description countTotal number of sources matching the query. nextURL of the next page, or nullon the last page.previousURL of the previous page, or nullon the first page.resultsThe sources on this page. Page size defaults to 20 and is capped at 100. Use the
limitandoffsetquery parameters to page through a project with more sources than that, or follownextuntil it isnull. -
Source objects now include
created_at, and thetypeenum addsrepository,openapi, andconfluence. If your integration validatestypeagainst a fixed list, update it.
New in v2
These capabilities have no v1 equivalent:
- Projects: create, list, update, and delete projects.
- Chats: list chats, retrieve a full conversation, delete a conversation, and submit message feedback.
- Sources: add GitHub repositories, OpenAPI specifications, and Confluence spaces, including private ones via a JSON body with credentials.
- Sync: poll sync runs and read the event log for a run.
- Analytics: read aggregate chat, search, MCP, and insights metrics.
- Teams: manage the team that owns the API key, including members and invitations. The team response also reports subscription status and plan (
subscription) and trial state (trial). - Search click tracking: report result clicks to improve search analytics.
- OpenAPI validation: check an OpenAPI specification against the same checks Biel runs when it indexes it, so you can catch a spec that would fail to parse before the next sync.
See the API v2 reference for details.