نِت اَرز · مستندات API هوش مصنوعی
همهٔ مستندات
مدل‌ها و قیمت‌ها مرجع تعاملی دریافت کلید

API مدیریت پروژه‌ها و کلیدها

برای هر کاربر محصول خودتان با کد یک پروژه و یک کلید API با سقف هزینه و تاریخ انقضای مشخص بسازید، سقف و انقضا را تغییر دهید، کلید را بچرخانید یا باطل کنید؛ با نمونه‌کد PHP، Node.js و Python.

base_url: https://netarz.ir/api/ai/v1 به‌روزرسانی: 1405/08/13

اگر محصولی دارید که کاربر ثبت‌نام می‌کند و هر کاربر باید به هوش مصنوعی دسترسی داشته باشد، لازم نیست برایشان در پنل نِت اَرز دستی پروژه و کلید بسازید. با API مدیریت پروژه‌ها و کلیدها سرور خودتان، همان لحظهٔ ثبت‌نام، یک پروژه و یک کلید با مبلغ مشخص و تاریخ انقضای مشخص می‌سازد، و بعداً هم همان مبلغ و تاریخ را از پنل خودتان تغییر می‌دهد، کلید را مکث یا باطل می‌کند و مصرف هر کاربر را می‌خواند.

این API برای چه کاری است؟

  • یک پروژه و یک کلید برای هر کاربر محصول شما. شناسهٔ کاربر خودتان را در external_id می‌گذارید و هر وقت لازم شد، با همان پیدایش می‌کنید.
  • مبلغ و انقضا را شما تعیین می‌کنید. کلید هر کاربر یک سقف هزینه (دلار) و، اگر بخواهید، یک تاریخ انقضا دارد؛ هر دو را بعداً عوض می‌کنید یا مبلغی به سقف اضافه می‌کنید.
  • کاربر شما کلید مدل را می‌گیرد، نه کلید مدیریت. کلیدی که ساخته می‌شود همان کلید معمولی sk-ntz-v1-… است و با درگاه مدل‌ها کار می‌کند؛ مثل هر کلید دیگر.
  • همهٔ هزینه از اعتبار حساب خودتان کم می‌شود. سقف هر کلید فقط نشان می‌دهد آن کاربر حداکثر چقدر خرج کند؛ اگر اعتبار حساب شما تمام شود، همهٔ کلیدها خطای اعتبار می‌گیرند.
فرق با ساختن کلید در پنل

کلیدی که در پنل می‌سازید برای کار خودتان است. این API برای ساختن «تعداد زیاد» کلید با کد است: هر پروژه‌ای که با آن بسازید در پنل هم دیده می‌شود و با برچسب «ساخته‌شده با API مدیریت» از پروژه‌های دستی جدا می‌ماند.

مدل امنیتی

این API با یک نوع کلید جدا کار می‌کند، کلید مدیریت. دو نوع کلید هیچ‌وقت جابه‌جا نمی‌شوند:

کلید مدلکلید مدیریت
پیشوندsk-ntz-v1-sk-ntz-mgmt-v1-
کارشصدا زدن مدل‌ها (گفت‌وگو، تصویر، صدا، …)ساختن و تغییر پروژه و کلید
مدل را صدا می‌زند؟بلهنه؛ درگاه مدل‌ها آن را نمی‌شناسد و 401 invalid_api_key می‌دهد
این API را صدا می‌زند؟نه؛ 401 invalid_api_keyبله
کجا نگه‌داری شود؟در برنامه یا نزد کاربرِ خودتانفقط روی سرور شما
کلید مدیریت را فقط روی سرور خودتان نگه دارید

آن را در اپ موبایل، صفحهٔ وب، فایل جاوااسکریپت یا مخزن کد نگذارید. هر کس آن را داشته باشد از طرف حساب شما کلید می‌سازد، و هر کلید از اعتبار شما خرج می‌کند. گیسو درخواست مرورگر به /api/v1/* را هم می‌پذیرد؛ یعنی فراخوانی از مرورگر ممکن است، ولی هرگز درست نیست.

یک کلید مدیریت به چه چیزهایی دست می‌زند؟

  • فقط پروژه‌های ساخته‌شده با همین API. پروژه‌ها و کلیدهایی که خودتان در پنل ساخته‌اید، کلیدهای سیستمی و کلیدهای کانال‌ها برای این API وجود ندارند (۴۰۴). شناسهٔ حساب دیگران هم همین‌طور؛ هیچ‌وقت ۴۰۳ نمی‌بینید که وجود شناسه لو برود.
  • همهٔ کلیدهای مدیریت یک حساب، همان پروژه‌ها را مدیریت می‌کنند. اگر کلید مدیریت را عوض یا باطل کنید، هیچ پروژه‌ای بی‌صاحب نمی‌شود.
  • نمی‌تواند مدل صدا بزند، کیف پول و پرداخت و تیکت‌ها را ببیند، تنظیمات حساب را عوض کند، یا اعتبار را جابه‌جا کند. فقط موجودی و شمارش‌های کلی حساب را می‌خواند (GET /account).
  • می‌تواند پروژه و کلید بسازد، سقف و انقضا را تغییر دهد و کلید را بچرخاند. چون هر کلید از اعتبار شما خرج می‌کند، اگر کلید مدیریتی لو رفت، همان لحظه آن را در پنل باطل کنید و پروژه‌های تازه‌ساخته‌شده را بررسی کنید. کلیدهایی که پیش‌تر ساخته است، با خودِ این API یا از پنل باطل می‌شوند.

چند عادت خوب

  • فهرست IP مجاز را در پنل برای کلید مدیریت پر کنید (IP سرور). درخواست از جای دیگر 403 ip_not_allowed می‌گیرد.
  • برای هر محیط (آزمایشی، واقعی) یک کلید مدیریت جدا بسازید. تا ۵ کلید فعال دارید.
  • کلید را در متغیر محیطی یا گنجینهٔ رمز سرور نگه دارید، نه در کد؛ در لاگ هم چاپش نکنید.
  • چرخش: کلید مدیریت تازه بسازید، سرور را به آن ببرید، بعد کلید قدیمی را باطل کنید. چون پروژه‌ها به حساب وابسته‌اند، چیزی از دست نمی‌رود.
  • کلید مدلی که می‌سازید را فقط یک بار می‌بینید. آن را رمزنگاری‌شده در پایگاه دادهٔ خودتان نگه دارید یا همان لحظه به کاربر بدهید.

گرفتن کلید مدیریت

  1. وارد پنل شوید در نِت اَرز وارد حساب خود شوید و از پنل کاربری API هوش مصنوعی را باز کنید. حساب API باید فعال و اعتبارش شارژ باشد.
  2. کلید مدیریت تازه بسازید در بخش کلیدهای مدیریت (نشانی https://netarz.ir/ai/management) نام کلید را بنویسید (مثلاً backend-prod)، آدرس‌های IP مجاز را بگذارید (اختیاری، ولی توصیه می‌شود)، اگر می‌خواهید خودِ کلید مدیریت هم منقضی شود تعداد روز را بنویسید (اختیاری) و «ساخت کلید مدیریت» را بزنید. هر حساب تا ۵ کلید مدیریت فعال دارد. در همان صفحه بعداً فهرست کلیدها (شکل کوتاه‌شده، آخرین استفاده و IP)، دکمهٔ باطل‌کردن و آخرین رویدادهای ثبت‌شده با این API را می‌بینید.
  3. کلید را همان لحظه کپی کنید کلید فقط همین یک بار کامل نشان داده می‌شود و با sk-ntz-mgmt-v1- شروع می‌شود. بعداً فقط شکل کوتاه‌شده‌اش را می‌بینید. اگر گم شد، کلید را باطل و کلید تازه بسازید.

نشانی و احراز هویت

نشانی پایه
نِت اَرزhttps://netarz.ir/api/ai/v1/manage
گیسوhttps://gisoo.pro/api/v1/manage

رفتار هر دو نشانی یکی است و یک کلید مدیریت روی هر دو کار می‌کند، چون حساب، اعتبار و کلیدها یکی است. کلیدی که می‌سازید پیشوند سایتی را می‌گیرد که صدایش زده‌اید (sk-ntz-v1- یا sk-gisoo-v1-). در این صفحه از نشانی نِت اَرز استفاده شده است.

  • هدر Authorization: Bearer <کلید مدیریت> (یا X-API-Key) در هر درخواست.
  • بدنهٔ درخواست‌های POST و PATCH JSON باشد و Content-Type: application/json داشته باشد.
  • پاسخ‌ها application/json; charset=utf-8 هستند. پول همه‌جا رشتهٔ دلاری با شش رقم اعشار است ("5.000000") تا گردشدن عدد اعشاری پیش نیاید؛ زمان‌ها ISO-8601 با منطقهٔ زمانی.
  • همهٔ مبلغ‌هایی که می‌فرستید دلار است: spend_limit_usd، monthly_budget_usd و spend_limit_add_usd. عدد یا رشته هر دو پذیرفته می‌شود؛ رشته را ترجیح بدهید.

موجودی و وضعیت حساب

GET/api/ai/v1/manage/accountنیازمند کلید مدیریت

برای آزمایش کلید و پایش موجودی، پیش از هر کاری یک بار این را صدا بزنید. همان موجودی را برمی‌گرداند که GET /me نشان می‌دهد، به‌همراه شمارش پروژه‌ها و کلیدهای این API و سقف‌های کاری.

cURL
curl https://netarz.ir/api/ai/v1/manage/account \
  -H "Authorization: Bearer $NETARZ_MANAGEMENT_KEY"
پاسخ
{
  "object": "management_account",
  "balance": {
    "usd": "48.120000",
    "usd_display": "$48.1200",
    "toman_estimate": 6015000,
    "bonus_usd": "0.000000",
    "bonus_expires_at": null
  },
  "totals": { "topup_usd": "100.000000", "spent_usd": "51.880000" },
  "status": "active",
  "management_key": {
    "id": 4,
    "object": "management_key",
    "name": "backend-prod",
    "masked": "sk-ntz-mgmt-v1-Q…bD1v",
    "allowed_ips": ["203.0.113.10"],
    "expires_at": null,
    "last_used_at": "2026-11-04T09:12:44+00:00",
    "last_used_ip": "203.0.113.10",
    "revoked_at": null,
    "created_at": "2026-11-01T08:00:00+00:00"
  },
  "counts": { "managed_projects": 318, "live_keys": 335 },
  "limits": {
    "max_managed_projects": 10000,
    "max_keys_per_project": 10,
    "max_management_keys": 5,
    "rate_limit_per_minute": 300,
    "max_key_lifetime_days": 3650,
    "max_usage_range_days": 92,
    "idempotency_ttl_hours": 24
  }
}

ثبت‌نام کاربر: یک پروژه و یک کلید در یک درخواست

این مهم‌ترین کار این API است. وقتی کاربری در محصول شما ثبت‌نام کرد، سرور شما یک درخواست می‌فرستد؛ پروژه و کلیدش در یک تراکنش ساخته می‌شوند، یعنی یا هر دو ساخته می‌شوند یا هیچ‌کدام. پاسخ شامل key.secret است؛ همان را به کاربر می‌دهید یا رمزنگاری‌شده کنار کاربر ذخیره می‌کنید.

POST/api/ai/v1/manage/projectsنیازمند کلید مدیریت
cURL
curl -X POST https://netarz.ir/api/ai/v1/manage/projects \
  -H "Authorization: Bearer $NETARZ_MANAGEMENT_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: signup-1042" \
  -d '{
    "name": "Ali Rezaei",
    "external_id": "user-1042",
    "description": "Free plan",
    "metadata": { "plan": "free" },
    "monthly_budget_usd": null,
    "key": {
      "name": "main",
      "spend_limit_usd": "5.00",
      "expires_in_days": 30
    }
  }'
پاسخ
HTTP/1.1 201 Created
Content-Type: application/json; charset=utf-8

{
  "id": 318,
  "object": "project",
  "name": "Ali Rezaei",
  "description": "Free plan",
  "external_id": "user-1042",
  "metadata": { "plan": "free" },
  "monthly_budget_usd": null,
  "spent_this_month_usd": "0.000000",
  "is_active": true,
  "archived": false,
  "live_keys": 1,
  "created_at": "2026-11-04T09:12:44+00:00",
  "updated_at": "2026-11-04T09:12:44+00:00",
  "key": {
    "id": 1207,
    "object": "api_key",
    "project_id": 318,
    "name": "main",
    "masked": "sk-ntz-v1-k3Jd8s…4wXa",
    "spend_limit_usd": "5.000000",
    "spent_usd": "0.000000",
    "remaining_usd": "5.000000",
    "expires_at": "2026-12-04T09:12:44+00:00",
    "is_active": true,
    "status": "active",
    "allowed_models": [],
    "allowed_ips": [],
    "rpm_limit": null,
    "requests_count": 0,
    "last_used_at": null,
    "created_at": "2026-11-04T09:12:44+00:00",
    "secret": "sk-ntz-v1-k3Jd8sLq0WmZ2xVn7RtYb5CeHg9PfUoA1iNq4wXa"
  }
}

نمونهٔ کامل سمت سرور، با Idempotency-Key و رسیدگی به خطا:

PHP (Laravel)
<?php

use Illuminate\Http\Client\ConnectionException;
use Illuminate\Http\Client\RequestException;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Str;

/**
 * Call it once when a user signs up in YOUR product.
 * The model key is shown only in this response: store it encrypted.
 */
function provisionAiAccess(App\Models\User $user): array
{
    $base = 'https://netarz.ir/api/ai/v1/manage';

    $http = Http::withToken(config('services.ai.management_key'))   // NETARZ_MANAGEMENT_KEY
        ->acceptJson()
        ->timeout(20)
        // Safe to repeat: the same Idempotency-Key always gets the same answer.
        ->retry(3, 500, fn ($e) => $e instanceof ConnectionException
            || ($e instanceof RequestException && in_array($e->response->status(), [429, 500, 502, 503, 504], true)),
            throw: false);

    $response = $http
        ->withHeaders(['Idempotency-Key' => "signup-{$user->id}"])
        ->post("$base/projects", [
            'name' => Str::limit($user->name, 80, ''),
            'external_id' => "user-{$user->id}",
            'metadata' => ['plan' => 'free'],
            'key' => [
                'name' => 'main',
                'spend_limit_usd' => '5.00',
                'expires_in_days' => 30,
            ],
        ]);

    if ($response->created()) {
        return [
            'project_id' => $response->json('id'),
            'key_id' => $response->json('key.id'),
            'secret' => $response->json('key.secret'),
        ];
    }

    $code = $response->json('error.code');

    if ($response->status() === 409 && $code === 'project_exists') {
        // This user already has a project (an earlier signup, or a retry after 24 hours).
        // A secret cannot be read again, so mint a new key for the same project.
        $projectId = $response->json('error.project_id');
        $key = $http
            ->withHeaders(['Idempotency-Key' => "signup-key-{$user->id}"])
            ->post("$base/projects/$projectId/keys", [
                'name' => 'main-2',
                'spend_limit_usd' => '5.00',
                'expires_in_days' => 30,
            ])
            ->throw()
            ->json();

        return ['project_id' => $projectId, 'key_id' => $key['id'], 'secret' => $key['secret']];
    }

    if ($response->status() === 422) {
        // Something you sent is wrong; error.errors lists the fields.
        throw new InvalidArgumentException(json_encode($response->json('error.errors'), JSON_UNESCAPED_UNICODE));
    }

    // 401/403: the management key. 429/5xx: still failing after the retries.
    throw new RuntimeException("AI provisioning failed: {$response->status()} {$code}");
}
Node.js
// provision.mjs — Node.js 18 or newer (fetch is built in)
const BASE = "https://netarz.ir/api/ai/v1/manage";
const AUTH = { Authorization: `Bearer ${process.env.NETARZ_MANAGEMENT_KEY}`, "Content-Type": "application/json" };
const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));

async function call(method, path, body, idempotencyKey) {
  const headers = idempotencyKey ? { ...AUTH, "Idempotency-Key": idempotencyKey } : AUTH;

  for (let attempt = 1; attempt <= 4; attempt++) {
    let res;
    try {
      res = await fetch(BASE + path, {
        method,
        headers,
        body: body ? JSON.stringify(body) : undefined,
        signal: AbortSignal.timeout(20_000),
      });
    } catch {
      await sleep(500 * attempt); // network error or timeout: the same key makes a repeat safe
      continue;
    }

    const data = await res.json().catch(() => ({}));
    const retryable = [429, 500, 502, 503, 504].includes(res.status)
      || data.error?.code === "idempotency_in_progress";

    if (!retryable || attempt === 4) return { status: res.status, data };
    await sleep((Number(res.headers.get("Retry-After")) || attempt) * 1000);
  }
  return { status: 0, data: {} };
}

// Call it once when a user signs up in YOUR product.
// The model key is shown only in this response: store it encrypted.
export async function provisionAiAccess(user) {
  const keyBody = { name: "main", spend_limit_usd: "5.00", expires_in_days: 30 };

  const res = await call("POST", "/projects", {
    name: user.name.slice(0, 80),
    external_id: `user-${user.id}`,
    metadata: { plan: "free" },
    key: keyBody,
  }, `signup-${user.id}`);

  if (res.status === 201) {
    return { projectId: res.data.id, keyId: res.data.key.id, secret: res.data.key.secret };
  }

  const code = res.data.error?.code;

  if (res.status === 409 && code === "project_exists") {
    // This user already has a project. A secret cannot be read again: mint a new key.
    const projectId = res.data.error.project_id;
    const key = await call("POST", `/projects/${projectId}/keys`, keyBody, `signup-key-${user.id}`);
    if (key.status === 201) return { projectId, keyId: key.data.id, secret: key.data.secret };
  }

  if (res.status === 422) {
    throw new Error("Invalid input: " + JSON.stringify(res.data.error.errors));
  }

  throw new Error(`AI provisioning failed: ${res.status} ${code}`);
}
Python
# provision.py — pip install requests
import os
import time

import requests

BASE = "https://netarz.ir/api/ai/v1/manage"
SESSION = requests.Session()
SESSION.headers.update({"Authorization": "Bearer " + os.environ["NETARZ_MANAGEMENT_KEY"]})


def call(method, path, body=None, idempotency_key=None):
    headers = {"Idempotency-Key": idempotency_key} if idempotency_key else {}

    for attempt in range(1, 5):
        try:
            res = SESSION.request(method, BASE + path, json=body, headers=headers, timeout=20)
        except (requests.ConnectionError, requests.Timeout):
            time.sleep(0.5 * attempt)       # the same key makes a repeat safe
            continue

        data = res.json() if res.content else {}
        retryable = res.status_code in (429, 500, 502, 503, 504) \
            or data.get("error", {}).get("code") == "idempotency_in_progress"

        if not retryable or attempt == 4:
            return res.status_code, data
        time.sleep(float(res.headers.get("Retry-After", attempt)))

    return 0, {}


def provision_ai_access(user):
    """Call it once when a user signs up in YOUR product.
    The model key is shown only in this response: store it encrypted."""
    key_body = {"name": "main", "spend_limit_usd": "5.00", "expires_in_days": 30}

    status, data = call("POST", "/projects", {
        "name": user.name[:80],
        "external_id": f"user-{user.id}",
        "metadata": {"plan": "free"},
        "key": key_body,
    }, idempotency_key=f"signup-{user.id}")

    if status == 201:
        return {"project_id": data["id"], "key_id": data["key"]["id"], "secret": data["key"]["secret"]}

    code = data.get("error", {}).get("code")

    if status == 409 and code == "project_exists":
        # This user already has a project. A secret cannot be read again: mint a new key.
        project_id = data["error"]["project_id"]
        key_status, key = call("POST", f"/projects/{project_id}/keys", key_body,
                               idempotency_key=f"signup-key-{user.id}")
        if key_status == 201:
            return {"project_id": project_id, "key_id": key["id"], "secret": key["secret"]}

    if status == 422:
        raise ValueError(f"Invalid input: {data['error']['errors']}")

    raise RuntimeError(f"AI provisioning failed: {status} {code}")

چرا این‌طور نوشته شده؟

  • کلید ایدمپوتنسی از شناسهٔ کاربر ساخته می‌شود (signup-1042). اگر پاسخ در راه گم شود و درخواست را دوباره بفرستید، همان پاسخ اول، با همان secret، برمی‌گردد و کاربر دو کلید نمی‌گیرد. جزئیات: ایدمپوتنسی.
  • external_id پشتیبان دوم است. اگر ایدمپوتنسی گذشته باشد (بیش از ۲۴ ساعت) یا کد دیگری دوباره پروژه بسازد، 409 project_exists با شناسهٔ همان پروژه می‌گیرید و پروژهٔ تکراری ساخته نمی‌شود.
  • فقط خطاهای قابل تکرار دوباره فرستاده می‌شوند: قطع شبکه، ۴۲۹ و ۵xx. ۴۰۱ و ۴۰۳ و ۴۲۲ را تکرار نکنید؛ باید علتشان را رفع کرد.
  • بعد از ثبت‌نام، کاربر شما با کلیدی که گرفته مدل را صدا می‌زند:
کلید مدل
# What YOUR user (or your server on their behalf) sends to the model:
# the key from key.secret, on the model gateway, not the management key.
curl https://netarz.ir/api/ai/v1/chat/completions \
  -H "Authorization: Bearer sk-ntz-v1-k3Jd8sLq0WmZ2xVn7RtYb5CeHg9PfUoA1iNq4wXa" \
  -H "Content-Type: application/json" \
  -d '{ "model": "gpt-4o-mini", "messages": [{ "role": "user", "content": "Hello" }] }'

پروژه‌ها

ساختن پروژه

POST/api/ai/v1/manage/projectsنیازمند کلید مدیریت

فیلدهای بدنه:

فیلدتوضیح
name
string الزامی
نام پروژه، تا ۸۰ نویسه.
external_id
string
شناسهٔ این کاربر در سیستم خودتان، تا ۱۹۱ نویسه. در هر حساب یکتاست: بار دوم 409 project_exists می‌گیرید و پروژهٔ تکراری ساخته نمی‌شود. بایگانی‌کردن پروژه این شناسه را آزاد نمی‌کند.
description
string | null
توضیح، تا ۲۵۵ نویسه.
monthly_budget_usd
string | number | null
بودجهٔ ماهانهٔ پروژه به دلار، از ۰٫۰۱ تا ۱٬۰۰۰٬۰۰۰. null یعنی بدون بودجهٔ ماهانه (سقف هر کلید همچنان برقرار است).
allowed_models
array
مدل‌های مجاز پروژه، تا ۳۰۰ مورد. نفرستید یا خالی بفرستید یعنی همهٔ مدل‌ها.
metadata
object
تا ۱۶ جفت کلید و مقدار. نام کلید ۱ تا ۴۰ نویسه از حرف انگلیسی، عدد و _ . -؛ مقدار حتماً رشته است و تا ۵۰۰ نویسه. برای نگه‌داشتن شناسه‌های خودتان (طرح، سازمان، …).
key
object
اگر بفرستید، اولین کلید پروژه هم در همان تراکنش ساخته می‌شود. فیلدهای آن در جدول بعد است؛ spend_limit_usd الزامی است و شیء خالی {} خطای ۴۲۲ می‌دهد.

فیلدهای شیء key (همان فیلدهای ساختن کلید):

فیلدتوضیح
name
string
نام کلید، تا ۸۰ نویسه. اگر نفرستید، «Key N» ساخته می‌شود.
spend_limit_usd
string | number الزامی
سقف هزینهٔ کلید به دلار، از ۰٫۰۱ تا ۱٬۰۰۰٬۰۰۰. کلیدی که با این API ساخته می‌شود هیچ‌وقت بدون سقف نیست.
expires_at
string
تاریخ انقضا به قالب ISO-8601 همراه با منطقهٔ زمانی، مثل 2027-01-31T23:59:59+03:30 یا …Z. باید در آینده و حداکثر ۳٬۶۵۰ روز بعد باشد. اگر نفرستید، کلید منقضی نمی‌شود.
expires_in_days
integer
به‌جای expires_at: انقضا از همین لحظه، ۱ تا ۳٬۶۵۰ روز بعد. هر دو را با هم نفرستید.
allowed_models
array
شناسهٔ مدل‌هایی که کلید می‌تواند صدا بزند، تا ۳۰۰ مورد؛ باید از مدل‌های در دسترس باشد و اگر پروژه فهرست مدل دارد، زیرمجموعهٔ آن. خالی یعنی هر مدلی که پروژه اجازه دهد.
allowed_ips
array
تا ۲۰ مورد: IP دقیق (IPv4 یا IPv6)، پیشوند IPv4 با نقطهٔ پایانی (203.0.113.) یا CIDR (203.0.113.0/24). خالی یعنی از هر IP.
rpm_limit
integer
سقف درخواست در دقیقه، ۱ تا ۱۰٬۰۰۰. ذخیره و نمایش داده می‌شود؛ نکتهٔ آخر صفحه (نکته‌های رفتار) را ببینید.

پاسخ 201 شیء پروژه است و اگر key فرستاده باشید، شیء key (با secret) هم درونش می‌آید. اگر external_id پیش‌تر به‌کار رفته باشد:

پاسخ ۴۰۹
HTTP/1.1 409 Conflict

{
  "error": {
    "message": "پروژه‌ای با این external_id از قبل وجود دارد.",
    "type": "conflict_error",
    "code": "project_exists",
    "param": null,
    "project_id": 318,
    "external_id": "user-1042"
  }
}

شیء پروژه

فیلدتوضیح
id
integer
شناسهٔ پروژه در نِت اَرز.
object
string
همیشه project.
name، description
string
همان‌هایی که فرستاده‌اید.
external_id
string | null
شناسهٔ خودتان.
metadata
object
خالی که باشد {} است.
monthly_budget_usd
string | null
بودجهٔ ماهانه به دلار با شش رقم اعشار؛ null یعنی بدون بودجه.
spent_this_month_usd
string
مصرف این ماه (از اول ماه میلادی) به دلار.
is_active
boolean
false یعنی پروژه مکث شده است.
archived
boolean
true یعنی بایگانی شده است.
live_keys
integer
تعداد کلیدهای فعال (باطل‌نشده، منقضی‌نشده و روشن).
created_at، updated_at
string
ISO-8601 با منطقهٔ زمانی.

فهرست و جست‌وجوی پروژه‌ها

GET/api/ai/v1/manage/projectsنیازمند کلید مدیریت
فیلدتوضیح
external_id
string
فقط پروژه‌ای که این شناسه را دارد.
archived
boolean
false بایگانی‌شده‌ها را پنهان می‌کند. نفرستید یعنی همه.
limit
integer
۱ تا ۱۰۰؛ پیش‌فرض ۲۰.
after
integer
نشانگر صفحهٔ بعد: مقدار next_after صفحهٔ قبل.
GET/api/ai/v1/manage/projects/{id}نیازمند کلید مدیریت
GET/api/ai/v1/manage/projects/by-external/{external_id}نیازمند کلید مدیریت

اولی با شناسهٔ نِت اَرز و دومی با شناسهٔ خودتان پروژه را برمی‌گرداند؛ پروژهٔ پیدانشده ۴۰۴ می‌دهد.

cURL
# the newest 20 projects
curl "https://netarz.ir/api/ai/v1/manage/projects?limit=20" -H "Authorization: Bearer $NETARZ_MANAGEMENT_KEY"

# the next page: after = next_after of the previous page
curl "https://netarz.ir/api/ai/v1/manage/projects?limit=20&after=299" -H "Authorization: Bearer $NETARZ_MANAGEMENT_KEY"

# one project by your own id
curl "https://netarz.ir/api/ai/v1/manage/projects/by-external/user-1042" -H "Authorization: Bearer $NETARZ_MANAGEMENT_KEY"
پاسخ فهرست
{
  "object": "list",
  "data": [
    { "id": 318, "object": "project", "name": "Ali Rezaei", "external_id": "user-1042", "...": "..." },
    { "id": 317, "object": "project", "name": "Sara Karimi", "external_id": "user-1041", "...": "..." }
  ],
  "has_more": true,
  "next_after": 299
}

تغییر پروژه

PATCH/api/ai/v1/manage/projects/{id}نیازمند کلید مدیریت

فقط فیلدهایی را بفرستید که می‌خواهید عوض شوند. بدنهٔ خالی 422 می‌دهد.

فیلدتوضیح
name
string
نام تازه، تا ۸۰ نویسه.
description
string | null
null توضیح را پاک می‌کند.
monthly_budget_usd
string | number | null
null بودجه را برمی‌دارد.
allowed_models
array | null
null یا خالی یعنی همهٔ مدل‌ها.
metadata
object | null
جای کل شیء قبلی می‌نشیند، ادغام نمی‌شود. null یا {} پاکش می‌کند.
is_active
boolean
false پروژه را مکث می‌کند: همهٔ کلیدهایش از همان لحظه رد می‌شوند. true برش می‌گرداند.
cURL
# pause: every key of the project stops working
curl -X PATCH https://netarz.ir/api/ai/v1/manage/projects/318 \
  -H "Authorization: Bearer $NETARZ_MANAGEMENT_KEY" -H "Content-Type: application/json" \
  -d '{ "is_active": false }'

# rename, set a monthly budget and replace the metadata
curl -X PATCH https://netarz.ir/api/ai/v1/manage/projects/318 \
  -H "Authorization: Bearer $NETARZ_MANAGEMENT_KEY" -H "Content-Type: application/json" \
  -d '{ "name": "Ali Rezaei (pro)", "monthly_budget_usd": "20.00", "metadata": { "plan": "pro" } }'

پروژهٔ بایگانی‌شده تغییر نمی‌کند (409 project_archived).

بایگانی پروژه

DELETE/api/ai/v1/manage/projects/{id}نیازمند کلید مدیریت
بازگشت‌ناپذیر

همهٔ کلیدهای پروژه باطل می‌شوند و پروژه خاموش و بایگانی می‌شود. هیچ ردیفی پاک نمی‌شود و تاریخچهٔ مصرف می‌ماند، ولی پروژه را نمی‌شود دوباره باز کرد و external_id آن هم آزاد نمی‌شود. تکرار همین درخواست بی‌ضرر است و دوباره ۲۰۰ می‌دهد.

cURL
curl -X DELETE https://netarz.ir/api/ai/v1/manage/projects/318 \
  -H "Authorization: Bearer $NETARZ_MANAGEMENT_KEY"

پاسخ، شیء پروژه با archived: true و is_active: false است. پروژه‌ای که از اینجا بایگانی شود در پنل هم می‌ماند (با برچسب «بایگانی‌شده»)، چون سابقهٔ آن حذف نمی‌شود.

کلیدها

ساختن کلید

POST/api/ai/v1/manage/projects/{id}/keysنیازمند کلید مدیریت

برای کاربری که از قبل پروژه دارد: کلید دوم (مثلاً برای اپ موبایل)، کلید تازه بعد از چرخش یا کلید برای ماه بعد. هر پروژه حداکثر ۱۰ کلید فعال دارد. پروژهٔ مکث‌شده یا بایگانی‌شده کلید تازه نمی‌گیرد.

فیلدتوضیح
name
string
نام کلید، تا ۸۰ نویسه. اگر نفرستید، «Key N» ساخته می‌شود.
spend_limit_usd
string | number الزامی
سقف هزینهٔ کلید به دلار، از ۰٫۰۱ تا ۱٬۰۰۰٬۰۰۰. کلیدی که با این API ساخته می‌شود هیچ‌وقت بدون سقف نیست.
expires_at
string
تاریخ انقضا به قالب ISO-8601 همراه با منطقهٔ زمانی، مثل 2027-01-31T23:59:59+03:30 یا …Z. باید در آینده و حداکثر ۳٬۶۵۰ روز بعد باشد. اگر نفرستید، کلید منقضی نمی‌شود.
expires_in_days
integer
به‌جای expires_at: انقضا از همین لحظه، ۱ تا ۳٬۶۵۰ روز بعد. هر دو را با هم نفرستید.
allowed_models
array
شناسهٔ مدل‌هایی که کلید می‌تواند صدا بزند، تا ۳۰۰ مورد؛ باید از مدل‌های در دسترس باشد و اگر پروژه فهرست مدل دارد، زیرمجموعهٔ آن. خالی یعنی هر مدلی که پروژه اجازه دهد.
allowed_ips
array
تا ۲۰ مورد: IP دقیق (IPv4 یا IPv6)، پیشوند IPv4 با نقطهٔ پایانی (203.0.113.) یا CIDR (203.0.113.0/24). خالی یعنی از هر IP.
rpm_limit
integer
سقف درخواست در دقیقه، ۱ تا ۱۰٬۰۰۰. ذخیره و نمایش داده می‌شود؛ نکتهٔ آخر صفحه (نکته‌های رفتار) را ببینید.
cURL
curl -X POST https://netarz.ir/api/ai/v1/manage/projects/318/keys \
  -H "Authorization: Bearer $NETARZ_MANAGEMENT_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: topup-1042-2026-11" \
  -d '{
    "name": "mobile-app",
    "spend_limit_usd": "2.50",
    "expires_at": "2027-01-31T23:59:59+03:30",
    "allowed_models": ["gpt-4o-mini"],
    "allowed_ips": ["203.0.113.0/24"]
  }'
پاسخ ۲۰۱
{
  "id": 1208,
  "object": "api_key",
  "project_id": 318,
  "name": "mobile-app",
  "masked": "sk-ntz-v1-k3Jd8s…4wXa",
  "spend_limit_usd": "2.500000",
  "spent_usd": "0.000000",
  "remaining_usd": "2.500000",
  "expires_at": "2027-01-31T20:29:59+00:00",
  "is_active": true,
  "status": "active",
  "allowed_models": ["gpt-4o-mini"],
  "allowed_ips": ["203.0.113.0/24"],
  "rpm_limit": null,
  "requests_count": 0,
  "last_used_at": null,
  "created_at": "2026-11-04T09:30:10+00:00",
  "secret": "sk-ntz-v1-k3Jd8sLq0WmZ2xVn7RtYb5CeHg9PfUoA1iNq4wXa"
}
کلید را فقط یک بار می‌بینید

مقدار secret را همان لحظه ذخیره کنید. در نِت اَرز فقط اثر انگشت (هش) کلید نگه داشته می‌شود و با GET یا هر راه دیگری برگردانده نمی‌شود. اگر گم شد، کلید را بچرخانید.

شیء کلید

فیلدتوضیح
id، project_id
integer
شناسهٔ کلید و پروژه‌اش.
object
string
همیشه api_key.
masked
string
شانزده نویسهٔ اول، سه نقطه و چهار نویسهٔ آخر؛ برای شناسایی در پنل و گزارش. خودِ کلید را از روی آن نمی‌شود ساخت.
spend_limit_usd، spent_usd، remaining_usd
string
سقف، مصرف‌شده و باقی‌مانده، به دلار با شش رقم اعشار.
expires_at
string | null
زمان انقضا یا null.
is_active
boolean
روشن یا خاموش بودن خودِ کلید.
status
string
active، disabled (کلید یا پروژه خاموش است)، expired، revoked یا limit_reached.
allowed_models، allowed_ips
array
خالی یعنی بدون محدودیت اضافه.
rpm_limit
integer | null
همان که فرستاده‌اید.
requests_count، last_used_at
integer، string | null
تعداد درخواست و آخرین استفاده. این دو پس از ثبت هر درخواست به‌روز می‌شوند.
secret
string
فقط در پاسخ ساخت کلید، ساخت پروژه همراه کلید (key.secret) و چرخش کلید می‌آید؛ جای دیگر هرگز.

فهرست و خواندن

GET/api/ai/v1/manage/projects/{id}/keysنیازمند کلید مدیریت
GET/api/ai/v1/manage/keys/{id}نیازمند کلید مدیریت

فهرست همهٔ کلیدهای پروژه را می‌دهد، با باطل‌شده‌ها و منقضی‌شده‌ها، و مثل پروژه‌ها صفحه‌بندی دارد.

تغییر کلید

PATCH/api/ai/v1/manage/keys/{id}نیازمند کلید مدیریت
فیلدتوضیح
name
string
نام تازه.
spend_limit_usd
string | number
سقف را دقیقاً روی این مقدار می‌گذارد؛ ۰٫۰۱ تا ۱٬۰۰۰٬۰۰۰. هیچ‌وقت null نمی‌شود.
spend_limit_add_usd
string | number
مقداری مثبت که به سقف فعلی اضافه می‌شود، در یک مرحلهٔ اتمی. با spend_limit_usd هم‌زمان نفرستید (۴۲۲). سقف کل از ۱٬۰۰۰٬۰۰۰ دلار بیشتر نمی‌شود.
expires_at
string | null
انقضای تازه (ISO-8601 با منطقهٔ زمانی، در آینده، تا ۱۰ سال). null یعنی هیچ‌وقت منقضی نشود.
expires_in_days
integer
انقضا از همین لحظه، ۱ تا ۳٬۶۵۰ روز بعد. با expires_at هم‌زمان نفرستید.
is_active
boolean
false کلید را خاموش می‌کند. روشن‌کردن دوباره سقف ۱۰ کلید فعال را می‌سنجد.
allowed_models
array | null
باید زیرمجموعهٔ مدل‌های مجاز پروژه باشد. null یا خالی یعنی هر چه پروژه اجازه دهد.
allowed_ips
array | null
null یا خالی یعنی از هر IP.
rpm_limit
integer | null
۱ تا ۱۰٬۰۰۰ یا null.

کلید باطل‌شده یخ‌زده است: هر تغییری 409 key_revoked می‌دهد.

چرخش کلید

POST/api/ai/v1/manage/keys/{id}/rotateنیازمند کلید مدیریت

همان کلید (همان شناسه، سقف، مصرف و تنظیم‌ها) یک مقدار secret تازه می‌گیرد و پاسخ آن را یک بار نشان می‌دهد. مقدار قدیمی همان لحظه از کار می‌افتد (درگاه مدل‌ها 401 invalid_api_key می‌دهد)، پس اگر کلید تازه را همان لحظه به جایی که لازم دارد نرسانید، کاربر قطع می‌شود. چرخش برای وقتی است که کلید لو رفته یا گم شده است.

cURL
curl -X POST https://netarz.ir/api/ai/v1/manage/keys/1207/rotate \
  -H "Authorization: Bearer $NETARZ_MANAGEMENT_KEY" \
  -H "Idempotency-Key: rotate-1207-2026-11-04"

باطل کردن کلید

DELETE/api/ai/v1/manage/keys/{id}نیازمند کلید مدیریت
بازگشت‌ناپذیر

کلید باطل‌شده دیگر کار نمی‌کند و هیچ‌وقت دوباره روشن نمی‌شود. اگر فقط می‌خواهید موقتاً قطع شود، is_active: false بفرستید. تکرار درخواست بی‌ضرر است.

cURL
curl -X DELETE https://netarz.ir/api/ai/v1/manage/keys/1207 \
  -H "Authorization: Bearer $NETARZ_MANAGEMENT_KEY"

تغییر مبلغ و انقضا

پرکاربردترین عملیات بعد از ثبت‌نام همین دو است. همه با PATCH /keys/{id} انجام می‌شود:

cURL
# set the limit to an exact amount
curl -X PATCH https://netarz.ir/api/ai/v1/manage/keys/1207 \
  -H "Authorization: Bearer $NETARZ_MANAGEMENT_KEY" -H "Content-Type: application/json" \
  -d '{ "spend_limit_usd": "10.00" }'

# or add to whatever the limit is now (one atomic step, safe to run in parallel)
curl -X PATCH https://netarz.ir/api/ai/v1/manage/keys/1207 \
  -H "Authorization: Bearer $NETARZ_MANAGEMENT_KEY" -H "Content-Type: application/json" \
  -d '{ "spend_limit_add_usd": "2.50" }'

# extend the expiry: a date with its offset, or a number of days from now
curl -X PATCH https://netarz.ir/api/ai/v1/manage/keys/1207 \
  -H "Authorization: Bearer $NETARZ_MANAGEMENT_KEY" -H "Content-Type: application/json" \
  -d '{ "expires_at": "2027-06-30T23:59:59+03:30" }'

curl -X PATCH https://netarz.ir/api/ai/v1/manage/keys/1207 \
  -H "Authorization: Bearer $NETARZ_MANAGEMENT_KEY" -H "Content-Type: application/json" \
  -d '{ "expires_in_days": 90 }'

# a key that never expires
curl -X PATCH https://netarz.ir/api/ai/v1/manage/keys/1207 \
  -H "Authorization: Bearer $NETARZ_MANAGEMENT_KEY" -H "Content-Type: application/json" \
  -d '{ "expires_at": null }'
  • spend_limit_usd یا spend_limit_add_usd؟ وقتی مبلغ نهایی را می‌دانید (مثلاً «پلن پرو: ۱۰ دلار»)، مقدار مطلق بفرستید. وقتی کاربر شارژ می‌خرد و می‌خواهید چیزی «اضافه» شود، spend_limit_add_usd را بفرستید؛ چون در پایگاه داده یک مرحله است، دو شارژ هم‌زمان روی هم نمی‌افتند.
  • مبلغ سقف «کل مصرف این کلید» است، نه ماهانه. اگر سقف را به مقداری برابر یا کمتر از مصرف‌شده برسانید، کلید همان لحظه می‌ایستد (limit_reached)؛ با بالا بردن سقف دوباره کار می‌کند.
  • برای ماهانه‌کردن، سقف پروژه را با monthly_budget_usd بگذارید یا ماه به ماه spend_limit_add_usd بفرستید.
  • انقضا هم نرم است: کلیدی که منقضی شده با PATCH و یک expires_at یا expires_in_days تازه دوباره کار می‌کند (به شرط این‌که باطل نشده باشد).

مکث، چرخش، ابطال و بایگانی

کاردرخواستاثر روی کاربر شمابرگشت‌پذیر؟
مکث کلیدPATCH /keys/{id} با is_active: false401 api_key_disabledبله
مکث پروژهPATCH /projects/{id} با is_active: falseهمهٔ کلیدهای پروژه: 403 project_inactiveبله
چرخش کلیدPOST /keys/{id}/rotateکلید قدیمی: 401 invalid_api_key؛ کلید تازه کار می‌کندکلید قدیمی برنمی‌گردد
ابطال کلیدDELETE /keys/{id}401 api_key_revokedخیر
بایگانی پروژهDELETE /projects/{id}همهٔ کلیدها باطل می‌شوندخیر

مصرف یک پروژه

GET/api/ai/v1/manage/projects/{id}/usageنیازمند کلید مدیریت
فیلدتوضیح
from
date
آغاز بازه (YYYY-MM-DD)؛ پیش‌فرض ۲۹ روز پیش از to.
to
date
پایان بازه؛ پیش‌فرض امروز (به وقت UTC). بازه حداکثر ۹۲ روز است، با هر دو سر.
key_id
integer
فقط مصرف یکی از کلیدهای همین پروژه.
cURL
curl "https://netarz.ir/api/ai/v1/manage/projects/318/usage?from=2026-10-06&to=2026-11-04" \
  -H "Authorization: Bearer $NETARZ_MANAGEMENT_KEY"

# only one key of the project
curl "https://netarz.ir/api/ai/v1/manage/projects/318/usage?key_id=1207" -H "Authorization: Bearer $NETARZ_MANAGEMENT_KEY"
پاسخ
{
  "object": "usage",
  "project_id": 318,
  "key_id": null,
  "from": "2026-10-06",
  "to": "2026-11-04",
  "totals": {
    "requests": 412,
    "errors": 3,
    "input_tokens": 190442,
    "output_tokens": 48120,
    "spend_usd": "0.731200"
  },
  "data": [
    { "date": "2026-11-02", "requests": 88, "errors": 0, "input_tokens": 40120, "output_tokens": 9800, "spend_usd": "0.150400" },
    { "date": "2026-11-03", "requests": 120, "errors": 1, "input_tokens": 50210, "output_tokens": 12004, "spend_usd": "0.201300" }
  ]
}

فقط روزهایی که مصرف داشته‌اند در data می‌آیند، صعودی. مصرف بعد از تسویهٔ هر درخواست به این گزارش اضافه می‌شود، پس چند ثانیه دیرتر از خود درخواست دیده می‌شود. spend_usd همان مبلغی است که از اعتبار شما کم شده است.

صفحه‌بندی

فهرست پروژه‌ها و کلیدها از جدیدترین به قدیمی‌ترین می‌آید و با نشانگر صفحه‌بندی می‌شود، نه شمارهٔ صفحه؛ پس وسط خواندن، ساخته‌شدن ردیف تازه چیزی را جابه‌جا نمی‌کند.

  • limit: ۱ تا ۱۰۰ (پیش‌فرض ۲۰).
  • has_more: اگر true بود، صفحهٔ بعدی هست.
  • next_after: همین را در درخواست بعد به‌عنوان after بفرستید. در صفحهٔ آخر null است.

ایدمپوتنسی (تکرار امن درخواست)

اگر پاسخ درخواستی به دستتان نرسد، نمی‌دانید پروژه ساخته شد یا نه. هدر Idempotency-Key این مشکل را حل می‌کند: همان درخواست را با همان کلید دوباره بفرستید و نتیجهٔ اول را می‌گیرید، نه یک پروژه یا کلید تازه.

  • روی هر سه درخواست POST کار می‌کند: ساخت پروژه، ساخت کلید و چرخش کلید. PATCH و DELETE ذاتاً تکرارپذیرند و آن را نادیده می‌گیرند.
  • مقدار، ۱ تا ۱۰۰ نویسهٔ قابل‌چاپ ASCII است. برای هر کار یک مقدار یکتا بسازید، مثلاً signup-1042؛ UUID هم خوب است. در هر حساب جداگانه شمرده می‌شود.
  • همان کلید و همان درخواست، تا ۲۴ ساعت: همان پاسخ، بایت‌به‌بایت و با همان secret، با هدر Idempotent-Replayed: true برمی‌گردد. پاسخ‌های ذخیره‌شده رمزنگاری می‌شوند و بعد از ۲۴ ساعت پاک می‌شوند.
  • همان کلید با درخواست دیگر (بدنهٔ متفاوت یا مسیر دیگر): 422 idempotency_key_reused. ترتیب فیلدهای JSON فرقی نمی‌کند.
  • درخواست اول هنوز در جریان است: 409 idempotency_in_progress. چند ثانیه صبر کنید و دوباره بفرستید. اگر درخواست اول بیش از ۲ دقیقه بی‌نتیجه بماند، آن را ناتمام می‌گیریم و تکرارش دوباره اجرا می‌شود.
  • فقط پاسخ‌های موفق (۲xx) به خاطر سپرده می‌شوند. اگر درخواست خطای ۴xx یا ۵xx بدهد، کلید آزاد می‌شود تا بعد از اصلاح همان کلید را دوباره به‌کار ببرید.
پاسخ تکراری
HTTP/1.1 201 Created
Idempotent-Replayed: true
Content-Type: application/json; charset=utf-8

{ ...the very same body as the first answer, secret included... }

خطاها

خطاها همان قالب درگاه مدل‌ها را دارند (صفحهٔ خطاها). در کد روی error.code تصمیم بگیرید؛ message فارسی است و ممکن است عوض شود. خطای ۴۲۲ فهرست فیلدها را در error.errors دارد.

نمونه: ۴۲۲
HTTP/1.1 422 Unprocessable Entity
Content-Type: application/json; charset=utf-8

{
  "error": {
    "message": "داده‌های ارسالی معتبر نیست.",
    "type": "invalid_request_error",
    "code": "validation_error",
    "param": "key.spend_limit_usd",
    "errors": {
      "key.spend_limit_usd": ["سقف هزینهٔ کلید الزامی است."]
    }
  }
}
وضعیتکدمعناچه کنید
401missing_api_keyکلید مدیریت نفرستاده‌اید.هدر Authorization: Bearer … را بگذارید.
401invalid_api_keyکلید وجود ندارد؛ یا این کلید مدیریت نیست (کلید مدل با این API کار نمی‌کند).کلید مدیریت را از پنل کپی کنید.
401api_key_revokedکلید مدیریت باطل شده است.در پنل کلید مدیریت تازه بسازید.
401api_key_expiredکلید مدیریت منقضی شده است.کلید مدیریت تازه بسازید.
403ip_not_allowedIP درخواست در فهرست IPهای مجاز این کلید مدیریت نیست.IP سرور را در پنل به کلید اضافه کنید.
403account_suspendedحساب API شما معلق شده است.با پشتیبانی تماس بگیرید.
503gateway_disabledسرویس API موقتاً بسته است.کمی بعد دوباره بفرستید.
413request_too_largeبدنهٔ درخواست از ۲۰ مگابایت بیشتر است.بدنه را کوچک‌تر کنید؛ این API هیچ‌وقت به این حجم نیاز ندارد.
404not_foundپروژه یا کلید پیدا نشد؛ یعنی وجود ندارد، مال حساب دیگری است، یا با این API ساخته نشده است.شناسه را بررسی کنید. پروژه و کلیدهای ساخته‌شده در پنل از این API دیده نمی‌شوند.
409project_existsپروژه‌ای با این external_id وجود دارد (در error.project_id می‌آید).از همان پروژه استفاده کنید؛ برای کلید تازه POST /projects/{id}/keys.
409project_archivedپروژه بایگانی شده و تغییر نمی‌کند.پروژهٔ تازه با external_id دیگری بسازید.
409project_inactiveپروژه مکث شده است و کلید تازه نمی‌گیرد.اول is_active: true را بفرستید.
409key_revokedکلید باطل شده است و دیگر تغییر یا چرخش ندارد.کلید تازه بسازید.
409limit_reachedبه سقف تعداد رسیده‌اید (پروژه یا کلید فعال).پروژه‌ها یا کلیدهای بی‌مصرف را ببندید؛ جدول محدودیت‌ها را ببینید.
409idempotency_in_progressدرخواستی با همین Idempotency-Key هنوز در حال انجام است.چند ثانیه صبر کنید و همان درخواست را با همان کلید دوباره بفرستید.
422validation_errorیک یا چند فیلد نامعتبر است؛ فهرست در error.errors و اولین فیلد در error.param.فیلدهای نام‌برده را اصلاح کنید؛ تکرار همان درخواست فایده ندارد.
422idempotency_key_reusedهمین Idempotency-Key با درخواست دیگری به‌کار رفته است.برای هر درخواست متفاوت، کلید تازه بسازید.
429rate_limitedبیش از ۳۰۰ درخواست در دقیقه با این کلید مدیریت.به اندازهٔ Retry-After (ثانیه) صبر کنید.
429too_many_failed_attemptsبیش از ۲۰ کلید اشتباه در ۱۰ دقیقه از این IP.چند دقیقه صبر کنید و کلید را بررسی کنید.
429rate_limit_exceededبیش از ۶۰۰ درخواست در دقیقه از این IP، پیش از احراز هویت.به اندازهٔ Retry-After صبر کنید.

کاربر شما چه خطایی می‌بیند؟

وقتی کلیدی که ساخته‌اید به مدل می‌رسد، خطاها از درگاه مدل‌ها می‌آید (https://netarz.ir/api/ai/v1) و کاربر شما باید بداند با هر کدام چه کند:

نمونه: کلید منقضی
HTTP/1.1 401 Unauthorized

{
  "error": {
    "message": "این کلید API منقضی شده است.",
    "type": "authentication_error",
    "code": "api_key_expired",
    "param": null
  }
}
وضعیتکدمعناراه‌حل از سمت شما
401api_key_expiredتاریخ انقضای کلید گذشته است.با PATCH /keys/{id} انقضا را جلو ببرید؛ همان کلید دوباره کار می‌کند.
402key_spend_limit_reachedسقف هزینهٔ کلید پر شده است.با spend_limit_add_usd سقف را زیاد کنید؛ همان کلید ادامه می‌دهد.
402project_budget_exceededبودجهٔ ماهانهٔ پروژه تمام شده است.بودجه را با PATCH /projects/{id} زیاد کنید یا تا ماه بعد صبر کنید.
402insufficient_creditاعتبار حساب شما (نه کلید) کم است.حساب را در پنل شارژ کنید. با GET /account موجودی را زیر نظر داشته باشید.
402daily_cap_reachedسقف مصرف روزانهٔ حساب شما پر شده است.فردا دوباره امتحان کنید یا با پشتیبانی تماس بگیرید.
401api_key_revokedکلید باطل شده است (با DELETE، بایگانی پروژه یا چرخش کلید).کلید تازه بسازید، یا بعد از چرخش، کلید جدید را به کاربر بدهید.
401api_key_disabledکلید با is_active: false خاموش شده است.با is_active: true روشنش کنید.
403project_inactiveپروژه مکث شده است.پروژه را با is_active: true برگردانید.
403model_not_allowedمدل درخواستی در فهرست مجاز کلید یا پروژه نیست.مدل را به allowed_models اضافه کنید.

هیچ‌کدام از این خطاها هزینه ندارند. فهرست کامل کدهای درگاه در صفحهٔ خطاها است.

محدودیت‌ها

موردمقداراگر بیشتر شود
پروژهٔ ساخته‌شده با API (بایگانی‌نشده)۱۰٬۰۰۰ در هر حساب409 limit_reached
کلید فعال در هر پروژه۱۰409 limit_reached
کلید مدیریت فعال۵ در هر حسابدر پنل ساخته نمی‌شود
درخواست به این API۳۰۰ در دقیقه برای هر کلید مدیریت429 rate_limited
درخواست از یک IP، پیش از احراز هویت۶۰۰ در دقیقه429 rate_limit_exceeded
کلید مدیریت اشتباه۲۰ در ۱۰ دقیقه از یک IP429 too_many_failed_attempts
حجم بدنهٔ درخواست۲۰ مگابایت413 request_too_large
نام پروژه و کلید۸۰ نویسه422
توضیح پروژه۲۵۵ نویسه422
external_id۱۹۱ نویسه422
metadata۱۶ کلید؛ نام تا ۴۰ نویسه؛ مقدار رشته تا ۵۰۰ نویسه422
allowed_models۳۰۰ مورد422
allowed_ips۲۰ مورد422
سقف هزینهٔ کلید و بودجهٔ ماهانهاز ۰٫۰۱ تا ۱٬۰۰۰٬۰۰۰ دلار422
عمر کلیدحداکثر ۳٬۶۵۰ روز (۱۰ سال) از همین لحظه422
بازهٔ گزارش مصرفحداکثر ۹۲ روز (دو سر بازه با هم)422
صفحه‌بندیlimit از ۱ تا ۱۰۰ (پیش‌فرض ۲۰)422
Idempotency-Key۱ تا ۱۰۰ نویسه؛ پاسخ ۲۴ ساعت نگه داشته می‌شود422

نکته‌های رفتار

  • اعلان‌ها. رسیدن یک کلید یا پروژهٔ ساخته‌شده با این API به سقف، برای شما ایمیل یا پیامک نمی‌فرستد (وگرنه کاربران شما صندوق‌تان را پر می‌کردند)، و ساخت و ابطال کلید با این API هم همین‌طور. اعلان‌های حساب، مثل کمبود یا اتمام اعتبار، سر جایش می‌ماند؛ برای کاربرانتان خودتان با GET …/usage یا خطاهای بالا پیام بسازید.
  • مکث پروژه و خاموش‌کردن کلید دو خطای متفاوت می‌دهند: پروژه 403 project_inactive و کلید 401 api_key_disabled. در وضعیت کلید (status) هر دو disabled دیده می‌شوند.
  • سقف درخواست در دقیقهٔ هر کلید (rpm_limit) ذخیره و نمایش داده می‌شود، ولی فعلاً درگاه مدل‌ها آن را برای هر کلید جدا اعمال نمی‌کند و سقف مؤثر همان سقف حساب است. روی آن حساب نکنید؛ برای کنترل هزینه از spend_limit_usd استفاده کنید.
  • پروژه‌های پنل و پروژه‌های API جدا می‌مانند. می‌توانید پروژهٔ ساخته‌شده با API را در پنل ببینید و حتی تغییر دهید؛ ولی در این صورت به فرض‌های برنامهٔ خودتان دست زده‌اید.
  • هزینه از اعتبار شما می‌رود. سقف کلیدها جمع نمی‌شود؛ مجموع سقف همهٔ کلیدها می‌تواند از موجودی شما بیشتر باشد، و هر کلید تا وقتی اعتبار حساب هست خرج می‌کند. اگر ملاحظهٔ امنیتی دارید، سقف حساب را هم در پنل بگذارید.

تغییرات

  • 1405/08/13: انتشار API مدیریت پروژه‌ها و کلیدها: کلید مدیریت، ساخت پروژه و کلید در یک درخواست، تغییر سقف و انقضا، چرخش و ابطال کلید، گزارش مصرف و ایدمپوتنسی. هیچ endpoint موجودی تغییر نکرده است.

مرجع تعاملی همین endpointها در مرجع API است (در بخش «Management»، با طرح امنیتی جدا برای کلید مدیریت). تغییرات بعدی در صفحهٔ تغییرات می‌آید.