اتصال به API Mizgerd
اتاق بسازید، شرکتکنندگان را مدیریت کنید، پیام بفرستید، فایل و تخته را کنترل کنید، ضبط بگیرید و حساب مدرسها را اداره کنید. قواعد دسترسی همان قواعد خود برنامه است.
معماری امن
browser -> your server (holds the key) -> https://mizgerd.com/api/v1
- کلید فقط روی سرور شما میماند. در جاوااسکریپت مرورگر، قالب وردپرس، برنامه موبایل یا مخزن عمومی نگذارید.
- سرور شما اول بررسی میکند کاربر اجازه کار را دارد، بعد با کلید خودش از میزگرد کار میخواهد.
- کلید با اختیار مدیری که ساخته کار میکند، در حد دسترسیهایی که انتخاب شده. اگر آن مدیر غیرفعال شود، کلیدهایش همان لحظه از کار میافتند.
- برای هر سرویس کلید جدا بسازید، کمترین دسترسی را بدهید، دورهای عوض کنید و کلید قدیمی را باطل کنید.
- کلید را در لاگ و پیام خطا چاپ نکنید.
نشانی پایه و احراز هویت
نشانی پایه: https://mizgerd.com/api/v1
- مدیر سامانه در کلیدهای API کلید میسازد. مقدار کلید فقط یک بار دیده میشود.
- کلید را در هدر Authorization: Bearer بفرستید. کوکی و CSRF روی این مسیرها لازم نیست و پذیرفته هم نمیشود.
curl https://mizgerd.com/api/v1/rooms?limit=1 \ -H "Authorization: Bearer mzk_your_key"
دسترسیها
هر عملیات دقیقا یک دسترسی میخواهد؛ write شامل read نیست| دسترسی | امکان | عملیات |
|---|---|---|
| rooms:read | فهرست و جزئیات اتاقها، وضعیت زنده اتاق (صف انتظار، حاضران، چیدمان، ضبط جاری) | ۳ |
| rooms:write | ساخت اتاق، تغییر قفل، اتاق انتظار، گفتگو و ظرفیت، تعیین چیدمان و کیفیت دوربینها، دریافت و تعویض و لغو لینک دعوت | ۶ |
| participants:read | فهرست و خواندن شرکتکنندگان یک اتاق، با مجوزهای موثر هر کدام | ۲ |
| participants:write | پذیرش، رد و حذف مهمان، دادن و گرفتن میکروفن، دوربین و اجازه نقاشی | ۶ |
| messages:read | خواندن گفتگوی عمومی و پیامهای خصوصی فرستادهشده به یک شرکتکننده | ۲ |
| messages:write | نوشتن و حذف پیام عمومی، فرستادن و پس گرفتن پیام خصوصی | ۴ |
| content:read | خواندن اطلاعات و فایل PDF، حاشیهنویسیها، صفحههای تخته و عملیات آنها | ۵ |
| content:write | بارگذاری، تعویض و توقف PDF، تغییر صفحه، حاشیهنویسی، مدیریت صفحههای تخته و نقاشی روی آن | ۱۳ |
| recordings:read | فهرست و وضعیت ضبطها و پخش فایل MP4 | ۳ |
| recordings:write | شروع و پایان ضبط | ۲ |
| users:read | فهرست و خواندن حسابهای مدیر و مدرس | ۲ |
| users:write | ساخت و ویرایش حساب، فعال و غیرفعال کردن، تعیین گذرواژه، خروج اجباری از همه نشستها | ۵ |
مجوزهای شرکتکننده
هر ردیف شرکتکننده یک شیء permissions دارد| کلید | معنا | چطور تعیین میشود |
|---|---|---|
| subscribe | دیدن و شنیدن دیگران | حاضر پذیرفتهشده |
| microphone قابل تعیین | روشن کردن میکروفن | مهمان: مجوز میکروفن. مدرس: همیشه |
| camera قابل تعیین | روشن کردن دوربین | مهمان: مجوز دوربین. مدرس: همیشه |
| screenShare | اشتراک صفحه | فقط مدرس یا مدیری که اتاق را مدیریت میکند. مهمان هرگز |
| draw قابل تعیین | نقاشی روی تخته و PDF | مهمان: مجوز نقاشی. مدرس: همیشه |
| publicChat | نوشتن در گفتگوی عمومی | پذیرفتهشده، گفتگوی اتاق باز است و مدرس ارسال پیام را برایش نبسته است |
| privateMessageReceive | دریافت پیام خصوصی یکطرفه | مهمان پذیرفتهشده؛ مدرس نه |
فقط microphone، camera و draw را میتوان با PATCH /rooms/{roomId}/participants/{participantId}/permissions عوض کرد. بقیه مشتقاند و فرستادنشان 400 میدهد. منتظر، ردشده و حذفشده هیچ مجوزی ندارند. لغو میکروفن یا دوربین همان لحظه روی شرکتکننده وصل اعمال میشود؛ اگر سرور رسانه تایید نکند 503 میگیرید و لغو در پایگاه داده میماند.
کیفیت دوربینها
PATCH /rooms/{roomId} با cameraQuality| مقدار | برچسب | ثبت تصویر | سقف بیتریت |
|---|---|---|---|
| LOW | کم مصرف | 640x360، ۱۵ فریم در ثانیه | حدود 250 kbps (یک لایه) |
| AUTO | خودکار | 1280x720، ۲۴ فریم در ثانیه | حدود 800 kbps، لایههای کوچکتر 180p و 360p |
| HIGH | باکیفیت | 1280x720، ۳۰ فریم در ثانیه | حدود 1200 kbps، لایههای کوچکتر 180p و 360p |
این سقف دوربین هر منتشرکننده است و دریافت تصویر را اجبار نمیکند. ضبط همیشه 720p است و کیفیت منبع میتواند پایینتر باشد.
پاسخ، صفحهبندی و خطا
- موفق: { "data": ..., "requestId": "req_..." }. ساخت چیز تازه 201 میدهد. هر پاسخ هدر X-Request-Id دارد.
- فهرستها کراندارند: limit از ۱ تا ۱۰۰. پاسخ "page": { "next": "...", "limit": 50 } دارد؛ next را بهعنوان cursor پس بفرستید. null یعنی صفحه آخر.
- خطا: { "error": { "code", "message" }, "requestId" }. روی code شرط بگذارید، نه روی متن message که انگلیسی است.
- سقف: ۳۰۰ درخواست در دقیقه برای هر کلید. این شمارنده در حافظه هر پردازش است.
- متن UTF-8 است و فارسی را بدون escape خاصی بفرستید. تاریخها ISO 8601 به وقت UTC با پسوند Z هستند.
- CORS پیشفرض بسته است. فقط مبداهای دقیق فهرستشده در API_CORS_ORIGINS مجازند. برای اتصال سرور به سرور لازم نیست.
- بارگذاری PDF: multipart/form-data با file (تا ۲۵ مگابایت) و pageCount (۱ تا ۲۰۰۰). فایل و ضبط از درخواست بازهای (Range) پشتیبانی میکنند.
| وضعیت | معنا |
|---|---|
| 400 | بدنه یا پارامتر نادرست، یا قاعده دامنه رد شد |
| 401 | کلید نیست، ناشناخته یا باطل است، یا سازندهاش دیگر مدیر فعال نیست |
| 403 | دسترسی کلید کافی نیست (insufficient_scope) یا کار مجاز نیست |
| 404 | نشانی یا منبع پیدا نشد؛ منبع اتاق دیگر هم همین را میگیرد |
| 409 | تعارض وضعیت، مثل ایمیل تکراری، آخرین مدیر فعال یا ضبط باز |
| 413 | بدنه JSON بیش از ۱ مگابایت یا PDF بیش از ۲۵ مگابایت |
| 429 | بیش از ۳۰۰ درخواست در دقیقه برای این کلید؛ Retry-After را رعایت کنید |
| 5xx | خطای سرور یا تاییدنشدن تغییر از سرور رسانه؛ دوباره تلاش کنید و requestId را گزارش دهید |
نمونه کد سمت سرور
فقط جانگهدار mzk_your_keycurl
export MIZGERD_API_KEY="mzk_your_key"
curl -sS https://mizgerd.com/api/v1/rooms \
-H "Authorization: Bearer $MIZGERD_API_KEY" \
-H "Content-Type: application/json" \
-d '{"title":"ریاضی دهم","capacity":150}'Node.js (۱۸ به بالا، fetch داخلی)
const BASE = "https://mizgerd.com/api/v1";
const KEY = process.env.MIZGERD_API_KEY; // مثلا mzk_your_key؛ فقط در سرور
async function mizgerd(method, path, body) {
const res = await fetch(BASE + path, {
method,
headers: { Authorization: `Bearer ${KEY}`, "Content-Type": "application/json" },
body: body === undefined ? undefined : JSON.stringify(body),
});
const json = await res.json();
if (!res.ok) {
const err = new Error(`${json.error.code} (${json.requestId})`);
err.status = res.status;
throw err;
}
return json.data;
}
const room = await mizgerd("POST", "/rooms", { title: "ریاضی دهم", capacity: 150 });
const invite = await mizgerd("GET", `/rooms/${room.id}/invite`);
console.log(room.id, invite.url);PHP (cURL)
<?php
function mizgerd(string $method, string $path, ?array $body = null): array {
$ch = curl_init("https://mizgerd.com/api/v1" . $path);
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => $method,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 20,
CURLOPT_HTTPHEADER => [
"Authorization: Bearer " . getenv("MIZGERD_API_KEY"), // مثلا mzk_your_key
"Content-Type: application/json",
],
]);
if ($body !== null) {
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($body, JSON_UNESCAPED_UNICODE));
}
$raw = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
$json = json_decode((string) $raw, true) ?? [];
if ($status >= 400) {
throw new RuntimeException(($json["error"]["code"] ?? "error") . " " . ($json["requestId"] ?? ""));
}
return $json["data"] ?? [];
}
$room = mizgerd("POST", "/rooms", ["title" => "ریاضی دهم", "capacity" => 150]);
$invite = mizgerd("GET", "/rooms/" . $room["id"] . "/invite");
echo $invite["url"];وردپرس: تعریف کلید در wp-config.php
کلید را اینجا بگذارید، نه در پایگاه داده قالب و نه در جاوااسکریپت.
<?php
define('MIZGERD_API_KEY', 'mzk_your_key');وردپرس: افزونه سمت سرور (mizgerd-rooms.php)
این کد فقط روی سرور وردپرس اجرا میشود و مرورگر کلید را نمیبیند. دسترسی کاربر و nonce را خود وردپرس بررسی میکند.
<?php
/* Plugin Name: Mizgerd Rooms */
function mizgerd_request(string $method, string $path, ?array $body = null) {
$args = [
'method' => $method,
'timeout' => 20,
'headers' => [
'Authorization' => 'Bearer ' . MIZGERD_API_KEY,
'Content-Type' => 'application/json; charset=utf-8',
],
];
if ($body !== null) {
$args['body'] = wp_json_encode($body, JSON_UNESCAPED_UNICODE);
}
$res = wp_remote_request('https://mizgerd.com/api/v1' . $path, $args);
if (is_wp_error($res)) {
return $res;
}
$json = json_decode(wp_remote_retrieve_body($res), true);
if (wp_remote_retrieve_response_code($res) >= 400) {
return new WP_Error($json['error']['code'] ?? 'mizgerd_error', $json['requestId'] ?? '');
}
return $json['data'] ?? [];
}
add_action('admin_post_mizgerd_create_room', function () {
if (!current_user_can('manage_options')) {
wp_die('forbidden', '', ['response' => 403]);
}
check_admin_referer('mizgerd_create_room');
$room = mizgerd_request('POST', '/rooms', ['title' => sanitize_text_field($_POST['title'] ?? ''), 'capacity' => 150]);
if (is_wp_error($room)) {
wp_die(esc_html($room->get_error_message()));
}
$invite = mizgerd_request('GET', '/rooms/' . rawurlencode($room['id']) . '/invite');
if (is_wp_error($invite)) {
wp_die(esc_html($invite->get_error_message()));
}
wp_safe_redirect(add_query_arg('invite', rawurlencode($invite['url']), admin_url('admin.php?page=mizgerd')));
exit;
});دستورهای مرحلهبهمرحله (ساخت کلید، کاربر، اتاق، دعوت، شرکتکننده، پیام خصوصی، چیدمان، فایل، ضبط) در راهنمای Markdown هستند.
نقاط پایانی
۵۳ عملیات · شرح کامل در OpenAPIاتاقها
- GET
/api/v1/roomsList rooms (paginated)rooms:read - POST
/api/v1/roomsCreate a roomrooms:write - GET
/api/v1/rooms/{roomId}Get a roomrooms:read - PATCH
/api/v1/rooms/{roomId}Update lock, waiting room, public chat switch, capacity or camera quality (LOW, AUTO, HIGH)rooms:write - PUT
/api/v1/rooms/{roomId}/layoutSet the global layout (FOCUS, SPLIT or GALLERY); every client and recordings follow itrooms:write - GET
/api/v1/rooms/{roomId}/stateRoom state: waiting list, admitted participants, hand queue, layout, board/presentation summary, current recordingrooms:read
لینک دعوت
- GET
/api/v1/rooms/{roomId}/inviteGet the guest invitation URL (a capability: needs rooms:write)rooms:write - POST
/api/v1/rooms/{roomId}/invite/rotateReplace the invitation link (the old one stops working)rooms:write - POST
/api/v1/rooms/{roomId}/invite/revokeRevoke the invitation linkrooms:write
شرکتکنندگان
- GET
/api/v1/rooms/{roomId}/participantsList participants (paginated)participants:read - GET
/api/v1/rooms/{roomId}/participants/{participantId}Get one participant with their effective permissionsparticipants:read - POST
/api/v1/rooms/{roomId}/participants/{participantId}/admitAdmit a waiting guest; returns the participant with their effective permissionsparticipants:write - PATCH
/api/v1/rooms/{roomId}/participants/{participantId}/permissionsGrant or revoke microphone, camera and drawing for an admitted guest in one atomic change; derived permissions (screenShare, subscribe, publicChat, privateMessageReceive) are rejectedparticipants:write - POST
/api/v1/rooms/{roomId}/participants/{participantId}/denyDeny a waiting guestparticipants:write - POST
/api/v1/rooms/{roomId}/participants/{participantId}/removeRemove a guest (final) and kick them from the media serverparticipants:write - PUT
/api/v1/rooms/{roomId}/participants/{participantId}/micGrant or revoke the microphoneparticipants:write - PUT
/api/v1/rooms/{roomId}/participants/{participantId}/drawGrant or revoke whiteboard / PDF-annotation drawingparticipants:write
گفتگوی عمومی
- GET
/api/v1/rooms/{roomId}/messagesPublic chat (newest 100, or the changes after `since`)messages:read - POST
/api/v1/rooms/{roomId}/messagesPost to the public chat as the key's usermessages:write - DELETE
/api/v1/rooms/{roomId}/messages/{messageId}Delete (tombstone) a public messagemessages:write
پیام خصوصی
- GET
/api/v1/rooms/{roomId}/participants/{participantId}/private-messagesPrivate messages sent to one participantmessages:read - POST
/api/v1/rooms/{roomId}/participants/{participantId}/private-messagesSend a one-way private message to one admitted participant (max 1000 characters)messages:write - DELETE
/api/v1/rooms/{roomId}/private-messages/{messageId}Retract a private messagemessages:write
فایل PDF
- GET
/api/v1/rooms/{roomId}/presentationCurrent PDF metadata (no storage path)content:read - POST
/api/v1/rooms/{roomId}/presentationUpload or replace the PDF (multipart: file, pageCount; max 25 MiB; starts on page 1)content:write - PUT
/api/v1/rooms/{roomId}/presentation/pageGo to a PDF pagecontent:write - DELETE
/api/v1/rooms/{roomId}/presentationStop presenting (deletes the file and its annotations)content:write - GET
/api/v1/rooms/{roomId}/presentation/fileDownload the PDF (byte ranges supported)content:read
حاشیهنویسی روی PDF
- GET
/api/v1/rooms/{roomId}/presentation/annotationsAnnotation operations of one PDF page (delta since a sequence number, max 500)content:read - POST
/api/v1/rooms/{roomId}/presentation/annotationsAdd an annotation on a PDF pagecontent:write - POST
/api/v1/rooms/{roomId}/presentation/annotations/undoUndo the newest annotation on a PDF pagecontent:write - POST
/api/v1/rooms/{roomId}/presentation/annotations/clearClear all annotations on a PDF pagecontent:write
تخته
- GET
/api/v1/rooms/{roomId}/boardWhiteboard pages, current page and what is on stagecontent:read - PUT
/api/v1/rooms/{roomId}/board/visibilityShow the whiteboard on stage, or return to the PDFcontent:write - POST
/api/v1/rooms/{roomId}/board/pagesAdd a whiteboard page (max 20)content:write - PUT
/api/v1/rooms/{roomId}/board/currentSwitch the current whiteboard pagecontent:write - DELETE
/api/v1/rooms/{roomId}/board/pages/{pageId}Delete a whiteboard page (never the last)content:write - GET
/api/v1/rooms/{roomId}/board/pages/{pageId}/opsOperations of one whiteboard page (delta since a sequence number, max 500)content:read - POST
/api/v1/rooms/{roomId}/board/pages/{pageId}/opsDraw on a whiteboard pagecontent:write - POST
/api/v1/rooms/{roomId}/board/pages/{pageId}/undoUndo the newest drawing on a pagecontent:write - POST
/api/v1/rooms/{roomId}/board/pages/{pageId}/clearClear a whiteboard pagecontent:write
کاربران (حسابهای مدیر و مدرس)
- GET
/api/v1/usersList staff accounts (paginated; search, role and status filters)users:read - POST
/api/v1/usersCreate a staff account (role ADMIN or TEACHER; password policy applies)users:write - GET
/api/v1/users/{userId}Get a staff accountusers:read - PATCH
/api/v1/users/{userId}Edit name, email or role (an admin cannot change their own role; the last active admin cannot be demoted)users:write - PUT
/api/v1/users/{userId}/statusEnable or disable an account; disabling signs it out at once and keeps its rooms and historyusers:write - PUT
/api/v1/users/{userId}/passwordSet a new password and sign the account out everywhereusers:write - DELETE
/api/v1/users/{userId}/sessionsRevoke every session of an account (force sign-out)users:write
ضبط
- GET
/api/v1/rooms/{roomId}/recordingsList recordings (newest 50) with statusrecordings:read - POST
/api/v1/rooms/{roomId}/recordingsStart recording (one open recording per room)recordings:write - POST
/api/v1/rooms/{roomId}/recordings/stopStop the open recordingrecordings:write - GET
/api/v1/rooms/{roomId}/recordings/{recordingId}Recording status and playback metadatarecordings:read - GET
/api/v1/rooms/{roomId}/recordings/{recordingId}/fileStream the MP4 (READY only; byte ranges supported)recordings:read
چکلیست mizgerd.com
- TLS معتبر روی https://mizgerd.com.
- NEXT_PUBLIC_APP_URL=https://mizgerd.com و ALLOWED_ORIGINS=https://mizgerd.com.
- API_CORS_ORIGINS خالی، مگر مبدا مرورگری مشخصی واقعا لازم باشد.
- پراکسی Host و X-Forwarded-Proto را پاس بدهد و بدنه تا ۲۶ مگابایت را بپذیرد.
- هدر Authorization در هیچ لاگی ثبت نشود.
- بررسی سلامت: curl -I https://mizgerd.com/ و GET /api/openapi.json. جزئیات در docs/DEPLOY.md.
هنوز نیست
OAuth، وبهوک عمومی خروجی، SDK تولیدشده و انقضای کلید در این نسخه وجود ندارند.
