تحقق من الاستشهادات برمجيًا. نقطة نهاية واحدة، تدفق عبر SSE.

Base URL

https://api.citetrue.com

بداية سريعة

  1. انتقل إلى لوحة التحكم → مفاتيح API وانقر مفتاح API جديد. انسخ المفتاح الذي يبدأ بـ sk_. يُعرض مرة واحدة فقط.
  2. أضف المفتاح في Authorization: Bearer sk_… مع كل طلب.
  3. أرسل POST لـ task إلى /verify/v2. الاستجابة text/event-stream؛ استهلك أحداث SSE حتى ترى task_completed.

أدنى نداء:

curl -N -X POST https://api.citetrue.com/verify/v2 \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"text":"[1] Vaswani, A., Shazeer, N., Parmar (2017). Attention is all you need."}'

-N يعطّل تخزين curl المؤقت فتتدفق أحداث SSE سطرًا سطرًا. لم يعد هناك depth لتختاره — تمر كل المراجع بالمسار نفسه. معظمها يكلف رصيدًا واحدًا؛ أما الصعبة التي تحتاج إلى مزيد من مصادر البيانات ومزيد من التحليل فحتى 5.

أمثلة العميل

SSE استجابة HTTP طويلة الأمد حيث ينتهي كل حدث بسطر فارغ (\n\n). تجاوز الأسطر التي لا تبدأ بـ data: وقم بتحليل JSON لبقية.

ملاحظة المتصفح: لا يستطيع EventSource المدمج إرسال رأس Authorization — استخدم fetch + ReadableStream كما يظهر أدناه.

Node 18+ with native fetch.

const API = 'https://api.citetrue.com'
const KEY = process.env.API_KEY

async function verify(text) {
  const resp = await fetch(`${API}/verify/v2`, {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${KEY}`,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({ text }),
  })
  if (!resp.ok) throw new Error(`${resp.status}: ${await resp.text()}`)

  const reader = resp.body.getReader()
  const decoder = new TextDecoder()
  const refs = []
  let buf = ''

  while (true) {
    const { value, done } = await reader.read()
    if (done) break
    buf += decoder.decode(value, { stream: true })
    let idx
    while ((idx = buf.indexOf('\n\n')) !== -1) {
      const chunk = buf.slice(0, idx); buf = buf.slice(idx + 2)
      for (const line of chunk.split('\n')) {
        if (!line.startsWith('data: ')) continue
        const evt = JSON.parse(line.slice(6))
        if (evt.event === 'ref_completed') {
          refs.push(evt.data.ref)
        }
        if (evt.event === 'task_completed') return { refs, balance: evt.data.balance }
        if (evt.event === 'error') throw new Error(evt.error)
      }
    }
  }
}

const out = await verify('[1] Vaswani, A., Shazeer, N., Parmar (2017). Attention is all you need.')
console.log(out)

المصادقة

مفاتيح API رموز bearer طويلة الأمد بالشكل sk_<40-char-token>. أرسلها في ترويسة Authorization:

Authorization: Bearer sk_AbCd123…
  • يمكنك إلغاء مفتاح من لوحة التحكم. الإلغاء ساري خلال ثوانٍ.
  • يمكن للمفتاح فعل كل ما يفعله مستخدمه. تعامل معه ككلمة مرور — دوّره وحدّد نطاقه لكل تكامل.

حدود المعدل

لكل مفتاح API مُحدِّد token-bucket:

  • دفعة: 10 طلبات.
  • مستدام: 60 طلبًا/دقيقة (bucket يُعاد ملؤه بمعدل 1 token/s).
  • عند التجاوز يفشل الطلب بـ 429 مع ترويسة Retry-After (ثوانٍ).

المُحدِّد لكل مفتاح؛ المفاتيح المختلفة لنفس الحساب لها دِلاء مستقلة. الأرصدة تُطبَّق إضافةً لذلك.

ترويسات الطلب

Every endpoint accepts the same authentication and content-type headers; only the request body and URL differ.

Headerمطلوبالقيمة
AuthorizationyesBearer sk_…
Content-Typeyesapplication/json

Responses are 200 OK with Content-Type: text/event-stream.

data: {"event":"<name>","data":{...},"error":""}

POST /verify/v2

Split a text blob into references and verify each. Supply exactly one of text (new task) or taskHash (resume). Every reference goes through the same flow — there is no verification level to choose.

جسم الطلب

الحقلالنوعملاحظات
textstringNew verify task. Max 10MB. Accepts numbered, bulleted, blank-line-separated, BibTeX, or in-text prose with (Author, Year) citations.
taskHashstringResume an existing task — replays cached state or attaches to live stream. References already charged aren't charged again; any that still need work are finished and billed as usual.
forceboolBypass the task-level dedup cache (forces a fresh run, billed like a new check).
localestringOptional 2-letter language code ("zh", "ja", "de", …). When set, AI translates the per-ref note into that language and surfaces it under noteTranslated[locale]. Default "" / "en" = no translation.

Idempotency: same text + same user returns the cached task on second POST (no re-billing) unless force: true.

Deprecated fields

  • depth — still accepted but ignored (1, 5, 20 or omitted all behave the same). Don't send it.
  • refHash + parentTaskHash — legacy single-reference mode kept for older clients. It ignores depth and simply finishes that one reference, billed under the normal rules. New integrations shouldn't use it.

طلب مثال (text)

{
  "text": "[1] Vaswani, A., Shazeer, N., Parmar (2017). Attention is all you need.\n[2] Piketty, T. (2016). Capital in the twenty-first century. Harvard University Press."
}

طلب مثال (resume)

{
  "taskHash": "f0e1d2c3b4a5..."
}

تسلسل الأحداث النموذجي

task_created → refs_created (N refs) →
  [ref_processing + ref_completed] × N (parallel) +
  task_progress × several →
task_completed

Per-ref assessment

Each ref_completed event carries an assessment string from this closed set:

  • authentic — paper exists and is the one cited. value contains the matched paper.
  • unsure — found something but can't confirm; notices and confidence describe why.
  • inauthentic — definitively not found / fabricated / unrelated.
  • invalid — input wasn't a citation; pipeline refused to search before any datasource hit.
  • error — verification failed on this single ref; sibling refs may still succeed. data.errors[] lists tokens (datasource_unavailable, timeout, rate_limited, parse_failed).
  • exceeded — account ran out of credits before this ref could run.

Notices on a result (year mismatch, author mismatch, …) are orthogonal to assessment — even an authentic verdict can carry notices worth showing. data.cost is the total credits this task has charged for the reference (0–5): 1 for most references, up to 5 for tricky ones that needed more data sources and more analysis, 0 if it was already paid for in another task. It covers every connection and resume of the same task, and the same number is sent on every push, replays included — overwrite it, don't add it up across reconnects. data.depth is kept only for compatibility with older clients — ignore it.

أحداث SSE

SSE event names emitted during verification. Listen for task_completed as the terminal success event; error for terminal failure.

  • task_created — task accepted, hash assigned.
  • refs_created — text was split into N refs.
  • split_completed — splitting phase finished.
  • ref_processing / ref_status — per-ref progress signal.
  • ref_completed — per-ref final assessment.
  • task_completed — all refs done; carries cost (credits newly charged during this connection, 0 for a pure replay) and the account balance afterwards (can be negative — see Credits & billing).
  • task_progress — periodic progress %.
  • warn — non-fatal warning.
  • error — terminal task-level failure.

GET /credits

GET /credits/v1 — returns current credit balance. Auth required. The balance can be negative (see Credits & billing).

الأرصدة والفوترة

Most references cost 1 credit. Tricky ones that need more data sources and more analysis can cost up to 5. Each reference is charged 1 credit when it's queued; anything extra is added when it finishes. Cached tasks (same text + user) do not re-bill.

Reading the charge: data.cost in ref_completed is the running total this task has charged for that reference — the same number is sent again on reconnects and replays, so overwrite it rather than adding it up. cost in task_completed is what this connection newly charged (0 for a pure replay), so after a reconnect it won't equal the sum of the per-ref costs. balance is the account balance afterwards.

Running out: a reference that hasn't started when the balance can't cover it comes back as exceeded, and the task still ends with task_completed. If you run out of credits mid-check, references already in progress still finish; the overage is deducted at your next credit reset, so balance can be negative.

مرجع الأخطاء

Standard HTTP status codes apply (400 invalid, 401 auth missing/invalid, 402 insufficient credits, 429 rate-limited, 5xx upstream). SSE-level failures arrive as a final error event.

الإصدارات والاستقرار

Path-versioned (/verify/v2 etc.). Breaking changes bump the version segment; backwards-compatible additions ship in-place.

يتولى صيانته فريق CiteTrue · آخر تحديث: