Verifique citações programaticamente. Um endpoint, streamed via SSE.

Base URL

https://api.citetrue.com

Início rápido

  1. Vá ao Painel → Chaves API e clique em Nova chave API. Copie a chave começando com sk_. É mostrada apenas uma vez.
  2. Inclua a chave em Authorization: Bearer sk_… em cada requisição.
  3. POST um task para /verify/v2. A resposta é text/event-stream; consuma eventos SSE até ver task_completed.

Chamada mínima:

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 desativa o buffering do curl para transmitir eventos SSE linha a linha. Não é mais preciso escolher depth: todas as referências passam pelo mesmo fluxo. A maioria custa 1 crédito; as complicadas, que precisam de mais fontes de dados e mais análise, até 5.

Exemplos de cliente

SSE é uma resposta HTTP persistente onde cada evento termina com linha em branco (\n\n). Ignore linhas que não começam com data: e JSON-parse o resto.

Nota do navegador: EventSource nativo não pode enviar cabeçalho Authorization — use fetch + ReadableStream como abaixo.

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)

Autenticação

Chaves API são tokens bearer de longa duração no formato sk_<40-char-token>. Envie-as no cabeçalho Authorization:

Authorization: Bearer sk_AbCd123…
  • Revogue uma chave no Painel. A revogação tem efeito em segundos.
  • Uma chave pode fazer tudo que o usuário dono pode. Trate como senha — rode e limite o escopo por integração.

Limites de taxa

Cada chave API tem um limitador token-bucket:

  • Pico: 10 requisições.
  • Sustentado: 60 requisições/minuto (bucket recarrega a 1 token/s).
  • Excedido, a requisição falha com 429 e cabeçalho Retry-After (segundos).

O limitador opera por chave; chaves diferentes da mesma conta têm buckets independentes. Créditos se aplicam à parte.

Cabeçalhos da requisição

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

HeaderObrigatórioValor
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.

Corpo da requisição

CampoTipoNotas
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.

Idempotência: 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.

Requisição exemplo (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."
}

Requisição exemplo (resume)

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

Sequência típica de eventos

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.

Eventos 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).

Créditos e cobrança

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.

Referência de erros

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.

Versionamento e estabilidade

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

Mantido pela equipa CiteTrue · Última atualização: