Skip to Content
Voice AICustom Tools (Call your APIs)

Custom tools — call your own APIs

The built-in tools (capture lead, schedule callback, transfer to human, etc.) cover the common cases. Custom tools cover everything else — any HTTP API you can describe with a URL and a few fields, the agent can call mid-conversation.

A few real examples customers ship:

  • “How many credits do I have left?” → agent calls GET https://api.yourapp.com/v1/users/{{user_id}}/balance and reads the number back.
  • “Where’s my order?” → agent calls GET https://api.yourapp.com/v1/orders/{{order_id}} and reads off the status, ETA, and tracking link.
  • “Book me an appointment for tomorrow” → agent calls POST https://api.yourapp.com/v1/appointments with date + service.
  • “Update my mobile number to …” → agent calls PATCH https://api.yourapp.com/v1/profile.

You configure each tool once on the agent’s Tools tab → Custom tools section. The agent decides when to fire each one based on the description you write — same as the built-in tools.

How it works (end-to-end)

  1. You define the tool — name, description, HTTP method, URL, headers, request fields, response mapping.
  2. The agent connects at call time and the platform passes your tool definitions into the call session as part of the room metadata.
  3. The agent registers your tools as functions the LLM can call. The LLM sees the tool’s name + description + parameters — that’s how it decides when to fire it.
  4. During the call, when the LLM decides to call your tool, the platform substitutes any {{placeholders}} in the URL/headers/body with the values the LLM filled in, then makes the HTTP request on your behalf. 10-second timeout.
  5. The response comes back to the LLM — either the mapped attributes (when you’ve configured response mapping) or the raw JSON body, trimmed.
  6. The LLM speaks the result to the caller in natural language.

You can hear the tool fire on your dashboard’s Activity tab, and the call recording will reflect the agent reading back whatever your API returned.

Setup walkthrough

1. Open the Tools tab

Go to AI Agents → [your voice agent] → Tools.

Scroll past the built-in tool list to Custom tools. Click + Add tool.

2. Name the tool

Give it a snake_case name like check_balance, get_order_status, or book_appointment. This is what the LLM uses internally to call it; not what the caller hears.

Names must be unique across the agent’s custom tools.

3. Describe what it does

The description is the most important field — the LLM reads it to decide whether to fire your tool. Write it like a one-line spec:

“Looks up the caller’s current credit balance. Use when the caller asks how many credits / how much balance they have left.”

Be specific about when to use it. Vague descriptions lead to the LLM either never firing it or firing it too eagerly.

4. Set the API endpoint

Pick the HTTP method — GET, POST, PUT, PATCH, DELETE — and paste the URL. Use {{field_name}} anywhere you want the LLM to fill in a value at call time:

https://api.yourapp.com/v1/orders/{{order_id}} https://api.yourapp.com/v1/users/{{user_id}}/balance

You can also use these always-available context placeholders without declaring them as fields:

PlaceholderValue
{{call_id}}The current voice call’s ID
{{user_id}}The Splashify Pro user ID
{{agent_id}}The voice agent’s ID
{{contact_phone}}The caller’s phone number
{{contact_name}}The caller’s saved contact name (if any)

5. Add headers

Click + Add header for each. Common cases:

KeyValue
AuthorizationBearer sk_live_...
X-API-Keyyour-api-key-here
Content-Typeapplication/json (added by default)

Secrets paste in here and never leave the platform.

6. Define request fields

For each piece of data the agent should fill in, click + Add field:

ColumnWhat it controls
NameField name. Match the placeholder in the URL/body (e.g. order_id).
LocationWhere the value goes: body, query, path, or header.
Typestring, number, or boolean.
RequiredForces the LLM to fill it before firing.
DescriptionWhat this field is for. The LLM uses this to fill it correctly — be specific.

Or click Auto-detect — the platform parses your URL and pulls out {{field}} placeholders + ?key=value query params + :param path segments and seeds the field list automatically. You then refine each row.

7. Map the response

When your API returns JSON, you usually only care about a few fields. Response attribute mapping lets you pick which keys the agent reads back:

Attribute (what the agent sees)Response key (JSON path into the API response)
balance_inrdata.balance
currencydata.currency
expires_atmeta.subscription.expires_at

The mapping uses dot-separated paths, including data.items.0.name for arrays. Unmapped keys are dropped — the LLM won’t see them.

If you leave mappings empty, the LLM gets the raw JSON body trimmed to 500 characters. That works for simple responses but the LLM has to figure out which key matters.

8. Test it

Click ▶ Test on the tool card. The platform makes the HTTP request with no parameters filled in — just the literal URL + headers as configured. Use this to confirm authentication is working and the endpoint is reachable.

For a full end-to-end test (with the LLM filling in parameters), use Test Call at the top of the page and ask the agent the question that should fire your tool.

9. Toggle it on + Save

The right-most switch on the tool card enables / disables it. Saved tools that aren’t enabled stay in your config but the LLM doesn’t see them — useful for keeping work-in-progress tools around without exposing them.

Click Save tools at the bottom of the page.

Worked example: “How many credits do I have?”

You ship a service at https://api.yourapp.com that exposes GET /v1/users/{user_id}/credits returning:

{ "data": { "balance": 247, "currency": "INR", "expires_at": "2026-12-31" } }

Configure the tool like this:

FieldValue
Namecheck_user_credits
Description”Looks up the caller’s credit balance. Use when the caller asks how many credits / what’s their balance / when their credits expire.”
MethodGET
URLhttps://api.yourapp.com/v1/users/{{user_phone}}/credits
HeadersAuthorization: Bearer sk_live_yourkey
Fieldsuser_phone (path, string, required, “The caller’s phone number”)
Mappingsbalance ← data.balance, currency ← data.currency, expires_at ← data.expires_at

During a call:

Caller: “Hey, do I have any credits left?”

Agent (decides to fire check_user_credits with user_phone= {{contact_phone}}):

Backend (you): replies with the JSON above.

Agent (reads mapped attributes back): “You have 247 INR in credits — they’re valid until December 31, 2026.”

Built-in security

  • HTTPS-only URLs (HTTP allowed during dev, but logged as a warning).
  • Request timeout: 10 seconds. Slow APIs return a polite “I couldn’t reach that service right now” so the call doesn’t stall.
  • Tool firing is rate-limited per call — the LLM can’t loop on a single tool indefinitely.
  • All tool fires are logged to your Activity tab with the request body and response body for replay / debugging.
  • The LLM never sees your raw API keys — they live in the headers config, are sent server-side from the platform, and never leak into the call transcript.

Limits

LimitValue
Custom tools per agent20
Headers per toolNo hard cap (keep it sane — 10 is plenty)
Request fields per toolNo hard cap
Response mappings per toolNo hard cap
Request timeout10 seconds
Response body consideredFirst 500 characters of trimmed JSON, OR all mapped values

Common errors

SymptomLikely causeFix
Test returns “Network error”URL unreachable from the platformConfirm DNS resolves, firewall allows our egress IPs, endpoint is public-facing
Test returns HTTP 401Wrong auth headerCheck the Authorization header value, refresh your API key if needed
Test returns HTTP 200 but the agent says “I couldn’t reach that service”Firewall is blocking the platform’s egressWhitelist 203.174.23.244 in your API gateway
Agent never fires the tool during a callDescription is too vague, OR the tool isn’t enabledRewrite the description to spell out when to fire it; confirm the toggle is on
Agent fires the tool with wrong valuesLLM misunderstood the parameter descriptionMake field descriptions explicit (“Order ID — typically a 10-digit number starting with ‘ORD-’“)
Save fails with “duplicate tool name”Two tools share a nameRename one — names must be unique per agent

What’s next

  • Built-in tools — see Tools the agent can use for the platform-managed actions (capture lead, schedule callback, transfer to human, etc.).
  • Knowledge base — for read-only lookups against your own documents, Knowledge base is faster than a custom tool because the data is pre-indexed.
  • Test calls — run an end-to-end test before deploying. See Test call.