Log Query
curl --request GET \
--url https://maas.gravitex.ai/prod-api/api/logs/v2/pageimport requests
url = "https://maas.gravitex.ai/prod-api/api/logs/v2/page"
response = requests.get(url)
print(response.text)const options = {method: 'GET'};
fetch('https://maas.gravitex.ai/prod-api/api/logs/v2/page', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://maas.gravitex.ai/prod-api/api/logs/v2/page",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://maas.gravitex.ai/prod-api/api/logs/v2/page"
req, _ := http.NewRequest("GET", url, nil)
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://maas.gravitex.ai/prod-api/api/logs/v2/page")
.asString();require 'uri'
require 'net/http'
url = URI("https://maas.gravitex.ai/prod-api/api/logs/v2/page")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
response = http.request(request)
puts response.read_bodyInterface module
Log Query
Paginated query for API call logs, consumption logs, top-up logs, and more
GET
/
prod-api
/
api
/
logs
/
v2
/
page
Log Query
curl --request GET \
--url https://maas.gravitex.ai/prod-api/api/logs/v2/pageimport requests
url = "https://maas.gravitex.ai/prod-api/api/logs/v2/page"
response = requests.get(url)
print(response.text)const options = {method: 'GET'};
fetch('https://maas.gravitex.ai/prod-api/api/logs/v2/page', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://maas.gravitex.ai/prod-api/api/logs/v2/page",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://maas.gravitex.ai/prod-api/api/logs/v2/page"
req, _ := http.NewRequest("GET", url, nil)
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://maas.gravitex.ai/prod-api/api/logs/v2/page")
.asString();require 'uri'
require 'net/http'
url = URI("https://maas.gravitex.ai/prod-api/api/logs/v2/page")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
response = http.request(request)
puts response.read_bodyPaginated query for call, consumption, top-up, admin, error, refund, and test-credit logs within the scope of the current credential.
Endpoint
- HTTP method:
GET - URL:
https://maas.gravitex.ai/prod-api/api/logs/v2/page - Auth header:
Authorization - Language header:
Accept-Language; supportszh-CN,en-US - Time format:
yyyy-MM-dd HH:mm:ss - Max time range: 31 days
- Default pagination:
page=1,pageSize=30 - Max page size: 1000
Authentication
All of the following formats are supported:Authorization: Bearer sk-your_api_key
Authorization: sk-your_api_key
| Credential | Query scope | tokenName behavior |
|---|---|---|
| System access token | Logs for that user | Uses request tokenName with fuzzy match |
| API Key | Logs for that user belonging to the current API Key | Server forces an exact match on the current API Key name; request tokenName is ignored |
Do not log full keys in URLs, frontend code, logs, or support tickets.
Query parameters
integer
default:"1"
Page number; values ≤ 0 are treated as 1
integer
default:"30"
Page size; values ≤ 0 are treated as 30; max 1000
string
API key name. Fuzzy match when authenticated with a system access token; unavailable for API key auth — the server always returns logs for the current API key only
string
Model name, exact match; comma-separated for multiple models
string
Request ID, exact match
string
Request IP, exact match
integer
Minimum duration in seconds, inclusive
integer
Maximum duration in seconds, inclusive
string
Start time, format
yyyy-MM-dd HH:mm:ss, inclusivestring
End time, format
yyyy-MM-dd HH:mm:ss, inclusivestring
Log types, comma-separated; allowed values:
1,2,3,5,6,8Log types
| Value | Type |
|---|---|
1 | Top-up |
2 | Consumption |
3 | Admin |
5 | Error |
6 | Refund |
8 | Test credit |
Accept-Language
Affects onlybillingProcessText:
| Header | Language |
|---|---|
Accept-Language: zh-CN | Chinese |
Accept-Language: en-US | English |
| Omitted or other values | Chinese |
Request examples
- curl
- JavaScript
- Python
curl --get 'https://maas.gravitex.ai/prod-api/api/logs/v2/page' \
--header 'Authorization: Bearer your_api_key' \
--header 'Accept-Language: en-US' \
--data-urlencode 'page=1' \
--data-urlencode 'pageSize=30' \
--data-urlencode 'startTime=2026-07-01 00:00:00' \
--data-urlencode 'endTime=2026-07-21 23:59:59' \
--data-urlencode 'types=2,5'
const params = new URLSearchParams({
page: '1',
pageSize: '30',
startTime: '2026-07-01 00:00:00',
endTime: '2026-07-21 23:59:59',
types: '2,5',
});
const response = await fetch(
`https://maas.gravitex.ai/prod-api/api/logs/v2/page?${params}`,
{
method: 'GET',
headers: {
Authorization: 'Bearer your_api_key',
'Accept-Language': 'en-US',
},
},
);
const result = await response.json();
if (result.code !== 200) {
throw new Error(result.msg);
}
console.log(result.data.total, result.data.rows);
import requests
url = "https://maas.gravitex.ai/prod-api/api/logs/v2/page"
headers = {
"Authorization": "Bearer your_api_key",
"Accept-Language": "en-US",
}
params = {
"page": 1,
"pageSize": 30,
"startTime": "2026-07-01 00:00:00",
"endTime": "2026-07-21 23:59:59",
"types": "2,5",
}
response = requests.get(url, headers=headers, params=params, timeout=30)
response.raise_for_status()
result = response.json()
if result.get("code") != 200:
raise RuntimeError(result.get("msg"))
print("Total records:", result["data"]["total"])
for item in result["data"]["rows"]:
print(item["requestId"], item["modelName"], item["quotaDollar"])
Response structure
{
"code": 200,
"msg": "操作成功",
"data": {
"total": 1,
"rows": [
{
"id": "7485162150730129409",
"createdAt": 1784601721,
"createTime": "2026-07-21 10:42:01",
"type": 2,
"requestId": "request_example_001",
"ip": "203.0.113.10",
"requestPath": "/v1/messages",
"isStream": 1,
"streamStatus": "正常 (eof)",
"useTime": 2,
"firstTokenTime": 1043,
"modelName": "claude-sonnet-5",
"tokenName": "default",
"quotaDollar": "0.006098",
"quotaDollarOrigin": "0.006098",
"billingType": "token_ratio",
"billingCountMode": "上游返回",
"requestConversion": "Claude Messages",
"textInputTokens": 2804,
"textOutputTokens": 49,
"cacheCreationTokens5m": null,
"cacheCreationTokens1h": null,
"cacheTokens": 0,
"audioInput": null,
"audioOutput": null,
"imageInputTokens": null,
"imageOutputTokens": null,
"videoOutputTokens": null,
"requestedSeconds": null,
"imageCount": null,
"videoResolution": null,
"videoAudio": null,
"videoHasInputVideo": null,
"toolCallBilling": null,
"billingProcessText": "Input price: ..., final cost: $0.006098"
}
]
}
}
quotaDollar is returned as a decimal string. Use Decimal/BigDecimal; avoid binary floating-point.Response fields
| Field | Type | Description |
|---|---|---|
code | integer | 200 = success, 401 = auth failure |
msg | string | Message |
data.total | integer | Total matching records (not page count) |
data.rows | array | Current page rows |
id | string/long | Log ID; treat as string on the client |
createdAt | integer | Unix timestamp in seconds |
createTime | string | Formatted creation time |
type | integer | Log type |
requestId | string/null | Request ID |
ip | string/null | Request IP |
requestPath | string/null | Request path |
isStream | integer/null | Whether streaming |
streamStatus | string/null | Stream status |
useTime | integer/null | Total duration in seconds |
firstTokenTime | integer/null | Time to first token in ms |
modelName | string/null | Model name |
tokenName | string/null | Token name |
quotaDollar | decimal/null | Actual cost (discounted price), in USD |
quotaDollarOrigin | decimal/null | Original price, in USD |
billingType | string/null | Billing type |
billingCountMode | string/null | Billing count mode |
requestConversion | string/null | Request protocol conversion |
textInputTokens | integer/null | Text input tokens |
textOutputTokens | integer/null | Text output tokens |
cacheCreationTokens5m | integer/null | 5-minute cache creation tokens |
cacheCreationTokens1h | integer/null | 1-hour cache creation tokens |
cacheTokens | integer/null | Cache hit tokens |
audioInput | integer/null | Audio input metering |
audioOutput | integer/null | Audio output metering |
imageInputTokens | integer/null | Image input tokens |
imageOutputTokens | integer/null | Image output tokens |
videoOutputTokens | integer/null | Video output tokens |
requestedSeconds | integer/null | Requested duration in seconds |
imageCount | integer/null | Image count |
videoResolution | string/null | Video resolution |
videoAudio | boolean/null | Whether audio is output |
videoHasInputVideo | boolean/null | Whether input video is included |
toolCallBilling | array/null | Tool call billing details |
billingProcessText | string/null | Billing breakdown per Accept-Language |
Error responses
- Missing or invalid Authorization
- Empty key
- Invalid or disabled key
- Invalid time format
- Range exceeds 31 days
{
"code": 401,
"msg": "Authorization header missing or invalid",
"data": null
}
{
"code": 401,
"msg": "Authorization key is empty",
"data": null
}
{
"code": 401,
"msg": "无效或已禁用的密钥",
"data": null
}
{
"code": 500,
"msg": "startTime 格式错误,请使用 yyyy-MM-dd HH:mm:ss",
"data": null
}
{
"code": 500,
"msg": "时间范围不能超过1个月",
"data": null
}
Recommendations
- Store access tokens or API keys securely on the server; never log full keys.
- Prefer a time range of at most 31 days.
- Read
data.totalwhen paging — do not treat it as a page count. - Check response body
code; do not rely on HTTP 200 alone. - Handle amounts with Decimal/BigDecimal; do not recompute with binary floats.
