مساعدو الذكاء الاصطناعي
وثائق قابلة للقراءة آليًا وكتلة سياق جاهزة للّصق كي يكتب مساعد البرمجة بالذكاء الاصطناعي كود فيديوهاتي كما ينبغي — ملف llms.txt وصفحات Markdown والإعداد لـ Claude Code وCodex وopencode وCursor.
إذا كنت تكتب كود فيديوهاتي بمساعدة أداة ذكاء اصطناعي، فامنحها الحقائق منذ البداية. تقدّم هذه الصفحة شيئين لهذا الغرض: وثائق يقرؤها المساعد كنصّ صِرف، وكتلة سياق تلصقها في ملف قواعد مساعدك كي يتوقّف عن تخمين أسماء الدوال والحالات.
وثائق قابلة للقراءة آليًا
كل صفحة هنا تُقدَّم أيضًا بصيغة Markdown صافية، إضافةً إلى ملفَّي فهرسة يتبعان اصطلاح llms.txt. وجِّه أداتك إلى هذه الملفات بدلًا من كشط الصفحات المعروضة:
- /llms.txt — سطر واحد لكل صفحة: العنوان، ورابط Markdown، ووصف مختصر. هذه هي الخريطة التي يقرؤها المساعد أولًا.
- /llms-full.txt — كل الصفحات مجموعةً في تدفّق نصّي واحد، لأداة تريد المجموعة كاملة في طلب واحد.
/md/en/<slug>.md— أي صفحة بصيغة Markdown الخام. مثلًا /md/en/quickstart.md أو /md/en/sdks/node.md. والصفحات العربية على/md/ar/<slug>.md.
علِّم مساعدك فيديوهاتي
الكتلة أدناه موجز مركَّز موجَّه للكود: المصادقة، ومسار الرفع ثم الانتظار ثم التشغيل، ونقاط الدخول لكل بيئة، وأحداث الويب هوك، وأصناف الأخطاء، والمزالق التي تُعثِر المحاولات الأولى. انسخها، أو نزّلها مباشرةً إلى ملف قواعد.
# Videohati — context for AI coding assistants
Videohati is a video hosting API for developers and teams: upload a file, it is
processed into adaptive streams, and you embed a player that measures views and
deters copying. The player and docs are Arabic-first (RTL) and also English.
## Authentication
- Project API keys are Bearer tokens: `Authorization: Bearer vh_live_...` in
production, `vh_test_...` against test data. The SDK derives the mode from the
prefix.
- Never put an API key in a browser or client bundle. For playback, create the
session on your server and hand only the short-lived `sessionToken` to the page.
- Projects and API keys are created and managed in the dashboard, not through
the API.
- Base URL: `https://api.videohati.com`. Dashboard: `https://app.videohati.com`.
## Golden path (Node, @videohati/node 1.0.0-rc.0)
```ts
import { Videohati } from "@videohati/node";
const videohati = new Videohati({ apiKey: process.env.VIDEOHATI_API_KEY });
// 1. Upload — one call runs create -> start -> multipart parts -> complete.
const uploaded = await videohati.videos.upload("./lecture-01.mp4", {
onProgress: (p) => console.log(`${p.uploadedBytes}/${p.totalBytes}`),
});
// 2. Wait until it is playable end to end (polls; do not build your own loop).
const video = await videohati.videos.waitForState(uploaded.videoId);
console.log(video.state); // "ready"
// 3. Create a playback session on the server; hand the token to the page.
const session = await videohati.playback.createSession({
videoId: video.videoId,
viewerDisplayText: "Ahmed K.", // drawn into the on-video watermark
});
// 4. Embed the player with session.sessionToken (see per-stack notes below).
```
Video states: `uploading` -> `uploaded` -> `encoding` -> `ready` (or `failed`).
There is no "queued" state.
## Per-stack entry points
**Node (@videohati/node)** — `new Videohati({ apiKey?, env?, baseUrl?,
maxRetries?, timeoutMs?, fetch? })`. Resources:
- `videos` — create, list, get, delete, setThumbnail, resetThumbnail,
startUpload, completeUpload, abortUpload, upload, waitForState.
- `playback` — createSession. Your app only calls createSession; the player
performs the rest of the playback calls on its own.
- `webhooks` — register, list, get, update, delete, rotateSecret,
reopenCircuit, sendTest, listDeliveries, verify.
**React (@videohati/react 1.0.0-rc.0)** — wrap once in `<VideohatiProvider
baseUrl=...>`, read config with `useVideohatiConfig()`. Play with
`<VideohatiPlayer videoId projectId sessionToken autoplay lang="ar" ... />`
(sessionToken is required and comes from a server call). Hooks:
`useVideohatiUpload({ projectId })`, `useVideohatiVideo(videoId, {
pollIntervalMs })`, `useWebhookDeliveries(projectId, endpointId, {...})`.
**Laravel (videohati/laravel 1.0.0-rc.0, PHP >= 8.2)** — reach the client
through the `Videohati\Laravel\Facades\Videohati` facade: `Videohati::videos()`,
`Videohati::playback()`, `Videohati::webhookEndpoints()`. Note the circuit method
is `reopen(...)` here (it is `reopenCircuit(...)` in Node). Render the embed with
the Blade directive: `@videohatiPlayer(['videoId' => $video->id, 'sessionToken'
=> $session->sessionToken])`.
**Plain HTML (@videohati/player 1.0.0)** — load the script and set attributes:
```html
<script src="https://cdn.videohati.com/player.js" async></script>
<div
data-videohati-video-id="..."
data-videohati-project-id="..."
data-videohati-session-token="<sessionToken>"
data-videohati-autoplay="muted"
data-videohati-lang="ar"
></div>
```
It auto-mounts on every `[data-videohati-video-id]` element and auto-destroys on
pagehide. Programmatic API: `Videohati.create({ target, videoId, projectId,
sessionToken, ... })`.
## Webhooks
Eight event types are delivered as `{ id, type, created_at, project_id, data }`:
`video.upload.completed`, `video.encoding.ready`, `video.encoding.failed`,
`video.deleted`, `playback.started`, `playback.completed`, `payment.succeeded`,
`payment.failed`.
Verify every delivery with the raw request body (never re-serialized JSON):
```ts
import { verifyWebhookSignature, SIGNATURE_HEADER } from "@videohati/node";
const { valid, event } = verifyWebhookSignature({
payload: req.rawBody, // exactly as received
header: req.headers[SIGNATURE_HEADER], // "videohati-signature"
secret: process.env.VIDEOHATI_WEBHOOK_SECRET,
});
if (!valid) return res.status(400).end();
res.status(200).end(); // return 2xx within 10 seconds
```
Header: `Videohati-Signature: t=<unix_ts>,v1=<hex_sha256>`, HMAC-SHA256 over
`<unix_ts>.<raw_body>`, 300s tolerance. Return a 2xx within 10 seconds — a slow
or non-2xx response counts as a failed delivery. Failed deliveries retry with a
growing delay; a persistently failing endpoint trips its circuit breaker, which
you clear with `webhooks.reopenCircuit(projectId, id)`.
## Errors and retries
Every non-2xx throws a typed subclass of `VideohatiError` (each carries `.status`
and a machine `.code`): `VideohatiConnectionError`, `VideohatiTimeoutError`,
`VideohatiValidationError` (400), `VideohatiAuthenticationError` (401),
`VideohatiPermissionError` (403), `VideohatiNotFoundError` (404),
`VideohatiConflictError` (409), `VideohatiRateLimitError` (429, read
`.retryAfterSeconds`), `VideohatiServerError` (5xx). GET/DELETE, 429s, and 5xxs
retry automatically with exponential backoff capped at 8 seconds (2 retries by
default; 429 honors `Retry-After`).
## Pitfalls
- Do not hand-roll a status poll — call `videos.waitForState(videoId)` (default
target states `["ready","failed"]`, 3s interval, 15-minute timeout).
- Playback sessions expire by design; mint a fresh one per view on the server
rather than caching `sessionToken`.
- Custom thumbnails must be JPEG, PNG, or WebP and at most 5 MB.
- Uploads are multipart with resumable parts — pass an `idempotencyKey` to make
`videos.upload` resume-safe across restarts.
## Pointers
- Machine-readable index: https://docs.videohati.com/llms.txt
- Full text of every page: https://docs.videohati.com/llms-full.txt
- Any page as markdown: https://docs.videohati.com/md/en/<slug>.md
(for example /md/en/quickstart.md, /md/en/sdks/node.md, /md/en/guides/webhooks.md)
curl -o CLAUDE.md https://docs.videohati.com/ai/videohati-context.mdهيّئ أداتك
يقرأ كل مساعد قواعد مشروعه من ملف بعينه. ضَع كتلة السياق في الملف الصحيح فتَسري على كل مطالبة في ذلك المشروع.
يقرأ Claude Code ملف CLAUDE.md في جذر المستودع ويعامله كذاكرة مشروع دائمة
الحضور. أضِف كتلة السياق إليه — يحفظ هذا أي ملاحظات لديك ويضيف فيديوهاتي تحتها.
curl https://docs.videohati.com/ai/videohati-context.md >> CLAUDE.mdيقرأ Codex ملف AGENTS.md في جذر المستودع. أضِف كتلة السياق كي تُحمَّل حقائق
فيديوهاتي مع كل مهمة في هذا المشروع.
curl https://docs.videohati.com/ai/videohati-context.md >> AGENTS.mdيعتمد opencode أيضًا اصطلاح AGENTS.md. يعمل السطر نفسه — وإن كان الملف موجودًا
فهذا يضيف فيديوهاتي في نهايته دون المساس بالباقي.
curl https://docs.videohati.com/ai/videohati-context.md >> AGENTS.mdيقرأ Cursor ملفات القواعد من .cursor/rules/. احفظ الكتلة كقاعدة .mdc، ثم
أضِف ترويسة من سطرين كي يستدعيها Cursor عند الحاجة فقط لا مع كل مطالبة.
mkdir -p .cursor/rules
curl -o .cursor/rules/videohati.mdc https://docs.videohati.com/ai/videohati-context.mdأضِف هذه الترويسة إلى أعلى ملف .cursor/rules/videohati.mdc:
---
description: Videohati video API — auth, upload, playback sessions, webhooks
alwaysApply: false
---أمّا الأدوات التي تتصفّح الوثائق من تلقاء نفسها فتلتقط /llms.txt تلقائيًا — دون
أي إعداد.