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

# Bulk Delete Workforce Employees by Filters

> Delete every own workforce employee matching a set of filters, guarded by the hash of the list you saw

[← Own Workforce API](/api-reference/own-workforce/overview)

Delete every employee matching a filter set, without collecting their ids first. The filters go in the **query string** — the same ones [List Workforce Employees](/api-reference/own-workforce/list) accepts — and the body carries the `filter_hash` that list returned.

<Warning>
  Irreversible, and it cascades to contracts, remunerations, trainings and absence records. Always run the equivalent list call first and read `total` before deleting.
</Warning>

## The filter\_hash guard

`filter_hash` fingerprints the filters that produced a page — including `consolidate_group`, `organization_id[]` and the project scope. Send it back and the server recomputes the fingerprint from the filters on *this* request:

* they match → the delete proceeds over exactly the set you listed;
* they differ → `409 Conflict`, and nothing is deleted.

That is what stops a client from listing one subsidiary, then widening the perimeter and deleting the whole group by accident. It guards against that drift, not against a caller who deliberately sends different filters — the tenant boundary is the organization scoping, not the hash. Take the hash verbatim from the list response.

No filter is required. With none, the delete covers every row of the perimeter the list showed: the header organization, or under `consolidate_group` the accepted family narrowed by `organization_id[]` (and the project scope, when it is on). The delete removes exactly the rows the list returns: an employee with no contract is not listed, so it is never deleted here either. Read `total` from the list before you delete.

## Request

### Headers

<ParamField header="x-api-key" type="string" required>
  Your API key for authentication

  **Example:** `sk_live_1234567890abcdef`
</ParamField>

<ParamField header="x-organization-id" type="string" required>
  Your organization UUID

  **Example:** `a8315ef3-dd50-43f8-b7ce-d839e68d51fa`
</ParamField>

### Query Parameters

The same filters as the list endpoint. All of them are optional.

<ParamField query="external_employee_id" type="string">
  Search by the employee identifier your HR system uses
</ParamField>

<ParamField query="file_id[]" type="array[string]">
  Filter by source upload file. The nil UUID matches rows with no file.
</ParamField>

<ParamField query="created_at_from" type="datetime">
  Only rows created at or after this instant
</ParamField>

<ParamField query="created_at_to" type="datetime">
  Only rows created at or before this instant
</ParamField>

<ParamField query="consolidate_group" type="boolean" default="false">
  Widen the perimeter to the accepted business family. Part of the hash.
</ParamField>

<ParamField query="organization_id[]" type="array[string]">
  Narrow a group-view delete to these organizations. Part of the hash.
</ParamField>

### Body

<ParamField body="filter_hash" type="string" required>
  The `filter_hash` from the list response that showed you these rows
</ParamField>

## Response

Same shape as [Bulk Delete Workforce Employees](/api-reference/own-workforce/bulk-delete): `success_count`, `success_ids`, `failed_count`, `failed_ids` and `message`.

## Example

<CodeGroup>
  ```bash cURL theme={"theme":{"light":"github-light","dark":"github-dark"}}
  curl -X POST "https://api.dcycle.io/v1/own_workforces/bulk-delete-by-filters?file_id[]=9f1c7f2a-64a1-4b2c-9d3e-70a5b8c1d2e3" \
    -H "x-api-key: ${DCYCLE_API_KEY}" \
    -H "x-organization-id: ${DCYCLE_ORG_ID}" \
    -H "Content-Type: application/json" \
    -d '{"filter_hash": "b6d1f0c47a9e2d38"}'
  ```

  ```python Python theme={"theme":{"light":"github-light","dark":"github-dark"}}
  import os

  import requests

  headers = {
      "x-api-key": os.getenv("DCYCLE_API_KEY"),
      "x-organization-id": os.getenv("DCYCLE_ORG_ID"),
  }

  filters = {"file_id[]": "9f1c7f2a-64a1-4b2c-9d3e-70a5b8c1d2e3"}

  # 1. List first: you need the hash, and you should see the count before deleting.
  listed = requests.get(
      "https://api.dcycle.io/v1/own_workforces",
      headers=headers,
      params=filters,
  ).json()
  print(f"about to delete {listed['total']} employees")

  # 2. Delete exactly that set.
  response = requests.post(
      "https://api.dcycle.io/v1/own_workforces/bulk-delete-by-filters",
      headers=headers,
      params=filters,
      json={"filter_hash": listed["filter_hash"]},
  )

  print(response.json()["message"])
  ```

  ```javascript JavaScript theme={"theme":{"light":"github-light","dark":"github-dark"}}
  const axios = require('axios');

  const headers = {
    'x-api-key': process.env.DCYCLE_API_KEY,
    'x-organization-id': process.env.DCYCLE_ORG_ID
  };

  const params = { 'file_id[]': '9f1c7f2a-64a1-4b2c-9d3e-70a5b8c1d2e3' };

  axios.get('https://api.dcycle.io/v1/own_workforces', { headers, params })
    .then(listed => {
      console.log(`about to delete ${listed.data.total} employees`);
      return axios.post(
        'https://api.dcycle.io/v1/own_workforces/bulk-delete-by-filters',
        { filter_hash: listed.data.filter_hash },
        { headers, params }
      );
    })
    .then(response => console.log(response.data.message))
    .catch(error => console.error(error));
  ```
</CodeGroup>

### Successful Response

```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
{
  "success_count": 145,
  "success_ids": [
    "… 145 ids in total, abridged here …",
    "550e8400-e29b-41d4-a716-446655440000"],
  "failed_count": 0,
  "failed_ids": [],
  "message": "Deleted 145 own workforce records"
}
```

## Common Errors

### 401 Unauthorized

**Cause:** the key is invalid, or it does not belong to the organization in `x-organization-id` — the two are looked up as a pair. A request carrying no credentials at all answers `AUTH_REQUIRED` instead.

```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
{
  "detail": "Invalid API key for organization",
  "code": "INVALID_API_KEY"
}
```

### 403 Forbidden

**Cause:** the key's owner is not an enabled member of the organization, or their role cannot write.

```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
{
  "detail": "Logged User is not Member of Organization",
  "code": "LOGGED_USER_NOT_MEMBER"
}
```

### 409 Conflict

**Cause:** `filter_hash` does not match the filters on this request. Nothing was deleted. Re-list with the filters you intend, then retry with the fresh hash.

```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
{
  "detail": "Filter hash mismatch. The filters have changed since the list was loaded. Please refresh and try again."
}
```

## Related Endpoints

<CardGroup cols={2}>
  <Card title="List employees" icon="users" href="/api-reference/own-workforce/list">
    Where `filter_hash` comes from
  </Card>

  <Card title="Bulk delete by ids" icon="trash" href="/api-reference/own-workforce/bulk-delete">
    When you already hold the ids
  </Card>
</CardGroup>


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