> ## Documentation Index
> Fetch the complete documentation index at: https://docs.orbit.devotel.io/llms.txt
> Use this file to discover all available pages before exploring further.

# The preview-dial loop

> How the two preview-mode operations chain: claim a contact atomically, review it on the agent's screen, then launch the dial.

## The preview-dial loop

Outbound-campaign operators run the dialer workspace. Progressive, predictive, and agentless campaigns fire through the pacing scheduler automatically; **preview mode** is the one where a human reviews each contact card before the call launches. That human loop compresses into two endpoints.

First the agent's frontend claims the next contact with `GET /api/v1/dialer/next-call`:

```bash cURL theme={null}
curl "https://api.orbit.devotel.io/api/v1/dialer/next-call?campaign_id=cmp_71bd" \
  -H "X-API-Key: $ORBIT_API_KEY"
```

<ResponseExample>
  ```json 200 theme={null}
  {
    "data": {
      "contact": {
        "id": "dc_3f9ac42b",
        "phone_e164": "+14155552671",
        "display_name": "Dana Reyes",
        "contact_id": "ct_d2b8",
        "attempts": 1
      },
      "preview_decision_seconds": 30,
      "decision_expires_at": "2026-08-01T12:01:30.000Z"
    },
    "meta": {
      "request_id": "req_next_call",
      "timestamp": "2026-08-01T12:00:00.000Z"
    }
  }
  ```
</ResponseExample>

The claim is atomic — two agents polling concurrently never receive the same number — so the response is the work ticket the agent then reviews on their screen. `preview_decision_seconds` is the per-campaign review countdown; `decision_expires_at` is the server-side deadline for that countdown. `204 No Content` means the campaign is progressive / predictive / agentless (calls fire automatically); `404` means the campaign is not active. A `null` `contact` means the list is drained.

Once the agent clicks "Call" the dial launches:

```bash cURL theme={null}
curl -X POST "https://api.orbit.devotel.io/api/v1/dialer/dial" \
  -H "X-API-Key: $ORBIT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"campaign_id":"cmp_71bd","contact_id":"dc_3f9ac42b"}'
```

The contact must still be in the `dialing` (claimed) state, or the request rejects with `409 CLAIM_NOT_HELD`. The requesting operator records as the call's agent for the TCPA audit trail, and the call itself exits through the Devotel softswitch — the preview loop never dials a number outside the commit path.
