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

# Direct API

> Build the call timeline yourself and send it to Tuner's Create Call API — for stacks that aren't Python.

<Note>
  On a Python stack? Use the [Python SDKs](/docs/integrations/custom-stack/sdk-quickstart) instead — they capture the timeline for you and send it in one call. This guide is for every other language.
</Note>

The API is what the SDKs call under the hood. Going direct means you own the part the observers would have handled: assembling the structured conversation timeline, and deriving per-turn timing and interruptions from whatever your stack exposes.

Concretely, you'll be building:

* the turn-by-turn timeline — user speech, agent speech, tool calls, tool results — each with start and end timestamps relative to call start
* per-turn latency fields, if you want them: STT time-to-transcript, LLM time-to-first-token, TTS time-to-first-byte, end-to-end
* interruption detection, by comparing when a user turn starts against when the agent's turn ended

For a worked example of how much that is in practice, see [Connecting to Vapi (Transient)](/docs/integrations/vapi-transient-assistants) — a single-file integration that does exactly this against Vapi's payload and call log.

***

## Prerequisites

* Tuner Active Account
* A Tuner agent with provider **Custom API**
* Your Tuner API key and workspace ID — see [the contract and authentication](/docs/integrations/custom-stack/overview#the-contract)

***

## Happy path

The video below walks through the full flow.

<iframe width="100%" style={{ aspectRatio: "16/9" }} src="https://www.youtube.com/embed/Izr5JsWDEzM" title="Custom Integration via the Tuner API" frameBorder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowFullScreen />

1. **Create a Tuner Agent** and select **Custom API** as the integration type.
2. In your voice system, after the call ends, capture:
   * the **full structured conversation timeline** (agent and user messages, tool calls, and any node or state transitions)
   * call start and end timestamps
   * a publicly accessible recording URL
   * any relevant operational or enrichment data — cost, call outcome, dynamic variables, or provider-native analysis
3. Call the **Create Call** endpoint with all data, following the API reference.
4. Open **Tuner → Calls** to see the processed results.

***

## API reference

The full **Create Call** request and response schema, with examples:

→ [Create Call API Reference](/docs/api-reference/create-call)

***

## Best practices

* **Make retries safe.** Treat `call_id` as immutable and retry the same request on failure. A duplicate `call_id` returns `409`, which counts as success.
* **Send the final transcript.** If you only have partial transcripts, send only when final, or the analysis runs on incomplete data.
* **Log request IDs and responses.** You'll want them when debugging ingestion.

***

## Common issues

### Calls don't appear in Tuner

Usually one of:

* wrong `workspace_id`
* `agent_remote_identifier` doesn't match the agent mapping you intended
* the call was sent but the transcript is empty or invalid

### Unauthorized (401)

* Ensure you're sending `Authorization: Bearer <API_KEY>`, not `X-API-Key`.
* Confirm the key belongs to the workspace you're sending to.

### Validation errors (4xx)

* Follow the API reference for required fields and types.
* If you're unsure which field failed, start from the minimal example in the API reference and add fields incrementally.

***

## Next steps

<CardGroup cols={2}>
  <Card title="Create Call API reference" icon="terminal" href="/docs/api-reference/create-call">
    Required fields, types, and a minimal example.
  </Card>

  <Card title="Worked example" icon="code" href="/docs/integrations/vapi-transient-assistants">
    A full single-file integration built on this API.
  </Card>

  <Card title="Webhooks" icon="bell" href="/docs/integrations/webhooks">
    Receive events when analysis finishes or an alert fires.
  </Card>

  <Card title="Review your first call" icon="magnifying-glass" href="/docs/observability/overview">
    What Tuner does with the data once it lands.
  </Card>
</CardGroup>
