POST /api/studio/rewrite يأخذ منتج (اسم + وصف حالي) ويرجع وصف محسّن بـAI، streamed بـServer-Sent Events.

#الـRequest body

FieldTypeRequiredالوصف
productNamestringyesاسم المنتج (max 500)
currentDescriptionstringnoالوصف الحالي (max 20,000)
productCategorystringnoفئة المنتج (يفيد الـAI في النبرة)
productAttributesstringnoخصائص (لون، مقاس، إلخ)
sallaStoreIdstringnoمعرّف متجر سلة (للـquota لكل متجر)
sallaProductIdstringnoمعرّف المنتج (للـanalytics)

#SSE Response

الـresponse هو text/event-stream، فيه 4 أنواع events:

EventData shapeمعنى
chunk{ "text": "..." }جزء من الوصف الجديد، يتم append
usage{ "input": N, "output": N, "cached": N, "id": "..." }إحصائيات الـtokens (واحدة في النهاية)
done{}الـstream اكتمل
error{ "message": "..." }حدث خطأ

#مثال كامل

javascript
const response = await fetch('/api/studio/rewrite', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  credentials: 'include',
  body: JSON.stringify({
    productName: 'قميص قطن مصري',
    currentDescription: 'قميص جميل بألوان متعددة',
    productCategory: 'أزياء رجالية',
    sallaStoreId: '1234567890',
    sallaProductId: '1828908128',
  }),
});

if (!response.ok) {
  const err = await response.json();
  console.error(err);
  return;
}

const reader = response.body.getReader();
const decoder = new TextDecoder();
let buffer = '';
let newDescription = '';

while (true) {
  const { value, done } = await reader.read();
  if (done) break;
  buffer += decoder.decode(value, { stream: true });

  // Parse SSE records (separated by blank line)
  let idx;
  while ((idx = buffer.indexOf('\n\n')) >= 0) {
    const record = buffer.slice(0, idx);
    buffer = buffer.slice(idx + 2);

    let eventName = 'message';
    let dataStr = '';
    for (const line of record.split('\n')) {
      if (line.startsWith('event: ')) eventName = line.slice(7);
      else if (line.startsWith('data: ')) dataStr += line.slice(6);
    }
    if (!dataStr) continue;
    const data = JSON.parse(dataStr);
    if (eventName === 'chunk') newDescription += data.text;
    if (eventName === 'usage') console.log('Used tokens:', data);
  }
}

console.log('Final:', newDescription);

#Quota

#Brand voice

لو حابب الـrewrite يتطابق مع نبرة علامتك:

  1. 1
  2. 2

    ارفع 5-10 أوصاف بتحبها. AI يستخرج النبرة.

  3. 3

    حفظ. كل rewrite بعد كده هيستخدم النبرة دي.

نبرة الـbrand بتتحفظ في studiobrandvoice لكل متجر منفصل.

#Caching

الـAPI بيستخدم prompt caching على Anthropic:

  • الـsystem prompt + brand voice = cached (5min TTL)
  • النتيجة: الـcalls المتتالية أرخص وأسرع بـ80-90%

#Errors

"Code""Sample
401{ "error": "unauthenticated" }
400{ "error": "invalid_request", "message": "..." }
429{ "error": "quotaexceeded", "retryafter_hours": 18 }
500{ "error": "anthropic_error" } (نادر)