> ## Documentation Index
> Fetch the complete documentation index at: https://docs.squasher.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Connectors API

> List the connector catalog, plan a connection, connect, verify one page, and disconnect.

Connectors pull vendor audit logs into Squasher. See [Connectors](https://docs.squasher.ai/integrations/connectors.md) for the
setup steps. Fields use snake\_case.

## Operations

| Operation | Method and path | Access | Purpose |
| - | - | - | - |
| `connectors.list` | `GET /v1/projects/{project_id}/connectors` | `providers:read` | List the connector catalog and the project's connections. |
| `connectors.get` | `GET /v1/projects/{project_id}/connectors/{connector_id}` | `providers:read` | Params, secrets, scopes, endpoints, schedule, and rate limit. |
| `connections.list` | `GET /v1/projects/{project_id}/connections` | `providers:read` | List connections and their status. |
| `connections.get` | `GET /v1/projects/{project_id}/connections/{connection_id}` | `providers:read` | One connection. Secrets are never returned. |
| `connections.plan` | `POST /v1/projects/{project_id}/connections/plan` | `providers:write` | Preview scopes, endpoints, egress, and cost. Writes nothing. |
| `connections.create` | `POST /v1/projects/{project_id}/connections` | `providers:write` | Verify one page, store the secrets, and start polling. |
| `connections.verify` | `POST /v1/projects/{project_id}/connections/{connection_id}/verify` | `providers:write` | Pull one page, map it to OCSF, and return samples. Stores nothing. |
| `connections.delete` | `DELETE /v1/projects/{project_id}/connections/{connection_id}` | `providers:write` | Stop polling and delete the secrets. Cannot be undone. |

## Plan a connection

```bash theme={null}
curl --request POST \
  --url "https://api.squasher.ai/v1/projects/$SQUASHER_PROJECT_ID/connections/plan" \
  --header "x-squasher-key: $SQUASHER_API_KEY" \
  --header "content-type: application/json" \
  --data '{"connector_id": "okta.system_log", "params": {"okta_domain": "acme.okta.com"}}'
```

```json theme={null}
{
  "dry_run": true,
  "connector_id": "okta.system_log",
  "params": { "okta_domain": "acme.okta.com" },
  "secrets_required": ["client_id", "private_key"],
  "scopes": ["okta.logs.read"],
  "endpoints": [
    { "method": "POST", "purpose": "token", "url": "https://acme.okta.com/oauth2/v1/token" },
    { "method": "GET", "purpose": "data", "url": "https://acme.okta.com/api/v1/logs" }
  ],
  "egress_origins": ["https://acme.okta.com"],
  "cost": {
    "polls_per_hour": 60,
    "estimated_requests_per_hour": 120,
    "max_requests_per_hour": 3060,
    "billed_as": "logs"
  },
  "warnings": ["The first pull reads up to 7d of history"],
  "setup_supported": true,
  "aws_role": null
}
```

For an `aws_role` connector, `aws_role` holds the `external_id` that Squasher issued for this
project and connector, the `trust_principal` that the role trust policy must allow
(`arn:aws:iam::381347172594:root`, the Squasher AWS account), and the `trust_policy_condition` for
the role trust policy. Send the role ARN in the `role_arn` param.

## Connect

```bash theme={null}
curl --request POST \
  --url "https://api.squasher.ai/v1/projects/$SQUASHER_PROJECT_ID/connections" \
  --header "x-squasher-key: $SQUASHER_API_KEY" \
  --header "content-type: application/json" \
  --header "Idempotency-Key: 4f6c1b2e-8d3a-4c5f-9e7b-1a2b3c4d5e6f" \
  --data @connection.json
```

`connection.json` holds `connector_id`, `params`, and `secrets` (secret values by name, from
`connectors.get`). Squasher pulls one page first. The response is `201` with the connection and its
`verification` when the page is good. When the vendor refuses the request, the response is `422`
with `status: "failed"` and the `verification` error, and Squasher stores nothing. Add
`?dry_run=true` to get the plan instead.

| Status | Meaning |
| - | - |
| `200` | Dry run plan, or a retry with the same `Idempotency-Key` and request. |
| `201` | Connected and verified. |
| `400` | A param or a secret is missing or does not match. |
| `409` | The project already has a connection of this connector. |
| `422` | Verification failed, or the `Idempotency-Key` was used with another request. |

## Verify

`POST .../connections/{connection_id}/verify` pulls one page with the stored secrets. The response
has `ok`, the number of `records`, up to three `sample` records (`uid`, `time`, raw `body`), and
`error` (`class` and `message`) when the pull fails. Verify sends nothing to your project and does
not move the cursor.

`mapping` holds the page mapped to OCSF by the connector mapping, the same mapping that runs on
ingest. Nothing is stored.

| Field | Meaning |
| - | - |
| `status` | `mapped`, `unavailable` (the mapping service did not answer; not a failure), or `error`. |
| `reason` | Why the status is `unavailable` or `error`. |
| `records` | Up to five records: `status`, the `ocsf.*` `attributes` (or `squasher.mapping.error`), and the record coverage. |
| `coverage.coverage` | Mean coverage of the required OCSF attributes, from 0 to 1. |
| `coverage.classes` | Per OCSF class: `class_uid`, `name`, `events`, `ratio`, `complete`, and the `missing` attributes. |

```json theme={null}
"mapping": {
  "status": "mapped",
  "reason": null,
  "connector_version": "9a06ebe4a76d",
  "records": [
    {
      "status": "mapped",
      "attributes": { "ocsf.class_uid": 3002, "ocsf.activity_id": 1, "ocsf.status_id": 1 },
      "coverage": { "class_uid": 3002, "required": 9, "satisfied": 9, "ratio": 1, "missing": [] }
    }
  ],
  "coverage": {
    "coverage": 1,
    "records": 1,
    "mapped": 1,
    "dropped": 0,
    "errors": 0,
    "classes": [
      { "class_uid": 3002, "name": "Authentication", "events": 1, "ratio": 1, "complete": 1, "missing": [] }
    ]
  }
}
```

## Disconnect

```bash theme={null}
curl --request DELETE \
  --url "https://api.squasher.ai/v1/projects/$SQUASHER_PROJECT_ID/connections/$CONNECTION_ID" \
  --header "x-squasher-key: $SQUASHER_API_KEY" \
  --header "Idempotency-Key: 9b1d2c3e-4f5a-4b6c-8d7e-0f1a2b3c4d5e"
```

The `Idempotency-Key` header is required. With `?dry_run=true`, the response lists the secrets that
would be deleted and whether polling would stop, and nothing changes.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.