# 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.

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 does | What 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](/glossary#glossary-term-api-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.

| Call | Removed old path | Path |
| --- | --- | --- |
| List the tools | `GET /v1/tools/tools` | `GET /v1/tools` |
| Read one tool | `GET /v1/tools/tools/{slug}` | `GET /v1/tools/{slug}` |
| Execute a tool | `POST /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:

```bash
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](/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.

```ts
// 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
# 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.
