# removePropertiesFromList

Remove properties from ONE list (`listId` from searchPropertyTags or getProperty's `lists`). ASYNC bulk-task op: poll getBulkTask(bulkTaskId). Same selection rules as addPropertiesToList: EXPLICIT `propertyIds` + `totalCount`, or FILTER-BACKED `filterId` / `filterTree` (strict) with `selectAll: true` or `selectCount: N` for the first N in DEFAULT traversal order, never a previewed `sort`: use `propertyIds` for a sorted top-N (one window, not both; neither is REFUSED), `excludeIds` on the filter-backed form only. `totalCount` is an EXECUTION CAP, derived server-side for explicit ids and `selectCount` and trusted only for select-all: the filter's `total` from filterProperties UNSUBTRACTED; understated means the removal stops early, so round up. Not on the list is skipped, not an error. Removes MEMBERSHIP only: list and properties survive. A filter-backed selection can touch thousands of properties in one call: state the match count to the user and get a go-ahead BEFORE submitting one.

- Call: `POST https://server.goliathdata.com/api/v1/call` with `{ "operationId": "removePropertiesFromList", "variables": {...} }`
- Scope: `WRITE`
- Type: mutation
- Idempotency: honors `Idempotency-Key` (24 h)
- Rate-limited: no

## Variables

- `propertyIds`: `[String!]`
- `filterId`: `ID`
- `filterTree`: `JSON`
- `selectAll`: `Boolean` (default `false`)
- `selectCount`: `Int`
- `excludeIds`: `[String!]`
- `includeIncompleteRecords`: `Boolean`
- `listId`: `String!` (required)
- `totalCount`: `Int!` (required)

## Response (data, an example)

```json
{
  "propertyMutation": {
    "removePropertiesFromList": {
      "mode": "SYNC",
      "bulkTaskId": "…"
    }
  }
}
```

## Example

```bash
curl https://server.goliathdata.com/api/v1/call \
  -H "Authorization: Bearer $GOLIATH_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
    "operationId": "removePropertiesFromList",
    "variables": {
      "listId": "<String>",
      "totalCount": 10
    }
  }'
```
