Call Tool
curl --request POST \
--url https://api.danubeai.com/v1/tools/call/{tool_id} \
--header 'Content-Type: application/json' \
--header 'danube-api-key: <api-key>' \
--data '
{
"tool_input": {
"limit": 5
}
}
'import requests
url = "https://api.danubeai.com/v1/tools/call/{tool_id}"
payload = { "tool_input": { "limit": 5 } }
headers = {
"danube-api-key": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'danube-api-key': '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({tool_input: {limit: 5}})
};
fetch('https://api.danubeai.com/v1/tools/call/{tool_id}', 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://api.danubeai.com/v1/tools/call/{tool_id}",
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([
'tool_input' => [
'limit' => 5
]
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"danube-api-key: <api-key>"
],
]);
$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://api.danubeai.com/v1/tools/call/{tool_id}"
payload := strings.NewReader("{\n \"tool_input\": {\n \"limit\": 5\n }\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("danube-api-key", "<api-key>")
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://api.danubeai.com/v1/tools/call/{tool_id}")
.header("danube-api-key", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"tool_input\": {\n \"limit\": 5\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.danubeai.com/v1/tools/call/{tool_id}")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["danube-api-key"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"tool_input\": {\n \"limit\": 5\n }\n}"
response = http.request(request)
puts response.read_body{
"tool_id": "<string>",
"status": "success",
"result": "<unknown>",
"error": "<string>",
"error_type": "<string>",
"fault": "danube",
"retryable": true,
"execution_time": 123,
"execution_id": "<string>",
"projection": {},
"defaults_applied": [
"<string>"
],
"response_headers": {},
"truncated": true,
"response_meta": {},
"redaction": {},
"cost_cents": 123,
"balance_cents": 123,
"request_params": {}
}{
"error": {
"code": "<string>",
"message": "<string>",
"details": {}
}
}{
"error": {
"code": "<string>",
"message": "<string>",
"details": {}
}
}{
"error": {
"code": "rate_limited",
"message": "<string>",
"details": {
"usage": {},
"upgrade_url": "<string>"
}
}
}Tools
Call Tool
Execute a tool with the provided input parameters
POST
/
tools
/
call
/
{tool_id}
Call Tool
curl --request POST \
--url https://api.danubeai.com/v1/tools/call/{tool_id} \
--header 'Content-Type: application/json' \
--header 'danube-api-key: <api-key>' \
--data '
{
"tool_input": {
"limit": 5
}
}
'import requests
url = "https://api.danubeai.com/v1/tools/call/{tool_id}"
payload = { "tool_input": { "limit": 5 } }
headers = {
"danube-api-key": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'danube-api-key': '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({tool_input: {limit: 5}})
};
fetch('https://api.danubeai.com/v1/tools/call/{tool_id}', 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://api.danubeai.com/v1/tools/call/{tool_id}",
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([
'tool_input' => [
'limit' => 5
]
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"danube-api-key: <api-key>"
],
]);
$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://api.danubeai.com/v1/tools/call/{tool_id}"
payload := strings.NewReader("{\n \"tool_input\": {\n \"limit\": 5\n }\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("danube-api-key", "<api-key>")
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://api.danubeai.com/v1/tools/call/{tool_id}")
.header("danube-api-key", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"tool_input\": {\n \"limit\": 5\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.danubeai.com/v1/tools/call/{tool_id}")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["danube-api-key"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"tool_input\": {\n \"limit\": 5\n }\n}"
response = http.request(request)
puts response.read_body{
"tool_id": "<string>",
"status": "success",
"result": "<unknown>",
"error": "<string>",
"error_type": "<string>",
"fault": "danube",
"retryable": true,
"execution_time": 123,
"execution_id": "<string>",
"projection": {},
"defaults_applied": [
"<string>"
],
"response_headers": {},
"truncated": true,
"response_meta": {},
"redaction": {},
"cost_cents": 123,
"balance_cents": 123,
"request_params": {}
}{
"error": {
"code": "<string>",
"message": "<string>",
"details": {}
}
}{
"error": {
"code": "<string>",
"message": "<string>",
"details": {}
}
}{
"error": {
"code": "rate_limited",
"message": "<string>",
"details": {
"usage": {},
"upgrade_url": "<string>"
}
}
}Execute a tool with the provided input parameters. The tool’s response format varies depending on the specific tool being called.
On the MCP server the same three fields ride in
Example
curl -X POST "https://api.danubeai.com/v1/tools/call/abc123" \
-H "danube-api-key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"tool_input": {"limit": 5}}'
Response envelope
| Field | Meaning |
|---|---|
status | success or error |
result | The tool’s payload |
error | Error message, when status is error |
execution_time | Seconds taken |
execution_id | Handle for the stored full result. GET /v1/tools/executions/{execution_id}/result?path=... reads any part of it back without re-running the tool (Get Execution Result) |
projection | Present when fields was sent: {fields, missing}, the paths kept and the paths that matched nothing, plus empty (paths that matched an empty list or object) when there are any |
defaults_applied | Names of parameters filled from saved parameter defaults because the call omitted them; present only when non-empty |
response_headers | Upstream response headers the tool is set up to pass back, such as a provider’s usage-credit counters (The Odds API’s x-requests-remaining, x-requests-used, x-requests-last); present only when the upstream sent one. On the MCP server they ride in _meta.response_headers |
cost_cents / balance_cents | After a paid tool: what this call cost and the wallet balance left |
catalog_repaired | Present when the tool’s catalog row pointed at an upstream tool that had been renamed; Danube re-synced the service and re-ran the call, and this is the real result |
request_params | The input the tool received, after secret redaction |
truncated / response_meta | Set when result was shrunk to fit a size cap (pass max_response_chars in the body to raise it, max 2,000,000) |
redaction | Present when credential values in result were masked: count, fields (path, key, rule), mode |
error_type | Machine-readable class when status is error, from a closed vocabulary: auth_required, auth_expired, permission_denied, bad_request, not_found, conflict, rate_limited, timeout, connection_error, server_error, upstream_rejected, endpoint_missing, upstream_tool_missing, request_malformed, internal_error, … |
fault | Who owns the failure when status is error. danube: Danube’s own handling (a stale catalog row, a request Danube built wrong, an internal failure); it is recorded for repair and retrying will not help. upstream: the third-party service failed (5xx, timeout, unreachable, rate limit); retrying later may work. caller: the request itself was rejected (credentials, parameters, a resource that does not exist, a cap); change it before retrying. Only upstream failures count against a tool’s reliability score. |
retryable | false when calling again with the same input cannot succeed (a missing credential, a catalog row whose upstream tool no longer exists); true for a transient upstream failure |
_meta, and the error text opens with the owner: Danube error: ..., Apify error: ..., or Request error: ....
Body options
Alongsidetool_input, the body accepts:
| Field | Meaning |
|---|---|
max_response_chars | Raise the size cap on result |
fields | Dotted paths to keep in result (the full result stays readable by execution_id) |
confirm_token | Completes the consent handshake for keys that require confirmation |
timeout_seconds | How long to wait on a slow upstream for this one call, 1 to 300 (default about 30). For tools that do real work before answering, such as an Apify actor run or a server-side render. Past 300 seconds, start the work asynchronously and poll with the service’s status tool instead. |
Secrets are redacted
Credential values an upstream hands back (environment variables, API keys, tokens, private keys) are masked as[REDACTED:<FIELD>] before the result
reaches you, and the masked form is what Danube stores. This is Danube
policy, not a broken tool. If a later call genuinely needs such a value,
store it as a credential on the service, or reference it with env:// /
vault://, rather than asking a tool to return the raw secret. Tools whose
purpose is to return a newly created credential are marked as such and report
redaction.passthrough_reason instead of masking.Authorizations
Your Danube API key
Path Parameters
The unique identifier of the tool to execute
Body
application/json
Tool input parameters
Input parameters for the tool. A body without tool_input is treated as the input itself, in which case the options below are not read.
Size cap on result (max 2000000)
Dotted paths to keep in result
Completes the consent handshake
Wait on a slow MCP-backed upstream for this one call
Required range:
1 <= x <= 300Response
Tool execution result
Execution envelope; result varies by tool
Available options:
success, error The tool's payload
Available options:
danube, upstream, caller Seconds
Handle for the stored full result
Declared upstream response headers, e.g. usage-credit counters
Show child attributes
Show child attributes
