شريك الرسم: صور داخل تطبيقك
امنح قرّاءك صورة لأي صفحة يقرؤونها، بأربعين نمطًا فنيًا وتسعة وعشرين عصرًا تاريخيًا. تستدعي واجهة واحدة من خادمك (أو تعطي صفحة الويب رمزًا قصير العمر)، ونحن نرسم، وتدفع دولارًا واحدًا في الشهر عن كل قارئ استخدمها فعلًا.
ماذا تقدّم
- يرسل مستخدمك نص صفحة، فنختار أبرز لحظة فيها ونرسمها بالنمط والعصر اللذين تختارهما (أو
"style_id": "auto"). - الصور والأنماط والعصور وقواعد الأمان نفسها التي في صفحة الرسم عندنا. الصور مُعلَّمة بأنها من صنع الذكاء الاصطناعي.
- لكل مستخدم من مستخدميك مفتاح فرعي خاص به، فتعمل الحدود والاستهلاك والإلغاء لكل مستخدم على حدة.
- تُحفظ النتائج 48 ساعة ثم تُحذف. ولا نحفظ نص الصفحة نفسه.
الأسعار
| السعر | دولار واحد لكل مستخدم نشط في الشهر |
|---|---|
| المستخدم النشط | من صنع صورة واحدة على الأقل في ذلك الشهر. المسجَّل الذي لم يصنع شيئًا مجاني. |
| المشمول | 30 صورة لكل مستخدم نشط في الشهر |
| الحد الأدنى | 10 دولارات في الشهر (تغطي حتى 10 مستخدمين نشطين) |
| أكثر من 30 في الشهر | يتوقف ذلك المستخدم حتى أول الشهر التالي |
فاتورتك هي الأكبر من: 10 دولارات، أو عدد المستخدمين النشطين بالدولار (max($10, active users x $1)). الصور المرفوضة والفاشلة والملغاة لا تُحتسب أبدًا، ولا تجعل المستخدم نشطًا. طلب نسختين من المشهد ("count": 2) يُحتسب صورتين.
كيف تعمل الفوترة
- احصل على مفتاح API عادي ببريدك الإلكتروني، واضغط رابط التأكيد الذي نرسله.
- استدعِ
POST /v1/partner/signupبذلك المفتاح. تحصل فورًا على مفتاح الشريك (nsk_partner_...) ورابط دفع Polar لأول 10 دولارات (تُحفظ البطاقة). يبدأ مفتاح الشريك العمل لحظة وصول الدفعة. - في أول كل شهر يخصم Polar مبلغ 10 دولارات، ومعه دولار عن كل مستخدم نشط فوق العشرة في الشهر السابق (يُحاسَب الاستهلاك بعد انتهاء الشهر).
- الفواتير والإيصالات تصلك من Polar. يمكنك الإلغاء متى شئت، ويبقى مستخدموك يعملون حتى نهاية الشهر المدفوع.
مهلة السداد
- إذا فشل دفع التجديد، يستمر كل شيء في العمل 10 أيام بينما يعيد Polar المحاولة.
- خلال ذلك يُظهر
GET /v1/partner/meالحالة"status": "payment_failed"وموعد الإيقاف فيgrace.pause_at، ويحمل كل رد (لك ولمستخدميك) الترويسةX-Partner-Warning: payment_failed. - في اليوم العاشر، إن لم يُدفع المبلغ، يتوقف صنع الصور الجديدة:
402 {"code": "PARTNER_PAUSED"}. أما متابعة الحالة والتنزيل والحذف فتبقى تعمل، ولا يُحذف شيء قبل موعده. - حين يتم الدفع تعود الصور فورًا.
- مهلة واحدة كل 90 يومًا: فشلُ دفعةٍ ثانيةٍ خلال 90 يومًا يوقف الحساب فورًا. والاعتراض على دفعة (chargeback) يوقفه فورًا أيضًا حتى نراجعه.
بداية سريعة (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الحدود والاستخدام العادل
- لكل مستخدم: 30 صورة في الشهر، و10 في اليوم، و3 طلبات صور في الدقيقة، و10 طلبات في الدقيقة إجمالًا. ويمكنك وضع حدود شهرية ويومية أقل.
- لحسابك كله: 60 طلب صورة في الدقيقة، وسقف يومي يرتفع كلما دفعت التجديدات في وقتها (300 في اليوم في البداية، و1,000 بعد أول تجديد مدفوع، و3,000 بعد ثلاثة، وأكثر عند الطلب).
- عدد المستخدمين الجدد في اليوم محدود بالطريقة نفسها: 100، ثم 500، ثم 2,000.
- ما دام حسابك جديدًا، يُحدّ عدد المستخدمين النشطين في الشهر بالأكبر من 50 أو ثلاثة أضعاف آخر فاتورة لك بالدولار. فوق ذلك تُرفض أول صورة لمستخدم جديد بـ
403 PARTNER_REVIEWحتى نراجع؛ ولا يتأثر المستخدمون النشطون الحاليون. - مفتاح الشريك يعمل من الخوادم فقط: يُرفض أي طلب يحمل ترويسة
Originمن متصفح. المفاتيح الفرعية والرموز لا تصنع إلا الصور وتتابعها وتنزّلها وتحذفها (لا OCR ولا ترجمة ولا كتبًا كاملة). إن تسرّب مفتاح الشريك فراسلنا لنستبدله. - نحتسب الطلبات التي يرفضها مرشّح الأمان (
POLICY_BLOCKEDوCUSTOM_BLOCKED). أكثر من 10 رفضات في يوم توقف ذلك المستخدم 24 ساعة. - الاعتراض على دفعة أو استرجاعها عبر البنك يوقف الحساب حتى ننظر فيه.
- حين تزدحم الخدمة قد يصلك
503معRetry-After. لا يُحتسب عليك أبدًا: انتظر وأعد المحاولة بالترويسةIdempotency-Keyنفسها.
رموز الأخطاء
الحالة و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].