> ## Documentation Index
> Fetch the complete documentation index at: https://docs.filexpress.app/llms.txt
> Use this file to discover all available pages before exploring further.

# Projects

> Query projects with their financial summary, create them and link documents to them

| Permission | Endpoints |
| - | - |
| `projects` | `GET /projects`, `GET /projects/{id}` |
| `projects.write` | `POST /projects`, `PUT /projects/{id}`, `POST /projects/{id}/items` |

> [!NOTE]
>
> These are **explicit** permissions: you must select them one by one in **External integrations**; existing integrations do not receive them automatically.

**Project statuses** (`status`):

| Value | Meaning |
| - | - |
| `planned` | Planned |
| `in_progress` | In progress |
| `on_hold` | On hold |
| `completed` | Completed |
| `cancelled` | Cancelled |

## Project object

```json theme={null}
{
  "id": "9e01...",
  "name": "Remodelación oficinas Grupo Alfa",
  "status": "in_progress",
  "customer": { "id": "9c77...", "name": "Grupo Alfa, S.A. de C.V." },
  "branch_id": "9d1c5a3e-...",
  "start_date": "2026-09-01",
  "end_date": "2026-12-15",
  "budget": 25000.0,
  "description": "Obra civil y mobiliario",
  "quotation_id": null,
  "created_at": "2026-08-28T09:30:00-06:00"
}
```

`customer.name` is the customer's legal name or, if it has none, its trade name.

## List projects

```http theme={null}
GET /projects?status=in_progress
```

| Parameter | Type | Required | Description |
| - | - | - | - |
| `status` | string | No | One of the statuses. |
| `customer_id` | string | No | Filters by customer. |
| `search` | string | No | Searches the name (max. 100). |
| `per_page` | integer | No | 1 to 200 (default 50). |

Returns `data` (project objects, most recent by start date first) and `pagination`. It does not include deleted projects.

## Get project

```http theme={null}
GET /projects/{id}
```

Returns the project object plus its financial summary in `summary`:

```json theme={null}
{
  "status": true,
  "data": {
    "id": "9e01...",
    "name": "Remodelación oficinas Grupo Alfa",
    "status": "in_progress",
    "...": "...",
    "summary": {
      "total_sales": 18000.0,
      "total_expenses": 9500.0,
      "total_payroll": 3200.0,
      "total_work_orders": 800.0,
      "total_costs": 13500.0,
      "profit": 4500.0,
      "margin_percent": 25.0,
      "budget": 25000.0,
      "budget_used_percent": 54.0,
      "counts": { "sales": 3, "expenses": 12, "payrolls": 2, "work_orders": 1 }
    }
  }
}
```

| Field | Calculation |
| - | - |
| `total_sales` | Total to pay of linked sales that are **processed** and not voided, from the business's environment. |
| `total_expenses` | Total to pay of linked purchases that are not voided or deleted, from the business's environment. |
| `total_payroll` | Total of linked payrolls that are not deleted. |
| `total_work_orders` | Total of the project's work orders. |
| `total_costs` | `total_expenses + total_payroll + total_work_orders`. |
| `profit` | `total_sales − total_costs`. |
| `margin_percent` | `profit / total_sales × 100`; `null` if there are no sales. |
| `budget_used_percent` | `total_costs / budget × 100`; `null` if the project has no budget. |
| `counts` | Number of sales, purchases, payrolls and work orders considered. |

**Errors**: `404` `Project not found` (nonexistent, deleted or belonging to another business).

## Create project

```http theme={null}
POST /projects
```

| Field | Type | Required | Description |
| - | - | - | - |
| `name` | string | Yes | Name (max. 255). |
| `customer_id` | string | Yes | Customer of a branch of the business. |
| `start_date` | date | Yes | `YYYY-MM-DD`. |
| `status` | string | Yes | One of the statuses. |
| `branch_id` | string | No | Branch of the business. |
| `end_date` | date | No | `YYYY-MM-DD`. |
| `budget` | number | No | Budget (≥ 0). Used for `budget_used_percent`. |
| `description` | string | No | Max. 2000 characters. |

```bash theme={null}
curl -X POST https://api.filexpress.app/api/external/v1/projects \
  -H "X-API-Key: fx_xxxxxxxx" \
  -H "Idempotency-Key: proyecto-PRJ-2026-014" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Remodelación oficinas Grupo Alfa",
    "customer_id": "9c77...",
    "start_date": "2026-09-01",
    "end_date": "2026-12-15",
    "budget": 25000,
    "status": "planned"
  }'
```

**`201` response**: the project object. Accepts [`Idempotency-Key`](https://docs.filexpress.app/en/docs/api/introduccion#idempotency).

**Errors**

| Code | Cause |
| - | - |
| `422` | Validation, `Branch not found` or `Customer not found` (belonging to another business or nonexistent). |
| `409` | `Idempotency-Key` conflict. |

## Update project

```http theme={null}
PUT /projects/{id}
```

Same fields as creation, all optional: only the ones sent are modified. Responds `200` with the updated object.

**Errors**: `404` `Project not found`; `422` validation, `Branch not found` or `Customer not found`.

## Link documents

```http theme={null}
POST /projects/{id}/items
```

Assigns sales, purchases or payrolls to the project so they count in its summary. If a document was already in another project, it moves to this one.

| Field | Type | Required | Description |
| - | - | - | - |
| `type` | string | Yes | `sale`, `expense` or `payroll`. |
| `ids` | array | Yes | 1 to 500 IDs of the indicated type. |

```json theme={null}
{
  "type": "sale",
  "ids": ["9a10...", "9a11...", "id-de-otro-negocio"]
}
```

**`200` response**

```json theme={null}
{
  "status": true,
  "data": {
    "linked": 2,
    "rejected_ids": ["id-de-otro-negocio"],
    "summary": { "total_sales": 18000.0, "...": "..." }
  }
}
```

Only documents from the same business are linked. Nonexistent IDs or IDs from another business do not cause an error: they are returned in `rejected_ids`. `summary` is the financial summary, already recalculated.

**Errors**: `404` `Project not found`; `422` validation.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.