لفترة محدودةالعضوية السنوية:خصم 30٪ووصول غير محدود إلى GPT Image وMiniMax H3 والمزيد
AI Chat الجديد · محاولات مجانية يوميًا
الترقية الآن
Pixmind

دليل البدء السريع لواجهة PixMind API: توليد الصور باستخدام Node.js

أنشئ مهمة لتوليد صورة، واحفظ معرّفها، وتابع نتيجتها بأمان من الخادم

جدول المحتويات

قبول طلب توليد صورة لا يعني أن الصورة أصبحت جاهزة. يحتاج تطبيقك إلى الاحتفاظ بمعرّف المهمة، والتحقق من حالة المهمة نفسها، والتعامل مع الطلب الفاشل أو المنقطع دون بدء مهمة أخرى عن طريق الخطأ.

في هذا الدليل، سننشئ عميلًا صغيرًا يعمل على الخادم باستخدام Node.js لتنفيذ هذه الخطوات. يتضمن العميل أمرين منفصلين هما submit وresume: ينشئ الأول مهمة، بينما يقتصر الثاني على التحقق من مهمة موجودة. ابدأ بالاطلاع على معرّفات النماذج التي تدعمها واجهة API، ولا تعتمد على اسم نموذج نسخته من لافتة في الصفحة الرئيسية.

يتناول هذا الدليل توليد الصور من النصوص. ولا يشمل رفع ملفات مرجعية، أو إنشاء واجهة في المتصفح، أو قياس جودة النماذج. يجمع التحقق بين 29 اختبارًا محليًا باستجابات محاكاة ومهمة واحدة مضبوطة لتوليد صورة في بيئة الإنتاج نُفّذت في 4 سبتمبر 2026. أعادت تلك المهمة صورة واحدة وسجّلت رسوم API قدرها 120 نقطة. وهذا تحقق مؤرّخ واحد من التكامل، وليس اختبارًا لقياس السرعة، أو سعرًا ينطبق على جميع الحالات، أو ضمانًا لتوافر الخدمة لحساب آخر.

صورة الغلاف هي لقطة شاشة لدليل النماذج التُقطت في 4 سبتمبر 2026. تعامل معها بوصفها توضيحًا مؤرّخًا، لا عرض سعر حاليًا أو ضمانًا للتوافر.

أهم النقاط

  • احتفظ بمفتاح API على خادمك، ولا تُدرجه في حزم المتصفح أو المستودعات العامة.
  • لمهمة توليد صورة، اقرأ القيمة الرقمية data.taskId من استجابة قبول الطلب، واحتفظ بها للاستعلامات اللاحقة.
  • استعلم دوريًا عن المهمة المحفوظة حتى تصل إلى ready أو failed. ولا تقرأ روابط الصور من data.images إلا بعد النجاح.
  • انتهاء المهلة لدى العميل لا يثبت فشل المهمة البعيدة أو إلغاءها. استأنف الاستعلامات إذا كان لديك معرّف المهمة، ولا تكرر طلب الإنشاء دون التحقق مما حدث.

محتويات الدليل

قبل البدء

استخدم طرفية خاصة أو بيئة خادم تتوافر فيها Node.js ومفتاح API وحساب مُعدّ لفوترة API. يستخدم المثال المرفق fetch المدمجة ووحدات JavaScript، دون الحاجة إلى تثبيت حزم خارجية. تشرح وثائق واجهات Node العامة كلًا من fetch وAbortSignal.timeout، اللتين يستخدمهما العميل لتقييد مدة الطلب الواحد. بيئة التحقق المحلي هي Windows مع Node.js بالإصدار v22.22.1؛ وهذا توثيق لبيئة الاختبار، لا ادعاء بأن جميع الإصدارات الأخرى قد اختُبرت.

ينبغي أن تكون ملمًا بتعديل الملفات، وضبط متغيرات البيئة، وقراءة JSON. تحقّق من بيئة التشغيل المثبّتة لديك قبل المتابعة:

node --version

يفترض أن يطبع الأمر رقم الإصدار المثبّت لديك. وهو لا يتصل بواجهة API لتوليد الصور. احفظ العميل الكامل الوارد في قسم لاحق باسم examples/pixmind-image.mjs داخل مجلد عمل، ثم نفّذ أوامره من ذلك المجلد.

اختر وصفًا نصيًا آمنًا للاختبار لا يتضمن بيانات عملاء أو معلومات سرية. يستخدم هذا الدليل كوب قهوة خزفيًا على خلفية استوديو، لذا لا يحتاج إلى رفع ملفات مرجعية. راجع سعر API الحالي للنموذج المحدد قبل الإرسال. ولا تفترض أن أرصدة Studio والاشتراكات وفوترة API قابلة للاستخدام بالتبادل؛ إذ يوضح دليل النماذج عرض API المعني.

إذا كنت تريد فقط إنشاء صورة بطريقة تفاعلية، فإن دليل Image Agent يشرح هذا المسار. أما العميل هنا فهو مخصص لتطبيق يحدد معرّف النموذج صراحةً ويتولى معالجة الاستجابة بنفسه.

اختيار نموذج وإعداد مفتاح API

استخدم معرّف نموذج تدعمه واجهة API ومعلمات يدعمها ذلك النموذج. يختار المثال nano-banana-pro مع aspectRatio: "1:1" وresolution: "1K"، بما يطابق طلب الصورة الوارد في دليل البدء السريع لواجهة API. وقد أكد طلب GET /models مُصادَق عليه واختبار الإنتاج صلاحية هذه التوليفة لحساب الاختبار في 4 سبتمبر 2026. تحقّق مجددًا من توافر النموذج ودعم المعلمات لحسابك قبل التنفيذ الفعلي. فتغيير سلسلة اسم النموذج وحدها لا يكفي لضمان بقاء بقية الطلب صالحًا.

أنشئ مفتاحًا في لوحة تحكم API، ثم مرّره إلى عملية الخادم عبر PIXMIND_API_KEY. استخدم آليتك الخاصة لإدارة الأسرار إن كانت متاحة. تعرض الأمثلة التالية صيغة ضبط متغير البيئة باستخدام قيمة نائبة، وليس بيانات اعتماد صالحة للاستخدام.

في PowerShell:

$env:PIXMIND_API_KEY = "REPLACE_WITH_YOUR_PRIVATE_API_KEY"
$env:PIXMIND_MODEL = "nano-banana-pro"
$env:PIXMIND_PROMPT = "A ceramic coffee cup on a plain studio background, soft side lighting, no text"

في Bash:

export PIXMIND_API_KEY="REPLACE_WITH_YOUR_PRIVATE_API_KEY"
export PIXMIND_MODEL="nano-banana-pro"
export PIXMIND_PROMPT="A ceramic coffee cup on a plain studio background, soft side lighting, no text"

تُعدّ هذه الإسنادات جلسة الصدفة الحالية والعمليات التي تُشغّل منها. وهي لا تنشئ مهمة. احرص على حماية سجل أوامر الصدفة وتسجيلات الجلسة عند إدخال سر حقيقي، ولا تحفظ ذلك السر مطلقًا في نظام التحكم بالإصدارات. اتبع إرشادات المصادقة بشأن فصل مفاتيح التطوير عن مفاتيح الإنتاج وتدوير المفاتيح بعد انكشافها.

عنوان URL الأساسي لهذا الدليل هو:

https://aihub-admin.aimix.pro/api-platform/v1

أضف /generations أو /tasks/{taskId} إلى ذلك العنوان الأساسي. ولا تُضف /v1 مرة ثانية. يمكن اكتشاف النماذج عبر GET /models؛ أما دليل النماذج فهو المكان الأنسب لقراءة الإمكانات الخاصة بكل نموذج قبل اختيار المعلمات.

إرسال أول طلب لتوليد الصور باستخدام cURL

طلب cURL بديل لأمر submit في Node.js، وليس خطوة إعداد يجب تنفيذها أولًا. فكلاهما يرسل طلب توليد. وقد يؤدي تشغيلهما معًا إلى إنشاء مهمتين خاضعتين للفوترة. إذا أرسلت الطلب باستخدام cURL، فاستخدم بعده أمر resume في Node.js مع معرّف المهمة الذي أعاده الطلب.

يستخدم هذا المثال صيغة Bash. في PowerShell، استخدم عميل Node.js أدناه بدلًا من لصق محارف متابعة الأسطر الخاصة بـ Bash في الطرفية.

curl --connect-timeout 10 --max-time 30 \
  --request POST \
  'https://aihub-admin.aimix.pro/api-platform/v1/generations' \
  --header "Authorization: Bearer $PIXMIND_API_KEY" \
  --header 'Content-Type: application/json' \
  --data '{
    "model": "nano-banana-pro",
    "type": "image",
    "prompt": "A ceramic coffee cup on a plain studio background, soft side lighting, no text",
    "aspectRatio": "1:1",
    "resolution": "1K"
  }'

الوصف النصي والمعلمات في جسم طلب cURL هذا قيم مكتوبة مباشرةً. وتغيير PIXMIND_PROMPT لا يغيّر JSON هنا؛ فعميل Node.js هو الذي يقرأ متغير البيئة ذلك. يساعد هذا التمييز على الفصل بوضوح بين الطلب الذي تنوي إرساله وإعدادات الصدفة المحيطة به.

فيما يلي مثال توضيحي مختصر لاستجابة قبول الطلب. المعرّف فيه قيمة نائبة، وليس معرّف اختبار الإنتاج؛ و12345 ليس معرّف مهمة ينبغي لك الاستعلام عنها.

{
  "code": 1000,
  "message": "success",
  "data": {
    "id": "img_12345",
    "taskId": 12345
  }
}

غلّفت استجابات الوسائط التي اختُبرت في بيئة الإنتاج البيانات الناجحة داخل كائن يحتوي على code وmessage وdata وtimestamp؛ ويحذف المثال التوضيحي الطابع الزمني وحقولًا أخرى. يتطلب النجاح في هذا المسار استجابة HTTP ناجحة واستجابة تطبيق صالحة معًا. اقرأ data.taskId، وليس data.id: فقد يحتوي الأخير على سلسلة ذات بادئة مثل img_12345، بينما يستخدم مسار الاستعلام عن المهمة المعرّف الرقمي.

احفظ ذلك المعرّف الرقمي فورًا. إذا انتهت مهلة الطلب قبل أن تتلقاه، فتوقف وتحقّق مما آل إليه الإرسال بالرجوع إلى سجلات مهام حسابك أو فريق الدعم. تكرار POST ليس بديلًا آمنًا لمعرفة ما حدث.

الاستعلام الدوري عن المهمة وقراءة روابط الصور

استعلم عن المهمة الموجودة حتى تصل إلى حالة نهائية. تشرح وثائق المهام غير المتزامنة الحالات pending وprocessing وready وfailed. ولا تُنهي مسار الاستعلام الدوري هذا إلا الحالتان الأخيرتان.

Submit once
    |
Save numeric taskId
    |
GET /tasks/{taskId} <--- wait, then query again
    |                            ^
    +--- pending / processing ---+
    |
    +--- ready  ---> read images, stop
    |
    +--- failed ---> report failure, stop

لإجراء استعلام يدوي في Bash، استبدل المعرّف النائب بمعرّف مهمتك:

TASK_ID="REPLACE_WITH_YOUR_NUMERIC_TASK_ID"
curl --connect-timeout 10 --max-time 30 \
  "https://aihub-admin.aimix.pro/api-platform/v1/tasks/$TASK_ID" \
  --header "Authorization: Bearer $PIXMIND_API_KEY"

في البنية المعتمدة حاليًا لاستجابة الوسائط، لكل حقل تحتاج إليه دور مختلف:

الحقل معناه في هذا العميل
data.taskId المعرّف الرقمي المستخدم للاستعلام عن المهمة الموجودة
data.status يحدد ما إذا كان ينبغي مواصلة الانتظار، أو قراءة النتيجة، أو التوقف بسبب الفشل
data.images مصفوفة روابط الصور الناتجة، وتُستخدم بعد الوصول إلى ready
data.videoUrl حقل الفيديو الناتج، وليس مصفوفة نتائج الصور

استجابة ready التي لا تحتوي على روابط صور قابلة للاستخدام لا تُعدّ نتيجة صورة ناجحة لتطبيقك. أظهِر هذا التعارض مع معرّف المهمة حتى يمكن التحقيق فيه. ولا تستبدل النتيجة برابط توضيحي أو تُبلغ بأن صورة قد نُزّلت.

يطبع العميل روابط الصور التي تعيدها الاستجابة؛ وهو لا يجلب ملفات الصور أو يؤرشفها. إذا كان تطبيقك يحتاج إلى تخزين دائم، فصمّم ذلك بوصفه خطوة مستقلة وتحقّق من شروط الاحتفاظ بالملفات واستخدامها ذات الصلة. ولا تستنتج من وجود رابط ضمانًا للتخزين الدائم.

تشغيل مثال Node.js الكامل

استخدم submit لمهمة جديدة واحدة، أو resume لمهمة موجودة. يؤدي تشغيل البرنامج النصي دون وسائط إلى طباعة تعليمات الاستخدام دون إجراء أي استدعاء لواجهة API. يمنع هذا السلوك الافتراضي إعادة التشغيل العادية أو مجرد تفقد واجهة سطر الأوامر من إنشاء مهمة جديدة.

احفظ الشيفرة المصدرية الكاملة أدناه باسم examples/pixmind-image.mjs:

الشيفرة المصدرية الكاملة بلغة Node.js: pixmind-image.mjs
import { pathToFileURL } from 'node:url';

const BASE_URL = 'https://aihub-admin.aimix.pro/api-platform/v1';
const sleep = ms => new Promise(resolve => setTimeout(resolve, ms));

export class ApiError extends Error {
  constructor(message, { status = 0, transient = false, retryAfterMs = 0 } = {}) {
    super(message);
    Object.assign(this, { status, transient, retryAfterMs });
  }
}

export function parseTaskId(value) {
  if (!/^\d+$/.test(String(value))) throw new Error('Use a numeric taskId, not img_...');
  const id = Number(value);
  if (!Number.isSafeInteger(id) || id <= 0) throw new Error('Invalid taskId');
  return id;
}

export function retryAfter(value, now) {
  if (!value) return 0;
  if (/^\d+(\.\d+)?$/.test(value)) return Number(value) * 1000;
  const date = Date.parse(value);
  return Number.isFinite(date) ? Math.max(0, date - now) : 0;
}

export function createClient({
  apiKey,
  fetchImpl = fetch,
  now = Date.now,
  wait = sleep,
  random = Math.random,
  requestTimeoutMs = 30_000,
  pollTimeoutMs = 300_000,
  maxConsecutiveErrors = 5,
} = {}) {
  if (typeof apiKey !== 'string' || !apiKey.trim()) throw new Error('Set PIXMIND_API_KEY');

  async function request(path, method, payload, timeoutMs = requestTimeoutMs) {
    let response;
    let body;
    try {
      response = await fetchImpl(`${BASE_URL}${path}`, {
        method,
        redirect: 'error',
        headers: {
          Authorization: `Bearer ${apiKey}`,
          ...(payload ? { 'Content-Type': 'application/json' } : {}),
        },
        ...(payload ? { body: JSON.stringify(payload) } : {}),
        signal: AbortSignal.timeout(Math.max(1, Math.ceil(timeoutMs))),
      });
      // Read the body inside the timeout/network error boundary as well.
      body = await response.text();
    } catch {
      throw new ApiError('Network error or request timeout', { transient: true });
    }
    let envelope;
    try { envelope = JSON.parse(body); } catch { /* handle below */ }
    const transient = response.status === 429 || response.status >= 500;
    if (!response.ok) {
      // Do not echo arbitrary server bodies, prompts, credentials, or output URLs.
      throw new ApiError(`HTTP ${response.status}; inspect the account and request`, {
        status: response.status,
        transient,
        retryAfterMs: retryAfter(response.headers.get('retry-after'), now()),
      });
    }
    if (!envelope || typeof envelope !== 'object') {
      throw new ApiError('Expected a JSON API response');
    }
    if (envelope.code !== 1000 || !envelope.data) {
      throw new ApiError('API returned an unsuccessful or incomplete envelope');
    }
    return envelope.data;
  }

  async function submit({ model = 'nano-banana-pro', prompt } = {}) {
    if (typeof model !== 'string' || !model.trim()) throw new Error('A model is required');
    if (typeof prompt !== 'string' || !prompt.trim()) throw new Error('A prompt is required');
    try {
      const data = await request('/generations', 'POST', {
        model, type: 'image', prompt, aspectRatio: '1:1', resolution: '1K',
      });
      // The public media contract returns a number, not the prefixed display ID.
      if (typeof data.taskId !== 'number') throw new Error('Missing numeric taskId');
      return parseTaskId(data.taskId);
    } catch (error) {
      // A timeout or malformed response does not prove that creation failed.
      throw new Error(`Submission not confirmed: ${error.message}. No automatic retry was made. Check task records before submitting again.`);
    }
  }

  async function poll(taskId) {
    const id = parseTaskId(taskId);
    const deadline = now() + pollTimeoutMs;
    let attempts = 0;
    let errors = 0;
    const timedOut = () => new Error(`Stopped waiting for task ${id}; it may still be running. Resume this ID later.`);
    while (now() < deadline) {
      let retryFloor = 0;
      let task;
      try {
        task = await request(`/tasks/${id}`, 'GET', undefined,
          Math.min(requestTimeoutMs, deadline - now()));
        errors = 0;
      } catch (error) {
        if (now() >= deadline) throw timedOut();
        if (!(error instanceof ApiError) || !error.transient) throw error;
        errors += 1;
        if (errors >= maxConsecutiveErrors) {
          throw new Error(`Stopped after ${errors} consecutive query errors for task ${id}; resume this ID later.`);
        }
        retryFloor = error.retryAfterMs;
      }
      if (now() >= deadline) throw timedOut();
      if (task) {
        if (task.taskId !== id) throw new Error('Task response ID does not match the requested task');
        if (task.status === 'failed') throw new Error(`Task ${id} failed; inspect its record before creating another task.`);
        if (task.status === 'ready') {
          if (!Array.isArray(task.images) || task.images.length === 0 ||
              !task.images.every(url => {
                try { return ['https:', 'http:'].includes(new URL(url).protocol); }
                catch { return false; }
              })) throw new Error(`Task ${id} is ready but has no valid image URLs`);
          return task.images;
        }
        if (!['pending', 'processing'].includes(task.status)) {
          throw new Error(`Task ${id} returned an unrecognized status; inspect its record.`);
        }
      }
      // Client policy, not a PixMind latency guarantee or server-side retry feature.
      const ceiling = Math.min(10_000, 1_000 * 2 ** Math.min(attempts++, 4));
      const delay = Math.max(retryFloor, ceiling * (0.5 + 0.5 * random()));
      const remaining = deadline - now();
      if (delay >= remaining) {
        // Never poll earlier than Retry-After just to fit the local deadline.
        await wait(Math.max(0, remaining));
        throw timedOut();
      }
      await wait(delay);
    }
    throw timedOut();
  }

  return { submit, poll };
}

export async function main(args = process.argv.slice(2), env = process.env, deps = {}) {
  const log = deps.log ?? console.log;
  const [mode, rawId] = args;
  if (!mode) {
    log('Usage: node examples/pixmind-image.mjs submit | resume TASK_ID');
    return;
  }
  if (!((mode === 'submit' && args.length === 1) || (mode === 'resume' && args.length === 2))) {
    throw new Error('Use submit, or resume followed by a numeric taskId');
  }
  const resumeId = mode === 'resume' ? parseTaskId(rawId) : undefined;
  const client = createClient({ ...deps, apiKey: env.PIXMIND_API_KEY });
  const id = resumeId ?? await client.submit({
    model: env.PIXMIND_MODEL || 'nano-banana-pro',
    prompt: env.PIXMIND_PROMPT || 'A studio photograph of an unbranded ceramic coffee cup on a plain background',
  });
  // Save this line in your application record before relying on the polling process.
  log(`TASK_ID=${id}`);
  log(`Resume without a new generation: node examples/pixmind-image.mjs resume ${id}`);
  const images = await client.poll(id);
  log(JSON.stringify({ taskId: id, images }, null, 2));
}

if (process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href) {
  main().catch(error => { console.error(error.message); process.exitCode = 1; });
}

تفقد أولًا واجهة الأوامر دون إرسال أي طلب:

node examples/pixmind-image.mjs

بعد التحقق من المفتاح ومعلمات النموذج والرسوم المتوقعة، أنشئ مهمة واحدة:

node examples/pixmind-image.mjs submit

عند نجاح الإنشاء، يطبع العميل TASK_ID فورًا، قبل انتظار الصورة. انسخ القيمة الفعلية إلى مكان خاص. لا يحفظ هذا المثال المعرّف في ملف أو قاعدة بيانات، لذا قد تفقد مرجع الاستئناف عند إغلاق الطرفية إذا لم تحفظ المخرجات.

لمواصلة الاستعلام عن مهمة، استبدل 12345 بتلك القيمة المحفوظة:

node examples/pixmind-image.mjs resume 12345

ينفّذ هذا الأمر طلبات GET للاستعلام عن المهمة فقط. وهو لا يقرأ وصفًا نصيًا جديدًا ولا ينشئ صورة أخرى. يفترض أن تنتج عن الحالة النهائية الناجحة روابط مخرجات لمهمتك أنت؛ ولا نقدّم هنا مخرجات إنتاج مختلقة بوصفها معيارًا للمقارنة.

يستخدم المثال حدًا قدره 30 ثانية لكل طلب HTTP، وموعدًا نهائيًا للاستعلام الدوري بعد خمس دقائق. تستخدم إعادة محاولات GET تأخيرًا يتزايد أُسّيًا مع إضافة تفاوت عشوائي، وحدًا محليًا أقصى للتأخير قدره 10 ثوانٍ، وترويسة استجابة Retry-After صالحة حيثما تنطبق. تكون الأولوية لمدة الانتظار الأطول التي يطلبها الخادم؛ وإذا تعذر احتواؤها ضمن الموعد النهائي المحلي، يتوقف العميل دون إجراء الاستعلام مبكرًا. ينهي الخطأ العابر الخامس المتتالي في GET هذه المحاولة، ما يتيح أربع إعادات للمحاولة ضمن سلسلة الأخطاء تلك. هذه القيم إعدادات للعميل، وليست اتفاقية لمستوى الخدمة أو وعدًا بأن كل صورة ستكتمل في غضون خمس دقائق.

اختر سياسة إجمالية للانتظار تناسب تطبيقك. فقد تستمر المهمة طويلة التنفيذ بعد انتهاء جلسة الطرفية أو طلب الويب. في الخدمة المنشورة، خزّن معرّف المهمة مع سجل العمل الخاص بك، وأتِح للمتصفح نقطة نهاية مستقلة للاستعلام عن الحالة، بدلًا من إلزام المستخدم بإبقاء اتصال واحد مفتوحًا.

معالجة الأخطاء دون تكرار العمل المدفوع

تعامل مع عدم اليقين بشأن الإنشاء على نحو مختلف عن فشل استعلام الحالة. يمكن تكرار GET للاستعلام عن المهمة دون إنشاء عملية توليد أخرى. أما POST للإنشاء الذي ضاعت استجابته فقد يكون قد بدأ العمل بالفعل، لذلك لا يعيد المثال إرساله تلقائيًا مطلقًا.

الحالة المرصودة الإجراء التالي
HTTP 400 تحقّق من بنية الطلب ومعرّف النموذج والمعلمات المدعومة قبل إجراء محاولة أخرى مقصودة.
HTTP 401 أو 403 تحقّق من المصادقة وصلاحيات الوصول. لا تضع المفتاح في السجلات أثناء تصحيح الأخطاء.
HTTP 404 عند الاستعلام عن مهمة تحقّق من المعرّف الرقمي المحفوظ والحساب الذي يملك المهمة. ولا تستبدله بمعرّف مهمة لشخص آخر.
HTTP 429 عند طلب GET لمهمة انتظر وفقًا لترويسة Retry-After الصالحة وسياسة إعادة المحاولة المحدودة في العميل.
خطأ شبكة أو خطأ خادم عابر عند طلب GET لمهمة أعد الاستعلام نفسه مع التدرج في التأخير، وتوقف عند بلوغ الحدود المضبوطة.
حالة المهمة failed توقف عن الاستعلام وأبلِغ عن فشل المهمة. يتطلب بدء توليد جديد قرارًا مستقلًا.
انتهاء مهلة الإنشاء، أو JSON غير صالح، أو غياب taskId تعامل مع نتيجة الإنشاء بوصفها مجهولة. تحقّق من سجلات المهام قبل الإرسال مجددًا.

لا تفترض أن جميع الأخطاء لها بنية استجابة واحدة. في تحقق الإنتاج بتاريخ 4 سبتمبر، أعاد GET /models دون مصادقة الحالة HTTP 401 مع code وmessage فقط؛ بينما تضمنت استجابات الوسائط الناجحة بعد المصادقة أيضًا data وtimestamp. لذلك لا يضمن هذا الدليل وجود requestId، أو علامة retryable، أو حقل سعر في كل استجابة. تصف حالات الأخطاء الأخرى أعلاه كيفية تعامل العميل معها، ولا تدّعي أن كل حالة أُعيد إنتاجها في بيئة الإنتاج. احتفظ بحالة HTTP ورسالة التطبيق بعد تنقيحها من المعلومات الحساسة إن وُجدت؛ وتعامل مع أجسام الاستجابة غير السليمة بوصفها أخطاء، بدلًا من التسبب في تعطل التنفيذ داخل JSON.parse.

انتهاء مهلة الاستعلام الدوري يعني أن العميل توقف عن الانتظار، وليس أن المهمة البعيدة قد أُلغيت. احتفظ بالمعرّف واستأنف لاحقًا. كما أن الحالة غير المألوفة ليست دليلًا على النجاح: يتوقف هذا العميل ويُبلغ عنها للفحص. لا تنتقل تلقائيًا إلى حالة «مكتمل» لمجرد أن قيمة ما غير موجودة ضمن تعليمة الاختيار.

لاستكشاف المشكلات، احتفظ بمعرّف المهمة ومعرّف النموذج والعملية وحالة HTTP والوقت التقريبي. تجنّب تسجيل ترويسات التفويض أو أجسام الطلب الكاملة التي تحتوي على أوصاف نصية خاصة. وتحقّق مما إذا كانت أجسام الاستجابة التشخيصية أو روابط المخرجات تتضمن معلومات حساسة قبل مشاركتها.

تكييف النمط للفيديو والمحادثة

يمكن استخدام فكرة الإرسال ثم الاستعلام الدوري نفسها للفيديو، لكنه يحتاج إلى تحقق خاص من الطلب وقراءة خاصة للنتيجة. تحقّق من الوسائط المدخلة المطلوبة والمدة والدقة وخيارات الصوت للنموذج المحدد للفيديو، بدلًا من افتراض إمكانية إعادة استخدام حقول جسم طلب الصورة. يستخدم الفيديو المكتمل data.videoUrl، وليس data.images.

يشرح دليل Video Agent سير عمل إبداعيًا تفاعليًا. وقد يساعدك على تحديد اللقطة المطلوبة قبل أتمتة التوليد، لكن وجود ميزة في Agent لا يثبت وجود معلمة API تحمل الاسم نفسه.

المحادثة مسار تكامل منفصل. المسار الموثّق /chat/completions متوافق مع OpenAI، ويعيد استجابة محادثة، أو تدفقًا عند طلب البث المتدفق. لا تمرّر تلك الاستجابة إلى محلّل data.taskId في عميل الصور. فاستخدام عنوان URL أساسي واحد لا يعني تطابق بنية الاستجابة في جميع نقاط النهاية.

أبقِ نطاق عميل الصور محدودًا حتى تتحقق من هذا المسار. أضف محوّلًا للفيديو أو عميلًا للمحادثة بصورة مستقلة، مع اختبارات لبنية استجابته الخاصة. هذا الفصل أسهل للفهم من دالة واحدة تخمّن ما إذا كان الكائن المُعاد مهمة صورة، أو مهمة فيديو، أو رسالة محادثة.

التحقق من التكامل واختيار الخطوة التالية

تتحقق الاختبارات المحلية باستخدام المحاكاة من سلوك العميل دون استهلاك رصيد API. اجتازت مجموعة الاختبارات المرفقة 29 اختبارًا في بيئة Windows وNode.js المذكورة، بما في ذلك مسار الإرسال بطلب POST واحد، والاستئناف بطلبات GET فقط، والاستجابات غير السليمة، والفشل النهائي، والمواعيد النهائية، وحدود إعادة المحاولة. احفظ ملف الاختبار المرفق بجوار الشيفرة المصدرية للعميل، ثم شغّل المجموعة من مجلد الدليل:

node --test examples/pixmind-image.test.mjs

لا تثبت اختبارات المحاكاة التوافر في بيئة الإنتاج أو آلية الفوترة. استخدم تحقق مستقل مضبوط في 4 سبتمبر 2026 العميل نفسه، وكان نطاقه المسجّل كما يلي:

عنصر الاختبار النتيجة المرصودة
الطلب طلب POST /generations واحد، باستخدام nano-banana-pro وtype: "image" وaspectRatio: "1:1" وresolution: "1K"
الوصف النصي A studio photograph of an unbranded ceramic coffee cup on a plain background
مرجع الاستئناف معرّف المهمة الرقمي 64114، الذي احتُفظ به قبل الاستعلام الدوري؛ وهو مرجع للأدلة، وليس معرّفًا ينبغي للقراء الاستعلام عنه
الاكتمال ثمانية استعلامات GET عن المهمة نفسها؛ الحالة النهائية ready، مع رابط واحد في data.images
فحص المخرجات حُمّلت الصورة المُعادة بأبعاد 1024 × 1024 بكسل، وظهر فيها بوضوح كوب خزفي على خلفية سادة
الفوترة حددت استجابة تسعير API تكلفة هذه الإعدادات بمقدار 120 نقطة؛ وسجّل دفتر حركات API المرتبط بالمهمة خصمًا قدره 120 نقطة

استخدم التحقق مفتاح API واحدًا موجودًا في المشروع، ووصفًا نصيًا غير حساس، دون رفع ملفات مرجعية أو إعادة محاولة الإنشاء تلقائيًا. وطُوبق قيد سجل الحركات مع معرّف المهمة، بدلًا من استنتاجه من عرض رصيد Studio. لم تُختبر فعليًا سوى هذه التوليفة الواحدة ومسار توليد الصورة الناجح؛ ولم تُختبر الفيديوهات أو المحادثة أو فوترة حالات الفشل أو استرداد الرسوم أو موثوقية التشغيل المتكرر. تحقّق من السعر مجددًا قبل إرسال طلبك، ولا تتعامل مع هذه الرسوم التاريخية بوصفها عرض سعر ساريًا دائمًا.

قبل ربط المثال بسير عمل فعلي يستخدمه المستخدمون، تأكد مما يلي:

  • يبقى المفتاح على الخادم، ولا يظهر في حزم العميل أو لقطات الشاشة أو السجلات العامة.
  • تدعم خدمة API الحالية النموذج المحدد وجميع المعلمات.
  • يترك لك الطلب المقبول معرّف مهمة رقميًا يمكنك استعادته.
  • لا ينفّذ resume أي POST للإنشاء، بما في ذلك بعد أخطاء الاستعلام العابرة.
  • تنتج عن فشل المهمة والنتيجة الفارغة وانتهاء المهلة المحلية مخرجات تشخيصية مختلفة.
  • لا يؤدي ضياع استجابة الإنشاء إلى إرسال طلب ثانٍ تلقائيًا.

في تحققك الفعلي المضبوط، سجّل الحساب والنموذج ونطاق التكلفة المعتمد والطلب المنقّح من المعلومات الحساسة ومعرّف المهمة والاستجابة النهائية وقيد الفوترة الفعلي. افحص المخرجات بشكل مستقل عن التحقق من وجود رابطها. ولا تُجرِ «اختبارات تحقق سريعة» متكررة دون مراعاة أن كل إرسال جديد قد ينشئ عملًا مدفوعًا.

عندما تكون مستعدًا، أنشئ مفتاح API واختر طريقة واحدة للإرسال. ابنِ انطلاقًا من مسار العمل الذي يحتفظ بالمهمة قبل إضافة قوائم الانتظار أو رفع الملفات أو المعالجة على دفعات. إذا كانت خطوتك التالية دمج الملفات المولّدة في عملية مراجعة إبداعية، فإن سير عمل إعلان منتج باستخدام Canvas يقدم مثالًا مستقلًا يديره الإنسان؛ وليس وعدًا بإمكانية تنفيذ مشاريع Canvas عبر واجهة API هذه.

المسؤولية التحريرية: PixMind Editorial Team هو اسم الجهة المؤلفة لهذا الدليل. ويستند الدليل إلى الوثائق الرسمية، وتنفيذ متحكم الوسائط في المشروع، و29 اختبارًا محليًا باستجابات محاكاة، والتحقق الوحيد في بيئة الإنتاج الموصوف أعلاه، وقد روجعت جميعها في 4 سبتمبر 2026. يُحتفظ بسجلات المهمة والفوترة المنقّحة من المعلومات الحساسة لأغراض التحقق التحريري. ولا يُدّعى هنا وجود مؤهلات لمهندس بعينه، أو نتائج مقارنة لجودة النماذج، أو اختبار معياري للأداء.


الدليل الكامل لفيديو Wan 3.0: المدخلات والصوت والأسعار وواجهة API

继续浏览中,生成器即将加载...