Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions docs/api/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ Starting in [Sourcegraph 7.0](https://sourcegraph.com/changelog/releases/7.0), a
<Callout type="note">
The new Sourcegraph API is a work in progress, and capabilities are
gradually being ported over. If you have an integration you'd like to build
that is not currently served by the new Sourcegraph API, please reach out at
support@sourcegraph.com.
that is not currently served by the new Sourcegraph API, or migrate to the new Sourcegraph API, you can learn more about it in [our migration guide](/api/migration/). Please reach out at
support@sourcegraph.com if you need more help.
</Callout>

For specific types of integrations, Sourcegraph also offers the following APIs:
Expand Down
330 changes: 330 additions & 0 deletions docs/api/migration/index.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,330 @@
# Upgrading to the new Sourcegraph API
Comment thread
julialeex marked this conversation as resolved.
Outdated

Starting in Sourcegraph 7.0, Sourcegraph introduces a new, versioned API at `/api/`. **The new API provides stable, supported endpoints** for functionality previously served by the experimental Deep Search API (`/.api/deepsearch/v1`) and the GraphQL API (`/.api/graphql`).
Comment thread
julialeex marked this conversation as resolved.
Outdated

Two services are available today:
Comment thread
julialeex marked this conversation as resolved.
Outdated

- **`deepsearch.v1.Service`** — replaces the experimental `/.api/deepsearch/v1` endpoints (create conversations, poll for results, manage follow-ups)
- **`users.v1.Service`** — replaces GraphQL user queries and mutations (get, list, update, delete users)

An interactive API reference is available at `/api-reference` on your Sourcegraph instance (e.g. `https://sourcegraph.example.com/api-reference`), where you can view all operations and download the OpenAPI schema.

![API reference](https://storage.googleapis.com/sourcegraph-assets/Docs/api-reference.png)
Comment thread
julialeex marked this conversation as resolved.
Outdated

## What changed

1. **Protocol**: REST / GraphQL → [ConnectRPC](https://connectrpc.com/) (always POST with JSON)
Comment thread
julialeex marked this conversation as resolved.
Outdated
2. **Base URL**: `/.api/deepsearch/v1/...` and `/.api/graphql` → `/api/{service}/...`
3. **Auth header**: `Authorization: token <TOKEN>` → `Authorization: Bearer <TOKEN>`
4. **Token scopes**: Any access token → token with `externalapi:read` / `externalapi:write` scope
5. **`X-Requested-With` header**: No longer required
6. **Resource identifiers**: Numeric IDs (`140`) → resource names (`users/-/conversations/140`)
7. **Status field** (Deep Search): `status: "processing"` → `state: "STATE_PROCESSING"`

## Why migrate

- **Stability guarantees** — the new API is versioned with backwards compatibility commitments
- **Interactive documentation** — explore and test at `/api-reference`
- **OpenAPI schema** — generate typed clients in any language
- **Scoped tokens** — finer-grained access control with `externalapi:read` / `externalapi:write`

## Endpoint mapping
Comment thread
julialeex marked this conversation as resolved.
Outdated

### Deep Search (`/.api/deepsearch/v1` → `deepsearch.v1.Service`)

| Operation | Old endpoint | New endpoint |
| ------------------- | ------------------------------------------------------ | ----------------------------------------------------------- |
| Create conversation | `POST /.api/deepsearch/v1` | `POST /api/deepsearch.v1.Service/CreateConversation` |
| Get conversation | `GET /.api/deepsearch/v1/{id}` | `POST /api/deepsearch.v1.Service/GetConversation` |
| List conversations | `GET /.api/deepsearch/v1` | `POST /api/deepsearch.v1.Service/ListConversationSummaries` |
| Add follow-up | `POST /.api/deepsearch/v1/{id}/questions` | `POST /api/deepsearch.v1.Service/AddConversationQuestion` |
| Cancel question | `POST /.api/deepsearch/v1/{id}/questions/{qid}/cancel` | `POST /api/deepsearch.v1.Service/CancelConversation` |
| Delete conversation | `DELETE /.api/deepsearch/v1/{id}` | `POST /api/deepsearch.v1.Service/DeleteConversation` |

### User management (`/.api/graphql` → `users.v1.Service`)

| Operation | GraphQL | New endpoint |
| -------------- | ------------------------------------------- | ----------------------------------------------- |
| Get user | `query { user(username: "alice") { ... } }` | `POST /api/users.v1.Service/GetUser` |
| List users | `query { users { nodes { ... } } }` | `POST /api/users.v1.Service/ListUsers` |
| Update user | `mutation { updateUser(...) { ... } }` | `POST /api/users.v1.Service/UpdateUser` |
| Delete users | `mutation { deleteUser(...) { ... } }` | `POST /api/users.v1.Service/BatchDeleteUsers` |
| Undelete users | _(not available in GraphQL)_ | `POST /api/users.v1.Service/BatchUndeleteUsers` |

## Migration by example (Python)

### Deep Search: Create a conversation

**Before:**

```python
import requests

resp = requests.post(
"https://sourcegraph.example.com/.api/deepsearch/v1",
headers={
"Authorization": f"token {TOKEN}",
"X-Requested-With": "my-client 1.0.0",
},
json={"question": "Does the repo have a README?"},
)
conversation = resp.json()
conversation_id = conversation["id"]
```

**After:**

```python
import requests

resp = requests.post(
"https://sourcegraph.example.com/api/deepsearch.v1.Service/CreateConversation",
headers={
"Authorization": f"Bearer {TOKEN}",
"Content-Type": "application/json",
},
json={"question": "Does the repo have a README?"},
)
conversation = resp.json()
conversation_name = conversation["name"] # e.g. "users/1/conversations/140"
```

**With curl:**

```bash
# Before
curl 'https://sourcegraph.example.com/.api/deepsearch/v1' \
-H "Authorization: token $TOKEN" \
-H 'X-Requested-With: my-client 1.0.0' \
-H 'Content-Type: application/json' \
-d '{"question":"Does the repo have a README?"}'

# After
curl 'https://sourcegraph.example.com/api/deepsearch.v1.Service/CreateConversation' \
-H "Authorization: Bearer $TOKEN" \
-H 'Content-Type: application/json' \
-d '{"question":"Does the repo have a README?"}'
```

### Deep Search: Poll for the result

The polling workflow is the same — keep calling until the status indicates completion. The only changes are the URL, method, and status field name.

**Before:**

```python
import time

while True:
resp = requests.get(
f"https://sourcegraph.example.com/.api/deepsearch/v1/{conversation_id}",
headers={
"Authorization": f"token {TOKEN}",
"X-Requested-With": "my-client 1.0.0",
},
)
data = resp.json()
if data["questions"][0]["status"] == "completed":
print(data["questions"][0]["answer"])
break
time.sleep(2)
```

**After:**

```python
import time

while True:
resp = requests.post(
"https://sourcegraph.example.com/api/deepsearch.v1.Service/GetConversation",
headers={
"Authorization": f"Bearer {TOKEN}",
"Content-Type": "application/json",
},
json={"name": conversation_name},
)
data = resp.json()
if data["state"] == "STATE_COMPLETED":
print(data["questions"][0]["answer"])
break
time.sleep(2)
```

### Deep Search: Add a follow-up question

**Before:**

```python
resp = requests.post(
f"https://sourcegraph.example.com/.api/deepsearch/v1/{conversation_id}/questions",
headers={
"Authorization": f"token {TOKEN}",
"X-Requested-With": "my-client 1.0.0",
},
json={
"conversation_id": conversation_id,
"question": "What does the README contain?",
},
)
```

**After:**

```python
resp = requests.post(
"https://sourcegraph.example.com/api/deepsearch.v1.Service/AddConversationQuestion",
headers={
"Authorization": f"Bearer {TOKEN}",
"Content-Type": "application/json",
},
json={
"parent": conversation_name,
"question": "What does the README contain?",
},
)
```

### User management: Get a user

**Before (GraphQL):**

```python
import requests

resp = requests.post(
"https://sourcegraph.example.com/.api/graphql",
headers={
"Authorization": f"token {TOKEN}",
},
json={
"query": 'query { user(username: "alice") { id username displayName } }',
},
)
user = resp.json()["data"]["user"]
```

**After:**

```python
import requests

resp = requests.post(
"https://sourcegraph.example.com/api/users.v1.Service/GetUser",
headers={
"Authorization": f"Bearer {TOKEN}",
"Content-Type": "application/json",
},
json={"name": "users/alice"},
)
user = resp.json()
```

**With curl:**

```bash
# Before (GraphQL)
curl 'https://sourcegraph.example.com/.api/graphql' \
-H "Authorization: token $TOKEN" \
-H 'Content-Type: application/json' \
-d '{"query":"query { user(username: \"alice\") { id username displayName } }"}'

# After
curl 'https://sourcegraph.example.com/api/users.v1.Service/GetUser' \
-H "Authorization: Bearer $TOKEN" \
-H 'Content-Type: application/json' \
-d '{"name":"users/alice"}'
```

### User management: List users

**Before (GraphQL):**

```python
resp = requests.post(
"https://sourcegraph.example.com/.api/graphql",
headers={
"Authorization": f"token {TOKEN}",
},
json={
"query": "query { users { nodes { id username displayName } } }",
},
)
users = resp.json()["data"]["users"]["nodes"]
```

**After:**

```python
resp = requests.post(
"https://sourcegraph.example.com/api/users.v1.Service/ListUsers",
headers={
"Authorization": f"Bearer {TOKEN}",
"Content-Type": "application/json",
},
json={},
)
users = resp.json()["users"]
```

## Response field mapping

### Deep Search

| Old field | New field |
| ---------------------- | ----------------------------------- |
| `id: 140` | `name: "users/1/conversations/140"` |
| `status: "processing"` | `state: "STATE_PROCESSING"` |
| `status: "completed"` | `state: "STATE_COMPLETED"` |
| `questions[].answer` | `questions[].answer` (unchanged) |
| `read_token` | Not exposed |
| `share_url` | Not exposed |

### User management

| GraphQL field | New field |
| ------------------------ | ---------------------- |
| `id` (opaque GraphQL ID) | `name: "users/alice"` |
| `username` | `username` (unchanged) |
| `displayName` | `display_name` |
| `avatarURL` | `avatar_uri` |
| `createdAt` | `create_time` |
| `updatedAt` | `update_time` |

## Features not yet in the new API

The following features from the old API do not have equivalents in the new API yet, but are planned to be supported in future versions:

- Starring conversations
- Read token rotation and sharing via tokens
- Bulk delete of all conversations
- SSE streaming of question processing progress
- Code search, repository, git metadata, and Batch Changes operations (currently GraphQL-only)
Comment thread
julialeex marked this conversation as resolved.
Outdated

If you depend on any of these, please reach out at **support@sourcegraph.com**.

## Migration checklist

- [ ] Generate a new access token with `externalapi:read` / `externalapi:write` scopes
- [ ] Update `Authorization` header from `token <TOKEN>` to `Bearer <TOKEN>`
Comment thread
julialeex marked this conversation as resolved.
Outdated
- [ ] Remove the `X-Requested-With` header
- [ ] Update Deep Search endpoint URLs from `/.api/deepsearch/v1/...` to `/api/deepsearch.v1.Service/...`
- [ ] Update user management calls from `/.api/graphql` to `/api/users.v1.Service/...`
- [ ] Change all HTTP methods to `POST`
- [ ] Update resource identifiers from numeric IDs to resource names (e.g. `users/-/conversations/140`)
- [ ] Update status checks from `"completed"` to `"STATE_COMPLETED"` (Deep Search)
- [ ] Test end-to-end

## Other Sourcegraph APIs

The existing Sourcegraph GraphQL API and experimental `/.api/deepsearch/` API remain available, but we recommend migrating to the new API at `/api/` for a stable integration experience. If you need features added to the new Sourcegraph API endpoints for your use cases, please reach out at **support@sourcegraph.com**.

The following APIs continue to work as before and are **not deprecated at this time**:

- **[GraphQL debug API](/api/graphql/)** (`/.api/graphql`) — code search, repositories, git metadata, Batch Changes, and all other functionality not yet covered by `/api/`. To reflect the GraphQL API's intended purpose, we have renamed it in our documentation and UI to the **Debug API** (or **Debug console**). New `/api/` equivalents will be introduced over time, and we recommend migrating to them as they become available.
- **[Stream API](/api/stream-api/)** (`/.api/search/stream`) — streaming search results
- **[Analytics API](/analytics/api/)** (`analytics.sourcegraph.com`) — usage metrics and reporting

## Need help?

If you have questions about the migration or need features not yet available in the new API, reach out at **support@sourcegraph.com**.