نظرة عامة
يتيح Vito API لتطبيقك التعامل مع رصيد Vito الخاص بالمستخدم من داخل Discord — قراءته أو تحصيل قيمة منه أو إضافة رصيد إليه. يؤكد المستخدم كل عملية تحصيل برمزه السري على vetox.io قبل تحرّك أي Vito، ويُخطَر تطبيقك بالنتيجة. وVito هي العملة الافتراضية داخل منظومة Vetox؛ استخدم الـ API لبناء تجارب قائمة على Vito — كفتح محتوى أو ميزات أو مزايا أو مكافآت. لا تجري أي عمليات بيع أو شراء بأموال حقيقية.
إنه واجهة REST API تُصادق بمفتاح سري. تُعيد جميع نقاط النهاية JSON ومُصدَّرة تحت /v1.
https://api.vetox.io/public/vito/v1الأرصدة والتسوية
مفتاح API الخاص بك مرتبط بحساب Vetox الخاص بك. كل عملية تحصيل تُسوّى لصالحك: عندما يخصم تطبيقك Vito من مستخدم، يُضاف ذلك Vito إلى رصيدك الخاص (مطروحًا منه رسوم المنصة)، ولا يُحرق أبدًا. وعندما يضيف تطبيقك Vito إلى مستخدم، يُموَّل ذلك من رصيدك.
ينتقل Vito دائمًا بين الأرصدة — وليس من أو إلى أموال حقيقية أبدًا. يُحصَّل من المستخدم المبلغ الكامل الذي تطلبه؛ وتستلم أنت المبلغ بعد رسوم المنصة؛ وتُموَّل الأرصدة المضافة والمكافآت من رصيدك عبر /add.
المتطلبات
يُمنح الوصول إلى Vito API لكل مشروع. قبل أن تستطيع استدعاءه تحتاج إلى:
- عضوية مستخدم نشطة (المستوى Silver أو أعلى). يتجمد الـ API تلقائيًا إذا انتهت عضوية المالك، ويُستعاد عند إعادة الاشتراك.
- طلب مطوّر موافق عليه. قدّم طلبًا من هذه الصفحة؛ يراجعه فريق Vetox يدويًا.
- قبول شروط مطوّري واجهة برمجة التطبيقات — تتم الموافقة عليها عند إرسال طلب المطوّر الخاص بك.
- الصلاحيات التي يحتاجها مشروعك. يمنحها فريق Vetox بناءً على طلبك.
الصلاحيات المتاحة
balance:readdeduct:createcredit:createtransfer:createtransactions:readالمصادقة
صادق كل طلب بمفتاح API السري في ترويسة Authorization كرمز Bearer. تبدأ المفاتيح بالبادئة vito_live_.
Authorization: Bearer vito_live_xxxxxxxxxxxxxxxxطبقتان اختياريتان تحميان مشروعك أكثر:
- قائمة IP المسموح بها — اقصر الطلبات على عناوين IP محددة للخادم (كوّنها في تبويب الإعدادات).
- حدود المعدل — سقوف طلبات لكل مشروع تتناسب مع مستوى عضويتك.
مفاتيح API — التخزين والتدوير والأمان
يُنشأ مفتاحك عند الموافقة على طلبك. يُعرض مرة واحدة فقط — اكشفه من تبويب مفاتيح API واحفظه فورًا.
لا يخزّن Vetox مفتاحك بصيغة قابلة للقراءة (مجرد تجزئة مملّحة). احتفظ به كسرّ على الخادم — متغير بيئة أو مدير أسرار — وليس أبدًا في كود العميل أو مستودع git أو المتصفح.
دوّره من تبويب مفاتيح API. يستمر المفتاح السابق بالعمل لفترة سماح مدتها 24 ساعة لتطرح المفتاح الجديد دون توقف، ثم يتوقف.
تدفّق تأكيد التحصيل
تمر كل عملية تحصيل عبر تأكيد يوافق عليه المستخدم برمزه السري — مفتاحك وحده لا ينقل Vito أبدًا:
- 1يستدعي تطبيقك POST /deduct بالمستخدم والمبلغ ومعرّف الخادم الأصلي وتفاصيل العنصر.
- 2ينشئ Vito تأكيدًا معلّقًا (صالحًا لمدة 10 دقائق) ويُعيد confirmUrl. عند تمرير guildId، يُرسَل للمستخدم أيضًا رسالة خاصة بالتفاصيل مع زر إلى صفحة التأكيد.
- 3يفتح المستخدم الرابط confirmUrl على vetox.io ويوافق على الخصم برمز محفظته السري.
- 4يخصم Vito المبلغ، ويسجّل المعاملة، ويرسل — إذا كان لديك Webhook مكوّن — حدث confirmation.completed موقّعًا إلى رابط الاستدعاء.
- 5يتحقق تطبيقك من التوقيع ويُكمل إجراءه (مثلًا، يفتح المحتوى).
معاملات الطلب (/deduct)
/v1/deductتقبل نقطة نهاية الخصم حقول الجسم التالية:
discordIdamountguildIdreasonmerchantRefproductproduct.imageUrlmetadata* حقل مطلوب.
POST https://api.vetox.io/public/vito/v1/deduct
Authorization: Bearer vito_live_xxxxxxxxxxxxxxxx
Content-Type: application/json
Idempotency-Key: req_9a1f2b # optional, dedupes retries for 24h
{
"discordId": "123456789012345678",
"amount": 500,
"guildId": "1470389021162209280",
"reason": "Unlock premium theme",
"merchantRef": "ref_1042",
"product": {
"type": "feature",
"name": "Premium theme",
"description": "Unlocks the premium theme pack",
"imageUrl": "https://cdn.example.com/theme.png"
},
"metadata": { "ref": "1042" }
}{
"success": true,
"data": {
"confirmationId": "f3c9...e1",
"confirmUrl": "https://vetox.io/confirm/vito/f3c9...e1",
"amount": 500,
"expiresAt": 1735689600000,
"status": "pending"
},
"requestId": "req_abc123",
"timestamp": 1735689300000
}إضافة Vito — الأرصدة المضافة (/add)
/v1/addيضيف POST /add رصيد Vito لمستخدم من رصيدك الخاص — للمكافآت أو الأرصدة المضافة. يأخذ نفس حقول /deduct باستثناء guildId وproduct. وعلى عكس التحصيل فهو فوري ولا يحتاج رمز PIN من المستخدم — مفتاح API هو صلاحيتك — لذا تعكس الاستجابة بالفعل التحويل المكتمل. يستلم المستخدم المبلغ الكامل؛ ولا تُطبَّق أي رسوم منصة.
POST https://api.vetox.io/public/vito/v1/add
Authorization: Bearer vito_live_xxxxxxxxxxxxxxxx
Content-Type: application/json
Idempotency-Key: credit_7f3a # optional, dedupes retries for 24h
{
"discordId": "123456789012345678",
"amount": 250,
"reason": "Event reward",
"merchantRef": "reward_1042",
"metadata": { "ref": "1042" }
}{
"success": true,
"data": {
"transactionId": "txn_91b2",
"toDiscordId": "123456789012345678",
"amount": 250,
"ownerBalance": 48250,
"recipientBalance": 1250,
"status": "completed"
},
"requestId": "req_def456",
"timestamp": 1735689300000
}Webhooks والتحقق من التوقيع
أضف رابط استدعاء https واحدًا أو أكثر في تبويب الإعدادات. يسلّم Vito طلب POST موقّعًا إلى كل رابط مكوّن كلما وصل تأكيد إلى حالة نهائية، مع إعادة المحاولة حتى 5 مرات بتراجع أسي.
التحقق من التوقيع
تحمل كل عملية تسليم ترويسة X-Vito-Signature بالصيغة ts=<unix>;h1=<hex>. أعد حساب HMAC على "<ts>:<rawBody>" بسرك التوقيعي وقارن بوقت ثابت. تحقّق دائمًا من جسم الطلب الخام قبل تحليل JSON.
signature = HMAC_SHA256(signingSecret, "<ts>:<rawBody>")
header = X-Vito-Signature: ts=<unix-seconds>;h1=<hex-signature>import crypto from 'crypto';
import express from 'express';
const app = express();
// IMPORTANT: verify against the RAW body, before JSON parsing.
app.post('/webhooks/vito', express.raw({ type: '*/*' }), (req, res) => {
const sig = req.header('X-Vito-Signature') || ''; // "ts=<unix>;h1=<hmac>[;h1=<hmac>]"
const pairs = sig.split(';').map(p => p.split('='));
const ts = pairs.find(([k]) => k === 'ts')?.[1];
const sigs = pairs.filter(([k]) => k === 'h1').map(([, v]) => v);
const rawBody = req.body.toString('utf8');
const expected = crypto
.createHmac('sha256', process.env.VITO_SIGNING_SECRET) // whsec_...
.update(`${ts}:${rawBody}`)
.digest('hex');
const expectedBuf = Buffer.from(expected, 'hex');
// During a 24h secret rotation the header carries TWO h1= values — accept ANY.
// Length-guard FIRST: crypto.timingSafeEqual throws on a length mismatch.
const ok = sigs.some(h => {
const got = Buffer.from(h, 'hex');
return (
got.length === expectedBuf.length &&
crypto.timingSafeEqual(got, expectedBuf)
);
});
// Reject anything older than ~5 minutes to stop replays.
const fresh = ts && Math.abs(Date.now() / 1000 - Number(ts)) < 300;
if (!ok || !fresh) return res.status(401).end();
const event = JSON.parse(rawBody);
if (event.eventType === 'confirmation.completed') {
grantPremiumTheme(event.data.merchantRef, event.data.fromDiscordId);
}
res.status(200).end(); // ack fast; run your action async if slow
});أحداث Webhook وحمولاتها
يرسل Vito أحد أربعة أنواع أحداث. تشترك كلها في نفس شكل الحمولة؛ ويعكس data.status النتيجة.
confirmation.completedconfirmation.failedconfirmation.expiredconfirmation.cancelledcredit.completedPOST https://your-app.com/webhooks/vito
X-Vito-Signature: ts=1735689600;h1=4f8b2c...e9
X-Vito-Event-Id: evt_3a2b1c
X-Vito-Event-Type: confirmation.completed
Content-Type: application/json
{
"eventId": "evt_3a2b1c",
"eventType": "confirmation.completed",
"timestamp": 1735689600000,
"data": {
"confirmationId": "f3c9...e1",
"type": "deduct",
"fromDiscordId": "123456789012345678",
"toDiscordId": null,
"amount": 500,
"reason": "Unlock premium theme",
"merchantRef": "ref_1042",
"product": { "type": "feature", "name": "Premium theme" },
"status": "completed",
"transactionId": "txn_77a2",
"metadata": { "ref": "1042" },
"failureReason": null
}
}رموز الأخطاء
تُعيد الأخطاء حالة غير 2xx مع جسم JSON يحمل error.code على المستوى الأعلى. الحالات الشائعة:
VITO_VALIDATION_ERRORinvalid keyOWNER_MEMBERSHIP_INACTIVEscope / IPnot foundinsufficient balanceINSUFFICIENT_OWNER_FUNDSrate limited{
"success": false,
"error": { "type": "Bad Request", "message": "guildId must be a valid Discord server ID", "code": "VITO_VALIDATION_ERROR" },
"requestId": "req_abc123",
"timestamp": 1735689300000
}أمثلة التكامل
أنشئ طلب تحصيل:
/v1/deductcurl -X POST https://api.vetox.io/public/vito/v1/deduct \
-H "Authorization: Bearer $VITO_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"discordId": "123456789012345678",
"amount": 500,
"guildId": "1470389021162209280",
"merchantRef": "ref_1042",
"product": { "type": "feature", "name": "Premium theme" }
}'تحقق من رصيد مستخدم:
/v1/balance/:discordIdcurl https://api.vetox.io/public/vito/v1/balance/123456789012345678 \
-H "Authorization: Bearer $VITO_API_KEY"الاختبار باستخدام التكامل التجريبي
يتوفر تكامل تجريبي مستقل لتجربة التدفّق الكامل من البداية للنهاية دون كتابة أي كود. يمر عبر الطلب ← التأكيد ← الرمز السري ← Webhook ← الإتمام.
- 1افتح مجلد التكامل التجريبي وأضف مفتاح Vito API ورمز بوت Discord ومعرّف خادم (guild) الاختبار إلى config.json.
- 2نفّذ npm install && npm start، ثم افتح http://localhost:4000.
- 3ابحث عن مستخدم بمعرّف Discord، اختر عنصرًا، وابدأ عملية تحصيل — يستدعي العرض التجريبي /deduct ويعرض confirmUrl.
- 4وافق على الرمز السري على vetox.io؛ يكتشف العرض الإتمام (عبر Webhook إن كان مكوّنًا، وإلا بالاستطلاع) ويُكمل الإجراء التجريبي.
أفضل الممارسات والحدود والأمان
الأمان
- أبقِ مفتاح API والسر التوقيعي على الخادم فقط؛ دوّر أيًا منهما فورًا إذا تسرّب.
- تحقق دائمًا من توقيع Webhook على الجسم الخام، وارفض عمليات التسليم الأقدم من نحو 5 دقائق (حماية من إعادة التشغيل).
- أكمل إجراءك فقط عند confirmation.completed — وليس أبدًا عند استجابة /deduct (لم يُحسم التحصيل بعدُ عند تلك النقطة).
- استخدم قائمة IP المسموح بها واطلب الصلاحيات التي تحتاجها فعلًا فقط.
الحدود
- تنتهي صلاحية التأكيدات بعد 10 دقائق؛ عامل الطلبات غير المؤكدة على أنها متروكة.
- حدود المعدل لكل مشروع وتتناسب مع مستوى عضوية المالك.
- يجب أن يكون amount عددًا صحيحًا موجبًا؛ وتُحدَّد metadata بـ 10 مفاتيح كحد أقصى.