# AgentDocs

Source: https://opvs.ai/docs/api/agentdocs

## `GET` /api/v1/docs/projects

**Api List Projects**

List documentation projects for the current brand.

**Parameters**

- `skip` (query, integer, optional)
- `limit` (query, integer, optional)

```bash
curl -X GET 'https://app.opvs.ai/api/v1/docs/projects' \
  -H 'Authorization: Bearer <token>'
```

```python
import httpx

resp = httpx.get(
    "https://app.opvs.ai/api/v1/docs/projects",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
```

```javascript
const resp = await fetch("https://app.opvs.ai/api/v1/docs/projects", {
  method: "GET",
  headers: { "Authorization": "Bearer <token>" }
});
const data = await resp.json();
console.log(data);
```

```go
package main

import (
	"net/http"
)

func main() {
	req, _ := http.NewRequest("GET", "https://app.opvs.ai/api/v1/docs/projects", nil)
	req.Header.Set("Authorization", "Bearer <token>")
	resp, _ := http.DefaultClient.Do(req)
	defer resp.Body.Close()
}
```

**Responses**

- `200` — Successful Response
- `422` — Validation Error

## `POST` /api/v1/docs/projects

**Api Create Project**

Create a new documentation project.

**Request body**

```bash
curl -X POST 'https://app.opvs.ai/api/v1/docs/projects' \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '{
  "name": "string",
  "description": "string",
  "visibility": "private",
  "author_type": "string",
  "author_name": "string"
}'
```

```python
import httpx

resp = httpx.post(
    "https://app.opvs.ai/api/v1/docs/projects",
    headers={"Authorization": "Bearer <token>", "Content-Type": "application/json"},
    json={"name": "string", "description": "string", "visibility": "private", "author_type": "string", "author_name": "string"},
)
resp.raise_for_status()
print(resp.json())
```

```javascript
const resp = await fetch("https://app.opvs.ai/api/v1/docs/projects", {
  method: "POST",
  headers: { "Authorization": "Bearer <token>", "Content-Type": "application/json" },
  body: JSON.stringify({"name": "string", "description": "string", "visibility": "private", "author_type": "string", "author_name": "string"})
});
const data = await resp.json();
console.log(data);
```

```go
package main

import (
	"net/http"
	"strings"
)

func main() {
	body := strings.NewReader(`{"name": "string", "description": "string", "visibility": "private", "author_type": "string", "author_name": "string"}`)
	req, _ := http.NewRequest("POST", "https://app.opvs.ai/api/v1/docs/projects", body)
	req.Header.Set("Authorization", "Bearer <token>")
	req.Header.Set("Content-Type", "application/json")
	resp, _ := http.DefaultClient.Do(req)
	defer resp.Body.Close()
}
```

**Responses**

- `201` — Successful Response
- `422` — Validation Error

## `GET` /api/v1/docs/projects/{project_id}

**Api Get Project**

Get a documentation project with page count.

**Parameters**

- `project_id` (path, string, required)

```bash
curl -X GET 'https://app.opvs.ai/api/v1/docs/projects/{project_id}' \
  -H 'Authorization: Bearer <token>'
```

```python
import httpx

resp = httpx.get(
    "https://app.opvs.ai/api/v1/docs/projects/{project_id}",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
```

```javascript
const resp = await fetch("https://app.opvs.ai/api/v1/docs/projects/{project_id}", {
  method: "GET",
  headers: { "Authorization": "Bearer <token>" }
});
const data = await resp.json();
console.log(data);
```

```go
package main

import (
	"net/http"
)

func main() {
	req, _ := http.NewRequest("GET", "https://app.opvs.ai/api/v1/docs/projects/{project_id}", nil)
	req.Header.Set("Authorization", "Bearer <token>")
	resp, _ := http.DefaultClient.Do(req)
	defer resp.Body.Close()
}
```

**Responses**

- `200` — Successful Response
- `422` — Validation Error

## `PATCH` /api/v1/docs/projects/{project_id}

**Api Update Project**

Update a documentation project. Brand admin only.

**Parameters**

- `project_id` (path, string, required)

**Request body**

```bash
curl -X PATCH 'https://app.opvs.ai/api/v1/docs/projects/{project_id}' \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '{
  "name": "string",
  "description": "string",
  "visibility": "string",
  "settings": {}
}'
```

```python
import httpx

resp = httpx.patch(
    "https://app.opvs.ai/api/v1/docs/projects/{project_id}",
    headers={"Authorization": "Bearer <token>", "Content-Type": "application/json"},
    json={"name": "string", "description": "string", "visibility": "string", "settings": {}},
)
resp.raise_for_status()
print(resp.json())
```

```javascript
const resp = await fetch("https://app.opvs.ai/api/v1/docs/projects/{project_id}", {
  method: "PATCH",
  headers: { "Authorization": "Bearer <token>", "Content-Type": "application/json" },
  body: JSON.stringify({"name": "string", "description": "string", "visibility": "string", "settings": {}})
});
const data = await resp.json();
console.log(data);
```

```go
package main

import (
	"net/http"
	"strings"
)

func main() {
	body := strings.NewReader(`{"name": "string", "description": "string", "visibility": "string", "settings": {}}`)
	req, _ := http.NewRequest("PATCH", "https://app.opvs.ai/api/v1/docs/projects/{project_id}", body)
	req.Header.Set("Authorization", "Bearer <token>")
	req.Header.Set("Content-Type", "application/json")
	resp, _ := http.DefaultClient.Do(req)
	defer resp.Body.Close()
}
```

**Responses**

- `200` — Successful Response
- `422` — Validation Error

## `DELETE` /api/v1/docs/projects/{project_id}

**Api Delete Project**

Soft-delete a documentation project. Brand admin only.

**Parameters**

- `project_id` (path, string, required)

```bash
curl -X DELETE 'https://app.opvs.ai/api/v1/docs/projects/{project_id}' \
  -H 'Authorization: Bearer <token>'
```

```python
import httpx

resp = httpx.delete(
    "https://app.opvs.ai/api/v1/docs/projects/{project_id}",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
```

```javascript
const resp = await fetch("https://app.opvs.ai/api/v1/docs/projects/{project_id}", {
  method: "DELETE",
  headers: { "Authorization": "Bearer <token>" }
});
const data = await resp.json();
console.log(data);
```

```go
package main

import (
	"net/http"
)

func main() {
	req, _ := http.NewRequest("DELETE", "https://app.opvs.ai/api/v1/docs/projects/{project_id}", nil)
	req.Header.Set("Authorization", "Bearer <token>")
	resp, _ := http.DefaultClient.Do(req)
	defer resp.Body.Close()
}
```

**Responses**

- `200` — Successful Response
- `422` — Validation Error

## `GET` /api/v1/docs/projects/{project_id}/pages

**Api List Pages**

List pages in a project. Use view=tree for nested structure.

**Parameters**

- `project_id` (path, string, required)
- `view` (query, string, optional)
- `skip` (query, integer, optional)
- `limit` (query, integer, optional)

```bash
curl -X GET 'https://app.opvs.ai/api/v1/docs/projects/{project_id}/pages' \
  -H 'Authorization: Bearer <token>'
```

```python
import httpx

resp = httpx.get(
    "https://app.opvs.ai/api/v1/docs/projects/{project_id}/pages",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
```

```javascript
const resp = await fetch("https://app.opvs.ai/api/v1/docs/projects/{project_id}/pages", {
  method: "GET",
  headers: { "Authorization": "Bearer <token>" }
});
const data = await resp.json();
console.log(data);
```

```go
package main

import (
	"net/http"
)

func main() {
	req, _ := http.NewRequest("GET", "https://app.opvs.ai/api/v1/docs/projects/{project_id}/pages", nil)
	req.Header.Set("Authorization", "Bearer <token>")
	resp, _ := http.DefaultClient.Do(req)
	defer resp.Body.Close()
}
```

**Responses**

- `200` — Successful Response
- `422` — Validation Error

## `POST` /api/v1/docs/projects/{project_id}/pages

**Api Create Page**

Create a new page with initial content (first revision).

**Parameters**

- `project_id` (path, string, required)

**Request body**

```bash
curl -X POST 'https://app.opvs.ai/api/v1/docs/projects/{project_id}/pages' \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '{
  "slug": "string",
  "title": "string",
  "path": "/",
  "content_md": "string",
  "commit_message": "string",
  "page_type": "markdown",
  "sort_order": 0,
  "tags": [
    "string"
  ],
  "extra_data": {},
  "agent_context": {},
  "author_type": "string",
  "author_name": "string"
}'
```

```python
import httpx

resp = httpx.post(
    "https://app.opvs.ai/api/v1/docs/projects/{project_id}/pages",
    headers={"Authorization": "Bearer <token>", "Content-Type": "application/json"},
    json={"slug": "string", "title": "string", "path": "/", "content_md": "string", "commit_message": "string", "page_type": "markdown", "sort_order": 0, "tags": ["string"], "extra_data": {}, "agent_context": {}, "author_type": "string", "author_name": "string"},
)
resp.raise_for_status()
print(resp.json())
```

```javascript
const resp = await fetch("https://app.opvs.ai/api/v1/docs/projects/{project_id}/pages", {
  method: "POST",
  headers: { "Authorization": "Bearer <token>", "Content-Type": "application/json" },
  body: JSON.stringify({"slug": "string", "title": "string", "path": "/", "content_md": "string", "commit_message": "string", "page_type": "markdown", "sort_order": 0, "tags": ["string"], "extra_data": {}, "agent_context": {}, "author_type": "string", "author_name": "string"})
});
const data = await resp.json();
console.log(data);
```

```go
package main

import (
	"net/http"
	"strings"
)

func main() {
	body := strings.NewReader(`{"slug": "string", "title": "string", "path": "/", "content_md": "string", "commit_message": "string", "page_type": "markdown", "sort_order": 0, "tags": ["string"], "extra_data": {}, "agent_context": {}, "author_type": "string", "author_name": "string"}`)
	req, _ := http.NewRequest("POST", "https://app.opvs.ai/api/v1/docs/projects/{project_id}/pages", body)
	req.Header.Set("Authorization", "Bearer <token>")
	req.Header.Set("Content-Type", "application/json")
	resp, _ := http.DefaultClient.Do(req)
	defer resp.Body.Close()
}
```

**Responses**

- `201` — Successful Response
- `422` — Validation Error

## `GET` /api/v1/docs/projects/{project_id}/pages/{slug}

**Api Get Page**

Get a page with its current content.

**Parameters**

- `slug` (path, string, required)
- `project_id` (path, string, required)

```bash
curl -X GET 'https://app.opvs.ai/api/v1/docs/projects/{project_id}/pages/{slug}' \
  -H 'Authorization: Bearer <token>'
```

```python
import httpx

resp = httpx.get(
    "https://app.opvs.ai/api/v1/docs/projects/{project_id}/pages/{slug}",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
```

```javascript
const resp = await fetch("https://app.opvs.ai/api/v1/docs/projects/{project_id}/pages/{slug}", {
  method: "GET",
  headers: { "Authorization": "Bearer <token>" }
});
const data = await resp.json();
console.log(data);
```

```go
package main

import (
	"net/http"
)

func main() {
	req, _ := http.NewRequest("GET", "https://app.opvs.ai/api/v1/docs/projects/{project_id}/pages/{slug}", nil)
	req.Header.Set("Authorization", "Bearer <token>")
	resp, _ := http.DefaultClient.Do(req)
	defer resp.Body.Close()
}
```

**Responses**

- `200` — Successful Response
- `422` — Validation Error

## `PUT` /api/v1/docs/projects/{project_id}/pages/{slug}

**Api Update Page**

Update a page (creates a new revision). Deduplicates identical content.

**Parameters**

- `slug` (path, string, required)
- `project_id` (path, string, required)

**Request body**

```bash
curl -X PUT 'https://app.opvs.ai/api/v1/docs/projects/{project_id}/pages/{slug}' \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '{
  "content_md": "string",
  "commit_message": "string",
  "title": "string",
  "tags": [
    "string"
  ],
  "extra_data": {},
  "agent_context": {},
  "author_type": "string",
  "author_name": "string"
}'
```

```python
import httpx

resp = httpx.put(
    "https://app.opvs.ai/api/v1/docs/projects/{project_id}/pages/{slug}",
    headers={"Authorization": "Bearer <token>", "Content-Type": "application/json"},
    json={"content_md": "string", "commit_message": "string", "title": "string", "tags": ["string"], "extra_data": {}, "agent_context": {}, "author_type": "string", "author_name": "string"},
)
resp.raise_for_status()
print(resp.json())
```

```javascript
const resp = await fetch("https://app.opvs.ai/api/v1/docs/projects/{project_id}/pages/{slug}", {
  method: "PUT",
  headers: { "Authorization": "Bearer <token>", "Content-Type": "application/json" },
  body: JSON.stringify({"content_md": "string", "commit_message": "string", "title": "string", "tags": ["string"], "extra_data": {}, "agent_context": {}, "author_type": "string", "author_name": "string"})
});
const data = await resp.json();
console.log(data);
```

```go
package main

import (
	"net/http"
	"strings"
)

func main() {
	body := strings.NewReader(`{"content_md": "string", "commit_message": "string", "title": "string", "tags": ["string"], "extra_data": {}, "agent_context": {}, "author_type": "string", "author_name": "string"}`)
	req, _ := http.NewRequest("PUT", "https://app.opvs.ai/api/v1/docs/projects/{project_id}/pages/{slug}", body)
	req.Header.Set("Authorization", "Bearer <token>")
	req.Header.Set("Content-Type", "application/json")
	resp, _ := http.DefaultClient.Do(req)
	defer resp.Body.Close()
}
```

**Responses**

- `200` — Successful Response
- `422` — Validation Error

## `DELETE` /api/v1/docs/projects/{project_id}/pages/{slug}

**Api Delete Page**

Soft-delete a page.

**Parameters**

- `slug` (path, string, required)
- `project_id` (path, string, required)

```bash
curl -X DELETE 'https://app.opvs.ai/api/v1/docs/projects/{project_id}/pages/{slug}' \
  -H 'Authorization: Bearer <token>'
```

```python
import httpx

resp = httpx.delete(
    "https://app.opvs.ai/api/v1/docs/projects/{project_id}/pages/{slug}",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
```

```javascript
const resp = await fetch("https://app.opvs.ai/api/v1/docs/projects/{project_id}/pages/{slug}", {
  method: "DELETE",
  headers: { "Authorization": "Bearer <token>" }
});
const data = await resp.json();
console.log(data);
```

```go
package main

import (
	"net/http"
)

func main() {
	req, _ := http.NewRequest("DELETE", "https://app.opvs.ai/api/v1/docs/projects/{project_id}/pages/{slug}", nil)
	req.Header.Set("Authorization", "Bearer <token>")
	resp, _ := http.DefaultClient.Do(req)
	defer resp.Body.Close()
}
```

**Responses**

- `200` — Successful Response
- `422` — Validation Error

## `PATCH` /api/v1/docs/projects/{project_id}/pages/{slug}/move

**Api Move Page**

Move a page to a new path or change sort order. Does not create a revision.

**Parameters**

- `slug` (path, string, required)
- `project_id` (path, string, required)

**Request body**

```bash
curl -X PATCH 'https://app.opvs.ai/api/v1/docs/projects/{project_id}/pages/{slug}/move' \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '{
  "path": "string",
  "sort_order": 0
}'
```

```python
import httpx

resp = httpx.patch(
    "https://app.opvs.ai/api/v1/docs/projects/{project_id}/pages/{slug}/move",
    headers={"Authorization": "Bearer <token>", "Content-Type": "application/json"},
    json={"path": "string", "sort_order": 0},
)
resp.raise_for_status()
print(resp.json())
```

```javascript
const resp = await fetch("https://app.opvs.ai/api/v1/docs/projects/{project_id}/pages/{slug}/move", {
  method: "PATCH",
  headers: { "Authorization": "Bearer <token>", "Content-Type": "application/json" },
  body: JSON.stringify({"path": "string", "sort_order": 0})
});
const data = await resp.json();
console.log(data);
```

```go
package main

import (
	"net/http"
	"strings"
)

func main() {
	body := strings.NewReader(`{"path": "string", "sort_order": 0}`)
	req, _ := http.NewRequest("PATCH", "https://app.opvs.ai/api/v1/docs/projects/{project_id}/pages/{slug}/move", body)
	req.Header.Set("Authorization", "Bearer <token>")
	req.Header.Set("Content-Type", "application/json")
	resp, _ := http.DefaultClient.Do(req)
	defer resp.Body.Close()
}
```

**Responses**

- `200` — Successful Response
- `422` — Validation Error

## `GET` /api/v1/docs/pages/{page_id}/history

**Api Get Revision History**

Get revision history for a page.

**Parameters**

- `page_id` (path, string, required)
- `skip` (query, integer, optional)
- `limit` (query, integer, optional)

```bash
curl -X GET 'https://app.opvs.ai/api/v1/docs/pages/{page_id}/history' \
  -H 'Authorization: Bearer <token>'
```

```python
import httpx

resp = httpx.get(
    "https://app.opvs.ai/api/v1/docs/pages/{page_id}/history",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
```

```javascript
const resp = await fetch("https://app.opvs.ai/api/v1/docs/pages/{page_id}/history", {
  method: "GET",
  headers: { "Authorization": "Bearer <token>" }
});
const data = await resp.json();
console.log(data);
```

```go
package main

import (
	"net/http"
)

func main() {
	req, _ := http.NewRequest("GET", "https://app.opvs.ai/api/v1/docs/pages/{page_id}/history", nil)
	req.Header.Set("Authorization", "Bearer <token>")
	resp, _ := http.DefaultClient.Do(req)
	defer resp.Body.Close()
}
```

**Responses**

- `200` — Successful Response
- `422` — Validation Error

## `GET` /api/v1/docs/revisions/{revision_id}

**Api Get Revision**

Get a specific revision with full content.

**Parameters**

- `revision_id` (path, string, required)

```bash
curl -X GET 'https://app.opvs.ai/api/v1/docs/revisions/{revision_id}' \
  -H 'Authorization: Bearer <token>'
```

```python
import httpx

resp = httpx.get(
    "https://app.opvs.ai/api/v1/docs/revisions/{revision_id}",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
```

```javascript
const resp = await fetch("https://app.opvs.ai/api/v1/docs/revisions/{revision_id}", {
  method: "GET",
  headers: { "Authorization": "Bearer <token>" }
});
const data = await resp.json();
console.log(data);
```

```go
package main

import (
	"net/http"
)

func main() {
	req, _ := http.NewRequest("GET", "https://app.opvs.ai/api/v1/docs/revisions/{revision_id}", nil)
	req.Header.Set("Authorization", "Bearer <token>")
	resp, _ := http.DefaultClient.Do(req)
	defer resp.Body.Close()
}
```

**Responses**

- `200` — Successful Response
- `422` — Validation Error

## `GET` /api/v1/docs/pages/{page_id}/diff

**Api Compute Diff**

Compute unified diff between two revisions. Omit 'from' for parent comparison.

**Parameters**

- `page_id` (path, string, required)
- `from` (query, any, optional)
- `to` (query, any, optional)

```bash
curl -X GET 'https://app.opvs.ai/api/v1/docs/pages/{page_id}/diff' \
  -H 'Authorization: Bearer <token>'
```

```python
import httpx

resp = httpx.get(
    "https://app.opvs.ai/api/v1/docs/pages/{page_id}/diff",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
```

```javascript
const resp = await fetch("https://app.opvs.ai/api/v1/docs/pages/{page_id}/diff", {
  method: "GET",
  headers: { "Authorization": "Bearer <token>" }
});
const data = await resp.json();
console.log(data);
```

```go
package main

import (
	"net/http"
)

func main() {
	req, _ := http.NewRequest("GET", "https://app.opvs.ai/api/v1/docs/pages/{page_id}/diff", nil)
	req.Header.Set("Authorization", "Bearer <token>")
	resp, _ := http.DefaultClient.Do(req)
	defer resp.Body.Close()
}
```

**Responses**

- `200` — Successful Response
- `422` — Validation Error

## `POST` /api/v1/docs/pages/{page_id}/rollback

**Api Rollback**

Rollback a page to a previous revision. Creates a new (non-destructive) revision.

**Parameters**

- `page_id` (path, string, required)

**Request body**

```bash
curl -X POST 'https://app.opvs.ai/api/v1/docs/pages/{page_id}/rollback' \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '{
  "revision_id": "string",
  "commit_message": "string"
}'
```

```python
import httpx

resp = httpx.post(
    "https://app.opvs.ai/api/v1/docs/pages/{page_id}/rollback",
    headers={"Authorization": "Bearer <token>", "Content-Type": "application/json"},
    json={"revision_id": "string", "commit_message": "string"},
)
resp.raise_for_status()
print(resp.json())
```

```javascript
const resp = await fetch("https://app.opvs.ai/api/v1/docs/pages/{page_id}/rollback", {
  method: "POST",
  headers: { "Authorization": "Bearer <token>", "Content-Type": "application/json" },
  body: JSON.stringify({"revision_id": "string", "commit_message": "string"})
});
const data = await resp.json();
console.log(data);
```

```go
package main

import (
	"net/http"
	"strings"
)

func main() {
	body := strings.NewReader(`{"revision_id": "string", "commit_message": "string"}`)
	req, _ := http.NewRequest("POST", "https://app.opvs.ai/api/v1/docs/pages/{page_id}/rollback", body)
	req.Header.Set("Authorization", "Bearer <token>")
	req.Header.Set("Content-Type", "application/json")
	resp, _ := http.DefaultClient.Do(req)
	defer resp.Body.Close()
}
```

**Responses**

- `200` — Successful Response
- `422` — Validation Error

## `GET` /api/v1/docs/projects/{project_id}/media

**Api List Media**

List media files in a project.

**Parameters**

- `project_id` (path, string, required)
- `skip` (query, integer, optional)
- `limit` (query, integer, optional)

```bash
curl -X GET 'https://app.opvs.ai/api/v1/docs/projects/{project_id}/media' \
  -H 'Authorization: Bearer <token>'
```

```python
import httpx

resp = httpx.get(
    "https://app.opvs.ai/api/v1/docs/projects/{project_id}/media",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
```

```javascript
const resp = await fetch("https://app.opvs.ai/api/v1/docs/projects/{project_id}/media", {
  method: "GET",
  headers: { "Authorization": "Bearer <token>" }
});
const data = await resp.json();
console.log(data);
```

```go
package main

import (
	"net/http"
)

func main() {
	req, _ := http.NewRequest("GET", "https://app.opvs.ai/api/v1/docs/projects/{project_id}/media", nil)
	req.Header.Set("Authorization", "Bearer <token>")
	resp, _ := http.DefaultClient.Do(req)
	defer resp.Body.Close()
}
```

**Responses**

- `200` — Successful Response
- `422` — Validation Error

## `POST` /api/v1/docs/projects/{project_id}/media

**Api Upload Media**

Upload a media file (image, PDF, etc.) to R2 storage.

**Parameters**

- `project_id` (path, string, required)

**Request body**

```bash
curl -X POST 'https://app.opvs.ai/api/v1/docs/projects/{project_id}/media' \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '{
  "file": "string"
}'
```

```python
import httpx

resp = httpx.post(
    "https://app.opvs.ai/api/v1/docs/projects/{project_id}/media",
    headers={"Authorization": "Bearer <token>", "Content-Type": "application/json"},
    json={"file": "string"},
)
resp.raise_for_status()
print(resp.json())
```

```javascript
const resp = await fetch("https://app.opvs.ai/api/v1/docs/projects/{project_id}/media", {
  method: "POST",
  headers: { "Authorization": "Bearer <token>", "Content-Type": "application/json" },
  body: JSON.stringify({"file": "string"})
});
const data = await resp.json();
console.log(data);
```

```go
package main

import (
	"net/http"
	"strings"
)

func main() {
	body := strings.NewReader(`{"file": "string"}`)
	req, _ := http.NewRequest("POST", "https://app.opvs.ai/api/v1/docs/projects/{project_id}/media", body)
	req.Header.Set("Authorization", "Bearer <token>")
	req.Header.Set("Content-Type", "application/json")
	resp, _ := http.DefaultClient.Do(req)
	defer resp.Body.Close()
}
```

**Responses**

- `201` — Successful Response
- `422` — Validation Error

## `GET` /api/v1/docs/recent-pages

**Api List Recent Pages**

List the most recently updated pages across every project in the brand.

**Parameters**

- `limit` (query, integer, optional)
- `author_type` (query, any, optional)

```bash
curl -X GET 'https://app.opvs.ai/api/v1/docs/recent-pages' \
  -H 'Authorization: Bearer <token>'
```

```python
import httpx

resp = httpx.get(
    "https://app.opvs.ai/api/v1/docs/recent-pages",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
```

```javascript
const resp = await fetch("https://app.opvs.ai/api/v1/docs/recent-pages", {
  method: "GET",
  headers: { "Authorization": "Bearer <token>" }
});
const data = await resp.json();
console.log(data);
```

```go
package main

import (
	"net/http"
)

func main() {
	req, _ := http.NewRequest("GET", "https://app.opvs.ai/api/v1/docs/recent-pages", nil)
	req.Header.Set("Authorization", "Bearer <token>")
	resp, _ := http.DefaultClient.Do(req)
	defer resp.Body.Close()
}
```

**Responses**

- `200` — Successful Response
- `422` — Validation Error

## `GET` /api/v1/docs/search

**Api Search**

Full-text search across all pages in the brand's documentation.

**Parameters**

- `q` (query, string, required)
- `project_id` (query, any, optional)
- `tags` (query, any, optional) — Comma-separated tags
- `author_type` (query, any, optional)
- `skip` (query, integer, optional)
- `limit` (query, integer, optional)

```bash
curl -X GET 'https://app.opvs.ai/api/v1/docs/search' \
  -H 'Authorization: Bearer <token>'
```

```python
import httpx

resp = httpx.get(
    "https://app.opvs.ai/api/v1/docs/search",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
```

```javascript
const resp = await fetch("https://app.opvs.ai/api/v1/docs/search", {
  method: "GET",
  headers: { "Authorization": "Bearer <token>" }
});
const data = await resp.json();
console.log(data);
```

```go
package main

import (
	"net/http"
)

func main() {
	req, _ := http.NewRequest("GET", "https://app.opvs.ai/api/v1/docs/search", nil)
	req.Header.Set("Authorization", "Bearer <token>")
	resp, _ := http.DefaultClient.Do(req)
	defer resp.Body.Close()
}
```

**Responses**

- `200` — Successful Response
- `422` — Validation Error

## `GET` /api/v1/docs/projects/{project_id}/branches

**Api List Branches**

List branches for a project.

**Parameters**

- `project_id` (path, string, required)
- `include_closed` (query, boolean, optional)

```bash
curl -X GET 'https://app.opvs.ai/api/v1/docs/projects/{project_id}/branches' \
  -H 'Authorization: Bearer <token>'
```

```python
import httpx

resp = httpx.get(
    "https://app.opvs.ai/api/v1/docs/projects/{project_id}/branches",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
```

```javascript
const resp = await fetch("https://app.opvs.ai/api/v1/docs/projects/{project_id}/branches", {
  method: "GET",
  headers: { "Authorization": "Bearer <token>" }
});
const data = await resp.json();
console.log(data);
```

```go
package main

import (
	"net/http"
)

func main() {
	req, _ := http.NewRequest("GET", "https://app.opvs.ai/api/v1/docs/projects/{project_id}/branches", nil)
	req.Header.Set("Authorization", "Bearer <token>")
	resp, _ := http.DefaultClient.Do(req)
	defer resp.Body.Close()
}
```

**Responses**

- `200` — Successful Response
- `422` — Validation Error

## `POST` /api/v1/docs/projects/{project_id}/branches

**Api Create Branch**

Create a new branch for draft/review workflows.

**Parameters**

- `project_id` (path, string, required)

**Request body**

```bash
curl -X POST 'https://app.opvs.ai/api/v1/docs/projects/{project_id}/branches' \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '{
  "name": "string",
  "description": "string",
  "source_branch": "main"
}'
```

```python
import httpx

resp = httpx.post(
    "https://app.opvs.ai/api/v1/docs/projects/{project_id}/branches",
    headers={"Authorization": "Bearer <token>", "Content-Type": "application/json"},
    json={"name": "string", "description": "string", "source_branch": "main"},
)
resp.raise_for_status()
print(resp.json())
```

```javascript
const resp = await fetch("https://app.opvs.ai/api/v1/docs/projects/{project_id}/branches", {
  method: "POST",
  headers: { "Authorization": "Bearer <token>", "Content-Type": "application/json" },
  body: JSON.stringify({"name": "string", "description": "string", "source_branch": "main"})
});
const data = await resp.json();
console.log(data);
```

```go
package main

import (
	"net/http"
	"strings"
)

func main() {
	body := strings.NewReader(`{"name": "string", "description": "string", "source_branch": "main"}`)
	req, _ := http.NewRequest("POST", "https://app.opvs.ai/api/v1/docs/projects/{project_id}/branches", body)
	req.Header.Set("Authorization", "Bearer <token>")
	req.Header.Set("Content-Type", "application/json")
	resp, _ := http.DefaultClient.Do(req)
	defer resp.Body.Close()
}
```

**Responses**

- `201` — Successful Response
- `422` — Validation Error

## `GET` /api/v1/docs/projects/{project_id}/branches/{branch_name}/diff

**Api Branch Diff**

Get diff summary for a branch compared to main.

**Parameters**

- `branch_name` (path, string, required)
- `project_id` (path, string, required)

```bash
curl -X GET 'https://app.opvs.ai/api/v1/docs/projects/{project_id}/branches/{branch_name}/diff' \
  -H 'Authorization: Bearer <token>'
```

```python
import httpx

resp = httpx.get(
    "https://app.opvs.ai/api/v1/docs/projects/{project_id}/branches/{branch_name}/diff",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
```

```javascript
const resp = await fetch("https://app.opvs.ai/api/v1/docs/projects/{project_id}/branches/{branch_name}/diff", {
  method: "GET",
  headers: { "Authorization": "Bearer <token>" }
});
const data = await resp.json();
console.log(data);
```

```go
package main

import (
	"net/http"
)

func main() {
	req, _ := http.NewRequest("GET", "https://app.opvs.ai/api/v1/docs/projects/{project_id}/branches/{branch_name}/diff", nil)
	req.Header.Set("Authorization", "Bearer <token>")
	resp, _ := http.DefaultClient.Do(req)
	defer resp.Body.Close()
}
```

**Responses**

- `200` — Successful Response
- `422` — Validation Error

## `POST` /api/v1/docs/projects/{project_id}/branches/{branch_name}/merge

**Api Merge Branch**

Merge a branch into main. Creates new revisions for affected pages.

**Parameters**

- `branch_name` (path, string, required)
- `project_id` (path, string, required)

**Request body**

```bash
curl -X POST 'https://app.opvs.ai/api/v1/docs/projects/{project_id}/branches/{branch_name}/merge' \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '{
  "target_branch": "main",
  "strategy": "overwrite"
}'
```

```python
import httpx

resp = httpx.post(
    "https://app.opvs.ai/api/v1/docs/projects/{project_id}/branches/{branch_name}/merge",
    headers={"Authorization": "Bearer <token>", "Content-Type": "application/json"},
    json={"target_branch": "main", "strategy": "overwrite"},
)
resp.raise_for_status()
print(resp.json())
```

```javascript
const resp = await fetch("https://app.opvs.ai/api/v1/docs/projects/{project_id}/branches/{branch_name}/merge", {
  method: "POST",
  headers: { "Authorization": "Bearer <token>", "Content-Type": "application/json" },
  body: JSON.stringify({"target_branch": "main", "strategy": "overwrite"})
});
const data = await resp.json();
console.log(data);
```

```go
package main

import (
	"net/http"
	"strings"
)

func main() {
	body := strings.NewReader(`{"target_branch": "main", "strategy": "overwrite"}`)
	req, _ := http.NewRequest("POST", "https://app.opvs.ai/api/v1/docs/projects/{project_id}/branches/{branch_name}/merge", body)
	req.Header.Set("Authorization", "Bearer <token>")
	req.Header.Set("Content-Type", "application/json")
	resp, _ := http.DefaultClient.Do(req)
	defer resp.Body.Close()
}
```

**Responses**

- `200` — Successful Response
- `422` — Validation Error

## `DELETE` /api/v1/docs/projects/{project_id}/branches/{branch_name}

**Api Close Branch**

Close a branch without merging.

**Parameters**

- `branch_name` (path, string, required)
- `project_id` (path, string, required)

```bash
curl -X DELETE 'https://app.opvs.ai/api/v1/docs/projects/{project_id}/branches/{branch_name}' \
  -H 'Authorization: Bearer <token>'
```

```python
import httpx

resp = httpx.delete(
    "https://app.opvs.ai/api/v1/docs/projects/{project_id}/branches/{branch_name}",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
```

```javascript
const resp = await fetch("https://app.opvs.ai/api/v1/docs/projects/{project_id}/branches/{branch_name}", {
  method: "DELETE",
  headers: { "Authorization": "Bearer <token>" }
});
const data = await resp.json();
console.log(data);
```

```go
package main

import (
	"net/http"
)

func main() {
	req, _ := http.NewRequest("DELETE", "https://app.opvs.ai/api/v1/docs/projects/{project_id}/branches/{branch_name}", nil)
	req.Header.Set("Authorization", "Bearer <token>")
	resp, _ := http.DefaultClient.Do(req)
	defer resp.Body.Close()
}
```

**Responses**

- `200` — Successful Response
- `422` — Validation Error

## `POST` /api/v1/docs/projects/{project_id}/pages/bulk

**Api Bulk Create Pages**

Bulk create/update pages. Used by agents for multi-page writes.

**Parameters**

- `project_id` (path, string, required)

**Request body**

```bash
curl -X POST 'https://app.opvs.ai/api/v1/docs/projects/{project_id}/pages/bulk' \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '{
  "pages": [
    {
      "slug": "string",
      "title": "string",
      "path": "/",
      "content_md": "string",
      "commit_message": "Bulk update",
      "page_type": "markdown"
    }
  ],
  "branch": "main",
  "agent_context": {},
  "author_type": "string",
  "author_name": "string"
}'
```

```python
import httpx

resp = httpx.post(
    "https://app.opvs.ai/api/v1/docs/projects/{project_id}/pages/bulk",
    headers={"Authorization": "Bearer <token>", "Content-Type": "application/json"},
    json={"pages": [{"slug": "string", "title": "string", "path": "/", "content_md": "string", "commit_message": "Bulk update", "page_type": "markdown"}], "branch": "main", "agent_context": {}, "author_type": "string", "author_name": "string"},
)
resp.raise_for_status()
print(resp.json())
```

```javascript
const resp = await fetch("https://app.opvs.ai/api/v1/docs/projects/{project_id}/pages/bulk", {
  method: "POST",
  headers: { "Authorization": "Bearer <token>", "Content-Type": "application/json" },
  body: JSON.stringify({"pages": [{"slug": "string", "title": "string", "path": "/", "content_md": "string", "commit_message": "Bulk update", "page_type": "markdown"}], "branch": "main", "agent_context": {}, "author_type": "string", "author_name": "string"})
});
const data = await resp.json();
console.log(data);
```

```go
package main

import (
	"net/http"
	"strings"
)

func main() {
	body := strings.NewReader(`{"pages": [{"slug": "string", "title": "string", "path": "/", "content_md": "string", "commit_message": "Bulk update", "page_type": "markdown"}], "branch": "main", "agent_context": {}, "author_type": "string", "author_name": "string"}`)
	req, _ := http.NewRequest("POST", "https://app.opvs.ai/api/v1/docs/projects/{project_id}/pages/bulk", body)
	req.Header.Set("Authorization", "Bearer <token>")
	req.Header.Set("Content-Type", "application/json")
	resp, _ := http.DefaultClient.Do(req)
	defer resp.Body.Close()
}
```

**Responses**

- `200` — Successful Response
- `422` — Validation Error

## `GET` /api/v1/docs/tokens

**Api List Tokens**

List all access tokens for the brand. Brand admin only.

```bash
curl -X GET 'https://app.opvs.ai/api/v1/docs/tokens' \
  -H 'Authorization: Bearer <token>'
```

```python
import httpx

resp = httpx.get(
    "https://app.opvs.ai/api/v1/docs/tokens",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
```

```javascript
const resp = await fetch("https://app.opvs.ai/api/v1/docs/tokens", {
  method: "GET",
  headers: { "Authorization": "Bearer <token>" }
});
const data = await resp.json();
console.log(data);
```

```go
package main

import (
	"net/http"
)

func main() {
	req, _ := http.NewRequest("GET", "https://app.opvs.ai/api/v1/docs/tokens", nil)
	req.Header.Set("Authorization", "Bearer <token>")
	resp, _ := http.DefaultClient.Do(req)
	defer resp.Body.Close()
}
```

**Responses**

- `200` — Successful Response

## `POST` /api/v1/docs/tokens

**Api Create Token**

Create a new access token. Returns the full token once (never again). Brand admin only.

**Request body**

```bash
curl -X POST 'https://app.opvs.ai/api/v1/docs/tokens' \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '{
  "name": "string",
  "permissions": {},
  "project_ids": [
    "string"
  ],
  "expires_at": "2026-01-01T00:00:00Z"
}'
```

```python
import httpx

resp = httpx.post(
    "https://app.opvs.ai/api/v1/docs/tokens",
    headers={"Authorization": "Bearer <token>", "Content-Type": "application/json"},
    json={"name": "string", "permissions": {}, "project_ids": ["string"], "expires_at": "2026-01-01T00:00:00Z"},
)
resp.raise_for_status()
print(resp.json())
```

```javascript
const resp = await fetch("https://app.opvs.ai/api/v1/docs/tokens", {
  method: "POST",
  headers: { "Authorization": "Bearer <token>", "Content-Type": "application/json" },
  body: JSON.stringify({"name": "string", "permissions": {}, "project_ids": ["string"], "expires_at": "2026-01-01T00:00:00Z"})
});
const data = await resp.json();
console.log(data);
```

```go
package main

import (
	"net/http"
	"strings"
)

func main() {
	body := strings.NewReader(`{"name": "string", "permissions": {}, "project_ids": ["string"], "expires_at": "2026-01-01T00:00:00Z"}`)
	req, _ := http.NewRequest("POST", "https://app.opvs.ai/api/v1/docs/tokens", body)
	req.Header.Set("Authorization", "Bearer <token>")
	req.Header.Set("Content-Type", "application/json")
	resp, _ := http.DefaultClient.Do(req)
	defer resp.Body.Close()
}
```

**Responses**

- `201` — Successful Response
- `422` — Validation Error

## `PATCH` /api/v1/docs/tokens/{token_id}

**Api Update Token**

Update token permissions or status. Brand admin only.

**Parameters**

- `token_id` (path, string, required)

**Request body**

```bash
curl -X PATCH 'https://app.opvs.ai/api/v1/docs/tokens/{token_id}' \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '{
  "name": "string",
  "permissions": {},
  "project_ids": [
    "string"
  ],
  "is_active": true
}'
```

```python
import httpx

resp = httpx.patch(
    "https://app.opvs.ai/api/v1/docs/tokens/{token_id}",
    headers={"Authorization": "Bearer <token>", "Content-Type": "application/json"},
    json={"name": "string", "permissions": {}, "project_ids": ["string"], "is_active": true},
)
resp.raise_for_status()
print(resp.json())
```

```javascript
const resp = await fetch("https://app.opvs.ai/api/v1/docs/tokens/{token_id}", {
  method: "PATCH",
  headers: { "Authorization": "Bearer <token>", "Content-Type": "application/json" },
  body: JSON.stringify({"name": "string", "permissions": {}, "project_ids": ["string"], "is_active": true})
});
const data = await resp.json();
console.log(data);
```

```go
package main

import (
	"net/http"
	"strings"
)

func main() {
	body := strings.NewReader(`{"name": "string", "permissions": {}, "project_ids": ["string"], "is_active": true}`)
	req, _ := http.NewRequest("PATCH", "https://app.opvs.ai/api/v1/docs/tokens/{token_id}", body)
	req.Header.Set("Authorization", "Bearer <token>")
	req.Header.Set("Content-Type", "application/json")
	resp, _ := http.DefaultClient.Do(req)
	defer resp.Body.Close()
}
```

**Responses**

- `200` — Successful Response
- `422` — Validation Error

## `DELETE` /api/v1/docs/tokens/{token_id}

**Api Revoke Token**

Revoke an access token. Brand admin only.

**Parameters**

- `token_id` (path, string, required)

```bash
curl -X DELETE 'https://app.opvs.ai/api/v1/docs/tokens/{token_id}' \
  -H 'Authorization: Bearer <token>'
```

```python
import httpx

resp = httpx.delete(
    "https://app.opvs.ai/api/v1/docs/tokens/{token_id}",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
```

```javascript
const resp = await fetch("https://app.opvs.ai/api/v1/docs/tokens/{token_id}", {
  method: "DELETE",
  headers: { "Authorization": "Bearer <token>" }
});
const data = await resp.json();
console.log(data);
```

```go
package main

import (
	"net/http"
)

func main() {
	req, _ := http.NewRequest("DELETE", "https://app.opvs.ai/api/v1/docs/tokens/{token_id}", nil)
	req.Header.Set("Authorization", "Bearer <token>")
	resp, _ := http.DefaultClient.Do(req)
	defer resp.Body.Close()
}
```

**Responses**

- `200` — Successful Response
- `422` — Validation Error

## `GET` /api/v1/docs/projects/{project_id}/export

**Api Export Project**

Export all project pages as a ZIP of markdown files.

**Parameters**

- `project_id` (path, string, required)

```bash
curl -X GET 'https://app.opvs.ai/api/v1/docs/projects/{project_id}/export' \
  -H 'Authorization: Bearer <token>'
```

```python
import httpx

resp = httpx.get(
    "https://app.opvs.ai/api/v1/docs/projects/{project_id}/export",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
```

```javascript
const resp = await fetch("https://app.opvs.ai/api/v1/docs/projects/{project_id}/export", {
  method: "GET",
  headers: { "Authorization": "Bearer <token>" }
});
const data = await resp.json();
console.log(data);
```

```go
package main

import (
	"net/http"
)

func main() {
	req, _ := http.NewRequest("GET", "https://app.opvs.ai/api/v1/docs/projects/{project_id}/export", nil)
	req.Header.Set("Authorization", "Bearer <token>")
	resp, _ := http.DefaultClient.Do(req)
	defer resp.Body.Close()
}
```

**Responses**

- `200` — Successful Response
- `422` — Validation Error

## `GET` /api/v1/docs/webhooks

**Api List Webhooks**

List webhooks for the brand. Brand admin only.

**Parameters**

- `project_id` (query, any, optional)

```bash
curl -X GET 'https://app.opvs.ai/api/v1/docs/webhooks' \
  -H 'Authorization: Bearer <token>'
```

```python
import httpx

resp = httpx.get(
    "https://app.opvs.ai/api/v1/docs/webhooks",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
```

```javascript
const resp = await fetch("https://app.opvs.ai/api/v1/docs/webhooks", {
  method: "GET",
  headers: { "Authorization": "Bearer <token>" }
});
const data = await resp.json();
console.log(data);
```

```go
package main

import (
	"net/http"
)

func main() {
	req, _ := http.NewRequest("GET", "https://app.opvs.ai/api/v1/docs/webhooks", nil)
	req.Header.Set("Authorization", "Bearer <token>")
	resp, _ := http.DefaultClient.Do(req)
	defer resp.Body.Close()
}
```

**Responses**

- `200` — Successful Response
- `422` — Validation Error

## `POST` /api/v1/docs/webhooks

**Api Create Webhook**

Create a webhook endpoint. Brand admin only.

**Request body**

```bash
curl -X POST 'https://app.opvs.ai/api/v1/docs/webhooks' \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '{
  "url": "string",
  "project_id": "string",
  "events": [
    "string"
  ]
}'
```

```python
import httpx

resp = httpx.post(
    "https://app.opvs.ai/api/v1/docs/webhooks",
    headers={"Authorization": "Bearer <token>", "Content-Type": "application/json"},
    json={"url": "string", "project_id": "string", "events": ["string"]},
)
resp.raise_for_status()
print(resp.json())
```

```javascript
const resp = await fetch("https://app.opvs.ai/api/v1/docs/webhooks", {
  method: "POST",
  headers: { "Authorization": "Bearer <token>", "Content-Type": "application/json" },
  body: JSON.stringify({"url": "string", "project_id": "string", "events": ["string"]})
});
const data = await resp.json();
console.log(data);
```

```go
package main

import (
	"net/http"
	"strings"
)

func main() {
	body := strings.NewReader(`{"url": "string", "project_id": "string", "events": ["string"]}`)
	req, _ := http.NewRequest("POST", "https://app.opvs.ai/api/v1/docs/webhooks", body)
	req.Header.Set("Authorization", "Bearer <token>")
	req.Header.Set("Content-Type", "application/json")
	resp, _ := http.DefaultClient.Do(req)
	defer resp.Body.Close()
}
```

**Responses**

- `201` — Successful Response
- `422` — Validation Error

## `DELETE` /api/v1/docs/webhooks/{webhook_id}

**Api Delete Webhook**

Delete a webhook. Brand admin only.

**Parameters**

- `webhook_id` (path, string, required)

```bash
curl -X DELETE 'https://app.opvs.ai/api/v1/docs/webhooks/{webhook_id}' \
  -H 'Authorization: Bearer <token>'
```

```python
import httpx

resp = httpx.delete(
    "https://app.opvs.ai/api/v1/docs/webhooks/{webhook_id}",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
```

```javascript
const resp = await fetch("https://app.opvs.ai/api/v1/docs/webhooks/{webhook_id}", {
  method: "DELETE",
  headers: { "Authorization": "Bearer <token>" }
});
const data = await resp.json();
console.log(data);
```

```go
package main

import (
	"net/http"
)

func main() {
	req, _ := http.NewRequest("DELETE", "https://app.opvs.ai/api/v1/docs/webhooks/{webhook_id}", nil)
	req.Header.Set("Authorization", "Bearer <token>")
	resp, _ := http.DefaultClient.Do(req)
	defer resp.Body.Close()
}
```

**Responses**

- `200` — Successful Response
- `422` — Validation Error

## `GET` /api/v1/docs/templates

**Api List Templates**

List available page templates (system + brand-specific).

```bash
curl -X GET 'https://app.opvs.ai/api/v1/docs/templates' \
  -H 'Authorization: Bearer <token>'
```

```python
import httpx

resp = httpx.get(
    "https://app.opvs.ai/api/v1/docs/templates",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
```

```javascript
const resp = await fetch("https://app.opvs.ai/api/v1/docs/templates", {
  method: "GET",
  headers: { "Authorization": "Bearer <token>" }
});
const data = await resp.json();
console.log(data);
```

```go
package main

import (
	"net/http"
)

func main() {
	req, _ := http.NewRequest("GET", "https://app.opvs.ai/api/v1/docs/templates", nil)
	req.Header.Set("Authorization", "Bearer <token>")
	resp, _ := http.DefaultClient.Do(req)
	defer resp.Body.Close()
}
```

**Responses**

- `200` — Successful Response

## `POST` /api/v1/docs/templates

**Api Create Template**

Create a brand-specific page template. Brand admin only.

**Request body**

```bash
curl -X POST 'https://app.opvs.ai/api/v1/docs/templates' \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '{
  "name": "string",
  "description": "string",
  "content_md": "string",
  "page_type": "markdown"
}'
```

```python
import httpx

resp = httpx.post(
    "https://app.opvs.ai/api/v1/docs/templates",
    headers={"Authorization": "Bearer <token>", "Content-Type": "application/json"},
    json={"name": "string", "description": "string", "content_md": "string", "page_type": "markdown"},
)
resp.raise_for_status()
print(resp.json())
```

```javascript
const resp = await fetch("https://app.opvs.ai/api/v1/docs/templates", {
  method: "POST",
  headers: { "Authorization": "Bearer <token>", "Content-Type": "application/json" },
  body: JSON.stringify({"name": "string", "description": "string", "content_md": "string", "page_type": "markdown"})
});
const data = await resp.json();
console.log(data);
```

```go
package main

import (
	"net/http"
	"strings"
)

func main() {
	body := strings.NewReader(`{"name": "string", "description": "string", "content_md": "string", "page_type": "markdown"}`)
	req, _ := http.NewRequest("POST", "https://app.opvs.ai/api/v1/docs/templates", body)
	req.Header.Set("Authorization", "Bearer <token>")
	req.Header.Set("Content-Type", "application/json")
	resp, _ := http.DefaultClient.Do(req)
	defer resp.Body.Close()
}
```

**Responses**

- `201` — Successful Response
- `422` — Validation Error

## `DELETE` /api/v1/docs/templates/{template_id}

**Api Delete Template**

Delete a brand-specific template. Cannot delete system templates. Brand admin only.

**Parameters**

- `template_id` (path, string, required)

```bash
curl -X DELETE 'https://app.opvs.ai/api/v1/docs/templates/{template_id}' \
  -H 'Authorization: Bearer <token>'
```

```python
import httpx

resp = httpx.delete(
    "https://app.opvs.ai/api/v1/docs/templates/{template_id}",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
```

```javascript
const resp = await fetch("https://app.opvs.ai/api/v1/docs/templates/{template_id}", {
  method: "DELETE",
  headers: { "Authorization": "Bearer <token>" }
});
const data = await resp.json();
console.log(data);
```

```go
package main

import (
	"net/http"
)

func main() {
	req, _ := http.NewRequest("DELETE", "https://app.opvs.ai/api/v1/docs/templates/{template_id}", nil)
	req.Header.Set("Authorization", "Bearer <token>")
	resp, _ := http.DefaultClient.Do(req)
	defer resp.Body.Close()
}
```

**Responses**

- `200` — Successful Response
- `422` — Validation Error

## `GET` /api/v1/docs/projects/{project_id}/members

**Api List Project Members**

List members of a project.

**Parameters**

- `project_id` (path, string, required)

```bash
curl -X GET 'https://app.opvs.ai/api/v1/docs/projects/{project_id}/members' \
  -H 'Authorization: Bearer <token>'
```

```python
import httpx

resp = httpx.get(
    "https://app.opvs.ai/api/v1/docs/projects/{project_id}/members",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
```

```javascript
const resp = await fetch("https://app.opvs.ai/api/v1/docs/projects/{project_id}/members", {
  method: "GET",
  headers: { "Authorization": "Bearer <token>" }
});
const data = await resp.json();
console.log(data);
```

```go
package main

import (
	"net/http"
)

func main() {
	req, _ := http.NewRequest("GET", "https://app.opvs.ai/api/v1/docs/projects/{project_id}/members", nil)
	req.Header.Set("Authorization", "Bearer <token>")
	resp, _ := http.DefaultClient.Do(req)
	defer resp.Body.Close()
}
```

**Responses**

- `200` — Successful Response
- `422` — Validation Error

## `POST` /api/v1/docs/projects/{project_id}/members

**Api Add Project Member**

Add a member (user or agent) to a project. Brand admin only.

**Parameters**

- `project_id` (path, string, required)

**Request body**

```bash
curl -X POST 'https://app.opvs.ai/api/v1/docs/projects/{project_id}/members' \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '{
  "member_type": "string",
  "member_id": "string"
}'
```

```python
import httpx

resp = httpx.post(
    "https://app.opvs.ai/api/v1/docs/projects/{project_id}/members",
    headers={"Authorization": "Bearer <token>", "Content-Type": "application/json"},
    json={"member_type": "string", "member_id": "string"},
)
resp.raise_for_status()
print(resp.json())
```

```javascript
const resp = await fetch("https://app.opvs.ai/api/v1/docs/projects/{project_id}/members", {
  method: "POST",
  headers: { "Authorization": "Bearer <token>", "Content-Type": "application/json" },
  body: JSON.stringify({"member_type": "string", "member_id": "string"})
});
const data = await resp.json();
console.log(data);
```

```go
package main

import (
	"net/http"
	"strings"
)

func main() {
	body := strings.NewReader(`{"member_type": "string", "member_id": "string"}`)
	req, _ := http.NewRequest("POST", "https://app.opvs.ai/api/v1/docs/projects/{project_id}/members", body)
	req.Header.Set("Authorization", "Bearer <token>")
	req.Header.Set("Content-Type", "application/json")
	resp, _ := http.DefaultClient.Do(req)
	defer resp.Body.Close()
}
```

**Responses**

- `201` — Successful Response
- `422` — Validation Error

## `DELETE` /api/v1/docs/projects/{project_id}/members/{member_type}/{member_id}

**Api Remove Project Member**

Remove a member from a project. Brand admin only.

**Parameters**

- `member_type` (path, string, required)
- `member_id` (path, string, required)
- `project_id` (path, string, required)

```bash
curl -X DELETE 'https://app.opvs.ai/api/v1/docs/projects/{project_id}/members/{member_type}/{member_id}' \
  -H 'Authorization: Bearer <token>'
```

```python
import httpx

resp = httpx.delete(
    "https://app.opvs.ai/api/v1/docs/projects/{project_id}/members/{member_type}/{member_id}",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
```

```javascript
const resp = await fetch("https://app.opvs.ai/api/v1/docs/projects/{project_id}/members/{member_type}/{member_id}", {
  method: "DELETE",
  headers: { "Authorization": "Bearer <token>" }
});
const data = await resp.json();
console.log(data);
```

```go
package main

import (
	"net/http"
)

func main() {
	req, _ := http.NewRequest("DELETE", "https://app.opvs.ai/api/v1/docs/projects/{project_id}/members/{member_type}/{member_id}", nil)
	req.Header.Set("Authorization", "Bearer <token>")
	resp, _ := http.DefaultClient.Do(req)
	defer resp.Body.Close()
}
```

**Responses**

- `200` — Successful Response
- `422` — Validation Error

## `PATCH` /api/v1/docs/projects/{project_id}/visibility

**Api Update Visibility**

Update project visibility. Automatically manages members on transitions. Brand admin only.

**Parameters**

- `project_id` (path, string, required)

**Request body**

```bash
curl -X PATCH 'https://app.opvs.ai/api/v1/docs/projects/{project_id}/visibility' \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '{
  "visibility": "string"
}'
```

```python
import httpx

resp = httpx.patch(
    "https://app.opvs.ai/api/v1/docs/projects/{project_id}/visibility",
    headers={"Authorization": "Bearer <token>", "Content-Type": "application/json"},
    json={"visibility": "string"},
)
resp.raise_for_status()
print(resp.json())
```

```javascript
const resp = await fetch("https://app.opvs.ai/api/v1/docs/projects/{project_id}/visibility", {
  method: "PATCH",
  headers: { "Authorization": "Bearer <token>", "Content-Type": "application/json" },
  body: JSON.stringify({"visibility": "string"})
});
const data = await resp.json();
console.log(data);
```

```go
package main

import (
	"net/http"
	"strings"
)

func main() {
	body := strings.NewReader(`{"visibility": "string"}`)
	req, _ := http.NewRequest("PATCH", "https://app.opvs.ai/api/v1/docs/projects/{project_id}/visibility", body)
	req.Header.Set("Authorization", "Bearer <token>")
	req.Header.Set("Content-Type", "application/json")
	resp, _ := http.DefaultClient.Do(req)
	defer resp.Body.Close()
}
```

**Responses**

- `200` — Successful Response
- `422` — Validation Error

## `PATCH` /api/v1/docs/projects/{project_id}/pages/{slug}/visibility

**Api Update Page Visibility**

Update a single page's visibility (public/private). Brand admin only.

**Parameters**

- `slug` (path, string, required)
- `project_id` (path, string, required)

**Request body**

```bash
curl -X PATCH 'https://app.opvs.ai/api/v1/docs/projects/{project_id}/pages/{slug}/visibility' \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '{
  "visibility": "string"
}'
```

```python
import httpx

resp = httpx.patch(
    "https://app.opvs.ai/api/v1/docs/projects/{project_id}/pages/{slug}/visibility",
    headers={"Authorization": "Bearer <token>", "Content-Type": "application/json"},
    json={"visibility": "string"},
)
resp.raise_for_status()
print(resp.json())
```

```javascript
const resp = await fetch("https://app.opvs.ai/api/v1/docs/projects/{project_id}/pages/{slug}/visibility", {
  method: "PATCH",
  headers: { "Authorization": "Bearer <token>", "Content-Type": "application/json" },
  body: JSON.stringify({"visibility": "string"})
});
const data = await resp.json();
console.log(data);
```

```go
package main

import (
	"net/http"
	"strings"
)

func main() {
	body := strings.NewReader(`{"visibility": "string"}`)
	req, _ := http.NewRequest("PATCH", "https://app.opvs.ai/api/v1/docs/projects/{project_id}/pages/{slug}/visibility", body)
	req.Header.Set("Authorization", "Bearer <token>")
	req.Header.Set("Content-Type", "application/json")
	resp, _ := http.DefaultClient.Do(req)
	defer resp.Body.Close()
}
```

**Responses**

- `200` — Successful Response
- `422` — Validation Error

## `PATCH` /api/v1/docs/projects/{project_id}/pages-visibility

**Api Bulk Update Page Visibility**

Bulk update visibility for multiple pages. Brand admin only.

**Parameters**

- `project_id` (path, string, required)

**Request body**

```bash
curl -X PATCH 'https://app.opvs.ai/api/v1/docs/projects/{project_id}/pages-visibility' \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '{
  "page_ids": [
    "string"
  ],
  "visibility": "string"
}'
```

```python
import httpx

resp = httpx.patch(
    "https://app.opvs.ai/api/v1/docs/projects/{project_id}/pages-visibility",
    headers={"Authorization": "Bearer <token>", "Content-Type": "application/json"},
    json={"page_ids": ["string"], "visibility": "string"},
)
resp.raise_for_status()
print(resp.json())
```

```javascript
const resp = await fetch("https://app.opvs.ai/api/v1/docs/projects/{project_id}/pages-visibility", {
  method: "PATCH",
  headers: { "Authorization": "Bearer <token>", "Content-Type": "application/json" },
  body: JSON.stringify({"page_ids": ["string"], "visibility": "string"})
});
const data = await resp.json();
console.log(data);
```

```go
package main

import (
	"net/http"
	"strings"
)

func main() {
	body := strings.NewReader(`{"page_ids": ["string"], "visibility": "string"}`)
	req, _ := http.NewRequest("PATCH", "https://app.opvs.ai/api/v1/docs/projects/{project_id}/pages-visibility", body)
	req.Header.Set("Authorization", "Bearer <token>")
	req.Header.Set("Content-Type", "application/json")
	resp, _ := http.DefaultClient.Do(req)
	defer resp.Body.Close()
}
```

**Responses**

- `200` — Successful Response
- `422` — Validation Error

## `GET` /api/v1/docs/projects/{project_id}/view

**Api Project View**

Full project overview in agent-readable format (markdown, YAML, or JSON).

**Parameters**

- `project_id` (path, string, required)
- `format` (query, string, optional)
- `include_content` (query, boolean, optional)

```bash
curl -X GET 'https://app.opvs.ai/api/v1/docs/projects/{project_id}/view' \
  -H 'Authorization: Bearer <token>'
```

```python
import httpx

resp = httpx.get(
    "https://app.opvs.ai/api/v1/docs/projects/{project_id}/view",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
```

```javascript
const resp = await fetch("https://app.opvs.ai/api/v1/docs/projects/{project_id}/view", {
  method: "GET",
  headers: { "Authorization": "Bearer <token>" }
});
const data = await resp.json();
console.log(data);
```

```go
package main

import (
	"net/http"
)

func main() {
	req, _ := http.NewRequest("GET", "https://app.opvs.ai/api/v1/docs/projects/{project_id}/view", nil)
	req.Header.Set("Authorization", "Bearer <token>")
	resp, _ := http.DefaultClient.Do(req)
	defer resp.Body.Close()
}
```

**Responses**

- `200` — Successful Response
- `422` — Validation Error

## `GET` /api/v1/docs/projects/{project_id}/page-view/{slug}

**Api Page View**

Single page with content in agent-readable format.

**Parameters**

- `slug` (path, string, required)
- `project_id` (path, string, required)
- `format` (query, string, optional)
- `include_history` (query, boolean, optional)

```bash
curl -X GET 'https://app.opvs.ai/api/v1/docs/projects/{project_id}/page-view/{slug}' \
  -H 'Authorization: Bearer <token>'
```

```python
import httpx

resp = httpx.get(
    "https://app.opvs.ai/api/v1/docs/projects/{project_id}/page-view/{slug}",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
```

```javascript
const resp = await fetch("https://app.opvs.ai/api/v1/docs/projects/{project_id}/page-view/{slug}", {
  method: "GET",
  headers: { "Authorization": "Bearer <token>" }
});
const data = await resp.json();
console.log(data);
```

```go
package main

import (
	"net/http"
)

func main() {
	req, _ := http.NewRequest("GET", "https://app.opvs.ai/api/v1/docs/projects/{project_id}/page-view/{slug}", nil)
	req.Header.Set("Authorization", "Bearer <token>")
	resp, _ := http.DefaultClient.Do(req)
	defer resp.Body.Close()
}
```

**Responses**

- `200` — Successful Response
- `422` — Validation Error

## `GET` /api/v1/docs/search/view

**Api Search View**

Search results in agent-readable format.

**Parameters**

- `q` (query, string, required)
- `project_id` (query, any, optional)
- `format` (query, string, optional)
- `limit` (query, integer, optional)

```bash
curl -X GET 'https://app.opvs.ai/api/v1/docs/search/view' \
  -H 'Authorization: Bearer <token>'
```

```python
import httpx

resp = httpx.get(
    "https://app.opvs.ai/api/v1/docs/search/view",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
```

```javascript
const resp = await fetch("https://app.opvs.ai/api/v1/docs/search/view", {
  method: "GET",
  headers: { "Authorization": "Bearer <token>" }
});
const data = await resp.json();
console.log(data);
```

```go
package main

import (
	"net/http"
)

func main() {
	req, _ := http.NewRequest("GET", "https://app.opvs.ai/api/v1/docs/search/view", nil)
	req.Header.Set("Authorization", "Bearer <token>")
	resp, _ := http.DefaultClient.Do(req)
	defer resp.Body.Close()
}
```

**Responses**

- `200` — Successful Response
- `422` — Validation Error

## `GET` /api/v1/docs/projects/{project_id}/graph

**Api Get Docs Graph**

Return pages + saved node positions + cross-references for Knowledge Canvas.

**Parameters**

- `project_id` (path, string, required)

```bash
curl -X GET 'https://app.opvs.ai/api/v1/docs/projects/{project_id}/graph' \
  -H 'Authorization: Bearer <token>'
```

```python
import httpx

resp = httpx.get(
    "https://app.opvs.ai/api/v1/docs/projects/{project_id}/graph",
    headers={"Authorization": "Bearer <token>"},
)
resp.raise_for_status()
print(resp.json())
```

```javascript
const resp = await fetch("https://app.opvs.ai/api/v1/docs/projects/{project_id}/graph", {
  method: "GET",
  headers: { "Authorization": "Bearer <token>" }
});
const data = await resp.json();
console.log(data);
```

```go
package main

import (
	"net/http"
)

func main() {
	req, _ := http.NewRequest("GET", "https://app.opvs.ai/api/v1/docs/projects/{project_id}/graph", nil)
	req.Header.Set("Authorization", "Bearer <token>")
	resp, _ := http.DefaultClient.Do(req)
	defer resp.Body.Close()
}
```

**Responses**

- `200` — Successful Response
- `422` — Validation Error

## `PUT` /api/v1/docs/projects/{project_id}/graph/positions

**Api Save Docs Positions**

Save per-user node positions for Knowledge Canvas.

**Parameters**

- `project_id` (path, string, required)

**Request body**

```bash
curl -X PUT 'https://app.opvs.ai/api/v1/docs/projects/{project_id}/graph/positions' \
  -H 'Authorization: Bearer <token>' \
  -H 'Content-Type: application/json' \
  -d '{}'
```

```python
import httpx

resp = httpx.put(
    "https://app.opvs.ai/api/v1/docs/projects/{project_id}/graph/positions",
    headers={"Authorization": "Bearer <token>", "Content-Type": "application/json"},
    json={},
)
resp.raise_for_status()
print(resp.json())
```

```javascript
const resp = await fetch("https://app.opvs.ai/api/v1/docs/projects/{project_id}/graph/positions", {
  method: "PUT",
  headers: { "Authorization": "Bearer <token>", "Content-Type": "application/json" },
  body: JSON.stringify({})
});
const data = await resp.json();
console.log(data);
```

```go
package main

import (
	"net/http"
	"strings"
)

func main() {
	body := strings.NewReader(`{}`)
	req, _ := http.NewRequest("PUT", "https://app.opvs.ai/api/v1/docs/projects/{project_id}/graph/positions", body)
	req.Header.Set("Authorization", "Bearer <token>")
	req.Header.Set("Content-Type", "application/json")
	resp, _ := http.DefaultClient.Do(req)
	defer resp.Body.Close()
}
```

**Responses**

- `200` — Successful Response
- `422` — Validation Error

## Api List Projects

`GET https://app.opvs.ai/api/v1/docs/projects`

List documentation projects for the current brand.

| Code | When | What to do |
| --- | --- | --- |
| 422 | Validation Error |  |

## Api Create Project

`POST https://app.opvs.ai/api/v1/docs/projects`

Create a new documentation project.

| Code | When | What to do |
| --- | --- | --- |
| 422 | Validation Error |  |

## Api Get Project

`GET https://app.opvs.ai/api/v1/docs/projects/{project_id}`

Get a documentation project with page count.

| Code | When | What to do |
| --- | --- | --- |
| 422 | Validation Error |  |

## Api Update Project

`PATCH https://app.opvs.ai/api/v1/docs/projects/{project_id}`

Update a documentation project. Brand admin only.

| Code | When | What to do |
| --- | --- | --- |
| 422 | Validation Error |  |

## Api Delete Project

`DELETE https://app.opvs.ai/api/v1/docs/projects/{project_id}`

Soft-delete a documentation project. Brand admin only.

| Code | When | What to do |
| --- | --- | --- |
| 422 | Validation Error |  |

## Api List Pages

`GET https://app.opvs.ai/api/v1/docs/projects/{project_id}/pages`

List pages in a project. Use view=tree for nested structure.

| Code | When | What to do |
| --- | --- | --- |
| 422 | Validation Error |  |

## Api Create Page

`POST https://app.opvs.ai/api/v1/docs/projects/{project_id}/pages`

Create a new page with initial content (first revision).

| Code | When | What to do |
| --- | --- | --- |
| 422 | Validation Error |  |

## Api Get Page

`GET https://app.opvs.ai/api/v1/docs/projects/{project_id}/pages/{slug}`

Get a page with its current content.

| Code | When | What to do |
| --- | --- | --- |
| 422 | Validation Error |  |

## Api Update Page

`PUT https://app.opvs.ai/api/v1/docs/projects/{project_id}/pages/{slug}`

Update a page (creates a new revision). Deduplicates identical content.

| Code | When | What to do |
| --- | --- | --- |
| 422 | Validation Error |  |

## Api Delete Page

`DELETE https://app.opvs.ai/api/v1/docs/projects/{project_id}/pages/{slug}`

Soft-delete a page.

| Code | When | What to do |
| --- | --- | --- |
| 422 | Validation Error |  |

## Api Move Page

`PATCH https://app.opvs.ai/api/v1/docs/projects/{project_id}/pages/{slug}/move`

Move a page to a new path or change sort order. Does not create a revision.

| Code | When | What to do |
| --- | --- | --- |
| 422 | Validation Error |  |

## Api Get Revision History

`GET https://app.opvs.ai/api/v1/docs/pages/{page_id}/history`

Get revision history for a page.

| Code | When | What to do |
| --- | --- | --- |
| 422 | Validation Error |  |

## Api Get Revision

`GET https://app.opvs.ai/api/v1/docs/revisions/{revision_id}`

Get a specific revision with full content.

| Code | When | What to do |
| --- | --- | --- |
| 422 | Validation Error |  |

## Api Compute Diff

`GET https://app.opvs.ai/api/v1/docs/pages/{page_id}/diff`

Compute unified diff between two revisions. Omit 'from' for parent comparison.

| Code | When | What to do |
| --- | --- | --- |
| 422 | Validation Error |  |

## Api Rollback

`POST https://app.opvs.ai/api/v1/docs/pages/{page_id}/rollback`

Rollback a page to a previous revision. Creates a new (non-destructive) revision.

| Code | When | What to do |
| --- | --- | --- |
| 422 | Validation Error |  |

## Api List Media

`GET https://app.opvs.ai/api/v1/docs/projects/{project_id}/media`

List media files in a project.

| Code | When | What to do |
| --- | --- | --- |
| 422 | Validation Error |  |

## Api Upload Media

`POST https://app.opvs.ai/api/v1/docs/projects/{project_id}/media`

Upload a media file (image, PDF, etc.) to R2 storage.

| Code | When | What to do |
| --- | --- | --- |
| 422 | Validation Error |  |

## Api List Recent Pages

`GET https://app.opvs.ai/api/v1/docs/recent-pages`

List the most recently updated pages across every project in the brand.

| Code | When | What to do |
| --- | --- | --- |
| 422 | Validation Error |  |

## Api Search

`GET https://app.opvs.ai/api/v1/docs/search`

Full-text search across all pages in the brand's documentation.

| Code | When | What to do |
| --- | --- | --- |
| 422 | Validation Error |  |

## Api List Branches

`GET https://app.opvs.ai/api/v1/docs/projects/{project_id}/branches`

List branches for a project.

| Code | When | What to do |
| --- | --- | --- |
| 422 | Validation Error |  |

## Api Create Branch

`POST https://app.opvs.ai/api/v1/docs/projects/{project_id}/branches`

Create a new branch for draft/review workflows.

| Code | When | What to do |
| --- | --- | --- |
| 422 | Validation Error |  |

## Api Branch Diff

`GET https://app.opvs.ai/api/v1/docs/projects/{project_id}/branches/{branch_name}/diff`

Get diff summary for a branch compared to main.

| Code | When | What to do |
| --- | --- | --- |
| 422 | Validation Error |  |

## Api Merge Branch

`POST https://app.opvs.ai/api/v1/docs/projects/{project_id}/branches/{branch_name}/merge`

Merge a branch into main. Creates new revisions for affected pages.

| Code | When | What to do |
| --- | --- | --- |
| 422 | Validation Error |  |

## Api Close Branch

`DELETE https://app.opvs.ai/api/v1/docs/projects/{project_id}/branches/{branch_name}`

Close a branch without merging.

| Code | When | What to do |
| --- | --- | --- |
| 422 | Validation Error |  |

## Api Bulk Create Pages

`POST https://app.opvs.ai/api/v1/docs/projects/{project_id}/pages/bulk`

Bulk create/update pages. Used by agents for multi-page writes.

| Code | When | What to do |
| --- | --- | --- |
| 422 | Validation Error |  |

## Api List Tokens

`GET https://app.opvs.ai/api/v1/docs/tokens`

List all access tokens for the brand. Brand admin only.

## Api Create Token

`POST https://app.opvs.ai/api/v1/docs/tokens`

Create a new access token. Returns the full token once (never again). Brand admin only.

| Code | When | What to do |
| --- | --- | --- |
| 422 | Validation Error |  |

## Api Update Token

`PATCH https://app.opvs.ai/api/v1/docs/tokens/{token_id}`

Update token permissions or status. Brand admin only.

| Code | When | What to do |
| --- | --- | --- |
| 422 | Validation Error |  |

## Api Revoke Token

`DELETE https://app.opvs.ai/api/v1/docs/tokens/{token_id}`

Revoke an access token. Brand admin only.

| Code | When | What to do |
| --- | --- | --- |
| 422 | Validation Error |  |

## Api Export Project

`GET https://app.opvs.ai/api/v1/docs/projects/{project_id}/export`

Export all project pages as a ZIP of markdown files.

| Code | When | What to do |
| --- | --- | --- |
| 422 | Validation Error |  |

## Api List Webhooks

`GET https://app.opvs.ai/api/v1/docs/webhooks`

List webhooks for the brand. Brand admin only.

| Code | When | What to do |
| --- | --- | --- |
| 422 | Validation Error |  |

## Api Create Webhook

`POST https://app.opvs.ai/api/v1/docs/webhooks`

Create a webhook endpoint. Brand admin only.

| Code | When | What to do |
| --- | --- | --- |
| 422 | Validation Error |  |

## Api Delete Webhook

`DELETE https://app.opvs.ai/api/v1/docs/webhooks/{webhook_id}`

Delete a webhook. Brand admin only.

| Code | When | What to do |
| --- | --- | --- |
| 422 | Validation Error |  |

## Api List Templates

`GET https://app.opvs.ai/api/v1/docs/templates`

List available page templates (system + brand-specific).

## Api Create Template

`POST https://app.opvs.ai/api/v1/docs/templates`

Create a brand-specific page template. Brand admin only.

| Code | When | What to do |
| --- | --- | --- |
| 422 | Validation Error |  |

## Api Delete Template

`DELETE https://app.opvs.ai/api/v1/docs/templates/{template_id}`

Delete a brand-specific template. Cannot delete system templates. Brand admin only.

| Code | When | What to do |
| --- | --- | --- |
| 422 | Validation Error |  |

## Api List Project Members

`GET https://app.opvs.ai/api/v1/docs/projects/{project_id}/members`

List members of a project.

| Code | When | What to do |
| --- | --- | --- |
| 422 | Validation Error |  |

## Api Add Project Member

`POST https://app.opvs.ai/api/v1/docs/projects/{project_id}/members`

Add a member (user or agent) to a project. Brand admin only.

| Code | When | What to do |
| --- | --- | --- |
| 422 | Validation Error |  |

## Api Remove Project Member

`DELETE https://app.opvs.ai/api/v1/docs/projects/{project_id}/members/{member_type}/{member_id}`

Remove a member from a project. Brand admin only.

| Code | When | What to do |
| --- | --- | --- |
| 422 | Validation Error |  |

## Api Update Visibility

`PATCH https://app.opvs.ai/api/v1/docs/projects/{project_id}/visibility`

Update project visibility. Automatically manages members on transitions. Brand admin only.

| Code | When | What to do |
| --- | --- | --- |
| 422 | Validation Error |  |

## Api Update Page Visibility

`PATCH https://app.opvs.ai/api/v1/docs/projects/{project_id}/pages/{slug}/visibility`

Update a single page's visibility (public/private). Brand admin only.

| Code | When | What to do |
| --- | --- | --- |
| 422 | Validation Error |  |

## Api Bulk Update Page Visibility

`PATCH https://app.opvs.ai/api/v1/docs/projects/{project_id}/pages-visibility`

Bulk update visibility for multiple pages. Brand admin only.

| Code | When | What to do |
| --- | --- | --- |
| 422 | Validation Error |  |

## Api Project View

`GET https://app.opvs.ai/api/v1/docs/projects/{project_id}/view`

Full project overview in agent-readable format (markdown, YAML, or JSON).

| Code | When | What to do |
| --- | --- | --- |
| 422 | Validation Error |  |

## Api Page View

`GET https://app.opvs.ai/api/v1/docs/projects/{project_id}/page-view/{slug}`

Single page with content in agent-readable format.

| Code | When | What to do |
| --- | --- | --- |
| 422 | Validation Error |  |

## Api Search View

`GET https://app.opvs.ai/api/v1/docs/search/view`

Search results in agent-readable format.

| Code | When | What to do |
| --- | --- | --- |
| 422 | Validation Error |  |

## Api Get Docs Graph

`GET https://app.opvs.ai/api/v1/docs/projects/{project_id}/graph`

Return pages + saved node positions + cross-references for Knowledge Canvas.

| Code | When | What to do |
| --- | --- | --- |
| 422 | Validation Error |  |

## Api Save Docs Positions

`PUT https://app.opvs.ai/api/v1/docs/projects/{project_id}/graph/positions`

Save per-user node positions for Knowledge Canvas.

| Code | When | What to do |
| --- | --- | --- |
| 422 | Validation Error |  |
