# Hubspot Contacts

> Use when the user wants to search, read, create, update, delete, or otherwise manage HubSpot CRM contacts (people records, emails, leads, subscribers) via the `hubspot` command-line tool.

- **Type:** Skill
- **Install:** `agentstack add skill-dipankar-hubspot-cli-hubspot-contacts`
- **Verified:** Yes — security-reviewed for prompt injection and unsafe behavior
- **Seller:** [dipankar](https://agentstack.voostack.com/s/dipankar)
- **Installs:** 0
- **Category:** [Developer Tools](https://agentstack.voostack.com/c/developer-tools)
- **Latest version:** 0.1.0
- **License:** MIT
- **Upstream author:** [dipankar](https://github.com/dipankar)
- **Source:** https://github.com/dipankar/hubspot-cli/tree/main/assets/skills/hubspot-contacts

## Install

```sh
agentstack add skill-dipankar-hubspot-cli-hubspot-contacts
```

Requires the [AgentStack CLI](https://agentstack.voostack.com/docs/cli). Works with Claude Code, Cursor, and any MCP-compatible agent.

## About

# HubSpot Contacts (via `hubspot` CLI)

Drive HubSpot contact operations through the `hubspot` CLI. Every command emits a JSON envelope (`{"success": true, "data": ...}`) suitable for parsing.

## Prerequisite: authentication

The CLI reads `HUBSPOT_ACCESS_TOKEN` (a HubSpot private-app token) from the environment. If a command returns exit code 3 with `AUTH_ERROR`, tell the user:

```bash
export HUBSPOT_ACCESS_TOKEN=
```

Multi-account users can pass `--profile ` (reads `[profiles.]` from `~/.config/hubspot-cli/config.toml`).

## Canonical commands

| Intent | Command |
| --- | --- |
| List recent contacts | `hubspot crm contacts list --limit 10` |
| Paginate | `hubspot crm contacts list --limit 50 --after ` |
| Request extra properties | `hubspot crm contacts list --properties phone,company,lifecyclestage` |
| Get by ID | `hubspot crm contacts get 12345` |
| Create from flags | `hubspot crm contacts create --email jane@example.com --firstname Jane --lastname Doe` |
| Create from JSON | `hubspot crm contacts create --properties '{"email":"jane@x.com","lifecyclestage":"lead"}'` |
| Update | `hubspot crm contacts update 12345 --firstname Janet` |
| Delete (archive) | `hubspot crm contacts delete 12345 --yes` |
| Simple search | `hubspot crm contacts search --query "email:*@acme.com" --limit 25` |
| Filtered search | `hubspot crm contacts search --filter-groups '[{"filters":[{"propertyName":"lifecyclestage","operator":"EQ","value":"customer"}]}]'` |
| Batch create | `hubspot crm contacts batch-create --inputs '[{"properties":{"email":"a@x.com"}},{"properties":{"email":"b@x.com"}}]'` |
| Discover properties | `hubspot discover properties contacts` |

## Filter-group operators

Common `operator` values for `--filter-groups`: `EQ`, `NEQ`, `GT`, `GTE`, `LT`, `LTE`, `BETWEEN`, `IN`, `NOT_IN`, `HAS_PROPERTY`, `NOT_HAS_PROPERTY`, `CONTAINS_TOKEN`, `NOT_CONTAINS_TOKEN`. Filter groups are OR'd; filters within a group are AND'd.

## Default vs custom properties

Only `email`, `firstname`, `lastname` come back by default. For anything else (phone, company, `lifecyclestage`, `hs_lead_status`, `hubspot_owner_id`, custom properties) pass `--properties prop1,prop2,...`. Use `hubspot discover properties contacts` to list every valid property name.

## Output envelope

```json
{
  "success": true,
  "data": { "id": "12345", "properties": { "email": "...", "firstname": "..." } },
  "paging": { "next_cursor": "abc", "has_more": true }
}
```

List endpoints put an array in `data`. Pagination: when `paging.has_more` is true, call again with `--after `.

## Error codes (JSON `error.code`, exit code)

| Code | Exit | Action |
| --- | --- | --- |
| `AUTH_ERROR` | 3 | Tell the user to set `HUBSPOT_ACCESS_TOKEN` |
| `VALIDATION_ERROR` / `DUPLICATE_EMAIL` | 5 | Show `error.message`; fix input |
| `NOT_FOUND` | 6 | Contact ID doesn't exist or was archived |
| `RATE_LIMIT` | 7 | Back off using `error.retry_after_seconds` |
| `SERVER_ERROR` | 8 | Transient; retry once |

## Required scopes

- Read: `crm.objects.contacts.read`
- Write: `crm.objects.contacts.write`
- Search: `crm.objects.contacts.read`

## Tips for the agent

- Prefer `search` over `list` when the user describes a filter ("contacts in lifecycle stage customer"). `list` has no filtering.
- Always pass `--limit` when the user says "a few" / "some" to keep responses small.
- Use `--output json-pretty` only when showing the raw JSON to the user; use the default `json` when piping into `jq` or parsing.
- Never echo the access token back to the user.

## Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [dipankar](https://github.com/dipankar)
- **Source:** [dipankar/hubspot-cli](https://github.com/dipankar/hubspot-cli)
- **License:** MIT

Install and usage instructions live in the source repository linked above.

## Pricing

- **Free** — Free

## Security capabilities

Automated source analysis of v0.1.0 — what this tool can access:

- **Network access:** no
- **Filesystem access:** no
- **Shell / process execution:** no
- **Environment & secrets:** no
- **Dynamic code execution:** no

*"Yes" means the capability is present in the source — more access means more to trust, not that it is unsafe.*


## Versions

- **0.1.0** — security scan: passed — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/skill-dipankar-hubspot-cli-hubspot-contacts
- Seller: https://agentstack.voostack.com/s/dipankar
- Browse the marketplace: https://agentstack.voostack.com/browse

---
Listed on AgentStack — the marketplace for AI agent skills and MCP servers. Every listing is security-reviewed. Creators keep 70%.
