Create mid call tool
curl --request POST \
--url https://app.heyfred.nl/api/user/tools \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"name": "<string>",
"description": "<string>",
"endpoint": "<string>",
"method": "<string>",
"body_format": "<string>",
"timeout": 123,
"headers": [
{
"name": "<string>",
"value": "<string>"
}
],
"static_fields": [
{
"key": "<string>",
"value": "<string>"
}
],
"schema": [
{
"name": "<string>",
"type": "<string>",
"description": "<string>",
"required": true
}
]
}
'import requests
url = "https://app.heyfred.nl/api/user/tools"
payload = {
"name": "<string>",
"description": "<string>",
"endpoint": "<string>",
"method": "<string>",
"body_format": "<string>",
"timeout": 123,
"headers": [
{
"name": "<string>",
"value": "<string>"
}
],
"static_fields": [
{
"key": "<string>",
"value": "<string>"
}
],
"schema": [
{
"name": "<string>",
"type": "<string>",
"description": "<string>",
"required": True
}
]
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
name: '<string>',
description: '<string>',
endpoint: '<string>',
method: '<string>',
body_format: '<string>',
timeout: 123,
headers: [{name: '<string>', value: '<string>'}],
static_fields: [{key: '<string>', value: '<string>'}],
schema: [{name: '<string>', type: '<string>', description: '<string>', required: true}]
})
};
fetch('https://app.heyfred.nl/api/user/tools', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://app.heyfred.nl/api/user/tools",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'name' => '<string>',
'description' => '<string>',
'endpoint' => '<string>',
'method' => '<string>',
'body_format' => '<string>',
'timeout' => 123,
'headers' => [
[
'name' => '<string>',
'value' => '<string>'
]
],
'static_fields' => [
[
'key' => '<string>',
'value' => '<string>'
]
],
'schema' => [
[
'name' => '<string>',
'type' => '<string>',
'description' => '<string>',
'required' => true
]
]
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://app.heyfred.nl/api/user/tools"
payload := strings.NewReader("{\n \"name\": \"<string>\",\n \"description\": \"<string>\",\n \"endpoint\": \"<string>\",\n \"method\": \"<string>\",\n \"body_format\": \"<string>\",\n \"timeout\": 123,\n \"headers\": [\n {\n \"name\": \"<string>\",\n \"value\": \"<string>\"\n }\n ],\n \"static_fields\": [\n {\n \"key\": \"<string>\",\n \"value\": \"<string>\"\n }\n ],\n \"schema\": [\n {\n \"name\": \"<string>\",\n \"type\": \"<string>\",\n \"description\": \"<string>\",\n \"required\": true\n }\n ]\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://app.heyfred.nl/api/user/tools")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"name\": \"<string>\",\n \"description\": \"<string>\",\n \"endpoint\": \"<string>\",\n \"method\": \"<string>\",\n \"body_format\": \"<string>\",\n \"timeout\": 123,\n \"headers\": [\n {\n \"name\": \"<string>\",\n \"value\": \"<string>\"\n }\n ],\n \"static_fields\": [\n {\n \"key\": \"<string>\",\n \"value\": \"<string>\"\n }\n ],\n \"schema\": [\n {\n \"name\": \"<string>\",\n \"type\": \"<string>\",\n \"description\": \"<string>\",\n \"required\": true\n }\n ]\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://app.heyfred.nl/api/user/tools")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"name\": \"<string>\",\n \"description\": \"<string>\",\n \"endpoint\": \"<string>\",\n \"method\": \"<string>\",\n \"body_format\": \"<string>\",\n \"timeout\": 123,\n \"headers\": [\n {\n \"name\": \"<string>\",\n \"value\": \"<string>\"\n }\n ],\n \"static_fields\": [\n {\n \"key\": \"<string>\",\n \"value\": \"<string>\"\n }\n ],\n \"schema\": [\n {\n \"name\": \"<string>\",\n \"type\": \"<string>\",\n \"description\": \"<string>\",\n \"required\": true\n }\n ]\n}"
response = http.request(request)
puts response.read_body{
"message": "Tool created successfully",
"data": {
"id": 1,
"name": "check_order_status",
"description": "Use this tool to check the status of a customer's order.",
"type": "http",
"endpoint": "https://api.yourstore.com/orders/{order_id}/status",
"method": "GET",
"body_format": "json",
"timeout": 10,
"headers": [
{
"name": "Content-Type",
"value": "application/json"
},
{
"name": "Authorization",
"value": "Bearer {{crm_key}}"
}
],
"static_fields": [
{
"key": "source",
"value": "autocalls"
},
{
"key": "caller",
"value": "{{customer_phone}}"
}
],
"schema": [
{
"name": "order_id",
"type": "string",
"description": "The customer's order ID",
"required": true
},
{
"name": "amount",
"type": "float",
"description": "Order total as a decimal, e.g. 19.99",
"required": false
},
{
"name": "priority_order",
"type": "boolean",
"description": "Whether this is a priority order",
"required": false
}
],
"created_at": "2025-10-10T12:00:00.000000Z",
"updated_at": "2025-10-10T12:00:00.000000Z"
}
}
{
"message": "Tool name must start with a letter or underscore and contain only letters, numbers, and underscores (max 64 characters).",
"errors": {
"name": [
"Tool name must start with a letter or underscore and contain only letters, numbers, and underscores (max 64 characters)."
]
}
}
{
"message": "You have reached your plan limit of 5 mid call tools. Please upgrade your plan to create more tools."
}
Mid Call Tools
Create mid call tool
Create a new mid call tool
POST
/
user
/
tools
Create mid call tool
curl --request POST \
--url https://app.heyfred.nl/api/user/tools \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"name": "<string>",
"description": "<string>",
"endpoint": "<string>",
"method": "<string>",
"body_format": "<string>",
"timeout": 123,
"headers": [
{
"name": "<string>",
"value": "<string>"
}
],
"static_fields": [
{
"key": "<string>",
"value": "<string>"
}
],
"schema": [
{
"name": "<string>",
"type": "<string>",
"description": "<string>",
"required": true
}
]
}
'import requests
url = "https://app.heyfred.nl/api/user/tools"
payload = {
"name": "<string>",
"description": "<string>",
"endpoint": "<string>",
"method": "<string>",
"body_format": "<string>",
"timeout": 123,
"headers": [
{
"name": "<string>",
"value": "<string>"
}
],
"static_fields": [
{
"key": "<string>",
"value": "<string>"
}
],
"schema": [
{
"name": "<string>",
"type": "<string>",
"description": "<string>",
"required": True
}
]
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
name: '<string>',
description: '<string>',
endpoint: '<string>',
method: '<string>',
body_format: '<string>',
timeout: 123,
headers: [{name: '<string>', value: '<string>'}],
static_fields: [{key: '<string>', value: '<string>'}],
schema: [{name: '<string>', type: '<string>', description: '<string>', required: true}]
})
};
fetch('https://app.heyfred.nl/api/user/tools', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://app.heyfred.nl/api/user/tools",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'name' => '<string>',
'description' => '<string>',
'endpoint' => '<string>',
'method' => '<string>',
'body_format' => '<string>',
'timeout' => 123,
'headers' => [
[
'name' => '<string>',
'value' => '<string>'
]
],
'static_fields' => [
[
'key' => '<string>',
'value' => '<string>'
]
],
'schema' => [
[
'name' => '<string>',
'type' => '<string>',
'description' => '<string>',
'required' => true
]
]
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://app.heyfred.nl/api/user/tools"
payload := strings.NewReader("{\n \"name\": \"<string>\",\n \"description\": \"<string>\",\n \"endpoint\": \"<string>\",\n \"method\": \"<string>\",\n \"body_format\": \"<string>\",\n \"timeout\": 123,\n \"headers\": [\n {\n \"name\": \"<string>\",\n \"value\": \"<string>\"\n }\n ],\n \"static_fields\": [\n {\n \"key\": \"<string>\",\n \"value\": \"<string>\"\n }\n ],\n \"schema\": [\n {\n \"name\": \"<string>\",\n \"type\": \"<string>\",\n \"description\": \"<string>\",\n \"required\": true\n }\n ]\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://app.heyfred.nl/api/user/tools")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"name\": \"<string>\",\n \"description\": \"<string>\",\n \"endpoint\": \"<string>\",\n \"method\": \"<string>\",\n \"body_format\": \"<string>\",\n \"timeout\": 123,\n \"headers\": [\n {\n \"name\": \"<string>\",\n \"value\": \"<string>\"\n }\n ],\n \"static_fields\": [\n {\n \"key\": \"<string>\",\n \"value\": \"<string>\"\n }\n ],\n \"schema\": [\n {\n \"name\": \"<string>\",\n \"type\": \"<string>\",\n \"description\": \"<string>\",\n \"required\": true\n }\n ]\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://app.heyfred.nl/api/user/tools")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"name\": \"<string>\",\n \"description\": \"<string>\",\n \"endpoint\": \"<string>\",\n \"method\": \"<string>\",\n \"body_format\": \"<string>\",\n \"timeout\": 123,\n \"headers\": [\n {\n \"name\": \"<string>\",\n \"value\": \"<string>\"\n }\n ],\n \"static_fields\": [\n {\n \"key\": \"<string>\",\n \"value\": \"<string>\"\n }\n ],\n \"schema\": [\n {\n \"name\": \"<string>\",\n \"type\": \"<string>\",\n \"description\": \"<string>\",\n \"required\": true\n }\n ]\n}"
response = http.request(request)
puts response.read_body{
"message": "Tool created successfully",
"data": {
"id": 1,
"name": "check_order_status",
"description": "Use this tool to check the status of a customer's order.",
"type": "http",
"endpoint": "https://api.yourstore.com/orders/{order_id}/status",
"method": "GET",
"body_format": "json",
"timeout": 10,
"headers": [
{
"name": "Content-Type",
"value": "application/json"
},
{
"name": "Authorization",
"value": "Bearer {{crm_key}}"
}
],
"static_fields": [
{
"key": "source",
"value": "autocalls"
},
{
"key": "caller",
"value": "{{customer_phone}}"
}
],
"schema": [
{
"name": "order_id",
"type": "string",
"description": "The customer's order ID",
"required": true
},
{
"name": "amount",
"type": "float",
"description": "Order total as a decimal, e.g. 19.99",
"required": false
},
{
"name": "priority_order",
"type": "boolean",
"description": "Whether this is a priority order",
"required": false
}
],
"created_at": "2025-10-10T12:00:00.000000Z",
"updated_at": "2025-10-10T12:00:00.000000Z"
}
}
{
"message": "Tool name must start with a letter or underscore and contain only letters, numbers, and underscores (max 64 characters).",
"errors": {
"name": [
"Tool name must start with a letter or underscore and contain only letters, numbers, and underscores (max 64 characters)."
]
}
}
{
"message": "You have reached your plan limit of 5 mid call tools. Please upgrade your plan to create more tools."
}
This endpoint allows you to create a new mid call tool that can be used by your AI assistants to interact with external APIs during calls.
Body Parameters
The public API creates HTTP request tools. Automation Platform tools (which
generate a linked flow) are created from the dashboard. Tool values support
dynamic variables — use
{param} for AI-extracted parameters in the URL, and
{{variable}} (e.g. {{customer_phone}}) in the URL, header values, and static
field values.string
required
Tool name — letters, numbers and underscores, starting with a letter or underscore (max 64 characters, e.g.,
get_weather, book_appointment)string
required
Detailed explanation of when and how the AI should use this tool (max 255 characters)
string
required
Valid URL of the API endpoint to call (max 2048 characters)
string
required
HTTP method:
GET, POST, PUT, PATCH, or DELETEstring
How the request body is encoded for write methods (POST/PUT/PATCH):
json (default) or form (application/x-www-form-urlencoded)integer
Request timeout in seconds (1-30, default: 10)
array
array
array
Parameters that the AI will extract from conversation and send to the endpoint
Show schema properties
Show schema properties
string
required
Parameter name (1-64 chars, must start with a letter or underscore, can contain letters, numbers and underscores)
string
required
Parameter type:
string, number, float, or booleanstring
required
Description to help AI understand how to extract this parameter (3-255 chars)
boolean
Whether the AI must collect this parameter. Optional parameters are only sent when a value was collected. Defaults to
false.Response fields
string
Success message
object
The created tool object
Show data properties
Show data properties
integer
The unique identifier of the tool
string
The name of the tool
string
Tool description
string
Tool type:
http or automationstring
API endpoint URL
string
HTTP method
string
Request body encoding:
json or forminteger
Request timeout in seconds
array
HTTP headers
array
Fixed key/value pairs always sent with the request
array
Parameter schema
string
ISO 8601 timestamp
string
ISO 8601 timestamp
{
"message": "Tool created successfully",
"data": {
"id": 1,
"name": "check_order_status",
"description": "Use this tool to check the status of a customer's order.",
"type": "http",
"endpoint": "https://api.yourstore.com/orders/{order_id}/status",
"method": "GET",
"body_format": "json",
"timeout": 10,
"headers": [
{
"name": "Content-Type",
"value": "application/json"
},
{
"name": "Authorization",
"value": "Bearer {{crm_key}}"
}
],
"static_fields": [
{
"key": "source",
"value": "autocalls"
},
{
"key": "caller",
"value": "{{customer_phone}}"
}
],
"schema": [
{
"name": "order_id",
"type": "string",
"description": "The customer's order ID",
"required": true
},
{
"name": "amount",
"type": "float",
"description": "Order total as a decimal, e.g. 19.99",
"required": false
},
{
"name": "priority_order",
"type": "boolean",
"description": "Whether this is a priority order",
"required": false
}
],
"created_at": "2025-10-10T12:00:00.000000Z",
"updated_at": "2025-10-10T12:00:00.000000Z"
}
}
{
"message": "Tool name must start with a letter or underscore and contain only letters, numbers, and underscores (max 64 characters).",
"errors": {
"name": [
"Tool name must start with a letter or underscore and contain only letters, numbers, and underscores (max 64 characters)."
]
}
}
{
"message": "You have reached your plan limit of 5 mid call tools. Please upgrade your plan to create more tools."
}
Attaching Tools to Assistants
After creating a tool, you need to attach it to an assistant to use it during calls. Tools are managed through the Assistant API:- Create Assistant - Use the
tool_idsparameter to attach tools when creating an assistant - Update Assistant - Use the
tool_idsparameter to add, remove, or replace tools on an existing assistant
⌘I

