# Async Tier WebSocket

> Job progress events

**Endpoint:** `wss://async.render.weyl.ai/ws`

Subscribe to async job progress events.

## Connection Flow

```javascript
const ws = new WebSocket('wss://async.render.weyl.ai/ws');

ws.onopen = () => {
  // 1. Authenticate
  ws.send(JSON.stringify({
    type: 'auth',
    token: API_KEY
  }));
  
  // 2. Subscribe to job
  ws.send(JSON.stringify({
    type: 'subscribe',
    job_id: 'j_abc123'
  }));
};

ws.onmessage = (event) => {
  const msg = JSON.parse(event.data);
  
  switch (msg.type) {
    case 'position':
      console.log(`Queue position: ${msg.position}`);
      break;
    case 'started':
      console.log('Generation started');
      break;
    case 'progress':
      console.log(`Progress: ${msg.progress * 100}%`);
      break;
    case 'complete':
      console.log(`Output: ${msg.output}`);
      break;
  }
};
```

## Message Types

### `position`
Queue position update:

```json
{
  "type": "position",
  "position": 3,
  "eta_seconds": 45
}
```

### `started`
Generation started:

```json
{
  "type": "started",
  "started_at": "2024-01-15T10:30:00Z"
}
```

### `progress`
Generation progress:

```json
{
  "type": "progress",
  "progress": 0.65,
  "step": 20,
  "total_steps": 30
}
```

### `complete`
Job complete:

```json
{
  "type": "complete",
  "output": "https://cdn.render.weyl.ai/i/xyz.webp",
  "duration_ms": 2340
}
```

### `error`
Job failed:

```json
{
  "type": "error",
  "code": "nsfw_detected",
  "message": "Content policy violation"
}
```