错误追踪
捕获错误与异常并按问题分组、检索与解决——Sentry 风格的错误监控。
1. 概览
https://api.infrai.cc/v1/errorsAuthorization: Bearer $INFRAI_API_KEY# Call any /v1/errors capability over raw HTTP — no SDK to install.
# curl:
curl https://api.infrai.cc/v1/errors/... \
-H "Authorization: Bearer $INFRAI_API_KEY" \
-H "Content-Type: application/json"2. 方法 (9)
2.1errors.capture
捕获应用错误,可选标签。
参数
| 名称 | 类型 | 必填 | 说明 |
|---|---|---|---|
message | string | 必填 | 可读的错误消息。 |
code | string | 可选 | 可选的应用错误码。 |
stack | string | 可选 | 可选的堆栈跟踪。 |
tags | Record<string, string> | 可选 | 用于分组的键/值标签。 |
返回
{ ok, error_id }| 名称 | 类型 | 说明 |
|---|---|---|
event_id | string | event的唯一标识符pattern: ^evt_err_[A-Za-z0-9]{20,}$ |
fingerprint | string | 用于分组的 sha256 十六进制哈希。 |
error_group_id | string | 此事件所属的错误分组标识符pattern: ^errgrp_[A-Za-z0-9]{20,}$ |
is_new_group | boolean | 本次捕获是否创建了新的错误分组 |
dashboard_url | string | 在控制台中查看此资源的 URLformat: uri |
示例
一次性前置(每个范例都假定已完成):
# No SDK to install — every call is a plain HTTPS request.
# Get a project key by signing in at https://infrai.cc/login (Google/GitHub gives
# you $2 free credit; email sign-in starts at $0). On 402 INSUFFICIENT_CREDIT, add
# funds at https://infrai.cc/billing (or POST /v1/account/topup and open the
# returned checkout_url).
export INFRAI_API_KEY="ifr_..."curl -X POST https://api.infrai.cc/v1/errors/capture \
-H "Authorization: Bearer $INFRAI_API_KEY" \
-H "Content-Type: application/json" \
-d '{}'# Zero-install REST call — no SDK required (short-term the API is REST-only).
import os, requests
resp = requests.post(
"https://api.infrai.cc/v1/errors/capture",
headers={
"Authorization": f"Bearer {os.environ['INFRAI_API_KEY']}",
},
json={},
)
resp.raise_for_status()
print(resp.json())// Zero-install REST call — no SDK required (short-term the API is REST-only).
const resp = await fetch(
"https://api.infrai.cc/v1/errors/capture",
{
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({}),
},
);
console.log(await resp.json());// Zero-install REST call — no SDK required (short-term the API is REST-only).
const resp = await fetch(
"https://api.infrai.cc/v1/errors/capture",
{
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({}),
},
);
if (!resp.ok) throw new Error(`infrai ${resp.status}`);
const data: unknown = await resp.json();
console.log(data);// Zero-install REST call — no SDK required (short-term the API is REST-only).
package main
import (
"bytes"
"fmt"
"net/http"
"os"
)
func main() {
body := []byte(`{}`)
req, _ := http.NewRequest("POST", "https://api.infrai.cc/v1/errors/capture", bytes.NewReader(body))
req.Header.Set("Authorization", "Bearer "+os.Getenv("INFRAI_API_KEY"))
req.Header.Set("Content-Type", "application/json")
resp, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
fmt.Println(resp.Status)
}// Zero-install REST call — no SDK required (short-term the API is REST-only).
import java.net.URI;
import java.net.http.*;
HttpRequest req = HttpRequest.newBuilder()
.uri(URI.create("https://api.infrai.cc/v1/errors/capture"))
.header("Authorization", "Bearer " + System.getenv("INFRAI_API_KEY"))
.header("Content-Type", "application/json")
.method("POST", HttpRequest.BodyPublishers.ofString("{}"))
.build();
HttpResponse<String> resp = HttpClient.newHttpClient()
.send(req, HttpResponse.BodyHandlers.ofString());
System.out.println(resp.body());// Zero-install REST call — no SDK required (short-term the API is REST-only).
using System;
using System.Net.Http;
var client = new HttpClient();
var req = new HttpRequestMessage(new HttpMethod("POST"), "https://api.infrai.cc/v1/errors/capture");
var key = Environment.GetEnvironmentVariable("INFRAI_API_KEY");
req.Headers.Add("Authorization", "Bearer " + key);
req.Content = new StringContent("{}", System.Text.Encoding.UTF8, "application/json");
var resp = await client.SendAsync(req);
Console.WriteLine(await resp.Content.ReadAsStringAsync());<?php
// Zero-install REST call — no SDK required (short-term the API is REST-only).
$ch = curl_init("https://api.infrai.cc/v1/errors/capture");
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer " . getenv("INFRAI_API_KEY"),
"Content-Type: application/json",
]);
curl_setopt($ch, CURLOPT_POSTFIELDS, "{}");
$response = curl_exec($ch);
curl_close($ch);
echo $response;# Zero-install REST call — no SDK required (short-term the API is REST-only).
require "net/http"
require "uri"
uri = URI("https://api.infrai.cc/v1/errors/capture")
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
req = Net::HTTP::Post.new(uri)
req["Authorization"] = "Bearer #{ENV['INFRAI_API_KEY']}"
req["Content-Type"] = "application/json"
req.body = '{}'
res = http.request(req)
puts res.body// Zero-install REST call — no SDK required (short-term the API is REST-only). (uses the reqwest + tokio crates)
use std::env;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let resp = reqwest::Client::new()
.post("https://api.infrai.cc/v1/errors/capture")
.header("Authorization", format!("Bearer {}", env::var("INFRAI_API_KEY")?))
.header("Content-Type", "application/json")
.body(r#"{}"#)
.send()
.await?;
println!("{}", resp.text().await?);
Ok(())
}2.2errors.message
上报一条结构化错误或日志消息
参数
| 名称 | 类型 | 必填 | 说明 |
|---|---|---|---|
text | string | 必填 | 消息正文≥ 1 chars |
level | "debug" | "info" | "warning" | "error" | "fatal" | 可选 | 级别:debug/info/warning/error/fataldefault: "info" |
tags | Record<string, string> | 可选 | 键值标签,便于过滤与分组 |
user_id | string | 可选 | 关联的用户 ID |
release | string | 可选 | 发布版本标识 |
environment | "production" | "staging" | "development" | null | 可选 | 环境:production/staging/development |
idempotency_key | string | 可选 | 幂等键,用于避免重复写入 |
返回
CaptureResult| 名称 | 类型 | 说明 |
|---|---|---|
event_id | string | event的唯一标识符pattern: ^evt_err_[A-Za-z0-9]{20,}$ |
fingerprint | string | 用于分组的 sha256 十六进制哈希。 |
error_group_id | string | 此事件所属的错误分组标识符pattern: ^errgrp_[A-Za-z0-9]{20,}$ |
is_new_group | boolean | 本次捕获是否创建了新的错误分组 |
dashboard_url | string | 在控制台中查看此资源的 URLformat: uri |
示例
一次性前置(每个范例都假定已完成):
# No SDK to install — every call is a plain HTTPS request.
# Get a project key by signing in at https://infrai.cc/login (Google/GitHub gives
# you $2 free credit; email sign-in starts at $0). On 402 INSUFFICIENT_CREDIT, add
# funds at https://infrai.cc/billing (or POST /v1/account/topup and open the
# returned checkout_url).
export INFRAI_API_KEY="ifr_..."curl -X POST https://api.infrai.cc/v1/errors/message \
-H "Authorization: Bearer $INFRAI_API_KEY" \
-H "Content-Type: application/json" \
-d '{"text": "hello"}'# Zero-install REST call — no SDK required (short-term the API is REST-only).
import os, requests
resp = requests.post(
"https://api.infrai.cc/v1/errors/message",
headers={
"Authorization": f"Bearer {os.environ['INFRAI_API_KEY']}",
},
json={'text': 'hello'},
)
resp.raise_for_status()
print(resp.json())// Zero-install REST call — no SDK required (short-term the API is REST-only).
const resp = await fetch(
"https://api.infrai.cc/v1/errors/message",
{
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({"text": "hello"}),
},
);
console.log(await resp.json());// Zero-install REST call — no SDK required (short-term the API is REST-only).
const resp = await fetch(
"https://api.infrai.cc/v1/errors/message",
{
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({"text": "hello"}),
},
);
if (!resp.ok) throw new Error(`infrai ${resp.status}`);
const data: unknown = await resp.json();
console.log(data);// Zero-install REST call — no SDK required (short-term the API is REST-only).
package main
import (
"bytes"
"fmt"
"net/http"
"os"
)
func main() {
body := []byte(`{"text": "hello"}`)
req, _ := http.NewRequest("POST", "https://api.infrai.cc/v1/errors/message", bytes.NewReader(body))
req.Header.Set("Authorization", "Bearer "+os.Getenv("INFRAI_API_KEY"))
req.Header.Set("Content-Type", "application/json")
resp, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
fmt.Println(resp.Status)
}// Zero-install REST call — no SDK required (short-term the API is REST-only).
import java.net.URI;
import java.net.http.*;
HttpRequest req = HttpRequest.newBuilder()
.uri(URI.create("https://api.infrai.cc/v1/errors/message"))
.header("Authorization", "Bearer " + System.getenv("INFRAI_API_KEY"))
.header("Content-Type", "application/json")
.method("POST", HttpRequest.BodyPublishers.ofString("{\"text\": \"hello\"}"))
.build();
HttpResponse<String> resp = HttpClient.newHttpClient()
.send(req, HttpResponse.BodyHandlers.ofString());
System.out.println(resp.body());// Zero-install REST call — no SDK required (short-term the API is REST-only).
using System;
using System.Net.Http;
var client = new HttpClient();
var req = new HttpRequestMessage(new HttpMethod("POST"), "https://api.infrai.cc/v1/errors/message");
var key = Environment.GetEnvironmentVariable("INFRAI_API_KEY");
req.Headers.Add("Authorization", "Bearer " + key);
req.Content = new StringContent("{\"text\": \"hello\"}", System.Text.Encoding.UTF8, "application/json");
var resp = await client.SendAsync(req);
Console.WriteLine(await resp.Content.ReadAsStringAsync());<?php
// Zero-install REST call — no SDK required (short-term the API is REST-only).
$ch = curl_init("https://api.infrai.cc/v1/errors/message");
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer " . getenv("INFRAI_API_KEY"),
"Content-Type: application/json",
]);
curl_setopt($ch, CURLOPT_POSTFIELDS, "{\"text\": \"hello\"}");
$response = curl_exec($ch);
curl_close($ch);
echo $response;# Zero-install REST call — no SDK required (short-term the API is REST-only).
require "net/http"
require "uri"
uri = URI("https://api.infrai.cc/v1/errors/message")
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
req = Net::HTTP::Post.new(uri)
req["Authorization"] = "Bearer #{ENV['INFRAI_API_KEY']}"
req["Content-Type"] = "application/json"
req.body = '{"text": "hello"}'
res = http.request(req)
puts res.body// Zero-install REST call — no SDK required (short-term the API is REST-only). (uses the reqwest + tokio crates)
use std::env;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let resp = reqwest::Client::new()
.post("https://api.infrai.cc/v1/errors/message")
.header("Authorization", format!("Bearer {}", env::var("INFRAI_API_KEY")?))
.header("Content-Type", "application/json")
.body(r#"{"text": "hello"}"#)
.send()
.await?;
println!("{}", resp.text().await?);
Ok(())
}2.3errors.list
分页列出捕获到的错误事件
参数
| 名称 | 类型 | 必填 | 说明 |
|---|---|---|---|
filter | Record<string, unknown> | 可选 | 过滤条件(观测过滤 DSL) |
cursor | string | 可选 | 分页游标 |
limit | number | 可选 | 每页返回数量 |
返回
ErrorEventList| 名称 | 类型 | 说明 |
|---|---|---|
items | object[] | 本页结果条目数组 |
items[].event_id | string | event的唯一标识符pattern: ^evt_err_[A-Za-z0-9]{20,}$ |
items[].fingerprint | string | 用于分组的 sha256 十六进制指纹。 |
items[].error_group_id | string | 此事件所属的错误分组标识符pattern: ^errgrp_[A-Za-z0-9]{20,}$ |
items[].timestamp | string | 数据点的 Unix 时间戳format: date-time |
items[].level | "debug" | "info" | "warning" | "error" | "fatal" | 严重级别或日志等级(如 info、warn、error) |
items[].title | string | 简短标题或摘要 |
items[].message | string | null | 详细消息内容 |
items[].environment | string | null | 部署环境(如 production、staging) |
items[].release | string | null | 软件发布版本 |
items[].user_id | string | null | 与此资源关联的用户标识符 |
items[].tags | object | null | 分类与筛选标签 |
items[].is_resolved | boolean | 此错误或分组是否被标记为已解决 |
items[].is_ignored | boolean | 此错误或分组是否被标记为已忽略 |
items[].dashboard_url | string | 在仪表盘中查看此资源的 URLformat: uri |
next_cursor | string | null | 获取下一页的不透明游标;null 或不存在表示最后一页 |
total | integer | 跨所有页的总条目数≥ 0 |
示例
一次性前置(每个范例都假定已完成):
# No SDK to install — every call is a plain HTTPS request.
# Get a project key by signing in at https://infrai.cc/login (Google/GitHub gives
# you $2 free credit; email sign-in starts at $0). On 402 INSUFFICIENT_CREDIT, add
# funds at https://infrai.cc/billing (or POST /v1/account/topup and open the
# returned checkout_url).
export INFRAI_API_KEY="ifr_..."curl -X GET https://api.infrai.cc/v1/errors/list \
-H "Authorization: Bearer $INFRAI_API_KEY"# Zero-install REST call — no SDK required (short-term the API is REST-only).
import os, requests
resp = requests.get(
"https://api.infrai.cc/v1/errors/list",
headers={
"Authorization": f"Bearer {os.environ['INFRAI_API_KEY']}",
},
)
resp.raise_for_status()
print(resp.json())// Zero-install REST call — no SDK required (short-term the API is REST-only).
const resp = await fetch(
"https://api.infrai.cc/v1/errors/list",
{
method: "GET",
headers: {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
},
},
);
console.log(await resp.json());// Zero-install REST call — no SDK required (short-term the API is REST-only).
const resp = await fetch(
"https://api.infrai.cc/v1/errors/list",
{
method: "GET",
headers: {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
},
},
);
if (!resp.ok) throw new Error(`infrai ${resp.status}`);
const data: unknown = await resp.json();
console.log(data);// Zero-install REST call — no SDK required (short-term the API is REST-only).
package main
import (
"fmt"
"net/http"
"os"
)
func main() {
req, _ := http.NewRequest("GET", "https://api.infrai.cc/v1/errors/list", nil)
req.Header.Set("Authorization", "Bearer "+os.Getenv("INFRAI_API_KEY"))
resp, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
fmt.Println(resp.Status)
}// Zero-install REST call — no SDK required (short-term the API is REST-only).
import java.net.URI;
import java.net.http.*;
HttpRequest req = HttpRequest.newBuilder()
.uri(URI.create("https://api.infrai.cc/v1/errors/list"))
.header("Authorization", "Bearer " + System.getenv("INFRAI_API_KEY"))
.method("GET", HttpRequest.BodyPublishers.noBody())
.build();
HttpResponse<String> resp = HttpClient.newHttpClient()
.send(req, HttpResponse.BodyHandlers.ofString());
System.out.println(resp.body());// Zero-install REST call — no SDK required (short-term the API is REST-only).
using System;
using System.Net.Http;
var client = new HttpClient();
var req = new HttpRequestMessage(new HttpMethod("GET"), "https://api.infrai.cc/v1/errors/list");
var key = Environment.GetEnvironmentVariable("INFRAI_API_KEY");
req.Headers.Add("Authorization", "Bearer " + key);
var resp = await client.SendAsync(req);
Console.WriteLine(await resp.Content.ReadAsStringAsync());<?php
// Zero-install REST call — no SDK required (short-term the API is REST-only).
$ch = curl_init("https://api.infrai.cc/v1/errors/list");
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "GET");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer " . getenv("INFRAI_API_KEY"),
]);
$response = curl_exec($ch);
curl_close($ch);
echo $response;# Zero-install REST call — no SDK required (short-term the API is REST-only).
require "net/http"
require "uri"
uri = URI("https://api.infrai.cc/v1/errors/list")
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
req = Net::HTTP::Get.new(uri)
req["Authorization"] = "Bearer #{ENV['INFRAI_API_KEY']}"
res = http.request(req)
puts res.body// Zero-install REST call — no SDK required (short-term the API is REST-only). (uses the reqwest + tokio crates)
use std::env;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let resp = reqwest::Client::new()
.get("https://api.infrai.cc/v1/errors/list")
.header("Authorization", format!("Bearer {}", env::var("INFRAI_API_KEY")?))
.send()
.await?;
println!("{}", resp.text().await?);
Ok(())
}2.4errors.search
按关键词搜索错误事件
参数
| 名称 | 类型 | 必填 | 说明 |
|---|---|---|---|
q | string | 必填 | 搜索关键词 |
filter | Record<string, unknown> | 可选 | 过滤条件(观测过滤 DSL) |
cursor | string | 可选 | 分页游标 |
limit | number | 可选 | 每页返回数量 |
返回
ErrorEventList| 名称 | 类型 | 说明 |
|---|---|---|
items | object[] | 本页结果条目数组 |
items[].event_id | string | event的唯一标识符pattern: ^evt_err_[A-Za-z0-9]{20,}$ |
items[].fingerprint | string | 用于分组的 sha256 十六进制指纹。 |
items[].error_group_id | string | 此事件所属的错误分组标识符pattern: ^errgrp_[A-Za-z0-9]{20,}$ |
items[].timestamp | string | 数据点的 Unix 时间戳format: date-time |
items[].level | "debug" | "info" | "warning" | "error" | "fatal" | 严重级别或日志等级(如 info、warn、error) |
items[].title | string | 简短标题或摘要 |
items[].message | string | null | 详细消息内容 |
items[].environment | string | null | 部署环境(如 production、staging) |
items[].release | string | null | 软件发布版本 |
items[].user_id | string | null | 与此资源关联的用户标识符 |
items[].tags | object | null | 分类与筛选标签 |
items[].is_resolved | boolean | 此错误或分组是否被标记为已解决 |
items[].is_ignored | boolean | 此错误或分组是否被标记为已忽略 |
items[].dashboard_url | string | 在仪表盘中查看此资源的 URLformat: uri |
next_cursor | string | null | 获取下一页的不透明游标;null 或不存在表示最后一页 |
total | integer | 跨所有页的总条目数≥ 0 |
示例
一次性前置(每个范例都假定已完成):
# No SDK to install — every call is a plain HTTPS request.
# Get a project key by signing in at https://infrai.cc/login (Google/GitHub gives
# you $2 free credit; email sign-in starts at $0). On 402 INSUFFICIENT_CREDIT, add
# funds at https://infrai.cc/billing (or POST /v1/account/topup and open the
# returned checkout_url).
export INFRAI_API_KEY="ifr_..."curl -X GET https://api.infrai.cc/v1/errors/search \
-H "Authorization: Bearer $INFRAI_API_KEY"# Zero-install REST call — no SDK required (short-term the API is REST-only).
import os, requests
resp = requests.get(
"https://api.infrai.cc/v1/errors/search",
headers={
"Authorization": f"Bearer {os.environ['INFRAI_API_KEY']}",
},
)
resp.raise_for_status()
print(resp.json())// Zero-install REST call — no SDK required (short-term the API is REST-only).
const resp = await fetch(
"https://api.infrai.cc/v1/errors/search",
{
method: "GET",
headers: {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
},
},
);
console.log(await resp.json());// Zero-install REST call — no SDK required (short-term the API is REST-only).
const resp = await fetch(
"https://api.infrai.cc/v1/errors/search",
{
method: "GET",
headers: {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
},
},
);
if (!resp.ok) throw new Error(`infrai ${resp.status}`);
const data: unknown = await resp.json();
console.log(data);// Zero-install REST call — no SDK required (short-term the API is REST-only).
package main
import (
"fmt"
"net/http"
"os"
)
func main() {
req, _ := http.NewRequest("GET", "https://api.infrai.cc/v1/errors/search", nil)
req.Header.Set("Authorization", "Bearer "+os.Getenv("INFRAI_API_KEY"))
resp, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
fmt.Println(resp.Status)
}// Zero-install REST call — no SDK required (short-term the API is REST-only).
import java.net.URI;
import java.net.http.*;
HttpRequest req = HttpRequest.newBuilder()
.uri(URI.create("https://api.infrai.cc/v1/errors/search"))
.header("Authorization", "Bearer " + System.getenv("INFRAI_API_KEY"))
.method("GET", HttpRequest.BodyPublishers.noBody())
.build();
HttpResponse<String> resp = HttpClient.newHttpClient()
.send(req, HttpResponse.BodyHandlers.ofString());
System.out.println(resp.body());// Zero-install REST call — no SDK required (short-term the API is REST-only).
using System;
using System.Net.Http;
var client = new HttpClient();
var req = new HttpRequestMessage(new HttpMethod("GET"), "https://api.infrai.cc/v1/errors/search");
var key = Environment.GetEnvironmentVariable("INFRAI_API_KEY");
req.Headers.Add("Authorization", "Bearer " + key);
var resp = await client.SendAsync(req);
Console.WriteLine(await resp.Content.ReadAsStringAsync());<?php
// Zero-install REST call — no SDK required (short-term the API is REST-only).
$ch = curl_init("https://api.infrai.cc/v1/errors/search");
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "GET");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer " . getenv("INFRAI_API_KEY"),
]);
$response = curl_exec($ch);
curl_close($ch);
echo $response;# Zero-install REST call — no SDK required (short-term the API is REST-only).
require "net/http"
require "uri"
uri = URI("https://api.infrai.cc/v1/errors/search")
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
req = Net::HTTP::Get.new(uri)
req["Authorization"] = "Bearer #{ENV['INFRAI_API_KEY']}"
res = http.request(req)
puts res.body// Zero-install REST call — no SDK required (short-term the API is REST-only). (uses the reqwest + tokio crates)
use std::env;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let resp = reqwest::Client::new()
.get("https://api.infrai.cc/v1/errors/search")
.header("Authorization", format!("Bearer {}", env::var("INFRAI_API_KEY")?))
.send()
.await?;
println!("{}", resp.text().await?);
Ok(())
}2.5errors.get
按事件 ID 获取错误事件详情
参数
| 名称 | 类型 | 必填 | 说明 |
|---|---|---|---|
event_id | string | 必填 | 错误事件 ID |
返回
ErrorEvent| 名称 | 类型 | 说明 |
|---|---|---|
event_id | string | event的唯一标识符pattern: ^evt_err_[A-Za-z0-9]{20,}$ |
fingerprint | string | 用于错误分组的指纹哈希pattern: ^[a-f0-9]{64}$ |
error_group_id | string | 此事件所属的错误分组标识符 |
timestamp | string | 数据点的 Unix 时间戳format: date-time |
level | "debug" | "info" | "warning" | "error" | "fatal" | 严重级别或日志等级(如 info、warn、error) |
title | string | 简短标题或摘要 |
message | string | null | 详细消息内容 |
environment | "production" | "staging" | "development" | null | 部署环境(如 production、staging) |
release | string | null | 软件发布版本 |
user_id | string | null | 关联此资源的用户标识 |
tags | object | 分类与筛选标签 |
is_resolved | boolean | 该错误或分组是否已标记为已解决default: false |
is_ignored | boolean | 该错误或分组是否已标记为已忽略default: false |
exception | object | null | 异常详情,包括类型和堆栈跟踪 |
breadcrumbs | object[] | breadcrumb events leading up to the error列表 |
context | object | 错误的附加上下文数据 |
extra | object | 附加在错误事件上的额外元数据 |
idempotency_key | string | null | errors.capture 的去重键(路由幂等:true)。 |
示例
一次性前置(每个范例都假定已完成):
# No SDK to install — every call is a plain HTTPS request.
# Get a project key by signing in at https://infrai.cc/login (Google/GitHub gives
# you $2 free credit; email sign-in starts at $0). On 402 INSUFFICIENT_CREDIT, add
# funds at https://infrai.cc/billing (or POST /v1/account/topup and open the
# returned checkout_url).
export INFRAI_API_KEY="ifr_..."curl -X GET https://api.infrai.cc/v1/errors/get/EVENT_ID \
-H "Authorization: Bearer $INFRAI_API_KEY"# Zero-install REST call — no SDK required (short-term the API is REST-only).
import os, requests
resp = requests.get(
"https://api.infrai.cc/v1/errors/get/EVENT_ID",
headers={
"Authorization": f"Bearer {os.environ['INFRAI_API_KEY']}",
},
)
resp.raise_for_status()
print(resp.json())// Zero-install REST call — no SDK required (short-term the API is REST-only).
const resp = await fetch(
"https://api.infrai.cc/v1/errors/get/EVENT_ID",
{
method: "GET",
headers: {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
},
},
);
console.log(await resp.json());// Zero-install REST call — no SDK required (short-term the API is REST-only).
const resp = await fetch(
"https://api.infrai.cc/v1/errors/get/EVENT_ID",
{
method: "GET",
headers: {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
},
},
);
if (!resp.ok) throw new Error(`infrai ${resp.status}`);
const data: unknown = await resp.json();
console.log(data);// Zero-install REST call — no SDK required (short-term the API is REST-only).
package main
import (
"fmt"
"net/http"
"os"
)
func main() {
req, _ := http.NewRequest("GET", "https://api.infrai.cc/v1/errors/get/EVENT_ID", nil)
req.Header.Set("Authorization", "Bearer "+os.Getenv("INFRAI_API_KEY"))
resp, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
fmt.Println(resp.Status)
}// Zero-install REST call — no SDK required (short-term the API is REST-only).
import java.net.URI;
import java.net.http.*;
HttpRequest req = HttpRequest.newBuilder()
.uri(URI.create("https://api.infrai.cc/v1/errors/get/EVENT_ID"))
.header("Authorization", "Bearer " + System.getenv("INFRAI_API_KEY"))
.method("GET", HttpRequest.BodyPublishers.noBody())
.build();
HttpResponse<String> resp = HttpClient.newHttpClient()
.send(req, HttpResponse.BodyHandlers.ofString());
System.out.println(resp.body());// Zero-install REST call — no SDK required (short-term the API is REST-only).
using System;
using System.Net.Http;
var client = new HttpClient();
var req = new HttpRequestMessage(new HttpMethod("GET"), "https://api.infrai.cc/v1/errors/get/EVENT_ID");
var key = Environment.GetEnvironmentVariable("INFRAI_API_KEY");
req.Headers.Add("Authorization", "Bearer " + key);
var resp = await client.SendAsync(req);
Console.WriteLine(await resp.Content.ReadAsStringAsync());<?php
// Zero-install REST call — no SDK required (short-term the API is REST-only).
$ch = curl_init("https://api.infrai.cc/v1/errors/get/EVENT_ID");
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "GET");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer " . getenv("INFRAI_API_KEY"),
]);
$response = curl_exec($ch);
curl_close($ch);
echo $response;# Zero-install REST call — no SDK required (short-term the API is REST-only).
require "net/http"
require "uri"
uri = URI("https://api.infrai.cc/v1/errors/get/EVENT_ID")
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
req = Net::HTTP::Get.new(uri)
req["Authorization"] = "Bearer #{ENV['INFRAI_API_KEY']}"
res = http.request(req)
puts res.body// Zero-install REST call — no SDK required (short-term the API is REST-only). (uses the reqwest + tokio crates)
use std::env;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let resp = reqwest::Client::new()
.get("https://api.infrai.cc/v1/errors/get/EVENT_ID")
.header("Authorization", format!("Bearer {}", env::var("INFRAI_API_KEY")?))
.send()
.await?;
println!("{}", resp.text().await?);
Ok(())
}2.6errors.groups
分页列出错误分组
参数
| 名称 | 类型 | 必填 | 说明 |
|---|---|---|---|
status | 'unresolved' | 'resolved' | 'ignored' | 可选 | 按状态过滤:unresolved/resolved/ignored |
sort | 'count_desc' | 'last_seen_desc' | 'first_seen_desc' | 可选 | 排序方式:count_desc/last_seen_desc/first_seen_desc |
cursor | string | 可选 | 分页游标 |
limit | number | 可选 | 每页返回数量 |
返回
ErrorGroupList| 名称 | 类型 | 说明 |
|---|---|---|
groups | object[] | error group objects列表 |
groups[].error_group_id | string | 此事件所属的错误分组标识符pattern: ^errgrp_[A-Za-z0-9]{20,}$ |
groups[].fingerprint | string | 用于错误分组的指纹哈希 |
groups[].title | string | 简短标题或摘要 |
groups[].first_seen_at | string | 首次观测到的 ISO 8601 时间戳format: date-time |
groups[].last_seen_at | string | 最近观测到的 ISO 8601 时间戳format: date-time |
groups[].count | integer | 所有页的条目总数≥ 1 |
groups[].user_count | integer | unique users affected数量≥ 0 |
groups[].level | "debug" | "info" | "warning" | "error" | "fatal" | 严重级别或日志等级(如 info、warn、error) |
groups[].is_resolved | boolean | 此错误或分组是否被标记为已解决 |
groups[].is_ignored | boolean | 此错误或分组是否被标记为已忽略 |
groups[].assigned_to | string | null | 分配调查此错误分组的用户 |
groups[].sample_event_id | string | 此错误分组中的样本事件 IDpattern: ^evt_err_[A-Za-z0-9]{20,}$ |
groups[].environments | string[] | null | environments where this error has been seen列表 |
groups[].releases | string[] | null | software releases where this error has been seen列表 |
groups[].trend_24h | object | null | 包含 current、previous 和 change_pct 的对象。 |
groups[].sparkline | integer[] | null | 用于迷你图的 24 个小时桶事件计数。 |
groups[].dashboard_url | string | 在仪表盘中查看此资源的 URLformat: uri |
next_cursor | string | null | 下一页不透明游标;null 表示结束。 |
total | integer | 跨所有页的总条目数≥ 0 |
示例
一次性前置(每个范例都假定已完成):
# No SDK to install — every call is a plain HTTPS request.
# Get a project key by signing in at https://infrai.cc/login (Google/GitHub gives
# you $2 free credit; email sign-in starts at $0). On 402 INSUFFICIENT_CREDIT, add
# funds at https://infrai.cc/billing (or POST /v1/account/topup and open the
# returned checkout_url).
export INFRAI_API_KEY="ifr_..."curl -X GET https://api.infrai.cc/v1/errors/groups \
-H "Authorization: Bearer $INFRAI_API_KEY"# Zero-install REST call — no SDK required (short-term the API is REST-only).
import os, requests
resp = requests.get(
"https://api.infrai.cc/v1/errors/groups",
headers={
"Authorization": f"Bearer {os.environ['INFRAI_API_KEY']}",
},
)
resp.raise_for_status()
print(resp.json())// Zero-install REST call — no SDK required (short-term the API is REST-only).
const resp = await fetch(
"https://api.infrai.cc/v1/errors/groups",
{
method: "GET",
headers: {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
},
},
);
console.log(await resp.json());// Zero-install REST call — no SDK required (short-term the API is REST-only).
const resp = await fetch(
"https://api.infrai.cc/v1/errors/groups",
{
method: "GET",
headers: {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
},
},
);
if (!resp.ok) throw new Error(`infrai ${resp.status}`);
const data: unknown = await resp.json();
console.log(data);// Zero-install REST call — no SDK required (short-term the API is REST-only).
package main
import (
"fmt"
"net/http"
"os"
)
func main() {
req, _ := http.NewRequest("GET", "https://api.infrai.cc/v1/errors/groups", nil)
req.Header.Set("Authorization", "Bearer "+os.Getenv("INFRAI_API_KEY"))
resp, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
fmt.Println(resp.Status)
}// Zero-install REST call — no SDK required (short-term the API is REST-only).
import java.net.URI;
import java.net.http.*;
HttpRequest req = HttpRequest.newBuilder()
.uri(URI.create("https://api.infrai.cc/v1/errors/groups"))
.header("Authorization", "Bearer " + System.getenv("INFRAI_API_KEY"))
.method("GET", HttpRequest.BodyPublishers.noBody())
.build();
HttpResponse<String> resp = HttpClient.newHttpClient()
.send(req, HttpResponse.BodyHandlers.ofString());
System.out.println(resp.body());// Zero-install REST call — no SDK required (short-term the API is REST-only).
using System;
using System.Net.Http;
var client = new HttpClient();
var req = new HttpRequestMessage(new HttpMethod("GET"), "https://api.infrai.cc/v1/errors/groups");
var key = Environment.GetEnvironmentVariable("INFRAI_API_KEY");
req.Headers.Add("Authorization", "Bearer " + key);
var resp = await client.SendAsync(req);
Console.WriteLine(await resp.Content.ReadAsStringAsync());<?php
// Zero-install REST call — no SDK required (short-term the API is REST-only).
$ch = curl_init("https://api.infrai.cc/v1/errors/groups");
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "GET");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer " . getenv("INFRAI_API_KEY"),
]);
$response = curl_exec($ch);
curl_close($ch);
echo $response;# Zero-install REST call — no SDK required (short-term the API is REST-only).
require "net/http"
require "uri"
uri = URI("https://api.infrai.cc/v1/errors/groups")
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
req = Net::HTTP::Get.new(uri)
req["Authorization"] = "Bearer #{ENV['INFRAI_API_KEY']}"
res = http.request(req)
puts res.body// Zero-install REST call — no SDK required (short-term the API is REST-only). (uses the reqwest + tokio crates)
use std::env;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let resp = reqwest::Client::new()
.get("https://api.infrai.cc/v1/errors/groups")
.header("Authorization", format!("Bearer {}", env::var("INFRAI_API_KEY")?))
.send()
.await?;
println!("{}", resp.text().await?);
Ok(())
}2.7errors.group_detail
获取错误分组的聚合详情
参数
| 名称 | 类型 | 必填 | 说明 |
|---|---|---|---|
error_group_id | string | 必填 | 错误分组 ID |
返回
ErrorGroupDetail| 名称 | 类型 | 说明 |
|---|---|---|
error_group_id | string | 此事件所属的错误分组标识符pattern: ^errgrp_[A-Za-z0-9]{20,}$ |
fingerprint | string | 用于错误分组的指纹哈希 |
title | string | 简短标题或摘要 |
first_seen_at | string | ISO 8601 时间戳:this was first observed(ISO 8601)format: date-time |
last_seen_at | string | ISO 8601 时间戳:this was last observed(ISO 8601)format: date-time |
count | integer | 跨所有页的总条目数≥ 1 |
user_count | integer | unique users affected数量≥ 0 |
level | string | 严重级别或日志等级(如 info、warn、error) |
is_resolved | boolean | 该错误或分组是否已标记为已解决 |
is_ignored | boolean | 该错误或分组是否已标记为已忽略 |
assigned_to | string | null | 分配调查此错误分组的用户 |
sample_event_id | string | 此错误分组中的样本事件 ID |
environments | string[] | null | environments where this error has been seen列表 |
releases | string[] | null | software releases where this error has been seen列表 |
trend_24h | object | null | 此错误分组的 24 小时趋势数据 |
sparkline | integer[] | null | 用于错误频率可视化的迷你图数据点 |
dashboard_url | string | 在控制台中查看此资源的 URLformat: uri |
representative_event | object | 此分组的代表性错误事件 |
representative_event.event_id | string | event的唯一标识符pattern: ^evt_err_[A-Za-z0-9]{20,}$ |
representative_event.fingerprint | string | 用于错误分组的指纹哈希 |
representative_event.error_group_id | string | 此事件所属的错误分组标识符pattern: ^errgrp_[A-Za-z0-9]{20,}$ |
representative_event.timestamp | string | 数据点的 Unix 时间戳format: date-time |
representative_event.level | "debug" | "info" | "warning" | "error" | "fatal" | 严重级别或日志等级(如 info、warn、error) |
representative_event.title | string | 简短标题或摘要 |
representative_event.message | string | null | 详细消息内容 |
representative_event.environment | string | null | 部署环境(如 production、staging) |
representative_event.release | string | null | 软件发布版本 |
representative_event.user_id | string | null | 与此资源关联的用户标识符 |
representative_event.tags | object | null | 分类与筛选标签 |
representative_event.is_resolved | boolean | 此错误或分组是否被标记为已解决 |
representative_event.is_ignored | boolean | 此错误或分组是否被标记为已忽略 |
representative_event.dashboard_url | string | 在仪表盘中查看此资源的 URLformat: uri |
representative_event.exception | object | 异常详情,包括类型和堆栈跟踪 |
representative_event.exception.type | string | 异常类名,如 "NullPointerException"。 |
representative_event.exception.value | string | 异常消息。 |
representative_event.exception.stacktrace | object[] | 错误堆栈跟踪 |
representative_event.exception.stacktrace[].func | string | 堆栈帧中的函数名 |
representative_event.exception.stacktrace[].file | string | 堆栈帧中的源文件名 |
representative_event.exception.stacktrace[].line | integer | 源文件行号≥ 0 |
representative_event.exception.stacktrace[].col | integer | null | 源文件列号≥ 0 |
representative_event.exception.stacktrace[].in_app | boolean | 为 true 表示该帧在用户代码中;false 表示来自 SDK/标准库。 |
representative_event.exception.stacktrace[].context_pre | string[] | null | 错误行之前最多 5 行源代码。 |
representative_event.exception.stacktrace[].context_line | string | null | 发生错误的源代码行。 |
representative_event.exception.stacktrace[].context_post | string[] | null | 错误行之后的源代码行 |
representative_event.exception.stacktrace[].vars | object | null | 局部变量快照(已清理 PII)。 |
representative_event.breadcrumbs | object[] | breadcrumb events leading up to the error列表 |
representative_event.breadcrumbs[].at | string | 事件的 ISO 8601 时间戳format: date-time |
representative_event.breadcrumbs[].category | string | 同意类别(如 marketing、analytics)e.g. http |
representative_event.breadcrumbs[].message | string | 详细消息内容 |
representative_event.breadcrumbs[].level | "debug" | "info" | "warning" | "error" | "critical" | null | 严重级别或日志等级(如 info、warn、error) |
representative_event.breadcrumbs[].data | object | null | 附加到此面包屑的自由结构化数据。 |
representative_event.context | object | null | 错误的附加上下文数据 |
representative_event.extra | object | null | 附加在错误事件上的额外元数据 |
representative_event.sdk | object | null | 包含 name 和 version 的对象。 |
representative_event.runtime | object | null | 包含 name、version 和 os 的对象。 |
representative_event.request | object | null | HTTP 请求信息(已清理)。 |
representative_event.user | object | null | 用户信息(已清理)。 |
representative_event.fingerprint_source | "default" | "user" | "rule" | 错误指纹来源 |
representative_event.received_at | string | 服务端接收错误的 ISO 8601 时间戳format: date-time |
representative_event.group_first_seen_at | string | 此分组首次出现的 ISO 8601 时间戳format: date-time |
representative_event.group_last_seen_at | string | 此分组最后出现的 ISO 8601 时间戳format: date-time |
representative_event.group_count | integer | events in this error group数量≥ 1 |
representative_event.group_user_count | integer | unique users affected in this group数量≥ 0 |
tag_distribution | object | null | tag 名称到计数的映射对象。 |
user_distribution | object | null | 受影响最多的用户:user_id 到计数的映射对象。 |
release_distribution | object | null | 事件在各软件版本中的分布 |
environment_distribution | object | null | 事件在各环境中的分布 |
timeline | object[] | null | 24 小时时间序列数据点。 |
comments | object[] | null | comments on this error group列表 |
activity_log | object[] | null | activity log entries for the error group列表 |
示例
一次性前置(每个范例都假定已完成):
# No SDK to install — every call is a plain HTTPS request.
# Get a project key by signing in at https://infrai.cc/login (Google/GitHub gives
# you $2 free credit; email sign-in starts at $0). On 402 INSUFFICIENT_CREDIT, add
# funds at https://infrai.cc/billing (or POST /v1/account/topup and open the
# returned checkout_url).
export INFRAI_API_KEY="ifr_..."curl -X GET https://api.infrai.cc/v1/errors/group_detail/ERROR_GROUP_ID \
-H "Authorization: Bearer $INFRAI_API_KEY"# Zero-install REST call — no SDK required (short-term the API is REST-only).
import os, requests
resp = requests.get(
"https://api.infrai.cc/v1/errors/group_detail/ERROR_GROUP_ID",
headers={
"Authorization": f"Bearer {os.environ['INFRAI_API_KEY']}",
},
)
resp.raise_for_status()
print(resp.json())// Zero-install REST call — no SDK required (short-term the API is REST-only).
const resp = await fetch(
"https://api.infrai.cc/v1/errors/group_detail/ERROR_GROUP_ID",
{
method: "GET",
headers: {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
},
},
);
console.log(await resp.json());// Zero-install REST call — no SDK required (short-term the API is REST-only).
const resp = await fetch(
"https://api.infrai.cc/v1/errors/group_detail/ERROR_GROUP_ID",
{
method: "GET",
headers: {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
},
},
);
if (!resp.ok) throw new Error(`infrai ${resp.status}`);
const data: unknown = await resp.json();
console.log(data);// Zero-install REST call — no SDK required (short-term the API is REST-only).
package main
import (
"fmt"
"net/http"
"os"
)
func main() {
req, _ := http.NewRequest("GET", "https://api.infrai.cc/v1/errors/group_detail/ERROR_GROUP_ID", nil)
req.Header.Set("Authorization", "Bearer "+os.Getenv("INFRAI_API_KEY"))
resp, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
fmt.Println(resp.Status)
}// Zero-install REST call — no SDK required (short-term the API is REST-only).
import java.net.URI;
import java.net.http.*;
HttpRequest req = HttpRequest.newBuilder()
.uri(URI.create("https://api.infrai.cc/v1/errors/group_detail/ERROR_GROUP_ID"))
.header("Authorization", "Bearer " + System.getenv("INFRAI_API_KEY"))
.method("GET", HttpRequest.BodyPublishers.noBody())
.build();
HttpResponse<String> resp = HttpClient.newHttpClient()
.send(req, HttpResponse.BodyHandlers.ofString());
System.out.println(resp.body());// Zero-install REST call — no SDK required (short-term the API is REST-only).
using System;
using System.Net.Http;
var client = new HttpClient();
var req = new HttpRequestMessage(new HttpMethod("GET"), "https://api.infrai.cc/v1/errors/group_detail/ERROR_GROUP_ID");
var key = Environment.GetEnvironmentVariable("INFRAI_API_KEY");
req.Headers.Add("Authorization", "Bearer " + key);
var resp = await client.SendAsync(req);
Console.WriteLine(await resp.Content.ReadAsStringAsync());<?php
// Zero-install REST call — no SDK required (short-term the API is REST-only).
$ch = curl_init("https://api.infrai.cc/v1/errors/group_detail/ERROR_GROUP_ID");
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "GET");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer " . getenv("INFRAI_API_KEY"),
]);
$response = curl_exec($ch);
curl_close($ch);
echo $response;# Zero-install REST call — no SDK required (short-term the API is REST-only).
require "net/http"
require "uri"
uri = URI("https://api.infrai.cc/v1/errors/group_detail/ERROR_GROUP_ID")
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
req = Net::HTTP::Get.new(uri)
req["Authorization"] = "Bearer #{ENV['INFRAI_API_KEY']}"
res = http.request(req)
puts res.body// Zero-install REST call — no SDK required (short-term the API is REST-only). (uses the reqwest + tokio crates)
use std::env;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let resp = reqwest::Client::new()
.get("https://api.infrai.cc/v1/errors/group_detail/ERROR_GROUP_ID")
.header("Authorization", format!("Bearer {}", env::var("INFRAI_API_KEY")?))
.send()
.await?;
println!("{}", resp.text().await?);
Ok(())
}2.8errors.events
列出某错误分组下的事件
参数
| 名称 | 类型 | 必填 | 说明 |
|---|---|---|---|
error_group_id | string | 必填 | 错误分组 ID |
cursor | string | 可选 | 分页游标 |
limit | number | 可选 | 每页返回数量 |
返回
ErrorEventList| 名称 | 类型 | 说明 |
|---|---|---|
items | object[] | 本页结果条目数组 |
items[].event_id | string | event的唯一标识符pattern: ^evt_err_[A-Za-z0-9]{20,}$ |
items[].fingerprint | string | 用于分组的 sha256 十六进制指纹。 |
items[].error_group_id | string | 此事件所属的错误分组标识符pattern: ^errgrp_[A-Za-z0-9]{20,}$ |
items[].timestamp | string | 数据点的 Unix 时间戳format: date-time |
items[].level | "debug" | "info" | "warning" | "error" | "fatal" | 严重级别或日志等级(如 info、warn、error) |
items[].title | string | 简短标题或摘要 |
items[].message | string | null | 详细消息内容 |
items[].environment | string | null | 部署环境(如 production、staging) |
items[].release | string | null | 软件发布版本 |
items[].user_id | string | null | 与此资源关联的用户标识符 |
items[].tags | object | null | 分类与筛选标签 |
items[].is_resolved | boolean | 此错误或分组是否被标记为已解决 |
items[].is_ignored | boolean | 此错误或分组是否被标记为已忽略 |
items[].dashboard_url | string | 在仪表盘中查看此资源的 URLformat: uri |
next_cursor | string | null | 获取下一页的不透明游标;null 或不存在表示最后一页 |
total | integer | 跨所有页的总条目数≥ 0 |
示例
一次性前置(每个范例都假定已完成):
# No SDK to install — every call is a plain HTTPS request.
# Get a project key by signing in at https://infrai.cc/login (Google/GitHub gives
# you $2 free credit; email sign-in starts at $0). On 402 INSUFFICIENT_CREDIT, add
# funds at https://infrai.cc/billing (or POST /v1/account/topup and open the
# returned checkout_url).
export INFRAI_API_KEY="ifr_..."curl -X GET https://api.infrai.cc/v1/errors/events/ERROR_GROUP_ID \
-H "Authorization: Bearer $INFRAI_API_KEY"# Zero-install REST call — no SDK required (short-term the API is REST-only).
import os, requests
resp = requests.get(
"https://api.infrai.cc/v1/errors/events/ERROR_GROUP_ID",
headers={
"Authorization": f"Bearer {os.environ['INFRAI_API_KEY']}",
},
)
resp.raise_for_status()
print(resp.json())// Zero-install REST call — no SDK required (short-term the API is REST-only).
const resp = await fetch(
"https://api.infrai.cc/v1/errors/events/ERROR_GROUP_ID",
{
method: "GET",
headers: {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
},
},
);
console.log(await resp.json());// Zero-install REST call — no SDK required (short-term the API is REST-only).
const resp = await fetch(
"https://api.infrai.cc/v1/errors/events/ERROR_GROUP_ID",
{
method: "GET",
headers: {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
},
},
);
if (!resp.ok) throw new Error(`infrai ${resp.status}`);
const data: unknown = await resp.json();
console.log(data);// Zero-install REST call — no SDK required (short-term the API is REST-only).
package main
import (
"fmt"
"net/http"
"os"
)
func main() {
req, _ := http.NewRequest("GET", "https://api.infrai.cc/v1/errors/events/ERROR_GROUP_ID", nil)
req.Header.Set("Authorization", "Bearer "+os.Getenv("INFRAI_API_KEY"))
resp, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
fmt.Println(resp.Status)
}// Zero-install REST call — no SDK required (short-term the API is REST-only).
import java.net.URI;
import java.net.http.*;
HttpRequest req = HttpRequest.newBuilder()
.uri(URI.create("https://api.infrai.cc/v1/errors/events/ERROR_GROUP_ID"))
.header("Authorization", "Bearer " + System.getenv("INFRAI_API_KEY"))
.method("GET", HttpRequest.BodyPublishers.noBody())
.build();
HttpResponse<String> resp = HttpClient.newHttpClient()
.send(req, HttpResponse.BodyHandlers.ofString());
System.out.println(resp.body());// Zero-install REST call — no SDK required (short-term the API is REST-only).
using System;
using System.Net.Http;
var client = new HttpClient();
var req = new HttpRequestMessage(new HttpMethod("GET"), "https://api.infrai.cc/v1/errors/events/ERROR_GROUP_ID");
var key = Environment.GetEnvironmentVariable("INFRAI_API_KEY");
req.Headers.Add("Authorization", "Bearer " + key);
var resp = await client.SendAsync(req);
Console.WriteLine(await resp.Content.ReadAsStringAsync());<?php
// Zero-install REST call — no SDK required (short-term the API is REST-only).
$ch = curl_init("https://api.infrai.cc/v1/errors/events/ERROR_GROUP_ID");
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "GET");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer " . getenv("INFRAI_API_KEY"),
]);
$response = curl_exec($ch);
curl_close($ch);
echo $response;# Zero-install REST call — no SDK required (short-term the API is REST-only).
require "net/http"
require "uri"
uri = URI("https://api.infrai.cc/v1/errors/events/ERROR_GROUP_ID")
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
req = Net::HTTP::Get.new(uri)
req["Authorization"] = "Bearer #{ENV['INFRAI_API_KEY']}"
res = http.request(req)
puts res.body// Zero-install REST call — no SDK required (short-term the API is REST-only). (uses the reqwest + tokio crates)
use std::env;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let resp = reqwest::Client::new()
.get("https://api.infrai.cc/v1/errors/events/ERROR_GROUP_ID")
.header("Authorization", format!("Bearer {}", env::var("INFRAI_API_KEY")?))
.send()
.await?;
println!("{}", resp.text().await?);
Ok(())
}2.9errors.resolve
将错误分组标记为已解决
参数
| 名称 | 类型 | 必填 | 说明 |
|---|---|---|---|
error_group_id | string | 必填 | 错误分组 IDpattern: ^errgrp_[A-Za-z0-9]{20,}$ |
返回
ErrorGroup| 名称 | 类型 | 说明 |
|---|---|---|
error_group_id | string | 此事件所属的错误分组标识符pattern: ^errgrp_[A-Za-z0-9]{20,}$ |
fingerprint | string | 用于错误分组的指纹哈希 |
title | string | 简短标题或摘要 |
first_seen_at | string | 首次观测到的 ISO 8601 时间戳format: date-time |
last_seen_at | string | 最近观测到的 ISO 8601 时间戳format: date-time |
count | integer | 所有页的条目总数≥ 1 |
user_count | integer | unique users affected数量≥ 0 |
level | string | 严重级别或日志等级(如 info、warn、error) |
is_resolved | boolean | 此错误或分组是否被标记为已解决 |
is_ignored | boolean | 此错误或分组是否被标记为已忽略 |
assigned_to | string | null | 分配调查此错误分组的用户 |
sample_event_id | string | 此错误分组中的样本事件 ID |
environments | string[] | null | environments where this error has been seen列表 |
releases | string[] | null | software releases where this error has been seen列表 |
trend_24h | object | null | 此错误分组的 24 小时趋势数据 |
sparkline | integer[] | null | 用于错误频率可视化的迷你图数据点 |
dashboard_url | string | 在仪表盘中查看此资源的 URLformat: uri |
representative_event | object | 此分组的代表性错误事件 |
representative_event.event_id | string | event的唯一标识符pattern: ^evt_err_[A-Za-z0-9]{20,}$ |
representative_event.fingerprint | string | 用于错误分组的指纹哈希 |
representative_event.error_group_id | string | 此事件所属的错误分组标识符pattern: ^errgrp_[A-Za-z0-9]{20,}$ |
representative_event.timestamp | string | 数据点的 Unix 时间戳format: date-time |
representative_event.level | "debug" | "info" | "warning" | "error" | "fatal" | 严重级别或日志等级(如 info、warn、error) |
representative_event.title | string | 简短标题或摘要 |
representative_event.message | string | null | 详细消息内容 |
representative_event.environment | string | null | 部署环境(如 production、staging) |
representative_event.release | string | null | 软件发布版本 |
representative_event.user_id | string | null | 与此资源关联的用户标识符 |
representative_event.tags | object | null | 分类与筛选标签 |
representative_event.is_resolved | boolean | 此错误或分组是否被标记为已解决 |
representative_event.is_ignored | boolean | 此错误或分组是否被标记为已忽略 |
representative_event.dashboard_url | string | 在仪表盘中查看此资源的 URLformat: uri |
representative_event.exception | object | 异常详情,包括类型和堆栈跟踪 |
representative_event.exception.type | string | 异常类名,如 "NullPointerException"。 |
representative_event.exception.value | string | 异常消息。 |
representative_event.exception.stacktrace | object[] | 错误堆栈跟踪 |
representative_event.exception.stacktrace[].func | string | 堆栈帧中的函数名 |
representative_event.exception.stacktrace[].file | string | 堆栈帧中的源文件名 |
representative_event.exception.stacktrace[].line | integer | 源文件行号≥ 0 |
representative_event.exception.stacktrace[].col | integer | null | 源文件列号≥ 0 |
representative_event.exception.stacktrace[].in_app | boolean | 为 true 表示该帧在用户代码中;false 表示来自 SDK/标准库。 |
representative_event.exception.stacktrace[].context_pre | string[] | null | 错误行之前最多 5 行源代码。 |
representative_event.exception.stacktrace[].context_line | string | null | 发生错误的源代码行。 |
representative_event.exception.stacktrace[].context_post | string[] | null | 错误行之后的源代码行 |
representative_event.exception.stacktrace[].vars | object | null | 局部变量快照(已清理 PII)。 |
representative_event.breadcrumbs | object[] | breadcrumb events leading up to the error列表 |
representative_event.breadcrumbs[].at | string | 事件的 ISO 8601 时间戳format: date-time |
representative_event.breadcrumbs[].category | string | 同意类别(如 marketing、analytics)e.g. http |
representative_event.breadcrumbs[].message | string | 详细消息内容 |
representative_event.breadcrumbs[].level | "debug" | "info" | "warning" | "error" | "critical" | null | 严重级别或日志等级(如 info、warn、error) |
representative_event.breadcrumbs[].data | object | null | 附加到此面包屑的自由结构化数据。 |
representative_event.context | object | null | 错误的附加上下文数据 |
representative_event.extra | object | null | 附加在错误事件上的额外元数据 |
representative_event.sdk | object | null | 包含 name 和 version 的对象。 |
representative_event.runtime | object | null | 包含 name、version 和 os 的对象。 |
representative_event.request | object | null | HTTP 请求信息(已清理)。 |
representative_event.user | object | null | 用户信息(已清理)。 |
representative_event.fingerprint_source | "default" | "user" | "rule" | 错误指纹来源 |
representative_event.received_at | string | 服务端接收错误的 ISO 8601 时间戳format: date-time |
representative_event.group_first_seen_at | string | 此分组首次出现的 ISO 8601 时间戳format: date-time |
representative_event.group_last_seen_at | string | 此分组最后出现的 ISO 8601 时间戳format: date-time |
representative_event.group_count | integer | events in this error group数量≥ 1 |
representative_event.group_user_count | integer | unique users affected in this group数量≥ 0 |
tag_distribution | object | null | tag 名称到计数的映射对象。 |
user_distribution | object | null | 受影响最多的用户:user_id 到计数的映射对象。 |
release_distribution | object | null | 事件在各软件版本中的分布 |
environment_distribution | object | null | 事件在各环境中的分布 |
timeline | object[] | null | 24 小时时间序列数据点。 |
comments | object[] | null | comments on this error group列表 |
activity_log | object[] | null | activity log entries for the error group列表 |
示例
一次性前置(每个范例都假定已完成):
# No SDK to install — every call is a plain HTTPS request.
# Get a project key by signing in at https://infrai.cc/login (Google/GitHub gives
# you $2 free credit; email sign-in starts at $0). On 402 INSUFFICIENT_CREDIT, add
# funds at https://infrai.cc/billing (or POST /v1/account/topup and open the
# returned checkout_url).
export INFRAI_API_KEY="ifr_..."curl -X POST https://api.infrai.cc/v1/errors/resolve/ERROR_GROUP_ID \
-H "Authorization: Bearer $INFRAI_API_KEY" \
-H "Content-Type: application/json" \
-d '{"error_group_id": "sample"}'# Zero-install REST call — no SDK required (short-term the API is REST-only).
import os, requests
resp = requests.post(
"https://api.infrai.cc/v1/errors/resolve/ERROR_GROUP_ID",
headers={
"Authorization": f"Bearer {os.environ['INFRAI_API_KEY']}",
},
json={'error_group_id': 'sample'},
)
resp.raise_for_status()
print(resp.json())// Zero-install REST call — no SDK required (short-term the API is REST-only).
const resp = await fetch(
"https://api.infrai.cc/v1/errors/resolve/ERROR_GROUP_ID",
{
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({"error_group_id": "sample"}),
},
);
console.log(await resp.json());// Zero-install REST call — no SDK required (short-term the API is REST-only).
const resp = await fetch(
"https://api.infrai.cc/v1/errors/resolve/ERROR_GROUP_ID",
{
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({"error_group_id": "sample"}),
},
);
if (!resp.ok) throw new Error(`infrai ${resp.status}`);
const data: unknown = await resp.json();
console.log(data);// Zero-install REST call — no SDK required (short-term the API is REST-only).
package main
import (
"bytes"
"fmt"
"net/http"
"os"
)
func main() {
body := []byte(`{"error_group_id": "sample"}`)
req, _ := http.NewRequest("POST", "https://api.infrai.cc/v1/errors/resolve/ERROR_GROUP_ID", bytes.NewReader(body))
req.Header.Set("Authorization", "Bearer "+os.Getenv("INFRAI_API_KEY"))
req.Header.Set("Content-Type", "application/json")
resp, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
fmt.Println(resp.Status)
}// Zero-install REST call — no SDK required (short-term the API is REST-only).
import java.net.URI;
import java.net.http.*;
HttpRequest req = HttpRequest.newBuilder()
.uri(URI.create("https://api.infrai.cc/v1/errors/resolve/ERROR_GROUP_ID"))
.header("Authorization", "Bearer " + System.getenv("INFRAI_API_KEY"))
.header("Content-Type", "application/json")
.method("POST", HttpRequest.BodyPublishers.ofString("{\"error_group_id\": \"sample\"}"))
.build();
HttpResponse<String> resp = HttpClient.newHttpClient()
.send(req, HttpResponse.BodyHandlers.ofString());
System.out.println(resp.body());// Zero-install REST call — no SDK required (short-term the API is REST-only).
using System;
using System.Net.Http;
var client = new HttpClient();
var req = new HttpRequestMessage(new HttpMethod("POST"), "https://api.infrai.cc/v1/errors/resolve/ERROR_GROUP_ID");
var key = Environment.GetEnvironmentVariable("INFRAI_API_KEY");
req.Headers.Add("Authorization", "Bearer " + key);
req.Content = new StringContent("{\"error_group_id\": \"sample\"}", System.Text.Encoding.UTF8, "application/json");
var resp = await client.SendAsync(req);
Console.WriteLine(await resp.Content.ReadAsStringAsync());<?php
// Zero-install REST call — no SDK required (short-term the API is REST-only).
$ch = curl_init("https://api.infrai.cc/v1/errors/resolve/ERROR_GROUP_ID");
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer " . getenv("INFRAI_API_KEY"),
"Content-Type: application/json",
]);
curl_setopt($ch, CURLOPT_POSTFIELDS, "{\"error_group_id\": \"sample\"}");
$response = curl_exec($ch);
curl_close($ch);
echo $response;# Zero-install REST call — no SDK required (short-term the API is REST-only).
require "net/http"
require "uri"
uri = URI("https://api.infrai.cc/v1/errors/resolve/ERROR_GROUP_ID")
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
req = Net::HTTP::Post.new(uri)
req["Authorization"] = "Bearer #{ENV['INFRAI_API_KEY']}"
req["Content-Type"] = "application/json"
req.body = '{"error_group_id": "sample"}'
res = http.request(req)
puts res.body// Zero-install REST call — no SDK required (short-term the API is REST-only). (uses the reqwest + tokio crates)
use std::env;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let resp = reqwest::Client::new()
.post("https://api.infrai.cc/v1/errors/resolve/ERROR_GROUP_ID")
.header("Authorization", format!("Bearer {}", env::var("INFRAI_API_KEY")?))
.header("Content-Type", "application/json")
.body(r#"{"error_group_id": "sample"}"#)
.send()
.await?;
println!("{}", resp.text().await?);
Ok(())
}3. 全部能力
本模块全部已路由能力——完整的对外 REST 契约。上方方法是带讲解的入门示例,此表是完整参考。
errors.capturePOST /v1/errors/captureCapture an error event, aggregated into a group by fingerprint.
参数 (13)
| 名称 | 类型 | 必填 | 说明 |
|---|---|---|---|
title | string | null | 可选 | Short error title; falls back to message or exception.value. |
message | string | null | 可选 | Detailed message content |
exception | object | null | 可选 | Structured exception, e.g. {type, value, stacktrace}. |
level | string | 可选 | Severity level (e.g. error, warning, info).default: "error" |
tags | object | null | 可选 | Tags for categorization and filtering |
user_id | string | null | 可选 | User identifier associated with this resource |
fingerprint | string | string[] | null | 可选 | Grouping fingerprint. |
breadcrumbs | object[] | null | 可选 | List of breadcrumb events leading up to the error |
context | object | null | 可选 | Additional context data for the error |
extra | object | null | 可选 | Extra metadata attached to the error event |
environment | string | null | 可选 | Deployment environment (e.g. production, staging) |
release | string | null | 可选 | Software release version |
idempotency_key | string | null | 可选 | Client-provided idempotency key; prevents duplicate execution on retry |
errors.eventsGET /v1/errors/events/{error_group_id}Page through all events within an error group.
参数 (1)
| 名称 | 类型 | 必填 | 说明 |
|---|---|---|---|
error_group_id | string | 必填 | Path parameter. |
errors.getGET /v1/errors/get/{event_id}Get the details of one error event by event ID.
参数 (1)
| 名称 | 类型 | 必填 | 说明 |
|---|---|---|---|
event_id | string | 必填 | Path parameter. |
errors.group_detailGET /v1/errors/group_detail/{error_group_id}Get the aggregated details of a specified error group.
参数 (1)
| 名称 | 类型 | 必填 | 说明 |
|---|---|---|---|
error_group_id | string | 必填 | Path parameter. |
errors.groupsGET /v1/errors/groupsPage through error groups, with status filtering and sorting.
无请求参数。
errors.listGET /v1/errors/listPage through captured error events, with filtering.
无请求参数。
errors.messagePOST /v1/errors/messageCapture a structured error/log message (level, tags, user, release, environment).
参数 (7)
| 名称 | 类型 | 必填 | 说明 |
|---|---|---|---|
text | string | 必填 | Message body; becomes the event title.≥ 1 chars |
level | "debug" | "info" | "warning" | "error" | "fatal" | 可选 | Severity or log level (e.g. info, warn, error)default: "info" |
tags | object | null | 可选 | Tags for categorization and filtering |
user_id | string | null | 可选 | User identifier associated with this resource |
release | string | null | 可选 | Software release version |
environment | "production" | "staging" | "development" | null | 可选 | Deployment environment (e.g. production, staging) |
idempotency_key | string | null | 可选 | Client-provided idempotency key; prevents duplicate execution on retry |
errors.resolvePOST /v1/errors/resolve/{error_group_id}Mark an error group as resolved.
参数 (1)
| 名称 | 类型 | 必填 | 说明 |
|---|---|---|---|
error_group_id | string | 必填 | Identifier of the error group this event belongs topattern: ^errgrp_[A-Za-z0-9]{20,}$ |
errors.searchGET /v1/errors/searchFull-text search error events by keyword.
无请求参数。
4. 完整示例
本模块的生产级端到端范例:先一次性配置,再运行业务流程,尽量覆盖本模块的多数 API。
单文件可运行 Python 程序(仅标准库、无 SDK):拷贝后填入 INFRAI_API_KEY 运行,即可按真实业务流逐步体验本模块核心 API——每一步都真实调用并计费,后续步骤复用前一步返回的真实字段。12 行 helper 就是全部集成代码。
#!/usr/bin/env python3
"""Infrai · errors — runnable real-app example (single file, zero deps).
Copy this file, set your key, run it: every step is a REAL call to
api.infrai.cc, billed at the real (tiny) per-call price, printing the
live JSON response. Get a key at https://infrai.cc/login (Google/
GitHub sign-in grants $2 free credit); add funds at
https://infrai.cc/billing. No SDK — the 12-line helper below is the
entire integration."""
import json
import os
from urllib import error, request
KEY = os.environ.get("INFRAI_API_KEY") or "ifr_..." # <- your key
BASE = "https://api.infrai.cc"
# Same raw HTTPS POST/GET as every per-method example on this page —
# wrapped once for reuse. There is nothing else to it: no SDK.
def infrai(method, path, body=None):
req = request.Request(
BASE + path, method=method,
data=json.dumps(body).encode() if body is not None else None,
headers={"Authorization": f"Bearer {KEY}",
"Content-Type": "application/json"})
try:
with request.urlopen(req, timeout=60) as r:
return json.loads(r.read())
except error.HTTPError as e:
return json.loads(e.read())
def show(label, resp):
print(f"\n== {label} ==")
print(json.dumps(resp, indent=2, ensure_ascii=False))
return resp
# 1) errors.capture — POST /v1/errors/capture · Capture an error event, aggregated into a group by fingerprint.
r1 = show("errors.capture", infrai("POST", "/v1/errors/capture", {"exception":{"type":"ValueError","message":"bad input","stacktrace":"..."},"level":"error"}))
# 2) errors.message — POST /v1/errors/message · Capture a structured error/log message (level, tags, user, release, environment).
r2 = show("errors.message", infrai("POST", "/v1/errors/message", {"text":"hello"}))
# 3) errors.list — GET /v1/errors/list · Page through captured error events, with filtering.
r3 = show("errors.list", infrai("GET", "/v1/errors/list"))
一次性前置(每个范例都假定已完成):
# No SDK to install — every call is a plain HTTPS request.
# Get a project key by signing in at https://infrai.cc/login (Google/GitHub gives
# you $2 free credit; email sign-in starts at $0). On 402 INSUFFICIENT_CREDIT, add
# funds at https://infrai.cc/billing (or POST /v1/account/topup and open the
# returned checkout_url).
export INFRAI_API_KEY="ifr_..."# 1) Auth: every call is a raw HTTPS request to the Infrai gateway carrying
# only your project key. No SDK, no install.
# Get your key: sign in with Google/GitHub at https://infrai.cc/login for a
# project key + $2 free credit (email sign-in starts at $0). On 402
# INSUFFICIENT_CREDIT, add funds at https://infrai.cc/billing (or POST
# /v1/account/topup and open the returned checkout_url).
export INFRAI_API_KEY="ifr_..." # from https://infrai.cc/login
# 2) errors.capture
curl -X POST https://api.infrai.cc/v1/errors/capture \
-H "Authorization: Bearer $INFRAI_API_KEY" \
-H "Content-Type: application/json" \
-d '{"exception": {"type": "ValueError", "message": "bad input", "stacktrace": "..."}, "level": "error"}'
# 3) errors.message
curl -X POST https://api.infrai.cc/v1/errors/message \
-H "Authorization: Bearer $INFRAI_API_KEY" \
-H "Content-Type: application/json" \
-d '{"text": "hello"}'
# 4) errors.list
curl -X GET https://api.infrai.cc/v1/errors/list \
-H "Authorization: Bearer $INFRAI_API_KEY"
# 5) errors.search
curl -X GET https://api.infrai.cc/v1/errors/search \
-H "Authorization: Bearer $INFRAI_API_KEY"
# 6) errors.get
curl -X GET https://api.infrai.cc/v1/errors/get/EVENT_ID \
-H "Authorization: Bearer $INFRAI_API_KEY"
# 7) errors.groups
curl -X GET https://api.infrai.cc/v1/errors/groups \
-H "Authorization: Bearer $INFRAI_API_KEY"
# 8) errors.group_detail
curl -X GET https://api.infrai.cc/v1/errors/group_detail/ERROR_GROUP_ID \
-H "Authorization: Bearer $INFRAI_API_KEY"
# 9) errors.events
curl -X GET https://api.infrai.cc/v1/errors/events/ERROR_GROUP_ID \
-H "Authorization: Bearer $INFRAI_API_KEY"
# 1) Auth: every call is a raw HTTPS request carrying only your project key.
# No SDK to install — just the `requests` library.
import os, requests
BASE = "https://api.infrai.cc"
HEADERS = {
"Authorization": f"Bearer {os.environ['INFRAI_API_KEY']}",
"Content-Type": "application/json",
}
# 2) errors.capture
# Zero-install REST call — no SDK required (short-term the API is REST-only).
import os, requests
resp = requests.post(
"https://api.infrai.cc/v1/errors/capture",
headers={
"Authorization": f"Bearer {os.environ['INFRAI_API_KEY']}",
},
json={'exception': {'type': 'ValueError', 'message': 'bad input', 'stacktrace': '...'}, 'level': 'error'},
)
resp.raise_for_status()
print(resp.json())
# 3) errors.message
# Zero-install REST call — no SDK required (short-term the API is REST-only).
import os, requests
resp = requests.post(
"https://api.infrai.cc/v1/errors/message",
headers={
"Authorization": f"Bearer {os.environ['INFRAI_API_KEY']}",
},
json={'text': 'hello'},
)
resp.raise_for_status()
print(resp.json())
# 4) errors.list
# Zero-install REST call — no SDK required (short-term the API is REST-only).
import os, requests
resp = requests.get(
"https://api.infrai.cc/v1/errors/list",
headers={
"Authorization": f"Bearer {os.environ['INFRAI_API_KEY']}",
},
)
resp.raise_for_status()
print(resp.json())
# 5) errors.search
# Zero-install REST call — no SDK required (short-term the API is REST-only).
import os, requests
resp = requests.get(
"https://api.infrai.cc/v1/errors/search",
headers={
"Authorization": f"Bearer {os.environ['INFRAI_API_KEY']}",
},
)
resp.raise_for_status()
print(resp.json())
# 6) errors.get
# Zero-install REST call — no SDK required (short-term the API is REST-only).
import os, requests
resp = requests.get(
"https://api.infrai.cc/v1/errors/get/EVENT_ID",
headers={
"Authorization": f"Bearer {os.environ['INFRAI_API_KEY']}",
},
)
resp.raise_for_status()
print(resp.json())
# 7) errors.groups
# Zero-install REST call — no SDK required (short-term the API is REST-only).
import os, requests
resp = requests.get(
"https://api.infrai.cc/v1/errors/groups",
headers={
"Authorization": f"Bearer {os.environ['INFRAI_API_KEY']}",
},
)
resp.raise_for_status()
print(resp.json())
# 8) errors.group_detail
# Zero-install REST call — no SDK required (short-term the API is REST-only).
import os, requests
resp = requests.get(
"https://api.infrai.cc/v1/errors/group_detail/ERROR_GROUP_ID",
headers={
"Authorization": f"Bearer {os.environ['INFRAI_API_KEY']}",
},
)
resp.raise_for_status()
print(resp.json())
# 9) errors.events
# Zero-install REST call — no SDK required (short-term the API is REST-only).
import os, requests
resp = requests.get(
"https://api.infrai.cc/v1/errors/events/ERROR_GROUP_ID",
headers={
"Authorization": f"Bearer {os.environ['INFRAI_API_KEY']}",
},
)
resp.raise_for_status()
print(resp.json())
// 1) Auth: every call is a raw HTTPS request carrying only your project key.
// No SDK to install — just the built-in fetch().
const BASE = "https://api.infrai.cc";
const HEADERS = {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
"Content-Type": "application/json",
};
// 2) errors.capture
// Zero-install REST call — no SDK required (short-term the API is REST-only).
const resp = await fetch(
"https://api.infrai.cc/v1/errors/capture",
{
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({"exception": {"type": "ValueError", "message": "bad input", "stacktrace": "..."}, "level": "error"}),
},
);
console.log(await resp.json());
// 3) errors.message
// Zero-install REST call — no SDK required (short-term the API is REST-only).
const resp = await fetch(
"https://api.infrai.cc/v1/errors/message",
{
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({"text": "hello"}),
},
);
console.log(await resp.json());
// 4) errors.list
// Zero-install REST call — no SDK required (short-term the API is REST-only).
const resp = await fetch(
"https://api.infrai.cc/v1/errors/list",
{
method: "GET",
headers: {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
},
},
);
console.log(await resp.json());
// 5) errors.search
// Zero-install REST call — no SDK required (short-term the API is REST-only).
const resp = await fetch(
"https://api.infrai.cc/v1/errors/search",
{
method: "GET",
headers: {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
},
},
);
console.log(await resp.json());
// 6) errors.get
// Zero-install REST call — no SDK required (short-term the API is REST-only).
const resp = await fetch(
"https://api.infrai.cc/v1/errors/get/EVENT_ID",
{
method: "GET",
headers: {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
},
},
);
console.log(await resp.json());
// 7) errors.groups
// Zero-install REST call — no SDK required (short-term the API is REST-only).
const resp = await fetch(
"https://api.infrai.cc/v1/errors/groups",
{
method: "GET",
headers: {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
},
},
);
console.log(await resp.json());
// 8) errors.group_detail
// Zero-install REST call — no SDK required (short-term the API is REST-only).
const resp = await fetch(
"https://api.infrai.cc/v1/errors/group_detail/ERROR_GROUP_ID",
{
method: "GET",
headers: {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
},
},
);
console.log(await resp.json());
// 9) errors.events
// Zero-install REST call — no SDK required (short-term the API is REST-only).
const resp = await fetch(
"https://api.infrai.cc/v1/errors/events/ERROR_GROUP_ID",
{
method: "GET",
headers: {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
},
},
);
console.log(await resp.json());
// 1) Auth: every call is a raw HTTPS request carrying only your project key.
// No SDK to install — just the built-in fetch(), typed.
const BASE = "https://api.infrai.cc";
const HEADERS: Record<string, string> = {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
"Content-Type": "application/json",
};
// 2) errors.capture
// Zero-install REST call — no SDK required (short-term the API is REST-only).
const resp = await fetch(
"https://api.infrai.cc/v1/errors/capture",
{
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({"exception": {"type": "ValueError", "message": "bad input", "stacktrace": "..."}, "level": "error"}),
},
);
if (!resp.ok) throw new Error(`infrai ${resp.status}`);
const data: unknown = await resp.json();
console.log(data);
// 3) errors.message
// Zero-install REST call — no SDK required (short-term the API is REST-only).
const resp = await fetch(
"https://api.infrai.cc/v1/errors/message",
{
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({"text": "hello"}),
},
);
if (!resp.ok) throw new Error(`infrai ${resp.status}`);
const data: unknown = await resp.json();
console.log(data);
// 4) errors.list
// Zero-install REST call — no SDK required (short-term the API is REST-only).
const resp = await fetch(
"https://api.infrai.cc/v1/errors/list",
{
method: "GET",
headers: {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
},
},
);
if (!resp.ok) throw new Error(`infrai ${resp.status}`);
const data: unknown = await resp.json();
console.log(data);
// 5) errors.search
// Zero-install REST call — no SDK required (short-term the API is REST-only).
const resp = await fetch(
"https://api.infrai.cc/v1/errors/search",
{
method: "GET",
headers: {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
},
},
);
if (!resp.ok) throw new Error(`infrai ${resp.status}`);
const data: unknown = await resp.json();
console.log(data);
// 6) errors.get
// Zero-install REST call — no SDK required (short-term the API is REST-only).
const resp = await fetch(
"https://api.infrai.cc/v1/errors/get/EVENT_ID",
{
method: "GET",
headers: {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
},
},
);
if (!resp.ok) throw new Error(`infrai ${resp.status}`);
const data: unknown = await resp.json();
console.log(data);
// 7) errors.groups
// Zero-install REST call — no SDK required (short-term the API is REST-only).
const resp = await fetch(
"https://api.infrai.cc/v1/errors/groups",
{
method: "GET",
headers: {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
},
},
);
if (!resp.ok) throw new Error(`infrai ${resp.status}`);
const data: unknown = await resp.json();
console.log(data);
// 8) errors.group_detail
// Zero-install REST call — no SDK required (short-term the API is REST-only).
const resp = await fetch(
"https://api.infrai.cc/v1/errors/group_detail/ERROR_GROUP_ID",
{
method: "GET",
headers: {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
},
},
);
if (!resp.ok) throw new Error(`infrai ${resp.status}`);
const data: unknown = await resp.json();
console.log(data);
// 9) errors.events
// Zero-install REST call — no SDK required (short-term the API is REST-only).
const resp = await fetch(
"https://api.infrai.cc/v1/errors/events/ERROR_GROUP_ID",
{
method: "GET",
headers: {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
},
},
);
if (!resp.ok) throw new Error(`infrai ${resp.status}`);
const data: unknown = await resp.json();
console.log(data);