账户
激活、余额、充值、密钥与套餐管理。
1. 概览
https://api.infrai.cc/v1/accountAuthorization: Bearer $INFRAI_API_KEY# Call any /v1/account capability over raw HTTP — no SDK to install.
# curl:
curl https://api.infrai.cc/v1/account/... \
-H "Authorization: Bearer $INFRAI_API_KEY" \
-H "Content-Type: application/json"2. 方法 (29)
2.1account.balance
读取钱包余额。
返回
{ balance_usd, currency }| 名称 | 类型 | 说明 |
|---|---|---|
balance | number | 当前钱包余额(美元)≥ 0 |
cap | number | null | 当前档位的钱包上限;Enterprise 为 null(无上限)。≥ 0 |
available_room | number | null | = cap - balance;cap 为 null 时(无上限)此值为 null。≥ 0 |
runway_days | number | null | 按当前日均消费估算的可持续天数;消费率接近 0 时为 null。≥ 0 |
daily_avg_spend | number | 日均消费(美元)≥ 0 |
tier | "standard" | "pro" | "enterprise" | 当前订阅档位(standard / pro / enterprise) |
expires_at | string | null | 试用额度过期时间(最后活动时间 + 宽限期窗口);无试用额度时为 null。format: date-time |
expires_in_days | integer | null | 当前余额或订阅到期天数 |
activity_required_by | string | null | 维持账户状态所需的最后活动日期format: date-time |
is_refundable | boolean | 当前余额是否符合退款条件 |
is_transferable | boolean | 当前余额是否可转移到其他账户 |
is_in_grace_period | boolean | 账户是否在余额过期后的宽限期内 |
grace_period_ends_at | string | null | 宽限期结束时间(ISO 8601)format: date-time |
forfeited_amount | number | null | 账户操作期间没收的金额(美元)≥ 0 |
pending_topups | string[] | null | 待处理充值会话列表 |
account_id | string | null | 该余额所属的账户。 |
balance_usd | number | `balance` 的别名,用于文档化的 SDK/CLI 状态展示。≥ 0 |
currency | string | ISO 4217 货币代码(如 USD、CNY)e.g. USD |
affordable_uses_hint | object | null | 按能力提示:当前余额还可覆盖多少次固定价格调用(尽力而为,按 token 计费的能力省略)。 |
示例
一次性前置(每个范例都假定已完成):
# 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/account/balance \
-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/account/balance",
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/account/balance",
{
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/account/balance",
{
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/account/balance", 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/account/balance"))
.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/account/balance");
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/account/balance");
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/account/balance")
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/account/balance")
.header("Authorization", format!("Bearer {}", env::var("INFRAI_API_KEY")?))
.send()
.await?;
println!("{}", resp.text().await?);
Ok(())
}2.2account.topup
为钱包充值;返回结账 URL 交给用户——卡数据从不经过 infrai。
参数
| 名称 | 类型 | 必填 | 说明 |
|---|---|---|---|
amount_usd | number | 必填 | 充值金额(美元)。≥ 0 |
return_url | string | 可选 | 结账后跳转地址。format: uri |
idempotency_key | string | 可选 | 可选去重 key;相同重试将返回同一结果。 |
返回
TopupRecord { topup_id, amount_usd, state, next_action_url? }| 名称 | 类型 | 说明 |
|---|---|---|
topup_id | string | 提供方结账会话 ID(Stripe cs_... / dev cs_mock_...)。传入 account.topup_status 以轮询结果。 |
status | "pending" | "paid" | "failed" | "unknown" | 待用户完成浏览器结账;Stripe Webhook 将其翻转为 paid/failed。 |
checkout_url | string | 打开此链接支付;成功后钱包将充值。format: uri |
checkout_mode | "stripe" | "mock" | stripe=真实 Stripe 结账;mock=本地开发会话。 |
amount_usd | number | 充值金额(美元)。≥ 0.5 |
amount | number | amount_usd 的向后兼容别名。≥ 0.5 |
currency | string | ISO 4217 货币代码(如 USD、CNY)e.g. USD |
示例
一次性前置(每个范例都假定已完成):
# 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/account/topup \
-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/account/topup",
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/account/topup",
{
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/account/topup",
{
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/account/topup", 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/account/topup"))
.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/account/topup");
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/account/topup");
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/account/topup")
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/account/topup")
.header("Authorization", format!("Bearer {}", env::var("INFRAI_API_KEY")?))
.header("Content-Type", "application/json")
.body(r#"{}"#)
.send()
.await?;
println!("{}", resp.text().await?);
Ok(())
}2.3account.keys.list
列出账户下的项目密钥。
返回
{ items: Array<{ key_id, label, scopes, created_at }> }| 名称 | 类型 | 说明 |
|---|---|---|
items | object[] | 本页结果条目数组 |
items[].key_id | string | 密钥 ID。列表返回时为掩码格式(可选前缀 + 分隔符 + 后4位)——分隔符为 ASCII "..."(路径安全)或传统的 Unicode 省略号。完整 ifr_ 值仅在创建时返回。pattern: ^ifr_[A-Za-z0-9_]*(\.\.\.|\u202… |
items[].key_secret | string | null | 完整明文值;仅在创建时返回。 |
items[].key | string | null | 仅 account.keys.rotate。新生成密钥的完整明文值,仅展示一次(作用同 create 时的 key_secret,此端点字段名不同)。 |
items[].old_key_id | string | null | 仅 account.keys.rotate。本次轮换所替换的旧密钥的掩码 ID。 |
items[].rotated | boolean | 仅 account.keys.rotate。是否确实生成了新密钥(引用的密钥不存在时为 false)。 |
items[].revoked | boolean | 仅 account.keys.revoke / .suspected_compromise。是否确实吊销了密钥(引用的密钥不存在时为 false)。 |
items[].action | string | null | 仅 account.keys.suspected_compromise。固定动作标签,如 "revoked_on_compromise_report"。 |
items[].updated | boolean | 仅 account.keys.update。是否确实更新了密钥记录(引用的密钥不存在时为 false)。 |
items[].name | string | null | 此资源的可读名称 |
items[].tier | string | null | 密钥从其账户继承的计费档位(standard/pro/enterprise)。 |
items[].scopes | string[] | 已授予的作用域。列表输出中省略——仅在有作用域暴露时出现。 |
items[].created_at | string | 此资源创建的 ISO 8601 时间戳format: date-time |
items[].last_used_at | string | null | 此密钥最后使用的 ISO 8601 时间戳format: date-time |
items[].last_used_ip | string | null | 使用此密钥认证的最近一次请求的 IP;从未使用时为 null。 |
items[].expires_at | string | null | 此资源或令牌过期的 ISO 8601 时间戳format: date-time |
items[].revoked_at | string | null | 此密钥被吊销的 ISO 8601 时间戳format: date-time |
items[].status | "active" | "rotating" | "revoked" | "not_found" | 此资源当前状态。当引用的 key_id 未解析到账户下的密钥时,keys.update/.rotate/.suspected_compromise 返回 "not_found"。 |
next_cursor | string | null | 获取下一页的不透明游标;null 或不存在表示最后一页 |
count | 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/account/keys/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/account/keys/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/account/keys/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/account/keys/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/account/keys/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/account/keys/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/account/keys/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/account/keys/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/account/keys/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/account/keys/list")
.header("Authorization", format!("Bearer {}", env::var("INFRAI_API_KEY")?))
.send()
.await?;
println!("{}", resp.text().await?);
Ok(())
}2.4account.tier.upgrade
将账户升级到目标套餐。
参数
| 名称 | 类型 | 必填 | 说明 |
|---|---|---|---|
target_tier | string | 必填 | 要升级到的套餐 id。 |
返回
AccountSummary { account_id, kind, status, tier, balance_usd }| 名称 | 类型 | 说明 |
|---|---|---|
target | "pro" | "team" | "enterprise" | Webhook 或通知的目标 URL 或资源 |
requires_checkout | boolean | 是否需 Stripe 结账会话才能完成变更 |
checkout_url | string | null | Stripe 结账会话 URLformat: uri |
requires_sales_contact | boolean | 是否需联系销售才能完成变更 |
contact_sales_url | string | null | 联系销售团队的 URLformat: uri |
current_tier | string | null | 本次升级前的有效档位。 |
status | "pending" | "active" | null | 调用后的订阅生命周期。pending=等待结账 Webhook;active=已确认(dev/非生产姿态)。 |
immediate_effect | boolean | null | 仅当档位立即切换时为 true(dev/非生产姿态,无真实支付)。 |
price_usd | number | null | 已解析方案价格(美元)。 |
period | string | null | 已解析方案的计费周期(如月付/年付)。 |
subscription | object | null | 已创建订阅的公开视图(确认后存在)。 |
subscription_id | string | null | 已创建的订阅 ID(待结账时存在)。 |
payment_source | "wallet" | "dev_mock" | "stripe_subscription" | null | 升级的资金来源(或将来源):钱包余额、dev/非生产自动确认,或真实的 Stripe 订阅结账。企业(联系销售)分支下不存在。 |
checkout_mode | string | null | 所创建结账会话的模式(如 "stripe"/"mock")。仅与 checkout_url 一同存在(payment_source=stripe_subscription)。 |
account_id | string | null | 升级所适用的账户。 |
示例
一次性前置(每个范例都假定已完成):
# 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/account/tier/upgrade \
-H "Authorization: Bearer $INFRAI_API_KEY" \
-H "Content-Type: application/json" \
-d '{"target": "pro"}'# 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/account/tier/upgrade",
headers={
"Authorization": f"Bearer {os.environ['INFRAI_API_KEY']}",
},
json={'target': 'pro'},
)
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/account/tier/upgrade",
{
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({"target": "pro"}),
},
);
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/account/tier/upgrade",
{
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({"target": "pro"}),
},
);
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(`{"target": "pro"}`)
req, _ := http.NewRequest("POST", "https://api.infrai.cc/v1/account/tier/upgrade", 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/account/tier/upgrade"))
.header("Authorization", "Bearer " + System.getenv("INFRAI_API_KEY"))
.header("Content-Type", "application/json")
.method("POST", HttpRequest.BodyPublishers.ofString("{\"target\": \"pro\"}"))
.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/account/tier/upgrade");
var key = Environment.GetEnvironmentVariable("INFRAI_API_KEY");
req.Headers.Add("Authorization", "Bearer " + key);
req.Content = new StringContent("{\"target\": \"pro\"}", 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/account/tier/upgrade");
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, "{\"target\": \"pro\"}");
$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/account/tier/upgrade")
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 = '{"target": "pro"}'
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/account/tier/upgrade")
.header("Authorization", format!("Bearer {}", env::var("INFRAI_API_KEY")?))
.header("Content-Type", "application/json")
.body(r#"{"target": "pro"}"#)
.send()
.await?;
println!("{}", resp.text().await?);
Ok(())
}2.5account.whoami
获取当前账户概要(账户 ID、类型、状态、档位、余额)。
返回
AccountSummary { account_id, kind, status, tier, balance_usd }| 名称 | 类型 | 说明 |
|---|---|---|
account_id | string | 真实 ID 使用 16 位十六进制设备/邮箱后缀(如 acct_anon_9424f4c4b31d4908);模式放宽为最少 12 位十六进制字符以匹配实际 ID 格式。pattern: ^acct_(anon|email|unbound)_[A-Z… |
account_kind | "anonymous" | "email" | "unbound" | 密钥持有者的身份状态。"unbound"=通过 infra.activate() 签发尚未绑定邮箱的密钥;"email"=通过 OTP/Google/GitHub 绑定。"anonymous"是"unbound"的旧别名(即将退役)。 |
email | string | null | 邮箱地址format: email |
email_verified | boolean | 邮箱地址是否已验证 |
linked_providers | ("email_otp" | "google" | "github" | "oauth")[] | 已验证此邮箱的身份提供方。同一邮箱可通过多种方式关联(Google + GitHub + OTP),均解析为同一账户。未绑定密钥时为空的数组。 |
display_name | string | null | 可读显示名 |
region | "global" | "cn" | 资源所在或处理的地理区域 |
created_at | string | null | 用户行创建时间。未绑定密钥为 null(尚无用户行)。format: date-time |
last_active_at | string | null | last_login_at / updated_at 中的较晚值。未绑定密钥为 null。format: date-time |
tier | "standard" | "pro" | "enterprise" | 当前订阅档位(standard / pro / enterprise) |
kyc_status | "none" | "pending" | "approved" | "rejected" | 当前 KYC 验证状态 |
totp_enabled | boolean | 该账户是否启用了基于 TOTP 的两步验证 |
pro_subscription | object | null | 有效 Pro 订阅的详情(如有) |
enterprise_contract | object | null | 企业合同的详情(如有) |
device_fingerprint | string | 用于身份追踪的设备指纹哈希 |
current_project_key_id | string | 当前项目密钥标识符 |
project_count | integer | projects in this account数量≥ 0 |
absorbed_anon_account_ids | string[] | anonymous account IDs absorbed during linking列表 |
linked_devices_count | integer | linked device accounts数量≥ 0 |
project_id | string | null | 调用方 bearer key 绑定的 project_id。反映 api_key.project_id(未绑定密钥如 "proj_anon_xxx")。无项目时 bearer 为 null。 |
key_id | string | null | 调用方 bearer key 的掩码(非秘密)形式——与 current_project_key_id 值相同。为保持与原 account.whoami 形态兼容;新调用方应读取 current_project_key_id。 |
示例
一次性前置(每个范例都假定已完成):
# 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/account/whoami \
-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/account/whoami",
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/account/whoami",
{
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/account/whoami",
{
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/account/whoami", 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/account/whoami"))
.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/account/whoami");
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/account/whoami");
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/account/whoami")
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/account/whoami")
.header("Authorization", format!("Bearer {}", env::var("INFRAI_API_KEY")?))
.send()
.await?;
println!("{}", resp.text().await?);
Ok(())
}2.6account.usage
获取本计费周期的用量汇总(消费、请求数、按能力拆分)。
返回
UsageSummary { period, spend_usd, requests, by_capability }| 名称 | 类型 | 说明 |
|---|---|---|
period | "1d" | "7d" | "30d" | "mtd" | "ytd" | 计费或保留周期(如月、日) |
period_start | string | 当前计费周期开始时间format: date-time |
period_end | string | 当前计费周期结束时间format: date-time |
total_cost | number | 查询期间的总费用(美元)≥ 0 |
total_calls | integer | 查询期间的 API 调用总数≥ 0 |
total_failed_calls | integer | 查询期间失败的 API 调用总数≥ 0 |
cache_hits | integer | cache hits in the queried period数量≥ 0 |
cache_savings | number | 缓存命中带来的预估成本节省(美元)≥ 0 |
breakdown | object[] | 按组件的成本分解 |
breakdown[].key | string | - |
breakdown[].label | string | - |
breakdown[].cost | number | -≥ 0 |
breakdown[].calls | integer | -≥ 0 |
breakdown[].failed_calls | integer | -≥ 0 |
breakdown[].avg_latency_ms | number | null | -≥ 0 |
breakdown[].p95_latency_ms | number | null | -≥ 0 |
breakdown[].error_rate | number | null | -0–1 |
breakdown[].top_errors | object[] | null | - |
示例
一次性前置(每个范例都假定已完成):
# 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/account/usage \
-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/account/usage",
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/account/usage",
{
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/account/usage",
{
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/account/usage", 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/account/usage"))
.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/account/usage");
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/account/usage");
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/account/usage")
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/account/usage")
.header("Authorization", format!("Bearer {}", env::var("INFRAI_API_KEY")?))
.send()
.await?;
println!("{}", resp.text().await?);
Ok(())
}2.7account.usage.timeseries
按时间粒度获取用量时间序列。
参数
| 名称 | 类型 | 必填 | 说明 |
|---|---|---|---|
start | string | 可选 | 起始时间(ISO 8601),留空则取周期起点。 |
end | string | 可选 | 结束时间(ISO 8601),留空则取当前。 |
granularity | "hour" | "day" | "month" | 可选 | 聚合粒度:hour / day / month。 |
返回
UsageTimeseries { granularity, points: Array<{ ts, spend_usd, requests }> }| 名称 | 类型 | 说明 |
|---|---|---|
period | "1d" | "7d" | "30d" | "mtd" | "ytd" | 计费或保留周期(如月、日) |
buckets | object[] | 按时间分桶的数据点 |
buckets[].date | string | -format: date |
buckets[].cost | number | -≥ 0 |
buckets[].calls | integer | -≥ 0 |
buckets[].failed_calls | integer | -≥ 0 |
buckets[].cache_hits | integer | null | -≥ 0 |
next_cursor | string | null | 获取下一页的不透明游标;null 或不存在表示最后一页 |
示例
一次性前置(每个范例都假定已完成):
# 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/account/usage/timeseries \
-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/account/usage/timeseries",
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/account/usage/timeseries",
{
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/account/usage/timeseries",
{
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/account/usage/timeseries", 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/account/usage/timeseries"))
.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/account/usage/timeseries");
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/account/usage/timeseries");
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/account/usage/timeseries")
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/account/usage/timeseries")
.header("Authorization", format!("Bearer {}", env::var("INFRAI_API_KEY")?))
.send()
.await?;
println!("{}", resp.text().await?);
Ok(())
}2.8account.budget.get
获取当前预算配置(周期、硬上限、告警阈值)。
返回
BudgetConfig { period, hard_cap_usd?, alert_threshold_usd? }| 名称 | 类型 | 说明 |
|---|---|---|
hard_cap_usd | number | null | 周期内消费达到此值即拦截;null 表示无上限。≥ 0 |
limit_usd | number | null | 仅 account.budget.set。含义同 hard_cap_usd,以请求字段名回显。≥ 0 |
period | "daily" | "monthly" | 计费或保留周期(如月、日) |
alert_threshold_usd | number | null | 余额达到此阈值时触发低余额/预算告警;null 表示不告警。≥ 0 |
alert_threshold_pct | number | null | 仅 account.budget.set。以 hard_cap_usd 百分比表示的告警阈值,按设置值回显。≥ 0 |
spent_this_period_usd | number | 当前计费周期已消费金额(美元)≥ 0 |
period_resets_at | string | null | 当前周期重置时间(ISO 8601)format: date-time |
configured | boolean | 是否已设置预算行(未配置时各相关字段为 null/零) |
updated_at | string | null | 资源最后更新时间(ISO 8601)format: date-time |
示例
一次性前置(每个范例都假定已完成):
# 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/account/budget/get \
-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/account/budget/get",
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/account/budget/get",
{
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/account/budget/get",
{
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/account/budget/get", 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/account/budget/get"))
.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/account/budget/get");
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/account/budget/get");
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/account/budget/get")
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/account/budget/get")
.header("Authorization", format!("Bearer {}", env::var("INFRAI_API_KEY")?))
.send()
.await?;
println!("{}", resp.text().await?);
Ok(())
}2.9account.budget.set
设置预算:周期内消费达到硬上限即拦截,达到阈值即告警。
参数
| 名称 | 类型 | 必填 | 说明 |
|---|---|---|---|
period | "daily" | "monthly" | 必填 | 预算周期:daily 或 monthly。 |
hard_cap_usd | number | 可选 | 硬上限(美元),超过即拦截后续计费请求。≥ 0 |
alert_threshold_usd | number | 可选 | 告警阈值(美元),达到即触发告警。≥ 0 |
idempotency_key | string | 可选 | 可选去重 key;相同重试将返回同一结果。 |
返回
BudgetConfig { period, hard_cap_usd?, alert_threshold_usd? }| 名称 | 类型 | 说明 |
|---|---|---|
hard_cap_usd | number | null | 周期内消费达到此值即拦截;null 表示无上限。≥ 0 |
limit_usd | number | null | 仅 account.budget.set。含义同 hard_cap_usd,以请求字段名回显。≥ 0 |
period | "daily" | "monthly" | 计费或保留周期(如月、日) |
alert_threshold_usd | number | null | 余额达到此阈值时触发低余额/预算告警;null 表示不告警。≥ 0 |
alert_threshold_pct | number | null | 仅 account.budget.set。以 hard_cap_usd 百分比表示的告警阈值,按设置值回显。≥ 0 |
spent_this_period_usd | number | 当前计费周期已消费金额(美元)≥ 0 |
period_resets_at | string | null | 当前周期重置时间(ISO 8601)format: date-time |
configured | boolean | 是否已设置预算行(未配置时各相关字段为 null/零) |
updated_at | string | null | 资源最后更新时间(ISO 8601)format: date-time |
示例
一次性前置(每个范例都假定已完成):
# 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 PUT https://api.infrai.cc/v1/account/budget/set \
-H "Authorization: Bearer $INFRAI_API_KEY" \
-H "Content-Type: application/json" \
-d '{"period": "daily"}'# Zero-install REST call — no SDK required (short-term the API is REST-only).
import os, requests
resp = requests.put(
"https://api.infrai.cc/v1/account/budget/set",
headers={
"Authorization": f"Bearer {os.environ['INFRAI_API_KEY']}",
},
json={'period': 'daily'},
)
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/account/budget/set",
{
method: "PUT",
headers: {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({"period": "daily"}),
},
);
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/account/budget/set",
{
method: "PUT",
headers: {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({"period": "daily"}),
},
);
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(`{"period": "daily"}`)
req, _ := http.NewRequest("PUT", "https://api.infrai.cc/v1/account/budget/set", 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/account/budget/set"))
.header("Authorization", "Bearer " + System.getenv("INFRAI_API_KEY"))
.header("Content-Type", "application/json")
.method("PUT", HttpRequest.BodyPublishers.ofString("{\"period\": \"daily\"}"))
.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("PUT"), "https://api.infrai.cc/v1/account/budget/set");
var key = Environment.GetEnvironmentVariable("INFRAI_API_KEY");
req.Headers.Add("Authorization", "Bearer " + key);
req.Content = new StringContent("{\"period\": \"daily\"}", 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/account/budget/set");
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "PUT");
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, "{\"period\": \"daily\"}");
$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/account/budget/set")
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
req = Net::HTTP::Put.new(uri)
req["Authorization"] = "Bearer #{ENV['INFRAI_API_KEY']}"
req["Content-Type"] = "application/json"
req.body = '{"period": "daily"}'
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()
.put("https://api.infrai.cc/v1/account/budget/set")
.header("Authorization", format!("Bearer {}", env::var("INFRAI_API_KEY")?))
.header("Content-Type", "application/json")
.body(r#"{"period": "daily"}"#)
.send()
.await?;
println!("{}", resp.text().await?);
Ok(())
}2.10account.autorecharge.get
获取自动充值配置。
返回
AutorechargeConfig { enabled, trigger_balance, recharge_amount, max_per_day, max_per_month }| 名称 | 类型 | 说明 |
|---|---|---|
enabled | boolean | 该功能或配置是否启用 |
trigger_balance | number | 触发自动充值的余额阈值(美元)≥ 0 |
recharge_amount | number | 触发时充值金额(美元)≥ 0 |
payment_method_id | string | 所用支付方式标识 |
payment_method_summary | string | 例如 "Visa ****4242"。 |
max_per_day | integer | 每日最大充值金额(美元)≥ 1 |
max_per_month | integer | 每月最大充值金额(美元)≥ 1 |
triggered_today | integer | 今日已充值金额(美元)≥ 0 |
triggered_this_month | integer | 本月已充值金额(美元)≥ 0 |
next_check_at | string | null | 下次余额检查时间(ISO 8601)format: date-time |
last_succeeded_at | string | null | 上次成功支付时间(ISO 8601)format: date-time |
last_failed_at | string | null | 上次支付失败时间(ISO 8601)format: date-time |
consecutive_failures | integer | 连续支付失败次数≥ 0 |
configured | boolean | 该账户是否存在配置行(未设置时各数字字段为零默认值) |
disabled_reason | string | null | 自动充值当前被禁用的原因(如 "user"、"max_failures"、"admin");启用时或从未禁用时为 null。 |
示例
一次性前置(每个范例都假定已完成):
# 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/account/autorecharge/get \
-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/account/autorecharge/get",
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/account/autorecharge/get",
{
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/account/autorecharge/get",
{
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/account/autorecharge/get", 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/account/autorecharge/get"))
.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/account/autorecharge/get");
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/account/autorecharge/get");
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/account/autorecharge/get")
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/account/autorecharge/get")
.header("Authorization", format!("Bearer {}", env::var("INFRAI_API_KEY")?))
.send()
.await?;
println!("{}", resp.text().await?);
Ok(())
}2.11account.autorecharge.configure
配置自动充值:余额低于触发值时自动扣款充值。
参数
| 名称 | 类型 | 必填 | 说明 |
|---|---|---|---|
trigger_balance | number | 必填 | 触发余额:钱包余额低于此值即自动充值。≥ 0 |
recharge_amount | number | 必填 | 每次自动充值的金额(美元)。> 0 |
payment_method_id | string | 可选 | 扣款支付方式 ID,留空则使用账户默认支付方式。 |
max_per_day | number | 可选 | 每日自动充值次数上限(防滥用)。≥ 1default: 3 |
max_per_month | number | 可选 | 每月自动充值次数上限(防滥用)。≥ 1default: 30 |
idempotency_key | string | 可选 | 可选去重 key;相同重试将返回同一结果。 |
返回
AutorechargeConfig { enabled, trigger_balance, recharge_amount, max_per_day, max_per_month }| 名称 | 类型 | 说明 |
|---|---|---|
enabled | boolean | 该功能或配置是否启用 |
trigger_balance | number | 触发自动充值的余额阈值(美元)≥ 0 |
recharge_amount | number | 触发时充值金额(美元)≥ 0 |
payment_method_id | string | 所用支付方式标识 |
payment_method_summary | string | 例如 "Visa ****4242"。 |
max_per_day | integer | 每日最大充值金额(美元)≥ 1 |
max_per_month | integer | 每月最大充值金额(美元)≥ 1 |
triggered_today | integer | 今日已充值金额(美元)≥ 0 |
triggered_this_month | integer | 本月已充值金额(美元)≥ 0 |
next_check_at | string | null | 下次余额检查时间(ISO 8601)format: date-time |
last_succeeded_at | string | null | 上次成功支付时间(ISO 8601)format: date-time |
last_failed_at | string | null | 上次支付失败时间(ISO 8601)format: date-time |
consecutive_failures | integer | 连续支付失败次数≥ 0 |
configured | boolean | 该账户是否存在配置行(未设置时各数字字段为零默认值) |
disabled_reason | string | null | 自动充值当前被禁用的原因(如 "user"、"max_failures"、"admin");启用时或从未禁用时为 null。 |
示例
一次性前置(每个范例都假定已完成):
# 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 PUT https://api.infrai.cc/v1/account/autorecharge/configure \
-H "Authorization: Bearer $INFRAI_API_KEY" \
-H "Content-Type: application/json" \
-d '{"trigger_balance": 1.0, "recharge_amount": 1.0}'# Zero-install REST call — no SDK required (short-term the API is REST-only).
import os, requests
resp = requests.put(
"https://api.infrai.cc/v1/account/autorecharge/configure",
headers={
"Authorization": f"Bearer {os.environ['INFRAI_API_KEY']}",
},
json={'trigger_balance': 1.0, 'recharge_amount': 1.0},
)
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/account/autorecharge/configure",
{
method: "PUT",
headers: {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({"trigger_balance": 1.0, "recharge_amount": 1.0}),
},
);
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/account/autorecharge/configure",
{
method: "PUT",
headers: {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({"trigger_balance": 1.0, "recharge_amount": 1.0}),
},
);
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(`{"trigger_balance": 1.0, "recharge_amount": 1.0}`)
req, _ := http.NewRequest("PUT", "https://api.infrai.cc/v1/account/autorecharge/configure", 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/account/autorecharge/configure"))
.header("Authorization", "Bearer " + System.getenv("INFRAI_API_KEY"))
.header("Content-Type", "application/json")
.method("PUT", HttpRequest.BodyPublishers.ofString("{\"trigger_balance\": 1.0, \"recharge_amount\": 1.0}"))
.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("PUT"), "https://api.infrai.cc/v1/account/autorecharge/configure");
var key = Environment.GetEnvironmentVariable("INFRAI_API_KEY");
req.Headers.Add("Authorization", "Bearer " + key);
req.Content = new StringContent("{\"trigger_balance\": 1.0, \"recharge_amount\": 1.0}", 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/account/autorecharge/configure");
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "PUT");
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, "{\"trigger_balance\": 1.0, \"recharge_amount\": 1.0}");
$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/account/autorecharge/configure")
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
req = Net::HTTP::Put.new(uri)
req["Authorization"] = "Bearer #{ENV['INFRAI_API_KEY']}"
req["Content-Type"] = "application/json"
req.body = '{"trigger_balance": 1.0, "recharge_amount": 1.0}'
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()
.put("https://api.infrai.cc/v1/account/autorecharge/configure")
.header("Authorization", format!("Bearer {}", env::var("INFRAI_API_KEY")?))
.header("Content-Type", "application/json")
.body(r#"{"trigger_balance": 1.0, "recharge_amount": 1.0}"#)
.send()
.await?;
println!("{}", resp.text().await?);
Ok(())
}2.12account.payment_method.set_default
将指定支付方式设为账户默认。
参数
| 名称 | 类型 | 必填 | 说明 |
|---|---|---|---|
payment_method_id | string | 必填 | 要设为默认的支付方式 ID。 |
idempotency_key | string | 可选 | 可选去重 key;相同重试将返回同一结果。 |
返回
AccountPaymentMethod { id, brand, last4, is_default }| 名称 | 类型 | 说明 |
|---|---|---|
payment_method_id | string | 所用支付方式标识 |
set_default | boolean | 仅 account.payment_method.set_default。是否确实更改了默认项(payment_method_id 非已保存的支付方式时为 false)。 |
status | "not_found" | null | 仅 account.payment_method.set_default。当 payment_method_id 未匹配到已保存的支付方式时存在("not_found")。 |
message | string | null | 仅 account.payment_method.set_default。set_default 为 false 时的可读详情。 |
kind | "card" | "sepa" | "ach" | "alipay" | "wechat" | "applepay" | "googlepay" | null | 可选。结构化支付方式类型;通过 setup-intent 流程保存的卡此项不存在——参见 `summary`。 |
summary | string | null | 支付方式的可读描述,例如 "Visa ****4242"。 |
stripe_customer_id | string | null | 支付方式关联的 Stripe 客户 ID;mock/dev 环境为 null。 |
is_default | boolean | 是否为默认支付方式 |
last4 | string | null | 卡号后 4 位pattern: ^[0-9]{4}$ |
brand | string | null | 卡品牌(如 visa、mastercard) |
expires | string | null | 卡种类的 MM/YY 格式。 |
added_at | string | null | 资源添加时间(ISO 8601)format: date-time |
示例
一次性前置(每个范例都假定已完成):
# 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/account/payment_method/set_default \
-H "Authorization: Bearer $INFRAI_API_KEY" \
-H "Content-Type: application/json" \
-d '{"payment_method_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/account/payment_method/set_default",
headers={
"Authorization": f"Bearer {os.environ['INFRAI_API_KEY']}",
},
json={'payment_method_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/account/payment_method/set_default",
{
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({"payment_method_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/account/payment_method/set_default",
{
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({"payment_method_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(`{"payment_method_id": "sample"}`)
req, _ := http.NewRequest("POST", "https://api.infrai.cc/v1/account/payment_method/set_default", 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/account/payment_method/set_default"))
.header("Authorization", "Bearer " + System.getenv("INFRAI_API_KEY"))
.header("Content-Type", "application/json")
.method("POST", HttpRequest.BodyPublishers.ofString("{\"payment_method_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/account/payment_method/set_default");
var key = Environment.GetEnvironmentVariable("INFRAI_API_KEY");
req.Headers.Add("Authorization", "Bearer " + key);
req.Content = new StringContent("{\"payment_method_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/account/payment_method/set_default");
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, "{\"payment_method_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/account/payment_method/set_default")
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 = '{"payment_method_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/account/payment_method/set_default")
.header("Authorization", format!("Bearer {}", env::var("INFRAI_API_KEY")?))
.header("Content-Type", "application/json")
.body(r#"{"payment_method_id": "sample"}"#)
.send()
.await?;
println!("{}", resp.text().await?);
Ok(())
}2.13account.tier
获取当前账户档位及其额度限制。
返回
TierInfo { tier, limits, billing_period }| 名称 | 类型 | 说明 |
|---|---|---|
tier | "standard" | "pro" | "enterprise" | 当前订阅档位(standard / pro / enterprise) |
since | string | the current tier or state became effective(ISO 8601)format: date-time |
wallet_cap | number | null | Enterprise 为 null(无上限)。≥ 0 |
rate_limit_multiplier | number | 此档位应用的限流倍数≥ 1 |
features | string[] | features available at this tier列表 |
pro_subscription | object | null | 有效 Pro 订阅的详情(如有) |
enterprise_contract | object | null | 企业合同的详情(如有) |
account_id | string | null | 此档位所属的账户。 |
示例
一次性前置(每个范例都假定已完成):
# 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/account/tier \
-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/account/tier",
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/account/tier",
{
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/account/tier",
{
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/account/tier", 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/account/tier"))
.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/account/tier");
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/account/tier");
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/account/tier")
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/account/tier")
.header("Authorization", format!("Bearer {}", env::var("INFRAI_API_KEY")?))
.send()
.await?;
println!("{}", resp.text().await?);
Ok(())
}2.14account.subscription.get
获取订阅状态(档位、当前周期结束时间、是否将取消)。
返回
SubscriptionInfo { status, tier, current_period_end, cancel_at_period_end }| 名称 | 类型 | 说明 |
|---|---|---|
model | "usage_based" | 始终为 usage_based;即用即付钱包,可选自动充值。 |
tier | "standard" | "pro" | "enterprise" | 当前订阅档位(standard / pro / enterprise) |
fixed_subscription | object | null | 保留用于未来的固定周期方案;当前为 null(无固定订阅)。 |
autorecharge | object | 循环资金策略:钱包余额低于 trigger_balance_usd 时自动充值。 |
autorecharge.enabled | boolean | - |
autorecharge.recharge_amount_usd | number | null | -≥ 0 |
autorecharge.trigger_balance_usd | number | null | -≥ 0 |
autorecharge.payment_method | string | null | 脱敏银行卡摘要,如 "Visa ****4242"。 |
示例
一次性前置(每个范例都假定已完成):
# 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/account/subscription/get \
-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/account/subscription/get",
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/account/subscription/get",
{
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/account/subscription/get",
{
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/account/subscription/get", 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/account/subscription/get"))
.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/account/subscription/get");
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/account/subscription/get");
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/account/subscription/get")
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/account/subscription/get")
.header("Authorization", format!("Bearer {}", env::var("INFRAI_API_KEY")?))
.send()
.await?;
println!("{}", resp.text().await?);
Ok(())
}2.15account.keys.create
创建 API Key,key_secret 仅在创建时返回一次。
参数
| 名称 | 类型 | 必填 | 说明 |
|---|---|---|---|
name | string | 可选 | Key 名称(最长 128 字符)。≤ 128 chars |
scopes | string[] | 可选 | 作用域列表,留空表示全模块。 |
idempotency_key | string | 可选 | 可选去重 key;相同重试将返回同一结果。 |
返回
ApiKey { key_id, name, scopes, key_secret, created_at }| 名称 | 类型 | 说明 |
|---|---|---|
key_id | string | 密钥 ID。列表返回时为掩码格式(可选前缀 + 分隔符 + 后4位)——分隔符为 ASCII "..."(路径安全)或传统的 Unicode 省略号。完整 ifr_ 值仅在创建时返回。pattern: ^ifr_[A-Za-z0-9_]*(\.\.\.|\u202… |
key_secret | string | null | 完整明文值;仅在创建时返回。 |
key | string | null | 仅 account.keys.rotate。新生成密钥的完整明文值,仅展示一次(作用同 create 时的 key_secret,此端点字段名不同)。 |
old_key_id | string | null | 仅 account.keys.rotate。本次轮换所替换的旧密钥的掩码 ID。 |
rotated | boolean | 仅 account.keys.rotate。是否确实生成了新密钥(引用的密钥不存在时为 false)。 |
revoked | boolean | 仅 account.keys.revoke / .suspected_compromise。是否确实吊销了密钥(引用的密钥不存在时为 false)。 |
action | string | null | 仅 account.keys.suspected_compromise。固定动作标签,如 "revoked_on_compromise_report"。 |
updated | boolean | 仅 account.keys.update。是否确实更新了密钥记录(引用的密钥不存在时为 false)。 |
name | string | null | 资源的可读名称 |
tier | string | null | 密钥从其账户继承的计费档位(standard/pro/enterprise)。 |
scopes | string[] | 已授予的作用域。列表输出中省略——仅在有作用域暴露时出现。 |
created_at | string | 资源创建时间(ISO 8601)format: date-time |
last_used_at | string | null | ISO 8601 时间戳:this key was last used(ISO 8601)format: date-time |
last_used_ip | string | null | 使用此密钥认证的最近一次请求的 IP;从未使用时为 null。 |
expires_at | string | null | 资源或令牌过期时间(ISO 8601)format: date-time |
revoked_at | string | null | ISO 8601 时间戳:this key was revoked(ISO 8601)format: date-time |
status | "active" | "rotating" | "revoked" | "not_found" | 当前资源状态 |
示例
一次性前置(每个范例都假定已完成):
# 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/account/keys/create \
-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/account/keys/create",
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/account/keys/create",
{
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/account/keys/create",
{
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/account/keys/create", 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/account/keys/create"))
.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/account/keys/create");
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/account/keys/create");
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/account/keys/create")
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/account/keys/create")
.header("Authorization", format!("Bearer {}", env::var("INFRAI_API_KEY")?))
.header("Content-Type", "application/json")
.body(r#"{}"#)
.send()
.await?;
println!("{}", resp.text().await?);
Ok(())
}2.16account.keys.update
更新 API Key 的名称和/或作用域,作用域收紧立即生效。
参数
| 名称 | 类型 | 必填 | 说明 |
|---|---|---|---|
key_id | string | 必填 | API Key ID。 |
name | string | 可选 | 新 Key 名称。≤ 128 chars |
scopes | string[] | 可选 | 新作用域列表。 |
idempotency_key | string | 可选 | 可选去重 key;相同重试将返回同一结果。 |
返回
ApiKey { key_id, name, scopes }| 名称 | 类型 | 说明 |
|---|---|---|
key_id | string | 密钥 ID。列表返回时为掩码格式(可选前缀 + 分隔符 + 后4位)——分隔符为 ASCII "..."(路径安全)或传统的 Unicode 省略号。完整 ifr_ 值仅在创建时返回。pattern: ^ifr_[A-Za-z0-9_]*(\.\.\.|\u202… |
key_secret | string | null | 完整明文值;仅在创建时返回。 |
key | string | null | 仅 account.keys.rotate。新生成密钥的完整明文值,仅展示一次(作用同 create 时的 key_secret,此端点字段名不同)。 |
old_key_id | string | null | 仅 account.keys.rotate。本次轮换所替换的旧密钥的掩码 ID。 |
rotated | boolean | 仅 account.keys.rotate。是否确实生成了新密钥(引用的密钥不存在时为 false)。 |
revoked | boolean | 仅 account.keys.revoke / .suspected_compromise。是否确实吊销了密钥(引用的密钥不存在时为 false)。 |
action | string | null | 仅 account.keys.suspected_compromise。固定动作标签,如 "revoked_on_compromise_report"。 |
updated | boolean | 仅 account.keys.update。是否确实更新了密钥记录(引用的密钥不存在时为 false)。 |
name | string | null | 资源的可读名称 |
tier | string | null | 密钥从其账户继承的计费档位(standard/pro/enterprise)。 |
scopes | string[] | 已授予的作用域。列表输出中省略——仅在有作用域暴露时出现。 |
created_at | string | 资源创建时间(ISO 8601)format: date-time |
last_used_at | string | null | ISO 8601 时间戳:this key was last used(ISO 8601)format: date-time |
last_used_ip | string | null | 使用此密钥认证的最近一次请求的 IP;从未使用时为 null。 |
expires_at | string | null | 资源或令牌过期时间(ISO 8601)format: date-time |
revoked_at | string | null | ISO 8601 时间戳:this key was revoked(ISO 8601)format: date-time |
status | "active" | "rotating" | "revoked" | "not_found" | 当前资源状态 |
示例
一次性前置(每个范例都假定已完成):
# 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 PATCH https://api.infrai.cc/v1/account/keys/update/ID \
-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.patch(
"https://api.infrai.cc/v1/account/keys/update/ID",
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/account/keys/update/ID",
{
method: "PATCH",
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/account/keys/update/ID",
{
method: "PATCH",
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("PATCH", "https://api.infrai.cc/v1/account/keys/update/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/account/keys/update/ID"))
.header("Authorization", "Bearer " + System.getenv("INFRAI_API_KEY"))
.header("Content-Type", "application/json")
.method("PATCH", 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("PATCH"), "https://api.infrai.cc/v1/account/keys/update/ID");
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/account/keys/update/ID");
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "PATCH");
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/account/keys/update/ID")
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
req = Net::HTTP::Patch.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()
.patch("https://api.infrai.cc/v1/account/keys/update/ID")
.header("Authorization", format!("Bearer {}", env::var("INFRAI_API_KEY")?))
.header("Content-Type", "application/json")
.body(r#"{}"#)
.send()
.await?;
println!("{}", resp.text().await?);
Ok(())
}2.17account.keys.rotate
轮换 API Key:签发新密钥,旧密钥在宽限期内仍有效。
参数
| 名称 | 类型 | 必填 | 说明 |
|---|---|---|---|
key_id | string | 必填 | API Key ID。 |
grace_hours | number | 可选 | 旧密钥宽限有效小时数(0-168,默认 24)。0–168default: 24 |
idempotency_key | string | 可选 | 可选去重 key;相同重试将返回同一结果。 |
返回
ApiKey { key_id, key_secret, status, grace_expires_at }| 名称 | 类型 | 说明 |
|---|---|---|
key_id | string | 密钥 ID。列表返回时为掩码格式(可选前缀 + 分隔符 + 后4位)——分隔符为 ASCII "..."(路径安全)或传统的 Unicode 省略号。完整 ifr_ 值仅在创建时返回。pattern: ^ifr_[A-Za-z0-9_]*(\.\.\.|\u202… |
key_secret | string | null | 完整明文值;仅在创建时返回。 |
key | string | null | 仅 account.keys.rotate。新生成密钥的完整明文值,仅展示一次(作用同 create 时的 key_secret,此端点字段名不同)。 |
old_key_id | string | null | 仅 account.keys.rotate。本次轮换所替换的旧密钥的掩码 ID。 |
rotated | boolean | 仅 account.keys.rotate。是否确实生成了新密钥(引用的密钥不存在时为 false)。 |
revoked | boolean | 仅 account.keys.revoke / .suspected_compromise。是否确实吊销了密钥(引用的密钥不存在时为 false)。 |
action | string | null | 仅 account.keys.suspected_compromise。固定动作标签,如 "revoked_on_compromise_report"。 |
updated | boolean | 仅 account.keys.update。是否确实更新了密钥记录(引用的密钥不存在时为 false)。 |
name | string | null | 资源的可读名称 |
tier | string | null | 密钥从其账户继承的计费档位(standard/pro/enterprise)。 |
scopes | string[] | 已授予的作用域。列表输出中省略——仅在有作用域暴露时出现。 |
created_at | string | 资源创建时间(ISO 8601)format: date-time |
last_used_at | string | null | ISO 8601 时间戳:this key was last used(ISO 8601)format: date-time |
last_used_ip | string | null | 使用此密钥认证的最近一次请求的 IP;从未使用时为 null。 |
expires_at | string | null | 资源或令牌过期时间(ISO 8601)format: date-time |
revoked_at | string | null | ISO 8601 时间戳:this key was revoked(ISO 8601)format: date-time |
status | "active" | "rotating" | "revoked" | "not_found" | 当前资源状态 |
示例
一次性前置(每个范例都假定已完成):
# 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/account/keys/rotate/ID \
-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/account/keys/rotate/ID",
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/account/keys/rotate/ID",
{
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/account/keys/rotate/ID",
{
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/account/keys/rotate/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/account/keys/rotate/ID"))
.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/account/keys/rotate/ID");
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/account/keys/rotate/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, "{}");
$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/account/keys/rotate/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 = '{}'
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/account/keys/rotate/ID")
.header("Authorization", format!("Bearer {}", env::var("INFRAI_API_KEY")?))
.header("Content-Type", "application/json")
.body(r#"{}"#)
.send()
.await?;
println!("{}", resp.text().await?);
Ok(())
}2.18account.keys.revoke
吊销 API Key,立即失效。
参数
| 名称 | 类型 | 必填 | 说明 |
|---|---|---|---|
key_id | string | 必填 | API Key ID。 |
idempotency_key | string | 可选 | 可选去重 key;相同重试将返回同一结果。 |
返回
{ revoked: boolean }| 名称 | 类型 | 说明 |
|---|---|---|
key_id | string | 密钥 ID。列表返回时为掩码格式(可选前缀 + 分隔符 + 后4位)——分隔符为 ASCII "..."(路径安全)或传统的 Unicode 省略号。完整 ifr_ 值仅在创建时返回。pattern: ^ifr_[A-Za-z0-9_]*(\.\.\.|\u202… |
key_secret | string | null | 完整明文值;仅在创建时返回。 |
key | string | null | 仅 account.keys.rotate。新生成密钥的完整明文值,仅展示一次(作用同 create 时的 key_secret,此端点字段名不同)。 |
old_key_id | string | null | 仅 account.keys.rotate。本次轮换所替换的旧密钥的掩码 ID。 |
rotated | boolean | 仅 account.keys.rotate。是否确实生成了新密钥(引用的密钥不存在时为 false)。 |
revoked | boolean | 仅 account.keys.revoke / .suspected_compromise。是否确实吊销了密钥(引用的密钥不存在时为 false)。 |
action | string | null | 仅 account.keys.suspected_compromise。固定动作标签,如 "revoked_on_compromise_report"。 |
updated | boolean | 仅 account.keys.update。是否确实更新了密钥记录(引用的密钥不存在时为 false)。 |
name | string | null | 资源的可读名称 |
tier | string | null | 密钥从其账户继承的计费档位(standard/pro/enterprise)。 |
scopes | string[] | 已授予的作用域。列表输出中省略——仅在有作用域暴露时出现。 |
created_at | string | 资源创建时间(ISO 8601)format: date-time |
last_used_at | string | null | ISO 8601 时间戳:this key was last used(ISO 8601)format: date-time |
last_used_ip | string | null | 使用此密钥认证的最近一次请求的 IP;从未使用时为 null。 |
expires_at | string | null | 资源或令牌过期时间(ISO 8601)format: date-time |
revoked_at | string | null | ISO 8601 时间戳:this key was revoked(ISO 8601)format: date-time |
status | "active" | "rotating" | "revoked" | "not_found" | 当前资源状态 |
示例
一次性前置(每个范例都假定已完成):
# 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 DELETE https://api.infrai.cc/v1/account/keys/revoke/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.delete(
"https://api.infrai.cc/v1/account/keys/revoke/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/account/keys/revoke/ID",
{
method: "DELETE",
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/account/keys/revoke/ID",
{
method: "DELETE",
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("DELETE", "https://api.infrai.cc/v1/account/keys/revoke/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/account/keys/revoke/ID"))
.header("Authorization", "Bearer " + System.getenv("INFRAI_API_KEY"))
.method("DELETE", 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("DELETE"), "https://api.infrai.cc/v1/account/keys/revoke/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/account/keys/revoke/ID");
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "DELETE");
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/account/keys/revoke/ID")
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
req = Net::HTTP::Delete.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()
.delete("https://api.infrai.cc/v1/account/keys/revoke/ID")
.header("Authorization", format!("Bearer {}", env::var("INFRAI_API_KEY")?))
.send()
.await?;
println!("{}", resp.text().await?);
Ok(())
}2.19account.keys.suspected_compromise
上报 API Key 疑似泄露,可立即吊销并自动签发替换密钥。
参数
| 名称 | 类型 | 必填 | 说明 |
|---|---|---|---|
key_id | string | 必填 | API Key ID。 |
confirmed_leak | boolean | 可选 | 是否已确认泄露,true 则立即吊销。default: false |
auto_rotate | boolean | 可选 | 是否自动签发替换密钥。default: true |
idempotency_key | string | 可选 | 可选去重 key;相同重试将返回同一结果。 |
返回
ApiKey { key_id, status, key_secret? }| 名称 | 类型 | 说明 |
|---|---|---|
key_id | string | 密钥 ID。列表返回时为掩码格式(可选前缀 + 分隔符 + 后4位)——分隔符为 ASCII "..."(路径安全)或传统的 Unicode 省略号。完整 ifr_ 值仅在创建时返回。pattern: ^ifr_[A-Za-z0-9_]*(\.\.\.|\u202… |
key_secret | string | null | 完整明文值;仅在创建时返回。 |
key | string | null | 仅 account.keys.rotate。新生成密钥的完整明文值,仅展示一次(作用同 create 时的 key_secret,此端点字段名不同)。 |
old_key_id | string | null | 仅 account.keys.rotate。本次轮换所替换的旧密钥的掩码 ID。 |
rotated | boolean | 仅 account.keys.rotate。是否确实生成了新密钥(引用的密钥不存在时为 false)。 |
revoked | boolean | 仅 account.keys.revoke / .suspected_compromise。是否确实吊销了密钥(引用的密钥不存在时为 false)。 |
action | string | null | 仅 account.keys.suspected_compromise。固定动作标签,如 "revoked_on_compromise_report"。 |
updated | boolean | 仅 account.keys.update。是否确实更新了密钥记录(引用的密钥不存在时为 false)。 |
name | string | null | 资源的可读名称 |
tier | string | null | 密钥从其账户继承的计费档位(standard/pro/enterprise)。 |
scopes | string[] | 已授予的作用域。列表输出中省略——仅在有作用域暴露时出现。 |
created_at | string | 资源创建时间(ISO 8601)format: date-time |
last_used_at | string | null | ISO 8601 时间戳:this key was last used(ISO 8601)format: date-time |
last_used_ip | string | null | 使用此密钥认证的最近一次请求的 IP;从未使用时为 null。 |
expires_at | string | null | 资源或令牌过期时间(ISO 8601)format: date-time |
revoked_at | string | null | ISO 8601 时间戳:this key was revoked(ISO 8601)format: date-time |
status | "active" | "rotating" | "revoked" | "not_found" | 当前资源状态 |
示例
一次性前置(每个范例都假定已完成):
# 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/account/keys/suspected_compromise/ID \
-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/account/keys/suspected_compromise/ID",
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/account/keys/suspected_compromise/ID",
{
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/account/keys/suspected_compromise/ID",
{
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/account/keys/suspected_compromise/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/account/keys/suspected_compromise/ID"))
.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/account/keys/suspected_compromise/ID");
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/account/keys/suspected_compromise/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, "{}");
$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/account/keys/suspected_compromise/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 = '{}'
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/account/keys/suspected_compromise/ID")
.header("Authorization", format!("Bearer {}", env::var("INFRAI_API_KEY")?))
.header("Content-Type", "application/json")
.body(r#"{}"#)
.send()
.await?;
println!("{}", resp.text().await?);
Ok(())
}2.20account.webhooks.list
分页列出已注册的 Webhook。
参数
| 名称 | 类型 | 必填 | 说明 |
|---|---|---|---|
cursor | string | 可选 | 分页游标:传入上一页返回的 next_cursor 获取下一页。 |
limit | number | 可选 | 单页返回条数上限。 |
返回
{ items: Array<Webhook>, next_cursor? }| 名称 | 类型 | 说明 |
|---|---|---|
items | object[] | 本页结果条目数组 |
items[].webhook_id | string | Webhook 订阅 ID(account_resource 存储中的 whk_...)。pattern: ^whk?_[A-Za-z0-9]{16,}$ |
items[].url | string | 此资源或端点的 URLformat: uri |
items[].events | string[] | 事件名称,见 enums/webhook_event.yaml。 |
items[].description | string | null | 资源的自由文本描述 |
items[].secret | string | null | 明文密钥——仅在首次创建时返回。 |
items[].secret_hash | string | null | 密钥的 SHA-256 十六进制摘要;在 list/get 中返回。 |
items[].active | boolean | 是否发送投递。规范状态字段。 |
items[].enabled | boolean | null | `active` 的向后兼容别名(控制台读取此字段)。 |
items[].status | string | null | account_resource 生命周期状态(如 "active")。 |
items[].retry_policy | "default" | "aggressive" | null | 重试策略配置 |
items[].headers | object | null | 添加到每次投递的自定义 HTTP 头。 |
items[].last_delivery_at | string | null | 上次投递尝试的 ISO 8601 时间戳format: date-time |
items[].last_delivery_status | "success" | "failed" | null | 上次投递尝试的状态 |
items[].failure_count_24h | integer | failed deliveries in the last 24 hours数量≥ 0 |
items[].auto_disabled_at | string | null | 连续 100 次失败触发自动禁用时设置的时间戳。format: date-time |
items[].created_at | string | null | 此资源创建的 ISO 8601 时间戳。account.webhooks.update 中不存在(patch 响应仅回显 updated_at)。format: date-time |
items[].updated_at | string | null | 此资源最后更新的 ISO 8601 时间戳。由 .get/.update 返回;.register/.list 上不存在。format: date-time |
next_cursor | string | null | 获取下一页的不透明游标;null 或不存在表示最后一页 |
count | 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/account/webhooks/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/account/webhooks/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/account/webhooks/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/account/webhooks/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/account/webhooks/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/account/webhooks/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/account/webhooks/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/account/webhooks/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/account/webhooks/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/account/webhooks/list")
.header("Authorization", format!("Bearer {}", env::var("INFRAI_API_KEY")?))
.send()
.await?;
println!("{}", resp.text().await?);
Ok(())
}2.21account.webhooks.register
注册 Webhook,URL 须为公网 https 端点(服务端做 SSRF 校验),secret 仅返回一次。
参数
| 名称 | 类型 | 必填 | 说明 |
|---|---|---|---|
url | string | 必填 | 接收回调的公网 https 地址。format: uri |
events | ("account.created" | "account.updated" | "account.absorbed" | "account.device_linked" | "account.deleted" | "topup.succeeded" | "topup.failed" | "topup.review_started" | "autorecharge.charged" | "autorecharge.failed" | "subscription.activated" | "subscription.renewed" | "subscription.cancelled" | "kyc.status_changed" | "tier.upgraded" | "tier.downgraded" | "wallet.low_balance" | "wallet.expiring_soon" | "wallet.expired" | "email.queued" | "email.sent" | "email.delivered" | "email.opened" | "email.clicked" | "email.bounced" | "email.complained" | "email.deferred" | "email.cancelled" | "email.unsubscribed" | "email.auto_suppressed" | "sms.queued" | "sms.sent" | "sms.delivered" | "sms.failed" | "sms.inbound" | "image.job.completed" | "image.job.failed" | "video.job.completed" | "video.job.failed" | "ai.batch.completed" | "ai.batch.failed" | "captcha.verified" | "captcha.failed" | "realtime.channel.occupied" | "realtime.channel.vacated" | "realtime.member.added" | "realtime.member.removed" | "cron.executed" | "cron.failed" | "queue.dlq" | "error.captured" | "error.rate_anomaly" | "system.vendor.down" | "system.maintenance.scheduled")[] | 必填 | 订阅的事件类型列表。≥ 1 item |
description | string | 可选 | 备注说明(可选,最长 256 字符)。≤ 256 chars |
secret | string | 可选 | 自定义签名密钥,留空则自动生成。 |
retry_policy | "default" | "aggressive" | null | 可选 | 重试策略:default 或 aggressive。 |
headers | Record<string, string> | 可选 | 每次投递附加的自定义 HTTP 头。 |
idempotency_key | string | 可选 | 可选去重 key;相同重试将返回同一结果。 |
返回
Webhook { id, url, events, secret, active }| 名称 | 类型 | 说明 |
|---|---|---|
webhook_id | string | Webhook 订阅 ID(account_resource 存储中的 whk_...)。pattern: ^whk?_[A-Za-z0-9]{16,}$ |
url | string | 资源或端点 URLformat: uri |
events | string[] | 事件名称,见 enums/webhook_event.yaml。 |
description | string | null | 资源的自由文本描述 |
secret | string | null | 明文密钥——仅在首次创建时返回。 |
secret_hash | string | null | 密钥的 SHA-256 十六进制;列表/详情接口返回。 |
active | boolean | 投递是否发送。规范状态字段。 |
enabled | boolean | null | `active` 的向后兼容别名(控制台读取此字段)。 |
status | string | null | account_resource 生命周期状态(如 "active")。 |
retry_policy | "default" | "aggressive" | null | 重试策略配置 |
headers | object | null | 每次投递附加的自定义 HTTP 头。 |
last_delivery_at | string | null | 上次投递尝试时间(ISO 8601)format: date-time |
last_delivery_status | "success" | "failed" | null | 上次投递尝试的状态 |
failure_count_24h | integer | 最近 24 小时投递失败次数≥ 0 |
auto_disabled_at | string | null | 连续 100 次失败触发自动禁用时设置的时间戳。format: date-time |
created_at | string | null | 资源创建时间(ISO 8601)format: date-time |
updated_at | string | null | 此资源最后更新的 ISO 8601 时间戳。由 .get/.update 返回;.register/.list 上不存在。format: date-time |
示例
一次性前置(每个范例都假定已完成):
# 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/account/webhooks/register \
-H "Authorization: Bearer $INFRAI_API_KEY" \
-H "Content-Type: application/json" \
-d '{"url": "https://example.com/callback", "events": ["account.created"]}'# 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/account/webhooks/register",
headers={
"Authorization": f"Bearer {os.environ['INFRAI_API_KEY']}",
},
json={'url': 'https://example.com/callback', 'events': ['account.created']},
)
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/account/webhooks/register",
{
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({"url": "https://example.com/callback", "events": ["account.created"]}),
},
);
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/account/webhooks/register",
{
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({"url": "https://example.com/callback", "events": ["account.created"]}),
},
);
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(`{"url": "https://example.com/callback", "events": ["account.created"]}`)
req, _ := http.NewRequest("POST", "https://api.infrai.cc/v1/account/webhooks/register", 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/account/webhooks/register"))
.header("Authorization", "Bearer " + System.getenv("INFRAI_API_KEY"))
.header("Content-Type", "application/json")
.method("POST", HttpRequest.BodyPublishers.ofString("{\"url\": \"https://example.com/callback\", \"events\": [\"account.created\"]}"))
.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/account/webhooks/register");
var key = Environment.GetEnvironmentVariable("INFRAI_API_KEY");
req.Headers.Add("Authorization", "Bearer " + key);
req.Content = new StringContent("{\"url\": \"https://example.com/callback\", \"events\": [\"account.created\"]}", 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/account/webhooks/register");
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, "{\"url\": \"https://example.com/callback\", \"events\": [\"account.created\"]}");
$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/account/webhooks/register")
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 = '{"url": "https://example.com/callback", "events": ["account.created"]}'
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/account/webhooks/register")
.header("Authorization", format!("Bearer {}", env::var("INFRAI_API_KEY")?))
.header("Content-Type", "application/json")
.body(r#"{"url": "https://example.com/callback", "events": ["account.created"]}"#)
.send()
.await?;
println!("{}", resp.text().await?);
Ok(())
}2.22account.webhooks.get
获取单个 Webhook 详情。
参数
| 名称 | 类型 | 必填 | 说明 |
|---|---|---|---|
webhook_id | string | 必填 | Webhook ID。 |
返回
Webhook { id, url, events, active, retry_policy }| 名称 | 类型 | 说明 |
|---|---|---|
webhook_id | string | Webhook 订阅 ID(account_resource 存储中的 whk_...)。pattern: ^whk?_[A-Za-z0-9]{16,}$ |
url | string | 资源或端点 URLformat: uri |
events | string[] | 事件名称,见 enums/webhook_event.yaml。 |
description | string | null | 资源的自由文本描述 |
secret | string | null | 明文密钥——仅在首次创建时返回。 |
secret_hash | string | null | 密钥的 SHA-256 十六进制;列表/详情接口返回。 |
active | boolean | 投递是否发送。规范状态字段。 |
enabled | boolean | null | `active` 的向后兼容别名(控制台读取此字段)。 |
status | string | null | account_resource 生命周期状态(如 "active")。 |
retry_policy | "default" | "aggressive" | null | 重试策略配置 |
headers | object | null | 每次投递附加的自定义 HTTP 头。 |
last_delivery_at | string | null | 上次投递尝试时间(ISO 8601)format: date-time |
last_delivery_status | "success" | "failed" | null | 上次投递尝试的状态 |
failure_count_24h | integer | 最近 24 小时投递失败次数≥ 0 |
auto_disabled_at | string | null | 连续 100 次失败触发自动禁用时设置的时间戳。format: date-time |
created_at | string | null | 资源创建时间(ISO 8601)format: date-time |
updated_at | string | null | 此资源最后更新的 ISO 8601 时间戳。由 .get/.update 返回;.register/.list 上不存在。format: date-time |
示例
一次性前置(每个范例都假定已完成):
# 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/account/webhooks/get/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/account/webhooks/get/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/account/webhooks/get/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/account/webhooks/get/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/account/webhooks/get/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/account/webhooks/get/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/account/webhooks/get/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/account/webhooks/get/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/account/webhooks/get/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/account/webhooks/get/ID")
.header("Authorization", format!("Bearer {}", env::var("INFRAI_API_KEY")?))
.send()
.await?;
println!("{}", resp.text().await?);
Ok(())
}2.23account.webhooks.update
局部更新 Webhook,修改 URL 会重新触发 SSRF 校验。
参数
| 名称 | 类型 | 必填 | 说明 |
|---|---|---|---|
webhook_id | string | 必填 | Webhook ID。 |
url | string | 可选 | 新的公网 https 地址。format: uri |
events | ("account.created" | "account.updated" | "account.absorbed" | "account.device_linked" | "account.deleted" | "topup.succeeded" | "topup.failed" | "topup.review_started" | "autorecharge.charged" | "autorecharge.failed" | "subscription.activated" | "subscription.renewed" | "subscription.cancelled" | "kyc.status_changed" | "tier.upgraded" | "tier.downgraded" | "wallet.low_balance" | "wallet.expiring_soon" | "wallet.expired" | "email.queued" | "email.sent" | "email.delivered" | "email.opened" | "email.clicked" | "email.bounced" | "email.complained" | "email.deferred" | "email.cancelled" | "email.unsubscribed" | "email.auto_suppressed" | "sms.queued" | "sms.sent" | "sms.delivered" | "sms.failed" | "sms.inbound" | "image.job.completed" | "image.job.failed" | "video.job.completed" | "video.job.failed" | "ai.batch.completed" | "ai.batch.failed" | "captcha.verified" | "captcha.failed" | "realtime.channel.occupied" | "realtime.channel.vacated" | "realtime.member.added" | "realtime.member.removed" | "cron.executed" | "cron.failed" | "queue.dlq" | "error.captured" | "error.rate_anomaly" | "system.vendor.down" | "system.maintenance.scheduled")[] | null | 可选 | 新的订阅事件类型列表。≥ 1 item |
description | string | 可选 | 备注说明。≤ 256 chars |
active | boolean | 可选 | 是否启用该 Webhook。 |
retry_policy | "default" | "aggressive" | null | 可选 | 重试策略:default 或 aggressive。 |
headers | Record<string, string> | 可选 | 每次投递附加的自定义 HTTP 头。 |
idempotency_key | string | 可选 | 可选去重 key;相同重试将返回同一结果。 |
返回
Webhook { id, url, events, active, retry_policy }| 名称 | 类型 | 说明 |
|---|---|---|
webhook_id | string | Webhook 订阅 ID(account_resource 存储中的 whk_...)。pattern: ^whk?_[A-Za-z0-9]{16,}$ |
url | string | 资源或端点 URLformat: uri |
events | string[] | 事件名称,见 enums/webhook_event.yaml。 |
description | string | null | 资源的自由文本描述 |
secret | string | null | 明文密钥——仅在首次创建时返回。 |
secret_hash | string | null | 密钥的 SHA-256 十六进制;列表/详情接口返回。 |
active | boolean | 投递是否发送。规范状态字段。 |
enabled | boolean | null | `active` 的向后兼容别名(控制台读取此字段)。 |
status | string | null | account_resource 生命周期状态(如 "active")。 |
retry_policy | "default" | "aggressive" | null | 重试策略配置 |
headers | object | null | 每次投递附加的自定义 HTTP 头。 |
last_delivery_at | string | null | 上次投递尝试时间(ISO 8601)format: date-time |
last_delivery_status | "success" | "failed" | null | 上次投递尝试的状态 |
failure_count_24h | integer | 最近 24 小时投递失败次数≥ 0 |
auto_disabled_at | string | null | 连续 100 次失败触发自动禁用时设置的时间戳。format: date-time |
created_at | string | null | 资源创建时间(ISO 8601)format: date-time |
updated_at | string | null | 此资源最后更新的 ISO 8601 时间戳。由 .get/.update 返回;.register/.list 上不存在。format: date-time |
示例
一次性前置(每个范例都假定已完成):
# 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 PATCH https://api.infrai.cc/v1/account/webhooks/update/ID \
-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.patch(
"https://api.infrai.cc/v1/account/webhooks/update/ID",
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/account/webhooks/update/ID",
{
method: "PATCH",
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/account/webhooks/update/ID",
{
method: "PATCH",
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("PATCH", "https://api.infrai.cc/v1/account/webhooks/update/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/account/webhooks/update/ID"))
.header("Authorization", "Bearer " + System.getenv("INFRAI_API_KEY"))
.header("Content-Type", "application/json")
.method("PATCH", 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("PATCH"), "https://api.infrai.cc/v1/account/webhooks/update/ID");
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/account/webhooks/update/ID");
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "PATCH");
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/account/webhooks/update/ID")
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
req = Net::HTTP::Patch.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()
.patch("https://api.infrai.cc/v1/account/webhooks/update/ID")
.header("Authorization", format!("Bearer {}", env::var("INFRAI_API_KEY")?))
.header("Content-Type", "application/json")
.body(r#"{}"#)
.send()
.await?;
println!("{}", resp.text().await?);
Ok(())
}2.24account.webhooks.delete
删除 Webhook。
参数
| 名称 | 类型 | 必填 | 说明 |
|---|---|---|---|
webhook_id | string | 必填 | Webhook ID。 |
idempotency_key | string | 可选 | 可选去重 key;相同重试将返回同一结果。 |
返回
{ deleted: boolean }| 名称 | 类型 | 说明 |
|---|---|---|
webhook_id | string | 被删除的目标 Webhook ID。 |
deleted | boolean | 是否确实删除了 Webhook(webhook_id 在此账户下未解析到记录时为 false)。 |
示例
一次性前置(每个范例都假定已完成):
# 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 DELETE https://api.infrai.cc/v1/account/webhooks/delete/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.delete(
"https://api.infrai.cc/v1/account/webhooks/delete/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/account/webhooks/delete/ID",
{
method: "DELETE",
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/account/webhooks/delete/ID",
{
method: "DELETE",
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("DELETE", "https://api.infrai.cc/v1/account/webhooks/delete/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/account/webhooks/delete/ID"))
.header("Authorization", "Bearer " + System.getenv("INFRAI_API_KEY"))
.method("DELETE", 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("DELETE"), "https://api.infrai.cc/v1/account/webhooks/delete/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/account/webhooks/delete/ID");
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "DELETE");
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/account/webhooks/delete/ID")
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
req = Net::HTTP::Delete.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()
.delete("https://api.infrai.cc/v1/account/webhooks/delete/ID")
.header("Authorization", format!("Bearer {}", env::var("INFRAI_API_KEY")?))
.send()
.await?;
println!("{}", resp.text().await?);
Ok(())
}2.25account.webhooks.test
向 Webhook 发送一条测试事件以验证连通性。
参数
| 名称 | 类型 | 必填 | 说明 |
|---|---|---|---|
webhook_id | string | 必填 | Webhook ID。 |
返回
WebhookDelivery { delivery_id, status_code, ok }| 名称 | 类型 | 说明 |
|---|---|---|
webhook_id | string | webhook的唯一标识符pattern: ^wh_[A-Za-z0-9]{20,}$ |
event | string | 测试中触发的事件名(如 "topup.succeeded")。 |
delivered | boolean | Webhook 投递是否成功 |
http_status | integer | null | Webhook 投递尝试的 HTTP 状态码100–599 |
latency_ms | integer | null | 操作延迟(毫秒)≥ 0 |
error | string | null | 操作失败时的错误消息 |
delivery_id | string | null | delivery attempt的唯一标识符pattern: ^dlv_[A-Za-z0-9]{20,}$ |
tested_at | string | 测试执行时间(ISO 8601)format: date-time |
示例
一次性前置(每个范例都假定已完成):
# 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/account/webhooks/test/ID \
-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/account/webhooks/test/ID",
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/account/webhooks/test/ID",
{
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/account/webhooks/test/ID",
{
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/account/webhooks/test/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/account/webhooks/test/ID"))
.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/account/webhooks/test/ID");
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/account/webhooks/test/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, "{}");
$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/account/webhooks/test/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 = '{}'
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/account/webhooks/test/ID")
.header("Authorization", format!("Bearer {}", env::var("INFRAI_API_KEY")?))
.header("Content-Type", "application/json")
.body(r#"{}"#)
.send()
.await?;
println!("{}", resp.text().await?);
Ok(())
}2.26account.webhooks.deliveries
分页列出某 Webhook 的投递记录。
参数
| 名称 | 类型 | 必填 | 说明 |
|---|---|---|---|
webhook_id | string | 必填 | Webhook ID。 |
cursor | string | 可选 | 分页游标:传入上一页返回的 next_cursor 获取下一页。 |
limit | number | 可选 | 单页返回条数上限。 |
返回
{ items: Array<WebhookDelivery>, next_cursor? }| 名称 | 类型 | 说明 |
|---|---|---|
items | object[] | 本页结果条目数组 |
items[].delivery_id | string | delivery attempt的唯一标识符pattern: ^dlv_[A-Za-z0-9]{20,}$ |
items[].webhook_id | string | webhook的唯一标识符pattern: ^wh_[A-Za-z0-9]{20,}$ |
items[].event | string | 事件名称,见 enums/webhook_event.yaml。 |
items[].status | "pending" | "success" | "retry" | "failed" | "dlq" | 此资源当前状态 |
items[].attempt | integer | 当前尝试次数(重试相关)≥ 1 |
items[].http_status | integer | null | Webhook 投递尝试的 HTTP 状态码100–599 |
items[].latency_ms | integer | null | 操作延迟(毫秒)≥ 0 |
items[].response_body_truncated | string | null | Webhook 投递尝试的截断响应正文≤ 4096 chars |
items[].error | string | null | 操作失败时的错误消息 |
items[].created_at | string | 此资源创建的 ISO 8601 时间戳format: date-time |
items[].completed_at | string | null | 执行完成的 ISO 8601 时间戳format: date-time |
next_cursor | string | null | 获取下一页的不透明游标;null 或不存在表示最后一页 |
count | 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/account/webhooks/deliveries/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/account/webhooks/deliveries/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/account/webhooks/deliveries/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/account/webhooks/deliveries/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/account/webhooks/deliveries/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/account/webhooks/deliveries/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/account/webhooks/deliveries/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/account/webhooks/deliveries/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/account/webhooks/deliveries/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/account/webhooks/deliveries/ID")
.header("Authorization", format!("Bearer {}", env::var("INFRAI_API_KEY")?))
.send()
.await?;
println!("{}", resp.text().await?);
Ok(())
}2.27account.routing.get
获取账户级路由配置(链路覆盖、故障转移策略、固定厂商)。
返回
RoutingConfig { chain_override?, failover_policy, pinned_vendors }| 名称 | 类型 | 说明 |
|---|---|---|
preferences | object | 仅 account.routing.get。账户已配置的按能力供应商排除列表,以能力 ID 为键。 |
effective_chains | object | 仅 account.routing.get。应用账户排除并过滤为当前可用供应商后的按能力故障转移链,以能力 ID 为键。每项以模型为先:供应商加其服务的模型。 |
no_china_route | boolean | account.routing.get(当前值)/ account.routing.set(回显新值,仅在设置了 no_china_route 开关时)。数据主权标志:为 true 时网关仅路由到非中国供应商。 |
capability | string | 仅 account.routing.set(按能力排除子动作)。设置排除列表所针对的能力。 |
exclude | string[] | 仅 account.routing.set(按能力排除子动作)。从该能力链中排除的供应商 ID 回显。 |
ok | boolean | 仅 account.routing.set。始终为 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/account/routing/get \
-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/account/routing/get",
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/account/routing/get",
{
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/account/routing/get",
{
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/account/routing/get", 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/account/routing/get"))
.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/account/routing/get");
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/account/routing/get");
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/account/routing/get")
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/account/routing/get")
.header("Authorization", format!("Bearer {}", env::var("INFRAI_API_KEY")?))
.send()
.await?;
println!("{}", resp.text().await?);
Ok(())
}2.28account.routing.set
设置账户级路由:覆盖默认厂商链路、固定指定厂商。
参数
| 名称 | 类型 | 必填 | 说明 |
|---|---|---|---|
chain_override | string[] | 可选 | 厂商优先级链路覆盖列表。 |
pinned_vendors | string[] | 可选 | 固定使用的厂商列表。 |
返回
RoutingConfig { chain_override?, failover_policy, pinned_vendors }| 名称 | 类型 | 说明 |
|---|---|---|
preferences | object | 仅 account.routing.get。账户已配置的按能力供应商排除列表,以能力 ID 为键。 |
effective_chains | object | 仅 account.routing.get。应用账户排除并过滤为当前可用供应商后的按能力故障转移链,以能力 ID 为键。每项以模型为先:供应商加其服务的模型。 |
no_china_route | boolean | account.routing.get(当前值)/ account.routing.set(回显新值,仅在设置了 no_china_route 开关时)。数据主权标志:为 true 时网关仅路由到非中国供应商。 |
capability | string | 仅 account.routing.set(按能力排除子动作)。设置排除列表所针对的能力。 |
exclude | string[] | 仅 account.routing.set(按能力排除子动作)。从该能力链中排除的供应商 ID 回显。 |
ok | boolean | 仅 account.routing.set。始终为 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 PUT https://api.infrai.cc/v1/account/routing/set \
-H "Authorization: Bearer $INFRAI_API_KEY" \
-H "Content-Type: application/json" \
-d '{"capability": "ai.chat"}'# Zero-install REST call — no SDK required (short-term the API is REST-only).
import os, requests
resp = requests.put(
"https://api.infrai.cc/v1/account/routing/set",
headers={
"Authorization": f"Bearer {os.environ['INFRAI_API_KEY']}",
},
json={'capability': 'ai.chat'},
)
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/account/routing/set",
{
method: "PUT",
headers: {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({"capability": "ai.chat"}),
},
);
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/account/routing/set",
{
method: "PUT",
headers: {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({"capability": "ai.chat"}),
},
);
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(`{"capability": "ai.chat"}`)
req, _ := http.NewRequest("PUT", "https://api.infrai.cc/v1/account/routing/set", 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/account/routing/set"))
.header("Authorization", "Bearer " + System.getenv("INFRAI_API_KEY"))
.header("Content-Type", "application/json")
.method("PUT", HttpRequest.BodyPublishers.ofString("{\"capability\": \"ai.chat\"}"))
.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("PUT"), "https://api.infrai.cc/v1/account/routing/set");
var key = Environment.GetEnvironmentVariable("INFRAI_API_KEY");
req.Headers.Add("Authorization", "Bearer " + key);
req.Content = new StringContent("{\"capability\": \"ai.chat\"}", 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/account/routing/set");
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "PUT");
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, "{\"capability\": \"ai.chat\"}");
$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/account/routing/set")
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
req = Net::HTTP::Put.new(uri)
req["Authorization"] = "Bearer #{ENV['INFRAI_API_KEY']}"
req["Content-Type"] = "application/json"
req.body = '{"capability": "ai.chat"}'
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()
.put("https://api.infrai.cc/v1/account/routing/set")
.header("Authorization", format!("Bearer {}", env::var("INFRAI_API_KEY")?))
.header("Content-Type", "application/json")
.body(r#"{"capability": "ai.chat"}"#)
.send()
.await?;
println!("{}", resp.text().await?);
Ok(())
}2.29account.routing.test
测试路由解析:给定能力返回将选用的厂商链路。
参数
| 名称 | 类型 | 必填 | 说明 |
|---|---|---|---|
capability | string | 必填 | 要测试的能力 ID(如 ai.chat)。default: "ai.chat"e.g. ai.chat |
chain_override | string[] | 可选 | 用于本次测试的临时链路覆盖。 |
返回
RoutingTestResult { ok, resolved_vendor, resolved_model?, tested_at? }| 名称 | 类型 | 说明 |
|---|---|---|
capability | string | 被测试的能力(未提供时默认为 ai.chat)。 |
customizable | boolean | 此能力是否接受按账户的供应商排除(仅 AI 推理/无状态能力)。 |
chain | string[] | 应用账户排除并过滤为当前可用供应商后的有效供应商 ID 链。 |
results | object[] | 按供应商的可达性,`chain` 中每个供应商一项。 |
results[].vendor | string | - |
results[].model | string | null | 此供应商将为该能力服务的模型(尽力返回)。 |
results[].up | boolean | 该供应商当前是否在实时注册表中被标记为可用。 |
ok | boolean | 测试路由是否解析成功 |
示例
一次性前置(每个范例都假定已完成):
# 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/account/routing/test \
-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/account/routing/test",
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/account/routing/test",
{
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/account/routing/test",
{
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/account/routing/test", 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/account/routing/test"))
.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/account/routing/test");
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/account/routing/test");
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/account/routing/test")
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/account/routing/test")
.header("Authorization", format!("Bearer {}", env::var("INFRAI_API_KEY")?))
.header("Content-Type", "application/json")
.body(r#"{}"#)
.send()
.await?;
println!("{}", resp.text().await?);
Ok(())
}3. 全部能力
本模块全部已路由能力——完整的对外 REST 契约。上方方法是带讲解的入门示例,此表是完整参考。
account.autorecharge.configurePUT /v1/account/autorecharge/configureConfigure automatic balance top-up when funds fall below a trigger threshold, with anti-abuse caps.
参数 (6)
| 名称 | 类型 | 必填 | 说明 |
|---|---|---|---|
trigger_balance | number | 必填 | Auto-charge fires when wallet balance drops below this.≥ 0 |
recharge_amount | number | 必填 | Amount in USD to add each time auto-charge fires.> 0 |
payment_method_id | string | null | 可选 | null uses the account default payment method. |
max_per_day | integer | 可选 | Maximum recharge amount per day in USD≥ 1default: 3 |
max_per_month | integer | 可选 | Maximum recharge amount per month in USD≥ 1default: 30 |
idempotency_key | string | null | 可选 | Client-provided idempotency key; prevents duplicate execution on retry |
account.autorecharge.getGET /v1/account/autorecharge/getGet the current auto-recharge configuration.
无请求参数。
account.balanceGET /v1/account/balanceGet the account wallet balance and trial status.
无请求参数。
account.budget.getGET /v1/account/budget/getGet the budget configuration (period, hard cap, alert thresholds).
无请求参数。
account.budget.setPUT /v1/account/budget/setSet a hard budget cap and alert thresholds, blocking billable calls when exceeded.
参数 (4)
| 名称 | 类型 | 必填 | 说明 |
|---|---|---|---|
hard_cap_usd | number | null | 可选 | Monthly spending hard cap in USD≥ 0 |
period | "daily" | "monthly" | 必填 | Billing or retention period (e.g. monthly, daily) |
alert_threshold_usd | number | null | 可选 | Monthly spending alert threshold in USD≥ 0 |
idempotency_key | string | null | 可选 | Client-provided idempotency key; prevents duplicate execution on retry |
account.keys.createPOST /v1/account/keys/createCreate an API key; the secret is returned only once.
参数 (4)
| 名称 | 类型 | 必填 | 说明 |
|---|---|---|---|
project_id | string | null | 可选 | null = caller's current project. |
name | string | null | 可选 | Human-readable name for this resource≤ 128 chars |
scopes | string[] | null | 可选 | Empty/null = all-modules; explicit scopes per enums/key_scope.yaml. |
idempotency_key | string | null | 可选 | Client-provided idempotency key; prevents duplicate execution on retry |
account.keys.listGET /v1/account/keys/listList all API keys on the account and their status.
无请求参数。
account.keys.revokeDELETE /v1/account/keys/revoke/{id}Revoke an API key, taking effect immediately.
参数 (1)
| 名称 | 类型 | 必填 | 说明 |
|---|---|---|---|
id | string | 必填 | Path parameter. |
account.keys.rotatePOST /v1/account/keys/rotate/{id}Rotate an API key; the old secret stays valid during a grace period.
参数 (3)
| 名称 | 类型 | 必填 | 说明 |
|---|---|---|---|
id | string | 必填 | Path parameter. |
grace_hours | integer | 可选 | Hours the old key remains valid after rotation0–168default: 24 |
idempotency_key | string | null | 可选 | Client-provided idempotency key; prevents duplicate execution on retry |
account.keys.suspected_compromisePOST /v1/account/keys/suspected_compromise/{id}Report an API key as suspected compromised to immediately revoke and auto-reissue it.
参数 (4)
| 名称 | 类型 | 必填 | 说明 |
|---|---|---|---|
id | string | 必填 | Path parameter. |
confirmed_leak | boolean | 可选 | Whether the key leak has been confirmeddefault: false |
auto_rotate | boolean | 可选 | Whether to automatically rotate the compromised keydefault: true |
idempotency_key | string | null | 可选 | Client-provided idempotency key; prevents duplicate execution on retry |
account.keys.updatePATCH /v1/account/keys/update/{id}Update an API key's name or scopes; scope tightening takes effect immediately.
参数 (4)
| 名称 | 类型 | 必填 | 说明 |
|---|---|---|---|
id | string | 必填 | Path parameter. |
name | string | null | 可选 | Human-readable name for this resource≤ 128 chars |
scopes | string[] | null | 可选 | Permission scopes granted to this API key |
idempotency_key | string | null | 可选 | Client-provided idempotency key; prevents duplicate execution on retry |
account.payment_method.set_defaultPOST /v1/account/payment_method/set_defaultSet a payment method as the account default.
参数 (2)
| 名称 | 类型 | 必填 | 说明 |
|---|---|---|---|
payment_method_id | string | 必填 | Identifier of the payment method used |
idempotency_key | string | null | 可选 | Client-provided idempotency key; prevents duplicate execution on retry |
account.routing.getGET /v1/account/routing/getGet the account's AI routing preference: per-capability vendor chains (model-annotated) + excluded vendors.
无请求参数。
account.routing.setPUT /v1/account/routing/setExclude vendors from an AI capability's routing (cost / reliability / data sovereignty).
参数 (3)
| 名称 | 类型 | 必填 | 说明 |
|---|---|---|---|
capability | string | 必填 | AI-inference capability id (ai.*) whose vendor exclude is being set.e.g. ai.chat |
exclude | string[] | 可选 | Vendors to never route this capability to (cost / reliability / data sovereignty).default: []e.g. ["openai"] |
idempotency_key | string | null | 可选 | Client-provided idempotency key; prevents duplicate execution on retry |
account.routing.testPOST /v1/account/routing/testTest routing resolution for an AI capability: the vendor chain and the model each serves.
参数 (1)
| 名称 | 类型 | 必填 | 说明 |
|---|---|---|---|
capability | string | null | 可选 | Capability id whose routing chain to test (defaults to ai.chat).default: "ai.chat"e.g. ai.chat |
account.subscription.getGET /v1/account/subscription/getGet the subscription status and billing period.
无请求参数。
account.tierGET /v1/account/tierGet the current tier and its quota limits.
无请求参数。
account.tier.upgradePOST /v1/account/tier/upgradeUpgrade the account tier (pro/team/enterprise), returning a checkout URL when payment is required.
参数 (3)
| 名称 | 类型 | 必填 | 说明 |
|---|---|---|---|
target | "pro" | "team" | "enterprise" | 必填 | Target URL or resource for webhook or notification |
return_url | string | null | 可选 | Where checkout redirects after success/cancel; echoed into the hosted checkout session.format: uri |
idempotency_key | string | null | 可选 | Client-provided idempotency key; prevents duplicate execution on retry |
account.topupPOST /v1/account/topupCreate a Stripe top-up session and return the hosted payment page URL.
参数 (5)
| 名称 | 类型 | 必填 | 说明 |
|---|---|---|---|
amount_usd | number | null | 可选 | Top-up amount in USD.≥ 0 |
amount | number | null | 可选 | Legacy alias for amount_usd.≥ 0 |
currency | string | 可选 | ISO 4217 currency code (e.g. USD, CNY)default: "USD" |
return_url | string | null | 可选 | URL the checkout redirects back to; defaults to the configured return URL.format: uri |
idempotency_key | string | null | 可选 | Client-provided idempotency key; prevents duplicate execution on retry |
account.usageGET /v1/account/usageSummarize usage for the current billing period: spend, request count, and a per-capability breakdown.
无请求参数。
account.usage.timeseriesGET /v1/account/usage/timeseriesReturn a usage time series at hour, day, or month granularity.
无请求参数。
account.webhooks.deleteDELETE /v1/account/webhooks/delete/{id}Delete a webhook registration; no further event deliveries are sent to its URL. Idempotent.
参数 (1)
| 名称 | 类型 | 必填 | 说明 |
|---|---|---|---|
id | string | 必填 | Path parameter. |
account.webhooks.deliveriesGET /v1/account/webhooks/deliveries/{id}List a webhook's delivery records with pagination.
参数 (1)
| 名称 | 类型 | 必填 | 说明 |
|---|---|---|---|
id | string | 必填 | Path parameter. |
account.webhooks.getGET /v1/account/webhooks/get/{id}Get details for a single webhook.
参数 (1)
| 名称 | 类型 | 必填 | 说明 |
|---|---|---|---|
id | string | 必填 | Path parameter. |
account.webhooks.listGET /v1/account/webhooks/listList registered webhooks with pagination.
无请求参数。
account.webhooks.registerPOST /v1/account/webhooks/registerRegister a webhook (public HTTPS, SSRF-validated); the signing secret is returned only once.
参数 (7)
| 名称 | 类型 | 必填 | 说明 |
|---|---|---|---|
url | string | 必填 | URL for this resource or endpointformat: uri |
events | ("account.created" | "account.updated" | "account.absorbed" | "account.device_linked" | "account.deleted" | "topup.succeeded" | "topup.failed" | "topup.review_started" | "autorecharge.charged" | "autorecharge.failed" | "subscription.activated" | "subscription.renewed" | "subscription.cancelled" | "kyc.status_changed" | "tier.upgraded" | "tier.downgraded" | "wallet.low_balance" | "wallet.expiring_soon" | "wallet.expired" | "email.queued" | "email.sent" | "email.delivered" | "email.opened" | "email.clicked" | "email.bounced" | "email.complained" | "email.deferred" | "email.cancelled" | "email.unsubscribed" | "email.auto_suppressed" | "sms.queued" | "sms.sent" | "sms.delivered" | "sms.failed" | "sms.inbound" | "image.job.completed" | "image.job.failed" | "video.job.completed" | "video.job.failed" | "ai.batch.completed" | "ai.batch.failed" | "captcha.verified" | "captcha.failed" | "realtime.channel.occupied" | "realtime.channel.vacated" | "realtime.member.added" | "realtime.member.removed" | "cron.executed" | "cron.failed" | "queue.dlq" | "error.captured" | "error.rate_anomaly" | "system.vendor.down" | "system.maintenance.scheduled")[] | 必填 | Event types to subscribe this webhook to; the closed set is the global event catalog.≥ 1 item |
description | string | null | 可选 | Free-text description of this resource≤ 256 chars |
secret | string | null | 可选 | Optional caller-provided signing secret; auto-generated when null. |
retry_policy | "default" | "aggressive" | null | 可选 | Retry policy configuration |
headers | object | null | 可选 | Custom HTTP headers added to every delivery. |
idempotency_key | string | null | 可选 | Client-provided idempotency key; prevents duplicate execution on retry |
account.webhooks.testPOST /v1/account/webhooks/test/{id}Send a test event to a webhook to verify connectivity.
参数 (1)
| 名称 | 类型 | 必填 | 说明 |
|---|---|---|---|
id | string | 必填 | Path parameter. |
account.webhooks.updatePATCH /v1/account/webhooks/update/{id}Partially update a webhook; changing the URL re-runs SSRF validation.
参数 (8)
| 名称 | 类型 | 必填 | 说明 |
|---|---|---|---|
id | string | 必填 | Path parameter. |
url | string | null | 可选 | URL for this resource or endpointformat: uri |
events | ("account.created" | "account.updated" | "account.absorbed" | "account.device_linked" | "account.deleted" | "topup.succeeded" | "topup.failed" | "topup.review_started" | "autorecharge.charged" | "autorecharge.failed" | "subscription.activated" | "subscription.renewed" | "subscription.cancelled" | "kyc.status_changed" | "tier.upgraded" | "tier.downgraded" | "wallet.low_balance" | "wallet.expiring_soon" | "wallet.expired" | "email.queued" | "email.sent" | "email.delivered" | "email.opened" | "email.clicked" | "email.bounced" | "email.complained" | "email.deferred" | "email.cancelled" | "email.unsubscribed" | "email.auto_suppressed" | "sms.queued" | "sms.sent" | "sms.delivered" | "sms.failed" | "sms.inbound" | "image.job.completed" | "image.job.failed" | "video.job.completed" | "video.job.failed" | "ai.batch.completed" | "ai.batch.failed" | "captcha.verified" | "captcha.failed" | "realtime.channel.occupied" | "realtime.channel.vacated" | "realtime.member.added" | "realtime.member.removed" | "cron.executed" | "cron.failed" | "queue.dlq" | "error.captured" | "error.rate_anomaly" | "system.vendor.down" | "system.maintenance.scheduled")[] | null | 可选 | List of event types this subscription listens to≥ 1 item |
description | string | null | 可选 | Free-text description of this resource≤ 256 chars |
active | boolean | null | 可选 | Whether this resource is currently active |
retry_policy | "default" | "aggressive" | null | 可选 | Retry policy configuration |
headers | object | null | 可选 | Custom HTTP headers to include in requests or responses |
idempotency_key | string | null | 可选 | Client-provided idempotency key; prevents duplicate execution on retry |
account.whoamiGET /v1/account/whoamiGet an account summary (ID, type, status, tier, balance).
无请求参数。
4. 完整示例
本模块的生产级端到端范例:先一次性配置,再运行业务流程,尽量覆盖本模块的多数 API。
单文件可运行 Python 程序(仅标准库、无 SDK):拷贝后填入 INFRAI_API_KEY 运行,即可按真实业务流逐步体验本模块核心 API——每一步都真实调用并计费,后续步骤复用前一步返回的真实字段。12 行 helper 就是全部集成代码。
#!/usr/bin/env python3
"""Infrai · account — 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) account.whoami — GET /v1/account/whoami · Get an account summary (ID, type, status, tier, balance).
r1 = show("account.whoami", infrai("GET", "/v1/account/whoami"))
# 2) account.balance — GET /v1/account/balance · Get the account wallet balance and trial status.
r2 = show("account.balance", infrai("GET", "/v1/account/balance"))
# 3) account.usage — GET /v1/account/usage · Summarize usage for the current billing period: spend, request count, and a per-capability breakdown.
r3 = show("account.usage", infrai("GET", "/v1/account/usage"))
一次性前置(每个范例都假定已完成):
# 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) account.balance
curl -X GET https://api.infrai.cc/v1/account/balance \
-H "Authorization: Bearer $INFRAI_API_KEY"
# 3) account.topup
curl -X POST https://api.infrai.cc/v1/account/topup \
-H "Authorization: Bearer $INFRAI_API_KEY" \
-H "Content-Type: application/json" \
-d '{"amount": 50, "currency": "USD", "payment_method": "stripe"}'
# 4) account.keys.list
curl -X GET https://api.infrai.cc/v1/account/keys/list \
-H "Authorization: Bearer $INFRAI_API_KEY"
# 5) account.tier.upgrade
curl -X POST https://api.infrai.cc/v1/account/tier/upgrade \
-H "Authorization: Bearer $INFRAI_API_KEY" \
-H "Content-Type: application/json" \
-d '{"target": "pro"}'
# 6) account.whoami
curl -X GET https://api.infrai.cc/v1/account/whoami \
-H "Authorization: Bearer $INFRAI_API_KEY"
# 7) account.usage
curl -X GET https://api.infrai.cc/v1/account/usage \
-H "Authorization: Bearer $INFRAI_API_KEY"
# 8) account.usage.timeseries
curl -X GET https://api.infrai.cc/v1/account/usage/timeseries \
-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) account.balance
# 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/account/balance",
headers={
"Authorization": f"Bearer {os.environ['INFRAI_API_KEY']}",
},
)
resp.raise_for_status()
print(resp.json())
# 3) account.topup
# 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/account/topup",
headers={
"Authorization": f"Bearer {os.environ['INFRAI_API_KEY']}",
},
json={'amount': 50, 'currency': 'USD', 'payment_method': 'stripe'},
)
resp.raise_for_status()
print(resp.json())
# 4) account.keys.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/account/keys/list",
headers={
"Authorization": f"Bearer {os.environ['INFRAI_API_KEY']}",
},
)
resp.raise_for_status()
print(resp.json())
# 5) account.tier.upgrade
# 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/account/tier/upgrade",
headers={
"Authorization": f"Bearer {os.environ['INFRAI_API_KEY']}",
},
json={'target': 'pro'},
)
resp.raise_for_status()
print(resp.json())
# 6) account.whoami
# 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/account/whoami",
headers={
"Authorization": f"Bearer {os.environ['INFRAI_API_KEY']}",
},
)
resp.raise_for_status()
print(resp.json())
# 7) account.usage
# 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/account/usage",
headers={
"Authorization": f"Bearer {os.environ['INFRAI_API_KEY']}",
},
)
resp.raise_for_status()
print(resp.json())
# 8) account.usage.timeseries
# 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/account/usage/timeseries",
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) account.balance
// Zero-install REST call — no SDK required (short-term the API is REST-only).
const resp = await fetch(
"https://api.infrai.cc/v1/account/balance",
{
method: "GET",
headers: {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
},
},
);
console.log(await resp.json());
// 3) account.topup
// Zero-install REST call — no SDK required (short-term the API is REST-only).
const resp = await fetch(
"https://api.infrai.cc/v1/account/topup",
{
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({"amount": 50, "currency": "USD", "payment_method": "stripe"}),
},
);
console.log(await resp.json());
// 4) account.keys.list
// Zero-install REST call — no SDK required (short-term the API is REST-only).
const resp = await fetch(
"https://api.infrai.cc/v1/account/keys/list",
{
method: "GET",
headers: {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
},
},
);
console.log(await resp.json());
// 5) account.tier.upgrade
// Zero-install REST call — no SDK required (short-term the API is REST-only).
const resp = await fetch(
"https://api.infrai.cc/v1/account/tier/upgrade",
{
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({"target": "pro"}),
},
);
console.log(await resp.json());
// 6) account.whoami
// Zero-install REST call — no SDK required (short-term the API is REST-only).
const resp = await fetch(
"https://api.infrai.cc/v1/account/whoami",
{
method: "GET",
headers: {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
},
},
);
console.log(await resp.json());
// 7) account.usage
// Zero-install REST call — no SDK required (short-term the API is REST-only).
const resp = await fetch(
"https://api.infrai.cc/v1/account/usage",
{
method: "GET",
headers: {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
},
},
);
console.log(await resp.json());
// 8) account.usage.timeseries
// Zero-install REST call — no SDK required (short-term the API is REST-only).
const resp = await fetch(
"https://api.infrai.cc/v1/account/usage/timeseries",
{
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) account.balance
// Zero-install REST call — no SDK required (short-term the API is REST-only).
const resp = await fetch(
"https://api.infrai.cc/v1/account/balance",
{
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);
// 3) account.topup
// Zero-install REST call — no SDK required (short-term the API is REST-only).
const resp = await fetch(
"https://api.infrai.cc/v1/account/topup",
{
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({"amount": 50, "currency": "USD", "payment_method": "stripe"}),
},
);
if (!resp.ok) throw new Error(`infrai ${resp.status}`);
const data: unknown = await resp.json();
console.log(data);
// 4) account.keys.list
// Zero-install REST call — no SDK required (short-term the API is REST-only).
const resp = await fetch(
"https://api.infrai.cc/v1/account/keys/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) account.tier.upgrade
// Zero-install REST call — no SDK required (short-term the API is REST-only).
const resp = await fetch(
"https://api.infrai.cc/v1/account/tier/upgrade",
{
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({"target": "pro"}),
},
);
if (!resp.ok) throw new Error(`infrai ${resp.status}`);
const data: unknown = await resp.json();
console.log(data);
// 6) account.whoami
// Zero-install REST call — no SDK required (short-term the API is REST-only).
const resp = await fetch(
"https://api.infrai.cc/v1/account/whoami",
{
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) account.usage
// Zero-install REST call — no SDK required (short-term the API is REST-only).
const resp = await fetch(
"https://api.infrai.cc/v1/account/usage",
{
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) account.usage.timeseries
// Zero-install REST call — no SDK required (short-term the API is REST-only).
const resp = await fetch(
"https://api.infrai.cc/v1/account/usage/timeseries",
{
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);