ThunderPhone 2.0 is live.Self-serve, from 2¢/min.Read the announcement

Developer

Integrations

Define reusable HTTP tool integrations with endpoint, auth, and parameter schemas that any of your agents can call mid-conversation to reach external systems.

Integrations are reusable tool definitions — an endpoint URL + method + headers + a JSON schema for arguments — that you can attach to one or more agents. During a call the agent uses the tool's schema to decide when to call out; ThunderPhone makes the outbound HTTP request on the agent's behalf using the integration's saved configuration.

See also Function Tools for the shape of the JSON schema an integration's spec must follow.

Endpoints

MethodPathDescription
GET/v1/integrationsList integrations
POST/v1/integrationsCreate an integration
GET/v1/integrations/{integration_id}Retrieve an integration
PATCH/v1/integrations/{integration_id}Update an integration
DELETE/v1/integrations/{integration_id}Delete an integration
POST/v1/integrations/{integration_id}/transferCopy / move to another org
GET/v1/integrations/{integration_id}/versionsList prior configuration revisions
POST/v1/integrations/test-requestProbe an integration endpoint from a sandbox

Integration object

{
  "id": "f9b5a1a4-...",
  "display_name": "Weather API",
  "spec": {
    "type": "function",
    "function": {
      "name": "get_weather",
      "description": "Return the current weather for a zip code.",
      "parameters": { /* JSON Schema */ }
    }
  },
  "endpoint_url": "https://api.example.com/weather",
  "endpoint_method": "GET",
  "request_format": "standard",
  "headers": [
    { "key": "X-Api-Key" }
  ],
  "wizard_input": "Use https://api.example.com/weather with X-Api-Key header.",
  "validation_status": "validated",
  "warnings": [],
  "created_at": "2026-04-20T18:24:10.113Z",
  "updated_at": "2026-04-20T18:24:10.113Z"
}
FieldTypeDescription
idUUIDIntegration id
display_namestring1–255 chars
specobjectOpenAI-style function tool schema (see Function Tools)
endpoint_urlstringOutbound HTTP URL the tool calls. Empty string when the integration is still being configured
endpoint_methodstringGET, POST, PUT, PATCH, or DELETE. Defaults to POST
request_formatstringstandard (default), vapi, or retell. Controls the body envelope for POST, PUT, and PATCH; GET and DELETE always use query parameters
headersarrayHeaders sent with every tool invocation. Key names only are returned: header values are write-only, encrypted at rest, and never appear in API responses, version history, or call records
wizard_inputstringFree-form text from the "describe this integration" wizard; kept for audit only
validation_statusstringuntested, validated, error — updated by test-request
created_at, updated_attimestampISO 8601 UTC
warningsarray of objectSaved settings worth a second look, each {code, field, detail} (read-only). tool_has_no_inputs (field is spec.function.parameters) when the tool declares no input properties, so the agent may call it without the data the endpoint needs. Never blocks a save. Empty when there is nothing to flag

List integrations

cURL
curl https://api.thunderphone.com/v1/integrations \
  -H "Authorization: Bearer sk_live_YOUR_API_KEY"

Returns an array of Integration objects.


Create an integration

cURL
curl -X POST https://api.thunderphone.com/v1/integrations \
  -H "Authorization: Bearer sk_live_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "display_name": "Weather API",
    "spec": {
      "type": "function",
      "function": {
        "name": "get_weather",
        "description": "Return the current weather for a zip code.",
        "parameters": {
          "type": "object",
          "properties": {
            "zip": { "type": "string" }
          },
          "required": ["zip"]
        }
      }
    },
    "endpoint_url":    "https://api.example.com/weather",
    "endpoint_method": "GET",
    "request_format":  "standard",
    "headers": [
      { "key": "X-Api-Key", "value": "abc..." }
    ]
  }'

Request fields

FieldTypeRequiredDescription
display_namestringyes1–255 chars
specobjectyesFunction-tool JSON schema. spec.type must be "function"
endpoint_urlstringnoHTTPS URL; defaults to empty string if omitted
endpoint_methodstringnoGET, POST (default), PUT, PATCH, DELETE
request_formatstringnostandard (default), vapi, or retell; see Function Tools request formats
headersarrayno[{key, value}] pairs. Each header needs a value. Names must be unique (case-insensitive)
copy_header_values_fromUUIDnoAnother integration in the same organization. A header sent without a value takes that integration's stored value for the same name (how the dashboard's Clone copies secrets it cannot read)
wizard_inputstringnoFree-form notes

Returns 201 Created with the new Integration object in validation_status="untested".


Retrieve / update / delete

GET, PATCH, and DELETE behave conventionally. PATCH accepts any subset of the create fields. Deleting an integration removes it from every agent it was linked to.

headers on PATCH replaces the whole list, with the same rules as MCP server headers:

  • An entry with an empty or omitted value keeps the stored value for that header name (matched case-insensitively), so you can save an integration you read back without re-sending its secrets.
  • An entry with a value sets or replaces it.
  • A header left out of the list is removed.
  • A new header name without a value is rejected with 400.

Transfer an integration

Copy or move an integration to another organization where you are an admin.

An sk_live_ API key is limited to its own organization: with a key, target_org_id must be the key's organization, and any other target returns 403. Copy or move between organizations from a signed-in session (Authorization: Token <session-token> plus X-ThunderPhone-Org for the source org), as below.

cURL
curl -X POST https://api.thunderphone.com/v1/integrations/f9b5a1a4-.../transfer \
  -H "Authorization: Token YOUR_SESSION_TOKEN" \
  -H "X-ThunderPhone-Org: 42" \
  -H "Content-Type: application/json" \
  -d '{"target_org_id": 77, "mode": "copy"}'
FieldTypeRequiredDescription
target_org_idintegeryes
modestringyescopy or move
namestringnoOverride the copy's display name

Returns 201 Created for copy / 200 OK for move:

{ "mode": "copy", "target_org_id": 77, "integration": { /* ... */ } }

Version history

cURL
curl 'https://api.thunderphone.com/v1/integrations/f9b5a1a4-.../versions?limit=20' \
  -H "Authorization: Bearer sk_live_YOUR_API_KEY"

Response is analogous to Agent versions: {count, results[]} with each result containing id, revision, created_by, snapshot, and changed_fields. Snapshots record header names only, so a change to a header's value alone does not create a new revision.


Test integration request

Execute a one-off HTTP request against the integration endpoint (from ThunderPhone's servers) to validate connectivity before linking the integration to an agent. The sandbox enforces SSRF guards — no requests to localhost or private IP ranges.

cURL
curl -X POST https://api.thunderphone.com/v1/integrations/test-request \
  -H "Authorization: Bearer sk_live_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://api.example.com/weather?zip=94110",
    "method": "GET",
    "tool_name": "get_weather",
    "request_format": "standard",
    "headers": { "X-Api-Key": "abc..." }
  }'
FieldTypeRequiredDescription
urlstringyesHTTPS; http:// is only allowed for localhost during local dev
methodstringyesGET, POST, PUT, PATCH, DELETE
headersobjectnoHeader-name → value map
bodystring | objectnoFor standard, a JSON body or raw string. For vapi/retell, a JSON object of tool arguments
tool_namestringnoTool name used in a Vapi or Retell envelope; defaults to test_tool
request_formatstringnostandard (default), vapi, or retell. Body methods use the selected envelope; GET/DELETE are unchanged
timeout_secondsintegerno1–60 (default 20)
integration_idUUIDnoA saved integration in your organization. Any header sent with an empty value is filled with that integration's stored value for the same name, so you can test a saved integration without re-entering its secrets. Requires admin or owner
Response
{
  "ok": true,
  "status_code": 200,
  "latency_ms": 187,
  "response_headers": { "content-type": "application/json" },
  "response_body_preview": "{\"temperature_f\": 64, ...}",
  "response_truncated": false
}

Response bodies are truncated at 6 kB. SSRF-blocked requests return 400 with code="url_not_allowed".