Account
Activation, balance, top-up, keys and tier management.
1. Overview
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. Methods (29)
2.1account.balance
Read the wallet balance.
Returns
{ balance_usd, currency }| Name | Type | Description |
|---|---|---|
balance | number | Current wallet balance in USD≥ 0 |
cap | number | null | Wallet upper bound for current tier; null for Enterprise (no cap).≥ 0 |
available_room | number | null | = cap - balance; null when cap is null (uncapped).≥ 0 |
runway_days | number | null | Estimated days at current daily_avg_spend; null when spend rate is ~0.≥ 0 |
daily_avg_spend | number | Average daily spend in USD≥ 0 |
tier | "standard" | "pro" | "enterprise" | Current subscription tier (standard / pro / enterprise) |
expires_at | string | null | Trial-credit expiry (last activity + grace window); null when there is no expiring trial credit.format: date-time |
expires_in_days | integer | null | Days until the current balance or subscription expires |
activity_required_by | string | null | Date by which account activity is required to maintain statusformat: date-time |
is_refundable | boolean | Whether the current balance is eligible for refund |
is_transferable | boolean | Whether the current balance can be transferred to another account |
is_in_grace_period | boolean | Whether the account is in the grace period after balance expiry |
grace_period_ends_at | string | null | ISO 8601 timestamp when the grace period endsformat: date-time |
forfeited_amount | number | null | Amount forfeited during account operations, in USD≥ 0 |
pending_topups | string[] | null | List of pending top-up sessions |
account_id | string | null | The account the balance belongs to. |
balance_usd | number | Alias of `balance` for the documented SDK/CLI status surface.≥ 0 |
currency | string | ISO 4217 currency code (e.g. USD, CNY)e.g. USD |
affordable_uses_hint | object | null | Per-capability hint: how many more flat-priced calls the current balance covers (best-effort, omitted for token-metered caps). |
Example
一次性前置(每个范例都假定已完成):
# 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
Top up the wallet; returns a checkout URL to hand the user — card data never touches infrai.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
amount_usd | number | Required | Top-up amount in USD.≥ 0 |
return_url | string | Optional | Where to return after checkout.format: uri |
idempotency_key | string | Optional | Optional dedup key; identical retries return the same result. |
Returns
TopupRecord { topup_id, amount_usd, state, next_action_url? }| Name | Type | Description |
|---|---|---|
topup_id | string | Provider checkout-session id (Stripe cs_... / dev cs_mock_...). Pass to account.topup_status to poll the outcome. |
status | "pending" | "paid" | "failed" | "unknown" | pending until the user completes browser checkout; the Stripe webhook flips it to paid/failed. |
checkout_url | string | Open this to pay; on success the wallet is credited.format: uri |
checkout_mode | "stripe" | "mock" | stripe = real Stripe Checkout; mock = local dev session. |
amount_usd | number | Top-up amount in USD.≥ 0.5 |
amount | number | Back-compat alias of amount_usd.≥ 0.5 |
currency | string | ISO 4217 currency code (e.g. USD, CNY)e.g. USD |
Example
一次性前置(每个范例都假定已完成):
# 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
List the project keys on the account.
Returns
{ items: Array<{ key_id, label, scopes, created_at }> }| Name | Type | Description |
|---|---|---|
items | object[] | Array of result items in this page |
items[].key_id | string | Key id. On list it is MASKED (optional prefix + separator + last 4) — the separator is ASCII '...' (path-safe) or the legacy unicode ellipsis, e.g. ifr_...52fb / ifr_pk_proj_…9180 / ifr_…ab74. The full ifr_ value is only ever returned at create time.pattern: ^ifr_[A-Za-z0-9_]*(\.\.\.|\u202… |
items[].key_secret | string | null | Full plaintext value; returned only on create. |
items[].key | string | null | account.keys.rotate only. Full plaintext value of the newly-minted secret, shown exactly once (same purpose as key_secret on create, different field name on this endpoint). |
items[].old_key_id | string | null | account.keys.rotate only. Masked id of the key that was superseded by this rotation. |
items[].rotated | boolean | account.keys.rotate only. Whether a new secret was actually minted (false when the referenced key was not found). |
items[].revoked | boolean | account.keys.revoke / .suspected_compromise only. Whether the key was actually revoked (false when the referenced key was not found). |
items[].action | string | null | account.keys.suspected_compromise only. Fixed action label, e.g. 'revoked_on_compromise_report'. |
items[].updated | boolean | account.keys.update only. Whether the key record was actually updated (false when the referenced key was not found). |
items[].name | string | null | Human-readable name for this resource |
items[].tier | string | null | Billing tier the key inherits from its account (standard/pro/enterprise). |
items[].scopes | string[] | Granted scopes. OMITTED from list output (internal; session keys filtered) — present only where the surface exposes it. |
items[].created_at | string | ISO 8601 timestamp when this resource was createdformat: date-time |
items[].last_used_at | string | null | ISO 8601 timestamp when this key was last usedformat: date-time |
items[].last_used_ip | string | null | IP of the most recent request authenticated with this key; null if never used. |
items[].expires_at | string | null | ISO 8601 timestamp when this resource or token expiresformat: date-time |
items[].revoked_at | string | null | ISO 8601 timestamp when this key was revokedformat: date-time |
items[].status | "active" | "rotating" | "revoked" | "not_found" | Current status of this resource. 'not_found' is returned by keys.update/.rotate/.suspected_compromise when the referenced key_id doesn't resolve to a key on this account. |
next_cursor | string | null | Opaque cursor to fetch the next page; null/absent if this is the last page |
count | integer | Total number of items across all pages≥ 0 |
Example
一次性前置(每个范例都假定已完成):
# 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
Upgrade the account to a target tier.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
target_tier | string | Required | Tier id to upgrade to. |
Returns
AccountSummary { account_id, kind, status, tier, balance_usd }| Name | Type | Description |
|---|---|---|
target | "pro" | "team" | "enterprise" | Target URL or resource for webhook or notification |
requires_checkout | boolean | Whether a Stripe checkout session is required to complete the change |
checkout_url | string | null | URL for the Stripe checkout sessionformat: uri |
requires_sales_contact | boolean | Whether contacting sales is required to complete the change |
contact_sales_url | string | null | URL to contact the sales teamformat: uri |
current_tier | string | null | Effective tier before this upgrade. |
status | "pending" | "active" | null | Subscription lifecycle after the call. pending = awaiting checkout webhook; active = confirmed (dev/non-prod posture). |
immediate_effect | boolean | null | True only when the tier flipped immediately (dev/non-prod posture, no real payment). |
price_usd | number | null | Resolved plan price in USD. |
period | string | null | Billing period of the resolved plan (e.g. monthly/annual). |
subscription | object | null | Public view of the created subscription (present when confirmed). |
subscription_id | string | null | Created subscription id (present when pending checkout). |
payment_source | "wallet" | "dev_mock" | "stripe_subscription" | null | How the upgrade was (or will be) funded: wallet balance, dev/non-prod auto-confirm, or a real Stripe subscription checkout. Absent for the enterprise (sales-contact) branch. |
checkout_mode | string | null | Mode of the created checkout session (e.g. 'stripe'/'mock'). Present only alongside checkout_url (payment_source=stripe_subscription). |
account_id | string | null | Account the upgrade applies to. |
Example
一次性前置(每个范例都假定已完成):
# 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、类型、状态、档位、余额)。
Returns
AccountSummary { account_id, kind, status, tier, balance_usd }| Name | Type | Description |
|---|---|---|
account_id | string | Real ids use a 16-hex device/email suffix (e.g. acct_anon_9424f4c4b31d4908); pattern relaxed to a minimum of 12 hex chars to match the live id format.pattern: ^acct_(anon|email|unbound)_[A-Z… |
account_kind | "anonymous" | "email" | "unbound" | Identity state of the key holder. `unbound` = key minted by infra.activate() not yet linked to an email; `email` = bound via OTP/Google/GitHub. `anonymous` is a legacy alias for `unbound` (will be retired). |
email | string | null | Email addressformat: email |
email_verified | boolean | Whether the email address has been verified |
linked_providers | ("email_otp" | "google" | "github" | "oauth")[] | Identity providers that have verified this email. The same email can be linked via multiple methods (Google + GitHub + OTP) and all resolve to one account. Empty for unbound keys. |
display_name | string | null | Human-readable display name |
region | "global" | "cn" | Geographic region where this resource is located or processed |
created_at | string | null | User-row creation time. Null for unbound keys (no User row yet).format: date-time |
last_active_at | string | null | Latest of last_login_at / updated_at on the User row. Null for unbound keys.format: date-time |
tier | "standard" | "pro" | "enterprise" | Current subscription tier (standard / pro / enterprise) |
kyc_status | "none" | "pending" | "approved" | "rejected" | Current KYC verification status |
totp_enabled | boolean | Whether TOTP-based 2FA is enabled for this account |
pro_subscription | object | null | Details of the active Pro subscription, if any |
enterprise_contract | object | null | Details of the enterprise contract, if any |
device_fingerprint | string | Device fingerprint hash for identity tracking |
current_project_key_id | string | Current project key identifier |
project_count | integer | Number of projects in this account≥ 0 |
absorbed_anon_account_ids | string[] | List of anonymous account IDs absorbed during linking |
linked_devices_count | integer | Number of linked device accounts≥ 0 |
project_id | string | null | The project_id the caller's bearer key is bound to. Mirrors api_key.project_id (e.g. `proj_anon_xxx` for an unbound key). Null when the bearer has no project. |
key_id | string | null | Masked (non-secret) form of the caller's bearer key — same value as `current_project_key_id`. Kept for compatibility with the original `account.whoami` shape; new callers should read `current_project_key_id`. |
Example
一次性前置(每个范例都假定已完成):
# 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
获取本计费周期的用量汇总(消费、请求数、按能力拆分)。
Returns
UsageSummary { period, spend_usd, requests, by_capability }| Name | Type | Description |
|---|---|---|
period | "1d" | "7d" | "30d" | "mtd" | "ytd" | Billing or retention period (e.g. monthly, daily) |
period_start | string | Start of the current billing periodformat: date-time |
period_end | string | End of the current billing periodformat: date-time |
total_cost | number | Total cost in USD for the queried period≥ 0 |
total_calls | integer | Total number of API calls in the queried period≥ 0 |
total_failed_calls | integer | Total number of failed API calls in the queried period≥ 0 |
cache_hits | integer | Number of cache hits in the queried period≥ 0 |
cache_savings | number | Estimated cost savings from cache hits in USD≥ 0 |
breakdown | object[] | Cost breakdown by component |
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 | - |
Example
一次性前置(每个范例都假定已完成):
# 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
按时间粒度获取用量时间序列。
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
start | string | Optional | 起始时间(ISO 8601),留空则取周期起点。 |
end | string | Optional | 结束时间(ISO 8601),留空则取当前。 |
granularity | "hour" | "day" | "month" | Optional | 聚合粒度:hour / day / month。 |
Returns
UsageTimeseries { granularity, points: Array<{ ts, spend_usd, requests }> }| Name | Type | Description |
|---|---|---|
period | "1d" | "7d" | "30d" | "mtd" | "ytd" | Billing or retention period (e.g. monthly, daily) |
buckets | object[] | Time-bucketed data points |
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 | Opaque cursor to fetch the next page; null/absent if this is the last page |
Example
一次性前置(每个范例都假定已完成):
# 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
获取当前预算配置(周期、硬上限、告警阈值)。
Returns
BudgetConfig { period, hard_cap_usd?, alert_threshold_usd? }| Name | Type | Description |
|---|---|---|
hard_cap_usd | number | null | Spend in the period is blocked past this; null = no cap.≥ 0 |
limit_usd | number | null | account.budget.set only. Same meaning as hard_cap_usd, echoed under the request field name.≥ 0 |
period | "daily" | "monthly" | Billing or retention period (e.g. monthly, daily) |
alert_threshold_usd | number | null | Fire low-balance / budget-near alert at this remaining balance; null = no alert.≥ 0 |
alert_threshold_pct | number | null | account.budget.set only. Alert threshold expressed as a percentage of hard_cap_usd, echoed back as set.≥ 0 |
spent_this_period_usd | number | Amount spent in the current billing period in USD≥ 0 |
period_resets_at | string | null | ISO 8601 timestamp when the current period resetsformat: date-time |
configured | boolean | Whether a budget row has been set (false = no cap configured; the *_usd fields are then null/0). |
updated_at | string | null | ISO 8601 timestamp when this resource was last updatedformat: date-time |
Example
一次性前置(每个范例都假定已完成):
# 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
设置预算:周期内消费达到硬上限即拦截,达到阈值即告警。
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
period | "daily" | "monthly" | Required | 预算周期:daily 或 monthly。 |
hard_cap_usd | number | Optional | 硬上限(美元),超过即拦截后续计费请求。≥ 0 |
alert_threshold_usd | number | Optional | 告警阈值(美元),达到即触发告警。≥ 0 |
idempotency_key | string | Optional | Optional dedup key; identical retries return the same result. |
Returns
BudgetConfig { period, hard_cap_usd?, alert_threshold_usd? }| Name | Type | Description |
|---|---|---|
hard_cap_usd | number | null | Spend in the period is blocked past this; null = no cap.≥ 0 |
limit_usd | number | null | account.budget.set only. Same meaning as hard_cap_usd, echoed under the request field name.≥ 0 |
period | "daily" | "monthly" | Billing or retention period (e.g. monthly, daily) |
alert_threshold_usd | number | null | Fire low-balance / budget-near alert at this remaining balance; null = no alert.≥ 0 |
alert_threshold_pct | number | null | account.budget.set only. Alert threshold expressed as a percentage of hard_cap_usd, echoed back as set.≥ 0 |
spent_this_period_usd | number | Amount spent in the current billing period in USD≥ 0 |
period_resets_at | string | null | ISO 8601 timestamp when the current period resetsformat: date-time |
configured | boolean | Whether a budget row has been set (false = no cap configured; the *_usd fields are then null/0). |
updated_at | string | null | ISO 8601 timestamp when this resource was last updatedformat: date-time |
Example
一次性前置(每个范例都假定已完成):
# 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
获取自动充值配置。
Returns
AutorechargeConfig { enabled, trigger_balance, recharge_amount, max_per_day, max_per_month }| Name | Type | Description |
|---|---|---|
enabled | boolean | Whether this feature or configuration is enabled |
trigger_balance | number | Balance threshold that triggers automatic recharge, in USD≥ 0 |
recharge_amount | number | Amount to recharge when triggered, in USD≥ 0 |
payment_method_id | string | Identifier of the payment method used |
payment_method_summary | string | e.g. 'Visa ****4242'. |
max_per_day | integer | Maximum recharge amount per day in USD≥ 1 |
max_per_month | integer | Maximum recharge amount per month in USD≥ 1 |
triggered_today | integer | Amount recharged today in USD≥ 0 |
triggered_this_month | integer | Amount recharged this month in USD≥ 0 |
next_check_at | string | null | ISO 8601 timestamp when the next balance check will occurformat: date-time |
last_succeeded_at | string | null | ISO 8601 timestamp of the last successful paymentformat: date-time |
last_failed_at | string | null | ISO 8601 timestamp of the last payment failureformat: date-time |
consecutive_failures | integer | Number of consecutive payment failures≥ 0 |
configured | boolean | Whether a config row exists for this account (false = never set up; the numeric fields are then zero defaults). |
disabled_reason | string | null | Why auto-recharge is currently disabled (e.g. 'user', 'max_failures', 'admin'); null when enabled or never disabled. |
Example
一次性前置(每个范例都假定已完成):
# 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
配置自动充值:余额低于触发值时自动扣款充值。
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
trigger_balance | number | Required | 触发余额:钱包余额低于此值即自动充值。≥ 0 |
recharge_amount | number | Required | 每次自动充值的金额(美元)。> 0 |
payment_method_id | string | Optional | 扣款支付方式 ID,留空则使用账户默认支付方式。 |
max_per_day | number | Optional | 每日自动充值次数上限(防滥用)。≥ 1default: 3 |
max_per_month | number | Optional | 每月自动充值次数上限(防滥用)。≥ 1default: 30 |
idempotency_key | string | Optional | Optional dedup key; identical retries return the same result. |
Returns
AutorechargeConfig { enabled, trigger_balance, recharge_amount, max_per_day, max_per_month }| Name | Type | Description |
|---|---|---|
enabled | boolean | Whether this feature or configuration is enabled |
trigger_balance | number | Balance threshold that triggers automatic recharge, in USD≥ 0 |
recharge_amount | number | Amount to recharge when triggered, in USD≥ 0 |
payment_method_id | string | Identifier of the payment method used |
payment_method_summary | string | e.g. 'Visa ****4242'. |
max_per_day | integer | Maximum recharge amount per day in USD≥ 1 |
max_per_month | integer | Maximum recharge amount per month in USD≥ 1 |
triggered_today | integer | Amount recharged today in USD≥ 0 |
triggered_this_month | integer | Amount recharged this month in USD≥ 0 |
next_check_at | string | null | ISO 8601 timestamp when the next balance check will occurformat: date-time |
last_succeeded_at | string | null | ISO 8601 timestamp of the last successful paymentformat: date-time |
last_failed_at | string | null | ISO 8601 timestamp of the last payment failureformat: date-time |
consecutive_failures | integer | Number of consecutive payment failures≥ 0 |
configured | boolean | Whether a config row exists for this account (false = never set up; the numeric fields are then zero defaults). |
disabled_reason | string | null | Why auto-recharge is currently disabled (e.g. 'user', 'max_failures', 'admin'); null when enabled or never disabled. |
Example
一次性前置(每个范例都假定已完成):
# 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
将指定支付方式设为账户默认。
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
payment_method_id | string | Required | 要设为默认的支付方式 ID。 |
idempotency_key | string | Optional | Optional dedup key; identical retries return the same result. |
Returns
AccountPaymentMethod { id, brand, last4, is_default }| Name | Type | Description |
|---|---|---|
payment_method_id | string | Identifier of the payment method used |
set_default | boolean | account.payment_method.set_default only. Whether the default was actually changed (false when payment_method_id isn't a known saved method). |
status | "not_found" | null | account.payment_method.set_default only. Present ('not_found') when payment_method_id doesn't match a saved method. |
message | string | null | account.payment_method.set_default only. Human-readable detail when set_default is false. |
kind | "card" | "sepa" | "ach" | "alipay" | "wechat" | "applepay" | "googlepay" | null | Optional. Structured instrument kind; absent for cards saved via the setup-intent flow (only the provider summary is retained) — see `summary`. |
summary | string | null | Human-readable description of the instrument, e.g. 'Visa ****4242'. |
stripe_customer_id | string | null | Stripe customer id the method is attached to; null in mock/dev. |
is_default | boolean | Whether this is the default payment method |
last4 | string | null | Last 4 digits of the card numberpattern: ^[0-9]{4}$ |
brand | string | null | Card brand (e.g. visa, mastercard) |
expires | string | null | MM/YY for card kind. |
added_at | string | null | ISO 8601 timestamp when this resource was addedformat: date-time |
Example
一次性前置(每个范例都假定已完成):
# 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
获取当前账户档位及其额度限制。
Returns
TierInfo { tier, limits, billing_period }| Name | Type | Description |
|---|---|---|
tier | "standard" | "pro" | "enterprise" | Current subscription tier (standard / pro / enterprise) |
since | string | ISO 8601 date when the current tier or state became effectiveformat: date-time |
wallet_cap | number | null | null for Enterprise (no cap).≥ 0 |
rate_limit_multiplier | number | Rate limit multiplier applied at this tier≥ 1 |
features | string[] | List of features available at this tier |
pro_subscription | object | null | Details of the active Pro subscription, if any |
enterprise_contract | object | null | Details of the enterprise contract, if any |
account_id | string | null | The account whose tier this is. |
Example
一次性前置(每个范例都假定已完成):
# 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
获取订阅状态(档位、当前周期结束时间、是否将取消)。
Returns
SubscriptionInfo { status, tier, current_period_end, cancel_at_period_end }| Name | Type | Description |
|---|---|---|
model | "usage_based" | Always usage_based; pay-as-you-go wallet with optional auto-recharge. |
tier | "standard" | "pro" | "enterprise" | Current subscription tier (standard / pro / enterprise) |
fixed_subscription | object | null | Reserved for a future fixed recurring plan; null today (no fixed subscription). |
autorecharge | object | The recurring funding policy: auto top-up of the wallet when it drops below 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 | Masked card summary, e.g. 'Visa ****4242'. |
Example
一次性前置(每个范例都假定已完成):
# 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 仅在创建时返回一次。
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
name | string | Optional | Key 名称(最长 128 字符)。≤ 128 chars |
scopes | string[] | Optional | 作用域列表,留空表示全模块。 |
idempotency_key | string | Optional | Optional dedup key; identical retries return the same result. |
Returns
ApiKey { key_id, name, scopes, key_secret, created_at }| Name | Type | Description |
|---|---|---|
key_id | string | Key id. On list it is MASKED (optional prefix + separator + last 4) — the separator is ASCII '...' (path-safe) or the legacy unicode ellipsis, e.g. ifr_...52fb / ifr_pk_proj_…9180 / ifr_…ab74. The full ifr_ value is only ever returned at create time.pattern: ^ifr_[A-Za-z0-9_]*(\.\.\.|\u202… |
key_secret | string | null | Full plaintext value; returned only on create. |
key | string | null | account.keys.rotate only. Full plaintext value of the newly-minted secret, shown exactly once (same purpose as key_secret on create, different field name on this endpoint). |
old_key_id | string | null | account.keys.rotate only. Masked id of the key that was superseded by this rotation. |
rotated | boolean | account.keys.rotate only. Whether a new secret was actually minted (false when the referenced key was not found). |
revoked | boolean | account.keys.revoke / .suspected_compromise only. Whether the key was actually revoked (false when the referenced key was not found). |
action | string | null | account.keys.suspected_compromise only. Fixed action label, e.g. 'revoked_on_compromise_report'. |
updated | boolean | account.keys.update only. Whether the key record was actually updated (false when the referenced key was not found). |
name | string | null | Human-readable name for this resource |
tier | string | null | Billing tier the key inherits from its account (standard/pro/enterprise). |
scopes | string[] | Granted scopes. OMITTED from list output (internal; session keys filtered) — present only where the surface exposes it. |
created_at | string | ISO 8601 timestamp when this resource was createdformat: date-time |
last_used_at | string | null | ISO 8601 timestamp when this key was last usedformat: date-time |
last_used_ip | string | null | IP of the most recent request authenticated with this key; null if never used. |
expires_at | string | null | ISO 8601 timestamp when this resource or token expiresformat: date-time |
revoked_at | string | null | ISO 8601 timestamp when this key was revokedformat: date-time |
status | "active" | "rotating" | "revoked" | "not_found" | Current status of this resource |
Example
一次性前置(每个范例都假定已完成):
# 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 的名称和/或作用域,作用域收紧立即生效。
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
key_id | string | Required | API Key ID。 |
name | string | Optional | 新 Key 名称。≤ 128 chars |
scopes | string[] | Optional | 新作用域列表。 |
idempotency_key | string | Optional | Optional dedup key; identical retries return the same result. |
Returns
ApiKey { key_id, name, scopes }| Name | Type | Description |
|---|---|---|
key_id | string | Key id. On list it is MASKED (optional prefix + separator + last 4) — the separator is ASCII '...' (path-safe) or the legacy unicode ellipsis, e.g. ifr_...52fb / ifr_pk_proj_…9180 / ifr_…ab74. The full ifr_ value is only ever returned at create time.pattern: ^ifr_[A-Za-z0-9_]*(\.\.\.|\u202… |
key_secret | string | null | Full plaintext value; returned only on create. |
key | string | null | account.keys.rotate only. Full plaintext value of the newly-minted secret, shown exactly once (same purpose as key_secret on create, different field name on this endpoint). |
old_key_id | string | null | account.keys.rotate only. Masked id of the key that was superseded by this rotation. |
rotated | boolean | account.keys.rotate only. Whether a new secret was actually minted (false when the referenced key was not found). |
revoked | boolean | account.keys.revoke / .suspected_compromise only. Whether the key was actually revoked (false when the referenced key was not found). |
action | string | null | account.keys.suspected_compromise only. Fixed action label, e.g. 'revoked_on_compromise_report'. |
updated | boolean | account.keys.update only. Whether the key record was actually updated (false when the referenced key was not found). |
name | string | null | Human-readable name for this resource |
tier | string | null | Billing tier the key inherits from its account (standard/pro/enterprise). |
scopes | string[] | Granted scopes. OMITTED from list output (internal; session keys filtered) — present only where the surface exposes it. |
created_at | string | ISO 8601 timestamp when this resource was createdformat: date-time |
last_used_at | string | null | ISO 8601 timestamp when this key was last usedformat: date-time |
last_used_ip | string | null | IP of the most recent request authenticated with this key; null if never used. |
expires_at | string | null | ISO 8601 timestamp when this resource or token expiresformat: date-time |
revoked_at | string | null | ISO 8601 timestamp when this key was revokedformat: date-time |
status | "active" | "rotating" | "revoked" | "not_found" | Current status of this resource |
Example
一次性前置(每个范例都假定已完成):
# 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:签发新密钥,旧密钥在宽限期内仍有效。
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
key_id | string | Required | API Key ID。 |
grace_hours | number | Optional | 旧密钥宽限有效小时数(0-168,默认 24)。0–168default: 24 |
idempotency_key | string | Optional | Optional dedup key; identical retries return the same result. |
Returns
ApiKey { key_id, key_secret, status, grace_expires_at }| Name | Type | Description |
|---|---|---|
key_id | string | Key id. On list it is MASKED (optional prefix + separator + last 4) — the separator is ASCII '...' (path-safe) or the legacy unicode ellipsis, e.g. ifr_...52fb / ifr_pk_proj_…9180 / ifr_…ab74. The full ifr_ value is only ever returned at create time.pattern: ^ifr_[A-Za-z0-9_]*(\.\.\.|\u202… |
key_secret | string | null | Full plaintext value; returned only on create. |
key | string | null | account.keys.rotate only. Full plaintext value of the newly-minted secret, shown exactly once (same purpose as key_secret on create, different field name on this endpoint). |
old_key_id | string | null | account.keys.rotate only. Masked id of the key that was superseded by this rotation. |
rotated | boolean | account.keys.rotate only. Whether a new secret was actually minted (false when the referenced key was not found). |
revoked | boolean | account.keys.revoke / .suspected_compromise only. Whether the key was actually revoked (false when the referenced key was not found). |
action | string | null | account.keys.suspected_compromise only. Fixed action label, e.g. 'revoked_on_compromise_report'. |
updated | boolean | account.keys.update only. Whether the key record was actually updated (false when the referenced key was not found). |
name | string | null | Human-readable name for this resource |
tier | string | null | Billing tier the key inherits from its account (standard/pro/enterprise). |
scopes | string[] | Granted scopes. OMITTED from list output (internal; session keys filtered) — present only where the surface exposes it. |
created_at | string | ISO 8601 timestamp when this resource was createdformat: date-time |
last_used_at | string | null | ISO 8601 timestamp when this key was last usedformat: date-time |
last_used_ip | string | null | IP of the most recent request authenticated with this key; null if never used. |
expires_at | string | null | ISO 8601 timestamp when this resource or token expiresformat: date-time |
revoked_at | string | null | ISO 8601 timestamp when this key was revokedformat: date-time |
status | "active" | "rotating" | "revoked" | "not_found" | Current status of this resource |
Example
一次性前置(每个范例都假定已完成):
# 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,立即失效。
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
key_id | string | Required | API Key ID。 |
idempotency_key | string | Optional | Optional dedup key; identical retries return the same result. |
Returns
{ revoked: boolean }| Name | Type | Description |
|---|---|---|
key_id | string | Key id. On list it is MASKED (optional prefix + separator + last 4) — the separator is ASCII '...' (path-safe) or the legacy unicode ellipsis, e.g. ifr_...52fb / ifr_pk_proj_…9180 / ifr_…ab74. The full ifr_ value is only ever returned at create time.pattern: ^ifr_[A-Za-z0-9_]*(\.\.\.|\u202… |
key_secret | string | null | Full plaintext value; returned only on create. |
key | string | null | account.keys.rotate only. Full plaintext value of the newly-minted secret, shown exactly once (same purpose as key_secret on create, different field name on this endpoint). |
old_key_id | string | null | account.keys.rotate only. Masked id of the key that was superseded by this rotation. |
rotated | boolean | account.keys.rotate only. Whether a new secret was actually minted (false when the referenced key was not found). |
revoked | boolean | account.keys.revoke / .suspected_compromise only. Whether the key was actually revoked (false when the referenced key was not found). |
action | string | null | account.keys.suspected_compromise only. Fixed action label, e.g. 'revoked_on_compromise_report'. |
updated | boolean | account.keys.update only. Whether the key record was actually updated (false when the referenced key was not found). |
name | string | null | Human-readable name for this resource |
tier | string | null | Billing tier the key inherits from its account (standard/pro/enterprise). |
scopes | string[] | Granted scopes. OMITTED from list output (internal; session keys filtered) — present only where the surface exposes it. |
created_at | string | ISO 8601 timestamp when this resource was createdformat: date-time |
last_used_at | string | null | ISO 8601 timestamp when this key was last usedformat: date-time |
last_used_ip | string | null | IP of the most recent request authenticated with this key; null if never used. |
expires_at | string | null | ISO 8601 timestamp when this resource or token expiresformat: date-time |
revoked_at | string | null | ISO 8601 timestamp when this key was revokedformat: date-time |
status | "active" | "rotating" | "revoked" | "not_found" | Current status of this resource |
Example
一次性前置(每个范例都假定已完成):
# 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 疑似泄露,可立即吊销并自动签发替换密钥。
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
key_id | string | Required | API Key ID。 |
confirmed_leak | boolean | Optional | 是否已确认泄露,true 则立即吊销。default: false |
auto_rotate | boolean | Optional | 是否自动签发替换密钥。default: true |
idempotency_key | string | Optional | Optional dedup key; identical retries return the same result. |
Returns
ApiKey { key_id, status, key_secret? }| Name | Type | Description |
|---|---|---|
key_id | string | Key id. On list it is MASKED (optional prefix + separator + last 4) — the separator is ASCII '...' (path-safe) or the legacy unicode ellipsis, e.g. ifr_...52fb / ifr_pk_proj_…9180 / ifr_…ab74. The full ifr_ value is only ever returned at create time.pattern: ^ifr_[A-Za-z0-9_]*(\.\.\.|\u202… |
key_secret | string | null | Full plaintext value; returned only on create. |
key | string | null | account.keys.rotate only. Full plaintext value of the newly-minted secret, shown exactly once (same purpose as key_secret on create, different field name on this endpoint). |
old_key_id | string | null | account.keys.rotate only. Masked id of the key that was superseded by this rotation. |
rotated | boolean | account.keys.rotate only. Whether a new secret was actually minted (false when the referenced key was not found). |
revoked | boolean | account.keys.revoke / .suspected_compromise only. Whether the key was actually revoked (false when the referenced key was not found). |
action | string | null | account.keys.suspected_compromise only. Fixed action label, e.g. 'revoked_on_compromise_report'. |
updated | boolean | account.keys.update only. Whether the key record was actually updated (false when the referenced key was not found). |
name | string | null | Human-readable name for this resource |
tier | string | null | Billing tier the key inherits from its account (standard/pro/enterprise). |
scopes | string[] | Granted scopes. OMITTED from list output (internal; session keys filtered) — present only where the surface exposes it. |
created_at | string | ISO 8601 timestamp when this resource was createdformat: date-time |
last_used_at | string | null | ISO 8601 timestamp when this key was last usedformat: date-time |
last_used_ip | string | null | IP of the most recent request authenticated with this key; null if never used. |
expires_at | string | null | ISO 8601 timestamp when this resource or token expiresformat: date-time |
revoked_at | string | null | ISO 8601 timestamp when this key was revokedformat: date-time |
status | "active" | "rotating" | "revoked" | "not_found" | Current status of this resource |
Example
一次性前置(每个范例都假定已完成):
# 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。
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
cursor | string | Optional | 分页游标:传入上一页返回的 next_cursor 获取下一页。 |
limit | number | Optional | 单页返回条数上限。 |
Returns
{ items: Array<Webhook>, next_cursor? }| Name | Type | Description |
|---|---|---|
items | object[] | Array of result items in this page |
items[].webhook_id | string | Webhook subscription id (whk_… in the account_resource store).pattern: ^whk?_[A-Za-z0-9]{16,}$ |
items[].url | string | URL for this resource or endpointformat: uri |
items[].events | string[] | Event names per enums/webhook_event.yaml. |
items[].description | string | null | Free-text description of this resource |
items[].secret | string | null | Plaintext secret — returned only on initial create. |
items[].secret_hash | string | null | SHA-256 hex of secret; returned on list/get. |
items[].active | boolean | Whether deliveries are sent. Canonical state field. |
items[].enabled | boolean | null | Back-compat alias of `active` (console reads this). |
items[].status | string | null | account_resource lifecycle status (e.g. 'active'). |
items[].retry_policy | "default" | "aggressive" | null | Retry policy configuration |
items[].headers | object | null | Custom HTTP headers added to every delivery. |
items[].last_delivery_at | string | null | ISO 8601 timestamp of the last delivery attemptformat: date-time |
items[].last_delivery_status | "success" | "failed" | null | Status of the last delivery attempt |
items[].failure_count_24h | integer | Number of failed deliveries in the last 24 hours≥ 0 |
items[].auto_disabled_at | string | null | Set when 100 consecutive failures triggered auto-disable.format: date-time |
items[].created_at | string | null | ISO 8601 timestamp when this resource was created. Absent on account.webhooks.update (patch response echoes updated_at only).format: date-time |
items[].updated_at | string | null | ISO 8601 timestamp when this resource was last updated. Returned by .get/.update; absent on .register/.list.format: date-time |
next_cursor | string | null | Opaque cursor to fetch the next page; null/absent if this is the last page |
count | integer | Total number of items across all pages≥ 0 |
Example
一次性前置(每个范例都假定已完成):
# 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 仅返回一次。
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
url | string | Required | 接收回调的公网 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")[] | Required | 订阅的事件类型列表。≥ 1 item |
description | string | Optional | 备注说明(可选,最长 256 字符)。≤ 256 chars |
secret | string | Optional | 自定义签名密钥,留空则自动生成。 |
retry_policy | "default" | "aggressive" | null | Optional | 重试策略:default 或 aggressive。 |
headers | Record<string, string> | Optional | 每次投递附加的自定义 HTTP 头。 |
idempotency_key | string | Optional | Optional dedup key; identical retries return the same result. |
Returns
Webhook { id, url, events, secret, active }| Name | Type | Description |
|---|---|---|
webhook_id | string | Webhook subscription id (whk_… in the account_resource store).pattern: ^whk?_[A-Za-z0-9]{16,}$ |
url | string | URL for this resource or endpointformat: uri |
events | string[] | Event names per enums/webhook_event.yaml. |
description | string | null | Free-text description of this resource |
secret | string | null | Plaintext secret — returned only on initial create. |
secret_hash | string | null | SHA-256 hex of secret; returned on list/get. |
active | boolean | Whether deliveries are sent. Canonical state field. |
enabled | boolean | null | Back-compat alias of `active` (console reads this). |
status | string | null | account_resource lifecycle status (e.g. 'active'). |
retry_policy | "default" | "aggressive" | null | Retry policy configuration |
headers | object | null | Custom HTTP headers added to every delivery. |
last_delivery_at | string | null | ISO 8601 timestamp of the last delivery attemptformat: date-time |
last_delivery_status | "success" | "failed" | null | Status of the last delivery attempt |
failure_count_24h | integer | Number of failed deliveries in the last 24 hours≥ 0 |
auto_disabled_at | string | null | Set when 100 consecutive failures triggered auto-disable.format: date-time |
created_at | string | null | ISO 8601 timestamp when this resource was createdformat: date-time |
updated_at | string | null | ISO 8601 timestamp when this resource was last updated. Returned by .get/.update; absent on .register/.list.format: date-time |
Example
一次性前置(每个范例都假定已完成):
# 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 详情。
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
webhook_id | string | Required | Webhook ID。 |
Returns
Webhook { id, url, events, active, retry_policy }| Name | Type | Description |
|---|---|---|
webhook_id | string | Webhook subscription id (whk_… in the account_resource store).pattern: ^whk?_[A-Za-z0-9]{16,}$ |
url | string | URL for this resource or endpointformat: uri |
events | string[] | Event names per enums/webhook_event.yaml. |
description | string | null | Free-text description of this resource |
secret | string | null | Plaintext secret — returned only on initial create. |
secret_hash | string | null | SHA-256 hex of secret; returned on list/get. |
active | boolean | Whether deliveries are sent. Canonical state field. |
enabled | boolean | null | Back-compat alias of `active` (console reads this). |
status | string | null | account_resource lifecycle status (e.g. 'active'). |
retry_policy | "default" | "aggressive" | null | Retry policy configuration |
headers | object | null | Custom HTTP headers added to every delivery. |
last_delivery_at | string | null | ISO 8601 timestamp of the last delivery attemptformat: date-time |
last_delivery_status | "success" | "failed" | null | Status of the last delivery attempt |
failure_count_24h | integer | Number of failed deliveries in the last 24 hours≥ 0 |
auto_disabled_at | string | null | Set when 100 consecutive failures triggered auto-disable.format: date-time |
created_at | string | null | ISO 8601 timestamp when this resource was createdformat: date-time |
updated_at | string | null | ISO 8601 timestamp when this resource was last updated. Returned by .get/.update; absent on .register/.list.format: date-time |
Example
一次性前置(每个范例都假定已完成):
# 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 校验。
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
webhook_id | string | Required | Webhook ID。 |
url | string | Optional | 新的公网 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 | Optional | 新的订阅事件类型列表。≥ 1 item |
description | string | Optional | 备注说明。≤ 256 chars |
active | boolean | Optional | 是否启用该 Webhook。 |
retry_policy | "default" | "aggressive" | null | Optional | 重试策略:default 或 aggressive。 |
headers | Record<string, string> | Optional | 每次投递附加的自定义 HTTP 头。 |
idempotency_key | string | Optional | Optional dedup key; identical retries return the same result. |
Returns
Webhook { id, url, events, active, retry_policy }| Name | Type | Description |
|---|---|---|
webhook_id | string | Webhook subscription id (whk_… in the account_resource store).pattern: ^whk?_[A-Za-z0-9]{16,}$ |
url | string | URL for this resource or endpointformat: uri |
events | string[] | Event names per enums/webhook_event.yaml. |
description | string | null | Free-text description of this resource |
secret | string | null | Plaintext secret — returned only on initial create. |
secret_hash | string | null | SHA-256 hex of secret; returned on list/get. |
active | boolean | Whether deliveries are sent. Canonical state field. |
enabled | boolean | null | Back-compat alias of `active` (console reads this). |
status | string | null | account_resource lifecycle status (e.g. 'active'). |
retry_policy | "default" | "aggressive" | null | Retry policy configuration |
headers | object | null | Custom HTTP headers added to every delivery. |
last_delivery_at | string | null | ISO 8601 timestamp of the last delivery attemptformat: date-time |
last_delivery_status | "success" | "failed" | null | Status of the last delivery attempt |
failure_count_24h | integer | Number of failed deliveries in the last 24 hours≥ 0 |
auto_disabled_at | string | null | Set when 100 consecutive failures triggered auto-disable.format: date-time |
created_at | string | null | ISO 8601 timestamp when this resource was createdformat: date-time |
updated_at | string | null | ISO 8601 timestamp when this resource was last updated. Returned by .get/.update; absent on .register/.list.format: date-time |
Example
一次性前置(每个范例都假定已完成):
# 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。
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
webhook_id | string | Required | Webhook ID。 |
idempotency_key | string | Optional | Optional dedup key; identical retries return the same result. |
Returns
{ deleted: boolean }| Name | Type | Description |
|---|---|---|
webhook_id | string | The webhook id that was targeted for deletion. |
deleted | boolean | Whether a webhook was actually deleted (false when webhook_id didn't resolve to a row on this account). |
Example
一次性前置(每个范例都假定已完成):
# 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 发送一条测试事件以验证连通性。
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
webhook_id | string | Required | Webhook ID。 |
Returns
WebhookDelivery { delivery_id, status_code, ok }| Name | Type | Description |
|---|---|---|
webhook_id | string | Unique identifier for this webhookpattern: ^wh_[A-Za-z0-9]{20,}$ |
event | string | Event name fired in the test (e.g. 'topup.succeeded'). |
delivered | boolean | Whether the webhook delivery succeeded |
http_status | integer | null | HTTP status code of the webhook delivery attempt100–599 |
latency_ms | integer | null | Latency of the operation in milliseconds≥ 0 |
error | string | null | Error message if the operation failed |
delivery_id | string | null | Unique identifier for this delivery attemptpattern: ^dlv_[A-Za-z0-9]{20,}$ |
tested_at | string | ISO 8601 timestamp when the test was executedformat: date-time |
Example
一次性前置(每个范例都假定已完成):
# 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 的投递记录。
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
webhook_id | string | Required | Webhook ID。 |
cursor | string | Optional | 分页游标:传入上一页返回的 next_cursor 获取下一页。 |
limit | number | Optional | 单页返回条数上限。 |
Returns
{ items: Array<WebhookDelivery>, next_cursor? }| Name | Type | Description |
|---|---|---|
items | object[] | Array of result items in this page |
items[].delivery_id | string | Unique identifier for this delivery attemptpattern: ^dlv_[A-Za-z0-9]{20,}$ |
items[].webhook_id | string | Unique identifier for this webhookpattern: ^wh_[A-Za-z0-9]{20,}$ |
items[].event | string | Event name per enums/webhook_event.yaml. |
items[].status | "pending" | "success" | "retry" | "failed" | "dlq" | Current status of this resource |
items[].attempt | integer | Current attempt number (for retries)≥ 1 |
items[].http_status | integer | null | HTTP status code of the webhook delivery attempt100–599 |
items[].latency_ms | integer | null | Latency of the operation in milliseconds≥ 0 |
items[].response_body_truncated | string | null | Truncated response body from the webhook delivery attempt≤ 4096 chars |
items[].error | string | null | Error message if the operation failed |
items[].created_at | string | ISO 8601 timestamp when this resource was createdformat: date-time |
items[].completed_at | string | null | ISO 8601 timestamp when execution completedformat: date-time |
next_cursor | string | null | Opaque cursor to fetch the next page; null/absent if this is the last page |
count | integer | Total number of items across all pages≥ 0 |
Example
一次性前置(每个范例都假定已完成):
# 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
获取账户级路由配置(链路覆盖、故障转移策略、固定厂商)。
Returns
RoutingConfig { chain_override?, failover_policy, pinned_vendors }| Name | Type | Description |
|---|---|---|
preferences | object | account.routing.get only. Per-capability vendor exclude list the account has configured, keyed by capability id. |
effective_chains | object | account.routing.get only. Per-capability failover chain after applying the account's exclude and filtering to currently-usable vendors, keyed by capability id. Each entry is model-first: the vendor plus the model it serves. |
no_china_route | boolean | account.routing.get (current value) / account.routing.set (echoed new value, only when the no_china_route toggle was set). Data-sovereignty flag: when true the gateway routes only to non-China vendors. |
capability | string | account.routing.set only (per-capability exclude sub-action). The capability the exclude list was set for. |
exclude | string[] | account.routing.set only (per-capability exclude sub-action). Echo of the vendor ids excluded from that capability's chain. |
ok | boolean | account.routing.set only. Always true — confirms the write was applied. |
Example
一次性前置(每个范例都假定已完成):
# 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
设置账户级路由:覆盖默认厂商链路、固定指定厂商。
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
chain_override | string[] | Optional | 厂商优先级链路覆盖列表。 |
pinned_vendors | string[] | Optional | 固定使用的厂商列表。 |
Returns
RoutingConfig { chain_override?, failover_policy, pinned_vendors }| Name | Type | Description |
|---|---|---|
preferences | object | account.routing.get only. Per-capability vendor exclude list the account has configured, keyed by capability id. |
effective_chains | object | account.routing.get only. Per-capability failover chain after applying the account's exclude and filtering to currently-usable vendors, keyed by capability id. Each entry is model-first: the vendor plus the model it serves. |
no_china_route | boolean | account.routing.get (current value) / account.routing.set (echoed new value, only when the no_china_route toggle was set). Data-sovereignty flag: when true the gateway routes only to non-China vendors. |
capability | string | account.routing.set only (per-capability exclude sub-action). The capability the exclude list was set for. |
exclude | string[] | account.routing.set only (per-capability exclude sub-action). Echo of the vendor ids excluded from that capability's chain. |
ok | boolean | account.routing.set only. Always true — confirms the write was applied. |
Example
一次性前置(每个范例都假定已完成):
# 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
测试路由解析:给定能力返回将选用的厂商链路。
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
capability | string | Required | 要测试的能力 ID(如 ai.chat)。default: "ai.chat"e.g. ai.chat |
chain_override | string[] | Optional | 用于本次测试的临时链路覆盖。 |
Returns
RoutingTestResult { ok, resolved_vendor, resolved_model?, tested_at? }| Name | Type | Description |
|---|---|---|
capability | string | The capability that was tested (defaults to ai.chat if not given). |
customizable | boolean | Whether this capability accepts a per-account vendor exclude (AI-inference/stateless only). |
chain | string[] | The effective vendor id chain after applying the account's exclude and filtering to currently-usable vendors. |
results | object[] | Per-vendor reachability, one entry per vendor in `chain`. |
results[].vendor | string | - |
results[].model | string | null | The model this vendor would serve for the capability, best-effort. |
results[].up | boolean | Whether the vendor is currently marked up in the live registry. |
ok | boolean | Whether the test routing resolved successfully |
Example
一次性前置(每个范例都假定已完成):
# 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. All capabilities
Every routed capability in this module — the complete public REST contract. The methods above are the guided walkthrough; this index is the full reference.
account.autorecharge.configurePUT /v1/account/autorecharge/configureConfigure automatic balance top-up when funds fall below a trigger threshold, with anti-abuse caps.
Parameters (6)
| Name | Type | Required | Description |
|---|---|---|---|
trigger_balance | number | Required | Auto-charge fires when wallet balance drops below this.≥ 0 |
recharge_amount | number | Required | Amount in USD to add each time auto-charge fires.> 0 |
payment_method_id | string | null | Optional | null uses the account default payment method. |
max_per_day | integer | Optional | Maximum recharge amount per day in USD≥ 1default: 3 |
max_per_month | integer | Optional | Maximum recharge amount per month in USD≥ 1default: 30 |
idempotency_key | string | null | Optional | Client-provided idempotency key; prevents duplicate execution on retry |
account.autorecharge.getGET /v1/account/autorecharge/getGet the current auto-recharge configuration.
No request parameters.
account.balanceGET /v1/account/balanceGet the account wallet balance and trial status.
No request parameters.
account.budget.getGET /v1/account/budget/getGet the budget configuration (period, hard cap, alert thresholds).
No request parameters.
account.budget.setPUT /v1/account/budget/setSet a hard budget cap and alert thresholds, blocking billable calls when exceeded.
Parameters (4)
| Name | Type | Required | Description |
|---|---|---|---|
hard_cap_usd | number | null | Optional | Monthly spending hard cap in USD≥ 0 |
period | "daily" | "monthly" | Required | Billing or retention period (e.g. monthly, daily) |
alert_threshold_usd | number | null | Optional | Monthly spending alert threshold in USD≥ 0 |
idempotency_key | string | null | Optional | 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.
Parameters (4)
| Name | Type | Required | Description |
|---|---|---|---|
project_id | string | null | Optional | null = caller's current project. |
name | string | null | Optional | Human-readable name for this resource≤ 128 chars |
scopes | string[] | null | Optional | Empty/null = all-modules; explicit scopes per enums/key_scope.yaml. |
idempotency_key | string | null | Optional | 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.
No request parameters.
account.keys.revokeDELETE /v1/account/keys/revoke/{id}Revoke an API key, taking effect immediately.
Parameters (1)
| Name | Type | Required | Description |
|---|---|---|---|
id | string | Required | Path parameter. |
account.keys.rotatePOST /v1/account/keys/rotate/{id}Rotate an API key; the old secret stays valid during a grace period.
Parameters (3)
| Name | Type | Required | Description |
|---|---|---|---|
id | string | Required | Path parameter. |
grace_hours | integer | Optional | Hours the old key remains valid after rotation0–168default: 24 |
idempotency_key | string | null | Optional | 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.
Parameters (4)
| Name | Type | Required | Description |
|---|---|---|---|
id | string | Required | Path parameter. |
confirmed_leak | boolean | Optional | Whether the key leak has been confirmeddefault: false |
auto_rotate | boolean | Optional | Whether to automatically rotate the compromised keydefault: true |
idempotency_key | string | null | Optional | 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.
Parameters (4)
| Name | Type | Required | Description |
|---|---|---|---|
id | string | Required | Path parameter. |
name | string | null | Optional | Human-readable name for this resource≤ 128 chars |
scopes | string[] | null | Optional | Permission scopes granted to this API key |
idempotency_key | string | null | Optional | 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.
Parameters (2)
| Name | Type | Required | Description |
|---|---|---|---|
payment_method_id | string | Required | Identifier of the payment method used |
idempotency_key | string | null | Optional | 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.
No request parameters.
account.routing.setPUT /v1/account/routing/setExclude vendors from an AI capability's routing (cost / reliability / data sovereignty).
Parameters (3)
| Name | Type | Required | Description |
|---|---|---|---|
capability | string | Required | AI-inference capability id (ai.*) whose vendor exclude is being set.e.g. ai.chat |
exclude | string[] | Optional | Vendors to never route this capability to (cost / reliability / data sovereignty).default: []e.g. ["openai"] |
idempotency_key | string | null | Optional | 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.
Parameters (1)
| Name | Type | Required | Description |
|---|---|---|---|
capability | string | null | Optional | 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.
No request parameters.
account.tierGET /v1/account/tierGet the current tier and its quota limits.
No request parameters.
account.tier.upgradePOST /v1/account/tier/upgradeUpgrade the account tier (pro/team/enterprise), returning a checkout URL when payment is required.
Parameters (3)
| Name | Type | Required | Description |
|---|---|---|---|
target | "pro" | "team" | "enterprise" | Required | Target URL or resource for webhook or notification |
return_url | string | null | Optional | Where checkout redirects after success/cancel; echoed into the hosted checkout session.format: uri |
idempotency_key | string | null | Optional | 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.
Parameters (5)
| Name | Type | Required | Description |
|---|---|---|---|
amount_usd | number | null | Optional | Top-up amount in USD.≥ 0 |
amount | number | null | Optional | Legacy alias for amount_usd.≥ 0 |
currency | string | Optional | ISO 4217 currency code (e.g. USD, CNY)default: "USD" |
return_url | string | null | Optional | URL the checkout redirects back to; defaults to the configured return URL.format: uri |
idempotency_key | string | null | Optional | 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.
No request parameters.
account.usage.timeseriesGET /v1/account/usage/timeseriesReturn a usage time series at hour, day, or month granularity.
No request parameters.
account.webhooks.deleteDELETE /v1/account/webhooks/delete/{id}Delete a webhook registration; no further event deliveries are sent to its URL. Idempotent.
Parameters (1)
| Name | Type | Required | Description |
|---|---|---|---|
id | string | Required | Path parameter. |
account.webhooks.deliveriesGET /v1/account/webhooks/deliveries/{id}List a webhook's delivery records with pagination.
Parameters (1)
| Name | Type | Required | Description |
|---|---|---|---|
id | string | Required | Path parameter. |
account.webhooks.getGET /v1/account/webhooks/get/{id}Get details for a single webhook.
Parameters (1)
| Name | Type | Required | Description |
|---|---|---|---|
id | string | Required | Path parameter. |
account.webhooks.listGET /v1/account/webhooks/listList registered webhooks with pagination.
No request parameters.
account.webhooks.registerPOST /v1/account/webhooks/registerRegister a webhook (public HTTPS, SSRF-validated); the signing secret is returned only once.
Parameters (7)
| Name | Type | Required | Description |
|---|---|---|---|
url | string | Required | 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")[] | Required | Event types to subscribe this webhook to; the closed set is the global event catalog.≥ 1 item |
description | string | null | Optional | Free-text description of this resource≤ 256 chars |
secret | string | null | Optional | Optional caller-provided signing secret; auto-generated when null. |
retry_policy | "default" | "aggressive" | null | Optional | Retry policy configuration |
headers | object | null | Optional | Custom HTTP headers added to every delivery. |
idempotency_key | string | null | Optional | 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.
Parameters (1)
| Name | Type | Required | Description |
|---|---|---|---|
id | string | Required | Path parameter. |
account.webhooks.updatePATCH /v1/account/webhooks/update/{id}Partially update a webhook; changing the URL re-runs SSRF validation.
Parameters (8)
| Name | Type | Required | Description |
|---|---|---|---|
id | string | Required | Path parameter. |
url | string | null | Optional | 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 | Optional | List of event types this subscription listens to≥ 1 item |
description | string | null | Optional | Free-text description of this resource≤ 256 chars |
active | boolean | null | Optional | Whether this resource is currently active |
retry_policy | "default" | "aggressive" | null | Optional | Retry policy configuration |
headers | object | null | Optional | Custom HTTP headers to include in requests or responses |
idempotency_key | string | null | Optional | Client-provided idempotency key; prevents duplicate execution on retry |
account.whoamiGET /v1/account/whoamiGet an account summary (ID, type, status, tier, balance).
No request parameters.
4. End-to-end example
A production-style walkthrough of this module: configure once, then run the flow. It exercises most of the module's APIs.
A copy-paste-runnable single-file Python program (stdlib only, no SDK): set your INFRAI_API_KEY, run it, and walk this module's core flow with REAL billed calls — later steps reuse real fields returned by earlier ones. The 12-line helper is the entire integration.
#!/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);