REST API
讀取與寫入您的監控項目、讀取與更新事件,並上傳 source map。這裡的每一項都使用與儀表板相同的權限檢查,以及相同的租戶隔離過濾——API 端沒有另一套可能與它逐漸分歧的實作。
所有方案都包含,免費方案也一樣。不需要加購任何附加元件,也沒有哪個等級才解鎖它。
基礎 URL
https://vitrinaengine.com/api/v1機器可讀的描述
/openapi.json是一份 OpenAPI 3.1 文件,涵蓋本頁上的每一條路由。把用戶端產生器指向它,或是交給一個必須呼叫這個 API、而沒有人能為它逐一解說的代理。
它是從服務本身產生的,而不是寫在服務旁邊:路由來自 API 自己在 GET / 發布的介面;訊息形狀與其說明文字來自 .proto 檔案,也就是 /api/proto所列的那一批;用量限制則來自實際執行這些限制的程式碼。當提交的文件與 API 不一致時建置會失敗,因此它描述的是實際提供的內容,而不是某人上次編輯時為真的內容。
它描述的是形狀。理由寫在這一頁上——跨組織的 id 會回應 404、config 永遠不會被回傳——而這些是任何產生器都寫不出來的。
給代理使用:MCP
https://vitrinaengine.com/mcp 是一台 Model Context Protocol 伺服器。把它加進 MCP 用戶端,並以 API 金鑰作為 bearer token,代理就能讀取您的監控項目、事件、錯誤與分析資料,也能建立、修改與刪除監控項目,不需要任何人向它解釋這個 API 如何運作。
{
"mcpServers": {
"vitrina-engine": {
"type": "http",
"url": "https://vitrinaengine.com/mcp",
"headers": { "Authorization": "Bearer vte_your_key_here" }
}
}
}它讀取一切,只寫三件事。本頁上的每個 GET 操作都是一項工具,另外還有 POST /monitors、PATCH /monitors/{id} 與 DELETE /monitors/{id}。其他任何會寫入的東西都構不著——工作區、成員、API 金鑰、狀態頁、您的帳戶,一概不行——因為根本沒有對應的工具;而獲准寫入的那份清單,是要有人刻意加上去的三行。
沒有寫入權限的金鑰照樣會被拒絕。一次工具呼叫,就是該金鑰自己直接發出的同一個要求,經過同樣的權限檢查與同樣的租戶過濾,因此拿著唯讀金鑰的代理就只能讀。除非您確實要它改動您的監控,否則就給它一把唯讀金鑰——並且要預期用戶端在刪除前會先問您一聲:刪掉一個監控項目,它的歷史也會一併帶走,且無法復原。想讓監控項目安靜下來又不失去它,請用 PATCH 把它暫停。
因為是同一個要求,它看到的正是該金鑰看得到的範圍,會寫下與儀表板相同的稽核紀錄,並且計入同一個用量限制兩次——一次是這通呼叫,一次是它內含的那個要求。寫入則計入寫入的限額。
在讓代理編輯監控項目之前,有一點值得先知道:config 是整個取代,而不是合併。請先讀出該監控項目,改掉那一個欄位,再把整個物件送回去。殘缺的設定會悄悄丟掉檢查所仰賴的標頭與憑證,而檢查仍會照常執行。
驗證
請在設定 → API 金鑰底下建立一把金鑰,然後以 bearer token 的形式送出。金鑰只在建立當下顯示一次,之後僅以雜湊形式保存——若遺失,請另外建立一把。
curl https://vitrinaengine.com/api/v1/summary \
-H "Authorization: Bearer vte_your_key_here"金鑰授予的權限,永遠不會多於建立它的人原本擁有的。它繫結在該成員的身分上,因此帶著對方的角色:由唯讀角色的人建立的金鑰無法寫入,無論您送出什麼。金鑰也可以被限制在單一工作區,此時每個回應都會過濾到該工作區,而工作區以外的一切,對這把金鑰而言並不存在。
把某人從您的組織中移除時,同一個操作會一併撤銷他建立的金鑰。撤銷存取權必須連同憑證一起撤銷,否則那個人手上仍留著一把能用的。
慣例
每個成功的回應都是帶有 data 屬性的 JSON 物件。每個失敗都是帶有 error 屬性的 JSON 物件,內含一句寫給人看的話。
{ "data": { "id": "8f14e45f-…", "name": "Marketing site" } }
{ "error": "This key cannot create monitors." }回應都會帶上 Cache-Control: private, no-store。這些是共用來源上屬於個別金鑰的資料,絕不該被任何代理伺服器保留。
Protobuf 與 gzip
/api/v1 底下的每個端點也都能說 Protocol Buffers。送出 Accept: application/x-protobuf,回應就會以 protobuf 傳回;若以 Content-Type: application/x-protobuf 送出 protobuf 的 body,回應也會是同樣的格式。兩者都不送,就是 JSON,和以前完全一樣。
curl https://vitrinaengine.com/api/v1/monitors \
-H "Authorization: Bearer vte_your_key_here" \
-H "Accept: application/x-protobuf" \
--compressed -o monitors.pb這些訊息都已公開:/api/proto 列出了每一個檔案。下載時請保留它們的路徑,並把 protoc -I 指向該目錄。有三點與 protobuf 使用者的預期不同:可以為空的欄位在 JSON 中是 null,在 protobuf 中則是不存在;少數形狀不固定的欄位——例如監控項目或通知管道的 config——是包在字串裡的 JSON 文件;而 StringList 包住的那份清單,本身也可能是 null。
Gzip 兩個方向都能用:回應用 Accept-Encoding: gzip,要求用 Content-Encoding: gzip。由於現在兩個呼叫端可能從同一個 URL 取得不同的位元組,每個回應都會帶上 Vary: Accept, Content-Type。
狀態碼
| 狀態碼 | 代表 |
|---|---|
200 | 一切正常。建立了東西時是 201。 |
400 | body 不是 JSON、缺少某個欄位,或是沒有提出任何變更。 |
401 | 沒有金鑰,或金鑰無效。刻意永遠不說是哪一種——能區分兩者的訊息,就是一種試探金鑰的手段。 |
403 | 金鑰有效,但沒有執行這個動作的權限。訊息會指出是哪一項。 |
404 | 對您而言沒有這筆紀錄。請見下方說明。 |
413 | source map 超過大小上限。 |
429 | 超過用量限制。會帶上 Retry-After。請見下方說明。 |
拒絕代碼
每個非 2xx 回應都在句子旁帶有 code——not_found、limit_reached、rate_limited——應當據此分支。error 字串是寫給看日誌的人的散文,隨時可能改寫;代碼則是穩定的。句子提到某個值時,vars 會以字串攜帶這些值,你可以按自己語言的語序擺放,而不必從英文中解析出來。
{
"error": "The Pro plan includes 50 monitors, and you have 50.",
"code": "limit_reached",
"vars": { "plan": "pro", "limit": "50", "current": "50", "resource": "monitors" }
}我們自己的應用就是據此用讀者的語言呈現拒絕訊息的。遇到不認識的代碼請照此處理——回退到 error——因為新增代碼不會提升版本號。
用量限制
以組織計算,而不是以金鑰計算——再開一把金鑰並不會把上限調高。
| 類別 | 上限 |
|---|---|
讀取(GET) | 每分鐘 120 次 |
寫入(POST、PATCH、DELETE) | 每分鐘 30 次 |
| source map 上傳 | 每小時 300 次 |
超過上限會回應 429,並帶上 Retry-After 標頭,以整秒數表示距離視窗重置還有多久。請遵守它,而不是立刻重試。
這些數字設在一般整合永遠碰不到的地方:每十秒輪詢一次的看板牆,只用掉 120 次讀取當中的六次。所有方案一視同仁,因為集合端點會在單一回應中回傳全部內容——擁有五百個監控項目的帳戶,並不會比只有二十個的帳戶需要更多次要求。source map 之所以採用每小時的視窗,是因為它們在部署時成批抵達,而一個前端很容易就有上百個 chunk。
刻意用 404 而不是 403
屬於另一位客戶的 id 會回應 「Not found.」,而不是「Forbidden.」。403 會確認該筆紀錄存在,那會讓這個端點變成一種試探 id 是否為真的手段。不要把 404 讀成任何地方都不存在這筆資料的證明——它只代表沒有任何這把金鑰能看見的東西存在。
端點
GET /search
帳戶中與 ?q= 相符的一切:監控、事件及其事後分析、主機、狀態頁、工作區、通知管道、維護時段、錯誤專案與問題、分析網站、成員與邀請、API 金鑰、代理程式和私有探針。一次請求即可,而不是每種類型一次。
?type= 可用逗號分隔的類型清單縮小範圍,?limit= 限制每種類型回傳的 數量,範圍 1 到 20(預設 5)。每種類型所需的權限與其自身端點相同;金鑰無權讀取的類型不會出現,與沒有相符結果的類型表現一致。任何密封、雜湊或機密的內容都不會被檢索或回傳。
參數與回應
| 名稱 | 位置 | 類型 |
|---|---|---|
limit | query | integer |
q | query | string |
type | query | string |
| 回應 | SearchResponse |
|---|---|
| 狀態碼 | 200 400 401 403 404 429 |
| 用量限制 | 每分鐘 120 次 |
GET /summary
各項計數,供看板牆或每日摘要使用。需要 monitor:read。
{
"data": {
"total": 42, "up": 39, "degraded": 1, "down": 1,
"paused": 1, "pending": 0,
"openIncidents": 2, "suppressedIncidents": 1
}
}suppressedIncidents 計算的是因為屬於另一起事件的影響範圍而被壓下的事件。它們是真實存在的,只是不是獨立的中斷。
參數與回應
未宣告參數或請求主體欄位。
| 回應 | GetSummaryResponse |
|---|---|
| 狀態碼 | 200 400 401 403 404 429 |
| 用量限制 | 每分鐘 120 次 |
GET /setup
新帳戶還有哪些事情沒做——與儀表板上的設定檢查清單所問的同樣四個問題,每次讀取時重新推導。需要 monitor:read。
{
"data": {
"hasMonitor": true,
"hasConfirmedChannel": false,
"hasStatusPage": false,
"hasColleague": false,
"dismissedAt": null
}
}hasConfirmedChannel 問的是警示是否真的送得到,而不是通知管道是否存在。這兩件事曾經嚴重地脫勾過一次,而一份把「警示已設定完成」打勾、實際上通知程式卻拒絕送出的檢查清單,等於是把那個錯誤以令人安心的形式重演一遍。
hasColleague 計算的是成員資格,絕不計算邀請:已送出但未接受的邀請,並沒有為您加進任何人。
它沒有併進 /summary,因為那個端點就只有依狀態分類的計數而已——每隔幾秒輪詢一次的看板牆,不會想要為了畫出一則對象是幾個月前建立帳戶的人的提示,而多做五次查詢。
參數與回應
未宣告參數或請求主體欄位。
| 回應 | GetSetupResponse |
|---|---|
| 狀態碼 | 200 400 401 403 404 429 |
| 用量限制 | 每分鐘 120 次 |
DELETE /setup
略過這份檢查清單。需要 org:update,因為關閉它是整個組織共用的一列資料,而不是每個人各自的偏好設定:在它被略過之後才加入的同事,不會再被顯示一次。
帳戶的其他部分不會有任何改變,也不會寫入稽核紀錄:隱藏一則提示,不會改變產品的行為、警示方式或計費方式。
參數與回應
未宣告參數或請求主體欄位。
| 回應 | DismissedResponse |
|---|---|
| 狀態碼 | 200 400 401 403 404 429 |
| 用量限制 | 每分鐘 30 次 |
GET /monitors
這把金鑰看得到的所有監控項目。需要 monitor:read。每一筆都帶有 id、name、kind、status、 statusSince、enabled、intervalSeconds、 tags、workspace、lastCheckedAt、 lastResponseTimeMs、lastMessage、uptime24h、 uptime30d 與 openIncidentId。
?tag=prod,eu 會把清單收窄到同時帶有全部所列標籤的監控項目——是「且」,不是「或」,所以多寫一個標籤總是回傳更少的監控項目,而不是更多。儀表板自己的篩選也是這樣讀的。標籤以小寫儲存,這裡的值在比較前也會同樣轉成小寫,所以 ?tag=Prod 找得到它們。不可能成為標籤的項目——空的,或比標籤允許的還長——會被丟掉,篩選的其餘部分照常生效,而不是拒絕這次呼叫:一條連結不該因為其中一個標籤被改名就不能用了。
config 永遠不會被回傳。在某些類型中它存放著要求標頭與憑證,而一把只有讀取範圍的金鑰,不該成為把某人填進表單的機密再讀回來的途徑。
參數與回應
| 名稱 | 位置 | 類型 |
|---|---|---|
tag | query | string |
| 回應 | ListMonitorsResponse |
|---|---|
| 狀態碼 | 200 400 401 403 404 429 |
| 用量限制 | 每分鐘 120 次 |
POST /monitors
需要 monitor:create。必填 name、kind、 workspaceId 與 config。選填: intervalSeconds(預設 300)、confirmations、 dependsOn。
curl -X POST https://vitrinaengine.com/api/v1/monitors \
-H "Authorization: Bearer vte_…" \
-H "Content-Type: application/json" \
-d '{
"name": "Marketing site",
"kind": "http",
"workspaceId": "…",
"intervalSeconds": 60,
"config": {
"url": "https://example.com",
"assertions": [{ "type": "status_code", "operator": "lt", "value": "400" }]
}
}'回應 201 與新的 id。間隔會被夾到您方案的下限,而不是被拒絕,因此在下限為 60 的方案上要求 10 秒會得到 60——如果這件事對您很重要,請讀回來確認。
參數與回應
| 名稱 | 位置 | 類型 |
|---|---|---|
name | body | string |
kind | body | string |
workspaceId | body | string |
config | body | string |
intervalSeconds | body | integer |
confirmations | body | integer |
dependsOn | body | string[] |
probeId | body | string |
tags | body | string[] |
| 回應 | CreatedResponse |
|---|---|
| 狀態碼 | 201 400 401 403 404 429 |
| 用量限制 | 每分鐘 30 次 |
GET /monitors/{id}
單一監控項目,包含清單所提供的一切,再加上 paused。需要 monitor:read。
對於 mail_posture、tls_audit 與 snmp,它還會帶上 lastCheckDetail,也就是上一次檢查自己的結果:狀態背後的發現項目,每一項都有穩定的 code 與 severity,再加上 TLS 評等或 SNMP 的讀數。在第一次檢查執行之前它是 null,其他類型則完全沒有這個欄位。
參數與回應
| 名稱 | 位置 | 類型 |
|---|---|---|
id 必填 | path | string |
| 回應 | GetMonitorResponse |
|---|---|
| 狀態碼 | 200 400 401 403 404 429 |
| 用量限制 | 每分鐘 120 次 |
PATCH /monitors/{id}
只送出您想變更的部分:name、intervalSeconds、 confirmations、enabled、config 或 paused。
paused 會對照 monitor:pause 檢查,其餘一切則對照 monitor:update,兩者分開——一把可以暫停但不能編輯的金鑰,仍然可以暫停。送出空白的變更是 400。
監控項目會被重新讀取後回傳,而不是把您送進來的內容原樣回聲,因此您看到的就是實際存下來的內容。
# Silence a monitor for the length of a deploy.
curl -X PATCH https://vitrinaengine.com/api/v1/monitors/$ID \
-H "Authorization: Bearer vte_…" \
-H "Content-Type: application/json" \
-d '{"paused": true}'參數與回應
| 名稱 | 位置 | 類型 |
|---|---|---|
id 必填 | path | string |
name | body | string |
intervalSeconds | body | integer |
confirmations | body | integer |
enabled | body | boolean |
paused | body | boolean |
config | body | string |
tags | body | StringList |
| 回應 | UpdatedMonitorResponse |
|---|---|
| 狀態碼 | 200 400 401 403 404 429 |
| 用量限制 | 每分鐘 30 次 |
DELETE /monitors/{id}
需要 monitor:delete。回應 { "data": { "id": "…", "deleted": true } }。
參數與回應
| 名稱 | 位置 | 類型 |
|---|---|---|
id 必填 | path | string |
| 回應 | AckResponse |
|---|---|
| 狀態碼 | 200 400 401 403 404 429 |
| 用量限制 | 每分鐘 30 次 |
GET /hosts · POST /hosts
主機是監控項目的第二種分組方式:工作區說明監控項目屬於誰,主機說明它跑在什麼機器上。完全可選——從未建立主機的帳戶不會失去任何東西,大多數監控項目也根本不指定主機。
每台主機都帶有 status、pinned 與 spanning。status 只由僅執行在該主機上的監控項目推導而來。橫跨多台機器的監控項目計入 spanning,且不會為其中任何一台上色:負載平衡端點失敗只說明服務壞了,而不是哪台機器壞了。 沒有專屬監控項目的主機回傳 "status": null 而非 up。
POST 需要 monitor:create 與 name。選填的 provider、address 與 notes 只供您自己查看,產品不會讀取。 與既有主機同名(忽略大小寫與結尾的點)會回傳 409。
參數與回應
GET /hosts
未宣告參數或請求主體欄位。
| 回應 | ListHostsResponse |
|---|---|
| 狀態碼 | 200 400 401 403 404 429 |
| 用量限制 | 每分鐘 120 次 |
POST /hosts
| 名稱 | 位置 | 類型 |
|---|---|---|
name | body | string |
provider | body | string |
address | body | string |
notes | body | string |
| 回應 | CreatedResponse |
|---|---|
| 狀態碼 | 201 400 401 403 404 429 |
| 用量限制 | 每分鐘 30 次 |
GET /hosts/{id} · PATCH /hosts/{id} · DELETE /hosts/{id}
詳情包含該主機及其上的監控項目,每項都標有 pinned;若不是專屬項目,則附上 alsoOn:它還從哪些機器回應——這正是您在重新啟動之前要看的內容。DELETE 會下線該主機,而上面的每個監控項目都會繼續執行:主機既沒有自己的排程,也沒有自己的歷史。
參數與回應
GET /hosts/{id}
| 名稱 | 位置 | 類型 |
|---|---|---|
id 必填 | path | string |
| 回應 | GetHostResponse |
|---|---|
| 狀態碼 | 200 400 401 403 404 429 |
| 用量限制 | 每分鐘 120 次 |
PATCH /hosts/{id}
| 名稱 | 位置 | 類型 |
|---|---|---|
id 必填 | path | string |
name | body | string |
provider | body | string |
address | body | string |
notes | body | string |
| 回應 | AckResponse |
|---|---|
| 狀態碼 | 200 400 401 403 404 429 |
| 用量限制 | 每分鐘 30 次 |
DELETE /hosts/{id}
| 名稱 | 位置 | 類型 |
|---|---|---|
id 必填 | path | string |
| 回應 | AckResponse |
|---|---|
| 狀態碼 | 200 400 401 403 404 429 |
| 用量限制 | 每分鐘 30 次 |
POST /hosts/{id}/monitors · DELETE /hosts/{id}/monitors
一次一個監控項目的掛載或移除,透過請求主體中的 monitorId 或 ?monitorId=。刻意不是整份清單:在代理商帳戶裡,一台主機承載著多個工作區的監控項目, 替換「整份清單」就會替換掉呼叫方從未看過的資料列。兩個方向都是冪等的。
參數與回應
POST /hosts/{id}/monitors
| 名稱 | 位置 | 類型 |
|---|---|---|
id 必填 | path | string |
monitorId | body | string |
| 回應 | AckResponse |
|---|---|
| 狀態碼 | 200 400 401 403 404 429 |
| 用量限制 | 每分鐘 30 次 |
DELETE /hosts/{id}/monitors
| 名稱 | 位置 | 類型 |
|---|---|---|
id 必填 | path | string |
monitorId | query | string |
monitorId | body | string |
| 回應 | AckResponse |
|---|---|
| 狀態碼 | 200 400 401 403 404 429 |
| 用量限制 | 每分鐘 30 次 |
GET /monitors/{id}/hosts · PUT /monitors/{id}/hosts
同一關係的另一側,這一側才是整份清單:這些關聯屬於單一監控項目,另一端沒有任何其他工作區看得到的東西。 送出 hostIds;空陣列是真實的請求,表示該監控項目不屬於任何特定主機。不屬於您的 id 會被捨棄而非拒絕。 每個監控項目的回應同樣帶有 hosts,沒有主機時為空。
參數與回應
GET /monitors/{id}/hosts
| 名稱 | 位置 | 類型 |
|---|---|---|
id 必填 | path | string |
| 回應 | ListMonitorHostsResponse |
|---|---|
| 狀態碼 | 200 400 401 403 404 429 |
| 用量限制 | 每分鐘 120 次 |
PUT /monitors/{id}/hosts
| 名稱 | 位置 | 類型 |
|---|---|---|
id 必填 | path | string |
hostIds | body | string[] |
| 回應 | ListMonitorHostsResponse |
|---|---|
| 狀態碼 | 200 400 401 403 404 429 |
| 用量限制 | 每分鐘 30 次 |
GET /incidents
需要 incident:read。接受 ?status=——其值為 open、acknowledged、resolved 或 suppressed 其中之一——以及 ?open=true,代表尚未解決的那三種。無法辨識的狀態會被忽略而不是拒絕,就像 ?limit=(預設 50)會被夾到 200 而不是被駁回一樣。
每一筆都帶有 id、monitorId、monitorName、 title、cause、status、severity、 startedAt、resolvedAt、durationSeconds、 acknowledgedAt 與 rootIncidentId。
rootIncidentId 是您在組建警示串流時該看的欄位。當它有值時,這起事件就是另一起事件的影響範圍——資料庫主機停機了,而這是它後方十二個服務之一。略過那些,您收到的就是一則警示,而不是十三則。
參數與回應
| 名稱 | 位置 | 類型 |
|---|---|---|
limit | query | integer |
open | query | boolean |
status | query | string |
| 回應 | ListIncidentsResponse |
|---|---|
| 狀態碼 | 200 400 401 403 404 429 |
| 用量限制 | 每分鐘 120 次 |
GET /incidents/{id}
單一事件。需要 incident:read。欄位與清單相同,再加上 workspaceId。
它不會回傳事件的時間軸——儀表板上看到的留言與狀態變更並不在這個端點上。如果您需要它們,請告訴我們,是可以加上去的;在它們還不存在時就寫在這裡,會比缺漏本身更糟。
參數與回應
| 名稱 | 位置 | 類型 |
|---|---|---|
id 必填 | path | string |
| 回應 | GetIncidentResponse |
|---|---|
| 狀態碼 | 200 400 401 403 404 429 |
| 用量限制 | 每分鐘 120 次 |
PATCH /incidents/{id}
送出值為 "acknowledged" 或 "resolved" 的 status,或是一則 comment,或兩者都送。每一項都會對照各自的權限檢查:incident:acknowledge、 incident:resolve、incident:comment。在留言中加上 "publish": true 會把它張貼到狀態頁面上,並額外需要 status_page:manage。
# A runbook that fixed the thing itself can close its own incident.
curl -X PATCH https://vitrinaengine.com/api/v1/incidents/$ID \
-H "Authorization: Bearer vte_…" \
-H "Content-Type: application/json" \
-d '{"status": "resolved", "comment": "Restarted by runbook.", "publish": true}'參數與回應
| 名稱 | 位置 | 類型 |
|---|---|---|
id 必填 | path | string |
status | body | string |
comment | body | string |
publish | body | boolean |
| 回應 | GetIncidentResponse |
|---|---|
| 狀態碼 | 200 400 401 403 404 429 |
| 用量限制 | 每分鐘 30 次 |
PUT /incidents/{id}/postmortem
撰寫或取代事件的事後檢討。需要 incident:resolve,且事件必須已解決——否則回傳 409,代碼為 incident_not_resolved。以 Markdown 傳送 body,去除前後空白後為 1 到 50,000 個字元(postmortem_required、postmortem_too_long)。每個事件只有一份,所以每次呼叫都會取代上一份。回應是事件本身,與 GET /incidents/{id} 回傳的相同。
GET /incidents/{id} 以 postmortem: { body, authorName, updatedAt } 或 null 的形式攜帶它,清單則攜帶 hasPostmortem。請將 body 呈現為 Markdown,絕不要當作 HTML:那是一個人輸入的文字。事後檢討是內部文件,從不出現在狀態頁上。
curl -X PUT https://vitrinaengine.com/api/v1/incidents/$ID/postmortem \
-H "Authorization: Bearer vte_…" \
-H "Content-Type: application/json" \
-d '{"body": "## What happened\n\nThe connection pool ran dry after a deploy."}'參數與回應
| 名稱 | 位置 | 類型 |
|---|---|---|
id 必填 | path | string |
body | body | string |
| 回應 | GetIncidentResponse |
|---|---|
| 狀態碼 | 200 400 401 403 404 429 |
| 用量限制 | 每分鐘 30 次 |
GET /probes
貴組織自己的私有探針:id, name, lastSeenAt, version, hostname, monitorCount, revoked 與 createdAt。需要 agent:read。這就是監控的探針選擇器所提供的內容。
沒有區域欄位,將來也不會有。你依名稱選擇探針;檢查在其背後於何處執行,由我們決定與調整。已撤銷的探針會帶 revoked: true 列出,且不再接收工作,所以請勿提供它們。
參數與回應
未宣告參數或請求主體欄位。
| 回應 | ListProbesResponse |
|---|---|
| 狀態碼 | 200 400 401 403 404 429 |
| 用量限制 | 每分鐘 120 次 |
GET /monitors/{id}/push-url
再次顯示 heartbeat 監控的 ping URL。需要 monitor:read。對於不接收 ping 的類型,以及無法再解密的權杖,url 為 null——監控仍會繼續運作,在主控台中輪替權杖即可取得可以顯示的 URL。
參數與回應
| 名稱 | 位置 | 類型 |
|---|---|---|
id 必填 | path | string |
| 回應 | GetPushUrlResponse |
|---|---|
| 狀態碼 | 200 400 401 403 404 429 |
| 用量限制 | 每分鐘 120 次 |
GET /organizations · PUT /organizations/active
已登入者所屬的組織,每個都附上其在該組織的 role,目前使用中的那個帶 active,以及在它們之間切換。傳送 organizationId;回應是現在使用中的成員身分。
僅限已登入的工作階段。金鑰只屬於一個成員身分,會收到 403 與 session_required。切換會移動此人所有的工作階段,包括主控台;對其不屬於的組織,回傳 404。
參數與回應
GET /organizations
未宣告參數或請求主體欄位。
| 回應 | ListOrganizationsResponse |
|---|---|
| 狀態碼 | 200 400 401 403 404 429 |
| 用量限制 | 每分鐘 120 次 |
PUT /organizations/active
| 名稱 | 位置 | 類型 |
|---|---|---|
organizationId | body | string |
| 回應 | ActiveOrganizationResponse |
|---|---|
| 狀態碼 | 200 400 401 403 404 429 |
| 用量限制 | 每分鐘 30 次 |
POST /sms/enrolment · POST /sms/enrolment/confirm
為簡訊警示登記你自己的手機號碼:傳送 phone(可選 name),我們會寄送六位數驗證碼給它;將該 code 傳送到第二個路由以確認。需要 notification_channel:manage 與已登入的工作階段——號碼由持有手機的人新增,絕不由金鑰新增。
號碼以未確認狀態儲存,在驗證碼回來之前不會收到任何內容。再次登記會取代你先前的號碼。拒絕:sms_not_included(402,方案不含簡訊)、not_a_phone_number, sms_country_unsupported, sms_route_not_open、verification_code_not_sent(502;再次呼叫以取得新驗證碼)、verification_code_malformed 與 verification_code_incorrect。成功開始時會攜帶 country 與 caveat(sender-replaced, registration-pending, unverified 或 null),值得在有人依賴該號碼之前顯示。
參數與回應
POST /sms/enrolment
| 名稱 | 位置 | 類型 |
|---|---|---|
phone | body | string |
name | body | string |
| 回應 | SmsEnrolmentResponse |
|---|---|
| 狀態碼 | 201 400 401 403 404 429 |
| 用量限制 | 每分鐘 30 次 |
POST /sms/enrolment/confirm
| 名稱 | 位置 | 類型 |
|---|---|---|
code | body | string |
| 回應 | SmsConfirmedResponse |
|---|---|
| 狀態碼 | 200 400 401 403 404 429 |
| 用量限制 | 每分鐘 30 次 |
POST /channels/{id}/confirmation
重新寄送電子郵件管道的確認訊息。需要 notification_channel:manage。每次呼叫都會產生新連結,先前的連結隨即失效。sent: false 表示沒有需要寄送的內容(該地址已確認),而且絕不會透過此方式再次寄信給已確認的地址。若郵件服務商拒絕寄送,回傳 502 與 confirmation_not_sent。
參數與回應
| 名稱 | 位置 | 類型 |
|---|---|---|
id 必填 | path | string |
| 回應 | ChannelConfirmationResponse |
|---|---|
| 狀態碼 | 200 400 401 403 404 429 |
| 用量限制 | 每分鐘 30 次 |
PATCH /workspaces/{id}
重新命名工作區。需要 workspace:update。name 為必填(1 到 80 個字元),clientReference 為選填——null 會將其清除。slug 永遠不會改變,因為它出現在狀態頁的 URL 中。回應是更新後的工作區。
參數與回應
| 名稱 | 位置 | 類型 |
|---|---|---|
id 必填 | path | string |
name | body | string |
clientReference | body | requests.NullableString |
| 回應 | UpdatedWorkspaceResponse |
|---|---|
| 狀態碼 | 200 400 401 403 404 429 |
| 用量限制 | 每分鐘 30 次 |
POST /sourcemaps
上傳 source map,讓壓縮過的堆疊追蹤能夠還原。需要 monitor:create。必填 projectRef(一個數字)與 filename,再加上 map 本身,形式為 map(JSON)或 mapGzipBase64。選填 debugId 與 release。
請送出 debug id 或 release。兩者都沒有的 map 無法對應到任何堆疊追蹤,只會擺在那裡什麼也不做。比對時先看 debugId,再看 release 加檔名。
map 是在問題被讀取時才還原,而不是在上傳時,因此在錯誤已經抵達之後才上傳的 map 仍然有用——而那正是常見的順序。
參數與回應
| 名稱 | 位置 | 類型 |
|---|---|---|
projectRef | body | integer |
filename | body | string |
debugId | body | string |
release | body | string |
map | body | string |
mapGzipBase64 | body | string |
| 回應 | UploadedSourceMapResponse |
|---|---|
| 狀態碼 | 201 400 401 403 404 429 |
| 用量限制 | 每小時 300 次 |
POST /symbols
原生應用程式的同一套做法:上傳 iOS 的 .dSYM 或 Android R8 的 mapping.txt,讓當機堆疊能夠還原。需要 monitor:create。每小時二十次上傳,每個專案保留二十個建置版本的份量。
與 /sourcemaps 不同的是,body 就是壓縮後的檔案本身,中繼資料則放在標頭裡:X-Vitrina-Project-Ref、X-Vitrina-Platform(ios 或 android)、X-Vitrina-Symbol-Name 以及 X-Vitrina-Release。一個 dSYM 有數十 MB,而放進 JSON 欄位的 base64 會讓傳輸量再多三分之一。
兩個平台的比對方式不同。iOS 的框架會指名它所屬映像檔的 Mach-O UUID,因此 iOS 的上傳必須帶上 X-Vitrina-Debug-Ids,並以它精確比對。R8 不會產生這樣的識別碼,所以 Android 的 mapping 只以 release 比對——而它必須與應用程式回報的內容完全一致,也就是 <applicationId>@<versionName>+<versionCode>。差一個數字,框架就會還原到看起來合理、實際上卻是錯的行號。
重新上傳同一個建置版本會取代它的符號檔,而不是失敗,因此重跑一次發布工作並不算錯誤。和 source map 一樣,還原是在問題被讀取時才發生。
參數與回應
未宣告參數或請求主體欄位。
| 回應 | UploadedSymbolsResponse |
|---|---|
| 狀態碼 | 200 400 401 403 404 429 |
| 用量限制 | 每小時 20 次 |
GET /errors/projects
這個帳戶擁有的錯誤追蹤專案。需要 monitor:read。每一筆都帶有 ref——也就是 DSN 裡的那個數字——以及 publicKey、 unresolved 與 eventsLast24h。唯讀:專案建立時會附帶一把仍需貼進應用程式設定的金鑰,因此這裡沒有任何端點能替您收尾的事。
參數與回應
未宣告參數或請求主體欄位。
| 回應 | ListErrorProjectsResponse |
|---|---|
| 狀態碼 | 200 400 401 403 404 429 |
| 用量限制 | 每分鐘 120 次 |
GET /errors/issues
分組後的錯誤,最近有動靜的排在前面。需要 monitor:read。一個問題是一組指紋而不是一個事件,因此同一次拋出的一千次發生,會是 timesSeen 為一千的單獨一列。?status= 預設為 unresolved,也接受 resolved、ignored 或 all;?project= 依專案 id 過濾,?q= 會搜尋類型、值與出錯位置,而 ?limit= 的上限是 200。 spark 是二十四筆每小時的計數,最舊的在前。
參數與回應
| 名稱 | 位置 | 類型 |
|---|---|---|
limit | query | integer |
project | query | string |
q | query | string |
status | query | string |
| 回應 | ListIssuesResponse |
|---|---|
| 狀態碼 | 200 400 401 403 404 429 |
| 用量限制 | 每分鐘 120 次 |
GET /errors/issues/{id}
單一問題與它的堆疊。需要 monitor:read。exceptions 是 SDK 自己的那串例外鏈,拋出的錯誤在最後、造成它的原因排在它前面,而它的框架會以您上傳過的任何 source map 還原——與儀表板所做的還原完全相同,因此指令稿與您正在對話的人,永遠不會看著不同的堆疊。無法套用的 map 會退回原始框架,而不是讓整個要求失敗。
lastEvent 刻意帶了兩個時間戳記。occurredAt 是 SDK 回報的時間,receivedAt 是收錄寫入的時間;裝置離線過,或佇列曾經塞住,差別就正好是這兩者之間的間隔。
參數與回應
| 名稱 | 位置 | 類型 |
|---|---|---|
id 必填 | path | string |
| 回應 | GetIssueResponse |
|---|---|
| 狀態碼 | 200 400 401 403 404 429 |
| 用量限制 | 每分鐘 120 次 |
PATCH /errors/issues/{id}
解決、忽略或重新開啟:{ "status": "resolved" }。需要 monitor:update。ignoreHours 可以與 ignored 一起送出,以便日後再把它解除忽略,上限為 90 天。
標記為解決時會記下它是在哪個 release 被解決的,因此較舊部署版本的漏網事件不會讓問題重新開啟。當 SDK 沒有送出 release 時,就沒有東西可以比對,之後的任何事件都會讓它重新開啟——既然無法分辨漏網事件與問題復發,安全的假設就是這個臭蟲又回來了。
參數與回應
| 名稱 | 位置 | 類型 |
|---|---|---|
id 必填 | path | string |
status | body | string |
ignoreHours | body | integer |
| 回應 | IssueStatusResponse |
|---|---|
| 狀態碼 | 200 400 401 403 404 429 |
| 用量限制 | 每分鐘 30 次 |
GET /analytics
這個帳戶所測量的網站。需要 monitor:read。帶有 publicId——也就是放進指令碼標籤裡的那個值,它本來就是公開的——以及 viewsLast24h 與 trafficAlerting,後者在某個網站的流量低於該時段平常水準期間為 true。
參數與回應
未宣告參數或請求主體欄位。
| 回應 | ListAnalyticsSitesResponse |
|---|---|
| 狀態碼 | 200 400 401 403 404 429 |
| 用量限制 | 每分鐘 120 次 |
GET /analytics/{id}
單一網站的數字,供試算表或報表使用。需要 monitor:read。?days= 預設為 7,上限為 365。 ?dimensions= 接受以逗號分隔的清單,可用值有 path、 referrer、country、browser、os、 device、utm_source、utm_medium、 utm_campaign 與 event;不認得的值會是 400,而不是回傳空的結果,因為一個拼錯而回傳空值的查詢讀起來就像「沒有流量」。
訪客數字這個欄位叫做 dailyUniqueVisitors,而它就是字面上的意思。它是每日不重複訪客的加總,也不可能是別的東西:訪客雜湊背後的祕密會在它所屬的 UTC 日結束時銷毀,所以在兩天各來過一次的人會被算兩次,而且沒有任何金鑰能把兩者接起來。那是隱私設計正在運作,而不是一種近似值——但若欄位名叫 visitors 又擺在 30 天的區間旁邊,就等於邀請您去回報一個意思完全不同的數字。
curl "https://vitrinaengine.com/api/v1/analytics/$ID?days=30&dimensions=path,referrer" \
-H "Authorization: Bearer vte_…"參數與回應
| 名稱 | 位置 | 類型 |
|---|---|---|
id 必填 | path | string |
days | query | integer |
| 回應 | GetAnalyticsSiteResponse |
|---|---|
| 狀態碼 | 200 400 401 403 404 429 |
| 用量限制 | 每分鐘 120 次 |
GET /billing
方案,以及它在哪裡計費。需要 billing:read。帶有 plan、status、cadence、 currentPeriodEnd、cancelAt、addOnPacks,以及最近十二筆收據。
source 的值是 paddle、apple、manual 或 none。這件事很重要:在 iOS 應用程式內購買的訂閱歸 Apple 管,方案、付款卡與取消都在客戶的 App Store 設定裡,而不在這裡。canCheckoutOnWeb 與 canPurchaseInApp 會說明哪些方案可以安全地呈現給對方,如此一來用戶端就不必自己重新推導那條規則,也不會朝著向某人重複收費的方向弄錯。
參數與回應
未宣告參數或請求主體欄位。
| 回應 | GetBillingResponse |
|---|---|
| 狀態碼 | 200 400 401 403 404 429 |
| 用量限制 | 每分鐘 120 次 |
GET /monitors/{id}/history
單一監控項目的每日可用性。需要 monitor:read。接受 days,上限為您方案的歷史保留期間。
它是從每日彙總資料計算的,而不是從個別的檢查結果,因此對於原始結果保留期已經刪除的時段,它仍然答得出來。
參數與回應
| 名稱 | 位置 | 類型 |
|---|---|---|
id 必填 | path | string |
days | query | integer |
| 回應 | GetMonitorHistoryResponse |
|---|---|
| 狀態碼 | 200 400 401 403 404 429 |
| 用量限制 | 每分鐘 120 次 |
GET /monitors/{id}/graph · GET /monitors/graphs
單個監控項最近幾個小時的逐小時資料,或者在一個回應裡給出此金鑰能看到的所有監控項的資料——也就是儀表板在監控項列和監控項頁面上繪製的內容。需要 monitor:read。接受 hours,預設 24,最多 168。
uptime 圖表給出每個小時通過檢查的比例,沒有檢查的小時為 null;value 圖表用於定量類型,以帶單位的序列給出讀數。視窗中的每個小時都會出現,無論是否有記錄,這樣空缺就明顯是空缺。讀數按實際測量值傳送:raw 序列沒有已知刻度,請以它自身的最高讀數為基準繪製,並且絕不要把這個比例當作讀數顯示。
參數與回應
GET /monitors/{id}/graph
| 名稱 | 位置 | 類型 |
|---|---|---|
id 必填 | path | string |
hours | query | integer |
| 回應 | GetMonitorGraphResponse |
|---|---|
| 狀態碼 | 200 400 401 403 404 429 |
| 用量限制 | 每分鐘 120 次 |
GET /monitors/graphs
| 名稱 | 位置 | 類型 |
|---|---|---|
hours | query | integer |
| 回應 | ListMonitorGraphsResponse |
|---|---|
| 狀態碼 | 200 400 401 403 404 429 |
| 用量限制 | 每分鐘 120 次 |
GET /monitors/{id}/channels · PUT /monitors/{id}/channels
這個監控項目會通知哪些通知管道,以及如何設定它們。讀取需要 notification_channel:read;寫入需要 monitor:update。
PUT 會取代整組設定——請送出您想要的每一個通知管道 id,而不是您正要新增的那幾個。空陣列代表這個監控項目誰也不通知,那是一種有效的需求,卻是一件不該不小心做出來的事。
參數與回應
GET /monitors/{id}/channels
| 名稱 | 位置 | 類型 |
|---|---|---|
id 必填 | path | string |
| 回應 | GetMonitorChannelsResponse |
|---|---|
| 狀態碼 | 200 400 401 403 404 429 |
| 用量限制 | 每分鐘 120 次 |
PUT /monitors/{id}/channels
| 名稱 | 位置 | 類型 |
|---|---|---|
id 必填 | path | string |
channelIds | body | StringList |
| 回應 | GetMonitorChannelsResponse |
|---|---|
| 狀態碼 | 200 400 401 403 404 429 |
| 用量限制 | 每分鐘 30 次 |
GET /incidents/{id}/events
單一事件的時間軸:狀態變更、確認、留言、升級步驟。需要 incident:read。這就是 GET /incidents/{id} 不會包含的那份時間軸。
參數與回應
| 名稱 | 位置 | 類型 |
|---|---|---|
id 必填 | path | string |
| 回應 | ListIncidentEventsResponse |
|---|---|
| 狀態碼 | 200 400 401 403 404 429 |
| 用量限制 | 每分鐘 120 次 |
GET /channels · POST /channels
讀取需要 notification_channel:read;建立需要 notification_channel:manage。每一筆都帶有 id、 kind、name、target 與 workspaceId。
secret 只在通知管道建立時回傳一次,之後不會再回傳。它是 webhook 的簽章金鑰;把它存在一個您能讀回來的地方,會讓一把唯讀範圍的金鑰變成偽造簽章要求的途徑。
您可以建立那些在儀表板上也能由人建立的種類:email、 webhook、telegram、slack、teams、 discord、pagerduty 與 jsm。簡訊、WhatsApp、衛星與推播是由接收它們的本人自行登錄的,無法透過 API 建立——正是這一點讓它們成為同意,而不是某人打進欄位裡的一串字。
電子郵件通知管道建立時處於未確認狀態,並會收到一封詢問它是否想接收警示的信。在它同意之前不會再送出任何東西,因此透過 API 建立一個,本身並不會把一個地址放進您的呼叫輪值表裡。
參數與回應
GET /channels
未宣告參數或請求主體欄位。
| 回應 | ListChannelsResponse |
|---|---|
| 狀態碼 | 200 400 401 403 404 429 |
| 用量限制 | 每分鐘 120 次 |
POST /channels
| 名稱 | 位置 | 類型 |
|---|---|---|
kind | body | string |
name | body | string |
target | body | string |
workspaceId | body | requests.NullableString |
| 回應 | CreatedChannelResponse |
|---|---|
| 狀態碼 | 201 400 401 403 404 429 |
| 用量限制 | 每分鐘 30 次 |
PATCH /channels/{id} · DELETE /channels/{id} · POST /channels/{id}/test
三者都需要 notification_channel:manage。對尚未確認的地址,測試發送會被拒絕——否則它就會變成一種無上限地寄信給未同意地址的手段,只是披著一個看起來很貼心的名字。
參數與回應
PATCH /channels/{id}
| 名稱 | 位置 | 類型 |
|---|---|---|
id 必填 | path | string |
enabled | body | boolean |
| 回應 | AckResponse |
|---|---|
| 狀態碼 | 200 400 401 403 404 429 |
| 用量限制 | 每分鐘 30 次 |
DELETE /channels/{id}
| 名稱 | 位置 | 類型 |
|---|---|---|
id 必填 | path | string |
| 回應 | AckResponse |
|---|---|
| 狀態碼 | 200 400 401 403 404 429 |
| 用量限制 | 每分鐘 30 次 |
POST /channels/{id}/test
| 名稱 | 位置 | 類型 |
|---|---|---|
id 必填 | path | string |
| 回應 | TestDeliveryResponse |
|---|---|
| 狀態碼 | 200 400 401 403 404 429 |
| 用量限制 | 每分鐘 30 次 |
GET /status-pages · POST /status-pages
讀取需要 status_page:read;寫入需要 status_page:manage。每一筆都帶有 id、name、 slug、visibility、customDomain、 domainVerifiedAt、subscribersEnabled、 componentCount、workspace 與 createdAt。
參數與回應
GET /status-pages
未宣告參數或請求主體欄位。
| 回應 | ListStatusPagesResponse |
|---|---|
| 狀態碼 | 200 400 401 403 404 429 |
| 用量限制 | 每分鐘 120 次 |
POST /status-pages
| 名稱 | 位置 | 類型 |
|---|---|---|
name | body | string |
workspaceId | body | string |
| 回應 | CreatedResponse |
|---|---|
| 狀態碼 | 201 400 401 403 404 429 |
| 用量限制 | 每分鐘 30 次 |
GET /status-pages/{id} · PATCH /status-pages/{id} · DELETE /status-pages/{id}
讀取需要 status_page:read;變更或刪除需要 status_page:manage。
參數與回應
GET /status-pages/{id}
| 名稱 | 位置 | 類型 |
|---|---|---|
id 必填 | path | string |
| 回應 | GetStatusPageResponse |
|---|---|
| 狀態碼 | 200 400 401 403 404 429 |
| 用量限制 | 每分鐘 120 次 |
PATCH /status-pages/{id}
| 名稱 | 位置 | 類型 |
|---|---|---|
id 必填 | path | string |
name | body | string |
headline | body | requests.NullableString |
description | body | requests.NullableString |
logoUrl | body | requests.NullableString |
themeAccent | body | string |
language | body | string |
historyDays | body | integer |
showResponseTimes | body | boolean |
showIncidentHistory | body | boolean |
subscribersEnabled | body | boolean |
visibility | body | string |
password | body | requests.NullableString |
customCss | body | requests.NullableString |
hideVitrinaBranding | body | boolean |
groupByHost | body | boolean |
| 回應 | UpdatedStatusPageResponse |
|---|---|
| 狀態碼 | 200 400 401 403 404 429 |
| 用量限制 | 每分鐘 30 次 |
DELETE /status-pages/{id}
| 名稱 | 位置 | 類型 |
|---|---|---|
id 必填 | path | string |
| 回應 | AckResponse |
|---|---|
| 狀態碼 | 200 400 401 403 404 429 |
| 用量限制 | 每分鐘 30 次 |
POST /status-pages/{id}/components · DELETE /status-pages/{id}/components
把一個監控項目加入頁面或從頁面移除。需要 status_page:manage。
該監控項目必須與頁面位於同一個工作區,而不只是位於同一個組織。在代理商帳戶裡,正是這一點防止某位客戶的監控項目被發布到另一位客戶的頁面上。
參數與回應
POST /status-pages/{id}/components
| 名稱 | 位置 | 類型 |
|---|---|---|
id 必填 | path | string |
monitorId | body | string |
displayName | body | string |
| 回應 | ComponentAckResponse |
|---|---|
| 狀態碼 | 201 400 401 403 404 429 |
| 用量限制 | 每分鐘 30 次 |
DELETE /status-pages/{id}/components
| 名稱 | 位置 | 類型 |
|---|---|---|
id 必填 | path | string |
component | query | string |
componentId | body | string |
| 回應 | ComponentAckResponse |
|---|---|
| 狀態碼 | 200 400 401 403 404 429 |
| 用量限制 | 每分鐘 30 次 |
GET /workspaces · POST /workspaces · DELETE /workspaces/{id}
讀取需要 workspace:read,其餘各自需要對應的權限。每一筆都帶有 id、name、slug、 clientReference 與 isDefault。
屬於受限成員的金鑰,只看得到該成員被限制在其中的那些工作區。預設工作區無法刪除。
參數與回應
GET /workspaces
未宣告參數或請求主體欄位。
| 回應 | ListWorkspacesResponse |
|---|---|
| 狀態碼 | 200 400 401 403 404 429 |
| 用量限制 | 每分鐘 120 次 |
POST /workspaces
| 名稱 | 位置 | 類型 |
|---|---|---|
name | body | string |
clientReference | body | string |
| 回應 | CreatedResponse |
|---|---|
| 狀態碼 | 201 400 401 403 404 429 |
| 用量限制 | 每分鐘 30 次 |
DELETE /workspaces/{id}
| 名稱 | 位置 | 類型 |
|---|---|---|
id 必填 | path | string |
| 回應 | AckResponse |
|---|---|
| 狀態碼 | 200 400 401 403 404 429 |
| 用量限制 | 每分鐘 30 次 |
GET /members · POST /members
讀取需要 member:read;邀請需要 member:invite。回應中 members 與 invitations 是分開的——沒有人接受的邀請並沒有加進任何人,而把兩者合併會做出一個與您實際帳單不符的席次數。
POST 送出的是一份邀請,而不是建立一個帳戶。它接受一個電子郵件地址、一個角色,以及選填的 workspaceIds 以限制對方的範圍。
參數與回應
GET /members
未宣告參數或請求主體欄位。
| 回應 | ListMembersResponse |
|---|---|
| 狀態碼 | 200 400 401 403 404 429 |
| 用量限制 | 每分鐘 120 次 |
POST /members
| 名稱 | 位置 | 類型 |
|---|---|---|
email | body | string |
role | body | string |
workspaceIds | body | string[] |
| 回應 | AckResponse |
|---|---|
| 狀態碼 | 201 400 401 403 404 429 |
| 用量限制 | 每分鐘 30 次 |
PATCH /members/{id} · DELETE /members/{id} · DELETE /invitations/{id}
變更角色需要 member:update_role;移除需要 member:remove;撤銷邀請需要 member:invite。
移除一位成員會刪除他個人的警示通知管道——他的手機、他的私人聊天室、他的行動電話號碼——連同他的 API 金鑰一起。共用的通知管道不受影響。最後一位擁有者無法被移除,也無法被降級。
參數與回應
PATCH /members/{id}
| 名稱 | 位置 | 類型 |
|---|---|---|
id 必填 | path | string |
role | body | string |
| 回應 | AckResponse |
|---|---|
| 狀態碼 | 200 400 401 403 404 429 |
| 用量限制 | 每分鐘 30 次 |
DELETE /members/{id}
| 名稱 | 位置 | 類型 |
|---|---|---|
id 必填 | path | string |
| 回應 | AckResponse |
|---|---|
| 狀態碼 | 200 400 401 403 404 429 |
| 用量限制 | 每分鐘 30 次 |
DELETE /invitations/{id}
| 名稱 | 位置 | 類型 |
|---|---|---|
id 必填 | path | string |
| 回應 | AckResponse |
|---|---|
| 狀態碼 | 200 400 401 403 404 429 |
| 用量限制 | 每分鐘 30 次 |
GET /maintenance · POST /maintenance · DELETE /maintenance
在這些期間內不會呼叫任何人。預設情況下檢查照常執行、照常記錄,因此這些分鐘與其他時間一樣計入可用性;將 keepChecking 設為 false 之後,時段開啟期間不會進行任何檢查,歷史紀錄中留下的是一段空白,而不是一次下滑。讀取需要 incident:read;寫入需要 maintenance:manage。
帶有 title、startsAt、endsAt、 timezone、monitorIds、recurrenceRule、 keepChecking、showOnStatusPage 與 notifySubscribers。週期性的維護時段是一列資料,而不是很多列。
規則會讓維護時段在它自己的 timezone 中按同一本地時間重複,因此跨越時鐘調整的時段仍停在預定的那個小時。FREQ=DAILY、FREQ=WEEKLY 與 FREQ=MONTHLY 會被展開,並可帶 INTERVAL、COUNT、UNTIL,以及指出時段本身起始那一天的 BYDAY 或 BYMONTHDAY。其他規則會原樣儲存並原樣回傳,且只在第一次發生時擋下警示——我們從不猜測。
參數與回應
GET /maintenance
| 名稱 | 位置 | 類型 |
|---|---|---|
past | query | boolean |
| 回應 | ListMaintenanceResponse |
|---|---|
| 狀態碼 | 200 400 401 403 404 429 |
| 用量限制 | 每分鐘 120 次 |
POST /maintenance
| 名稱 | 位置 | 類型 |
|---|---|---|
title | body | string |
description | body | string |
workspaceId | body | string |
monitorIds | body | string[] |
startsAt | body | string |
endsAt | body | string |
recurrenceRule | body | string |
timezone | body | string |
keepChecking | body | boolean |
showOnStatusPage | body | boolean |
notifySubscribers | body | boolean |
| 回應 | CreatedResponse |
|---|---|
| 狀態碼 | 201 400 401 403 404 429 |
| 用量限制 | 每分鐘 30 次 |
DELETE /maintenance
| 名稱 | 位置 | 類型 |
|---|---|---|
id | query | string |
| 回應 | AckResponse |
|---|---|
| 狀態碼 | 200 400 401 403 404 429 |
| 用量限制 | 每分鐘 30 次 |
GET /on-call
值班表、升級政策、代班,以及現在正在值班的人。需要 oncall:read。
onCallNow 是在您詢問的當下解析出來的,並以 viaOverride 說明它來自輪值還是來自某位代班的人。unreachable 會指出哪些參與者沒有任何真的聯絡得上他們的通知管道,而那正是值得在事件發生之前、而不是發生當中才發現的故障。
參數與回應
未宣告參數或請求主體欄位。
| 回應 | GetOnCallResponse |
|---|---|
| 狀態碼 | 200 400 401 403 404 429 |
| 用量限制 | 每分鐘 120 次 |
GET /agents · POST /agents · DELETE /agents · GET /agents/{id}/metrics
伺服器代理程式會從您自己的機器回報 CPU、記憶體與磁碟。登錄需要 agent:enroll,讀取需要 agent:read,移除需要 agent:delete。
登錄時會回傳一個 token,只有那一次。它是代理程式用來驗證身分的東西,因此之後永遠讀不回來。
參數與回應
GET /agents
未宣告參數或請求主體欄位。
| 回應 | ListAgentsResponse |
|---|---|
| 狀態碼 | 200 400 401 403 404 429 |
| 用量限制 | 每分鐘 120 次 |
POST /agents
| 名稱 | 位置 | 類型 |
|---|---|---|
name | body | string |
workspaceId | body | requests.NullableString |
| 回應 | EnrolledAgentResponse |
|---|---|
| 狀態碼 | 201 400 401 403 404 429 |
| 用量限制 | 每分鐘 30 次 |
DELETE /agents
| 名稱 | 位置 | 類型 |
|---|---|---|
id | query | string |
id | body | string |
| 回應 | AckResponse |
|---|---|
| 狀態碼 | 200 400 401 403 404 429 |
| 用量限制 | 每分鐘 30 次 |
GET /agents/{id}/metrics
| 名稱 | 位置 | 類型 |
|---|---|---|
id 必填 | path | string |
hours | query | integer |
limit | query | integer |
| 回應 | GetAgentMetricsResponse |
|---|---|
| 狀態碼 | 200 400 401 403 404 429 |
| 用量限制 | 每分鐘 120 次 |
GET /api-keys · POST /api-keys · DELETE /api-keys
讀取需要 api_key:read;建立與撤銷需要 api_key:manage。每一筆都帶有 id、name、 prefix、scopes、workspaceIds、 owner、createdAt、lastUsedAt、 expiresAt 與 revokedAt。
token 只在建立時回傳。prefix 是可顯示的那一段,正是它讓您能在清單裡分辨兩把金鑰,而不必讓任何一把可被讀取。
金鑰會繼承建立它的那份成員資格的角色與工作區限制,因此金鑰不可能成為繞過其作者所受限制的途徑。
參數與回應
GET /api-keys
未宣告參數或請求主體欄位。
| 回應 | ListApiKeysResponse |
|---|---|
| 狀態碼 | 200 400 401 403 404 429 |
| 用量限制 | 每分鐘 120 次 |
POST /api-keys
| 名稱 | 位置 | 類型 |
|---|---|---|
name | body | string |
scopes | body | string[] |
workspaceIds | body | string[] |
expiresInDays | body | requests.NullableInt64 |
| 回應 | CreatedApiKeyResponse |
|---|---|
| 狀態碼 | 201 400 401 403 404 429 |
| 用量限制 | 每分鐘 30 次 |
DELETE /api-keys
| 名稱 | 位置 | 類型 |
|---|---|---|
id | query | string |
id | body | string |
| 回應 | AckResponse |
|---|---|
| 狀態碼 | 200 400 401 403 404 429 |
| 用量限制 | 每分鐘 30 次 |
GET /audit
設定的變更,以及是誰做的、改了什麼。需要 audit_log:read,也就是 Business 以上方案。
以 nextBefore 分頁,而不是以頁碼,因此在您讀取的過程中分頁界線不會移動。所有方案都會記錄項目——方案限制的是讀取,因此升級會打開整段歷史,而不是從那一刻才開始累積。
憑證、雜湊與機密絕不會被寫進 changes。
參數與回應
| 名稱 | 位置 | 類型 |
|---|---|---|
limit | query | integer |
| 回應 | ListAuditResponse |
|---|---|
| 狀態碼 | 200 400 401 403 404 429 |
| 用量限制 | 每分鐘 120 次 |
GET /me
這把金鑰是誰、它能觸及什麼,以及方案允許什麼。不需要任何權限——每把金鑰都能描述它自己。
帶有 user、organization、membership(角色與工作區限制)、entitlements(解析後的方案限額, 任何加購方案包都已經折算進去)與 usage。請用它在嘗試建立之前先確認限額,而不是被拒絕之後才查。
以工作階段呼叫時還會得到 organizations,列出這個人所屬的每一個組織。API 金鑰則不會:金鑰是針對單一份成員資格核發並受限於它,因此列出其他組織等於是在宣傳那把憑證根本觸及不到的組織。
參數與回應
未宣告參數或請求主體欄位。
| 回應 | GetMeResponse |
|---|---|
| 狀態碼 | 200 400 401 403 404 429 |
| 用量限制 | 每分鐘 120 次 |
DELETE /account
刪除這個組織以及其中的一切。這一項沒有任何權限常數守著,因為擁有權就是檢查本身:不是擁有者的人一律被拒絕。
它無法復原,也不是暫停。請審慎使用。
參數與回應
未宣告參數或請求主體欄位。
| 回應 | AccountDeletedResponse |
|---|---|
| 狀態碼 | 200 400 401 403 404 429 |
| 用量限制 | 每分鐘 30 次 |
POST /billing/apple/verify
確認在我們自己的行動應用程式中完成的應用程式內購買。需要 billing:manage。
列在這裡是為了完整,而不是為了讓您使用:它只能以 Apple 核發給我們應用程式的收據來呼叫,因此第三方整合對它無事可做。之所以仍然列出,是因為一條存在卻沒有任何地方描述的路由,和一條被人遺忘的路由看起來一模一樣。
參數與回應
| 名稱 | 位置 | 類型 |
|---|---|---|
transactionId | body | string |
| 回應 | AppleVerifyResponse |
|---|---|
| 狀態碼 | 200 400 401 403 404 429 |
| 用量限制 | 每分鐘 30 次 |
GET /
索引。它列出這次部署所提供的路由,也就是本頁的機器可讀版本,而且永遠是最新的——它是從實際掛載的內容產生的。
事件訂閱來源(RSS 與 Atom)
把帳戶中的所有事件做成訂閱來源,供閱讀器使用,而不是給用戶端函式庫。請在控制台的設定 → 通知中建立這個網址:
https://vitrinaengine.com/feeds/incidents/vtf_…/feed.xml
https://vitrinaengine.com/feeds/incidents/vtf_…/atom.xml這個網址本身就是憑證。不必送出任何標頭:持有連結的人就能讀取帳戶中的每一個事件,涵蓋所有工作區。它會在控制台中隨時重新顯示,因為它存放在某人遲早會重灌的訂閱閱讀器裡——而且可以更換或撤銷,自下一次請求起立即生效,不必等某個快取過期。
它只承載事件層級的事實:監控項目名稱、原因、嚴重程度、狀態、開始與結束時間,以及標記為公開的更新。絕不包含事後檢討,不包含監控項目設定,也絕不包含檢查從何處發出。多數閱讀器會透過第三方伺服器同步,因此這份文件是按照「會離開您的場所」來撰寫的——事實也正是如此。
每分鐘抓取一次屬於正常。單一網址每分鐘超過六十次請求會回應 429;從未有效、已被更換或已被撤銷的網址都回應 404——三種情況給出同一個答覆,以免有人藉此推斷哪些權杖曾經真實存在。
這個 API 刻意不回傳的東西
- 監控項目的
config。它可能含有憑證。 - 某次檢查是從哪個區域執行的。我們從何處檢查,是由我們決定、也由我們隨著探針的佈署與搬遷而更動的。那會是一項關於我們基礎架構、而您無法據以行動的承諾,而且產品的其他任何地方也都不會顯示它。
Exporting your data
Two routes hand back a file rather than a message, so that taking your data out does not mean paging through a collection endpoint a thousand times. Both are on every plan, the free one included — what a plan changes is how much history there is to export, not whether you may.
GET /export/{entity}
某一類列資料,輸出為 CSV 或 JSON。entity 可以是 monitors、hosts、status-pages、notification-channels、members、incidents、incident-events、postmortems、audit-log、error-issues、uptime-daily、uptime-hourly 或 analytics-hourly, 其他一律回應 404。
format 為 csv(預設)或 json;from 與 to 是 RFC 3339 時間戳記。bom 會在 CSV 前加上 UTF-8 位元組順序標記: Excel 需要它才能正確顯示非 ASCII 名稱,而多數指令碼語言會把它當成第一個欄名的一部分,因此預設關閉。
參數與回應
| 名稱 | 位置 | 類型 |
|---|---|---|
entity 必填 | path | string |
bom | query | boolean |
format | query | string |
from | query | string |
to | query | string |
| 狀態碼 | 200 400 401 403 404 429 |
|---|---|
| 用量限制 | 每小時 6 次 |
GET /export
該金鑰可讀的全部內容,打包為 zip:每個實體一個檔案,外加 manifest.json, 說明壓縮檔內容、每個檔案的列數以及缺少哪些實體。金鑰角色無權讀取的部分會被省略,而不是讓整個 請求失敗;清單的作用正是讓這種省略不再悄無聲息。
參數與回應
| 名稱 | 位置 | 類型 |
|---|---|---|
bom | query | boolean |
format | query | string |
from | query | string |
to | query | string |
| 狀態碼 | 200 400 401 403 404 429 |
|---|---|
| 用量限制 | 每小時 6 次 |
What an export does not contain
匯出不包含任何可用於驗證的內容:沒有通道設定,沒有 heartbeat 權杖,也沒有 密碼雜湊。監測器的設定會包含在內,但會移除一切形似憑證的欄位——請求主體、請求標頭、SNMP community、 信箱登入。原始檢查結果同樣不在其中:保留期會將其刪除,因此可用率來自彙總資料。
Size, and the one refusal you may meet
小時級序列每次請求最多 92 天;更寬的時間範圍會以 export_window_too_wide 拒絕,而不是悄悄截斷。它有獨立的速率上限:每個組織每小時 6 次匯出。
版本控管
版本寫在路徑裡。回應中會新增欄位——請把不認得的欄位視為可以忽略的東西,而不是錯誤——但 v1 之中不會移除任何東西,也不會有任何東西改變意義。
少了什麼嗎?
這個介面刻意保持精簡:它涵蓋一面看板牆、一份聊天室摘要,以及一段在發布期間把監控項目靜音的部署指令稿。如果您正在做的東西它構不到,請寫信到 support@vitrinaengine.com——知道大家實際想要什麼,正是下一個端點如何被選出來的方式。