التعليقات

التعليقات على قائمة مهام، أو على مهمة، قراءةً وكتابةً، ونص الملفات المرفقة بها.

عنوان الخدمة https://app.fareeqy.com/api/v1

شكل المورد

الحقول التي ترجع داخل data في مسارات هذه المجموعة.

idinteger

معرّف رقمي، فالتعليقات بلا slug.

urlstring | null

الصفحة التي يُقرأ فيها التعليق، وهي صفحة أبيه. وكل تعليقات النقاش الواحد تحمل العنوان نفسه.

contentstring | null

النص العادي المقابل للمحتوى المنسّق.

authorstring | null
created_atstring (date-time)
updated_atstring (date-time)

يساوي created_at حتى يُعدَّل التعليق.

attachmentsobject[]

الملفات المضمّنة في متن التعليق. فالنص العادي في content يُسقط المرفقات كلها، ولولا هذا الحقل لقرأت تعليقاً يشير إلى لقطة شاشة وكأنه يشير إلى لا شيء. ويكون فارغاً حين لا مرفقات. واقرأ المرفق النصي عبر مسار مرفق التعليق، بمعرّفه id.

Comment
{
  "id": 512,
  "url": "https://app.fareeqy.com/tasks/tsk-9wb7t",
  "content": "راجعت النسخة الأخيرة، ينقصنا حالة الخطأ في النموذج.",
  "author": "عبدالله المطيري",
  "created_at": "2026-07-15T09:48:03.000+03:00",
  "updated_at": "2026-07-15T09:48:03.000+03:00",
  "attachments": [
    {
      "id": 9031,
      "name": "error-state.png",
      "content_type": "image/png",
      "byte_size": 184320
    }
  ]
}

عرض تعليقات قائمة مهام

GET/projects/{project_id}/lists/{task_list_id}/commentsيتطلب comments:read

الأقدم أولاً.

بارامترات المسار

project_idstringمطلوب

المعرّف الثابت للمشروع، أو الـ slug الخاص به.

task_list_idstringمطلوب

المعرّف الثابت لقائمة المهام، أو الـ slug الخاص بها.

بارامترات الاستعلام

limitinteger

حجم الصفحة. الافتراضي 50، والحد الأقصى 100، وما زاد عنه يُقصَر عليه.

الافتراضي: 50

offsetinteger

عدد السجلات التي تُتخطّى. الافتراضي 0.

الافتراضي: 0

مثال الطلب

cURL
curl "https://app.fareeqy.com/api/v1/projects/prj-8f3kd/lists/lst-4m2qp/comments" \
  -H "Authorization: Bearer $FAREEQY_API_KEY"

مثال الاستجابة

200
{
  "data": [
    {
      "id": 512,
      "url": "https://app.fareeqy.com/tasks/tsk-9wb7t",
      "content": "راجعت النسخة الأخيرة، ينقصنا حالة الخطأ في النموذج.",
      "author": "عبدالله المطيري",
      "created_at": "2026-07-15T09:48:03.000+03:00",
      "updated_at": "2026-07-15T09:48:03.000+03:00",
      "attachments": [
        {
          "id": 9031,
          "name": "error-state.png",
          "content_type": "image/png",
          "byte_size": 184320
        }
      ]
    }
  ],
  "meta": {
    "total": 4,
    "limit": 50,
    "offset": 0,
    "count": 4
  }
}
حالات الرفض:401403404429اعرض أمثلة الرفض
401default

Missing or invalid API key.

default
{
  "error": {
    "code": "unauthorized",
    "message": "مفتاح الـ API غير صالح أو غير مُرسَل."
  }
}
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
{
  "error": {
    "code": "forbidden",
    "message": "هذا الـ API key لا يملك صلاحية تنفيذ هذه العملية."
  }
}
The company's plan carries no API access
{
  "error": {
    "code": "plan_upgrade_required",
    "message": "خطة «الاحترافي» لا تشمل الوصول إلى API. رقِّ إلى «المتطور» أو «الإنتاجي» لتفعيله."
  }
}
404not_found

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.

A record that is missing or out of reach
{
  "error": {
    "code": "not_found",
    "message": "غير موجود، أو لا تملك صلاحية الوصول إليه."
  }
}
A path that matches no endpoint
{
  "error": {
    "code": "unknown_endpoint",
    "message": "لا يوجد endpoint يطابق GET /api/v1/projcts. راجع المسار في توثيق الـ API."
  }
}
429rate_limit_exceeded

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.

Today's daily allowance is spent (application envelope)
{
  "error": {
    "code": "rate_limit_exceeded",
    "message": "استهلكت رصيد اليوم من طلبات API في خطة «المتطور» (1000 طلب يوميًا). يتجدد الرصيد عند منتصف الليل بتوقيت Asia/Riyadh."
  }
}
Over 300 requests in a minute (Rack::Attack body, flat error)
{
  "error": "Rate limit exceeded. Please try again later."
}
الأخطاء

التعليق على قائمة مهام

POST/projects/{project_id}/lists/{task_list_id}/commentsيتطلب comments:write

بارامترات المسار

project_idstringمطلوب

المعرّف الثابت للمشروع، أو الـ slug الخاص به.

task_list_idstringمطلوب

المعرّف الثابت لقائمة المهام، أو الـ slug الخاص بها.

جسم الطلب

contentstringمطلوب

متن التعليق بنص منسّق، ويُرسل نصاً عادياً.

مثال الطلب

cURL
curl -X POST "https://app.fareeqy.com/api/v1/projects/prj-8f3kd/lists/lst-4m2qp/comments" \
  -H "Authorization: Bearer $FAREEQY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"content":"خلصنا الهيدر، باقي قسم المزايا."}'

مثال الاستجابة

201
{
  "data": {
    "id": 512,
    "url": "https://app.fareeqy.com/tasks/tsk-9wb7t",
    "content": "راجعت النسخة الأخيرة، ينقصنا حالة الخطأ في النموذج.",
    "author": "عبدالله المطيري",
    "created_at": "2026-07-15T09:48:03.000+03:00",
    "updated_at": "2026-07-15T09:48:03.000+03:00",
    "attachments": [
      {
        "id": 9031,
        "name": "error-state.png",
        "content_type": "image/png",
        "byte_size": 184320
      }
    ]
  }
}
حالات الرفض:401403404409422429اعرض أمثلة الرفض
401default

Missing or invalid API key.

default
{
  "error": {
    "code": "unauthorized",
    "message": "مفتاح الـ API غير صالح أو غير مُرسَل."
  }
}
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
{
  "error": {
    "code": "forbidden",
    "message": "هذا الـ API key لا يملك صلاحية تنفيذ هذه العملية."
  }
}
The company's plan carries no API access
{
  "error": {
    "code": "plan_upgrade_required",
    "message": "خطة «الاحترافي» لا تشمل الوصول إلى API. رقِّ إلى «المتطور» أو «الإنتاجي» لتفعيله."
  }
}
404not_found

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.

A record that is missing or out of reach
{
  "error": {
    "code": "not_found",
    "message": "غير موجود، أو لا تملك صلاحية الوصول إليه."
  }
}
A path that matches no endpoint
{
  "error": {
    "code": "unknown_endpoint",
    "message": "لا يوجد endpoint يطابق GET /api/v1/projcts. راجع المسار في توثيق الـ API."
  }
}
409default

A uniqueness/record conflict; retry.

default
{
  "error": {
    "code": "conflict",
    "message": "تعذّر إتمام العملية بسبب تعارض. أعد المحاولة."
  }
}
422default

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

default
{
  "error": {
    "code": "unprocessable_entity",
    "message": "قيمة due_at غير صالحة؛ أرسل تاريخاً مثل 2026-07-20. المهمة تُستحق في يوم، وأي وقت ترسله يُهمل."
  }
}
429rate_limit_exceeded

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.

Today's daily allowance is spent (application envelope)
{
  "error": {
    "code": "rate_limit_exceeded",
    "message": "استهلكت رصيد اليوم من طلبات API في خطة «المتطور» (1000 طلب يوميًا). يتجدد الرصيد عند منتصف الليل بتوقيت Asia/Riyadh."
  }
}
Over 300 requests in a minute (Rack::Attack body, flat error)
{
  "error": "Rate limit exceeded. Please try again later."
}
الأخطاء

قراءة ملف مرفق بتعليق على قائمة مهام

GET/projects/{project_id}/lists/{task_list_id}/comments/{comment_id}/attachments/{id}يتطلب comments:read

يرجع نص ملف واحد مرفق داخل تعليق. وid المعرّف الرقمي للمرفق، وتقرؤه من حقل attachments في التعليق. ولا يُقرأ هنا إلا الملف النصي (بامتدادات مثل md، وtxt، وcsv، وtsv، وjson، وyml، وxml، وhtml، وlog، وsql، وملفات الشيفرة الشائعة)، حتى 256 كيلوبايت. والصورة، وملف PDF، والملف الأكبر من الحد، والملف الفارغ، والملف المفقود من التخزين، كلها تُرفض بالرمز 422 مع ذكر اسمه، فافتحه من صفحة التعليق. ومعرّف مرفق يتبع تعليقاً آخر يرجع 404.

بارامترات المسار

project_idstringمطلوب

المعرّف الثابت للمشروع، أو الـ slug الخاص به.

task_list_idstringمطلوب

المعرّف الثابت لقائمة المهام، أو الـ slug الخاص بها.

comment_idintegerمطلوب

المعرّف الرقمي للتعليق، فالتعليقات بلا معرّف ثابت وبلا slug.

idintegerمطلوب

المعرّف الرقمي للمرفق، من حقل attachments في التعليق.

مثال الطلب

cURL
curl "https://app.fareeqy.com/api/v1/projects/prj-8f3kd/lists/lst-4m2qp/comments/4821/attachments/1937" \
  -H "Authorization: Bearer $FAREEQY_API_KEY"

مثال الاستجابة

200
{
  "data": {
    "id": 9044,
    "name": "أخطاء-الاستيراد.csv",
    "content_type": "text/csv",
    "byte_size": 412,
    "comment_id": 518,
    "comment_url": "https://app.fareeqy.com/tasks/tsk-9wb7t",
    "content": "row,error\n14,missing due date\n22,unknown assignee\n"
  }
}
حالات الرفض:401403404422429اعرض أمثلة الرفض
401default

Missing or invalid API key.

default
{
  "error": {
    "code": "unauthorized",
    "message": "مفتاح الـ API غير صالح أو غير مُرسَل."
  }
}
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
{
  "error": {
    "code": "forbidden",
    "message": "هذا الـ API key لا يملك صلاحية تنفيذ هذه العملية."
  }
}
The company's plan carries no API access
{
  "error": {
    "code": "plan_upgrade_required",
    "message": "خطة «الاحترافي» لا تشمل الوصول إلى API. رقِّ إلى «المتطور» أو «الإنتاجي» لتفعيله."
  }
}
404not_found

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.

A record that is missing or out of reach
{
  "error": {
    "code": "not_found",
    "message": "غير موجود، أو لا تملك صلاحية الوصول إليه."
  }
}
A path that matches no endpoint
{
  "error": {
    "code": "unknown_endpoint",
    "message": "لا يوجد endpoint يطابق GET /api/v1/projcts. راجع المسار في توثيق الـ API."
  }
}
422default

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

default
{
  "error": {
    "code": "unprocessable_entity",
    "message": "قيمة due_at غير صالحة؛ أرسل تاريخاً مثل 2026-07-20. المهمة تُستحق في يوم، وأي وقت ترسله يُهمل."
  }
}
429rate_limit_exceeded

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.

Today's daily allowance is spent (application envelope)
{
  "error": {
    "code": "rate_limit_exceeded",
    "message": "استهلكت رصيد اليوم من طلبات API في خطة «المتطور» (1000 طلب يوميًا). يتجدد الرصيد عند منتصف الليل بتوقيت Asia/Riyadh."
  }
}
Over 300 requests in a minute (Rack::Attack body, flat error)
{
  "error": "Rate limit exceeded. Please try again later."
}
الأخطاء

عرض تعليقات مهمة

GET/projects/{project_id}/lists/{task_list_id}/tasks/{task_id}/commentsيتطلب comments:read

الأقدم أولاً.

بارامترات المسار

project_idstringمطلوب

المعرّف الثابت للمشروع، أو الـ slug الخاص به.

task_list_idstringمطلوب

المعرّف الثابت لقائمة المهام، أو الـ slug الخاص بها.

task_idstringمطلوب

المعرّف الثابت للمهمة، أو الـ slug الخاص بها.

بارامترات الاستعلام

limitinteger

حجم الصفحة. الافتراضي 50، والحد الأقصى 100، وما زاد عنه يُقصَر عليه.

الافتراضي: 50

offsetinteger

عدد السجلات التي تُتخطّى. الافتراضي 0.

الافتراضي: 0

مثال الطلب

cURL
curl "https://app.fareeqy.com/api/v1/projects/prj-8f3kd/lists/lst-4m2qp/tasks/tsk-9wb7t/comments" \
  -H "Authorization: Bearer $FAREEQY_API_KEY"

مثال الاستجابة

200
{
  "data": [
    {
      "id": 512,
      "url": "https://app.fareeqy.com/tasks/tsk-9wb7t",
      "content": "راجعت النسخة الأخيرة، ينقصنا حالة الخطأ في النموذج.",
      "author": "عبدالله المطيري",
      "created_at": "2026-07-15T09:48:03.000+03:00",
      "updated_at": "2026-07-15T09:48:03.000+03:00",
      "attachments": []
    },
    {
      "id": 518,
      "url": "https://app.fareeqy.com/tasks/tsk-9wb7t",
      "content": "راجعت الهيدر على ثلاثة مقاسات، وعندي ثلاث ملاحظات. رفعت لقطة للحالات الثلاث.",
      "author": "نورة الحربي",
      "created_at": "2026-07-15T11:20:41.000+03:00",
      "updated_at": "2026-07-15T11:34:09.000+03:00",
      "attachments": [
        {
          "id": 9037,
          "name": "الحالات-الثلاث.png",
          "content_type": "image/png",
          "byte_size": 612352
        }
      ]
    },
    {
      "id": 524,
      "url": "https://app.fareeqy.com/tasks/tsk-9wb7t",
      "content": "خذوا ملاحظات نورة كلها، وابدأوا بالثانية لأنها تكسر الاستخدام لا الشكل. نراجع الاثنين القادم.",
      "author": "سارة العتيبي",
      "created_at": "2026-07-15T14:05:12.000+03:00",
      "updated_at": "2026-07-15T14:05:12.000+03:00",
      "attachments": []
    }
  ],
  "meta": {
    "total": 3,
    "limit": 50,
    "offset": 0,
    "count": 3
  }
}
حالات الرفض:401403404429اعرض أمثلة الرفض
401default

Missing or invalid API key.

default
{
  "error": {
    "code": "unauthorized",
    "message": "مفتاح الـ API غير صالح أو غير مُرسَل."
  }
}
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
{
  "error": {
    "code": "forbidden",
    "message": "هذا الـ API key لا يملك صلاحية تنفيذ هذه العملية."
  }
}
The company's plan carries no API access
{
  "error": {
    "code": "plan_upgrade_required",
    "message": "خطة «الاحترافي» لا تشمل الوصول إلى API. رقِّ إلى «المتطور» أو «الإنتاجي» لتفعيله."
  }
}
404not_found

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.

A record that is missing or out of reach
{
  "error": {
    "code": "not_found",
    "message": "غير موجود، أو لا تملك صلاحية الوصول إليه."
  }
}
A path that matches no endpoint
{
  "error": {
    "code": "unknown_endpoint",
    "message": "لا يوجد endpoint يطابق GET /api/v1/projcts. راجع المسار في توثيق الـ API."
  }
}
429rate_limit_exceeded

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.

Today's daily allowance is spent (application envelope)
{
  "error": {
    "code": "rate_limit_exceeded",
    "message": "استهلكت رصيد اليوم من طلبات API في خطة «المتطور» (1000 طلب يوميًا). يتجدد الرصيد عند منتصف الليل بتوقيت Asia/Riyadh."
  }
}
Over 300 requests in a minute (Rack::Attack body, flat error)
{
  "error": "Rate limit exceeded. Please try again later."
}
الأخطاء

التعليق على مهمة

POST/projects/{project_id}/lists/{task_list_id}/tasks/{task_id}/commentsيتطلب comments:write

بارامترات المسار

project_idstringمطلوب

المعرّف الثابت للمشروع، أو الـ slug الخاص به.

task_list_idstringمطلوب

المعرّف الثابت لقائمة المهام، أو الـ slug الخاص بها.

task_idstringمطلوب

المعرّف الثابت للمهمة، أو الـ slug الخاص بها.

جسم الطلب

contentstringمطلوب

متن التعليق بنص منسّق، ويُرسل نصاً عادياً.

مثال الطلب

cURL
curl -X POST "https://app.fareeqy.com/api/v1/projects/prj-8f3kd/lists/lst-4m2qp/tasks/tsk-9wb7t/comments" \
  -H "Authorization: Bearer $FAREEQY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"content":"خلصنا الهيدر، باقي قسم المزايا."}'

مثال الاستجابة

201 · A quick reply
{
  "data": {
    "id": 512,
    "url": "https://app.fareeqy.com/tasks/tsk-9wb7t",
    "content": "راجعت النسخة الأخيرة، ينقصنا حالة الخطأ في النموذج.",
    "author": "عبدالله المطيري",
    "created_at": "2026-07-15T09:48:03.000+03:00",
    "updated_at": "2026-07-15T09:48:03.000+03:00",
    "attachments": []
  }
}
201 · A long review comment from another member
{
  "data": {
    "id": 518,
    "url": "https://app.fareeqy.com/tasks/tsk-9wb7t",
    "content": "راجعت الهيدر على ثلاثة مقاسات، وعندي ثلاث ملاحظات.\n\nالأولى أن الشعار يقفز سطراً كاملاً تحت 380 بكسل لأن العنصر المجاور له لا ينكمش، فيظهر فراغ أبيض في أعلى الصفحة على أجهزة قديمة ما زالت تمثل نسبة معتبرة من زوارنا.\n\nالثانية أن القائمة المنسدلة تفتح لليسار في الوضع العربي، وهذا يخالف اتجاه القراءة ويجعلها تخرج خارج الشاشة.\n\nالثالثة بسيطة: وزن الخط في الروابط 500 بينما بقية الموقع على 400، فيبدو الهيدر أثقل مما حوله. رفعت لقطة للحالات الثلاث في مجلد «التصاميم».",
    "author": "نورة الحربي",
    "created_at": "2026-07-15T11:20:41.000+03:00",
    "updated_at": "2026-07-15T11:20:41.000+03:00",
    "attachments": [
      {
        "id": 9037,
        "name": "الحالات-الثلاث.png",
        "content_type": "image/png",
        "byte_size": 612352
      }
    ]
  }
}
201 · A closing note from the project owner
{
  "data": {
    "id": 524,
    "url": "https://app.fareeqy.com/tasks/tsk-9wb7t",
    "content": "خذوا ملاحظات نورة كلها، وابدأوا بالثانية لأنها تكسر الاستخدام لا الشكل. نراجع الاثنين القادم.",
    "author": "سارة العتيبي",
    "created_at": "2026-07-15T14:05:12.000+03:00",
    "updated_at": "2026-07-15T14:05:12.000+03:00",
    "attachments": []
  }
}
حالات الرفض:401403404409422429اعرض أمثلة الرفض
401default

Missing or invalid API key.

default
{
  "error": {
    "code": "unauthorized",
    "message": "مفتاح الـ API غير صالح أو غير مُرسَل."
  }
}
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
{
  "error": {
    "code": "forbidden",
    "message": "هذا الـ API key لا يملك صلاحية تنفيذ هذه العملية."
  }
}
The company's plan carries no API access
{
  "error": {
    "code": "plan_upgrade_required",
    "message": "خطة «الاحترافي» لا تشمل الوصول إلى API. رقِّ إلى «المتطور» أو «الإنتاجي» لتفعيله."
  }
}
404not_found

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.

A record that is missing or out of reach
{
  "error": {
    "code": "not_found",
    "message": "غير موجود، أو لا تملك صلاحية الوصول إليه."
  }
}
A path that matches no endpoint
{
  "error": {
    "code": "unknown_endpoint",
    "message": "لا يوجد endpoint يطابق GET /api/v1/projcts. راجع المسار في توثيق الـ API."
  }
}
409default

A uniqueness/record conflict; retry.

default
{
  "error": {
    "code": "conflict",
    "message": "تعذّر إتمام العملية بسبب تعارض. أعد المحاولة."
  }
}
422default

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

default
{
  "error": {
    "code": "unprocessable_entity",
    "message": "قيمة due_at غير صالحة؛ أرسل تاريخاً مثل 2026-07-20. المهمة تُستحق في يوم، وأي وقت ترسله يُهمل."
  }
}
429rate_limit_exceeded

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.

Today's daily allowance is spent (application envelope)
{
  "error": {
    "code": "rate_limit_exceeded",
    "message": "استهلكت رصيد اليوم من طلبات API في خطة «المتطور» (1000 طلب يوميًا). يتجدد الرصيد عند منتصف الليل بتوقيت Asia/Riyadh."
  }
}
Over 300 requests in a minute (Rack::Attack body, flat error)
{
  "error": "Rate limit exceeded. Please try again later."
}
الأخطاء

قراءة ملف مرفق بتعليق على مهمة

GET/projects/{project_id}/lists/{task_list_id}/tasks/{task_id}/comments/{comment_id}/attachments/{id}يتطلب comments:read

يرجع نص ملف واحد مرفق داخل تعليق. وid المعرّف الرقمي للمرفق، وتقرؤه من حقل attachments في التعليق. ولا يُقرأ هنا إلا الملف النصي (بامتدادات مثل md، وtxt، وcsv، وtsv، وjson، وyml، وxml، وhtml، وlog، وsql، وملفات الشيفرة الشائعة)، حتى 256 كيلوبايت. والصورة، وملف PDF، والملف الأكبر من الحد، والملف الفارغ، والملف المفقود من التخزين، كلها تُرفض بالرمز 422 مع ذكر اسمه، فافتحه من صفحة التعليق. ومعرّف مرفق يتبع تعليقاً آخر يرجع 404.

بارامترات المسار

project_idstringمطلوب

المعرّف الثابت للمشروع، أو الـ slug الخاص به.

task_list_idstringمطلوب

المعرّف الثابت لقائمة المهام، أو الـ slug الخاص بها.

task_idstringمطلوب

المعرّف الثابت للمهمة، أو الـ slug الخاص بها.

comment_idintegerمطلوب

المعرّف الرقمي للتعليق، فالتعليقات بلا معرّف ثابت وبلا slug.

idintegerمطلوب

المعرّف الرقمي للمرفق، من حقل attachments في التعليق.

مثال الطلب

cURL
curl "https://app.fareeqy.com/api/v1/projects/prj-8f3kd/lists/lst-4m2qp/tasks/tsk-9wb7t/comments/4821/attachments/1937" \
  -H "Authorization: Bearer $FAREEQY_API_KEY"

مثال الاستجابة

200
{
  "data": {
    "id": 9044,
    "name": "أخطاء-الاستيراد.csv",
    "content_type": "text/csv",
    "byte_size": 412,
    "comment_id": 518,
    "comment_url": "https://app.fareeqy.com/tasks/tsk-9wb7t",
    "content": "row,error\n14,missing due date\n22,unknown assignee\n"
  }
}
حالات الرفض:401403404422429اعرض أمثلة الرفض
401default

Missing or invalid API key.

default
{
  "error": {
    "code": "unauthorized",
    "message": "مفتاح الـ API غير صالح أو غير مُرسَل."
  }
}
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
{
  "error": {
    "code": "forbidden",
    "message": "هذا الـ API key لا يملك صلاحية تنفيذ هذه العملية."
  }
}
The company's plan carries no API access
{
  "error": {
    "code": "plan_upgrade_required",
    "message": "خطة «الاحترافي» لا تشمل الوصول إلى API. رقِّ إلى «المتطور» أو «الإنتاجي» لتفعيله."
  }
}
404not_found

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.

A record that is missing or out of reach
{
  "error": {
    "code": "not_found",
    "message": "غير موجود، أو لا تملك صلاحية الوصول إليه."
  }
}
A path that matches no endpoint
{
  "error": {
    "code": "unknown_endpoint",
    "message": "لا يوجد endpoint يطابق GET /api/v1/projcts. راجع المسار في توثيق الـ API."
  }
}
422default

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

default
{
  "error": {
    "code": "unprocessable_entity",
    "message": "قيمة due_at غير صالحة؛ أرسل تاريخاً مثل 2026-07-20. المهمة تُستحق في يوم، وأي وقت ترسله يُهمل."
  }
}
429rate_limit_exceeded

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.

Today's daily allowance is spent (application envelope)
{
  "error": {
    "code": "rate_limit_exceeded",
    "message": "استهلكت رصيد اليوم من طلبات API في خطة «المتطور» (1000 طلب يوميًا). يتجدد الرصيد عند منتصف الليل بتوقيت Asia/Riyadh."
  }
}
Over 300 requests in a minute (Rack::Attack body, flat error)
{
  "error": "Rate limit exceeded. Please try again later."
}
الأخطاء

عرض تعليقات قائمة مهام بمعرّفها الثابت

GET/lists/{task_list_id}/commentsيتطلب comments:read

الأقدم أولاً.

بارامترات المسار

task_list_idstringمطلوب

المعرّف الثابت لقائمة المهام (lst-4m2qp). ولا يُقبل الـ slug هنا.

بارامترات الاستعلام

limitinteger

حجم الصفحة. الافتراضي 50، والحد الأقصى 100، وما زاد عنه يُقصَر عليه.

الافتراضي: 50

offsetinteger

عدد السجلات التي تُتخطّى. الافتراضي 0.

الافتراضي: 0

مثال الطلب

cURL
curl "https://app.fareeqy.com/api/v1/lists/lst-4m2qp/comments" \
  -H "Authorization: Bearer $FAREEQY_API_KEY"

مثال الاستجابة

200
{
  "data": [
    {
      "id": 512,
      "url": "https://app.fareeqy.com/tasks/tsk-9wb7t",
      "content": "راجعت النسخة الأخيرة، ينقصنا حالة الخطأ في النموذج.",
      "author": "عبدالله المطيري",
      "created_at": "2026-07-15T09:48:03.000+03:00",
      "updated_at": "2026-07-15T09:48:03.000+03:00",
      "attachments": [
        {
          "id": 9031,
          "name": "error-state.png",
          "content_type": "image/png",
          "byte_size": 184320
        }
      ]
    }
  ],
  "meta": {
    "total": 4,
    "limit": 50,
    "offset": 0,
    "count": 4
  }
}
حالات الرفض:401403404429اعرض أمثلة الرفض
401default

Missing or invalid API key.

default
{
  "error": {
    "code": "unauthorized",
    "message": "مفتاح الـ API غير صالح أو غير مُرسَل."
  }
}
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
{
  "error": {
    "code": "forbidden",
    "message": "هذا الـ API key لا يملك صلاحية تنفيذ هذه العملية."
  }
}
The company's plan carries no API access
{
  "error": {
    "code": "plan_upgrade_required",
    "message": "خطة «الاحترافي» لا تشمل الوصول إلى API. رقِّ إلى «المتطور» أو «الإنتاجي» لتفعيله."
  }
}
404not_found

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.

A record that is missing or out of reach
{
  "error": {
    "code": "not_found",
    "message": "غير موجود، أو لا تملك صلاحية الوصول إليه."
  }
}
A path that matches no endpoint
{
  "error": {
    "code": "unknown_endpoint",
    "message": "لا يوجد endpoint يطابق GET /api/v1/projcts. راجع المسار في توثيق الـ API."
  }
}
429rate_limit_exceeded

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.

Today's daily allowance is spent (application envelope)
{
  "error": {
    "code": "rate_limit_exceeded",
    "message": "استهلكت رصيد اليوم من طلبات API في خطة «المتطور» (1000 طلب يوميًا). يتجدد الرصيد عند منتصف الليل بتوقيت Asia/Riyadh."
  }
}
Over 300 requests in a minute (Rack::Attack body, flat error)
{
  "error": "Rate limit exceeded. Please try again later."
}
الأخطاء

التعليق على قائمة مهام بمعرّفها الثابت

POST/lists/{task_list_id}/commentsيتطلب comments:write

بارامترات المسار

task_list_idstringمطلوب

المعرّف الثابت لقائمة المهام (lst-4m2qp). ولا يُقبل الـ slug هنا.

جسم الطلب

contentstringمطلوب

متن التعليق بنص منسّق، ويُرسل نصاً عادياً.

مثال الطلب

cURL
curl -X POST "https://app.fareeqy.com/api/v1/lists/lst-4m2qp/comments" \
  -H "Authorization: Bearer $FAREEQY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"content":"خلصنا الهيدر، باقي قسم المزايا."}'

مثال الاستجابة

201
{
  "data": {
    "id": 512,
    "url": "https://app.fareeqy.com/tasks/tsk-9wb7t",
    "content": "راجعت النسخة الأخيرة، ينقصنا حالة الخطأ في النموذج.",
    "author": "عبدالله المطيري",
    "created_at": "2026-07-15T09:48:03.000+03:00",
    "updated_at": "2026-07-15T09:48:03.000+03:00",
    "attachments": [
      {
        "id": 9031,
        "name": "error-state.png",
        "content_type": "image/png",
        "byte_size": 184320
      }
    ]
  }
}
حالات الرفض:401403404409422429اعرض أمثلة الرفض
401default

Missing or invalid API key.

default
{
  "error": {
    "code": "unauthorized",
    "message": "مفتاح الـ API غير صالح أو غير مُرسَل."
  }
}
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
{
  "error": {
    "code": "forbidden",
    "message": "هذا الـ API key لا يملك صلاحية تنفيذ هذه العملية."
  }
}
The company's plan carries no API access
{
  "error": {
    "code": "plan_upgrade_required",
    "message": "خطة «الاحترافي» لا تشمل الوصول إلى API. رقِّ إلى «المتطور» أو «الإنتاجي» لتفعيله."
  }
}
404not_found

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.

A record that is missing or out of reach
{
  "error": {
    "code": "not_found",
    "message": "غير موجود، أو لا تملك صلاحية الوصول إليه."
  }
}
A path that matches no endpoint
{
  "error": {
    "code": "unknown_endpoint",
    "message": "لا يوجد endpoint يطابق GET /api/v1/projcts. راجع المسار في توثيق الـ API."
  }
}
409default

A uniqueness/record conflict; retry.

default
{
  "error": {
    "code": "conflict",
    "message": "تعذّر إتمام العملية بسبب تعارض. أعد المحاولة."
  }
}
422default

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

default
{
  "error": {
    "code": "unprocessable_entity",
    "message": "قيمة due_at غير صالحة؛ أرسل تاريخاً مثل 2026-07-20. المهمة تُستحق في يوم، وأي وقت ترسله يُهمل."
  }
}
429rate_limit_exceeded

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.

Today's daily allowance is spent (application envelope)
{
  "error": {
    "code": "rate_limit_exceeded",
    "message": "استهلكت رصيد اليوم من طلبات API في خطة «المتطور» (1000 طلب يوميًا). يتجدد الرصيد عند منتصف الليل بتوقيت Asia/Riyadh."
  }
}
Over 300 requests in a minute (Rack::Attack body, flat error)
{
  "error": "Rate limit exceeded. Please try again later."
}
الأخطاء

قراءة ملف مرفق بتعليق على قائمة مهام، بمعرّفها الثابت

GET/lists/{task_list_id}/comments/{comment_id}/attachments/{id}يتطلب comments:read

يرجع نص ملف واحد مرفق داخل تعليق. وid المعرّف الرقمي للمرفق، وتقرؤه من حقل attachments في التعليق. ولا يُقرأ هنا إلا الملف النصي (بامتدادات مثل md، وtxt، وcsv، وtsv، وjson، وyml، وxml، وhtml، وlog، وsql، وملفات الشيفرة الشائعة)، حتى 256 كيلوبايت. والصورة، وملف PDF، والملف الأكبر من الحد، والملف الفارغ، والملف المفقود من التخزين، كلها تُرفض بالرمز 422 مع ذكر اسمه، فافتحه من صفحة التعليق. ومعرّف مرفق يتبع تعليقاً آخر يرجع 404.

بارامترات المسار

task_list_idstringمطلوب

المعرّف الثابت لقائمة المهام (lst-4m2qp). ولا يُقبل الـ slug هنا.

comment_idintegerمطلوب

المعرّف الرقمي للتعليق، فالتعليقات بلا معرّف ثابت وبلا slug.

idintegerمطلوب

المعرّف الرقمي للمرفق، من حقل attachments في التعليق.

مثال الطلب

cURL
curl "https://app.fareeqy.com/api/v1/lists/lst-4m2qp/comments/4821/attachments/1937" \
  -H "Authorization: Bearer $FAREEQY_API_KEY"

مثال الاستجابة

200
{
  "data": {
    "id": 9044,
    "name": "أخطاء-الاستيراد.csv",
    "content_type": "text/csv",
    "byte_size": 412,
    "comment_id": 518,
    "comment_url": "https://app.fareeqy.com/tasks/tsk-9wb7t",
    "content": "row,error\n14,missing due date\n22,unknown assignee\n"
  }
}
حالات الرفض:401403404422429اعرض أمثلة الرفض
401default

Missing or invalid API key.

default
{
  "error": {
    "code": "unauthorized",
    "message": "مفتاح الـ API غير صالح أو غير مُرسَل."
  }
}
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
{
  "error": {
    "code": "forbidden",
    "message": "هذا الـ API key لا يملك صلاحية تنفيذ هذه العملية."
  }
}
The company's plan carries no API access
{
  "error": {
    "code": "plan_upgrade_required",
    "message": "خطة «الاحترافي» لا تشمل الوصول إلى API. رقِّ إلى «المتطور» أو «الإنتاجي» لتفعيله."
  }
}
404not_found

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.

A record that is missing or out of reach
{
  "error": {
    "code": "not_found",
    "message": "غير موجود، أو لا تملك صلاحية الوصول إليه."
  }
}
A path that matches no endpoint
{
  "error": {
    "code": "unknown_endpoint",
    "message": "لا يوجد endpoint يطابق GET /api/v1/projcts. راجع المسار في توثيق الـ API."
  }
}
422default

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

default
{
  "error": {
    "code": "unprocessable_entity",
    "message": "قيمة due_at غير صالحة؛ أرسل تاريخاً مثل 2026-07-20. المهمة تُستحق في يوم، وأي وقت ترسله يُهمل."
  }
}
429rate_limit_exceeded

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.

Today's daily allowance is spent (application envelope)
{
  "error": {
    "code": "rate_limit_exceeded",
    "message": "استهلكت رصيد اليوم من طلبات API في خطة «المتطور» (1000 طلب يوميًا). يتجدد الرصيد عند منتصف الليل بتوقيت Asia/Riyadh."
  }
}
Over 300 requests in a minute (Rack::Attack body, flat error)
{
  "error": "Rate limit exceeded. Please try again later."
}
الأخطاء

عرض تعليقات مهمة بمعرّفها الثابت

GET/tasks/{task_id}/commentsيتطلب comments:read

الأقدم أولاً.

بارامترات المسار

task_idstringمطلوب

المعرّف الثابت للمهمة (tsk-9wb7t). ولا يُقبل الـ slug هنا.

بارامترات الاستعلام

limitinteger

حجم الصفحة. الافتراضي 50، والحد الأقصى 100، وما زاد عنه يُقصَر عليه.

الافتراضي: 50

offsetinteger

عدد السجلات التي تُتخطّى. الافتراضي 0.

الافتراضي: 0

مثال الطلب

cURL
curl "https://app.fareeqy.com/api/v1/tasks/tsk-9wb7t/comments" \
  -H "Authorization: Bearer $FAREEQY_API_KEY"

مثال الاستجابة

200
{
  "data": [
    {
      "id": 512,
      "url": "https://app.fareeqy.com/tasks/tsk-9wb7t",
      "content": "راجعت النسخة الأخيرة، ينقصنا حالة الخطأ في النموذج.",
      "author": "عبدالله المطيري",
      "created_at": "2026-07-15T09:48:03.000+03:00",
      "updated_at": "2026-07-15T09:48:03.000+03:00",
      "attachments": [
        {
          "id": 9031,
          "name": "error-state.png",
          "content_type": "image/png",
          "byte_size": 184320
        }
      ]
    }
  ],
  "meta": {
    "total": 4,
    "limit": 50,
    "offset": 0,
    "count": 4
  }
}
حالات الرفض:401403404429اعرض أمثلة الرفض
401default

Missing or invalid API key.

default
{
  "error": {
    "code": "unauthorized",
    "message": "مفتاح الـ API غير صالح أو غير مُرسَل."
  }
}
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
{
  "error": {
    "code": "forbidden",
    "message": "هذا الـ API key لا يملك صلاحية تنفيذ هذه العملية."
  }
}
The company's plan carries no API access
{
  "error": {
    "code": "plan_upgrade_required",
    "message": "خطة «الاحترافي» لا تشمل الوصول إلى API. رقِّ إلى «المتطور» أو «الإنتاجي» لتفعيله."
  }
}
404not_found

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.

A record that is missing or out of reach
{
  "error": {
    "code": "not_found",
    "message": "غير موجود، أو لا تملك صلاحية الوصول إليه."
  }
}
A path that matches no endpoint
{
  "error": {
    "code": "unknown_endpoint",
    "message": "لا يوجد endpoint يطابق GET /api/v1/projcts. راجع المسار في توثيق الـ API."
  }
}
429rate_limit_exceeded

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.

Today's daily allowance is spent (application envelope)
{
  "error": {
    "code": "rate_limit_exceeded",
    "message": "استهلكت رصيد اليوم من طلبات API في خطة «المتطور» (1000 طلب يوميًا). يتجدد الرصيد عند منتصف الليل بتوقيت Asia/Riyadh."
  }
}
Over 300 requests in a minute (Rack::Attack body, flat error)
{
  "error": "Rate limit exceeded. Please try again later."
}
الأخطاء

التعليق على مهمة بمعرّفها الثابت

POST/tasks/{task_id}/commentsيتطلب comments:write

بارامترات المسار

task_idstringمطلوب

المعرّف الثابت للمهمة (tsk-9wb7t). ولا يُقبل الـ slug هنا.

جسم الطلب

contentstringمطلوب

متن التعليق بنص منسّق، ويُرسل نصاً عادياً.

مثال الطلب

cURL
curl -X POST "https://app.fareeqy.com/api/v1/tasks/tsk-9wb7t/comments" \
  -H "Authorization: Bearer $FAREEQY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"content":"خلصنا الهيدر، باقي قسم المزايا."}'

مثال الاستجابة

201
{
  "data": {
    "id": 512,
    "url": "https://app.fareeqy.com/tasks/tsk-9wb7t",
    "content": "راجعت النسخة الأخيرة، ينقصنا حالة الخطأ في النموذج.",
    "author": "عبدالله المطيري",
    "created_at": "2026-07-15T09:48:03.000+03:00",
    "updated_at": "2026-07-15T09:48:03.000+03:00",
    "attachments": [
      {
        "id": 9031,
        "name": "error-state.png",
        "content_type": "image/png",
        "byte_size": 184320
      }
    ]
  }
}
حالات الرفض:401403404409422429اعرض أمثلة الرفض
401default

Missing or invalid API key.

default
{
  "error": {
    "code": "unauthorized",
    "message": "مفتاح الـ API غير صالح أو غير مُرسَل."
  }
}
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
{
  "error": {
    "code": "forbidden",
    "message": "هذا الـ API key لا يملك صلاحية تنفيذ هذه العملية."
  }
}
The company's plan carries no API access
{
  "error": {
    "code": "plan_upgrade_required",
    "message": "خطة «الاحترافي» لا تشمل الوصول إلى API. رقِّ إلى «المتطور» أو «الإنتاجي» لتفعيله."
  }
}
404not_found

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.

A record that is missing or out of reach
{
  "error": {
    "code": "not_found",
    "message": "غير موجود، أو لا تملك صلاحية الوصول إليه."
  }
}
A path that matches no endpoint
{
  "error": {
    "code": "unknown_endpoint",
    "message": "لا يوجد endpoint يطابق GET /api/v1/projcts. راجع المسار في توثيق الـ API."
  }
}
409default

A uniqueness/record conflict; retry.

default
{
  "error": {
    "code": "conflict",
    "message": "تعذّر إتمام العملية بسبب تعارض. أعد المحاولة."
  }
}
422default

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

default
{
  "error": {
    "code": "unprocessable_entity",
    "message": "قيمة due_at غير صالحة؛ أرسل تاريخاً مثل 2026-07-20. المهمة تُستحق في يوم، وأي وقت ترسله يُهمل."
  }
}
429rate_limit_exceeded

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.

Today's daily allowance is spent (application envelope)
{
  "error": {
    "code": "rate_limit_exceeded",
    "message": "استهلكت رصيد اليوم من طلبات API في خطة «المتطور» (1000 طلب يوميًا). يتجدد الرصيد عند منتصف الليل بتوقيت Asia/Riyadh."
  }
}
Over 300 requests in a minute (Rack::Attack body, flat error)
{
  "error": "Rate limit exceeded. Please try again later."
}
الأخطاء

قراءة ملف مرفق بتعليق على مهمة، بمعرّفها الثابت

GET/tasks/{task_id}/comments/{comment_id}/attachments/{id}يتطلب comments:read

يرجع نص ملف واحد مرفق داخل تعليق. وid المعرّف الرقمي للمرفق، وتقرؤه من حقل attachments في التعليق. ولا يُقرأ هنا إلا الملف النصي (بامتدادات مثل md، وtxt، وcsv، وtsv، وjson، وyml، وxml، وhtml، وlog، وsql، وملفات الشيفرة الشائعة)، حتى 256 كيلوبايت. والصورة، وملف PDF، والملف الأكبر من الحد، والملف الفارغ، والملف المفقود من التخزين، كلها تُرفض بالرمز 422 مع ذكر اسمه، فافتحه من صفحة التعليق. ومعرّف مرفق يتبع تعليقاً آخر يرجع 404.

بارامترات المسار

task_idstringمطلوب

المعرّف الثابت للمهمة (tsk-9wb7t). ولا يُقبل الـ slug هنا.

comment_idintegerمطلوب

المعرّف الرقمي للتعليق، فالتعليقات بلا معرّف ثابت وبلا slug.

idintegerمطلوب

المعرّف الرقمي للمرفق، من حقل attachments في التعليق.

مثال الطلب

cURL
curl "https://app.fareeqy.com/api/v1/tasks/tsk-9wb7t/comments/4821/attachments/1937" \
  -H "Authorization: Bearer $FAREEQY_API_KEY"

مثال الاستجابة

200
{
  "data": {
    "id": 9044,
    "name": "أخطاء-الاستيراد.csv",
    "content_type": "text/csv",
    "byte_size": 412,
    "comment_id": 518,
    "comment_url": "https://app.fareeqy.com/tasks/tsk-9wb7t",
    "content": "row,error\n14,missing due date\n22,unknown assignee\n"
  }
}
حالات الرفض:401403404422429اعرض أمثلة الرفض
401default

Missing or invalid API key.

default
{
  "error": {
    "code": "unauthorized",
    "message": "مفتاح الـ API غير صالح أو غير مُرسَل."
  }
}
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
{
  "error": {
    "code": "forbidden",
    "message": "هذا الـ API key لا يملك صلاحية تنفيذ هذه العملية."
  }
}
The company's plan carries no API access
{
  "error": {
    "code": "plan_upgrade_required",
    "message": "خطة «الاحترافي» لا تشمل الوصول إلى API. رقِّ إلى «المتطور» أو «الإنتاجي» لتفعيله."
  }
}
404not_found

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.

A record that is missing or out of reach
{
  "error": {
    "code": "not_found",
    "message": "غير موجود، أو لا تملك صلاحية الوصول إليه."
  }
}
A path that matches no endpoint
{
  "error": {
    "code": "unknown_endpoint",
    "message": "لا يوجد endpoint يطابق GET /api/v1/projcts. راجع المسار في توثيق الـ API."
  }
}
422default

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

default
{
  "error": {
    "code": "unprocessable_entity",
    "message": "قيمة due_at غير صالحة؛ أرسل تاريخاً مثل 2026-07-20. المهمة تُستحق في يوم، وأي وقت ترسله يُهمل."
  }
}
429rate_limit_exceeded

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.

Today's daily allowance is spent (application envelope)
{
  "error": {
    "code": "rate_limit_exceeded",
    "message": "استهلكت رصيد اليوم من طلبات API في خطة «المتطور» (1000 طلب يوميًا). يتجدد الرصيد عند منتصف الليل بتوقيت Asia/Riyadh."
  }
}
Over 300 requests in a minute (Rack::Attack body, flat error)
{
  "error": "Rate limit exceeded. Please try again later."
}
الأخطاء