## Check or cancel an audience request

`GET /v1/infra/servers/:id/audience-proposals/:proposalId`

`POST /v1/infra/servers/:id/audience-proposals/:proposalId/cancel`

Let the original API key read or cancel its own request to change application access. The original operation returns `proposalId` in `error.details.proposalId` with `409 AUDIENCE_APPROVAL_REQUIRED`. Another key belonging to the same owner cannot access the request.

An API key cannot approve a request. A signed-in person makes that decision in their account. `APPROVED` means consent has been given, not that the change has been applied: retry the original operation with the same key, exact parameters and `approvalId`. Cancellation itself does not change access.

## Parameters

| Parameter | In | Type | Required | Description |
|-----------|----|------|:--------:|-------------|
| `id` | path | string (UUID) | yes | Server ID from the original operation; see [List servers](/docs/infra/servers/list) |
| `proposalId` | path | string (UUID) | yes | Request ID from `error.details.proposalId` |

The cancellation body is optional. If provided, it must be an empty object `{}`. The verified `X-Api-Key` identifies the caller; body fields cannot supply an identity.

## Examples

### curl — check

```bash
curl "https://vibecode.bitrix24.com/v1/infra/servers/SERVER_ID/audience-proposals/PROPOSAL_ID"   -H "X-Api-Key: YOUR_API_KEY"
```

### curl — cancel

```bash
curl -X POST "https://vibecode.bitrix24.com/v1/infra/servers/SERVER_ID/audience-proposals/PROPOSAL_ID/cancel"   -H "X-Api-Key: YOUR_API_KEY"
```

### JavaScript — check

```javascript
const response = await fetch(
  `https://vibecode.bitrix24.com/v1/infra/servers/${serverId}/audience-proposals/${proposalId}`,
  { headers: { 'X-Api-Key': apiKey } },
)
const { proposal } = await response.json()
console.log(proposal.state)
```

### JavaScript — cancel

```javascript
const response = await fetch(
  `https://vibecode.bitrix24.com/v1/infra/servers/${serverId}/audience-proposals/${proposalId}/cancel`,
  { method: 'POST', headers: { 'X-Api-Key': apiKey } },
)
const { proposal } = await response.json()
console.log(proposal.state)
```

## Response fields

A successful response is `{ "proposal": ... }`, without a `success` or `data` envelope. The table lists the main fields; the response also includes the exact operation, original, proposed and current access snapshots, participant labels and differences.

| Field | Type | Description |
|-------|------|-------------|
| `proposal.id` | string (UUID) | Request ID |
| `proposal.state` | string | `PENDING`, `APPROVED`, `APPLIED`, `REJECTED`, `CANCELLED`, `EXPIRED` or `STALE` |
| `proposal.baseRevision` | string | Access revision when the request was created; a decimal string |
| `proposal.currentRevision` | string | Current access revision; a decimal string |
| `proposal.expiresAt` | string | Request expiry in ISO 8601 |
| `proposal.canDecide` | boolean | Always `false` for an API key |
| `proposal.canCancel` | boolean | Whether the request can be cancelled now |
| `proposal.resultEntityId` | string (UUID), optional | ID of the record created when applied; not a token or secret URL |

## Response example

Only the ID, state and revisions from the status response are shown below:

```json
{
  "proposal": {
    "id": "00000000-0000-4000-8000-000000000001",
    "state": "PENDING",
    "baseRevision": "0",
    "currentRevision": "0"
  }
}
```

Successful cancellation returns the `CANCELLED` state.

## Error response example

404 — the request does not exist or belongs to another caller:

```json
{
  "success": false,
  "error": { "code": "NOT_FOUND", "message": "Proposal not found" }
}
```

## Errors

| HTTP | Code | Description |
|------|------|-------------|
| 400 | `VALIDATION_ERROR` | Invalid UUID or a nonempty cancellation body |
| 401 | `MISSING_API_KEY` | No key was supplied |
| 401 | `INVALID_API_KEY` | The key was not recognized |
| 403 | `AUDIENCE_APPROVAL_FORBIDDEN` | The current key, its owner or portal binding no longer permits the operation |
| 404 | `NOT_FOUND` | No server or request in the required portal, or the request was created by another caller |
| 409 | `AUDIENCE_APPROVAL_REPLAY` | Cancellation: the request was already applied, cancelled or completed by another decision |
| 409 | `AUDIENCE_APPROVAL_STALE` | Cancellation: the access revision changed |
| 410 | `AUDIENCE_APPROVAL_EXPIRED` | Cancellation: the request expired |

For common API errors, see [Errors](/docs/errors).

## Known specifics

- **The original key is still required.** Issuing another key to the same owner does not transfer the request. Even a key with the `vibe:cowork` scope can check and cancel its own request if the other current checks pass; this does not authorize it to perform infra write operations.
- **Reading detects an outdated request.** A status check may return `STALE` or `EXPIRED`. That consent cannot be used; create a new request through the original operation.
- **The report does not return secrets.** Only the original operation receives Bearer/JWT credentials or secret URLs after application, not these methods.

## See also

- [Access policy](/docs/infra/access/access-policy)
- [Create a token](/docs/infra/access-tokens/create)
