---
title: "Unified workspace search"
method: GET
path: "/search"
tags: ["Account"]
---

# Unified workspace search

`GET /search`

## Request

- Base URL: `https://app.fareeqy.com/api/v1`
- URL: `https://app.fareeqy.com/api/v1/search`
- Auth: HTTP bearer

Finds projects, task lists, tasks, folders, files and majlis topics by name
(Arabic-normalized, within the key's company). Returns the refs and ids the
other endpoints take. Each kind is capped independently (`per_type`);
`truncated` names every kind that had more matches than were returned.
`widened` names every kind where no record carried every word of the query,
so its hits are near-misses: check one before acting on it. A blank `q`
returns empty results. Requires operation `account:read`.

## Query parameters

- `q` string
- `types` string[]
- `per_type` integer

## Response `200`

Search results.

- object
  - `data` object
    - `query` string
    - `results` SearchResult[]
      - union: A unified search hit. The shape depends on `type`; each carries the refs/ids the other endpoints take, and a `url`.
        - SearchProject
          - `type` 'project', required
          - `id` string: The project ref.
          - `url` string, nullable: Absolute address of the page a person opens in فريقي.
          - `title` string
          - `project_slug` string: The project ref. Named _slug for compatibility.
          - `archived` boolean
        - SearchTaskList
          - `type` 'task_list', required
          - `id` string: The task-list ref.
          - `url` string, nullable: Absolute address of the page a person opens in فريقي.
          - `title` string
          - `project_slug` string: The project ref. Named _slug for compatibility.
          - `task_list_slug` string: The task-list ref. Named _slug for compatibility.
          - `completed` boolean
        - SearchTask
          - `type` 'task', required
          - `id` string: The task ref.
          - `url` string, nullable: Absolute address of the page a person opens in فريقي.
          - `title` string
          - `project_slug` string: The project ref. Named _slug for compatibility.
          - `task_list_slug` string: The task-list ref. Named _slug for compatibility.
          - `task_slug` string: The task ref. Named _slug for compatibility.
          - `completed` boolean
        - SearchFolder
          - `type` 'folder', required
          - `url` string, nullable: The project's files page scoped to this folder.
          - `name` string
          - `project_slug` string: The project ref. Named _slug for compatibility.
          - `folder_id` integer
        - SearchFile
          - `type` 'file', required
          - `id` string: The file ref.
          - `url` string, nullable: Absolute address of the page a person opens in فريقي.
          - `name` string
          - `project_slug` string: The project ref. Named _slug for compatibility.
          - `file_id` integer
          - `folder_id` integer, nullable
        - SearchDiscussion
          - `type` 'discussion', required
          - `id` string: The majlis topic ref.
          - `url` string, nullable: Absolute address of the page a person opens in فريقي.
          - `title` string
          - `project_slug` string: The project ref. Named _slug for compatibility.
          - `discussion_slug` string: The majlis topic ref. Named _slug for compatibility.
    - `truncated` string[]: The kinds that had more matches than were returned.
    - `widened` string[]: The kinds where no record matched every word of the query, so the hits are near-misses. Always present, empty when every kind matched exactly.

## Other responses

- `401`: Missing or invalid API key.
- `403`: 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.
- `404`: 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.
- `429`: 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.

---

[API](https://skmtc.dev/fareeqy/apis/fareeqy-rest-api.md) · [All operations](https://skmtc.dev/fareeqy/apis/fareeqy-rest-api/llms.txt) · [OpenAPI document](https://skmtc.dev/fareeqy/apis/fareeqy-rest-api/revisions/dc964e05e3d2?raw)
