---
title: "Projects | Fareeqy API"
description: "The company's projects, private ones included. The Projects endpoints in the Fareeqy REST API: parameters, request bodies, response examples, and refusals."
url: https://fareeqy.com/api/v1/docs/projects/en
language: en
---

# Projects

The company's projects, private ones included.

Base URL `https://app.fareeqy.com/api/v1`

Contents

On this page

-   The resource
-   List the company's projects
-   Create a project
-   Get a project
-   Update a project
-   Delete a project
-   Archive a project
-   Unarchive a project

Endpoints

-   [Account](https://fareeqy.com/api/v1/docs/account/en)
-   [Events](https://fareeqy.com/api/v1/docs/events/en)
-   [Projects](https://fareeqy.com/api/v1/docs/projects/en)
-   [Members](https://fareeqy.com/api/v1/docs/members/en)
-   [Task lists](https://fareeqy.com/api/v1/docs/task-lists/en)
-   [Tasks](https://fareeqy.com/api/v1/docs/tasks/en)
-   [Comments](https://fareeqy.com/api/v1/docs/comments/en)
-   [Discussions](https://fareeqy.com/api/v1/docs/discussions/en)
-   [Files](https://fareeqy.com/api/v1/docs/files/en)
-   [Folders](https://fareeqy.com/api/v1/docs/folders/en)

More

-   [Changelog](https://fareeqy.com/api/v1/docs/changelog/en)

On this page

-   The resource
-   List the company's projects
-   Create a project
-   Get a project
-   Update a project
-   Delete a project
-   Archive a project
-   Unarchive a project

Endpoints

-   [Account](https://fareeqy.com/api/v1/docs/account/en)
-   [Events](https://fareeqy.com/api/v1/docs/events/en)
-   [Projects](https://fareeqy.com/api/v1/docs/projects/en)
-   [Members](https://fareeqy.com/api/v1/docs/members/en)
-   [Task lists](https://fareeqy.com/api/v1/docs/task-lists/en)
-   [Tasks](https://fareeqy.com/api/v1/docs/tasks/en)
-   [Comments](https://fareeqy.com/api/v1/docs/comments/en)
-   [Discussions](https://fareeqy.com/api/v1/docs/discussions/en)
-   [Files](https://fareeqy.com/api/v1/docs/files/en)
-   [Folders](https://fareeqy.com/api/v1/docs/folders/en)

More

-   [Changelog](https://fareeqy.com/api/v1/docs/changelog/en)

## The resource

The fields returned inside `data` by the endpoints in this group.

`id` string

The project ref: the stable public id. A slug is still accepted anywhere this is passed back.

`url` string | null

Absolute address of the page a person opens in فريقي.

`name` string

`description` string | null

`is_public` boolean

`archived` boolean

`start_date` string (date) | null

`end_date` string (date) | null

`task_lists_count` integer

Number of task lists (counter cache).

`tasks_count` integer

Number of tasks across the project's lists.

`created_at` string (date-time)

`updated_at` string (date-time)

Project Copy

 `{   "id": "prj-8f3kd",   "url": "https://app.fareeqy.com/projects/prj-8f3kd",   "name": "تطوير الموقع",   "description": "إعادة بناء الموقع التعريفي وربطه بالمنتج.",   "is_public": false,   "archived": false,   "start_date": "2026-07-01",   "end_date": "2026-09-30",   "task_lists_count": 4,   "tasks_count": 27,   "created_at": "2026-07-01T09:15:00.000+03:00",   "updated_at": "2026-07-14T12:22:31.000+03:00" }`

### List the company's projects

GET /projects Requires `projects:read`

Every project in the key's company, private ones included, newest first. The one exception is an onboarding demo project, which stays private to the person it was created for. Excludes archived unless `include_archived`.

#### Query parameters

`include_archived` boolean

Include archived projects.

Default: `false`

`limit` integer

Page size (default 50, max 100, clamped).

Default: `50`

`offset` integer

Number of records to skip (default 0).

Default: `0`

#### Request

cURL Copy

 `curl "https://app.fareeqy.com/api/v1/projects" \   -H "Authorization: Bearer $FAREEQY_API_KEY"`

#### Response

200 Copy

 `{   "data": [     {       "id": "prj-8f3kd",       "url": "https://app.fareeqy.com/projects/prj-8f3kd",       "name": "تطوير الموقع",       "description": "إعادة بناء الموقع التعريفي وربطه بالمنتج.",       "is_public": false,       "archived": false,       "start_date": "2026-07-01",       "end_date": "2026-09-30",       "task_lists_count": 4,       "tasks_count": 27,       "created_at": "2026-07-01T09:15:00.000+03:00",       "updated_at": "2026-07-14T12:22:31.000+03:00"     }   ],   "meta": {     "total": 4,     "limit": 50,     "offset": 0,     "count": 4   } }`

Refusals: 401 403 404 429 Show failure examples Hide failure examples

401 `default`

Missing or invalid API key.

default Copy

 `{   "error": {     "code": "unauthorized",     "message": "مفتاح الـ API غير صالح أو غير مُرسَل."   } }`

403 `forbidden`

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 Copy

 `{   "error": {     "code": "forbidden",     "message": "هذا الـ API key لا يملك صلاحية تنفيذ هذه العملية."   } }`

The company's plan carries no API access Copy

 `{   "error": {     "code": "plan_upgrade_required",     "message": "خطة «الاحترافي» لا تشمل الوصول إلى API. رقِّ إلى «المتطور» أو «الإنتاجي» لتفعيله."   } }`

404 `not_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 Copy

 `{   "error": {     "code": "not_found",     "message": "غير موجود، أو لا تملك صلاحية الوصول إليه."   } }`

A path that matches no endpoint Copy

 `{   "error": {     "code": "unknown_endpoint",     "message": "لا يوجد endpoint يطابق GET /api/v1/projcts. راجع المسار في توثيق الـ API."   } }`

429 `rate_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) Copy

 `{   "error": {     "code": "rate_limit_exceeded",     "message": "استهلكت رصيد اليوم من طلبات API في خطة «المتطور» (1000 طلب يوميًا). يتجدد الرصيد عند منتصف الليل بتوقيت Asia/Riyadh."   } }`

Over 300 requests in a minute (Rack::Attack body, flat error) Copy

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

[Errors](https://fareeqy.com/api/v1/docs/en#errors)

### Create a project

POST /projects Requires `projects:write`

#### Request body

`name` string required

`description` string | null

`start_date` string | null

ISO 8601 date.

`end_date` string | null

ISO 8601 date.

`is_public` boolean

#### Request

cURL Copy

 `curl -X POST "https://app.fareeqy.com/api/v1/projects" \   -H "Authorization: Bearer $FAREEQY_API_KEY" \   -H "Content-Type: application/json" \   -d '{"name":"تطوير الموقع","description":"إعادة بناء الموقع التعريفي وربطه بالمنتج.","start_date":"2026-07-01","end_date":"2026-09-30","is_public":false}'`

#### Response

201 Copy

 `{   "data": {     "id": "prj-8f3kd",     "url": "https://app.fareeqy.com/projects/prj-8f3kd",     "name": "تطوير الموقع",     "description": "إعادة بناء الموقع التعريفي وربطه بالمنتج.",     "is_public": false,     "archived": false,     "start_date": "2026-07-01",     "end_date": "2026-09-30",     "task_lists_count": 4,     "tasks_count": 27,     "created_at": "2026-07-01T09:15:00.000+03:00",     "updated_at": "2026-07-14T12:22:31.000+03:00"   } }`

Refusals: 401 403 404 409 422 429 Show failure examples Hide failure examples

401 `default`

Missing or invalid API key.

default Copy

 `{   "error": {     "code": "unauthorized",     "message": "مفتاح الـ API غير صالح أو غير مُرسَل."   } }`

403 `forbidden`

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 Copy

 `{   "error": {     "code": "forbidden",     "message": "هذا الـ API key لا يملك صلاحية تنفيذ هذه العملية."   } }`

The company's plan carries no API access Copy

 `{   "error": {     "code": "plan_upgrade_required",     "message": "خطة «الاحترافي» لا تشمل الوصول إلى API. رقِّ إلى «المتطور» أو «الإنتاجي» لتفعيله."   } }`

404 `not_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 Copy

 `{   "error": {     "code": "not_found",     "message": "غير موجود، أو لا تملك صلاحية الوصول إليه."   } }`

A path that matches no endpoint Copy

 `{   "error": {     "code": "unknown_endpoint",     "message": "لا يوجد endpoint يطابق GET /api/v1/projcts. راجع المسار في توثيق الـ API."   } }`

409 `default`

A uniqueness/record conflict; retry.

default Copy

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

422 `default`

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

default Copy

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

429 `rate_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) Copy

 `{   "error": {     "code": "rate_limit_exceeded",     "message": "استهلكت رصيد اليوم من طلبات API في خطة «المتطور» (1000 طلب يوميًا). يتجدد الرصيد عند منتصف الليل بتوقيت Asia/Riyadh."   } }`

Over 300 requests in a minute (Rack::Attack body, flat error) Copy

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

[Errors](https://fareeqy.com/api/v1/docs/en#errors)

### Get a project

GET /projects/ {id} Requires `projects:read`

#### Path parameters

`id` string required

The project REF (prj-8f3kd), or its slug (unique within the company).

#### Request

cURL Copy

 `curl "https://app.fareeqy.com/api/v1/projects/prj-8f3kd" \   -H "Authorization: Bearer $FAREEQY_API_KEY"`

#### Response

200 Copy

 `{   "data": {     "id": "prj-8f3kd",     "url": "https://app.fareeqy.com/projects/prj-8f3kd",     "name": "تطوير الموقع",     "description": "إعادة بناء الموقع التعريفي وربطه بالمنتج.",     "is_public": false,     "archived": false,     "start_date": "2026-07-01",     "end_date": "2026-09-30",     "task_lists_count": 4,     "tasks_count": 27,     "created_at": "2026-07-01T09:15:00.000+03:00",     "updated_at": "2026-07-14T12:22:31.000+03:00"   } }`

Refusals: 401 403 404 429 Show failure examples Hide failure examples

401 `default`

Missing or invalid API key.

default Copy

 `{   "error": {     "code": "unauthorized",     "message": "مفتاح الـ API غير صالح أو غير مُرسَل."   } }`

403 `forbidden`

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 Copy

 `{   "error": {     "code": "forbidden",     "message": "هذا الـ API key لا يملك صلاحية تنفيذ هذه العملية."   } }`

The company's plan carries no API access Copy

 `{   "error": {     "code": "plan_upgrade_required",     "message": "خطة «الاحترافي» لا تشمل الوصول إلى API. رقِّ إلى «المتطور» أو «الإنتاجي» لتفعيله."   } }`

404 `not_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 Copy

 `{   "error": {     "code": "not_found",     "message": "غير موجود، أو لا تملك صلاحية الوصول إليه."   } }`

A path that matches no endpoint Copy

 `{   "error": {     "code": "unknown_endpoint",     "message": "لا يوجد endpoint يطابق GET /api/v1/projcts. راجع المسار في توثيق الـ API."   } }`

429 `rate_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) Copy

 `{   "error": {     "code": "rate_limit_exceeded",     "message": "استهلكت رصيد اليوم من طلبات API في خطة «المتطور» (1000 طلب يوميًا). يتجدد الرصيد عند منتصف الليل بتوقيت Asia/Riyadh."   } }`

Over 300 requests in a minute (Rack::Attack body, flat error) Copy

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

[Errors](https://fareeqy.com/api/v1/docs/en#errors)

### Update a project

PATCH /projects/ {id} Requires `projects:write`

#### Path parameters

`id` string required

The project REF (prj-8f3kd), or its slug (unique within the company).

#### Request body

`name` string

`description` string | null

`start_date` string | null

`end_date` string | null

`is_public` boolean

#### Request

cURL Copy

 `curl -X PATCH "https://app.fareeqy.com/api/v1/projects/prj-8f3kd" \   -H "Authorization: Bearer $FAREEQY_API_KEY" \   -H "Content-Type: application/json" \   -d '{"description":"إعادة بناء الموقع التعريفي وربطه بالمنتج وبلوحة القياس.","end_date":"2026-10-15"}'`

#### Response

200 Copy

 `{   "data": {     "id": "prj-8f3kd",     "url": "https://app.fareeqy.com/projects/prj-8f3kd",     "name": "تطوير الموقع",     "description": "إعادة بناء الموقع التعريفي وربطه بالمنتج.",     "is_public": false,     "archived": false,     "start_date": "2026-07-01",     "end_date": "2026-09-30",     "task_lists_count": 4,     "tasks_count": 27,     "created_at": "2026-07-01T09:15:00.000+03:00",     "updated_at": "2026-07-14T12:22:31.000+03:00"   } }`

Refusals: 401 403 404 409 422 429 Show failure examples Hide failure examples

401 `default`

Missing or invalid API key.

default Copy

 `{   "error": {     "code": "unauthorized",     "message": "مفتاح الـ API غير صالح أو غير مُرسَل."   } }`

403 `forbidden`

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 Copy

 `{   "error": {     "code": "forbidden",     "message": "هذا الـ API key لا يملك صلاحية تنفيذ هذه العملية."   } }`

The company's plan carries no API access Copy

 `{   "error": {     "code": "plan_upgrade_required",     "message": "خطة «الاحترافي» لا تشمل الوصول إلى API. رقِّ إلى «المتطور» أو «الإنتاجي» لتفعيله."   } }`

404 `not_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 Copy

 `{   "error": {     "code": "not_found",     "message": "غير موجود، أو لا تملك صلاحية الوصول إليه."   } }`

A path that matches no endpoint Copy

 `{   "error": {     "code": "unknown_endpoint",     "message": "لا يوجد endpoint يطابق GET /api/v1/projcts. راجع المسار في توثيق الـ API."   } }`

409 `default`

A uniqueness/record conflict; retry.

default Copy

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

422 `default`

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

default Copy

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

429 `rate_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) Copy

 `{   "error": {     "code": "rate_limit_exceeded",     "message": "استهلكت رصيد اليوم من طلبات API في خطة «المتطور» (1000 طلب يوميًا). يتجدد الرصيد عند منتصف الليل بتوقيت Asia/Riyadh."   } }`

Over 300 requests in a minute (Rack::Attack body, flat error) Copy

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

[Errors](https://fareeqy.com/api/v1/docs/en#errors)

### Delete a project

DELETE /projects/ {id} Requires `projects:destructive`

Permanent, cascading delete. Prefer archive. The response reports the counts destroyed. A project that a connected integration feeds is refused with 409 `project_in_use` until the integration is disconnected or pointed at another project.

#### Path parameters

`id` string required

The project REF (prj-8f3kd), or its slug (unique within the company).

#### Request

cURL Copy

 `curl -X DELETE "https://app.fareeqy.com/api/v1/projects/prj-8f3kd" \   -H "Authorization: Bearer $FAREEQY_API_KEY"`

#### Response

200 Copy

 `{   "data": {     "deleted": true,     "project": {       "name": "تطوير الموقع",       "id": "prj-8f3kd"     },     "destroyed": {       "task_lists": 4,       "tasks": 27,       "discussions": 3,       "files": 12,       "folders": 2     }   } }`

Refusals: 401 403 404 409 429 Show failure examples Hide failure examples

401 `default`

Missing or invalid API key.

default Copy

 `{   "error": {     "code": "unauthorized",     "message": "مفتاح الـ API غير صالح أو غير مُرسَل."   } }`

403 `forbidden`

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 Copy

 `{   "error": {     "code": "forbidden",     "message": "هذا الـ API key لا يملك صلاحية تنفيذ هذه العملية."   } }`

The company's plan carries no API access Copy

 `{   "error": {     "code": "plan_upgrade_required",     "message": "خطة «الاحترافي» لا تشمل الوصول إلى API. رقِّ إلى «المتطور» أو «الإنتاجي» لتفعيله."   } }`

404 `not_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 Copy

 `{   "error": {     "code": "not_found",     "message": "غير موجود، أو لا تملك صلاحية الوصول إليه."   } }`

A path that matches no endpoint Copy

 `{   "error": {     "code": "unknown_endpoint",     "message": "لا يوجد endpoint يطابق GET /api/v1/projcts. راجع المسار في توثيق الـ API."   } }`

409 `default`

The project cannot be deleted because a connected integration sends its work there. Nothing was deleted. Disconnect the integration, or point it at another project, then delete again. Retrying as-is will not help.

default Copy

 `{   "error": {     "code": "project_in_use",     "message": "هذا المشروع وجهة تكامل موصول (Sentry). حذفه لا يوقف وصول الأخطاء، بل يجعلها تصل إلى لا مكان. افصل التكامل من «الإعدادات ← التكاملات»، أو وجّهه إلى مشروع آخر، ثم احذف هذا المشروع."   } }`

429 `rate_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) Copy

 `{   "error": {     "code": "rate_limit_exceeded",     "message": "استهلكت رصيد اليوم من طلبات API في خطة «المتطور» (1000 طلب يوميًا). يتجدد الرصيد عند منتصف الليل بتوقيت Asia/Riyadh."   } }`

Over 300 requests in a minute (Rack::Attack body, flat error) Copy

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

[Errors](https://fareeqy.com/api/v1/docs/en#errors)

### Archive a project

POST /projects/ {id} /archive Requires `projects:write`

Reversible put-away; records a timeline event and freezes writes across the project. Prefer this over delete.

#### Path parameters

`id` string required

The project REF (prj-8f3kd), or its slug (unique within the company).

#### Request

cURL Copy

 `curl -X POST "https://app.fareeqy.com/api/v1/projects/prj-8f3kd/archive" \   -H "Authorization: Bearer $FAREEQY_API_KEY"`

#### Response

200 Copy

 `{   "data": {     "id": "prj-8f3kd",     "url": "https://app.fareeqy.com/projects/prj-8f3kd",     "name": "تطوير الموقع",     "description": "إعادة بناء الموقع التعريفي وربطه بالمنتج.",     "is_public": false,     "archived": false,     "start_date": "2026-07-01",     "end_date": "2026-09-30",     "task_lists_count": 4,     "tasks_count": 27,     "created_at": "2026-07-01T09:15:00.000+03:00",     "updated_at": "2026-07-14T12:22:31.000+03:00"   } }`

Refusals: 401 403 404 409 422 429 Show failure examples Hide failure examples

401 `default`

Missing or invalid API key.

default Copy

 `{   "error": {     "code": "unauthorized",     "message": "مفتاح الـ API غير صالح أو غير مُرسَل."   } }`

403 `forbidden`

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 Copy

 `{   "error": {     "code": "forbidden",     "message": "هذا الـ API key لا يملك صلاحية تنفيذ هذه العملية."   } }`

The company's plan carries no API access Copy

 `{   "error": {     "code": "plan_upgrade_required",     "message": "خطة «الاحترافي» لا تشمل الوصول إلى API. رقِّ إلى «المتطور» أو «الإنتاجي» لتفعيله."   } }`

404 `not_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 Copy

 `{   "error": {     "code": "not_found",     "message": "غير موجود، أو لا تملك صلاحية الوصول إليه."   } }`

A path that matches no endpoint Copy

 `{   "error": {     "code": "unknown_endpoint",     "message": "لا يوجد endpoint يطابق GET /api/v1/projcts. راجع المسار في توثيق الـ API."   } }`

409 `default`

A uniqueness/record conflict; retry.

default Copy

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

422 `default`

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

default Copy

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

429 `rate_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) Copy

 `{   "error": {     "code": "rate_limit_exceeded",     "message": "استهلكت رصيد اليوم من طلبات API في خطة «المتطور» (1000 طلب يوميًا). يتجدد الرصيد عند منتصف الليل بتوقيت Asia/Riyadh."   } }`

Over 300 requests in a minute (Rack::Attack body, flat error) Copy

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

[Errors](https://fareeqy.com/api/v1/docs/en#errors)

### Unarchive a project

POST /projects/ {id} /unarchive Requires `projects:write`

#### Path parameters

`id` string required

The project REF (prj-8f3kd), or its slug (unique within the company).

#### Request

cURL Copy

 `curl -X POST "https://app.fareeqy.com/api/v1/projects/prj-8f3kd/unarchive" \   -H "Authorization: Bearer $FAREEQY_API_KEY"`

#### Response

200 Copy

 `{   "data": {     "id": "prj-8f3kd",     "url": "https://app.fareeqy.com/projects/prj-8f3kd",     "name": "تطوير الموقع",     "description": "إعادة بناء الموقع التعريفي وربطه بالمنتج.",     "is_public": false,     "archived": false,     "start_date": "2026-07-01",     "end_date": "2026-09-30",     "task_lists_count": 4,     "tasks_count": 27,     "created_at": "2026-07-01T09:15:00.000+03:00",     "updated_at": "2026-07-14T12:22:31.000+03:00"   } }`

Refusals: 401 403 404 409 422 429 Show failure examples Hide failure examples

401 `default`

Missing or invalid API key.

default Copy

 `{   "error": {     "code": "unauthorized",     "message": "مفتاح الـ API غير صالح أو غير مُرسَل."   } }`

403 `forbidden`

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 Copy

 `{   "error": {     "code": "forbidden",     "message": "هذا الـ API key لا يملك صلاحية تنفيذ هذه العملية."   } }`

The company's plan carries no API access Copy

 `{   "error": {     "code": "plan_upgrade_required",     "message": "خطة «الاحترافي» لا تشمل الوصول إلى API. رقِّ إلى «المتطور» أو «الإنتاجي» لتفعيله."   } }`

404 `not_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 Copy

 `{   "error": {     "code": "not_found",     "message": "غير موجود، أو لا تملك صلاحية الوصول إليه."   } }`

A path that matches no endpoint Copy

 `{   "error": {     "code": "unknown_endpoint",     "message": "لا يوجد endpoint يطابق GET /api/v1/projcts. راجع المسار في توثيق الـ API."   } }`

409 `default`

A uniqueness/record conflict; retry.

default Copy

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

422 `default`

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

default Copy

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

429 `rate_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) Copy

 `{   "error": {     "code": "rate_limit_exceeded",     "message": "استهلكت رصيد اليوم من طلبات API في خطة «المتطور» (1000 طلب يوميًا). يتجدد الرصيد عند منتصف الليل بتوقيت Asia/Riyadh."   } }`

Over 300 requests in a minute (Rack::Attack body, flat error) Copy

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

[Errors](https://fareeqy.com/api/v1/docs/en#errors)

[Previous Events](https://fareeqy.com/api/v1/docs/events/en) [Next Members](https://fareeqy.com/api/v1/docs/members/en)
