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

# CRM

> Read CRM records and add notes with approval

Three read-only tools use a [connection](/api-reference/connections/overview) to Salesforce or HubSpot:

* `POST /v1/tools/crm/accounts` (`crm_accounts`)
* `POST /v1/tools/crm/contacts` (`crm_contacts`)
* `POST /v1/tools/crm/opportunities` (`crm_opportunities`)

Select `connection_id` from `GET /v1/connections`, by `system` and `account_label`.

Reads use `connected_systems` grants and payment headers. Nothing fetched is stored or logged; receipts contain identifiers and record counts only.

## Input

| Field | Meaning |
| - | - |
| `connection_id` | Required connection UUID. |
| `query` | Case insensitive literal name contains. |
| `updated_since` | Updated on or after this ISO calendar date, `YYYY-MM-DD`, at midnight UTC. |
| `limit` | Integer from 1 to 100, default 25. |
| `cursor` | Previous `next_cursor`; keep the connection and filters unchanged. |
| `account_id` | Contacts and opportunities only: associated account id. |
| `status` | Opportunities only: `open`, `won`, `lost` or `all` (default). |

```json theme={null}
{
  "connection_id": "5f4a3b2c-1d0e-4f9a-8b7c-6d5e4f3a2b1c",
  "query": "Example",
  "updated_since": "2026-10-01",
  "limit": 25
}
```

## Output

Each record carries `source: { system, id }`. No `next_cursor` means finished.

```json theme={null}
{ "success": true, "data": { "records": [], "receipt_id": "...", "next_cursor": "..." } }
```

| Read | Record fields |
| - | - |
| Accounts | `id`, `name`, `domain`, `industry`, `owner`, `updated_at`, `source` |
| Contacts | `id`, `name`, `title`, `email`, `phone`, `account: { id, name }`, `updated_at`, `source` |
| Opportunities | `id`, `name`, `account: { id, name }`, `stage`, `status`, `amount`, `currency`, `close_date`, `owner`, `updated_at`, `source` |

Missing fields are null. Owner/stage are system identifiers. Status follows closed/won flags. HubSpot accounts/opportunities are companies/deals. Associated company: requested, otherwise primary, otherwise lexically lowest id.

HubSpot filters each page by name. Empty pages can have `next_cursor`; continue. Beyond 10,000 records, narrow `updated_since` or `account_id`.

## Errors

Refusals precede payment: another agent’s connection returns `404 connection_not_found`; wrong system, `400 connection_wrong_system`; inactive connections, `409`; unavailable systems, `503 not_configured`. Cursor/limit refusals: `400 unsupported_for_system` or `not_supported`. Busy/failed reads: `503 rate_limited` or `system_unavailable`; expired sign-in: `409 connection_expired`. Failed paid reads return account credit.

## Write a note

`POST /v1/tools/crm/notes` (`crm_notes_create`) needs approval unless an enabled agent policy allows it. Send payment headers and `Idempotency-Key`. After approval, retry unchanged with `X-Approval-Id`. Same-key retries return the original note without writing again.

`body` is plain text, 1 to 5,000 characters.

`connection_scope_missing` means use console Reconnect to grant writing permission. `write_outcome_unknown` means inspect the CRM before using another key.

`created_at` is the UTC dispatch time. Only the approval record retains the note body. See [Pricing](/pricing).

```json theme={null}
{
  "connection_id": "5f4a3b2c-1d0e-4f9a-8b7c-6d5e4f3a2b1c",
  "record": { "type": "contact", "id": "101" },
  "body": "Customer requested a follow-up."
}
```

`record.type`: `account`, `contact` or `opportunity`.

```json theme={null}
{ "success": true, "data": { "id": "501", "created_at": "2026-10-17T12:00:00.000Z", "source": { "system": "hubspot", "id": "501" } } }
```


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