# Shared Thread Tool Approval

Approve or deny a tool call (or a compose-email card) that is waiting for confirmation on a **live-shared** thread you **joined** — the slug-scoped twin of the owner tool-approval endpoint, for a joiner co-working on someone else's thread.

When an assistant parks a tool that needs confirmation, it emits a `tool.approval_required` event on the live stream. A joiner co-working live can submit the decision through this endpoint. The decision releases the **same parked turn** the owner's approval would — both the owner route and this slug-scoped route key on the same underlying thread — so whichever participant confirms first unblocks the run.

Authorized by the joiner's **live**-share grant on the slug. A `view` or `fork` slug returns `403`; an unknown or unauthorized link returns `404`; a `tool_call_id` with no matching pending approval returns `404`.

## Authentication

Requires **user** authentication (Bearer token).

## Path Parameters

**`slug`** string required

The share-link slug, from the share URL. The link must be a `live` link.

## Body Parameters

**`tool_call_id`** string required

The `tool_call_id` from the `tool.approval_required` stream event.

**`approved`** boolean required

`true` to approve, `false` to deny.

**`arguments`** object optional

Edited payload, present only when approving an edit-and-confirm card (e.g. a compose_email Send): `selected_option_id`, `body`, `is_html`, `subject`, `from_identity_id`, `to`/`cc`/`bcc`. Omitted for a plain approval.

**`retry`** boolean optional

Set (with `approved: true`) to explicitly re-send a compose card whose previous send failed. Defaults to `false`.

**`batch`** object optional

Batch-level payload for a compose_email_batch card: `action` (`send_all` | `send_selected` | `discard_all`), `selected_email_ids`, `per_email_overrides`. Mutually exclusive with single-email `arguments`.

## Returns

- **tool_call_id** `string` — the tool call that was approved/denied.
- **approved** `boolean` — the decision recorded.
- **status** `string` — processing status (e.g. `decision_recorded`, or the compose send outcome).
- **version** `integer | null` — the compose-state version AFTER this decision resolved, when known. Every send attempt advances the version server-side (a **failed** send too), so adopt it for your next compose-state `PATCH` instead of reusing the pre-send one (which would return `409 VERSION_CONFLICT`). Populated on the offline compose path (`sent` / `failed` / `denied` / `already_sent` / `expired` / `error`); `null` for non-compose approvals and for live decisions (`decision_recorded`), where the version arrives on the `compose_email_status` stream block instead.


## Code Examples

### cURL


```bash
curl -X POST "https://api.aitronos.com/v1/shared-threads/abc123slug/tool-approval" \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"tool_call_id": "tc_1", "approved": true}'
```

### Python SDK


```python
from aitronos import Aitronos

client = Aitronos(api_key="", token="YOUR_TOKEN")
result = client.threads.shared.tool_approval(
    slug="abc123slug", tool_call_id="tc_1", approved=True
)
print(result.status)
```

### Python (requests)


```python
import requests

response = requests.post(
    "https://api.aitronos.com/v1/shared-threads/abc123slug/tool-approval",
    headers={"Authorization": "Bearer YOUR_TOKEN"},
    json={"tool_call_id": "tc_1", "approved": True},
)
print(response.json()["status"])
```

### JavaScript


```javascript
const response = await fetch(
  "https://api.aitronos.com/v1/shared-threads/abc123slug/tool-approval",
  {
    method: "POST",
    headers: {
      Authorization: "Bearer YOUR_TOKEN",
      "Content-Type": "application/json",
    },
    body: JSON.stringify({ tool_call_id: "tc_1", approved: true }),
  },
);
const result = await response.json();
console.log(result.status);
```

## Response Examples

### Success (200)


```json
{
  "tool_call_id": "tc_1",
  "approved": true,
  "status": "decision_recorded",
  "version": null
}
```

### Error — Not a live link (403)


```json
{
  "success": false,
  "error": {
    "code": "INSUFFICIENT_PERMISSIONS",
    "message": "You do not have permission to perform this action.",
    "system_message": "This share link does not grant live co-working access",
    "type": "authorization_error",
    "status": 403,
    "details": { "link_id": "tslnk_...", "access_level": "view" },
    "trace_id": "...",
    "timestamp": "..."
  }
}
```

### Error — No pending approval (404)


```json
{
  "success": false,
  "error": {
    "code": "RESOURCE_NOT_FOUND",
    "message": "The requested resource could not be found.",
    "system_message": "No pending tool approval for this thread",
    "type": "client_error",
    "status": 404,
    "details": { "thread_id": "thread_...", "tool_call_id": "tc_1" },
    "trace_id": "...",
    "timestamp": "..."
  }
}
```

## Related Resources

- [Join Shared Thread](/api-reference/shared-threads/join-shared-thread) — Join the live-shared thread first
- [Shared Thread Compose State](/api-reference/shared-threads/shared-thread-compose-state) — Edit the compose card before approving its Send
- [Shared Thread Reactions](/api-reference/shared-threads/shared-thread-reactions) — React to messages as a joiner
- [Live Shared Thread](/api-reference/shared-threads/live-shared-thread) — The real-time stream that emits `tool.approval_required`