401Unauthorized
Missing or invalid API key.
{
"error": {
"code": "unauthorized",
"message": "Invalid or missing API key."
}
}للمطوّرين
فريقي API هي REST API تتيح قراءة المشاريع، وقوائم المهام، والمهام، ومناقشات المجلس، والملفات، والمجلدات، وأحداث التقويم، والأعضاء، والتعليقات، وإنشاءها، وتحديثها. يُعتمد الطلب بمفتاح Bearer ونطاق وعمليات مسموح بها. الواجهة قيد المعاينة وتُفعّل لكل شركة.
https://app.fareeqy.com/api/v1curl "https://app.fareeqy.com/api/v1/me" \
-H "Authorization: Bearer $FAREEQY_API_KEY"{
"data": {
"key": {
"name": "مزامنة الفوترة",
"access": "write",
"operations": [
"projects:read",
"tasks:read",
"tasks:write"
]
},
"company": {
"name": "فريق التقنية"
},
"created_by": {
"name": "سارة العتيبي",
"email": "sara@example.com"
}
}
}حقل created_by توقيع يُعرف به أي مفتاح تحمله تكاملاتك، وليس الهوية التي يُنفَّذ بها الطلب.
الواجهة متاحة على خطتَي المتطور والإنتاجي وخطة المؤسسات. أما الخطة المجانية والاحترافية فلا تشملان الوصول إلى API، وأي طلب منهما يُرفض بالرمز 403 ورسالة plan_upgrade_required، ولا فائدة من إعادة المحاولة.
السطح في مرحلة معاينة، ويُفعَّل لكل شركة على حدة. وما دام غير مفعّل لشركتك، يرجع كل مسار مصادَق عليه الرمز 404: السطح مخفي، لا ممنوع. يُفحص المفتاح أولاً، فالمفتاح الخاطئ يبقى 401، ثم يُفحص التفعيل، فلا يظهر الـ 404 إلا بعد تقديم مفتاح صالح.
لتفعيل الواجهة لشركتك، أو لطلب حدود أعلى، تواصل معنا وسنفعّلها على حسابك.
كل طلب يحمل مفتاح API في header Authorization بصيغة Bearer. ويُعرض المفتاح مرة واحدة عند إنشائه، ولا يُخزَّن منه إلا بصمته المشفّرة، فاحفظه حينها.
curl "https://app.fareeqy.com/api/v1/me" \
-H "Authorization: Bearer $FAREEQY_API_KEY"مفاتيح REST ورموز MCP بيانات اعتماد مختلفة، ولا يصادق أحدهما على واجهة الآخر.
المفتاح ملك للشركة لا لمنشئه، ويستمر بعد مغادرته.
عملية غير ممنوحة للمفتاح ← 403.
يصل المفتاح إلى كل مشاريع شركته، ومنها الخاصة.
سجل تابع لشركة أخرى ← 404.
created_by اسم منشئ المفتاح، لا هوية تنفيذ الطلب.
إدارة المفاتيح للمالك وللمصرّح له، وليست للمدير أو العضو افتراضياً.
كل مسار يعلن العملية الواحدة التي يطلبها، وهي نص ثابت بصيغة <المورد>:<القدرة> مثل projects:write. والمفتاح يُفحص مرتين قبل أن يمر الطلب.
النطاق هو السقف: read أو write. ومفتاح write يحمل read معه. النطاق يقرر أي العمليات يجوز للمفتاح أن يحملها أصلاً.
قائمة العمليات المسموحة هي البوابة الفعلية: العمليات التي يستطيع هذا المفتاح استدعاءها بالتحديد، ويُتحقق أنها ضمن ما يسمح به نطاقه. والقائمة الفارغة تعني لا شيء، فلا ينفتح مفتاح بالخطأ.
يجب أن يتحقق الشرطان معاً: أن تكون العملية في قائمة المفتاح، وأن يفي نطاقه بقدرتها. وإلا فالطلب مرفوض بالرمز 403، ويُسجَّل في سجل التدقيق بحالة denied.
الحذف اختياري بقرار صريح. عمليات destructive تحتاج نطاق write، لكنها مستثناة عمداً من المنح الافتراضي، فتُفعَّل كل عملية حذف يدوياً على المفتاح. اطّلع على جدول العمليات بالأسفل.
المشاريع، وقوائم المهام، والمهام، ومواضيع المجلس تُعنوَن بـ slug مقروء. والـ slug فريد داخل المورد الأب فقط، لذلك المسارات متداخلة بالكامل: يُحلّ slug القائمة داخل مشروعها، وslug المهمة داخل قائمتها. قد يتكرر slug القائمة نفسه في مشروعين، فلا تفترض أبداً أن الـ slug فريد عالمياً.
أما الملفات، والمجلدات، والأحداث، والتعليقات فتُعنوَن بمعرّفات رقمية. وهي عامة، لذلك تمرّ كل عملية بحث عنها عبر مشروعها (أو عبر ما تصل إليه أنت، في حالة الأحداث)، فمعرّف من شركة أخرى ينتهي إلى 404، لا إلى تسريب.
الـ slugs عربية لأن أسماء مشاريعك عربية. رمّزها ترميز URL قبل إرسالها: تطوير-الموقع تصبح %D8%AA%D8%B7%D9%88%D9%8A%D8%B1-.... أمثلة الطلبات هنا تعرض النص الأصلي ليبقى مقروءاً.
كل استجابة مغلّفة، فلا تتعامل مع مصفوفة عارية ولا مع حقل في الجذر.
مورد واحد: { "data": { ... } }
مجموعة: { "data": [ ... ], "meta": { total, limit, offset, count } }
حذف: { "data": { "deleted": true, ... } }
خطأ: { "error": { "code": "...", "message": "..." } }
المجموعات تستقبل limit (الافتراضي 50، والحد الأقصى 100، وما تجاوزه يُقصَر عليه) وoffset (الافتراضي 0). وmeta.total هو العدد الكلي بلا ترشيح، وmeta.count عدد السجلات في الصفحة المُرجَعة.
طبقتان مستقلتان، وترفضان بطريقتين مختلفتين.
الاندفاع. كل مفتاح محدود بـ 300 طلب في الدقيقة، ويسري حد مماثل لكل عنوان IP. وتجاوز أيهما يرجع 429.
الحصة اليومية. كل طلب يستهلك واحداً من رصيد الشركة اليومي. والرصيد للشركة لا للمفتاح، فإنشاء مفاتيح إضافية لا يرفعه، ويتجدد عند منتصف الليل بتوقيت شركتك.
| الخطة | الطلبات اليومية |
|---|---|
| المجاني | لا وصول إلى API |
| الاحترافي | لا وصول إلى API |
| المتطور | 1,000 |
| الإنتاجي | 10,000 |
| المؤسسات | حسب الاتفاق، اطلب عرض سعر |
الخطة بلا وصول ليست خطة محدودة السرعة: الرفض فيها 403 برمز plan_upgrade_required، ولا يصحبه Retry-After، لأن الانتظار لن ينفع أبداً. أما الخطة التي تملك وصولاً واستهلكت رصيد يومها فترجع 429 برمز rate_limit_exceeded ومعه Retry-After يشير إلى منتصف ليل شركتك القادم. الخلط بين الحالتين يدفع عميلاً منضبطاً إلى حلقة إعادة محاولة لا تنجح أبداً.
تُضاف الـ headers X-RateLimit-Limit وX-RateLimit-Remaining وX-RateLimit-Reset إلى كل استجابة مخدومة، لا إلى الرفض وحده، حتى يبطئ عميلك قبل أن يصل إلى الصفر. وعلى خطة بلا سقف تقرأ الأوليان unlimited.
يعرض الجدول جميع العمليات التي يمكن منحها للمفتاح، مجمعةً حسب المورد. لا تُمنح عمليات الحذف تلقائياً، بل تُفعّل كل عملية منها فردياً.
| المورد | قراءة | كتابة | حذف |
|---|---|---|---|
account | account:read | لا يوجد | لا يوجد |
projects | projects:read | projects:write | projects:destructive |
task_lists | task_lists:read | task_lists:write | task_lists:destructive |
tasks | tasks:read | tasks:write | tasks:destructive |
discussions | discussions:read | discussions:write | discussions:destructive |
comments | لا يوجد | comments:write | لا يوجد |
files | files:read | files:write | files:destructive |
events | events:read | events:write | events:destructive |
تستخدم جميع الأخطاء بنيةً موحدةً تتضمن رمزاً ثابتاً قابلاً للقراءة آلياً، ورسالةً توضيحيةً. وقد يُرجعها أي مسار.
Missing or invalid API key.
{
"error": {
"code": "unauthorized",
"message": "Invalid or missing API key."
}
}Two different refusals share this status, and a client must tell them apart by error.code. forbidden means the key's scope or allowlist does not permit this operation, or Pundit denied the action. plan_upgrade_required means the company's plan carries no API access at all, so no key on it can ever succeed and there is nothing to retry.
This key may not perform this operation
{
"error": {
"code": "forbidden",
"message": "This API key is not permitted to perform this operation."
}
}The company's plan carries no API access
{
"error": {
"code": "plan_upgrade_required",
"message": "خطة «الاحترافي» لا تشمل الوصول إلى API. رقِّ إلى «المتطور» أو «الانتاجي» لتفعيله. — The الاحترافي plan does not include API access. Upgrade to «المتطور» or «الانتاجي» to enable it."
}
}Resource not found or not accessible — also returned for EVERY endpoint when the company's rest_api feature flag is disabled (the surface is hidden). Lookups drill through the URL hierarchy, so another company's record is a 404 and never a leak. A path that matches no route at all answers 404 with the distinct code unknown_endpoint and echoes the path back, so a mistyped or half-built URL is told apart from a record that is missing or out of reach.
{
"error": {
"code": "not_found",
"message": "Resource not found, or you do not have access to it."
}
}A caller-fixable bad request (validation error, bad date, bad enum).
{
"error": {
"code": "unprocessable_entity",
"message": "Title can't be blank"
}
}A uniqueness/record conflict; retry.
{
"error": {
"code": "conflict",
"message": "Could not complete due to a conflict; please retry."
}
}Either the company's daily API allowance is spent (rate_limit_exceeded), or the per-key / per-IP burst throttle of 300 requests per minute fired. Both come back after a wait, so Retry-After is honest here. The two bodies are not the same shape. The daily-quota refusal uses the standard error envelope. The burst throttle is served by Rack::Attack ahead of the application, so its body is a flat {"error": "<string>"} with no code. A client that reads error.code has to tolerate error being a plain string.
الـ headers المصاحبة
Retry-After Seconds to wait before retrying. On a spent daily allowance this points at the company's next midnight.
X-RateLimit-Limit The plan's daily API allowance, or unlimited.
X-RateLimit-Remaining Calls left in today's allowance, or unlimited.
X-RateLimit-Reset Unix timestamp of the next reset (the company's next midnight).
Today's daily allowance is spent (application envelope)
{
"error": {
"code": "rate_limit_exceeded",
"message": "استهلكت رصيد اليوم من طلبات API في خطة «المتطور» (1000 طلب يوميًا). يتجدد الرصيد عند منتصف الليل بتوقيت Asia/Riyadh. — Daily API quota exhausted: the المتطور plan allows 1000 calls per day. It resets at midnight Asia/Riyadh."
}
}Over 300 requests in a minute (Rack::Attack body, flat error)
{
"error": "Rate limit exceeded. Please try again later."
}يسرد الفهرس جميع المسارات. افتح مجموعة أي مسار لعرض بارامتراته، وجسم طلبه، ومثال استجابته.
هوية المفتاح الذي يستدعي الواجهة، والبحث الموحّد في مساحة العمل.
أحداث تقويم الشركة. معرّفات رقمية.
المشاريع التي يصل إليها صاحب المفتاح.
من يمكن إسناد العمل إليهم داخل المشروع.
حاويات تجمع المهام داخل المشروع. معرّفات بصيغة slug.
البنود القابلة للتنفيذ داخل قائمة المهام. معرّفات بصيغة slug.
التعليقات على قائمة مهام، أو على مهمة.
مواضيع النقاش داخل المشروع. معرّفات بصيغة slug.
ملفات المشروع والروابط الخارجية. معرّفات رقمية.
المجلدات في قسم ملفات المشروع. معرّفات رقمية.
اطلب تفعيل API لشركتك. بعد التفعيل، أصدر مفتاحاً من إعدادات API Keys، وحدد العمليات المسموح بها.