Open API

تصدير تفاصيل الاستخدام

دليل تصدير استخدام LMU AI: سجّل الدخول للحصول على JWT، ثم استدعِ /api/v1/usage مع الترقيم والنطاق الزمني وتصفية النموذج، مع أمثلة بثلاث لغات.

سجّل الدخول بحسابك وكلمة المرور للحصول على JWT، ثم استخدم هذا الـ JWT لاستدعاء /api/v1/usage وسحب جدول تفاصيل استخدام الرموز الكامل، المطابق لصفحة /usage في وحدة التحكم.

مثالي للسكربتات طويلة الأمد التي تؤتمت التصدير والمطابقة والتحميل إلى أنظمة BI المؤسسية — دون الحاجة إلى تنزيل ملف CSV يدويًا في كل مرة.

لماذا لا يمكنك سحبها مباشرةً باستخدام مفتاح API من نوع sk-...؟ المفتاح مخصص فقط لاستدعاءات أعمال البوابة (/v1/messages، إلخ) ولا يكشف استعلامات التفاصيل على مستوى الحساب — وهذا تصميم أمني متعمّد: إذا تسرّب مفتاح، فأنت لا تريد أن تُكشف فاتورتك بالكامل. يجب أن تستخدم البيانات على مستوى الحساب مصادقة الحساب (JWT).


1. نظرة عامة على الواجهة

العنصرالقيمة
Base URLhttps://api.lmuai.com
المصادقةAuthorization: Bearer <access_token> (الـ JWT من تسجيل دخول الحساب)
صلاحية رمز الوصول86400 ثانية (24 ساعة)، قابل للتجديد باستخدام refresh_token
تنسيق الاستجابةJSON؛ code: 0 يعني النجاح، وعند الفشل code != 0 مع حقل message
الاستخدام المُوصى بهتصدير الفوترة المؤتمت، التحميل إلى أنظمة BI المؤسسية، سكربتات المطابقة

2. الخطوة 1 — سجّل الدخول للحصول على JWT

POST /api/v1/auth/login

POST /api/v1/auth/login HTTP/1.1
Content-Type: application/json

{
  "email": "your@email.com",
  "password": "your-password"
}

الاستجابة (مقتطف):

{
  "code": 0,
  "message": "success",
  "data": {
    "access_token": "eyJhbGc...",
    "refresh_token": "rt_756a220ffa...",
    "expires_in": 86400,
    "token_type": "Bearer",
    "user": { "id": 3, "email": "...", "balance": 1575.13 }
  }
}

جميع الطلبات اللاحقة تتضمّن فقط Authorization: Bearer <access_token>.


3. الخطوة 2 — اسحب تفاصيل الاستخدام

GET /api/v1/usage

GET /api/v1/usage?page=1&page_size=200&start_date=2026-06-01&end_date=2026-06-23&timezone=Asia/Shanghai
Authorization: Bearer <access_token>

معاملات الاستعلام

المعاملالنوعمطلوبالافتراضيالوصف
pageintلا1رقم الصفحة، يبدأ من 1
page_sizeintلا20عدد الصفوف لكل صفحة، يُوصى بـ 200 (القيم المفرطة تُقتطع)
start_datestringلاتاريخ البداية YYYY-MM-DD، يُحلَّل حسب timezone
end_datestringلاتاريخ النهاية (شامل ذلك اليوم)
timezonestringلاUTCالمنطقة الزمنية لتحليل معاملات التاريخ، مثل Asia/Shanghai؛ يُوصى بها بشدة، وإلا فلن تتطابق الحدود مع وقتك المحلي
api_key_idintلاعرض تفاصيل مفتاح واحد فقط (يجب أن يكون ملكًا للمستخدم الحالي)
modelstringلاالتصفية حسب معرّف النموذج (مثل claude-sonnet-5)
streamboolلاtrue للبثّي فقط، false لغير البثّي فقط
billing_typeintلاقائمة تعداد نوع الفوترة (انظر أدناه)
sort_bystringلاcreated_atحقل الترتيب
sort_orderstringلاdescasc أو desc

بنية الاستجابة

{
  "code": 0,
  "message": "success",
  "data": {
    "items": [ { /* UsageLog */ }, ... ],
    "total": 30423,
    "page": 1,
    "page_size": 200,
    "pages": 153
  }
}

حقول الترقيم موجودة في المستوى الأعلى من data، وليست في الغلاف الخارجي. مصفوفة التفاصيل موجودة في data.items — أي أن data ليست مصفوفة بحدّ ذاتها.

تعيين الحقول لسجل واحد

تقابل هذه بالضبط كل عمود من أعمدة صفحة /usage في وحدة التحكم:

عمود وحدة التحكمحقل JSONالنوعالوصف
النموذجmodelstringمعرّف النموذج الذي تمّت فوترته فعليًا
جهد الاستدلالreasoning_effortstring | nulllow / medium / high / xhigh / max
نقطة النهاية الواردةinbound_endpointstring | nullالمسار الذي استدعاه العميل، مثل /v1/messages
نقطة النهاية العلويةupstream_endpointstring | nullالمسار العلوي المُطبَّع
نوع الطلبrequest_typestringchat / stream / responses / messages، إلخ
البثّstreamboolهل كان بثيًا
وضع الفوترةbilling_modestringtoken / per_request / image / subscription
نوع الفوترةbilling_typeintقائمة تعداد نوع الفوترة
المضاعِفrate_multiplierfloatمضاعِف القناة المُطبَّق على هذا الطلب
رموز الإدخالinput_tokensint
رموز الإخراجoutput_tokensint
إنشاء الذاكرة المؤقتةcache_creation_tokensintجميع عمليات الكتابة إلى الذاكرة المؤقتة
إنشاء الذاكرة المؤقتة 5mcache_creation_5m_tokensintطبقة Anthropic العابرة لمدة 5 دقائق
إنشاء الذاكرة المؤقتة 1hcache_creation_1h_tokensintطبقة Anthropic لمدة ساعة واحدة
قراءة الذاكرة المؤقتةcache_read_tokensint
تكلفة الإدخالinput_costfloatUSD
تكلفة الإخراجoutput_costfloatUSD
تكلفة إنشاء الذاكرة المؤقتةcache_creation_costfloatUSD
تكلفة قراءة الذاكرة المؤقتةcache_read_costfloatUSD
الإجمالي بسعر القائمةtotal_costfloatUSD، قبل المضاعِف
الرسم الفعليactual_costfloat= total_cost × rate_multiplier، ما يُخصم فعليًا من رصيدك
زمن الرمز الأولfirst_token_msint | nullTTFT، صالح للبثّ
المدة الإجماليةduration_msint | null
الوقتcreated_atISO8601وقت الكتابة على جانب الخادم
معرّف الطلبrequest_idstringلاستكشاف الأخطاء وتتبعها
توليد الصورimage_count / image_size / image_output_tokens / image_output_costيُملأ فقط للطلبات متعددة الوسائط
مفتاح APIapi_key_id + كائن api_key المتداخلint + obj
المجموعةgroup_id + كائن group المتداخلint + obj

يحمل كل سجل كائنات user / api_key / group متداخلة (حوالي +1KB لكل صف). يحتوي كائن api_key على النص الكامل للمفتاح — احرص على إخفائه في سجلات السكربت / لقطات الشاشة / ملفات CSV؛ وللتصدير بالجملة، إذا لم تكن بحاجة إلى الكائنات المتداخلة، استخدم jq أو تعيين الحقول على جانب العميل للاحتفاظ فقط بالحقول التي تحتاجها.

قائمة تعداد نوع الفوترة (billing_type)

القيمةالمعنى
0الفوترة بالرمز (الغالبية العظمى من الطلبات)
1خصم من حصة الاشتراك

حقل billing_mode هو النسخة النصية، ويصف نموذج التسعير المحدد (token / per_request / image / subscription، إلخ)؛ وهو أسهل قراءةً ويُوصى به للتصنيف.


4. تجديد الرمز

تنتهي صلاحية رمز الوصول بعد 24 ساعة. هناك طريقتان لتجديده:

التجديد باستخدام refresh_token (يُوصى به للسكربتات)

POST /api/v1/auth/refresh
Content-Type: application/json

{
  "refresh_token": "rt_756a220ffa..."
}

يُعيد access_token جديدًا (وعادةً يُدوّر refresh_token أيضًا). صلاحية رمز التحديث 30 يومًا.

تسجيل الدخول مجددًا

طريقة بدائية لكنها بسيطة، مناسبة للسكربتات لمرة واحدة: استدعِ /auth/login مجددًا قبل كل تشغيل.


5. أمثلة برمجية

Bash + curl + jq

#!/usr/bin/env bash
set -e

EMAIL="${EMAIL:?set EMAIL env}"
PASSWORD="${PASSWORD:?set PASSWORD env}"
BASE="https://api.lmuai.com"

JWT=$(curl -s -X POST "$BASE/api/v1/auth/login" \
  -H "Content-Type: application/json" \
  -d "{\"email\":\"$EMAIL\",\"password\":\"$PASSWORD\"}" \
  | jq -r '.data.access_token')

[ -n "$JWT" ] && [ "$JWT" != "null" ] || { echo "login failed" >&2; exit 1; }

START="2026-06-01"; END="2026-06-30"; TZ="Asia/Shanghai"; PAGE_SIZE=200

# Fetch page 1 to get total
META=$(curl -s "$BASE/api/v1/usage?page=1&page_size=$PAGE_SIZE&start_date=$START&end_date=$END&timezone=$TZ" \
  -H "Authorization: Bearer $JWT")
PAGES=$(echo "$META" | jq -r '.data.pages')

# CSV header
echo "created_at,model,request_type,input_tokens,output_tokens,cache_read_tokens,total_cost,actual_cost,duration_ms" > usage.csv

# Write page 1
echo "$META" | jq -r '.data.items[] | [.created_at, .model, .request_type, .input_tokens, .output_tokens, .cache_read_tokens, .total_cost, .actual_cost, .duration_ms] | @csv' >> usage.csv

# Fetch remaining pages
for ((p=2; p<=PAGES; p++)); do
  curl -s "$BASE/api/v1/usage?page=$p&page_size=$PAGE_SIZE&start_date=$START&end_date=$END&timezone=$TZ" \
    -H "Authorization: Bearer $JWT" \
    | jq -r '.data.items[] | [.created_at, .model, .request_type, .input_tokens, .output_tokens, .cache_read_tokens, .total_cost, .actual_cost, .duration_ms] | @csv' >> usage.csv
done

echo "saved $(wc -l < usage.csv) lines to usage.csv"

Python

import os, csv, requests

BASE = "https://api.lmuai.com"
EMAIL = os.environ["EMAIL"]
PASSWORD = os.environ["PASSWORD"]

def login() -> str:
    r = requests.post(f"{BASE}/api/v1/auth/login",
                      json={"email": EMAIL, "password": PASSWORD},
                      timeout=15)
    r.raise_for_status()
    data = r.json()
    if data["code"] != 0:
        raise RuntimeError(data.get("message", "login failed"))
    return data["data"]["access_token"]

def fetch_usage(jwt: str, **params):
    """Yield each row from paginated /usage endpoint."""
    page = 1
    while True:
        r = requests.get(f"{BASE}/api/v1/usage",
                         headers={"Authorization": f"Bearer {jwt}"},
                         params={**params, "page": page, "page_size": 200},
                         timeout=30)
        r.raise_for_status()
        d = r.json()["data"]
        for row in d.get("items", []):
            yield row
        if page >= d.get("pages", 1):
            return
        page += 1

if __name__ == "__main__":
    jwt = login()
    cols = ["created_at","model","request_type","input_tokens","output_tokens",
            "cache_read_tokens","total_cost","actual_cost","duration_ms"]
    with open("usage.csv", "w", newline="") as f:
        w = csv.writer(f); w.writerow(cols)
        for row in fetch_usage(jwt, start_date="2026-06-01", end_date="2026-06-30",
                               timezone="Asia/Shanghai"):
            w.writerow([row.get(c) for c in cols])
    print("done")

Node.js

import fs from 'node:fs'

const BASE = 'https://api.lmuai.com'
const { EMAIL, PASSWORD } = process.env

async function login() {
  const r = await fetch(`${BASE}/api/v1/auth/login`, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ email: EMAIL, password: PASSWORD }),
  })
  const j = await r.json()
  if (j.code !== 0) throw new Error(j.message || 'login failed')
  return j.data.access_token
}

async function* fetchUsage(jwt, params) {
  for (let page = 1; ; page++) {
    const q = new URLSearchParams({ ...params, page, page_size: '200' })
    const r = await fetch(`${BASE}/api/v1/usage?${q}`, {
      headers: { Authorization: `Bearer ${jwt}` },
    })
    const j = await r.json()
    for (const row of j.data.items) yield row
    if (page >= j.data.pages) return
  }
}

const jwt = await login()
const cols = ['created_at','model','request_type','input_tokens','output_tokens',
              'cache_read_tokens','total_cost','actual_cost','duration_ms']
const out = fs.createWriteStream('usage.csv')
out.write(cols.join(',') + '\n')
for await (const row of fetchUsage(jwt, {
  start_date: '2026-06-01', end_date: '2026-06-30', timezone: 'Asia/Shanghai',
})) {
  out.write(cols.map(c => JSON.stringify(row[c] ?? '')).join(',') + '\n')
}
console.log('done')

6. ملاحظات عملية

  1. أضف تأخيرًا بين تقليب الصفحات بالجملة — عند تصفح N صفحة على التوالي، يُوصى بـ sleep(0.1~0.3s) لتجنّب تفعيل حدود المعدل.
  2. لا تسحب نطاقًا زمنيًا طويلًا جدًا دفعة واحدة — امتداد عدة أشهر وملايين الصفوف بطيء. التقطيع حسب الشهر أكثر استقرارًا.
  3. يُوصى بـ page_size قدره 200 — يقتطع الخادم القيم المفرطة.
  4. وفّر عرض النطاق الترددي — الكائنات المتداخلة user / api_key / group كبيرة؛ إذا كنت تريد صفوف التفاصيل فقط، صفّها باستخدام jq على جانب العميل.
  5. الأخطاء الشائعة:
    • 401 انتهت صلاحية الـ JWT → جدّد باستخدام refresh_token أو سجّل الدخول مجددًا
    • 403 وصول غير مصرّح به (مثل الاستعلام عن مفتاح شخص آخر عبر api_key_id) → تحقّق من أن المفتاح يخصّ المستخدم الحالي
    • 400 معامل خاطئ (مثل تنسيق start_date) → تحقّق من صحة YYYY-MM-DD + timezone

7. توصيات الأمان (يجب قراءتها)

كلمة مرور حسابك + الـ JWT تعادلان الوصول الكامل إلى الحساب. قبل كتابة سكربت للتصدير، تأكّد من:

العنصرالتوصية
إدارة بيانات الاعتمادلا تُدرج أبدًا كلمة المرور / access_token / refresh_token في git أو سجلات CI؛ استخدم متغيرات البيئة، أو مدير أسرار، أو .env (مع .gitignore)
أمان الحسابيُوصى بشدة بتفعيل المصادقة الثنائية TOTP (فعّلها في إعدادات الحساب). تدعم هذه الواجهة التحقق عبر TOTP أثناء تسجيل الدخول
التدوير الدوريغيّر كلمة مرور حسابك بانتظام؛ ودوّر refresh_token فورًا بعد انتهاء صلاحيته
مراقبة الشذوذراقب "آخر وقت / عنوان IP لتسجيل الدخول" في الحساب؛ وغيّر كلمة المرور فورًا إذا لاحظت جهازًا غير مألوف
إخفاء الحقولإن api_key.key المتداخل (نص sk-... الكامل)، وuser.email، وrefresh_token في الاستجابة كلها حقول حساسة — أخفِها قبل الإخراج / السجلات / ملفات CSV
أقل امتيازإن أمكنك الفصل، استخدم حسابًا فرعيًا مخصصًا لسكربت التصدير (إذا كانت لمؤسستك بنية متعددة الحسابات) لتجنّب التعرّض طويل الأمد للحساب الرئيسي
إعادة المحاولة عند الأخطاءلا تُعِد المحاولة إلى ما لا نهاية عند فشل تسجيل الدخول — فهذا يفعّل ضوابط المخاطر بسهولة؛ يُوصى بالتراجع الأسّي

8. مرجع سريع للحقول

مفيد لتعيين أعمدة CSV:

التسميةالحقلالوحدة
النموذجmodel
جهد الاستدلالreasoning_effort
نقطة النهاية الواردةinbound_endpointpath
نقطة النهاية العلويةupstream_endpointpath
نوع الطلبrequest_typeenum
البثّstreambool
وضع الفوترةbilling_modeenum
نوع الفوترةbilling_typeint
المضاعِفrate_multiplierfloat
رموز الإدخالinput_tokensint
رموز الإخراجoutput_tokensint
رموز قراءة الذاكرة المؤقتةcache_read_tokensint
رموز كتابة الذاكرة المؤقتةcache_creation_tokensint
كتابة الذاكرة المؤقتة 5mcache_creation_5m_tokensint
كتابة الذاكرة المؤقتة 1hcache_creation_1h_tokensint
تكلفة الإدخالinput_costUSD
تكلفة الإخراجoutput_costUSD
تكلفة إنشاء الذاكرة المؤقتةcache_creation_costUSD
تكلفة قراءة الذاكرة المؤقتةcache_read_costUSD
الإجمالي بسعر القائمةtotal_costUSD
الرسم الفعليactual_costUSD
الرمز الأولfirst_token_msms
المدة الإجماليةduration_msms
الوقتcreated_atISO8601
معرّف الطلبrequest_idstring
المجموعةgroup_id / group.nameint / string
مفتاح APIapi_key_id / api_key.nameint / string

آخر تحديث:

في هذه الصفحة