# Request Access Through a Dead Share Link

Asks a chat's owner to let the caller back in after the share link they were given stopped working. Call it with the slug of a link that answered [Get Shared Thread](/api-reference/shared-threads/get-shared-thread#when-a-link-stops-working) with `422` `share_revoked` or `share_expired` and `details.can_request_access: true`.

The first call files one request and notifies the owner with a `thread.access_requested` notification. A repeat call while that request is still pending returns `200` with the same `id` and notifies nobody again, so a double-press is harmless.

The owner answers from [List Access Requests](/api-reference/threads/list-access-requests):

- [Grant](/api-reference/threads/grant-access-request) creates a new `explicit` share link naming only the caller. The caller receives the usual `thread.shared` notification carrying the new link.
- [Dismiss](/api-reference/threads/dismiss-access-request) closes the request. The caller is not notified, and may not ask again for 24 hours.


Sharing the chat with the caller again through [Create Share Link](/api-reference/threads/create-share-link) also answers the request as `granted`.

The request's current state is returned as `details.access_request` whenever the dead link is opened again, so the dead-link screen can show "Request sent" without a separate lookup.

## Authentication

Requires **user** authentication (Bearer token). API-key authentication is rejected with `403`. A share link names people, and an API key is never a person.

## Path Parameters

**`slug`** string required

The slug of the share link that stopped working.

## Body Parameters

The body is optional. Send no body, or send `{}`.

**`message`** string | null optional

A note to the owner, up to 1000 characters. A longer note is refused with `422`; it is never shortened. The owner's notification quotes the first 200 characters.

## Returns

`201 Created` when this call filed the request. `200 OK` when a pending request already existed. Both return the same shape:

- **id** `string`: the access request ID (`tsar_…`).
- **status** `string`: `pending`, `granted` or `dismissed`. A new request is always `pending`.
- **created_at** `string`: when the request was filed (ISO 8601 UTC).
- **decided_at** `string | null`: when it was granted or dismissed. `null` while pending.
- **retry_after** `integer | null`: seconds until the caller may ask again. Set only on a `dismissed` request whose 24-hour cooldown is still running.
- **created** `boolean`: `true` with `201`, `false` with `200`.


## The owner's notification

The chat's owner receives one notification per request:

| Field | Value |
|  --- | --- |
| `event_type` | `thread.access_requested` |
| `title` | `{requester} asked for access to “{chat title}”` |
| `body` | `Their share link no longer works. Grant access to send {requester} a new link.` If the requester left a note, `They wrote: “…”` is appended. |
| `link` | `null`. Open the chat from `payload.thread_id`. |
| `actor_user_id` | The requester. |


`payload`:

- **request_id** `string`: pass it to [Grant](/api-reference/threads/grant-access-request) or [Dismiss](/api-reference/threads/dismiss-access-request).
- **thread_id** `string`: the chat.
- **thread_title** `string | null`
- **link_id** `string | null`: the dead link the requester asked through.
- **access_level** `string | null`: that link's level (`view`, `fork` or `live`). A grant reuses it by default.
- **requester_user_id** `string`
- **requester_name** `string | null`: a display name, never an email address.
- **message** `string | null`: the requester's note, at most 200 characters.


The notification is resolved (moved to `responded`) as soon as the request is granted or dismissed by anyone with edit access, or answered by a re-share, so it never lingers as an open action.

## Code Examples

### cURL


```bash
curl -X POST https://api.aitronos.com/v1/shared-threads/abc123slug/access-requests \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"message": "I was reviewing this for the board meeting."}'
```

### Python (requests)


```python
import requests

response = requests.post(
    "https://api.aitronos.com/v1/shared-threads/abc123slug/access-requests",
    headers={"Authorization": "Bearer YOUR_TOKEN"},
    json={"message": "I was reviewing this for the board meeting."},
)
print(response.status_code, response.json())  # 201 on the first press, 200 after
```

### JavaScript


```javascript
const response = await fetch(
  "https://api.aitronos.com/v1/shared-threads/abc123slug/access-requests",
  {
    method: "POST",
    headers: {
      Authorization: "Bearer YOUR_TOKEN",
      "Content-Type": "application/json",
    },
    body: JSON.stringify({ message: "I was reviewing this for the board meeting." }),
  },
);
const request = await response.json();
```

## Response Examples

### Filed (201)


```json
{
  "id": "tsar_5b1f0c2d9e8a4b7c9d6e5f4a3b2c1d0e",
  "status": "pending",
  "created_at": "2026-09-30T17:48:02Z",
  "decided_at": null,
  "retry_after": null,
  "created": true
}
```

### Already pending (200)

The same request, with `created: false`. Nobody is notified again.


```json
{
  "id": "tsar_5b1f0c2d9e8a4b7c9d6e5f4a3b2c1d0e",
  "status": "pending",
  "created_at": "2026-09-30T17:48:02Z",
  "decided_at": null,
  "retry_after": null,
  "created": false
}
```

### Error: not found (404)

This is the uniform body the share resolver uses. It is returned for every caller the link was not given to: an unknown slug, a member who was never granted an `explicit` link, and a former member of the organization. It is also returned for a chat that was deleted. It never reveals whether the slug exists.


```json
{
  "success": false,
  "error": {
    "code": "RESOURCE_NOT_FOUND",
    "message": "The requested resource could not be found.",
    "system_message": "Share link not found",
    "type": "client_error",
    "status": 404,
    "details": {},
    "trace_id": "...",
    "timestamp": "..."
  }
}
```

### Error: asking would change nothing (409)

`THREAD_ACCESS_REQUEST_NOT_NEEDED`. `details.reason` is one of:

- `link_active`: the link works again.
- `caller_is_owner`: the caller owns the chat.
- `has_other_access`: another share link or a space still opens the chat for the caller.


`details.thread_id` is included with `caller_is_owner` and `has_other_access`, because the caller can already open the chat.


```json
{
  "success": false,
  "error": {
    "code": "THREAD_ACCESS_REQUEST_NOT_NEEDED",
    "message": "You can already open this chat, so there is nothing to ask for.",
    "system_message": "The caller can already open this chat",
    "type": "client_error",
    "status": 409,
    "details": { "reason": "has_other_access", "thread_id": "thread_8f3c" },
    "trace_id": "...",
    "timestamp": "..."
  }
}
```

### Error: the owner can no longer be asked (409)

`THREAD_ACCESS_REQUEST_OWNER_UNAVAILABLE`. The owner's account is deactivated, or the owner left the organization.


```json
{
  "success": false,
  "error": {
    "code": "THREAD_ACCESS_REQUEST_OWNER_UNAVAILABLE",
    "message": "The owner of this chat can no longer be asked for access.",
    "system_message": "The chat's owner can no longer be asked for access",
    "type": "client_error",
    "status": 409,
    "details": { "reason": "owner_inactive" },
    "trace_id": "...",
    "timestamp": "..."
  }
}
```

### Error: dismissed recently (429)

`THREAD_ACCESS_REQUEST_COOLDOWN`. The caller's last request for this chat was dismissed less than 24 hours ago. `details.retry_after` is in seconds and is rounded up.


```json
{
  "success": false,
  "error": {
    "code": "THREAD_ACCESS_REQUEST_COOLDOWN",
    "message": "Your last request for this chat was dismissed. You can ask again later.",
    "system_message": "A dismissed access request may not be re-filed yet",
    "type": "client_error",
    "status": 429,
    "details": { "retry_after": 86217 },
    "trace_id": "...",
    "timestamp": "..."
  }
}
```

### Error: rate limited (429)

`RATE_LIMIT_EXCEEDED`. The caller made more than 10 requests to this route within 60 seconds, across all slugs.


```json
{
  "success": false,
  "error": {
    "code": "RATE_LIMIT_EXCEEDED",
    "message": "...",
    "system_message": "Rate limit exceeded",
    "type": "client_error",
    "status": 429,
    "details": { "limit": 10, "window_seconds": 60, "retry_after": 41 },
    "trace_id": "...",
    "timestamp": "..."
  }
}
```

## Related Resources

- [Get Shared Thread](/api-reference/shared-threads/get-shared-thread#when-a-link-stops-working): the dead-link reasons and `details.access_request`
- [List Access Requests](/api-reference/threads/list-access-requests): the owner's view
- [Grant Access Request](/api-reference/threads/grant-access-request)
- [Dismiss Access Request](/api-reference/threads/dismiss-access-request)