存储
S3 兼容的存储桶与对象,支持预签名 URL。
1. 概览
https://api.infrai.cc/v1/storageAuthorization: Bearer $INFRAI_API_KEY# Call any /v1/storage capability over raw HTTP — no SDK to install.
# curl:
curl https://api.infrai.cc/v1/storage/... \
-H "Authorization: Bearer $INFRAI_API_KEY" \
-H "Content-Type: application/json"2. 方法 (22)
2.1storage.bucket.create
创建对象存储桶。名称需为 3-63 位小写字母、数字、点号或中划线,且以字母或数字开头和结尾;region 使用 cn-beijing、ap-singapore 这类规范区域代码。
参数
| 名称 | 类型 | 必填 | 说明 |
|---|---|---|---|
name | string | 必填 | 存储桶名称。长度 3-63,只能包含小写字母、数字、点号和中划线,且必须以字母或数字开头和结尾。新接入建议使用 name;bucket 也会作为别名接受。 |
bucket | string | 可选 | name 的别名。新接入建议优先使用 name。 |
vendor | string | 可选 | 固定使用某个供应商,而非自动路由。 |
region | "us-east-1" | "us-west-2" | "eu-west-1" | "eu-central-1" | "ap-southeast-1" | "ap-northeast-1" | "cn-hangzhou" | "cn-beijing" | "auto" | "ap-singapore" | "ap-hongkong" | "ap-tokyo" | "ap-bangkok" | "na-siliconvalley" | null | 可选 | 存储区域代码,例如北京传 cn-beijing,新加坡传 ap-singapore。不要传 北京 这类中文城市名;不支持的区域会返回 INVALID_REGION。 |
acl | "private" | "signed-only" | 可选 | 存储桶访问控制。默认 private;当前仅支持 private、signed-only,不支持 public 或 public-read。default: "private" |
返回
Bucket { bucket, vendor, region, created_at, acl? }| 名称 | 类型 | 说明 |
|---|---|---|
bucket_id | string | storage bucket的唯一标识符pattern: ^bkt_[A-Za-z0-9]{20,}$ |
name | string | 资源的可读名称 |
vendor | "r2" | "s3" | "oss" | "cos" | 处理此请求的供应商 |
region | string | null | 资源所在或处理的地理区域 |
acl | "private" | "signed-only" | 桶或对象的访问控制列表 |
created_at | string | 资源创建时间(ISO 8601)format: date-time |
cors_rules | object[] | 存储桶的 CORS 配置规则 |
lifecycle_rules | object[] | 存储桶的生命周期管理规则 |
lifecycle_rules[].prefix | string | 匹配 key 以此开头的对象。e.g. tmp/ |
lifecycle_rules[].expire_days | integer | null | N 天后自动删除。≥ 1e.g. 1 |
lifecycle_rules[].transition_class | string | null | 转移到更冷的存储类型(如 "glacier")。 |
示例
一次性前置(每个范例都假定已完成):
# 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/storage/bucket/create \
-H "Authorization: Bearer $INFRAI_API_KEY" \
-H "Content-Type: application/json" \
-d '{"name": "example"}'# 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/storage/bucket/create",
headers={
"Authorization": f"Bearer {os.environ['INFRAI_API_KEY']}",
},
json={'name': 'example'},
)
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/storage/bucket/create",
{
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({"name": "example"}),
},
);
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/storage/bucket/create",
{
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({"name": "example"}),
},
);
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(`{"name": "example"}`)
req, _ := http.NewRequest("POST", "https://api.infrai.cc/v1/storage/bucket/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/storage/bucket/create"))
.header("Authorization", "Bearer " + System.getenv("INFRAI_API_KEY"))
.header("Content-Type", "application/json")
.method("POST", HttpRequest.BodyPublishers.ofString("{\"name\": \"example\"}"))
.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/storage/bucket/create");
var key = Environment.GetEnvironmentVariable("INFRAI_API_KEY");
req.Headers.Add("Authorization", "Bearer " + key);
req.Content = new StringContent("{\"name\": \"example\"}", 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/storage/bucket/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, "{\"name\": \"example\"}");
$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/storage/bucket/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 = '{"name": "example"}'
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/storage/bucket/create")
.header("Authorization", format!("Bearer {}", env::var("INFRAI_API_KEY")?))
.header("Content-Type", "application/json")
.body(r#"{"name": "example"}"#)
.send()
.await?;
println!("{}", resp.text().await?);
Ok(())
}2.2storage.bucket.list
列出你的存储桶。
返回
{ items: Bucket[] }| 名称 | 类型 | 说明 |
|---|---|---|
items | object[] | 本页结果条目数组 |
items[].bucket_id | string | storage bucket的唯一标识符pattern: ^bkt_[A-Za-z0-9]{20,}$ |
items[].name | string | 此资源的可读名称 |
items[].vendor | "r2" | "s3" | "oss" | "cos" | 处理此请求的供应商 |
items[].region | string | null | 资源所在或处理的地理区域 |
items[].acl | "private" | "signed-only" | 桶或对象的访问控制列表 |
items[].created_at | string | 此资源创建的 ISO 8601 时间戳format: date-time |
items[].cors_rules | object[] | 存储桶的 CORS 配置规则 |
items[].lifecycle_rules | object[] | 存储桶的生命周期管理规则 |
items[].lifecycle_rules[].prefix | string | 匹配 key 以此开头的对象。e.g. tmp/ |
items[].lifecycle_rules[].expire_days | integer | null | N 天后自动删除。≥ 1e.g. 1 |
items[].lifecycle_rules[].transition_class | string | null | 转移到更冷的存储类型(如 "glacier")。 |
next_cursor | string | null | 获取下一页的不透明游标;null 或不存在表示最后一页 |
示例
一次性前置(每个范例都假定已完成):
# No SDK to install — every call is a plain HTTPS request.
# Get a project key by signing in at https://infrai.cc/login (Google/GitHub gives
# you $2 free credit; email sign-in starts at $0). On 402 INSUFFICIENT_CREDIT, add
# funds at https://infrai.cc/billing (or POST /v1/account/topup and open the
# returned checkout_url).
export INFRAI_API_KEY="ifr_..."curl -X GET https://api.infrai.cc/v1/storage/bucket/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/storage/bucket/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/storage/bucket/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/storage/bucket/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/storage/bucket/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/storage/bucket/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/storage/bucket/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/storage/bucket/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/storage/bucket/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/storage/bucket/list")
.header("Authorization", format!("Bearer {}", env::var("INFRAI_API_KEY")?))
.send()
.await?;
println!("{}", resp.text().await?);
Ok(())
}2.3storage.object.presign
为上传或下载对象创建预签名 URL;op=put 时,按返回的 method 将文件二进制内容上传到返回的 URL。
参数
| 名称 | 类型 | 必填 | 说明 |
|---|---|---|---|
bucket | string | 必填 | 存储桶名称。 |
key | string | 必填 | 桶内的对象 key(路径)。 |
op | "get" | "put" | 必填 | 预签名 URL 的用途:get 生成下载 URL;put 生成上传 URL。op=put 时,按响应中的 method 将文件二进制内容发送到返回的 url。e.g. put |
expires_seconds | number | 可选 | 预签名 URL 有效时长(秒)。≥ 1 |
返回
PresignedUrl { url, method, expires_at, headers? }| 名称 | 类型 | 说明 |
|---|---|---|
url | string | 资源或端点 URL |
method | "PUT" | "POST" | 所用的认证方式(如 email_otp、oauth、password) |
headers | object | null | 请求或响应中包含的自定义 HTTP 头 |
fields | object | null | 用于 POST 表单上传。 |
expires_at | string | 资源或令牌过期时间(ISO 8601)format: date-time |
max_bytes | integer | null | 允许的最大文件大小(字节)≥ 0 |
示例
一次性前置(每个范例都假定已完成):
# No SDK to install — every call is a plain HTTPS request.
# Get a project key by signing in at https://infrai.cc/login (Google/GitHub gives
# you $2 free credit; email sign-in starts at $0). On 402 INSUFFICIENT_CREDIT, add
# funds at https://infrai.cc/billing (or POST /v1/account/topup and open the
# returned checkout_url).
export INFRAI_API_KEY="ifr_..."curl -X POST https://api.infrai.cc/v1/storage/object/presign/BUCKET/KEY \
-H "Authorization: Bearer $INFRAI_API_KEY" \
-H "Content-Type: application/json" \
-d '{"op": "put"}'# 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/storage/object/presign/BUCKET/KEY",
headers={
"Authorization": f"Bearer {os.environ['INFRAI_API_KEY']}",
},
json={'op': 'put'},
)
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/storage/object/presign/BUCKET/KEY",
{
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({"op": "put"}),
},
);
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/storage/object/presign/BUCKET/KEY",
{
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({"op": "put"}),
},
);
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(`{"op": "put"}`)
req, _ := http.NewRequest("POST", "https://api.infrai.cc/v1/storage/object/presign/BUCKET/KEY", 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/storage/object/presign/BUCKET/KEY"))
.header("Authorization", "Bearer " + System.getenv("INFRAI_API_KEY"))
.header("Content-Type", "application/json")
.method("POST", HttpRequest.BodyPublishers.ofString("{\"op\": \"put\"}"))
.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/storage/object/presign/BUCKET/KEY");
var key = Environment.GetEnvironmentVariable("INFRAI_API_KEY");
req.Headers.Add("Authorization", "Bearer " + key);
req.Content = new StringContent("{\"op\": \"put\"}", 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/storage/object/presign/BUCKET/KEY");
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, "{\"op\": \"put\"}");
$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/storage/object/presign/BUCKET/KEY")
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 = '{"op": "put"}'
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/storage/object/presign/BUCKET/KEY")
.header("Authorization", format!("Bearer {}", env::var("INFRAI_API_KEY")?))
.header("Content-Type", "application/json")
.body(r#"{"op": "put"}"#)
.send()
.await?;
println!("{}", resp.text().await?);
Ok(())
}2.4storage.object.delete
删除存储桶中的单个对象。删除后 head/get 会返回未找到。
参数
| 名称 | 类型 | 必填 | 说明 |
|---|---|---|---|
bucket | string | 必填 | 存储桶名称。 |
key | string | 必填 | 桶内的对象 key(路径)。 |
返回
{ ok: boolean }| 名称 | 类型 | 说明 |
|---|---|---|
bucket | string | 对象被删除的来源存储桶 |
key | string | 已删除对象的键 |
deleted | boolean | 对象是否存在并已删除 |
示例
一次性前置(每个范例都假定已完成):
# No SDK to install — every call is a plain HTTPS request.
# Get a project key by signing in at https://infrai.cc/login (Google/GitHub gives
# you $2 free credit; email sign-in starts at $0). On 402 INSUFFICIENT_CREDIT, add
# funds at https://infrai.cc/billing (or POST /v1/account/topup and open the
# returned checkout_url).
export INFRAI_API_KEY="ifr_..."curl -X DELETE https://api.infrai.cc/v1/storage/object/delete/BUCKET/KEY \
-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/storage/object/delete/BUCKET/KEY",
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/storage/object/delete/BUCKET/KEY",
{
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/storage/object/delete/BUCKET/KEY",
{
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/storage/object/delete/BUCKET/KEY", 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/storage/object/delete/BUCKET/KEY"))
.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/storage/object/delete/BUCKET/KEY");
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/storage/object/delete/BUCKET/KEY");
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/storage/object/delete/BUCKET/KEY")
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/storage/object/delete/BUCKET/KEY")
.header("Authorization", format!("Bearer {}", env::var("INFRAI_API_KEY")?))
.send()
.await?;
println!("{}", resp.text().await?);
Ok(())
}2.5storage.bucket.get
获取存储桶元信息
参数
| 名称 | 类型 | 必填 | 说明 |
|---|---|---|---|
bucket | string | 必填 | 存储桶名称 |
返回
Bucket { bucket_id, name, vendor, region, acl, created_at, cors_rules, lifecycle_rules }| 名称 | 类型 | 说明 |
|---|---|---|
bucket_id | string | storage bucket的唯一标识符pattern: ^bkt_[A-Za-z0-9]{20,}$ |
name | string | 资源的可读名称 |
vendor | "r2" | "s3" | "oss" | "cos" | 处理此请求的供应商 |
region | string | null | 资源所在或处理的地理区域 |
acl | "private" | "signed-only" | 桶或对象的访问控制列表 |
created_at | string | 资源创建时间(ISO 8601)format: date-time |
cors_rules | object[] | 存储桶的 CORS 配置规则 |
lifecycle_rules | object[] | 存储桶的生命周期管理规则 |
lifecycle_rules[].prefix | string | 匹配 key 以此开头的对象。e.g. tmp/ |
lifecycle_rules[].expire_days | integer | null | N 天后自动删除。≥ 1e.g. 1 |
lifecycle_rules[].transition_class | string | null | 转移到更冷的存储类型(如 "glacier")。 |
示例
一次性前置(每个范例都假定已完成):
# 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/storage/bucket/get/BUCKET \
-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/storage/bucket/get/BUCKET",
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/storage/bucket/get/BUCKET",
{
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/storage/bucket/get/BUCKET",
{
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/storage/bucket/get/BUCKET", 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/storage/bucket/get/BUCKET"))
.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/storage/bucket/get/BUCKET");
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/storage/bucket/get/BUCKET");
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/storage/bucket/get/BUCKET")
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/storage/bucket/get/BUCKET")
.header("Authorization", format!("Bearer {}", env::var("INFRAI_API_KEY")?))
.send()
.await?;
println!("{}", resp.text().await?);
Ok(())
}2.6storage.bucket.delete
删除存储桶。空桶可直接删除;非空桶需要传 force=true,否则返回 STORAGE_DELETE_NOT_FORCED。
参数
| 名称 | 类型 | 必填 | 说明 |
|---|---|---|---|
bucket | string | 必填 | 存储桶名称 |
force | boolean | 可选 | 是否强制删除非空存储桶。默认 false:桶内仍有对象时返回 STORAGE_DELETE_NOT_FORCED;传 true 会连同桶内对象一起删除。 |
idempotency_key | string | 可选 | 幂等键;省略时自动派生 |
返回
BucketDeleteResult { deleted }| 名称 | 类型 | 说明 |
|---|---|---|
deleted | boolean | 资源是否已成功删除 |
示例
一次性前置(每个范例都假定已完成):
# No SDK to install — every call is a plain HTTPS request.
# Get a project key by signing in at https://infrai.cc/login (Google/GitHub gives
# you $2 free credit; email sign-in starts at $0). On 402 INSUFFICIENT_CREDIT, add
# funds at https://infrai.cc/billing (or POST /v1/account/topup and open the
# returned checkout_url).
export INFRAI_API_KEY="ifr_..."curl -X DELETE https://api.infrai.cc/v1/storage/bucket/delete/BUCKET \
-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/storage/bucket/delete/BUCKET",
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/storage/bucket/delete/BUCKET",
{
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/storage/bucket/delete/BUCKET",
{
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/storage/bucket/delete/BUCKET", 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/storage/bucket/delete/BUCKET"))
.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/storage/bucket/delete/BUCKET");
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/storage/bucket/delete/BUCKET");
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/storage/bucket/delete/BUCKET")
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/storage/bucket/delete/BUCKET")
.header("Authorization", format!("Bearer {}", env::var("INFRAI_API_KEY")?))
.send()
.await?;
println!("{}", resp.text().await?);
Ok(())
}2.7storage.bucket.usage
查询存储桶用量
参数
| 名称 | 类型 | 必填 | 说明 |
|---|---|---|---|
bucket | string | 必填 | 存储桶名称 |
返回
BucketUsageResult { byte_count, object_count, as_of }| 名称 | 类型 | 说明 |
|---|---|---|
byte_count | integer | 存储桶中存储的总字节数≥ 0 |
object_count | integer | objects in the bucket数量≥ 0 |
as_of | string | ISO 8601 时间戳:the usage was measured(ISO 8601)format: date-time |
示例
一次性前置(每个范例都假定已完成):
# No SDK to install — every call is a plain HTTPS request.
# Get a project key by signing in at https://infrai.cc/login (Google/GitHub gives
# you $2 free credit; email sign-in starts at $0). On 402 INSUFFICIENT_CREDIT, add
# funds at https://infrai.cc/billing (or POST /v1/account/topup and open the
# returned checkout_url).
export INFRAI_API_KEY="ifr_..."curl -X GET https://api.infrai.cc/v1/storage/bucket/usage/BUCKET \
-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/storage/bucket/usage/BUCKET",
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/storage/bucket/usage/BUCKET",
{
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/storage/bucket/usage/BUCKET",
{
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/storage/bucket/usage/BUCKET", 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/storage/bucket/usage/BUCKET"))
.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/storage/bucket/usage/BUCKET");
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/storage/bucket/usage/BUCKET");
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/storage/bucket/usage/BUCKET")
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/storage/bucket/usage/BUCKET")
.header("Authorization", format!("Bearer {}", env::var("INFRAI_API_KEY")?))
.send()
.await?;
println!("{}", resp.text().await?);
Ok(())
}2.8storage.bucket.set_lifecycle
设置存储桶生命周期规则
参数
| 名称 | 类型 | 必填 | 说明 |
|---|---|---|---|
bucket | string | 必填 | 存储桶名称 |
rules | Array<{ prefix: string; expire_days?: number; transition_class?: string }> | 必填 | 生命周期规则列表。每条规则可包含 prefix、expire_days、transition_class;expire_days 以天为单位,最少 1 天。提交的 rules 会替换当前规则列表。e.g. [{"prefix":"tmp/","expire_days":1}] |
idempotency_key | string | 可选 | 幂等键;省略时自动派生 |
返回
Bucket { bucket_id, name, vendor, region, acl, created_at, cors_rules, lifecycle_rules }| 名称 | 类型 | 说明 |
|---|---|---|
bucket_id | string | storage bucket的唯一标识符pattern: ^bkt_[A-Za-z0-9]{20,}$ |
name | string | 资源的可读名称 |
vendor | "r2" | "s3" | "oss" | "cos" | 处理此请求的供应商 |
region | string | null | 资源所在或处理的地理区域 |
acl | "private" | "signed-only" | 桶或对象的访问控制列表 |
created_at | string | 资源创建时间(ISO 8601)format: date-time |
cors_rules | object[] | 存储桶的 CORS 配置规则 |
lifecycle_rules | object[] | 存储桶的生命周期管理规则 |
lifecycle_rules[].prefix | string | 匹配 key 以此开头的对象。e.g. tmp/ |
lifecycle_rules[].expire_days | integer | null | N 天后自动删除。≥ 1e.g. 1 |
lifecycle_rules[].transition_class | string | null | 转移到更冷的存储类型(如 "glacier")。 |
示例
一次性前置(每个范例都假定已完成):
# 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/storage/bucket/set_lifecycle/BUCKET \
-H "Authorization: Bearer $INFRAI_API_KEY" \
-H "Content-Type: application/json" \
-d '{"rules": [{"prefix": "tmp/", "expire_days": 1}]}'# 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/storage/bucket/set_lifecycle/BUCKET",
headers={
"Authorization": f"Bearer {os.environ['INFRAI_API_KEY']}",
},
json={'rules': [{'prefix': 'tmp/', 'expire_days': 1}]},
)
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/storage/bucket/set_lifecycle/BUCKET",
{
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({"rules": [{"prefix": "tmp/", "expire_days": 1}]}),
},
);
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/storage/bucket/set_lifecycle/BUCKET",
{
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({"rules": [{"prefix": "tmp/", "expire_days": 1}]}),
},
);
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(`{"rules": [{"prefix": "tmp/", "expire_days": 1}]}`)
req, _ := http.NewRequest("POST", "https://api.infrai.cc/v1/storage/bucket/set_lifecycle/BUCKET", 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/storage/bucket/set_lifecycle/BUCKET"))
.header("Authorization", "Bearer " + System.getenv("INFRAI_API_KEY"))
.header("Content-Type", "application/json")
.method("POST", HttpRequest.BodyPublishers.ofString("{\"rules\": [{\"prefix\": \"tmp/\", \"expire_days\": 1}]}"))
.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/storage/bucket/set_lifecycle/BUCKET");
var key = Environment.GetEnvironmentVariable("INFRAI_API_KEY");
req.Headers.Add("Authorization", "Bearer " + key);
req.Content = new StringContent("{\"rules\": [{\"prefix\": \"tmp/\", \"expire_days\": 1}]}", 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/storage/bucket/set_lifecycle/BUCKET");
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, "{\"rules\": [{\"prefix\": \"tmp/\", \"expire_days\": 1}]}");
$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/storage/bucket/set_lifecycle/BUCKET")
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 = '{"rules": [{"prefix": "tmp/", "expire_days": 1}]}'
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/storage/bucket/set_lifecycle/BUCKET")
.header("Authorization", format!("Bearer {}", env::var("INFRAI_API_KEY")?))
.header("Content-Type", "application/json")
.body(r#"{"rules": [{"prefix": "tmp/", "expire_days": 1}]}"#)
.send()
.await?;
println!("{}", resp.text().await?);
Ok(())
}2.9storage.bucket.set_notification
订阅存储桶对象事件到回调 URL
参数
| 名称 | 类型 | 必填 | 说明 |
|---|---|---|---|
bucket | string | 必填 | 存储桶名称 |
events | ("object.created" | "object.deleted" | "multipart.completed")[] | 必填 | 要订阅的事件类型列表,当前支持 object.created、object.deleted、multipart.completed。≥ 1 iteme.g. ["object.created","object.deleted","multipart.completed"] |
target | { url: string } | 必填 | 回调目标。传 {"url":"https://..."};事件触发时会收到 JSON POST,Header 含 X-Infrai-Event,Body 含 event/type、account_id、bucket、key、timestamp、subscription_id。e.g. {"url":"https://example.com/storage-events"} |
idempotency_key | string | 可选 | 幂等键;省略时自动派生 |
返回
BucketSetNotificationResult { subscription_id }| 名称 | 类型 | 说明 |
|---|---|---|
subscription_id | string | subscription的唯一标识符 |
示例
一次性前置(每个范例都假定已完成):
# 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/storage/bucket/set_notification/BUCKET \
-H "Authorization: Bearer $INFRAI_API_KEY" \
-H "Content-Type: application/json" \
-d '{"events": ["object.created", "object.deleted", "multipart.completed"], "target": {"url": "https://example.com/storage-events"}}'# 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/storage/bucket/set_notification/BUCKET",
headers={
"Authorization": f"Bearer {os.environ['INFRAI_API_KEY']}",
},
json={'events': ['object.created', 'object.deleted', 'multipart.completed'], 'target': {'url': 'https://example.com/storage-events'}},
)
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/storage/bucket/set_notification/BUCKET",
{
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({"events": ["object.created", "object.deleted", "multipart.completed"], "target": {"url": "https://example.com/storage-events"}}),
},
);
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/storage/bucket/set_notification/BUCKET",
{
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({"events": ["object.created", "object.deleted", "multipart.completed"], "target": {"url": "https://example.com/storage-events"}}),
},
);
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(`{"events": ["object.created", "object.deleted", "multipart.completed"], "target": {"url": "https://example.com/storage-events"}}`)
req, _ := http.NewRequest("POST", "https://api.infrai.cc/v1/storage/bucket/set_notification/BUCKET", 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/storage/bucket/set_notification/BUCKET"))
.header("Authorization", "Bearer " + System.getenv("INFRAI_API_KEY"))
.header("Content-Type", "application/json")
.method("POST", HttpRequest.BodyPublishers.ofString("{\"events\": [\"object.created\", \"object.deleted\", \"multipart.completed\"], \"target\": {\"url\": \"https://example.com/storage-events\"}}"))
.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/storage/bucket/set_notification/BUCKET");
var key = Environment.GetEnvironmentVariable("INFRAI_API_KEY");
req.Headers.Add("Authorization", "Bearer " + key);
req.Content = new StringContent("{\"events\": [\"object.created\", \"object.deleted\", \"multipart.completed\"], \"target\": {\"url\": \"https://example.com/storage-events\"}}", 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/storage/bucket/set_notification/BUCKET");
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, "{\"events\": [\"object.created\", \"object.deleted\", \"multipart.completed\"], \"target\": {\"url\": \"https://example.com/storage-events\"}}");
$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/storage/bucket/set_notification/BUCKET")
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 = '{"events": ["object.created", "object.deleted", "multipart.completed"], "target": {"url": "https://example.com/storage-events"}}'
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/storage/bucket/set_notification/BUCKET")
.header("Authorization", format!("Bearer {}", env::var("INFRAI_API_KEY")?))
.header("Content-Type", "application/json")
.body(r#"{"events": ["object.created", "object.deleted", "multipart.completed"], "target": {"url": "https://example.com/storage-events"}}"#)
.send()
.await?;
println!("{}", resp.text().await?);
Ok(())
}2.10storage.object.put
服务端直接写入对象;请求体需用 JSON 的 data_base64 传 base64 编码内容。base64 上传适合小文件,不推荐超过 1MB;较大文件建议使用预签名直传或分片直传。
参数
| 名称 | 类型 | 必填 | 说明 |
|---|---|---|---|
bucket | string | 必填 | 存储桶名称 |
key | string | 必填 | 对象键(路径) |
data_base64 | string | 必填 | 对象字节内容的 base64 字符串,放在 JSON 请求体里;也接受 data: URL。base64 上传适合小文件,不推荐超过 1MB。 |
data | string | null | 可选 | data_base64 的别名。 |
file_base64 | string | null | 可选 | data_base64 的别名。 |
content_type | string | 可选 | 对象的 MIME 类型 |
metadata | Record<string, string> | 可选 | 任意用户自定义元数据键值对 |
cache_control | string | 可选 | Cache-Control 头 |
storage_class | string | 可选 | 存储类别(默认 standard)default: "standard" |
idempotency_key | string | 可选 | 幂等键;省略时按内容哈希自动派生 |
返回
StorageObject { bucket_id, key, size_bytes, etag, content_type, metadata, created_at, last_modified }| 名称 | 类型 | 说明 |
|---|---|---|
bucket_id | string | storage bucket的唯一标识符pattern: ^bkt_[A-Za-z0-9]{20,}$ |
key | string | 资源的唯一标识键 |
size_bytes | integer | 资源大小(字节)≥ 0 |
etag | string | 对象内容的 ETag 哈希 |
content_type | string | null | 对象的 MIME 类型 |
metadata | object | null | 附加在此资源上的任意键值元数据 |
created_at | string | 资源创建时间(ISO 8601)format: date-time |
last_modified | string | null | 对象最后修改时间(ISO 8601)format: date-time |
示例
一次性前置(每个范例都假定已完成):
# No SDK to install — every call is a plain HTTPS request.
# Get a project key by signing in at https://infrai.cc/login (Google/GitHub gives
# you $2 free credit; email sign-in starts at $0). On 402 INSUFFICIENT_CREDIT, add
# funds at https://infrai.cc/billing (or POST /v1/account/topup and open the
# returned checkout_url).
export INFRAI_API_KEY="ifr_..."curl -X PUT https://api.infrai.cc/v1/storage/object/put/BUCKET/KEY \
-H "Authorization: Bearer $INFRAI_API_KEY" \
-H "Content-Type: application/json" \
-d '{"data_base64": "sample"}'# 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/storage/object/put/BUCKET/KEY",
headers={
"Authorization": f"Bearer {os.environ['INFRAI_API_KEY']}",
},
json={'data_base64': '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/storage/object/put/BUCKET/KEY",
{
method: "PUT",
headers: {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({"data_base64": "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/storage/object/put/BUCKET/KEY",
{
method: "PUT",
headers: {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({"data_base64": "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(`{"data_base64": "sample"}`)
req, _ := http.NewRequest("PUT", "https://api.infrai.cc/v1/storage/object/put/BUCKET/KEY", 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/storage/object/put/BUCKET/KEY"))
.header("Authorization", "Bearer " + System.getenv("INFRAI_API_KEY"))
.header("Content-Type", "application/json")
.method("PUT", HttpRequest.BodyPublishers.ofString("{\"data_base64\": \"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("PUT"), "https://api.infrai.cc/v1/storage/object/put/BUCKET/KEY");
var key = Environment.GetEnvironmentVariable("INFRAI_API_KEY");
req.Headers.Add("Authorization", "Bearer " + key);
req.Content = new StringContent("{\"data_base64\": \"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/storage/object/put/BUCKET/KEY");
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, "{\"data_base64\": \"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/storage/object/put/BUCKET/KEY")
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 = '{"data_base64": "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()
.put("https://api.infrai.cc/v1/storage/object/put/BUCKET/KEY")
.header("Authorization", format!("Bearer {}", env::var("INFRAI_API_KEY")?))
.header("Content-Type", "application/json")
.body(r#"{"data_base64": "sample"}"#)
.send()
.await?;
println!("{}", resp.text().await?);
Ok(())
}2.11storage.object.get
下载对象内容,以 JSON 返回对象信息和 base64 编码的 data_base64。
参数
| 名称 | 类型 | 必填 | 说明 |
|---|---|---|---|
bucket | string | 必填 | 存储桶名称 |
key | string | 必填 | 对象键(路径) |
返回
object bytes (application/octet-stream)| 名称 | 类型 | 说明 |
|---|---|---|
found | boolean | 对象是否被找到 |
status | string | "found" 或 "not_found" |
key | string | 所请求对象的键 |
size_bytes | integer | 对象大小(字节)(仅在找到时存在) |
data_base64 | string | Base64 编码的对象内容(仅在找到时存在) |
示例
一次性前置(每个范例都假定已完成):
# 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/storage/object/get/BUCKET/KEY \
-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/storage/object/get/BUCKET/KEY",
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/storage/object/get/BUCKET/KEY",
{
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/storage/object/get/BUCKET/KEY",
{
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/storage/object/get/BUCKET/KEY", 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/storage/object/get/BUCKET/KEY"))
.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/storage/object/get/BUCKET/KEY");
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/storage/object/get/BUCKET/KEY");
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/storage/object/get/BUCKET/KEY")
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/storage/object/get/BUCKET/KEY")
.header("Authorization", format!("Bearer {}", env::var("INFRAI_API_KEY")?))
.send()
.await?;
println!("{}", resp.text().await?);
Ok(())
}2.12storage.object.head
查询对象元信息
参数
| 名称 | 类型 | 必填 | 说明 |
|---|---|---|---|
bucket | string | 必填 | 存储桶名称 |
key | string | 必填 | 对象键(路径) |
返回
ObjectHeadResult { found, status, key, size_bytes, etag, content_type, metadata, last_modified }| 名称 | 类型 | 说明 |
|---|---|---|
found | boolean | 资源是否存在 |
status | "found" | "not_found" | 当前资源状态 |
key | string | null | 资源的唯一标识键 |
size_bytes | integer | null | 资源大小(字节)≥ 0 |
etag | string | null | 对象内容的 ETag 哈希 |
content_type | string | null | 对象的 MIME 类型 |
metadata | object | null | 附加在此资源上的任意键值元数据 |
last_modified | string | null | 对象最后修改时间(ISO 8601)format: date-time |
示例
一次性前置(每个范例都假定已完成):
# No SDK to install — every call is a plain HTTPS request.
# Get a project key by signing in at https://infrai.cc/login (Google/GitHub gives
# you $2 free credit; email sign-in starts at $0). On 402 INSUFFICIENT_CREDIT, add
# funds at https://infrai.cc/billing (or POST /v1/account/topup and open the
# returned checkout_url).
export INFRAI_API_KEY="ifr_..."curl -X GET https://api.infrai.cc/v1/storage/object/head/BUCKET/KEY \
-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/storage/object/head/BUCKET/KEY",
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/storage/object/head/BUCKET/KEY",
{
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/storage/object/head/BUCKET/KEY",
{
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/storage/object/head/BUCKET/KEY", 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/storage/object/head/BUCKET/KEY"))
.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/storage/object/head/BUCKET/KEY");
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/storage/object/head/BUCKET/KEY");
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/storage/object/head/BUCKET/KEY")
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/storage/object/head/BUCKET/KEY")
.header("Authorization", format!("Bearer {}", env::var("INFRAI_API_KEY")?))
.send()
.await?;
println!("{}", resp.text().await?);
Ok(())
}2.13storage.object.list
列举存储桶内对象
参数
| 名称 | 类型 | 必填 | 说明 |
|---|---|---|---|
bucket | string | 必填 | 存储桶名称 |
prefix | string | 可选 | 仅列举键以此前缀开头的对象 |
delimiter | string | 可选 | S3 风格的目录分隔符(如 /),将键归并为 common_prefixes |
cursor | string | 可选 | 来自上次 next_cursor 的分页游标 |
limit | number | 可选 | 本次返回的最大条数(1-1000) |
返回
ObjectListResult { items: StorageObject[], next_cursor, common_prefixes }| 名称 | 类型 | 说明 |
|---|---|---|
items | object[] | 本页结果条目数组 |
items[].bucket_id | string | storage bucket的唯一标识符pattern: ^bkt_[A-Za-z0-9]{20,}$ |
items[].key | string | 资源的唯一标识键 |
items[].size_bytes | integer | 资源大小(字节)≥ 0 |
items[].etag | string | 对象内容的 ETag 哈希 |
items[].content_type | string | null | 对象的 MIME 类型 |
items[].metadata | object | null | 附加在此资源上的任意键值元数据 |
items[].created_at | string | 此资源创建的 ISO 8601 时间戳format: date-time |
items[].last_modified | string | null | 对象最后修改的 ISO 8601 时间戳format: date-time |
next_cursor | string | null | 获取下一页的不透明游标;null 或不存在表示最后一页 |
common_prefixes | string[] | null | 向 object.list 提供分隔符时的 S3 风格文件夹前缀。 |
示例
一次性前置(每个范例都假定已完成):
# 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/storage/object/list/BUCKET \
-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/storage/object/list/BUCKET",
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/storage/object/list/BUCKET",
{
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/storage/object/list/BUCKET",
{
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/storage/object/list/BUCKET", 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/storage/object/list/BUCKET"))
.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/storage/object/list/BUCKET");
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/storage/object/list/BUCKET");
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/storage/object/list/BUCKET")
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/storage/object/list/BUCKET")
.header("Authorization", format!("Bearer {}", env::var("INFRAI_API_KEY")?))
.send()
.await?;
println!("{}", resp.text().await?);
Ok(())
}2.14storage.object.copy
复制对象;支持同桶或跨桶复制,并保留 content_type 与自定义 metadata。
参数
| 名称 | 类型 | 必填 | 说明 |
|---|---|---|---|
src_bucket | string | 必填 | 源存储桶名称 |
src_key | string | 必填 | 源对象键 |
dst_bucket | string | 必填 | 目标存储桶名称 |
dst_key | string | 必填 | 目标对象键 |
idempotency_key | string | 可选 | 幂等键;省略时自动派生 |
返回
StorageObject { bucket_id, key, size_bytes, etag, content_type, metadata, created_at, last_modified }| 名称 | 类型 | 说明 |
|---|---|---|
bucket_id | string | storage bucket的唯一标识符pattern: ^bkt_[A-Za-z0-9]{20,}$ |
key | string | 资源的唯一标识键 |
size_bytes | integer | 资源大小(字节)≥ 0 |
etag | string | 对象内容的 ETag 哈希 |
content_type | string | null | 对象的 MIME 类型 |
metadata | object | null | 附加在此资源上的任意键值元数据 |
created_at | string | 资源创建时间(ISO 8601)format: date-time |
last_modified | string | null | 对象最后修改时间(ISO 8601)format: date-time |
示例
一次性前置(每个范例都假定已完成):
# No SDK to install — every call is a plain HTTPS request.
# Get a project key by signing in at https://infrai.cc/login (Google/GitHub gives
# you $2 free credit; email sign-in starts at $0). On 402 INSUFFICIENT_CREDIT, add
# funds at https://infrai.cc/billing (or POST /v1/account/topup and open the
# returned checkout_url).
export INFRAI_API_KEY="ifr_..."curl -X POST https://api.infrai.cc/v1/storage/object/copy \
-H "Authorization: Bearer $INFRAI_API_KEY" \
-H "Content-Type: application/json" \
-d '{"src_bucket": "sample", "src_key": "sample", "dst_bucket": "sample", "dst_key": "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/storage/object/copy",
headers={
"Authorization": f"Bearer {os.environ['INFRAI_API_KEY']}",
},
json={'src_bucket': 'sample', 'src_key': 'sample', 'dst_bucket': 'sample', 'dst_key': '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/storage/object/copy",
{
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({"src_bucket": "sample", "src_key": "sample", "dst_bucket": "sample", "dst_key": "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/storage/object/copy",
{
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({"src_bucket": "sample", "src_key": "sample", "dst_bucket": "sample", "dst_key": "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(`{"src_bucket": "sample", "src_key": "sample", "dst_bucket": "sample", "dst_key": "sample"}`)
req, _ := http.NewRequest("POST", "https://api.infrai.cc/v1/storage/object/copy", 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/storage/object/copy"))
.header("Authorization", "Bearer " + System.getenv("INFRAI_API_KEY"))
.header("Content-Type", "application/json")
.method("POST", HttpRequest.BodyPublishers.ofString("{\"src_bucket\": \"sample\", \"src_key\": \"sample\", \"dst_bucket\": \"sample\", \"dst_key\": \"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/storage/object/copy");
var key = Environment.GetEnvironmentVariable("INFRAI_API_KEY");
req.Headers.Add("Authorization", "Bearer " + key);
req.Content = new StringContent("{\"src_bucket\": \"sample\", \"src_key\": \"sample\", \"dst_bucket\": \"sample\", \"dst_key\": \"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/storage/object/copy");
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, "{\"src_bucket\": \"sample\", \"src_key\": \"sample\", \"dst_bucket\": \"sample\", \"dst_key\": \"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/storage/object/copy")
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 = '{"src_bucket": "sample", "src_key": "sample", "dst_bucket": "sample", "dst_key": "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/storage/object/copy")
.header("Authorization", format!("Bearer {}", env::var("INFRAI_API_KEY")?))
.header("Content-Type", "application/json")
.body(r#"{"src_bucket": "sample", "src_key": "sample", "dst_bucket": "sample", "dst_key": "sample"}"#)
.send()
.await?;
println!("{}", resp.text().await?);
Ok(())
}2.15storage.object.delete_batch
批量删除对象;返回 deleted 与 errors,不存在的 key 会出现在 errors 中。
参数
| 名称 | 类型 | 必填 | 说明 |
|---|---|---|---|
bucket | string | 必填 | 存储桶名称 |
keys | string[] | 必填 | 要删除的对象键列表(1-1000 个)。不存在的 key 会返回在 errors 中,code 为 STORAGE_OBJECT_NOT_FOUND。1–1000 items |
idempotency_key | string | 可选 | 幂等键;省略时按键集合内容哈希自动派生 |
返回
ObjectDeleteBatchResult { deleted, errors }| 名称 | 类型 | 说明 |
|---|---|---|
deleted | string[] | 已成功删除的键。 |
errors | object[] | 批量操作中逐条错误的数组 |
errors[].key | string | - |
errors[].code | string | 来自 errors/registry.yaml 的错误码。 |
示例
一次性前置(每个范例都假定已完成):
# 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/storage/object/delete_batch/BUCKET \
-H "Authorization: Bearer $INFRAI_API_KEY" \
-H "Content-Type: application/json" \
-d '{"keys": ["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/storage/object/delete_batch/BUCKET",
headers={
"Authorization": f"Bearer {os.environ['INFRAI_API_KEY']}",
},
json={'keys': ['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/storage/object/delete_batch/BUCKET",
{
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({"keys": ["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/storage/object/delete_batch/BUCKET",
{
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({"keys": ["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(`{"keys": ["sample"]}`)
req, _ := http.NewRequest("POST", "https://api.infrai.cc/v1/storage/object/delete_batch/BUCKET", 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/storage/object/delete_batch/BUCKET"))
.header("Authorization", "Bearer " + System.getenv("INFRAI_API_KEY"))
.header("Content-Type", "application/json")
.method("POST", HttpRequest.BodyPublishers.ofString("{\"keys\": [\"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/storage/object/delete_batch/BUCKET");
var key = Environment.GetEnvironmentVariable("INFRAI_API_KEY");
req.Headers.Add("Authorization", "Bearer " + key);
req.Content = new StringContent("{\"keys\": [\"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/storage/object/delete_batch/BUCKET");
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, "{\"keys\": [\"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/storage/object/delete_batch/BUCKET")
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 = '{"keys": ["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/storage/object/delete_batch/BUCKET")
.header("Authorization", format!("Bearer {}", env::var("INFRAI_API_KEY")?))
.header("Content-Type", "application/json")
.body(r#"{"keys": ["sample"]}"#)
.send()
.await?;
println!("{}", resp.text().await?);
Ok(())
}2.16storage.object.set_acl
设置对象访问权限;当前支持 private 与 signed-only,不支持 public/public-read。
参数
| 名称 | 类型 | 必填 | 说明 |
|---|---|---|---|
bucket | string | 必填 | 存储桶名称 |
key | string | 必填 | 对象键(路径) |
acl | "private" | "signed-only" | 必填 | 访问权限。支持 private、signed-only;public 和 public-read 当前不支持,public_url 固定为 null。 |
idempotency_key | string | 可选 | 幂等键;省略时自动派生 |
返回
ObjectSetAclResult { acl, public_url }| 名称 | 类型 | 说明 |
|---|---|---|
acl | "private" | "signed-only" | 桶或对象的访问控制列表 |
public_url | string | null | 始终为 null(已移除公开读;无永久公开直接链接)。 |
示例
一次性前置(每个范例都假定已完成):
# No SDK to install — every call is a plain HTTPS request.
# Get a project key by signing in at https://infrai.cc/login (Google/GitHub gives
# you $2 free credit; email sign-in starts at $0). On 402 INSUFFICIENT_CREDIT, add
# funds at https://infrai.cc/billing (or POST /v1/account/topup and open the
# returned checkout_url).
export INFRAI_API_KEY="ifr_..."curl -X POST https://api.infrai.cc/v1/storage/object/set_acl/BUCKET/KEY \
-H "Authorization: Bearer $INFRAI_API_KEY" \
-H "Content-Type: application/json" \
-d '{"acl": "private"}'# 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/storage/object/set_acl/BUCKET/KEY",
headers={
"Authorization": f"Bearer {os.environ['INFRAI_API_KEY']}",
},
json={'acl': 'private'},
)
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/storage/object/set_acl/BUCKET/KEY",
{
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({"acl": "private"}),
},
);
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/storage/object/set_acl/BUCKET/KEY",
{
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({"acl": "private"}),
},
);
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(`{"acl": "private"}`)
req, _ := http.NewRequest("POST", "https://api.infrai.cc/v1/storage/object/set_acl/BUCKET/KEY", 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/storage/object/set_acl/BUCKET/KEY"))
.header("Authorization", "Bearer " + System.getenv("INFRAI_API_KEY"))
.header("Content-Type", "application/json")
.method("POST", HttpRequest.BodyPublishers.ofString("{\"acl\": \"private\"}"))
.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/storage/object/set_acl/BUCKET/KEY");
var key = Environment.GetEnvironmentVariable("INFRAI_API_KEY");
req.Headers.Add("Authorization", "Bearer " + key);
req.Content = new StringContent("{\"acl\": \"private\"}", 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/storage/object/set_acl/BUCKET/KEY");
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, "{\"acl\": \"private\"}");
$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/storage/object/set_acl/BUCKET/KEY")
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 = '{"acl": "private"}'
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/storage/object/set_acl/BUCKET/KEY")
.header("Authorization", format!("Bearer {}", env::var("INFRAI_API_KEY")?))
.header("Content-Type", "application/json")
.body(r#"{"acl": "private"}"#)
.send()
.await?;
println!("{}", resp.text().await?);
Ok(())
}2.17storage.object.set_metadata
更新对象的 content_type、cache_control 与自定义 metadata;metadata 为替换语义。
参数
| 名称 | 类型 | 必填 | 说明 |
|---|---|---|---|
bucket | string | 必填 | 存储桶名称 |
key | string | 必填 | 对象键(路径) |
content_type | string | 可选 | 对象的 MIME 类型 |
cache_control | string | 可选 | Cache-Control 头 |
metadata | Record<string, string> | 可选 | 用户自定义元数据键值对。传入 metadata 会整体替换原 metadata,不是与旧值合并;未传时保留原值。 |
idempotency_key | string | 可选 | 幂等键;省略时自动派生 |
返回
StorageObject { bucket_id, key, size_bytes, etag, content_type, metadata, created_at, last_modified }| 名称 | 类型 | 说明 |
|---|---|---|
bucket_id | string | storage bucket的唯一标识符pattern: ^bkt_[A-Za-z0-9]{20,}$ |
key | string | 资源的唯一标识键 |
size_bytes | integer | 资源大小(字节)≥ 0 |
etag | string | 对象内容的 ETag 哈希 |
content_type | string | null | 对象的 MIME 类型 |
metadata | object | null | 附加在此资源上的任意键值元数据 |
created_at | string | 资源创建时间(ISO 8601)format: date-time |
last_modified | string | null | 对象最后修改时间(ISO 8601)format: date-time |
示例
一次性前置(每个范例都假定已完成):
# No SDK to install — every call is a plain HTTPS request.
# Get a project key by signing in at https://infrai.cc/login (Google/GitHub gives
# you $2 free credit; email sign-in starts at $0). On 402 INSUFFICIENT_CREDIT, add
# funds at https://infrai.cc/billing (or POST /v1/account/topup and open the
# returned checkout_url).
export INFRAI_API_KEY="ifr_..."curl -X POST https://api.infrai.cc/v1/storage/object/set_metadata/BUCKET/KEY \
-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/storage/object/set_metadata/BUCKET/KEY",
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/storage/object/set_metadata/BUCKET/KEY",
{
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/storage/object/set_metadata/BUCKET/KEY",
{
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/storage/object/set_metadata/BUCKET/KEY", 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/storage/object/set_metadata/BUCKET/KEY"))
.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/storage/object/set_metadata/BUCKET/KEY");
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/storage/object/set_metadata/BUCKET/KEY");
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/storage/object/set_metadata/BUCKET/KEY")
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/storage/object/set_metadata/BUCKET/KEY")
.header("Authorization", format!("Bearer {}", env::var("INFRAI_API_KEY")?))
.header("Content-Type", "application/json")
.body(r#"{}"#)
.send()
.await?;
println!("{}", resp.text().await?);
Ok(())
}2.18storage.multipart.create
发起分片上传
参数
| 名称 | 类型 | 必填 | 说明 |
|---|---|---|---|
bucket | string | 必填 | 存储桶名称 |
key | string | 必填 | 对象键(路径) |
content_type | string | 可选 | 对象的 MIME 类型 |
idempotency_key | string | 可选 | 幂等键;省略时自动派生 |
返回
MultipartUpload { upload_id, bucket_id, key, started_at, part_size_min, part_count_max }| 名称 | 类型 | 说明 |
|---|---|---|
upload_id | string | multipart upload的唯一标识符 |
bucket_id | string | storage bucket的唯一标识符pattern: ^bkt_[A-Za-z0-9]{20,}$ |
key | string | 资源的唯一标识键 |
started_at | string | 执行开始时间(ISO 8601)format: date-time |
part_size_min | integer | null | 供应商最小分片大小(S3 为 ≥5 MiB)。≥ 5242880 |
part_count_max | integer | null | 允许的最大分片数1–10000 |
示例
一次性前置(每个范例都假定已完成):
# 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/storage/multipart/create/BUCKET \
-H "Authorization: Bearer $INFRAI_API_KEY" \
-H "Content-Type: application/json" \
-d '{"key": "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/storage/multipart/create/BUCKET",
headers={
"Authorization": f"Bearer {os.environ['INFRAI_API_KEY']}",
},
json={'key': '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/storage/multipart/create/BUCKET",
{
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({"key": "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/storage/multipart/create/BUCKET",
{
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({"key": "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(`{"key": "sample"}`)
req, _ := http.NewRequest("POST", "https://api.infrai.cc/v1/storage/multipart/create/BUCKET", 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/storage/multipart/create/BUCKET"))
.header("Authorization", "Bearer " + System.getenv("INFRAI_API_KEY"))
.header("Content-Type", "application/json")
.method("POST", HttpRequest.BodyPublishers.ofString("{\"key\": \"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/storage/multipart/create/BUCKET");
var key = Environment.GetEnvironmentVariable("INFRAI_API_KEY");
req.Headers.Add("Authorization", "Bearer " + key);
req.Content = new StringContent("{\"key\": \"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/storage/multipart/create/BUCKET");
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, "{\"key\": \"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/storage/multipart/create/BUCKET")
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 = '{"key": "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/storage/multipart/create/BUCKET")
.header("Authorization", format!("Bearer {}", env::var("INFRAI_API_KEY")?))
.header("Content-Type", "application/json")
.body(r#"{"key": "sample"}"#)
.send()
.await?;
println!("{}", resp.text().await?);
Ok(())
}2.19storage.multipart.presign_part
为单个分片生成预签名上传 URL;按返回的 method 上传该分片的二进制内容,并在 complete 时提交 ETag。
参数
| 名称 | 类型 | 必填 | 说明 |
|---|---|---|---|
upload_id | string | 必填 | 分片上传 ID |
part_number | number | 必填 | 分片序号(从 1 开始)。除最后一片外,上传到该 URL 的分片通常需不小于 5 MiB。≥ 1 |
返回
MultipartPresignPartResult { url, method, headers, expires_at }| 名称 | 类型 | 说明 |
|---|---|---|
url | string | 资源或端点 URL |
method | "PUT" | 所用的认证方式(如 email_otp、oauth、password) |
headers | object | null | 请求或响应中包含的自定义 HTTP 头 |
expires_at | string | 资源或令牌过期时间(ISO 8601)format: date-time |
示例
一次性前置(每个范例都假定已完成):
# No SDK to install — every call is a plain HTTPS request.
# Get a project key by signing in at https://infrai.cc/login (Google/GitHub gives
# you $2 free credit; email sign-in starts at $0). On 402 INSUFFICIENT_CREDIT, add
# funds at https://infrai.cc/billing (or POST /v1/account/topup and open the
# returned checkout_url).
export INFRAI_API_KEY="ifr_..."curl -X POST https://api.infrai.cc/v1/storage/multipart/presign_part/UPLOAD_ID/PART_NUMBER \
-H "Authorization: Bearer $INFRAI_API_KEY" \
-H "Content-Type: application/json" \
-d '{"upload_id": "sample", "part_number": 1}'# 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/storage/multipart/presign_part/UPLOAD_ID/PART_NUMBER",
headers={
"Authorization": f"Bearer {os.environ['INFRAI_API_KEY']}",
},
json={'upload_id': 'sample', 'part_number': 1},
)
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/storage/multipart/presign_part/UPLOAD_ID/PART_NUMBER",
{
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({"upload_id": "sample", "part_number": 1}),
},
);
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/storage/multipart/presign_part/UPLOAD_ID/PART_NUMBER",
{
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({"upload_id": "sample", "part_number": 1}),
},
);
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(`{"upload_id": "sample", "part_number": 1}`)
req, _ := http.NewRequest("POST", "https://api.infrai.cc/v1/storage/multipart/presign_part/UPLOAD_ID/PART_NUMBER", 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/storage/multipart/presign_part/UPLOAD_ID/PART_NUMBER"))
.header("Authorization", "Bearer " + System.getenv("INFRAI_API_KEY"))
.header("Content-Type", "application/json")
.method("POST", HttpRequest.BodyPublishers.ofString("{\"upload_id\": \"sample\", \"part_number\": 1}"))
.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/storage/multipart/presign_part/UPLOAD_ID/PART_NUMBER");
var key = Environment.GetEnvironmentVariable("INFRAI_API_KEY");
req.Headers.Add("Authorization", "Bearer " + key);
req.Content = new StringContent("{\"upload_id\": \"sample\", \"part_number\": 1}", 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/storage/multipart/presign_part/UPLOAD_ID/PART_NUMBER");
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, "{\"upload_id\": \"sample\", \"part_number\": 1}");
$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/storage/multipart/presign_part/UPLOAD_ID/PART_NUMBER")
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 = '{"upload_id": "sample", "part_number": 1}'
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/storage/multipart/presign_part/UPLOAD_ID/PART_NUMBER")
.header("Authorization", format!("Bearer {}", env::var("INFRAI_API_KEY")?))
.header("Content-Type", "application/json")
.body(r#"{"upload_id": "sample", "part_number": 1}"#)
.send()
.await?;
println!("{}", resp.text().await?);
Ok(())
}2.20storage.multipart.upload_part
上传单个分片
参数
| 名称 | 类型 | 必填 | 说明 |
|---|---|---|---|
upload_id | string | 必填 | 分片上传 ID |
part_number | number | 必填 | 分片序号(从 1 开始)≥ 1 |
body | bytes | 必填 | 分片字节内容 |
idempotency_key | string | 可选 | 幂等键;省略时自动派生 |
返回
MultipartPart { part_number, etag }| 名称 | 类型 | 说明 |
|---|---|---|
part_number | integer | 分片上传中的分片序号1–10000 |
etag | string | 对象内容的 ETag 哈希 |
size_bytes | integer | null | 资源大小(字节)≥ 0 |
示例
一次性前置(每个范例都假定已完成):
# No SDK to install — every call is a plain HTTPS request.
# Get a project key by signing in at https://infrai.cc/login (Google/GitHub gives
# you $2 free credit; email sign-in starts at $0). On 402 INSUFFICIENT_CREDIT, add
# funds at https://infrai.cc/billing (or POST /v1/account/topup and open the
# returned checkout_url).
export INFRAI_API_KEY="ifr_..."curl -X PUT https://api.infrai.cc/v1/storage/multipart/upload_part/UPLOAD_ID/PART_NUMBER \
-H "Authorization: Bearer $INFRAI_API_KEY" \
-H "Content-Type: application/json" \
-d '{"upload_id": "sample", "part_number": 1, "data_base64": "sample"}'# 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/storage/multipart/upload_part/UPLOAD_ID/PART_NUMBER",
headers={
"Authorization": f"Bearer {os.environ['INFRAI_API_KEY']}",
},
json={'upload_id': 'sample', 'part_number': 1, 'data_base64': '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/storage/multipart/upload_part/UPLOAD_ID/PART_NUMBER",
{
method: "PUT",
headers: {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({"upload_id": "sample", "part_number": 1, "data_base64": "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/storage/multipart/upload_part/UPLOAD_ID/PART_NUMBER",
{
method: "PUT",
headers: {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({"upload_id": "sample", "part_number": 1, "data_base64": "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(`{"upload_id": "sample", "part_number": 1, "data_base64": "sample"}`)
req, _ := http.NewRequest("PUT", "https://api.infrai.cc/v1/storage/multipart/upload_part/UPLOAD_ID/PART_NUMBER", 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/storage/multipart/upload_part/UPLOAD_ID/PART_NUMBER"))
.header("Authorization", "Bearer " + System.getenv("INFRAI_API_KEY"))
.header("Content-Type", "application/json")
.method("PUT", HttpRequest.BodyPublishers.ofString("{\"upload_id\": \"sample\", \"part_number\": 1, \"data_base64\": \"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("PUT"), "https://api.infrai.cc/v1/storage/multipart/upload_part/UPLOAD_ID/PART_NUMBER");
var key = Environment.GetEnvironmentVariable("INFRAI_API_KEY");
req.Headers.Add("Authorization", "Bearer " + key);
req.Content = new StringContent("{\"upload_id\": \"sample\", \"part_number\": 1, \"data_base64\": \"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/storage/multipart/upload_part/UPLOAD_ID/PART_NUMBER");
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, "{\"upload_id\": \"sample\", \"part_number\": 1, \"data_base64\": \"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/storage/multipart/upload_part/UPLOAD_ID/PART_NUMBER")
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 = '{"upload_id": "sample", "part_number": 1, "data_base64": "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()
.put("https://api.infrai.cc/v1/storage/multipart/upload_part/UPLOAD_ID/PART_NUMBER")
.header("Authorization", format!("Bearer {}", env::var("INFRAI_API_KEY")?))
.header("Content-Type", "application/json")
.body(r#"{"upload_id": "sample", "part_number": 1, "data_base64": "sample"}"#)
.send()
.await?;
println!("{}", resp.text().await?);
Ok(())
}2.21storage.multipart.complete
完成分片上传
参数
| 名称 | 类型 | 必填 | 说明 |
|---|---|---|---|
upload_id | string | 必填 | 分片上传 ID |
parts | MultipartPart[] | 必填 | 已上传分片列表(每项含 part_number 与 etag,1-10000 个);etag 使用每个分片上传响应返回的 ETag。1–10000 items |
idempotency_key | string | 可选 | 幂等键;省略时自动派生 |
返回
StorageObject { bucket_id, key, size_bytes, etag, content_type, metadata, created_at, last_modified }| 名称 | 类型 | 说明 |
|---|---|---|
bucket_id | string | storage bucket的唯一标识符pattern: ^bkt_[A-Za-z0-9]{20,}$ |
key | string | 资源的唯一标识键 |
size_bytes | integer | 资源大小(字节)≥ 0 |
etag | string | 对象内容的 ETag 哈希 |
content_type | string | null | 对象的 MIME 类型 |
metadata | object | null | 附加在此资源上的任意键值元数据 |
created_at | string | 资源创建时间(ISO 8601)format: date-time |
last_modified | string | null | 对象最后修改时间(ISO 8601)format: date-time |
示例
一次性前置(每个范例都假定已完成):
# No SDK to install — every call is a plain HTTPS request.
# Get a project key by signing in at https://infrai.cc/login (Google/GitHub gives
# you $2 free credit; email sign-in starts at $0). On 402 INSUFFICIENT_CREDIT, add
# funds at https://infrai.cc/billing (or POST /v1/account/topup and open the
# returned checkout_url).
export INFRAI_API_KEY="ifr_..."curl -X POST https://api.infrai.cc/v1/storage/multipart/complete/UPLOAD_ID \
-H "Authorization: Bearer $INFRAI_API_KEY" \
-H "Content-Type: application/json" \
-d '{"parts": [{"part_number": 1, "etag": "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/storage/multipart/complete/UPLOAD_ID",
headers={
"Authorization": f"Bearer {os.environ['INFRAI_API_KEY']}",
},
json={'parts': [{'part_number': 1, 'etag': '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/storage/multipart/complete/UPLOAD_ID",
{
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({"parts": [{"part_number": 1, "etag": "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/storage/multipart/complete/UPLOAD_ID",
{
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({"parts": [{"part_number": 1, "etag": "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(`{"parts": [{"part_number": 1, "etag": "sample"}]}`)
req, _ := http.NewRequest("POST", "https://api.infrai.cc/v1/storage/multipart/complete/UPLOAD_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/storage/multipart/complete/UPLOAD_ID"))
.header("Authorization", "Bearer " + System.getenv("INFRAI_API_KEY"))
.header("Content-Type", "application/json")
.method("POST", HttpRequest.BodyPublishers.ofString("{\"parts\": [{\"part_number\": 1, \"etag\": \"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/storage/multipart/complete/UPLOAD_ID");
var key = Environment.GetEnvironmentVariable("INFRAI_API_KEY");
req.Headers.Add("Authorization", "Bearer " + key);
req.Content = new StringContent("{\"parts\": [{\"part_number\": 1, \"etag\": \"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/storage/multipart/complete/UPLOAD_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, "{\"parts\": [{\"part_number\": 1, \"etag\": \"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/storage/multipart/complete/UPLOAD_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 = '{"parts": [{"part_number": 1, "etag": "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/storage/multipart/complete/UPLOAD_ID")
.header("Authorization", format!("Bearer {}", env::var("INFRAI_API_KEY")?))
.header("Content-Type", "application/json")
.body(r#"{"parts": [{"part_number": 1, "etag": "sample"}]}"#)
.send()
.await?;
println!("{}", resp.text().await?);
Ok(())
}2.22storage.multipart.abort
中止分片上传。成功后 upload_id 失效,后续 presign_part/complete 会返回 STORAGE_MULTIPART_INCONSISTENT。
参数
| 名称 | 类型 | 必填 | 说明 |
|---|---|---|---|
upload_id | string | 必填 | 分片上传 ID |
idempotency_key | string | 可选 | 幂等键;省略时自动派生 |
返回
MultipartAbortResult { aborted }| 名称 | 类型 | 说明 |
|---|---|---|
aborted | boolean | 分片上传是否已成功中止 |
示例
一次性前置(每个范例都假定已完成):
# No SDK to install — every call is a plain HTTPS request.
# Get a project key by signing in at https://infrai.cc/login (Google/GitHub gives
# you $2 free credit; email sign-in starts at $0). On 402 INSUFFICIENT_CREDIT, add
# funds at https://infrai.cc/billing (or POST /v1/account/topup and open the
# returned checkout_url).
export INFRAI_API_KEY="ifr_..."curl -X DELETE https://api.infrai.cc/v1/storage/multipart/abort/UPLOAD_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/storage/multipart/abort/UPLOAD_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/storage/multipart/abort/UPLOAD_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/storage/multipart/abort/UPLOAD_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/storage/multipart/abort/UPLOAD_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/storage/multipart/abort/UPLOAD_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/storage/multipart/abort/UPLOAD_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/storage/multipart/abort/UPLOAD_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/storage/multipart/abort/UPLOAD_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/storage/multipart/abort/UPLOAD_ID")
.header("Authorization", format!("Bearer {}", env::var("INFRAI_API_KEY")?))
.send()
.await?;
println!("{}", resp.text().await?);
Ok(())
}高级:指定 vendor
默认情况下 infrai 会把每次调用智能路由到最佳可用供应商——无需自己挑选 vendor。作为高级逃生口,本能力支持可选的 vendor 入参以锁定某个供应商。本能力当前所有可用 vendor 可通过该能力 id 对应的 discovery 端点实时获取——参见 discovery API。
GET /v1/discovery/{capability}storage.bucket.create
3. 全部能力
本模块全部已路由能力——完整的对外 REST 契约。上方方法是带讲解的入门示例,此表是完整参考。
storage.bucket.createPOST /v1/storage/bucket/createCreate an object storage bucket. Bucket names must be 3-63 lowercase letters, digits, dots, or hyphens and start/end with a letter or digit; `region` must be a canonical region code.
参数 (6)
| 名称 | 类型 | 必填 | 说明 |
|---|---|---|---|
name | string | 必填 | Bucket name. Length 3-63; lowercase letters, digits, dots, and hyphens only; must start and end with a letter or digit. Example: demo-files. |
bucket | string | null | 可选 | Alias for name. Prefer name in new integrations. |
vendor | string | null | 可选 | Pin to a specific storage vendor. |
region | "us-east-1" | "us-west-2" | "eu-west-1" | "eu-central-1" | "ap-southeast-1" | "ap-northeast-1" | "cn-hangzhou" | "cn-beijing" | "auto" | "ap-singapore" | "ap-hongkong" | "ap-tokyo" | "ap-bangkok" | "na-siliconvalley" | null | 可选 | Optional storage region code. Pass a canonical code such as cn-beijing for Beijing or ap-singapore for Singapore; localized names such as 北京 are rejected. |
acl | string | 可选 | Bucket access control. Defaults to private; currently only private and signed-only are supported. public and public-read are not supported.default: "private" |
idempotency_key | string | null | 可选 | Client-provided idempotency key; prevents duplicate execution on retry |
storage.bucket.deleteDELETE /v1/storage/bucket/delete/{bucket}Delete an object storage bucket (idempotent). Empty buckets can be deleted directly; non-empty buckets require `force=true`, otherwise the API returns STORAGE_DELETE_NOT_FORCED.
参数 (1)
| 名称 | 类型 | 必填 | 说明 |
|---|---|---|---|
bucket | string | 必填 | Path parameter. |
storage.bucket.getGET /v1/storage/bucket/get/{bucket}Retrieve a bucket's metadata (provider, region, ACL, CORS, and lifecycle rules).
参数 (1)
| 名称 | 类型 | 必填 | 说明 |
|---|---|---|---|
bucket | string | 必填 | Path parameter. |
storage.bucket.listGET /v1/storage/bucket/listList the account's object storage buckets.
无请求参数。
storage.bucket.set_lifecyclePOST /v1/storage/bucket/set_lifecycle/{bucket}Set bucket lifecycle rules by key prefix; expire_days is measured in days and must be at least 1.
参数 (3)
| 名称 | 类型 | 必填 | 说明 |
|---|---|---|---|
bucket | string | 必填 | Path parameter. |
rules | object[] | 必填 | Lifecycle rule set governing object expiration/transition. Each rule supports prefix, expire_days, and transition_class. The whole list replaces the existing rule set.e.g. [{"prefix":"tmp/","expire_days":1}] |
idempotency_key | string | null | 可选 | Client-provided idempotency key; prevents duplicate execution on retry |
storage.bucket.set_notificationPOST /v1/storage/bucket/set_notification/{bucket}Subscribe storage object events to a callback URL; Infrai sends JSON POST notifications with X-Infrai-Event.
参数 (4)
| 名称 | 类型 | 必填 | 说明 |
|---|---|---|---|
bucket | string | 必填 | Path parameter. |
events | ("object.created" | "object.deleted" | "multipart.completed")[] | 必填 | Event types that trigger a notification. Supported values are object.created, object.deleted, and multipart.completed.≥ 1 iteme.g. ["object.created","object.deleted","multipart.completed"] |
target | object | 必填 | Notification callback target. For public API usage, pass target.url.e.g. {"url":"https://example.com/storage-events"} |
idempotency_key | string | null | 可选 | Client-provided idempotency key; prevents duplicate execution on retry |
storage.bucket.usageGET /v1/storage/bucket/usage/{bucket}Query a bucket's usage statistics: object count, bytes stored, and measurement timestamp.
参数 (1)
| 名称 | 类型 | 必填 | 说明 |
|---|---|---|---|
bucket | string | 必填 | Path parameter. |
storage.multipart.abortDELETE /v1/storage/multipart/abort/{upload_id}Abort a multipart upload and invalidate the upload_id.
参数 (1)
| 名称 | 类型 | 必填 | 说明 |
|---|---|---|---|
upload_id | string | 必填 | Path parameter. |
storage.multipart.completePOST /v1/storage/multipart/complete/{upload_id}Complete a multipart upload, assembling parts into the final StorageObject.
参数 (3)
| 名称 | 类型 | 必填 | 说明 |
|---|---|---|---|
upload_id | string | 必填 | Path parameter. |
parts | object[] | 必填 | Uploaded parts (part number + ETag) to assemble into the final object, in order.1–10000 items |
idempotency_key | string | null | 可选 | Client-provided idempotency key; prevents duplicate execution on retry |
storage.multipart.createPOST /v1/storage/multipart/create/{bucket}Initiate a multipart upload, returning an upload_id and part size/count limits.
参数 (4)
| 名称 | 类型 | 必填 | 说明 |
|---|---|---|---|
bucket | string | 必填 | Path parameter. |
key | string | 必填 | Destination object key (path) for the multipart upload. |
content_type | string | null | 可选 | MIME type of the object |
idempotency_key | string | null | 可选 | Client-provided idempotency key; prevents duplicate execution on retry |
storage.multipart.presign_partPOST /v1/storage/multipart/presign_part/{upload_id}/{part_number}Generate a presigned upload URL for a single part; upload the part binary with the returned method.
参数 (3)
| 名称 | 类型 | 必填 | 说明 |
|---|---|---|---|
upload_id | string | 必填 | Id of the multipart upload. |
part_number | integer | 必填 | 1-based index of the part being uploaded. Except for the final part, S3-compatible multipart uploads usually require each part to be at least 5 MiB.≥ 1 |
idempotency_key | string | null | 可选 | Client-provided idempotency key; prevents duplicate execution on retry |
storage.multipart.upload_partPUT /v1/storage/multipart/upload_part/{upload_id}/{part_number}Upload the bytes of a single part, returning that part's etag.
参数 (6)
| 名称 | 类型 | 必填 | 说明 |
|---|---|---|---|
upload_id | string | 必填 | Id of the multipart upload. |
part_number | integer | 必填 | 1-based index of this part.≥ 1 |
data_base64 | string | 必填 | Base64-encoded part bytes (the part payload — required). Aliases data/file_base64 are also accepted by the server. |
data | string | null | 可选 | Base64-encoded part bytes (alias of data_base64/file_base64). |
file_base64 | string | null | 可选 | Base64-encoded part bytes (alias). |
idempotency_key | string | null | 可选 | Client-provided idempotency key; prevents duplicate execution on retry |
storage.object.copyPOST /v1/storage/object/copyCopy an object within or across buckets, preserving content_type and metadata.
参数 (5)
| 名称 | 类型 | 必填 | 说明 |
|---|---|---|---|
src_bucket | string | 必填 | Source bucket to copy from. |
src_key | string | 必填 | Source object key (path) to copy from. |
dst_bucket | string | 必填 | Destination bucket to copy into. |
dst_key | string | 必填 | Destination object key (path) to write. |
idempotency_key | string | null | 可选 | Client-provided idempotency key; prevents duplicate execution on retry |
storage.object.deleteDELETE /v1/storage/object/delete/{bucket}/{key}Delete a storage object (idempotent).
参数 (2)
| 名称 | 类型 | 必填 | 说明 |
|---|---|---|---|
key | string | 必填 | Path parameter. |
bucket | string | 必填 | Path parameter. |
storage.object.delete_batchPOST /v1/storage/object/delete_batch/{bucket}Delete up to 1000 objects in one call, returning deleted keys plus per-key errors.
参数 (3)
| 名称 | 类型 | 必填 | 说明 |
|---|---|---|---|
bucket | string | 必填 | Path parameter. |
keys | string[] | 必填 | Object keys to delete in one batch. Missing keys are returned in errors with code STORAGE_OBJECT_NOT_FOUND.1–1000 items |
idempotency_key | string | null | 可选 | Optional; SDK auto-derives from the content_hash of the key set when omitted. |
storage.object.getGET /v1/storage/object/get/{bucket}/{key}Download an object's contents as JSON metadata plus base64-encoded data_base64.
参数 (2)
| 名称 | 类型 | 必填 | 说明 |
|---|---|---|---|
key | string | 必填 | Path parameter. |
bucket | string | 必填 | Path parameter. |
storage.object.headGET /v1/storage/object/head/{bucket}/{key}Fetch an object's existence and metadata (size, etag, content_type, metadata) without the body.
参数 (2)
| 名称 | 类型 | 必填 | 说明 |
|---|---|---|---|
key | string | 必填 | Path parameter. |
bucket | string | 必填 | Path parameter. |
storage.object.listGET /v1/storage/object/list/{bucket}List objects in a bucket, supporting prefix, delimiter, and cursor pagination.
参数 (1)
| 名称 | 类型 | 必填 | 说明 |
|---|---|---|---|
bucket | string | 必填 | Path parameter. |
storage.object.presignPOST /v1/storage/object/presign/{bucket}/{key}Generate a presigned URL for direct client upload or download of an object (idempotent). For `op=put`, use the returned URL with its returned method (usually PUT) to upload raw binary bytes directly; do not send the Infrai API key to the presigned URL.
参数 (8)
| 名称 | 类型 | 必填 | 说明 |
|---|---|---|---|
key | string | 必填 | Path parameter. |
bucket | string | 必填 | Path parameter. |
op | "get" | "put" | 必填 | Operation type: get creates a download URL; put creates an upload URL for direct binary upload.e.g. put |
expires_seconds | integer | null | 可选 | TTL of the presigned URL (defaults: get=3600, put=300).≥ 1 |
content_type | string | null | 可选 | For op=put: constrain the upload content type. |
max_bytes | integer | null | 可选 | For op=put: cap the upload size.≥ 0 |
response_disposition | string | null | 可选 | For op=get: Content-Disposition for the download filename. |
idempotency_key | string | null | 可选 | Client-provided idempotency key; prevents duplicate execution on retry |
storage.object.putPUT /v1/storage/object/put/{bucket}/{key}Upload an object server-side with JSON `data_base64`. Base64 upload is intended for small files and is not recommended above 1 MB; use presigned or multipart direct upload for larger files.
参数 (10)
| 名称 | 类型 | 必填 | 说明 |
|---|---|---|---|
key | string | 必填 | Path parameter. |
bucket | string | 必填 | Path parameter. |
data_base64 | string | 必填 | REQUIRED. The object bytes, base64-encoded as a bare base64 string or data: URL. Intended for small files; not recommended above 1 MB. |
data | string | null | 可选 | Alias for data_base64 (base64-encoded object bytes). |
file_base64 | string | null | 可选 | Alias for data_base64 (base64-encoded object bytes). |
content_type | string | null | 可选 | MIME type of the object |
metadata | object | null | 可选 | Arbitrary user metadata key/value pairs. |
cache_control | string | null | 可选 | Cache-Control header value |
storage_class | string | null | 可选 | Storage class (e.g. standard, infrequent_access)default: "standard" |
idempotency_key | string | null | 可选 | Optional; SDK auto-derives a content-hash key (bucket_id+key+content) when omitted. |
storage.object.set_aclPOST /v1/storage/object/set_acl/{bucket}/{key}Set object access policy. Current supported ACL values are private and signed-only; public/public-read are not supported.
参数 (4)
| 名称 | 类型 | 必填 | 说明 |
|---|---|---|---|
key | string | 必填 | Path parameter. |
bucket | string | 必填 | Path parameter. |
acl | "private" | "signed-only" | 必填 | Access policy. Supported values: private, signed-only. public/public-read are not supported; public_url remains null. |
idempotency_key | string | null | 可选 | Client-provided idempotency key; prevents duplicate execution on retry |
storage.object.set_metadataPOST /v1/storage/object/set_metadata/{bucket}/{key}Update a stored object's content-type, cache-control, and custom metadata; metadata replaces previous metadata.
参数 (6)
| 名称 | 类型 | 必填 | 说明 |
|---|---|---|---|
key | string | 必填 | Path parameter. |
bucket | string | 必填 | Path parameter. |
content_type | string | null | 可选 | MIME type of the object |
cache_control | string | null | 可选 | Cache-Control header value |
metadata | object | null | 可选 | Custom metadata key/value pairs. Passing metadata replaces the previous metadata instead of merging with it; omit metadata to preserve the old value. |
idempotency_key | string | null | 可选 | Client-provided idempotency key; prevents duplicate execution on retry |
4. 完整示例
本模块的生产级端到端范例:先一次性配置,再运行业务流程,尽量覆盖本模块的多数 API。
单文件可运行 Python 程序(仅标准库、无 SDK):拷贝后填入 INFRAI_API_KEY 运行,即可按真实业务流逐步体验本模块核心 API——每一步都真实调用并计费,后续步骤复用前一步返回的真实字段。12 行 helper 就是全部集成代码。
#!/usr/bin/env python3
"""Infrai · storage — 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) storage.bucket.create — POST /v1/storage/bucket/create · Create an object storage bucket. Bucket names must be 3-63 lowercase letters, digits, dots, or hyphens and start/end with a letter or digit; `region` must be a canonical region code.
r1 = show("storage.bucket.create", infrai("POST", "/v1/storage/bucket/create", {"name":"demo-bucket"}))
# 2) storage.object.presign — POST /v1/storage/object/presign/{bucket}/{key} · Generate a presigned URL for direct client upload or download of an object (idempotent). For `op=put`, use the returned URL with its returned method (usually PUT) to upload raw binary bytes directly; do not send the Infrai API key to the presigned URL.
bucket_2 = (r1.get("data") or {}).get("name") or ""
r2 = show("storage.object.presign", infrai("POST", f"/v1/storage/object/presign/{bucket_2}/hello.txt", {"op":"put","expires_seconds":300}))
# 3) storage.bucket.list — GET /v1/storage/bucket/list · List the account's object storage buckets.
r3 = show("storage.bucket.list", infrai("GET", "/v1/storage/bucket/list"))
一次性前置(每个范例都假定已完成):
# No SDK to install — every call is a plain HTTPS request.
# Get a project key by signing in at https://infrai.cc/login (Google/GitHub gives
# you $2 free credit; email sign-in starts at $0). On 402 INSUFFICIENT_CREDIT, add
# funds at https://infrai.cc/billing (or POST /v1/account/topup and open the
# returned checkout_url).
export INFRAI_API_KEY="ifr_..."# 1) Auth: every call is a raw HTTPS request to the Infrai gateway carrying
# only your project key. No SDK, no install.
# Get your key: sign in with Google/GitHub at https://infrai.cc/login for a
# project key + $2 free credit (email sign-in starts at $0). On 402
# INSUFFICIENT_CREDIT, add funds at https://infrai.cc/billing (or POST
# /v1/account/topup and open the returned checkout_url).
export INFRAI_API_KEY="ifr_..." # from https://infrai.cc/login
# 2) storage.bucket.create
curl -X POST https://api.infrai.cc/v1/storage/bucket/create \
-H "Authorization: Bearer $INFRAI_API_KEY" \
-H "Content-Type: application/json" \
-d '{"name": "example"}'
# 3) storage.bucket.list
curl -X GET https://api.infrai.cc/v1/storage/bucket/list \
-H "Authorization: Bearer $INFRAI_API_KEY"
# 4) storage.object.presign
curl -X POST https://api.infrai.cc/v1/storage/object/presign/BUCKET/KEY \
-H "Authorization: Bearer $INFRAI_API_KEY" \
-H "Content-Type: application/json" \
-d '{"bucket_id": "bkt_42", "key": "uploads/photo.jpg", "ttl_seconds": 3600}'
# Use data.url from the response above to upload the file bytes directly.
# Do not include the Infrai Authorization header on this PUT request.
curl -X PUT "PASTE_RETURNED_DATA_URL_HERE" \
-H "Content-Type: application/octet-stream" \
--data-binary @upload.bin
# 5) storage.object.delete
curl -X DELETE https://api.infrai.cc/v1/storage/object/delete/BUCKET/KEY \
-H "Authorization: Bearer $INFRAI_API_KEY"
# 6) storage.bucket.get
curl -X GET https://api.infrai.cc/v1/storage/bucket/get/BUCKET \
-H "Authorization: Bearer $INFRAI_API_KEY"
# 7) storage.bucket.delete
curl -X DELETE https://api.infrai.cc/v1/storage/bucket/delete/BUCKET \
-H "Authorization: Bearer $INFRAI_API_KEY"
# Non-empty buckets require force=true; otherwise the API returns STORAGE_DELETE_NOT_FORCED.
curl -X DELETE https://api.infrai.cc/v1/storage/bucket/delete/BUCKET \
-H "Authorization: Bearer $INFRAI_API_KEY" \
-H "Content-Type: application/json" \
-d '{"force": true}'
# 8) storage.bucket.usage
curl -X GET https://api.infrai.cc/v1/storage/bucket/usage/BUCKET \
-H "Authorization: Bearer $INFRAI_API_KEY"
# 9) storage.bucket.set_lifecycle
curl -X POST https://api.infrai.cc/v1/storage/bucket/set_lifecycle/BUCKET \
-H "Authorization: Bearer $INFRAI_API_KEY" \
-H "Content-Type: application/json" \
-d '{"rules": [{"prefix": "tmp/", "expire_days": 1}]}'
# 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) storage.bucket.create
# 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/storage/bucket/create",
headers={
"Authorization": f"Bearer {os.environ['INFRAI_API_KEY']}",
},
json={'name': 'example'},
)
resp.raise_for_status()
print(resp.json())
# 3) storage.bucket.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/storage/bucket/list",
headers={
"Authorization": f"Bearer {os.environ['INFRAI_API_KEY']}",
},
)
resp.raise_for_status()
print(resp.json())
# 4) storage.object.presign
# 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/storage/object/presign/BUCKET/KEY",
headers={
"Authorization": f"Bearer {os.environ['INFRAI_API_KEY']}",
},
json={'bucket_id': 'bkt_42', 'key': 'uploads/photo.jpg', 'ttl_seconds': 3600},
)
resp.raise_for_status()
print(resp.json())
# Use data['data']['url'] from the response above to upload raw bytes.
# Do not include the Infrai Authorization header on this PUT request.
with open("upload.bin", "rb") as f:
upload_resp = requests.put(resp.json()["data"]["url"], data=f, headers={"Content-Type": "application/octet-stream"})
upload_resp.raise_for_status()
# 5) storage.object.delete
# 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/storage/object/delete/BUCKET/KEY",
headers={
"Authorization": f"Bearer {os.environ['INFRAI_API_KEY']}",
},
)
resp.raise_for_status()
print(resp.json())
# 6) storage.bucket.get
# Zero-install REST call — no SDK required (short-term the API is REST-only).
import os, requests
resp = requests.get(
"https://api.infrai.cc/v1/storage/bucket/get/BUCKET",
headers={
"Authorization": f"Bearer {os.environ['INFRAI_API_KEY']}",
},
)
resp.raise_for_status()
print(resp.json())
# 7) storage.bucket.delete
# 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/storage/bucket/delete/BUCKET",
headers={
"Authorization": f"Bearer {os.environ['INFRAI_API_KEY']}",
},
)
resp.raise_for_status()
print(resp.json())
# Non-empty buckets require force=True; otherwise the API returns STORAGE_DELETE_NOT_FORCED.
resp = requests.delete(
"https://api.infrai.cc/v1/storage/bucket/delete/BUCKET",
headers={"Authorization": f"Bearer {os.environ['INFRAI_API_KEY']}"},
json={"force": True},
)
resp.raise_for_status()
print(resp.json())
# 8) storage.bucket.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/storage/bucket/usage/BUCKET",
headers={
"Authorization": f"Bearer {os.environ['INFRAI_API_KEY']}",
},
)
resp.raise_for_status()
print(resp.json())
# 9) storage.bucket.set_lifecycle
# 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/storage/bucket/set_lifecycle/BUCKET",
headers={
"Authorization": f"Bearer {os.environ['INFRAI_API_KEY']}",
},
json={'rules': [{'prefix': 'tmp/', 'expire_days': 1}]},
)
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) storage.bucket.create
// Zero-install REST call — no SDK required (short-term the API is REST-only).
const resp = await fetch(
"https://api.infrai.cc/v1/storage/bucket/create",
{
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({"name": "example"}),
},
);
console.log(await resp.json());
// 3) storage.bucket.list
// Zero-install REST call — no SDK required (short-term the API is REST-only).
const resp = await fetch(
"https://api.infrai.cc/v1/storage/bucket/list",
{
method: "GET",
headers: {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
},
},
);
console.log(await resp.json());
// 4) storage.object.presign
// Zero-install REST call — no SDK required (short-term the API is REST-only).
const resp = await fetch(
"https://api.infrai.cc/v1/storage/object/presign/BUCKET/KEY",
{
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({"bucket_id": "bkt_42", "key": "uploads/photo.jpg", "ttl_seconds": 3600}),
},
);
console.log(await resp.json());
// Use data.url from the response above to upload raw bytes.
// Do not include the Infrai Authorization header on this PUT request.
const uploadUrl = "PASTE_RETURNED_DATA_URL_HERE";
const { readFile } = await import("node:fs/promises");
const fileBytes = await readFile("upload.bin");
const uploadResp = await fetch(uploadUrl, {
method: "PUT",
headers: { "Content-Type": "application/octet-stream" },
body: fileBytes,
});
if (!uploadResp.ok) throw new Error(`upload ${uploadResp.status}`);
// 5) storage.object.delete
// Zero-install REST call — no SDK required (short-term the API is REST-only).
const resp = await fetch(
"https://api.infrai.cc/v1/storage/object/delete/BUCKET/KEY",
{
method: "DELETE",
headers: {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
},
},
);
console.log(await resp.json());
// 6) storage.bucket.get
// Zero-install REST call — no SDK required (short-term the API is REST-only).
const resp = await fetch(
"https://api.infrai.cc/v1/storage/bucket/get/BUCKET",
{
method: "GET",
headers: {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
},
},
);
console.log(await resp.json());
// 7) storage.bucket.delete
// Zero-install REST call — no SDK required (short-term the API is REST-only).
const resp = await fetch(
"https://api.infrai.cc/v1/storage/bucket/delete/BUCKET",
{
method: "DELETE",
headers: {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
},
},
);
console.log(await resp.json());
// Non-empty buckets require force=true; otherwise the API returns STORAGE_DELETE_NOT_FORCED.
const forceDeleteResp = await fetch(
"https://api.infrai.cc/v1/storage/bucket/delete/BUCKET",
{
method: "DELETE",
headers: {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({ force: true }),
},
);
console.log(await forceDeleteResp.json());
// 8) storage.bucket.usage
// Zero-install REST call — no SDK required (short-term the API is REST-only).
const resp = await fetch(
"https://api.infrai.cc/v1/storage/bucket/usage/BUCKET",
{
method: "GET",
headers: {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
},
},
);
console.log(await resp.json());
// 9) storage.bucket.set_lifecycle
// Zero-install REST call — no SDK required (short-term the API is REST-only).
const resp = await fetch(
"https://api.infrai.cc/v1/storage/bucket/set_lifecycle/BUCKET",
{
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({"rules": [{"prefix": "tmp/", "expire_days": 1}]}),
},
);
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) storage.bucket.create
// Zero-install REST call — no SDK required (short-term the API is REST-only).
const resp = await fetch(
"https://api.infrai.cc/v1/storage/bucket/create",
{
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({"name": "example"}),
},
);
if (!resp.ok) throw new Error(`infrai ${resp.status}`);
const data: unknown = await resp.json();
console.log(data);
// 3) storage.bucket.list
// Zero-install REST call — no SDK required (short-term the API is REST-only).
const resp = await fetch(
"https://api.infrai.cc/v1/storage/bucket/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);
// 4) storage.object.presign
// Zero-install REST call — no SDK required (short-term the API is REST-only).
const resp = await fetch(
"https://api.infrai.cc/v1/storage/object/presign/BUCKET/KEY",
{
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({"bucket_id": "bkt_42", "key": "uploads/photo.jpg", "ttl_seconds": 3600}),
},
);
if (!resp.ok) throw new Error(`infrai ${resp.status}`);
const data: unknown = await resp.json();
console.log(data);
// Use data.url from the response above to upload raw bytes.
// Do not include the Infrai Authorization header on this PUT request.
const uploadUrl = "PASTE_RETURNED_DATA_URL_HERE";
const { readFile } = await import("node:fs/promises");
const fileBytes = await readFile("upload.bin");
const uploadResp = await fetch(uploadUrl, {
method: "PUT",
headers: { "Content-Type": "application/octet-stream" },
body: fileBytes,
});
if (!uploadResp.ok) throw new Error(`upload ${uploadResp.status}`);
// 5) storage.object.delete
// Zero-install REST call — no SDK required (short-term the API is REST-only).
const resp = await fetch(
"https://api.infrai.cc/v1/storage/object/delete/BUCKET/KEY",
{
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);
// 6) storage.bucket.get
// Zero-install REST call — no SDK required (short-term the API is REST-only).
const resp = await fetch(
"https://api.infrai.cc/v1/storage/bucket/get/BUCKET",
{
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) storage.bucket.delete
// Zero-install REST call — no SDK required (short-term the API is REST-only).
const resp = await fetch(
"https://api.infrai.cc/v1/storage/bucket/delete/BUCKET",
{
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);
// Non-empty buckets require force=true; otherwise the API returns STORAGE_DELETE_NOT_FORCED.
const forceDeleteResp = await fetch(
"https://api.infrai.cc/v1/storage/bucket/delete/BUCKET",
{
method: "DELETE",
headers: {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({ force: true }),
},
);
console.log(await forceDeleteResp.json());
// 8) storage.bucket.usage
// Zero-install REST call — no SDK required (short-term the API is REST-only).
const resp = await fetch(
"https://api.infrai.cc/v1/storage/bucket/usage/BUCKET",
{
method: "GET",
headers: {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
},
},
);
if (!resp.ok) throw new Error(`infrai ${resp.status}`);
const data: unknown = await resp.json();
console.log(data);
// 9) storage.bucket.set_lifecycle
// Zero-install REST call — no SDK required (short-term the API is REST-only).
const resp = await fetch(
"https://api.infrai.cc/v1/storage/bucket/set_lifecycle/BUCKET",
{
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.INFRAI_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({"rules": [{"prefix": "tmp/", "expire_days": 1}]}),
},
);
if (!resp.ok) throw new Error(`infrai ${resp.status}`);
const data: unknown = await resp.json();
console.log(data);