# Viewing logs

> Source: https://truto.one/docs/guides/logs/viewing-logs/

Pull up the log rows for one failed call, sync job run, or webhook delivery and see what the remote API returned. Truto logs every Unified and Proxy API call, every RapidBridge (sync job) run, every webhook delivery, and every call to a per-integrated-account MCP server. Read them under **Logs** in the dashboard, with `GET /log`, or with `truto logs`.

:::skip-reading{cli="truto logs --log-type unified_proxy_api --integrated-account-id <integrated_account_id> -o json" skill="truto-cli"}
:::

Logs are scoped to environments. The dashboard shows logs for the environment you have selected. An API token sees logs for its own environment only.

## Pick the log type

Each tab under **Logs** maps to one `log_type` value on the API.

| Dashboard tab | Page | `log_type` | What it records |
| --- | --- | --- | --- |
| **Unified and Proxy API** | `/logs/unified-proxy-api` | `unified_proxy_api` | Every Unified API and Proxy API request |
| **RapidBridge** | `/logs/rapidbridge` | `rapid_bridge` | Every step of a sync job run, including record errors and the failure reason of a failed run |
| **Webhook** | `/logs/webhook` | `webhook` | Every attempt to deliver a webhook to your endpoint |
| **MCP** | `/logs/mcp` | `mcp` | Every request to a per-integrated-account MCP server |
| (API and CLI only) | n/a | `sync_job_cron_trigger` | One row each time a sync job's cron schedule fires |

## Find the logs in the dashboard

Open **Logs** in the sidebar (`https://app.truto.one/logs`), pick a tab, set the filters, and click **Fetch logs**. Click a row to expand it, and click **Load more logs** at the bottom to fetch the next page.

| Tab | Filters | Columns |
| --- | --- | --- |
| **Unified and Proxy API** | **Integrated accounts**, **Request type** (**All**, **Unified API**, **Proxy API**), **From** / **To** | **Timestamp**, **Method**, **Status**, **Path**, **Integrated account** |
| **RapidBridge** | **Sync job runs**, **Integrated accounts**, **From** / **To** | **Timestamp**, **Event**, **Path**, **Sync Job Run**, **Integrated account** |
| **Webhook** | **Webhook ID**, **From** / **To** | **Timestamp**, **Status** (your endpoint's HTTP response code), **Webhook ID** |
| **MCP** | **Integrated accounts**, **MCP Servers**, **From** / **To** | **Timestamp**, **Method**, **Status**, **MCP Method**, **Tool Name**, **MCP Server ID**, **Integrated account** |

An expanded row shows every field the table has no room for. For a Unified or Proxy API call that includes the integration, the authentication method (**Truto UI**, **API Key**, or **RapidForm**), the API token ID, **Request Duration (ms)**, **Remote Fetch Duration (ms)**, and the log lines Truto wrote while handling the call. A call made by Truto support during an [impersonation session](/docs/guides/team-security/two-factor-and-passkeys) is marked **Called by Truto staff**.

You don't have to type IDs into the filters. Two shortcuts open the right tab already filtered:

- **One integrated account:** on the account's page, open the menu and choose **View logs**. This opens **Unified and Proxy API** filtered to that account.
- **One sync job run:** in **Sync jobs**, open a job's runs and choose **View logs** from a run's row menu or from the run's page. This opens **RapidBridge** filtered to that run.

## Query logs with the API

`GET /log` returns the same rows. `log_type` is required.

:::code-tabs

```bash label="cURL"
curl -G https://api.truto.one/log \
  -H "Authorization: Bearer <API token>" \
  --data-urlencode "log_type=unified_proxy_api" \
  --data-urlencode "log_type_filter[integrated_account_id]=<integrated_account_id>" \
  --data-urlencode "created_at[gt]=2026-11-01T00:00:00.000Z" \
  --data-urlencode "created_at[lt]=2026-11-02T00:00:00.000Z" \
  --data-urlencode "limit=50"
```

```bash label="CLI"
truto logs --log-type unified_proxy_api \
  --integrated-account-id <integrated_account_id> \
  --start 2026-11-01T00:00:00.000Z \
  --end 2026-11-02T00:00:00.000Z \
  --limit 50
```

```typescript label="TypeScript"
import TrutoApi from '@truto/truto-ts-sdk'

const trutoApi = new TrutoApi({ token: process.env.TRUTO_API_TOKEN })

const logTypeFilter: Record<string, string> = {
  integrated_account_id: '<integrated_account_id>',
}

const rows = await trutoApi.log
  .list({
    log_type: 'unified_proxy_api',
    log_type_filter: logTypeFilter,
    created_at: {
      gt: '2026-11-01T00:00:00.000Z',
      lt: '2026-11-02T00:00:00.000Z',
    },
    limit: 50,
  })
  .toArray()
```

```python label="Python"
from truto_python_sdk import TrutoApi

truto_api = TrutoApi(token="<API token>")

rows = await truto_api.logs.list(
    log_type="unified_proxy_api",
    log_type_filter={"integrated_account_id": "<integrated_account_id>"},
    created_at={
        "gt": "2026-11-01T00:00:00.000Z",
        "lt": "2026-11-02T00:00:00.000Z",
    },
    limit=50,
).to_array()
```

:::

The TypeScript and Python SDKs follow `next_cursor` for you, so `toArray()` and `to_array()` return every matching row across all pages.

The response holds a page of rows, newest first, and a cursor:

```json
{
  "result": [
    {
      "timestamp": "2026-11-01T14:03:11.412Z",
      "log_type": "unified_proxy_api",
      "request_type": "unified",
      "http_method": "GET",
      "http_status_code": 401,
      "http_url_details_path": "/unified/crm/contacts",
      "integrated_account_id": "1ba1f401-7183-47c5-9e39-e8e257e3c795",
      "integration": "hubspot",
      "resource": "contacts",
      "method": "list",
      "duration": 412,
      "fetch_duration": 380,
      "integrated_account_needs_reauth": true,
      "logs": ["..."]
    }
  ],
  "next_cursor": "MjAyNi0xMS0wMVQxNDowMzoxMS40MTJa"
}
```

### Query parameters

| Parameter | Notes |
| --- | --- |
| `log_type` | Required. One of `unified_proxy_api`, `rapid_bridge`, `webhook`, `mcp`, `sync_job_cron_trigger`. |
| `created_at[gt]`, `created_at[lt]` | ISO 8601 timestamps. If you send `created_at[gt]`, you must also send `created_at[lt]`, and the range can't be longer than one month. `created_at[lt]` defaults to now. |
| `limit` | Rows per page. Default and maximum: `100`. |
| `next_cursor` | The `next_cursor` from the previous page. Send it with the same filters. It is `null` when there are no more rows. |
| `log_type_filter[...]` | Filters that depend on the log type. See the table below. Send an array (`log_type_filter[integrated_account_id][]=a&log_type_filter[integrated_account_id][]=b`) to match any of several values. |

| `log_type` | `log_type_filter` keys |
| --- | --- |
| `unified_proxy_api` | `integrated_account_id`, `request_type` (`unified` or `proxy`), `integration` |
| `rapid_bridge` | `integrated_account_id`, `sync_job_id`, `sync_job_run_id`, `sync_job_run_event`, `webhook_id`, `integration` |
| `webhook` | `integrated_account_id`, `webhook_id`, `event`, `integration` |
| `mcp` | `integrated_account_id`, `mcp_server_id`, `mcp_method`, `tool_name`, `resource`, `method`, `client_name`, `client_version`, `request_id`, `integration` |
| `sync_job_cron_trigger` | None besides the environment |

The CLI flags map onto these keys: `--integrated-account-id`, `--sync-job-id`, `--sync-job-run-id`, `--webhook-id`, `--mcp-server-id`, `--integration`, and `--event`. Add `-o json` to get every field instead of the table columns.

## Find the cause of a failure

**A Unified or Proxy API call failed.** Filter by the integrated account and look at `http_status_code`. If `integrated_account_needs_reauth` is `true`, the account's credentials need refreshing. See [Reauthorizing connections](/docs/guides/integrated-accounts/reauthorizing-connections). The `logs` array holds the messages Truto wrote while handling the call.

**A sync job run failed.** Filter `rapid_bridge` logs by the run. `sync_job_run_event` carries the outcome of each row. Look for `failed` (the run's failure reason is logged here) and `record_error`:

:::code-tabs

```bash label="cURL"
curl -G https://api.truto.one/log \
  -H "Authorization: Bearer <API token>" \
  --data-urlencode "log_type=rapid_bridge" \
  --data-urlencode "log_type_filter[sync_job_run_id]=<sync_job_run_id>"
```

```bash label="CLI"
truto logs --log-type rapid_bridge --sync-job-run-id <sync_job_run_id> -o json
```

:::

**A webhook delivery failed.** Filter `webhook` logs by `webhook_id`, or by `event` to match one event type such as `integrated_account:active`. Rows for a failed delivery have `status: "error"`. `webhook_endpoint_status` is the HTTP code your endpoint returned, and it's absent when Truto couldn't get a response at all. `method` is `deliver` for the first attempt and `alarm` for a retry. [Webhooks overview](/docs/guides/webhooks/overview) explains which responses are retried.

**An MCP call failed.** Filter `mcp` logs by `mcp_server_id` and `tool_name`. Each row carries `mcp_method` (for example `tools/call`), `http_status_code`, and the client's `client_name`. See [MCP servers for an integrated account](/docs/guides/integrated-accounts/mcp-servers).

## See the raw remote response for a Unified API call

Add `truto_response_format=debug` to a Unified API request. The response then includes a `debug` object next to `result`. It holds the request Truto sent to the integration (`requestUrl`, `requestOptions`), the integration's raw response body (`data`), and its response headers (`responseHeaders`). Use it to check whether a wrong value comes from the integration or from the mapping.

```bash
curl "https://api.truto.one/unified/crm/contacts?integrated_account_id=<integrated_account_id>&truto_response_format=debug" \
  -H "Authorization: Bearer <API token>"
```

`debug` is `null` when Truto answered without calling the integration. Responses that aren't JSON, such as file downloads, return `400` in debug mode.

## Next

To keep logs in your own tooling, forward them to Datadog, Splunk, or another destination with [log forwarding](/docs/guides/observability/log-forwarding). For webhook retries and signatures, see [Webhooks overview](/docs/guides/webhooks/overview).
