Auto-Reader

شريك الرسم: صور داخل تطبيقك

امنح قرّاءك صورة لأي صفحة يقرؤونها، بأربعين نمطًا فنيًا وتسعة وعشرين عصرًا تاريخيًا. تستدعي واجهة واحدة من خادمك (أو تعطي صفحة الويب رمزًا قصير العمر)، ونحن نرسم، وتدفع دولارًا واحدًا في الشهر عن كل قارئ استخدمها فعلًا.

احصل على مفتاح شريك

ماذا تقدّم

الأسعار

السعردولار واحد لكل مستخدم نشط في الشهر
المستخدم النشطمن صنع صورة واحدة على الأقل في ذلك الشهر. المسجَّل الذي لم يصنع شيئًا مجاني.
المشمول30 صورة لكل مستخدم نشط في الشهر
الحد الأدنى10 دولارات في الشهر (تغطي حتى 10 مستخدمين نشطين)
أكثر من 30 في الشهريتوقف ذلك المستخدم حتى أول الشهر التالي

فاتورتك هي الأكبر من: 10 دولارات، أو عدد المستخدمين النشطين بالدولار (max($10, active users x $1)). الصور المرفوضة والفاشلة والملغاة لا تُحتسب أبدًا، ولا تجعل المستخدم نشطًا. طلب نسختين من المشهد ("count": 2) يُحتسب صورتين.

كيف تعمل الفوترة

  1. احصل على مفتاح API عادي ببريدك الإلكتروني، واضغط رابط التأكيد الذي نرسله.
  2. استدعِ POST /v1/partner/signup بذلك المفتاح. تحصل فورًا على مفتاح الشريك (nsk_partner_...) ورابط دفع Polar لأول 10 دولارات (تُحفظ البطاقة). يبدأ مفتاح الشريك العمل لحظة وصول الدفعة.
  3. في أول كل شهر يخصم Polar مبلغ 10 دولارات، ومعه دولار عن كل مستخدم نشط فوق العشرة في الشهر السابق (يُحاسَب الاستهلاك بعد انتهاء الشهر).
  4. الفواتير والإيصالات تصلك من Polar. يمكنك الإلغاء متى شئت، ويبقى مستخدموك يعملون حتى نهاية الشهر المدفوع.

مهلة السداد

بداية سريعة (curl)

العنوان الأساسي: https://api.auto-reader.com. هناك نوعان من المفاتيح: مفتاح الشريك (nsk_partner_...، على الخادم فقط، لإدارة المستخدمين، ولا يصنع صورًا) والمفتاح الفرعي للمستخدم (nsk_live_...، يصنع الصور لمستخدم واحد وتُحتسب عليك).

0. التسجيل

# a. an ordinary key with your email (we send a verification link: click it)
curl -X POST https://api.auto-reader.com/signup \
  -H "Content-Type: application/json" -d '{"email": "[email protected]"}'
# -> {"api_key":"nsk_live_...", ...}

# b. become a partner with that key
curl -X POST https://api.auto-reader.com/v1/partner/signup \
  -H "Authorization: Bearer $NSK_LIVE" -H "Content-Type: application/json" -d '{}'
# -> {"partner_id":"ptn_...","partner_key":"nsk_partner_...","status":"pending",
#     "checkout_url":"https://..."}   keep the partner key: it is your server credential

# c. pay the first $10 at checkout_url. Then:
curl -H "Authorization: Bearer $NSK_PARTNER" https://api.auto-reader.com/v1/partner/me
# -> {"status":"active", ...}   (403 EMAIL_NOT_VERIFIED in step b = click the link first)

1. أنشئ مفتاحًا لأحد مستخدميك (أو استرجعه)

المعرّف external_id نفسه يعيد المفتاح نفسه، فتكرار الطلب آمن (201 عند الإنشاء و200 عند الاسترجاع). يتكوّن external_id من 1 إلى 128 حرفًا من A-Z a-z 0-9 . _ : @ -.

curl -X POST https://api.auto-reader.com/v1/partner/users \
  -H "Authorization: Bearer $NSK_PARTNER" -H "Content-Type: application/json" \
  -d '{"external_id": "user-123"}'
# -> {"external_id":"user-123","api_key":"nsk_live_...","created":true,"partner_status":"active",
#     "pictures_month":0,"pictures_left_month":30,"pictures_today":0,"pictures_left_today":10}

2. ارسم صفحة

curl -X POST https://api.auto-reader.com/v1/illustrate \
  -H "Authorization: Bearer $USER_KEY" -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{"text": "The old sailor knocked on the inn door...", "style_id": "auto"}'
# -> 202 {"job_id":"img_...","status":"queued","poll":"/v1/jobs/img_...","eta_seconds":8, ...}

3. تابع الحالة ثم نزّل الصورة

تابع كل 3 ثوانٍ. تستغرق الصورة عادة بضع ثوانٍ، وأكثر حين يزدحم الطابور.

curl -H "Authorization: Bearer $USER_KEY" https://api.auto-reader.com/v1/jobs/img_...
# -> {"status":"done","images":[{"n":1,"url":"/v1/jobs/img_.../image/1", ...}]}
curl -H "Authorization: Bearer $USER_KEY" -o page.webp \
  https://api.auto-reader.com/v1/jobs/img_.../image/1

4. صفحة الويب: رمز قصير العمر

لا تضع مفتاح الشريك في أي مكان غير خادمك. لصفحة ويب، سجّل نطاقات الصفحة مرة واحدة، ثم دع خادمك يُصدر رمزًا لمستخدم واحد (ttl من 30 إلى 900 ثانية، والافتراضي 900). يستعمله المتصفح مفتاحًا له؛ ولا يعمل إلا مع /v1/illustrate و/v1/jobs/*، وفقط حين تكون ترويسة Origin من المتصفح أحد النطاقات التي سجّلتها.

curl -X POST https://api.auto-reader.com/v1/partner/settings \
  -H "Authorization: Bearer $NSK_PARTNER" -H "Content-Type: application/json" \
  -d '{"allowed_origins": ["https://yourapp.com"]}'

curl -X POST https://api.auto-reader.com/v1/partner/tokens \
  -H "Authorization: Bearer $NSK_PARTNER" -H "Content-Type: application/json" \
  -d '{"external_id": "user-123", "ttl": 900}'
# -> {"token":"nsk_tok_...","expires_at":"2026-11-09T12:15:00.000Z","external_id":"user-123"}

التطبيقات الأصلية (أندرويد وiOS) لا ترسل ترويسة Origin، فالرموز ليست لها: أعطِ التطبيق المفتاح الفرعي الخاص بذلك المستخدم من خادمك (لا يصنع إلا صورًا لذلك المستخدم وحده، ويمكنك إلغاؤه متى شئت). الزر الجاهز لصفحات الويب قادم.

5. الاستهلاك والفاتورة حتى الآن

curl -H "Authorization: Bearer $NSK_PARTNER" https://api.auto-reader.com/v1/partner/me
# -> {"status":"active","trust_level":0,"month":"2026-11","active_users":12,"pictures_month":140,
#     "pictures_today":9,"estimated_bill_usd":12,"limits":{...},"grace":null,"allowed_origins":[...]}
# (/v1/partner/usage is the same answer)

المستخدمون: استعلام وقائمة وإزالة

إزالة المستخدم تلغي مفتاحه الفرعي؛ تنتهي المهام الجارية ولا يُحتسب عليه شيء بعدها. يبقى عدّاده الشهري محفوظًا، فإعادة إنشاء المعرّف external_id نفسه لا تمنحه 30 صورة جديدة.

curl -H "Authorization: Bearer $NSK_PARTNER" https://api.auto-reader.com/v1/partner/users/user-123
curl -H "Authorization: Bearer $NSK_PARTNER" "https://api.auto-reader.com/v1/partner/users?cursor="
# -> {"users":[{"external_id":"user-123"}, ...],"cursor":null}
curl -X DELETE -H "Authorization: Bearer $NSK_PARTNER" \
  https://api.auto-reader.com/v1/partner/users/user-123
# -> {"external_id":"user-123","revoked":true}

الإعدادات

اخفض حدود المستخدم لحسابك كله، أو سجّل نطاقات الويب (حتى 20 نطاقًا بصيغة https://host[:port]).

curl -X POST https://api.auto-reader.com/v1/partner/settings \
  -H "Authorization: Bearer $NSK_PARTNER" -H "Content-Type: application/json" \
  -d '{"user_monthly": 20, "user_daily": 5, "allowed_origins": ["https://yourapp.com"]}'

أمثلة برمجية

JavaScript (Node على الخادم)

// Node 18+ (server side). Never ship the partner key to a browser or an app.
const API = "https://api.auto-reader.com";
const P = { Authorization: "Bearer " + process.env.NSK_PARTNER, "Content-Type": "application/json" };

async function illustrate(externalId, text) {
  const u = await (await fetch(API + "/v1/partner/users", { method: "POST", headers: P,
    body: JSON.stringify({ external_id: externalId }) })).json();
  const H = { Authorization: "Bearer " + u.api_key, "Content-Type": "application/json",
    "Idempotency-Key": crypto.randomUUID() };
  const r = await fetch(API + "/v1/illustrate", { method: "POST", headers: H,
    body: JSON.stringify({ text, style_id: "auto" }) });
  const job = await r.json();
  if (r.status !== 202) throw new Error(job.code || job.error);   // e.g. USER_MONTHLY_LIMIT, PARTNER_PAUSED
  for (;;) {
    await new Promise(res => setTimeout(res, 3000));
    const j = await (await fetch(API + job.poll, { headers: H })).json();
    if (j.status === "done") return Buffer.from(await (await fetch(API + j.images[0].url, { headers: H })).arrayBuffer());
    if (j.status === "failed" || j.status === "cancelled") throw new Error(j.error || j.status);
  }
}

Python

import os, time, uuid, requests

API = "https://api.auto-reader.com"
P = {"Authorization": "Bearer " + os.environ["NSK_PARTNER"]}

def illustrate(external_id, text):
    key = requests.post(API + "/v1/partner/users", headers=P,
                        json={"external_id": external_id}).json()["api_key"]
    h = {"Authorization": "Bearer " + key}
    r = requests.post(API + "/v1/illustrate", json={"text": text, "style_id": "auto"},
                      headers={**h, "Idempotency-Key": str(uuid.uuid4())})
    job = r.json()
    if r.status_code != 202:
        raise RuntimeError(job.get("code") or job.get("error"))
    while True:
        time.sleep(3)
        j = requests.get(API + job["poll"], headers=h).json()
        if j["status"] == "done":
            return requests.get(API + j["images"][0]["url"], headers=h).content
        if j["status"] in ("failed", "cancelled"):
            raise RuntimeError(j.get("error") or j["status"])

المتصفح (برمز قصير العمر)

// Your backend: POST /v1/partner/tokens with the partner key, return {token} to the page.
const { token } = await (await fetch("/api/illustrate-token")).json();   // your own endpoint
const H = { Authorization: "Bearer " + token, "Content-Type": "application/json",
  "Idempotency-Key": crypto.randomUUID() };
const job = await (await fetch("https://api.auto-reader.com/v1/illustrate", { method: "POST",
  headers: H, body: JSON.stringify({ text: pageText, style_id: "auto" }) })).json();
// poll job.poll every 3 s with the same header, then show images[0].url (fetch it with the header, make a blob URL)

Kotlin (أندرويد، OkHttp)

// Android: ask YOUR backend for this user's sub-key (it calls /v1/partner/users), then call the API with it.
val userKey = myBackend.illustrateKey()
val req = Request.Builder()
    .url("https://api.auto-reader.com/v1/illustrate")
    .header("Authorization", "Bearer $userKey")
    .header("Idempotency-Key", UUID.randomUUID().toString())
    .post("""{"text": ${JSONObject.quote(pageText)}, "style_id": "auto"}"""
        .toRequestBody("application/json".toMediaType()))
    .build()
val job = JSONObject(client.newCall(req).execute().body!!.string())
// then poll job.getString("poll") every 3 s and download images[0].url

Swift (iOS)

// iOS: same flow, the user's sub-key from your own backend.
let userKey = try await myBackend.illustrateKey()
var req = URLRequest(url: URL(string: "https://api.auto-reader.com/v1/illustrate")!)
req.httpMethod = "POST"
req.setValue("Bearer \(userKey)", forHTTPHeaderField: "Authorization")
req.setValue("application/json", forHTTPHeaderField: "Content-Type")
req.setValue(UUID().uuidString, forHTTPHeaderField: "Idempotency-Key")
req.httpBody = try JSONSerialization.data(withJSONObject: ["text": pageText, "style_id": "auto"])
let (data, _) = try await URLSession.shared.data(for: req)
// decode {"job_id","poll"}, poll every 3 s, then download images[0].url

الحدود والاستخدام العادل

رموز الأخطاء

الحالة وcodeالمعنى
403 EMAIL_NOT_VERIFIEDالتسجيل: اضغط رابط التأكيد أولًا
403 PARTNER_NOT_LIVEلم تُدفع أول 10 دولارات بعد
402 PARTNER_PAUSEDانتهت المهلة، أو اعتراض على دفعة، أو إلغاء: الصور متوقفة؛ المتابعة والتنزيل يعملان
403 PARTNER_REVIEWمستخدم جديد يتجاوز سقف الالتزام غير المدفوع (انظر الحدود)
429 USER_MONTHLY_LIMIT / USER_DAILY_LIMITحد ذلك المستخدم: 30 في الشهر / 10 في اليوم (أو حدك الأقل)؛ Retry-After يحدد الموعد
429 BURST / PARTNER_DAILY_LIMIT / PARTNER_NEW_USERS_LIMITحد الدقيقة، أو سقفك اليومي، أو حد المستخدمين الجدد في اليوم
429 USER_PAUSEDأكثر من 10 طلبات مرفوضة اليوم: ذلك المستخدم متوقف 24 ساعة
403 SCOPEمفتاح غير مناسب لهذا المسار (مفتاح الشريك في طلب صورة، أو مفتاح فرعي في غير الصور)
403 PARTNER_KEY_IN_BROWSERاستُعمل مفتاح الشريك مع ترويسة Origin
401 TOKEN_INVALID / 403 TOKEN_ORIGINرمز منتهٍ أو معدَّل أو مستخدمه مُلغى / نطاق الصفحة غير مسجَّل
403 POLICY_BLOCKED / CUSTOM_BLOCKEDلا يمكن رسم النص أو الكلمات المخصصة؛ لا تعد المحاولة تلقائيًا

تحمل ردود الصور أيضًا X-Credits-Charged: 0 (مستخدموك لا ينفقون رصيدًا أبدًا)، وفي مهلة السداد X-Partner-Warning: payment_failed.

أسئلة شائعة

هل يكلّف المستخدم غير النشط شيئًا؟

لا. يُحتسب فقط من صنع صورة واحدة على الأقل في الشهر.

هل يستطيع مستخدمي اختيار النمط؟

نعم. أرسل style_id وera إن شئت. القائمة هي نفسها في صفحة الرسم (يعرضها GET /v1/illustrate/status)، و"auto" يختار نمطًا من النص.

هل تحمل الصور علامة؟

لا علامة لـ Auto-Reader ولا رمز QR. الصور مُعلَّمة بأنها من صنع الذكاء الاصطناعي في بياناتها الوصفية، كما في موقعنا.

هل يستطيع مستخدمي استعمال OCR أو الترجمة أو الكتب الكاملة بمفتاحه الفرعي؟

لا. المفتاح الفرعي يصنع الصور المفردة ويتابعها وينزّلها ويحذفها فقط (/v1/illustrate و/v1/illustrate/status و/v1/jobs/*)، ويقرأ استهلاكه (/v1/usage).

هل تحتفظون بنصوص مستخدميّ؟

لا. يتحول النص إلى وصف قصير للمشهد يُحفظ مع الصورة 48 ساعة، ثم يُحذف الاثنان.

ماذا لو بلغ مستخدم 30 صورة؟

يصله 429 USER_MONTHLY_LIMIT حتى أول الشهر القادم، ولا يتأثر باقي المستخدمين.

أين المرجع الكامل للواجهة؟

طلبات الصور هي واجهة /v1/illustrate العامة: أرسل text (صفحة واحدة، حتى 4,000 حرف) وstyle_id وera اختياريًا وcount (1 أو 2) وdetail (standard أو detailed) وpurpose (page أو chapter أو cover)، مع ترويسة Idempotency-Key كي لا تصنع إعادة المحاولة صورتين. يصلك 202 مع job_id، فتتابع /v1/jobs/{id} حتى done، ثم تنزّل كل images[].url، وDELETE /v1/jobs/{id} يحذفها مبكرًا. ويخبرك GET /v1/illustrate/status هل الخدمة مفتوحة. للأسئلة: [email protected].