Skip to content
Tools

POSThttps://core-api.heysadie.ai/tools

name body instruction textInstructions serverUrl success data id tenantId hasTenantInstruction createdAt updatedAt metadata timestamp version path error code message details field

Create tool

Define a new assistant tool that can be executed through structured function-calling. Use this when: - You want the assistant to call an external API using structured logic - You want to define when, how, and what to send to a tool/function ### Fields - `name`: A friendly name for the tool (e.g., "GetMenu", "SubmitReservation") - `body`: The tool function definition, following the function-calling schema. This includes: - `name`: The function name (e.g., "getMenu") - `description`: A short explanation of what the function does - `parameters`: A JSON Schema object describing the expected parameters. Each parameter includes a name, type, and description. **Example:** ```json { "name": "getMenu", "description": "Fetches the current menu for a location", "parameters": { "type": "object", "properties": { "locationId": { "type": "string", "description": "Unique ID of the restaurant location" } }, "required": ["locationId"] } } ``` - `instruction`: A list of step-by-step instructions the assistant should follow before calling the tool. This lets you tightly control the assistant's behavior and validation. **Example:** ```json [ { "step": "check_requirements", "description": "Ensure the user has specified a location" }, { "step": "call_tool", "description": "Invoke the getMenu function with the locationId" }, { "step": "respond", "description": "Summarize the menu results back to the user" } ] ``` - `textInstructions` (optional): Instructions in the same shape as `instruction`, used instead of it when the assistant is in a text conversation (SMS, WhatsApp, webchat). Voice calls always use `instruction`. Leave it out or set it to `null` and text conversations use `instruction` too. Per-assistant step overrides for this version are set through the `text-override` endpoints. - `serverUrl`: The URL endpoint to which the assistant will send the final tool payload (e.g., "https://api.myapp.com/v1/tools/get-menu") This enables deep integration between the assistant's reasoning and your backend systems. ⚠️ All tools are tenant-scoped. Make sure each tool is specific to the use case of your assistant.

Try it in the API Explorer

Example request

Terminal
curl -X POST "https://core-api.heysadie.ai/tools" \
  -H "Authorization: ApiKey YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Transfer to contact",
    "serverUrl": "https://your-directory-server.example.com/find-destination",
    "body": {
      "type": "dynamicTransfer",
      "function": {
        "name": "transferToContact",
        "description": "Look up a person by name in the company directory and transfer the caller to them. Use whenever the caller asks to be connected or transferred to a specific person or department.",
        "parameters": {
          "type": "object",
          "properties": {
            "firstName": {
              "type": "string",
              "description": "First name of the contact the caller wants to reach"
            }
          },
          "required": [
            "firstName"
          ]
        }
      },
      "defaultMode": "cold",
      "messages": [
        {
          "type": "request-start",
          "mode": "static",
          "content": "One moment, connecting you now."
        }
      ]
    },
    "instruction": {
      "title": "Transfer caller to a named contact",
      "description": "How to use transferToContact to connect the caller to the right person.",
      "steps": [
        {
          "title": "Get the contact name",
          "action": "Ask who the caller wants to reach and capture their first name.",
          "wait_for_response": true
        },
        {
          "title": "Look up and connect",
          "action": "Call transferToContact with the first name. If several matches come back, read the options to the caller and ask which one, then call it again. If there's no match, tell the caller you couldn't find that person.",
          "wait_for_response": false
        }
      ]
    }
  }'

Authentication

Authenticate with an API key in the Authorization header using the ApiKey scheme. See Authentication for how keys work and where to get them.

Authorizationstringrequired

API key in the ApiKey scheme: ApiKey YOUR_API_KEY. Tenant keys authorize their own tenant; organization keys can act on any tenant in the organization.

X-Tenant-Idstring (uuid)optional

Required when authenticating with an organization key: it selects the tenant the request acts on. Omit with tenant keys.

Request

Body application/json · required

nameanyoptional

Friendly name for the tool (e.g., 'CheckAvailability')

bodyanyoptional

The full tool definition. `body.type` is `function`, `dynamicTransfer` or `sendDtmf`. For dynamicTransfer: { type, function, defaultMode?, messages? } (see docs/dynamic-transfer-tool.md). For sendDtmf (press dial-pad digits into the call, e.g. a door intercom's open code): { type, function, digits? | codes? } where `digits` is a single dial code and `codes` maps named codes to digits ({ front_door: '#235' }); one of the two is required, allowed characters 0-9 * #. sendDtmf tools have no server: serverUrl may be omitted.

instructionanyoptional

Structured steps or logic the assistant should follow before invoking the tool

textInstructionsanyoptional

Optional instructions used instead of `instruction` when the assistant is in a text conversation (SMS, WhatsApp, webchat). Same shape as `instruction`. Omit to leave the current value unchanged; send null to clear it, so text conversations use `instruction` again.

serverUrlanyoptional

The URL endpoint to call when this tool is invoked

Responses

200
successbooleanrequired

true on every 2xx

dataobjectoptional

The result

Show 10 child properties
idstringrequired
namestringrequired
bodyanyrequired
instructionanyrequired
textInstructionsanyoptional
serverUrlstring | nullrequired
tenantIdstring | nulloptional
hasTenantInstructionbooleanoptional
createdAtstring (date-time) | string (date) | number | nullrequired
updatedAtstring (date-time) | string (date) | number | nullrequired
metadataobjectoptional

Request metadata

Show 3 child properties
timestampstringrequired

When the server answered, ISO 8601 UTC

versionstringrequired

API version

pathstringoptional

The URL that was requested

400The request is invalid. `details` lists each field that failed
successbooleanrequired

false on every error

errorobjectoptional

What went wrong: a stable `code` to branch on and a human-readable `message`

Show 3 child properties
codeenumrequired

A parameter or body field broke a rule

Allowed values:"VALIDATION_ERROR"
messagestringrequired

Human-readable explanation. Do not parse it; branch on `code`

detailsobject[]optional

One entry per field that failed

Show 2 item properties
fieldstringrequired

The offending field

messagestringrequired

The rule it broke

metadataobjectoptional

Request metadata

Show 3 child properties
timestampstringrequired

When the server answered, ISO 8601 UTC

versionstringrequired

API version

pathstringoptional

The URL that was requested

401Missing or invalid credentials
successbooleanrequired

false on every error

errorobjectoptional

What went wrong: a stable `code` to branch on and a human-readable `message`

Show 2 child properties
codeenumrequired

No valid credentials

Allowed values:"UNAUTHORIZED"
messagestringrequired

Human-readable explanation. Do not parse it; branch on `code`

metadataobjectoptional

Request metadata

Show 3 child properties
timestampstringrequired

When the server answered, ISO 8601 UTC

versionstringrequired

API version

pathstringoptional

The URL that was requested

403The credentials are valid but may not use this route
successbooleanrequired

false on every error

errorobjectoptional

What went wrong: a stable `code` to branch on and a human-readable `message`

Show 2 child properties
codeenumrequired

The credentials may not use this route

Allowed values:"FORBIDDEN"
messagestringrequired

Human-readable explanation. Do not parse it; branch on `code`

metadataobjectoptional

Request metadata

Show 3 child properties
timestampstringrequired

When the server answered, ISO 8601 UTC

versionstringrequired

API version

pathstringoptional

The URL that was requested

404Not found, or outside the caller's scope
successbooleanrequired

false on every error

errorobjectoptional

What went wrong: a stable `code` to branch on and a human-readable `message`

Show 2 child properties
codeenumrequired

An id names nothing the caller can see

Allowed values:"RESOURCE_NOT_FOUND"
messagestringrequired

Human-readable explanation. Do not parse it; branch on `code`

metadataobjectoptional

Request metadata

Show 3 child properties
timestampstringrequired

When the server answered, ISO 8601 UTC

versionstringrequired

API version

pathstringoptional

The URL that was requested

500An unexpected server error
successbooleanrequired

false on every error

errorobjectoptional

What went wrong: a stable `code` to branch on and a human-readable `message`

Show 2 child properties
codeenumrequired

An unexpected server failure

Allowed values:"INTERNAL_SERVER_ERROR"
messagestringrequired

Human-readable explanation. Do not parse it; branch on `code`

metadataobjectoptional

Request metadata

Show 3 child properties
timestampstringrequired

When the server answered, ISO 8601 UTC

versionstringrequired

API version

pathstringoptional

The URL that was requested