Tài liệu API v1

REST + JSON. Mọi request cần header Authorization với API key.

Xác thực

Key thuộc về workspace nơi bạn tạo nó: key tạo trong workspace tổ chức trừ credit của tổ chức và tính vào hạn mức tháng của bạn; key mất hiệu lực khi bạn rời tổ chức.

Gửi key trong header Authorization: Bearer orx_live_…. Key có hai quyền: scan:write (gửi, xóa) và scan:read (xem). Giới hạn mặc định 120 request/phút mỗi key; header X-RateLimit-Remaining cho biết số lượt còn lại, vượt giới hạn trả 429 kèm Retry-After.

Gửi tài liệu để quét — POST /v1/scans

Trả 202 kèm lượt quét ở trạng thái QUEUED. Mỗi lượt trừ credit cố định; nếu không đủ credit trả 402 INSUFFICIENT_CREDITS. Gửi lại đúng file với cùng tùy chọn trong 7 ngày sẽ nhận lại kết quả cũ (deduplicated: true, không trừ credit).

curl https://api.orivex.vn/v1/scans \
  -H "Authorization: Bearer $ORIVEX_API_KEY" \
  -H "Idempotency-Key: assignment-42-student-7" \
  -F "file=@bai-tieu-luan.docx" \
  -F "callbackUrl=https://your-app.example/webhooks/orivex"

Hoặc gửi văn bản thuần dạng JSON:

curl https://api.orivex.vn/v1/scans \
  -H "Authorization: Bearer $ORIVEX_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"title": "Bài 1", "text": "Nội dung cần kiểm tra..."}'

Tùy chọn (form field hoặc JSON):

  • sources: internal, web (mặc định cả hai)
  • excludeQuotes, excludeBibliography: bỏ qua trích dẫn / tài liệu tham khảo (mặc định true)
  • storeInRepository: lưu bài vào kho để so khớp về sau (mặc định true)
  • excludeOwnSubmissions: không so với bài cũ của chính tài khoản (mặc định true)
  • minMatchWords: độ dài tối thiểu của một đoạn trùng, 5–50 (mặc định 8)
  • semantic: phát hiện đoạn viết lại ý và đoạn dịch Anh ↔ Việt (mặc định true, không tốn thêm credit)
  • callbackUrl: URL https nhận webhook khi quét xong

Header Idempotency-Key (tối đa 100 ký tự) giúp gửi lại an toàn khi mạng lỗi: cùng key luôn trả về cùng lượt quét và chỉ trừ credit một lần.

Hỗ trợ PDF (kể cả PDF ảnh scan, được nhận dạng chữ bằng OCR), DOCX, TXT (UTF-8), tối đa 20 MB. Bài OCR có cờ ocr: true trong báo cáo và có thể chậm hơn vài chục giây.

Xem kết quả

GET /v1/scans/{id}          # trạng thái, similarity (% trùng nguyên văn), paraphraseSimilarity
GET /v1/scans/{id}/report   # báo cáo đầy đủ: text, matches[], paraphrases[], sources[]
GET /v1/scans/{id}/report.pdf  # báo cáo PDF để in / gửi kèm
GET /v1/scans?page=0&size=20
DELETE /v1/scans/{id}       # xóa file, báo cáo và dữ liệu trong kho
GET /v1/balance             # số dư credit

Trạng thái: QUEUED → PROCESSING → COMPLETED hoặc FAILED. Lượt quét thất bại được hoàn credit tự động. start/end trong báo cáo là vị trí ký tự trong trường text.

Báo cáo có hai con số độc lập: similarity là tỷ lệ từ trùng nguyên văn (so dấu vân tay), còn paraphraseSimilarity là tỷ lệ từ nằm trong câu bị viết lại ý hoặc dịch (so theo nghĩa bằng mô hình ngôn ngữ đa ngữ), chỉ tính trên phần chưa trùng nguyên văn nên tổng hai số không vượt quá 100%. Mỗi phần tử của paraphrases có kind là paraphrase hoặc translation và score (độ tương đồng 0–1). Đây là tín hiệu để người chấm xem lại, không phải kết luận đạo văn.

Webhook

Khi lượt quét kết thúc, Orivex gửi POST tới callbackUrl với sự kiện scan.completed hoặc scan.failed. Nếu bạn không trả mã 2xx, Orivex thử lại tối đa 7 lần (sau 10 giây, 1 phút, 5 phút, 30 phút, 2 giờ, 6 giờ, 12 giờ); hãy xử lý theo id của sự kiện để không làm một việc hai lần.

Orivex-Signature: t=1767225600,v1=5f2c...

# Xác minh (Node.js)
const [t, v1] = header.split(",").map(p => p.split("=")[1]);
const expected = crypto.createHmac("sha256", WEBHOOK_SECRET)
  .update(`${t}.${rawBody}`).digest("hex");
const ok = crypto.timingSafeEqual(Buffer.from(v1), Buffer.from(expected))
  && Math.abs(Date.now() / 1000 - Number(t)) < 300;

SDK

SDK chính thức cho JavaScript/TypeScript (@orivex/sdk, Node.js ≥ 20, không phụ thuộc thư viện ngoài) và Python (orivex, Python ≥ 3.9). SDK tự thử lại khi lỗi mạng, 429 hoặc 5xx, luôn gửi Idempotency-Key khi tạo lượt quét (thử lại không trừ credit hai lần) và có hàm xác minh chữ ký webhook.

// JavaScript / TypeScript
import { Orivex, verifyWebhook } from "@orivex/sdk";
const orivex = new Orivex({ apiKey: process.env.ORIVEX_API_KEY });
const scan = await orivex.scans.createText("Nội dung...", { title: "Bài 1" });
const done = await orivex.scans.wait(scan.id);
const report = await orivex.scans.report(done.id);

# Python
from orivex import Orivex, verify_webhook
client = Orivex()  # đọc ORIVEX_API_KEY
scan = client.scans.create("bai-tieu-luan.pdf", callback_url="https://your-app.example/webhooks/orivex")
event = verify_webhook(raw_body, headers["Orivex-Signature"], WEBHOOK_SECRET)

Mã lỗi thường gặp

  • 401 INVALID_API_KEY — key sai, đã thu hồi hoặc hết hạn
  • 402 INSUFFICIENT_CREDITS — hết credit
  • 402 QUOTA_EXCEEDED — key của tổ chức: thành viên tạo key đã dùng hết hạn mức tháng do quản trị đặt
  • 429 TOO_MANY_FAILED_SCANS — hôm nay đã có quá nhiều bài lỗi do file (quá dài, hỏng, rỗng); bài lỗi vẫn được hoàn credit
  • 413 FILE_TOO_LARGE, 415 UNSUPPORTED_FILE_TYPE
  • 429 RATE_LIMITED, 429 TOO_MANY_ACTIVE_SCANS — quá nhiều lượt quét đang chạy cùng lúc
  • Lỗi trong errorCode khi FAILED: ENCRYPTED_PDF, EXTRACTION_FAILED, EXTRACTION_TIMEOUT, EMPTY_DOCUMENT, DOCUMENT_TOO_LARGE