Guides
- Hire an AI Employee
- Manufacture a catalog product
- System endpoints
- Format negotiation
- Read depth and cross-board reach
- Board health
- Plans & billing
- Professions (Guild Hall)
- Code index
- Memory (AgentMemory)
- Workspace settings
- Coder profiles
- Move or copy a card to another board
- Email boards
- Your repo's knowledge in AgentMemory
Reference
- API reference
- CLI reference
- MCP server
- OPVS Mail
- Board
- Board Inbox
- Board Chat
- Board Agent API
- AgentDocs
- Public Docs
- AgentMemory
- Employees
- My mail
- Calendar
- Webhooks
- Notifications
- POSTSend Email Notification
- POSTSend In App Notification
- GETGet Preferences
- GETGet Dnd
- PATCHUpdate Dnd
- PATCHUpdate Preference
- GETUnsubscribe Landing
- POSTUnsubscribe One Click
- GETGet Notification Feed
- GETList Notifications
- GETGet Unread Count
- POSTMark All Notifications Read
- POSTMark Notification Read
- GETNotification Stream
- Auth
- PAT Provisioning
- Agents
- Agent Workspace
- Agent Embed
- Org Chart
- AI Office
- Invitations
- Workflows
- Decisions
- Code Index
- Workstations
- Professions
- Integrations
- Data Sources
- Data Connectors
- Brands
- OPVS Protocol
- Marketplace Registry
- System
Factory
- How the factory works
- Set up your factory
- Fix a machine or desk that won't come up
- Fix a board that doesn't build or ship
- Machines, desks and the sidecar
- Board types and columns
- Projects and project settings
- Builders and engines
- How a card moves
- Connect GitHub
- Set a review policy
- Run your factory with the opvs skill and the agent-ops kit
- Factory CLI reference
Notifications
Send Email Notification
/api/v1/notifications/emailSend an email notification to all admins of a brand.
Errors
| Code | When | What to do |
|---|---|---|
| 422 | Validation Error | — |
curl -X POST "https://app.opvs.ai/api/v1/notifications/email" \
-H "Authorization: Bearer $OPVS_TOKEN" \
-H "Content-Type: application/json" \
-d '{}'import os
import requests
r = requests.request(
"POST",
"https://app.opvs.ai/api/v1/notifications/email",
headers={"Authorization": f"Bearer {os.environ['OPVS_TOKEN']}", "Content-Type": "application/json"},
data='{}',
)
r.raise_for_status()
print(r.json())const r = await fetch("https://app.opvs.ai/api/v1/notifications/email", {
method: "POST",
headers: { Authorization: `Bearer ${process.env.OPVS_TOKEN}`, "Content-Type": "application/json" },
body: JSON.stringify({}),
});
if (!r.ok) throw new Error(String(r.status));
console.log(await r.json());req, _ := http.NewRequest("POST", "https://app.opvs.ai/api/v1/notifications/email", strings.NewReader(`{}`))
req.Header.Set("Authorization", "Bearer "+os.Getenv("OPVS_TOKEN"))
req.Header.Set("Content-Type", "application/json")
resp, err := http.DefaultClient.Do(req)
if err != nil { log.Fatal(err) }
defer resp.Body.Close()Send In App Notification
/api/v1/notifications/in-appCreate an in-app notification for the deliverable members of a brand.
Errors
| Code | When | What to do |
|---|---|---|
| 422 | Validation Error | — |
curl -X POST "https://app.opvs.ai/api/v1/notifications/in-app" \
-H "Authorization: Bearer $OPVS_TOKEN" \
-H "Content-Type: application/json" \
-d '{}'import os
import requests
r = requests.request(
"POST",
"https://app.opvs.ai/api/v1/notifications/in-app",
headers={"Authorization": f"Bearer {os.environ['OPVS_TOKEN']}", "Content-Type": "application/json"},
data='{}',
)
r.raise_for_status()
print(r.json())const r = await fetch("https://app.opvs.ai/api/v1/notifications/in-app", {
method: "POST",
headers: { Authorization: `Bearer ${process.env.OPVS_TOKEN}`, "Content-Type": "application/json" },
body: JSON.stringify({}),
});
if (!r.ok) throw new Error(String(r.status));
console.log(await r.json());req, _ := http.NewRequest("POST", "https://app.opvs.ai/api/v1/notifications/in-app", strings.NewReader(`{}`))
req.Header.Set("Authorization", "Bearer "+os.Getenv("OPVS_TOKEN"))
req.Header.Set("Content-Type", "application/json")
resp, err := http.DefaultClient.Do(req)
if err != nil { log.Fatal(err) }
defer resp.Body.Close()Get Preferences
/api/v1/notifications/preferencesEvery catalog event with this user's effective (email, in_app, delivery) for the active brand. ?format=yaml|md for agents.
Errors
| Code | When | What to do |
|---|---|---|
| 422 | Validation Error | — |
curl "https://app.opvs.ai/api/v1/notifications/preferences" \
-H "Authorization: Bearer $OPVS_TOKEN"import os
import requests
r = requests.request(
"GET",
"https://app.opvs.ai/api/v1/notifications/preferences",
headers={"Authorization": f"Bearer {os.environ['OPVS_TOKEN']}"},
)
r.raise_for_status()
print(r.json())const r = await fetch("https://app.opvs.ai/api/v1/notifications/preferences", {
method: "GET",
headers: { Authorization: `Bearer ${process.env.OPVS_TOKEN}` },
});
if (!r.ok) throw new Error(String(r.status));
console.log(await r.json());req, _ := http.NewRequest("GET", "https://app.opvs.ai/api/v1/notifications/preferences", nil)
req.Header.Set("Authorization", "Bearer "+os.Getenv("OPVS_TOKEN"))
resp, err := http.DefaultClient.Do(req)
if err != nil { log.Fatal(err) }
defer resp.Body.Close()Get Dnd
/api/v1/notifications/preferences/dndcurl "https://app.opvs.ai/api/v1/notifications/preferences/dnd" \
-H "Authorization: Bearer $OPVS_TOKEN"import os
import requests
r = requests.request(
"GET",
"https://app.opvs.ai/api/v1/notifications/preferences/dnd",
headers={"Authorization": f"Bearer {os.environ['OPVS_TOKEN']}"},
)
r.raise_for_status()
print(r.json())const r = await fetch("https://app.opvs.ai/api/v1/notifications/preferences/dnd", {
method: "GET",
headers: { Authorization: `Bearer ${process.env.OPVS_TOKEN}` },
});
if (!r.ok) throw new Error(String(r.status));
console.log(await r.json());req, _ := http.NewRequest("GET", "https://app.opvs.ai/api/v1/notifications/preferences/dnd", nil)
req.Header.Set("Authorization", "Bearer "+os.Getenv("OPVS_TOKEN"))
resp, err := http.DefaultClient.Do(req)
if err != nil { log.Fatal(err) }
defer resp.Body.Close()Update Dnd
/api/v1/notifications/preferences/dndErrors
| Code | When | What to do |
|---|---|---|
| 422 | Validation Error | — |
curl -X PATCH "https://app.opvs.ai/api/v1/notifications/preferences/dnd" \
-H "Authorization: Bearer $OPVS_TOKEN" \
-H "Content-Type: application/json" \
-d '{}'import os
import requests
r = requests.request(
"PATCH",
"https://app.opvs.ai/api/v1/notifications/preferences/dnd",
headers={"Authorization": f"Bearer {os.environ['OPVS_TOKEN']}", "Content-Type": "application/json"},
data='{}',
)
r.raise_for_status()
print(r.json())const r = await fetch("https://app.opvs.ai/api/v1/notifications/preferences/dnd", {
method: "PATCH",
headers: { Authorization: `Bearer ${process.env.OPVS_TOKEN}`, "Content-Type": "application/json" },
body: JSON.stringify({}),
});
if (!r.ok) throw new Error(String(r.status));
console.log(await r.json());req, _ := http.NewRequest("PATCH", "https://app.opvs.ai/api/v1/notifications/preferences/dnd", strings.NewReader(`{}`))
req.Header.Set("Authorization", "Bearer "+os.Getenv("OPVS_TOKEN"))
req.Header.Set("Content-Type", "application/json")
resp, err := http.DefaultClient.Do(req)
if err != nil { log.Fatal(err) }
defer resp.Body.Close()Update Preference
/api/v1/notifications/preferences/{event_key}Toggle one event's channels/delivery for the active brand.
Errors
| Code | When | What to do |
|---|---|---|
| 422 | Validation Error | — |
curl -X PATCH "https://app.opvs.ai/api/v1/notifications/preferences/{event_key}" \
-H "Authorization: Bearer $OPVS_TOKEN" \
-H "Content-Type: application/json" \
-d '{}'import os
import requests
r = requests.request(
"PATCH",
"https://app.opvs.ai/api/v1/notifications/preferences/{event_key}",
headers={"Authorization": f"Bearer {os.environ['OPVS_TOKEN']}", "Content-Type": "application/json"},
data='{}',
)
r.raise_for_status()
print(r.json())const r = await fetch("https://app.opvs.ai/api/v1/notifications/preferences/{event_key}", {
method: "PATCH",
headers: { Authorization: `Bearer ${process.env.OPVS_TOKEN}`, "Content-Type": "application/json" },
body: JSON.stringify({}),
});
if (!r.ok) throw new Error(String(r.status));
console.log(await r.json());req, _ := http.NewRequest("PATCH", "https://app.opvs.ai/api/v1/notifications/preferences/{event_key}", strings.NewReader(`{}`))
req.Header.Set("Authorization", "Bearer "+os.Getenv("OPVS_TOKEN"))
req.Header.Set("Content-Type", "application/json")
resp, err := http.DefaultClient.Do(req)
if err != nil { log.Fatal(err) }
defer resp.Body.Close()Unsubscribe Landing
/api/v1/notifications/unsubscribeBody-link landing — applies the unsubscribe and shows a confirmation.
Errors
| Code | When | What to do |
|---|---|---|
| 422 | Validation Error | — |
curl "https://app.opvs.ai/api/v1/notifications/unsubscribe" \
-H "Authorization: Bearer $OPVS_TOKEN"import os
import requests
r = requests.request(
"GET",
"https://app.opvs.ai/api/v1/notifications/unsubscribe",
headers={"Authorization": f"Bearer {os.environ['OPVS_TOKEN']}"},
)
r.raise_for_status()
print(r.json())const r = await fetch("https://app.opvs.ai/api/v1/notifications/unsubscribe", {
method: "GET",
headers: { Authorization: `Bearer ${process.env.OPVS_TOKEN}` },
});
if (!r.ok) throw new Error(String(r.status));
console.log(await r.json());req, _ := http.NewRequest("GET", "https://app.opvs.ai/api/v1/notifications/unsubscribe", nil)
req.Header.Set("Authorization", "Bearer "+os.Getenv("OPVS_TOKEN"))
resp, err := http.DefaultClient.Do(req)
if err != nil { log.Fatal(err) }
defer resp.Body.Close()Unsubscribe One Click
/api/v1/notifications/unsubscribeRFC 8058 one-click target (the MUA POSTs here). No body required.
Errors
| Code | When | What to do |
|---|---|---|
| 422 | Validation Error | — |
curl -X POST "https://app.opvs.ai/api/v1/notifications/unsubscribe" \
-H "Authorization: Bearer $OPVS_TOKEN" \
-H "Content-Type: application/json" \
-d '{}'import os
import requests
r = requests.request(
"POST",
"https://app.opvs.ai/api/v1/notifications/unsubscribe",
headers={"Authorization": f"Bearer {os.environ['OPVS_TOKEN']}", "Content-Type": "application/json"},
data='{}',
)
r.raise_for_status()
print(r.json())const r = await fetch("https://app.opvs.ai/api/v1/notifications/unsubscribe", {
method: "POST",
headers: { Authorization: `Bearer ${process.env.OPVS_TOKEN}`, "Content-Type": "application/json" },
body: JSON.stringify({}),
});
if (!r.ok) throw new Error(String(r.status));
console.log(await r.json());req, _ := http.NewRequest("POST", "https://app.opvs.ai/api/v1/notifications/unsubscribe", strings.NewReader(`{}`))
req.Header.Set("Authorization", "Bearer "+os.Getenv("OPVS_TOKEN"))
req.Header.Set("Content-Type", "application/json")
resp, err := http.DefaultClient.Do(req)
if err != nil { log.Fatal(err) }
defer resp.Body.Close()Get Notification Feed
/api/v1/notifications/feedKeyset-paginated in-app bell feed, newest first. Pass the previous page's ``next_cursor`` back as ``cursor_created_at`` + ``cursor_id``.
Errors
| Code | When | What to do |
|---|---|---|
| 422 | Validation Error | — |
curl "https://app.opvs.ai/api/v1/notifications/feed" \
-H "Authorization: Bearer $OPVS_TOKEN"import os
import requests
r = requests.request(
"GET",
"https://app.opvs.ai/api/v1/notifications/feed",
headers={"Authorization": f"Bearer {os.environ['OPVS_TOKEN']}"},
)
r.raise_for_status()
print(r.json())const r = await fetch("https://app.opvs.ai/api/v1/notifications/feed", {
method: "GET",
headers: { Authorization: `Bearer ${process.env.OPVS_TOKEN}` },
});
if (!r.ok) throw new Error(String(r.status));
console.log(await r.json());req, _ := http.NewRequest("GET", "https://app.opvs.ai/api/v1/notifications/feed", nil)
req.Header.Set("Authorization", "Bearer "+os.Getenv("OPVS_TOKEN"))
resp, err := http.DefaultClient.Do(req)
if err != nil { log.Fatal(err) }
defer resp.Body.Close()List Notifications
/api/v1/notificationsAlias of ``GET /notifications/feed`` at the router root — a parity convenience (no existing consumer requires it; see DISCOVERY §2 E1). Returns the same keyset-paginated in-app bell feed for the (user, active brand).
Errors
| Code | When | What to do |
|---|---|---|
| 422 | Validation Error | — |
curl "https://app.opvs.ai/api/v1/notifications" \
-H "Authorization: Bearer $OPVS_TOKEN"import os
import requests
r = requests.request(
"GET",
"https://app.opvs.ai/api/v1/notifications",
headers={"Authorization": f"Bearer {os.environ['OPVS_TOKEN']}"},
)
r.raise_for_status()
print(r.json())const r = await fetch("https://app.opvs.ai/api/v1/notifications", {
method: "GET",
headers: { Authorization: `Bearer ${process.env.OPVS_TOKEN}` },
});
if (!r.ok) throw new Error(String(r.status));
console.log(await r.json());req, _ := http.NewRequest("GET", "https://app.opvs.ai/api/v1/notifications", nil)
req.Header.Set("Authorization", "Bearer "+os.Getenv("OPVS_TOKEN"))
resp, err := http.DefaultClient.Do(req)
if err != nil { log.Fatal(err) }
defer resp.Body.Close()Get Unread Count
/api/v1/notifications/unread-countCount of the user's unread in-app notifications for the active brand.
curl "https://app.opvs.ai/api/v1/notifications/unread-count" \
-H "Authorization: Bearer $OPVS_TOKEN"import os
import requests
r = requests.request(
"GET",
"https://app.opvs.ai/api/v1/notifications/unread-count",
headers={"Authorization": f"Bearer {os.environ['OPVS_TOKEN']}"},
)
r.raise_for_status()
print(r.json())const r = await fetch("https://app.opvs.ai/api/v1/notifications/unread-count", {
method: "GET",
headers: { Authorization: `Bearer ${process.env.OPVS_TOKEN}` },
});
if (!r.ok) throw new Error(String(r.status));
console.log(await r.json());req, _ := http.NewRequest("GET", "https://app.opvs.ai/api/v1/notifications/unread-count", nil)
req.Header.Set("Authorization", "Bearer "+os.Getenv("OPVS_TOKEN"))
resp, err := http.DefaultClient.Do(req)
if err != nil { log.Fatal(err) }
defer resp.Body.Close()Mark All Notifications Read
/api/v1/notifications/read-allMark every unread in-app notification for (user, brand) read.
curl -X POST "https://app.opvs.ai/api/v1/notifications/read-all" \
-H "Authorization: Bearer $OPVS_TOKEN" \
-H "Content-Type: application/json" \
-d '{}'import os
import requests
r = requests.request(
"POST",
"https://app.opvs.ai/api/v1/notifications/read-all",
headers={"Authorization": f"Bearer {os.environ['OPVS_TOKEN']}", "Content-Type": "application/json"},
data='{}',
)
r.raise_for_status()
print(r.json())const r = await fetch("https://app.opvs.ai/api/v1/notifications/read-all", {
method: "POST",
headers: { Authorization: `Bearer ${process.env.OPVS_TOKEN}`, "Content-Type": "application/json" },
body: JSON.stringify({}),
});
if (!r.ok) throw new Error(String(r.status));
console.log(await r.json());req, _ := http.NewRequest("POST", "https://app.opvs.ai/api/v1/notifications/read-all", strings.NewReader(`{}`))
req.Header.Set("Authorization", "Bearer "+os.Getenv("OPVS_TOKEN"))
req.Header.Set("Content-Type", "application/json")
resp, err := http.DefaultClient.Do(req)
if err != nil { log.Fatal(err) }
defer resp.Body.Close()Mark Notification Read
/api/v1/notifications/{notification_id}/readMark one notification read. The body carries ``created_at`` (the row's partition key) so the UPDATE prunes to a single partition (LANDMINE 5). Returns ``updated=false`` if the row isn't the caller's or was already read.
Errors
| Code | When | What to do |
|---|---|---|
| 422 | Validation Error | — |
curl -X POST "https://app.opvs.ai/api/v1/notifications/{notification_id}/read" \
-H "Authorization: Bearer $OPVS_TOKEN" \
-H "Content-Type: application/json" \
-d '{}'import os
import requests
r = requests.request(
"POST",
"https://app.opvs.ai/api/v1/notifications/{notification_id}/read",
headers={"Authorization": f"Bearer {os.environ['OPVS_TOKEN']}", "Content-Type": "application/json"},
data='{}',
)
r.raise_for_status()
print(r.json())const r = await fetch("https://app.opvs.ai/api/v1/notifications/{notification_id}/read", {
method: "POST",
headers: { Authorization: `Bearer ${process.env.OPVS_TOKEN}`, "Content-Type": "application/json" },
body: JSON.stringify({}),
});
if (!r.ok) throw new Error(String(r.status));
console.log(await r.json());req, _ := http.NewRequest("POST", "https://app.opvs.ai/api/v1/notifications/{notification_id}/read", strings.NewReader(`{}`))
req.Header.Set("Authorization", "Bearer "+os.Getenv("OPVS_TOKEN"))
req.Header.Set("Content-Type", "application/json")
resp, err := http.DefaultClient.Do(req)
if err != nil { log.Fatal(err) }
defer resp.Body.Close()Notification Stream
/api/v1/notifications/streamServer-Sent Events stream of ``notification.created`` frames for the authenticated user. The browser's EventSource sends the session cookie, so auth resolves via ``get_current_brand``. Frames are keyed PER USER and carry ``brand_id`` — the client filters to the active brand (LANDMINE 4).
curl "https://app.opvs.ai/api/v1/notifications/stream" \
-H "Authorization: Bearer $OPVS_TOKEN"import os
import requests
r = requests.request(
"GET",
"https://app.opvs.ai/api/v1/notifications/stream",
headers={"Authorization": f"Bearer {os.environ['OPVS_TOKEN']}"},
)
r.raise_for_status()
print(r.json())const r = await fetch("https://app.opvs.ai/api/v1/notifications/stream", {
method: "GET",
headers: { Authorization: `Bearer ${process.env.OPVS_TOKEN}` },
});
if (!r.ok) throw new Error(String(r.status));
console.log(await r.json());req, _ := http.NewRequest("GET", "https://app.opvs.ai/api/v1/notifications/stream", nil)
req.Header.Set("Authorization", "Bearer "+os.Getenv("OPVS_TOKEN"))
resp, err := http.DefaultClient.Do(req)
if err != nil { log.Fatal(err) }
defer resp.Body.Close()