للمطوّرين

التكاملات الخارجية عبر فريقي API

فريقي API هي REST API تتيح قراءة المشاريع، وقوائم المهام، والمهام، ومناقشات المجلس، والملفات، والمجلدات، وأحداث التقويم، والأعضاء، والتعليقات، وإنشاءها، وتحديثها. يُعتمد الطلب بمفتاح Bearer ونطاق وعمليات مسموح بها. الواجهة قيد المعاينة وتُفعّل لكل شركة.

عنوان الخدمة
https://app.fareeqy.com/api/v1
الإصدار
v1.0.0
OpenAPI 3.1
ملف OpenAPI
الحالة
معاينة، تُفعَّل لكل شركة على حدة

ابدأ في ثلاث خطوات

  1. أنشئ مفتاح API من إعدادات شركتك، وحدّد نطاقه والعمليات التي يحملها.
  2. تأكد أن المفتاح يعمل، واعرف ما يحمله من عمليات ولأي شركة يعمل.
  3. اقرأ مشاريعك، ثم اعمل داخلها: قوائم، ومهام، ومجلس، وملفات.
الطلب
curl "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
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.

جدول العمليات

يعرض الجدول جميع العمليات التي يمكن منحها للمفتاح، مجمعةً حسب المورد. لا تُمنح عمليات الحذف تلقائياً، بل تُفعّل كل عملية منها فردياً.

الموردقراءةكتابةحذف
accountaccount:readلا يوجدلا يوجد
projectsprojects:readprojects:writeprojects:destructive
task_liststask_lists:readtask_lists:writetask_lists:destructive
taskstasks:readtasks:writetasks:destructive
discussionsdiscussions:readdiscussions:writediscussions:destructive
commentsلا يوجدcomments:writeلا يوجد
filesfiles:readfiles:writefiles:destructive
eventsevents:readevents:writeevents:destructive

الأخطاء

تستخدم جميع الأخطاء بنيةً موحدةً تتضمن رمزاً ثابتاً قابلاً للقراءة آلياً، ورسالةً توضيحيةً. وقد يُرجعها أي مسار.

401Unauthorized

Missing or invalid API key.

401
{
  "error": {
    "code": "unauthorized",
    "message": "Invalid or missing API key."
  }
}

403Forbidden

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

403
{
  "error": {
    "code": "forbidden",
    "message": "This API key is not permitted to perform this operation."
  }
}

The company's plan carries no API access

403
{
  "error": {
    "code": "plan_upgrade_required",
    "message": "خطة «الاحترافي» لا تشمل الوصول إلى API. رقِّ إلى «المتطور» أو «الانتاجي» لتفعيله. — The الاحترافي plan does not include API access. Upgrade to «المتطور» or «الانتاجي» to enable it."
  }
}

404NotFound

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.

404
{
  "error": {
    "code": "not_found",
    "message": "Resource not found, or you do not have access to it."
  }
}

422Unprocessable

A caller-fixable bad request (validation error, bad date, bad enum).

422
{
  "error": {
    "code": "unprocessable_entity",
    "message": "Title can't be blank"
  }
}

409Conflict

A uniqueness/record conflict; retry.

409
{
  "error": {
    "code": "conflict",
    "message": "Could not complete due to a conflict; please retry."
  }
}

429RateLimited

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)

429
{
  "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)

429
{
  "error": "Rate limit exceeded. Please try again later."
}

كل المسارات

يسرد الفهرس جميع المسارات. افتح مجموعة أي مسار لعرض بارامتراته، وجسم طلبه، ومثال استجابته.

الحساب

هوية المفتاح الذي يستدعي الواجهة، والبحث الموحّد في مساحة العمل.

الأعضاء

من يمكن إسناد العمل إليهم داخل المشروع.

المهام

البنود القابلة للتنفيذ داخل قائمة المهام. معرّفات بصيغة slug.

تفعيل API وإصدار مفتاح

اطلب تفعيل API لشركتك. بعد التفعيل، أصدر مفتاحاً من إعدادات API Keys، وحدد العمليات المسموح بها.