
## Refresh status

`POST /v1/infra/servers/:id/refresh`

Forcibly polls the cloud provider, retrieves the current status and IP of the server, and updates the record in the database if anything changed. Useful when the status in the platform diverges from reality — for example, after provider maintenance, a hang in `provisioning`, or a manual stop of the virtual machine through the provider's console.

## Parameters

| Parameter | In | Type | Required | Description |
|----------|---|-----|:-----:|----------|
| `id` | path | string (UUID) | yes | Server ID |

The request body is empty.

## Examples

### curl — personal key

```bash
curl -X POST -H "X-Api-Key: YOUR_API_KEY" \
  https://vibecode.bitrix24.com/v1/infra/servers/SERVER_ID/refresh
```

### curl — OAuth application

```bash
curl -X POST -H "X-Api-Key: YOUR_APP_KEY" \
  -H "Authorization: Bearer USER_SESSION_TOKEN" \
  https://vibecode.bitrix24.com/v1/infra/servers/SERVER_ID/refresh
```

### JavaScript — personal key

```javascript
const res = await fetch(
  `https://vibecode.bitrix24.com/v1/infra/servers/${serverId}/refresh`,
  { method: 'POST', headers: { 'X-Api-Key': 'YOUR_API_KEY' } }
)
const { data: status } = await res.json()
console.log(`Current status: ${status}`)
```

### JavaScript — OAuth application

```javascript
await fetch(
  `https://vibecode.bitrix24.com/v1/infra/servers/${serverId}/refresh`,
  {
    method: 'POST',
    headers: {
      'X-Api-Key': 'YOUR_APP_KEY',
      'Authorization': 'Bearer USER_SESSION_TOKEN',
    },
  }
)
```

## Response fields

| Field | Type | Description |
|------|-----|----------|
| `success` | boolean | Always `true` on success |
| `data` | string | Current status in uppercase: `PROVISIONING`, `RUNNING`, `SLEEPING`, `ERROR` |
| `currentState` | object | State snapshot — the same fields as in `error.currentState` for 422 SERVER_WRONG_STATE: `status`, `blackholeStatus`, `hasExternalId`, `lastSeenAt` |
| `availableActions` | string[] | A subset of `['wake','start','reboot','sleep-now','repair','delete']` — actions that make sense to call in the current state |

> The `data` field is a status string kept for backward compatibility. The state snapshot and the list of actions are moved to the adjacent `currentState` and `availableActions` fields. For a full server snapshot (IP, policy, etc.) request [`GET /v1/infra/servers/:id`](/docs/infra/servers/get).

## Response example

```json
{
  "success": true,
  "data": "RUNNING",
  "currentState": {
    "status": "RUNNING",
    "blackholeStatus": "CONNECTED",
    "hasExternalId": true,
    "lastSeenAt": null
  },
  "availableActions": ["reboot", "sleep-now", "delete"]
}
```

## Error response example

404 — the server does not exist:

```json
{
  "success": false,
  "error": {
    "code": "SERVER_NOT_FOUND",
    "message": "Server not found"
  }
}
```

## Errors

| HTTP | Code | Description |
|------|-----|----------|
| 401 | `MISSING_API_KEY` | The `X-Api-Key` header was not provided |
| 401 | `INVALID_API_KEY` | Invalid or expired API key |
| 404 | `SERVER_NOT_FOUND` | The server does not exist, was deleted, or belongs to another API key |
| 429 | `RATE_LIMITED` | The platform's overall request limit was exceeded |
| 502 | `PROVIDER_ERROR` | The cloud provider returned an error while polling the virtual machine |

The full list of common API errors — [Errors](/docs/errors).

## Known specifics

- **It may overwrite the status in the database.** If the provider reports a status that differs from the current one in the database (for example, `stopped` at the provider while `running` in the database), the record is updated: `running → sleeping`, `sleeping → running`, an IP appears, and so on. This is the main way an `error` record "self-heals".
- **Comparison gotcha:** `data === 'RUNNING'`, not `data.status === 'RUNNING'` — the `data` field is intentionally kept as a string for backward compatibility. The state snapshot and the list of available actions are the adjacent `currentState` and `availableActions` fields. This differs from [`GET /v1/infra/servers/:id`](/docs/infra/servers/get), where all the information is inside `data`.
- **Idempotent and safe.** Frequent calls do not create records, do not start the virtual machine, and do not finalize billing. Suitable for ad-hoc reconciliation. For readiness polling loops, [`GET /v1/infra/servers/:id`](/docs/infra/servers/get) is a better fit — it returns the full object.
- **Does not reset the background monitor timer.** If the provider returned the same status and IP already in the database, `/refresh` does not update `updatedAt` — so as not to reset the timer of the internal monitor that counts down `provisioning` timeouts (10 minutes).

## See also

- [Get server](/docs/infra/servers/get) — `GET /v1/infra/servers/:id` — the full picture (automatically triggers refresh if the status is `provisioning`).
- [Repair tunnel](./repair.md) — if the status is `running` but `blackholeStatus: DISCONNECTED`.
- [Start server](./start.md) — if `/refresh` unexpectedly showed `sleeping`.
