# PUT /api/v1/inboxes/:id/threads/:threadId/assignment

Auth: Bearer

HTML: https://cooperemail.com/docs/reference/put-thread-assignment

## Summary

Assign the thread to a handle, or take an exclusive claim. assignee is required, 1–64 characters: letters, digits, and . _ @ + : -. note is optional and at most 500 characters. Omit note to keep the current note. null clears it. lease_seconds is an optional integer from 30 to 86400. When it is set, claimed_until is now plus that many seconds and a different assignee receives HTTP 409 thread_claimed with assignee and claimed_until unless force is true. The same assignee can renew, and a renew does not emit thread.assigned. Without lease_seconds, claimed_until is null and the assignment is not exclusive. Two concurrent claims resolve in one conditional upsert, so exactly one wins. Unknown thread returns 404 thread_not_found. Invalid fields return invalid_assignee, invalid_note, invalid_lease, or invalid_force. Same permission as PATCH thread labels (message_update).

## Request

```json
{
  "assignee": "billing-agent",
  "note": "invoice question",
  "lease_seconds": 300
}
```

## Response

The OpenAPI document does not declare a JSON response schema for this call. The summary is the contract.

## Errors

- HTTP 409 thread_claimed
- HTTP 404 thread_not_found

The live `message` is the sentence for that code. Branch on `code`.

```json
{
  "error": {
    "type": "conflict",
    "code": "thread_claimed",
    "docs_url": "https://cooperemail.com/docs#thread_claimed"
  }
}
```

## Idempotency

This route does not document Idempotency-Key or client_id.
