# completeTaskById

Complete a task by taskId ALONE, for tasks with NO contact (listMyTasks contact: null; typically deal tasks). Returns the task. isCompleted: false reopens. It REFUSES a task with a contact (it would skip the timeline entry): use completeTask. A contact-less APPOINTMENT completes too (type says so); no task count includes it. It only completes tasks YOU are on: a non-admin key gets a permission error for someone else's. Confirm with the user first.

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

## Variables

- `taskId`: `ID!` (required)
- `isCompleted`: `Boolean!` (default `true`)

## Response (data, an example)

```json
{
  "tasksMutation": {
    "updateTasksCompletedByIds": [
      {
        "id": "<ID>",
        "title": "…",
        "type": "APPOINTMENT",
        "description": "…",
        "taskType": "…",
        "dueDate": "2026-01-01T00:00:00.000Z",
        "timezone": "IDLW",
        "completedAt": "2026-01-01T00:00:00.000Z",
        "participants": [
          {
            "id": "<ID>",
            "firstName": "…",
            "lastName": "…"
          }
        ]
      }
    ]
  }
}
```

## 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": "completeTaskById",
    "variables": {
      "taskId": "<taskId>"
    }
  }'
```
