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

# API Quickstart

> Generate an API key, create a contact, schedule a call, poll its status, and fetch the finished result — a complete first request against the Voxworks API.

## Overview

This walks through the shortest path from a fresh API key to a finished call result: generate a key, create a contact, schedule an outbound call, poll it until it finishes, then fetch the transcript and summary. Every request below is a real endpoint you can run as-is once you swap in your own key, script, and number.

For the full endpoint list see [REST Endpoints (OpenAPI)](/api-reference/overview); for what each field on a call means see [Call Statuses, End Reasons & Outcomes Reference](/calls/statuses).

***

## 1. Generate an API key

In the app, go to **Settings → API Keys** and click **Generate Key**. Give it an optional **Key Name (optional)** (for example *Quickstart test*) so you can tell keys apart later, then click **Generate**.

The full key is shown exactly once — *"Copy your API key now. It won't be shown again."* Copy it somewhere safe. Afterwards the key list only shows its prefix (keys start with `vxw_`) alongside its name, creation date, and last-used date, so if you lose the plaintext value you'll need to revoke it and generate a new one.

Every request below authenticates with this key as a bearer token:

```http theme={null}
Authorization: Bearer YOUR_API_KEY
Content-Type: application/json
```

An API key is scoped to the team it was generated under — every contact, call, and record it touches belongs to that team. See [API Keys & Authentication](/api-reference/authentication) for revocation and error details, and [Rate Limits & Request Limits](/api-reference/rate-limits) for how many requests per minute a key can make.

***

## 2. Create a contact

```bash theme={null}
curl -X POST https://api.voxworks.ai/api/v1/create-contact \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "phone_number": "0429069971",
    "first_name": "John",
    "last_name": "Smith",
    "email": "john.smith@example.com"
  }'
```

`phone_number` and `first_name` are required; `last_name`, `email`, `address`, `location`, `gender`, `age`, and `title` are optional. Send the number in whatever common local format you have on hand — the API normalises it to E.164 for you (`0429069971` becomes `+61429069971`). If a contact with that normalised number already exists on your team, the request fails with `409 Conflict` rather than creating a duplicate.

A successful call returns `201 Created`:

```json theme={null}
{
  "success": true,
  "contact_id": "a1b2c3d4-5678-90ab-cdef-1234567890ab"
}
```

Keep `contact_id` — you'll want it if you look the contact up again later, though scheduling a call in the next step only needs the phone number.

***

## 3. Find your `script_id` and `from_number`

Two values are required to schedule a call and both live in the app rather than being generated by this API:

* **`script_id`** — open **Call Scripts**, select the script you want the call to run, go to its **Settings** tab, and read the **Script UUID** field on the **Call Settings** card.
* **`from_number`** — go to **Numbers & Routing → Numbers**, select the number you want to call from, and use the **Copy number** button that appears when you hover over the number in its detail panel. It must be a number that belongs to your team.

***

## 4. Schedule the call

```bash theme={null}
curl -X POST https://api.voxworks.ai/api/v1/create-phone-call \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "from_number": "+61291234567",
    "script_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "contact": {
      "phone_number": "0429069971",
      "first_name": "John",
      "last_name": "Smith"
    },
    "scheduled_time": "2026-07-16T09:00:00Z"
  }'
```

`from_number`, `script_id`, and `contact.phone_number` are required. `scheduled_time` is an ISO 8601 timestamp and defaults to now if you leave it out. The contact block upserts by phone number — since `0429069971` normalises to the same contact you created in step 2, this call is linked to that existing contact rather than creating a second one; any `first_name`/`last_name` you send here updates the existing record.

A successful call returns `201 Created`:

```json theme={null}
{
  "success": true,
  "call_id": "c9d8e7f6-1234-4abc-9def-0987654321ba",
  "contact_id": "a1b2c3d4-5678-90ab-cdef-1234567890ab",
  "status": "scheduled"
}
```

Save `call_id` — every remaining step uses it.

<Note>
  `from_number` and `contact.phone_number` must both be sent in a format the API can parse to E.164 — either already E.164 (`+61291234567`) or a common local format (`02 9123 4567`). Both are normalised before the call is created.
</Note>

***

## 5. Poll the call status

```bash theme={null}
curl https://api.voxworks.ai/api/v1/get-call-status/c9d8e7f6-1234-4abc-9def-0987654321ba \
  -H "Authorization: Bearer YOUR_API_KEY"
```

```json theme={null}
{
  "success": true,
  "call": {
    "id": "c9d8e7f6-1234-4abc-9def-0987654321ba",
    "status": "in-progress",
    "end_reason": null,
    "duration": null,
    "scheduled_time": "2026-07-16T09:00:00Z",
    "actual_time": "2026-07-16T09:00:03Z",
    "end_time": null,
    "modified_at": "2026-07-16T09:00:03Z"
  }
}
```

Poll on an interval (a few seconds is reasonable) until `status` reaches one of the terminal values — `completed`, `voicemail`, `dropout`, `hang-up`, `rang-out`, `failed`, `cancelled`, `User rejected`, or `User unavailable`. The full meaning of each status is documented on [Call Statuses, End Reasons & Outcomes Reference](/calls/statuses) — note that `status` reaching a terminal value means the call itself has finished, but the transcript and summary may still be generated a few seconds later.

***

## 6. Fetch the result

Once `status` is terminal, fetch the full result:

```bash theme={null}
curl https://api.voxworks.ai/api/v1/get-call-result/c9d8e7f6-1234-4abc-9def-0987654321ba \
  -H "Authorization: Bearer YOUR_API_KEY"
```

```json theme={null}
{
  "success": true,
  "call": {
    "id": "c9d8e7f6-1234-4abc-9def-0987654321ba",
    "status": "completed",
    "type": "outbound",
    "script_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "contact_id": "a1b2c3d4-5678-90ab-cdef-1234567890ab",
    "duration": 142,
    "actual_time": "2026-07-16T09:00:03Z",
    "end_time": "2026-07-16T09:02:25Z",
    "end_reason": "User Hangup",
    "call_summary": "Confirmed the appointment for Thursday at 2pm.",
    "structured_data": { "appointment_confirmed": true },
    "transcript": "AI: Hi, is this John?\nUser: Yes, speaking...",
    "transcript_json": [{ "role": "ai", "text": "Hi, is this John?" }],
    "recording_url": "https://storage.voxworks.ai/recordings/c9d8e7f6.mp3",
    "rating": null,
    "objectives": [{ "objective": "Confirm appointment time", "met": true }],
    "post_call_actions": []
  }
}
```

If you poll `get-call-result` too soon after `status` turns terminal, `call_summary`, `structured_data`, `transcript`, `transcript_json`, and `objectives` may still be empty — give processing a few more seconds and fetch again.

***

## The `%2B` encoding gotcha

Whenever a phone number appears in a URL path — for example `GET /api/v1/get-contact/{phone_number}` — its leading `+` must be percent-encoded as `%2B`, because a literal `+` in a URL path is ambiguous with a space:

```bash theme={null}
curl https://api.voxworks.ai/api/v1/get-contact/%2B61429069971 \
  -H "Authorization: Bearer YOUR_API_KEY"
```

Phone numbers sent inside a JSON request body (like `phone_number` in `create-contact` or `create-phone-call`) don't need this encoding — only ones placed directly in the URL path.

***

## Handling errors

Every endpoint returns the same JSON error shape:

```json theme={null}
{
  "success": false,
  "message": "phone_number: Phone number is not a valid number: 555"
}
```

`400` means the request itself was malformed (missing field, bad phone number, invalid timestamp); `401` means the API key is missing, malformed, or invalid; `403` means the API key has been revoked; `404` means the `script_id`, `from_number`, or `call_id` doesn't exist or doesn't belong to your team; `409` means a contact with that phone number already exists; `429` means you've hit a rate-limit bucket — see [Rate Limits & Request Limits](/api-reference/rate-limits) for the exact numbers and the `Retry-After` header to respect.

***

## Next Steps

<CardGroup cols={2}>
  <Card title="API Keys & Authentication" href="/api-reference/authentication">
    Generate, name, and revoke API keys, and the exact 401/403 responses to expect.
  </Card>

  <Card title="REST Endpoints (OpenAPI)" href="/api-reference/endpoints">
    The full endpoint reference, including contacts, lists, custom variables, and webhooks.
  </Card>

  <Card title="Call Statuses, End Reasons & Outcomes Reference" href="/calls/statuses">
    Every status and end reason a call can report, plus cancel/reschedule/retry rules.
  </Card>

  <Card title="Rate Limits & Request Limits" href="/api-reference/rate-limits">
    Every rate-limit bucket, the 429 response headers, and the request body size cap.
  </Card>
</CardGroup>
