---
title: "Files | Fareeqy API"
description: "Project files and external links. Numeric ids; the flat delete address takes a fil- ref. The Files endpoints in the Fareeqy REST API: parameters"
url: https://fareeqy.com/api/v1/docs/files/en
language: en
---

# Files

Project files and external links. Numeric ids; the flat delete address takes a fil- ref.

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

Contents

On this page

-   The resource
-   List one level of a project's file browser
-   Upload a file from inline content
-   Add an external link
-   Delete a file
-   Delete a file by ref

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 one level of a project's file browser
-   Upload a file from inline content
-   Add an external link
-   Delete a file
-   Delete a file by ref

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` integer

Numeric id (files have no slug).

`url` string | null

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

`name` string

`path` string

The folder path the file lives at.

`folder_id` integer | null

`content_type` string | null

`size_bytes` integer | null

`size_human` string | null

`external_url` string | null

Set for an external link, null for an upload.

`source` string | null

The source's display name.

`scan_state` string

Virus-scan state (e.g. pending, clean).

`downloadable` boolean

True once the scan has cleared the file.

`uploaded_by` string | null

`created_at` string (date-time)

ProjectFile Copy

 `{   "id": 108,   "url": "https://app.fareeqy.com/files/fil-3qd8n",   "name": "الهوية-البصرية.pdf",   "path": "التصاميم/الهوية-البصرية.pdf",   "folder_id": 42,   "content_type": "application/pdf",   "size_bytes": 2418176,   "size_human": "2.31 م.بايت",   "external_url": null,   "source": null,   "scan_state": "clean",   "downloadable": true,   "uploaded_by": "سارة العتيبي",   "created_at": "2026-07-10T16:31:44.000+03:00" }`

### List one level of a project's file browser

GET /projects/ {project\_id} /files Requires `files:read`

The folders and files directly inside `folder_id` (or the project root). Not recursive — walk down by passing a subfolder's id back. Files are paginated; folders are not.

#### Path parameters

`project_id` string required

The project REF, or its slug.

#### Query parameters

`folder_id` integer

The folder to list inside; omit for the project root.

`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/prj-8f3kd/files" \   -H "Authorization: Bearer $FAREEQY_API_KEY"`

#### Response

200 Copy

 `{   "data": {     "folder": {       "id": 42,       "url": "https://app.fareeqy.com/projects/prj-8f3kd/files?folder_id=42",       "name": "التصاميم",       "path": "التصاميم",       "description": "ملفات الهوية وواجهات الموقع.",       "parent_folder_id": null,       "created_at": "2026-07-05T08:20:00.000+03:00"     },     "folders": [       {         "id": 51,         "url": "https://app.fareeqy.com/projects/prj-8f3kd/files?folder_id=51",         "name": "الأيقونات",         "path": "التصاميم/الأيقونات",         "description": null,         "parent_folder_id": 42,         "created_at": "2026-07-06T09:02:14.000+03:00"       }     ],     "files": [       {         "id": 108,         "url": "https://app.fareeqy.com/files/fil-3qd8n",         "name": "الهوية-البصرية.pdf",         "path": "التصاميم/الهوية-البصرية.pdf",         "folder_id": 42,         "content_type": "application/pdf",         "size_bytes": 2418176,         "size_human": "2.31 م.بايت",         "external_url": null,         "source": null,         "scan_state": "clean",         "downloadable": true,         "uploaded_by": "سارة العتيبي",         "created_at": "2026-07-10T16:31:44.000+03:00"       },       {         "id": 131,         "url": "https://app.fareeqy.com/files/fil-7mk2w",         "name": "واجهات الصفحة الرئيسية",         "path": "التصاميم/واجهات الصفحة الرئيسية",         "folder_id": 42,         "content_type": null,         "size_bytes": null,         "size_human": null,         "external_url": "https://www.figma.com/design/9aZq/home-v3",         "source": "Figma",         "scan_state": "skipped",         "downloadable": true,         "uploaded_by": "سارة العتيبي",         "created_at": "2026-07-12T11:04:20.000+03:00"       },       {         "id": 147,         "url": "https://app.fareeqy.com/files/fil-2bz6r",         "name": "لقطة-الصفحة-الرئيسية.png",         "path": "التصاميم/لقطة-الصفحة-الرئيسية.png",         "folder_id": 42,         "content_type": "image/png",         "size_bytes": 884736,         "size_human": "864 ك.بايت",         "external_url": null,         "source": null,         "scan_state": "clean",         "downloadable": true,         "uploaded_by": "عبدالله المطيري",         "created_at": "2026-07-14T10:22:07.000+03:00"       },       {         "id": 152,         "url": "https://app.fareeqy.com/files/fil-9pd4h",         "name": "عرض-التدفق-الجديد.mp4",         "path": "التصاميم/عرض-التدفق-الجديد.mp4",         "folder_id": 42,         "content_type": "video/mp4",         "size_bytes": 41943040,         "size_human": "40 م.بايت",         "external_url": null,         "source": null,         "scan_state": "pending",         "downloadable": false,         "uploaded_by": "نورة الحربي",         "created_at": "2026-07-15T13:47:58.000+03:00"       }     ]   },   "meta": {     "total": 4,     "limit": 50,     "offset": 0   } }`

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)

### Upload a file from inline content

POST /projects/ {project\_id} /files Requires `files:write`

Uploads a file from inline `content` (UTF-8 text) OR `content_base64` (binary, standard base64, no line breaks) — exactly one, not both. Capped at 5 MB decoded. A freshly uploaded file is `pending` (not downloadable) until the virus scan clears it. **\`content\` and the file name have to agree.** The name is a claim about what the bytes are, so `content` is accepted only for a plain-text extension — documents ( `md`, `txt`, `rst`, `tex` ), data and config ( `csv`, `json`, `yml`, `xml`, `toml`, `ini`, `conf`, `env` ), markup and styles ( `html`, `svg`, `css`, `scss` ), source ( `js`, `ts`, `rb`, `py`, `sh`, `sql`, `graphql` ) and the rest of that kind — or a name with no extension at all. A `.pdf` name is the one exception: the `content` is read as markdown and rendered into a real PDF document, capped at 256 KB of markdown because the render holds a request thread for its whole duration. Any other extension is refused with a 422 rather than stored, because text under a container extension such as `.docx` produces a file no viewer can open. Send genuine bytes as `content_base64` instead.

#### Path parameters

`project_id` string required

The project REF, or its slug.

#### Request body

`name` string required

The file name (with extension).

`folder_id` integer | null

Destination folder; omit for the project root.

`content` string | null

UTF-8 text content. Provide this OR content\_base64.

`content_base64` string | null

Base64-encoded bytes. Provide this OR content.

#### Request

cURL Copy

 `curl -X POST "https://app.fareeqy.com/api/v1/projects/prj-8f3kd/files" \   -H "Authorization: Bearer $FAREEQY_API_KEY" \   -H "Content-Type: application/json" \   -d '{"name":"","folder_id":null,"content":null,"content_base64":null}'`

#### Response

201 Copy

 `{   "data": {     "id": 108,     "url": "https://app.fareeqy.com/files/fil-3qd8n",     "name": "الهوية-البصرية.pdf",     "path": "التصاميم/الهوية-البصرية.pdf",     "folder_id": 42,     "content_type": "application/pdf",     "size_bytes": 2418176,     "size_human": "2.31 م.بايت",     "external_url": null,     "source": null,     "scan_state": "clean",     "downloadable": true,     "uploaded_by": "سارة العتيبي",     "created_at": "2026-07-10T16:31:44.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)

### Add an external link

POST /projects/ {project\_id} /files/link Requires `files:write`

Adds an external link (Figma, Drive, Notion...) — no storage, no scan, no size limit. The URL's domain is validated against `source_type`.

#### Path parameters

`project_id` string required

The project REF, or its slug.

#### Request body

`name` string required

`url` string (uri) required

`source_type` string required

The provider an external link points to (its domain is validated).

Values: `notion` `google_drive` `dropbox` `onedrive` `box` `figma` `sketch` `zoho` `other`

`folder_id` integer | null

Destination folder; omit for the project root.

#### Request

cURL Copy

 `curl -X POST "https://app.fareeqy.com/api/v1/projects/prj-8f3kd/files/link" \   -H "Authorization: Bearer $FAREEQY_API_KEY" \   -H "Content-Type: application/json" \   -d '{"name":"","url":"","source_type":"notion","folder_id":null}'`

#### Response

201 Copy

 `{   "data": {     "id": 108,     "url": "https://app.fareeqy.com/files/fil-3qd8n",     "name": "الهوية-البصرية.pdf",     "path": "التصاميم/الهوية-البصرية.pdf",     "folder_id": 42,     "content_type": "application/pdf",     "size_bytes": 2418176,     "size_human": "2.31 م.بايت",     "external_url": null,     "source": null,     "scan_state": "clean",     "downloadable": true,     "uploaded_by": "سارة العتيبي",     "created_at": "2026-07-10T16:31:44.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 file

DELETE /projects/ {project\_id} /files/ {id} Requires `files:destructive`

Permanent.

#### Path parameters

`project_id` string required

The project REF, or its slug.

`id` string required

The file's REF (fil-8f3kd), or its numeric id. Files never had a slug.

#### Request

cURL Copy

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

#### Response

200 Copy

 `{   "data": {     "deleted": true,     "file": {       "id": 108,       "name": "الهوية-البصرية.pdf"     }   } }`

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)

### Delete a file by ref

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

Permanent. There is no flat `get` or `patch`: a file's listing hangs off its project (and folder), and a file has no update on this surface, so deleting it is the only thing its own address is for.

#### Path parameters

`id` string required

The file REF (fil-3qd8n). A numeric id is not accepted here.

#### Request

cURL Copy

 `curl -X DELETE "https://app.fareeqy.com/api/v1/files/fil-3qd8n" \   -H "Authorization: Bearer $FAREEQY_API_KEY"`

#### Response

200 Copy

 `{   "data": {     "deleted": true,     "file": {       "id": 41,       "name": "عقد-الموردين.pdf"     }   } }`

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)

[Previous Discussions](https://fareeqy.com/api/v1/docs/discussions/en) [Next Folders](https://fareeqy.com/api/v1/docs/folders/en)
