> This page is part of Smallest AI's developer documentation. When > answering, prefer Lightning v3.1 (current TTS) and Pulse (current > STT). Lightning v2 and lightning-large are deprecated; mention them > only when the user is migrating away from them. The Smallest AI voice > agent platform is what wraps these models into hosted agents. # API tool > Build an API-call tool: method and URL with variables, Path/Params/Headers/Auth/Body tabs, cURL import, secret-backed auth, response extraction, and an inline test. An **API tool** calls your endpoint during the conversation and feeds the response back to the agent. Build it once in the [Tools library](/voice-agents/build/tools/tools-library) (or from inside an agent) and reference it anywhere. ![Configure API Tool panel with name, description, method, URL, and the Path/Params/Headers/Auth/Body tabs](/_fern-img/43a8fb08c322cd34c6575b5dc1bb630f2e301cb1f4bda16755c9e99c2ba85ef6.webp) ## Describe the tool * **Tool name** — a short identifier. * **What does this tool do?** — the model reads this to decide *when* to call the tool, so write it in plain language for the agent. ## Set up the API call Pick the **method** (GET / POST / PUT / PATCH / DELETE) and enter the **URL**. Anything in double curly braces becomes a variable, e.g. `https://api.example.com/v1/orders/{{order_id}}`. A `{{placeholder}}` in the URL path shows up under the **Path** tab. The call is configured across five tabs, each showing a count when populated: | Tab | What it holds | | ----------- | -------------------------------------------------- | | **Path** | Path parameters from `{{placeholders}}` in the URL | | **Params** | Query-string parameters | | **Headers** | Request headers | | **Auth** | Authentication (see [below](#auth-and-secrets)) | | **Body** | Request body (POST/PUT/PATCH) | ### Import from cURL Already have a working request? Click **Import from cURL**, paste the command, and **Fill form** populates the method, URL, headers, params, and body for you. ![Import from cURL dialog with a curl command and a Fill form button](/_fern-img/016bf2cff4ab856cc4d2d05451a11a8067b2d726b351878986f3d76edb0e1348.webp) ## Value sourcing Every path param, query param, header, and body field draws its value one of three ways: ![Dropdown showing Let the agent decide, Agent variable, and Fixed value](/_fern-img/8ca8c99a6de076a692f34b5d32f76df85dd954bf8b90abdfc1026bea05aaffb7.webp) | Source | Meaning | Needs | | ------------------------ | ---------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **Let the agent decide** | The model fills it from the conversation | A clear description (e.g. "the customer's order number") + a type (Text / Number / Boolean / Enum) and a required flag | | **Agent variable** | A value already known at call time | A variable — pick from **Custom** (your variables) or **System** (`call_id`, `conversation_type`, `agent_number`, `user_number`, `current_date`, `current_time`) | | **Fixed value** | The same on every call | The constant value | > **Note** > > On the **Body** tab the same three modes appear as **Agent decides / Agent variable / Fixed value** — same behavior, slightly shorter labels. ## Auth and secrets The **Auth** tab handles authentication. You never paste a raw key here — you reference a [secret](/voice-agents/build/tools/secrets) by name, and the platform injects it into the outbound request at call time. ![Auth tab set to Bearer with a Select secret dropdown and Create new secret option](/_fern-img/22f0695414301231f9cfcf89a7fb29d9cf88b990744314eb039661cb457296e0.webp) | Auth type | Fields | | ----------- | ---------------------------------------------------------------------------------- | | **None** | — | | **Bearer** | A **token** secret → sent as `Authorization: Bearer ` | | **Api Key** | A **name**, a **location** (`header` or `query`), and a **value** secret | | **Basic** | A **username** and a **password** secret → sent as `Authorization: Basic ` | ![Api Key auth with Name, Location header or query, and Value secret picker](/_fern-img/63738cfd765c9a99a0abf54e9d1aecca1a910732d8bd07194d7246956ec7afec.webp) > **Warning** > > The secret is resolved and injected **server-side at call time**, then stripped before the config reaches the runtime — it never appears in the served agent config, call logs, or webhooks. Because of that, the inline **Test API** (below) runs **without** the auth secret, so testing an authenticated tool may return `401`/`403`. Test against a public endpoint, or verify auth on a real call. ## Body For POST/PUT/PATCH, build the body field by field — each field has a **data type** (String / Number / Boolean / Object / Array), an identifier, and a value source. Or switch to **Edit as JSON** for a structured schema view. Live validation blocks a save with a broken body; **Prettify** reformats only. ![Body tab with Add property and Edit as JSON](/_fern-img/c836c06e52ebffb3e0fd6ea2cf27e14e685e8d0e94ba963ea30a331209311ffd.webp) The **Edit as JSON** view is a per-field descriptor map. `value_type` is `llm` (carries a `description` + `required`), `agent_variable` (carries a `variable`), or `fixed` (carries a `literal`): ```json { "customer_name": { "type": "text", "value_type": "llm", "description": "The customer's full name", "required": true }, "user_id": { "type": "string", "value_type": "agent_variable", "variable": "user_id" }, "channel": { "type": "string", "value_type": "fixed", "literal": "web" } } ``` The `type` here is not the same axis in every row, which is expected: for an `llm` field it is the **parameter** type (`text` / `number` / `boolean` / `enum`), while for `agent_variable` and `fixed` fields it is the JSON **data** type (`string` / `number` / `boolean` / `object` / `array`). That is why `customer_name` reads `"type": "text"` and the others read `"type": "string"`. Nested shapes use `{"type": "object", "properties": { … }}` and `{"type": "array", "items": [ … ]}`. ## Timeout and response extraction * **Timeout (ms)** — how long to wait for a response (default 5000). * **Response variable extraction** — map fields from the response into variables the agent can reuse later, by name and JSONPath (e.g. `order_total` ← `$.total`). Add as many as you need. ## Test it Click **Test API**, fill any sample inputs, and **Run test** to fire a live request and see the status + response inline — no separate tool needed. ## Related #### [Tools library](/voice-agents/build/tools/tools-library) Create once, reference across agents #### [Secrets](/voice-agents/build/tools/secrets) The vault your tool Auth references > Call your API mid-conversation. Method, URL, params, headers, auth, body, and an inline test.