Skip to main content

Docs

Coming from the Composio SDK

The Composio SDK's tools.execute cannot reach this API. Three things are different, and the fix for all three is to send the request yourself.

On this page

SambungAPI speaks the Composio wire vocabulary — the same tool slugs, the same argument names, the same error taxonomy — but it serves that vocabulary on its own /v1 surface. The Composio SDK is written against the paths and the response shape of the Composio platform, so it does not arrive.

The three mismatches

What the SDK doesWhat this server does
Calls POST {base}/api/v3.1/tools/execute/{slug}.Serves no /api/v3* path at all. Every one of them answers 404 with the slug Route_NotFound. The route here is POST /v1/tools/{slug}/execute.
Fetches the tool schema first, with GET {base}/api/v3.1/tools/{slug}, and will not send the execute call until that schema resolves.Answers that pre-flight GET with the same 404 Route_NotFound, so the SDK stops before it sends anything. The schema route here is GET /v1/tools/{slug}.
Reads a bare body: successful, data and error at the top level.Answers {data, meta}. The tool's own result is nested one level down, as data.successful, data.data and data.error, and meta carries request_id and vocabulary_version.

Two things already match, so they need no work. A project key is the credential your software uses to run tools for one project. The credential is the same ak_ project key: send it as Authorization: Bearer, and the x-api-key header of the Composio SDK is accepted too. The request body is the same: arguments and user_id are required, connected_account_id is optional, and version is accepted and ignored.

A generated Composio client is not a supported caller

SambungAPI keeps what an application reads from a Composio answer: the name and the meaning of each field of the request body and of the tool result. It selects its own paths, and it adds fields, headers and routes when they help a developer. So a client that is generated from the Composio API description is not a supported caller. Send the plain HTTP request below.

Three routes moved to paths that SambungAPI selected. The old paths were removed: each one answers 404 with the slug Route_NotFound, and its suggested_fix names the path to call.

CallRemoved old pathPath
List the toolsGET /v1/tools/toolsGET /v1/tools
Read one toolGET /v1/tools/tools/{slug}GET /v1/tools/{slug}
Execute a toolPOST /v1/tools/tools/execute/{slug}POST /v1/tools/{slug}/execute

The plain-HTTP request

This is what the Playground shows, and it is the whole call:

curl -sS \
  "https://sabi.metatech.id/v1/tools/GMAIL_SEND_EMAIL/execute" \
  -H "Authorization: Bearer ak_xxxxxxxxxxxxxxxx" \
  -H "content-type: application/json" \
  -d '{
        "arguments": {
          "recipient_email": "someone@example.com",
          "subject": "Hi",
          "body": "Hello"
        },
        "user_id": "user-123",
        "connected_account_id": "ca_xxxxxxxx"
      }'

/docs/api has the same call in full: the response envelope, the error envelope, and the WhatsApp gateway send.

If you must keep the SDK object

Both generated Composio clients document a raw HTTP escape hatch for undocumented endpoints, and it still applies the client's base URL and API key. That reaches this server. It is the SDK's HTTP client, not the SDK's execute call: it goes around tools.execute, so the modifiers and the response schema of the SDK do not apply, and the response you read is this server's {data, meta} envelope.

The shapes below were read from the shipped client sources and were not executed against any server.

// TypeScript — raw client, verified shape; not executed
import Composio from "@composio/client";

const client = new Composio({ apiKey: "ak_xxxxxxxxxxxxxxxx", baseURL: "https://sabi.metatech.id" });

const envelope = await client.post("/v1/tools/GMAIL_SEND_EMAIL/execute", {
  body: {
    arguments: { recipient_email: "someone@example.com", subject: "Hi", body: "Hello" },
    user_id: "user-123",
    connected_account_id: "ca_xxxxxxxx", // optional
  },
});
// envelope.data.successful, envelope.data.data, envelope.data.error, envelope.meta.request_id

Send an X-Idempotency-Key header with each execute call, for example client.post(path, { body, headers: { "X-Idempotency-Key": key } }). The client repeats a failed call by itself, and with the same key a tool that changes data does not run twice.

The import is @composio/client, not @composio/core. The Composio class of @composio/core keeps its client protected, so the raw verb is not reachable through it.

# Python — raw client, verified shape; not executed
import httpx
from composio import Composio

composio = Composio(api_key="ak_xxxxxxxxxxxxxxxx", base_url="https://sabi.metatech.id")

response = composio.client.post(
    "/v1/tools/GMAIL_SEND_EMAIL/execute",
    cast_to=httpx.Response,
    body={
        "arguments": {"recipient_email": "someone@example.com", "subject": "Hi", "body": "Hello"},
        "user_id": "user-123",
        "connected_account_id": "ca_xxxxxxxx",  # optional
    },
)
envelope = response.json()  # envelope["data"]["successful"], envelope["meta"]["request_id"]

In Python the client attribute is public, so the SDK object you already hold is enough.

What this server does not do

It does not serve /api/v3.1/tools/{slug} or /api/v3.1/tools/execute/{slug} under any alias, and it does not answer the bare {successful, data, error} body on any route. One server carries one envelope. If your code branches on the top-level successful, move that read to data.successful.


Composio is a product of Sampark Inc. The name is used here only to identify the third-party SDK this page describes. SambungAPI is built and operated by Metatech ID (PT Trifidia Cipta Korpora) and is not affiliated with, endorsed by, or sponsored by Sampark Inc.