Export business data with Composio: HubSpot contacts to CSV and JSON
Download a bounded HubSpot export example using Composio Proxy, with pagination, CSV, JSONL and completion checks. Choose Combined for maintained business-data SQL.
Choose Combined when your agent needs maintained business datasets and repeatable cross-app SQL. If you already use Composio and need a one-off contact export, this guide gives you a runnable Python example: retrieve HubSpot records through an explicitly selected connection, follow pagination and save CSV, JSONL and a completion manifest. Try the included synthetic sample without an account, then configure your own connection for a live run.
Choose the data path for the answer you need
Start with Combined for recurring business questions. It syncs selected business records into managed storage and exposes read-only SQL through MCP. Use the export below when a local file from an existing Composio connection is the immediate deliverable. The distinction is who maintains the data after today's extraction.
| Your job | Recommended start | What you deliver |
|---|---|---|
| Repeat a CRM and billing question every week | Combined | Maintained datasets, explicit mapping and reusable SQL. |
| Export contact records through an existing Composio connection | This Python example | A bounded local extract with coverage and completion recorded. |
| Let an agent discover and perform app operations | Evaluate Composio sessions | Scoped tools and execution, with the required account selected. |
Read our Composio review for the operating responsibilities, or compare Composio alternatives before choosing the platform. This tutorial focuses on retrieving provider records, rather than listing connected accounts.
1. Download and run the account-free sample
Save the Python exporter and synthetic two-page fixture in the same folder. Python 3.10 or later is enough; the script uses the standard library. The optional README explains the files and error codes.
python3 composio-hubspot-export.py --out sample-exportThe sample prints this summary and creates a new output folder:
{"mode":"fixture","pages":2,"received_records":3,
"unique_records":3,"complete":true,"reason":"end_of_listing"}records.jsonl: the accepted records in receipt order, preserving original values.contacts.csv: selected fields, with one row per contact ID.manifest.json: API version, selection, counts, limits, next cursor and completion reason.
All three contacts are invented. This run makes no network request. It lets you inspect punctuation, Unicode, a large string ID and missing values before using the same exporter with your own connection. Choose a new folder for every run: the script refuses to overwrite an existing output directory.
2. Select the HubSpot account and retrieval contract
In Composio, identify the connected account for the HubSpot portal you intend to read. Confirm its contact read permissions and selected fields. Use an explicit account ID, especially when more than one portal is connected. HubSpot describes its permission model in the scope guide.
Composio's HubSpot toolkit lists HUBSPOT_LIST_CONTACTS and HUBSPOT_LIST_DEALS. If you use a catalog tool, inspect its input/output schema and pin the version your parser expects. The public catalog showed version 20260915_00 on September 17; it is an observed catalog version, not a live execution result.
GET /api/v3.1/tools/HUBSPOT_LIST_CONTACTS?version=20260915_00The tool metadata endpoint returns the schema and version information. Use your project key in the request header. Read the current versioning rules before switching between SDK or REST examples.
The download takes the documented Proxy route so its parser can follow HubSpot's published response contract directly. It pins the provider API path below; it does not execute a versioned catalog tool or ask an LLM to invent the arguments.
3. Retrieve active contacts through Composio Proxy
Set COMPOSIO_API_KEY and HUBSPOT_CONNECTED_ACCOUNT_ID in your environment or secret manager. Then explicitly opt into the live request:
python3 composio-hubspot-export.py --live \
--out my-contact-export --max-pages 10 --max-records 500The Composio API receives a POST at /api/v3.1/tools/execute/proxy. Its body asks for a HubSpot GET:
{
"connected_account_id": "YOUR_HUBSPOT_CONNECTED_ACCOUNT_ID",
"method": "GET",
"endpoint": "https://api.hubapi.com/crm/objects/2026-09/contacts?limit=50&archived=false&properties=firstname%2Clastname%2Cemail%2Ccreatedate%2Clastmodifieddate"
}Composio injects the selected provider credentials. Its proxy response includes the upstream status and parsed data. The exporter requires successful transport and an upstream 200 before reading data.results. See the request contract and proxy behavior.
The example is free to download. Live execution uses your service account and can incur provider or Composio usage charges. Our published validation uses synthetic responses; the current account permissions and live provider response are checks for your own run.
4. Check completion before using the export
HubSpot's contacts listing returns results and, when another page exists, paging.next.after. The exporter carries that opaque cursor into the next request to the fixed provider endpoint. An empty page with a next cursor still requires another read.
| Manifest result | Meaning | Your next step |
|---|---|---|
complete: true | The selected listing ended normally. | Check the requested scope and sample records before analysis. |
configured_limit | A page or received-record cap stopped a partial export. | Review the next cursor and rerun with suitable bounds in a new folder. |
| Authentication or upstream error | The export stopped; accepted earlier pages remain available. | Check the account, permissions and provider status. |
| Cursor or response-shape error | The contract needs investigation before continuing. | Inspect the current API/schema and adapt the parser deliberately. |
Our implementation validates and flushes each page before advancing its manifest. It rejects repeated cursors and redirects, and bounds transient retries to three attempts. Defaults are 10 pages and 500 received records, with hard caps of 100 pages and 5,000 records. Duplicate records count toward the cap. It records a checkpoint but does not implement automatic resume.
CSV keeps the last observed record per ID. Null and missing values become empty cells; formula-like text receives a leading apostrophe for spreadsheet import. JSONL keeps original values and duplicates. Completion applies to active contacts and selected current properties. Associations, archived records and property history require separate selection, and a changing portal is not a fixed snapshot.
5. Move the recurring question to Combined
Choose Combined when tomorrow's answer should use maintained data instead of another file run. Connect HubSpot, select the available datasets and confirm their schema and successful sync. Give your agent the intended Source grants through MCP. The HubSpot setup guide walks through that path.
Authorize HubSpot in Combined separately. The local export is useful for inspecting fields and validating the question; it does not transfer Composio's OAuth grant or automatically load these files into Combined. If the goal is CRM plus billing, preserve a maintained company-to-customer map and aggregate each side before joining. Follow the HubSpot–Stripe worked answer.
Set a freshness requirement for each question, check it with the free freshness checker, and keep the client handoff in the FDE delivery guide. You can also use our business-data planner to choose the first Sources for your agent.
The downloadable adapter and writer passed local tests for request construction, pagination, partial failure, duplicate handling and output files. That establishes the example's tested behavior; it is not a benchmark of a connected customer account. Start with the sample, then make the deployment choice around the data you want maintained.
Sources and further reading
Explore the documentation behind this guide. Product details checked on September 17, 2026.
- Combined MCP tools and Source grants
- Combined SQL interface
- Combined connector availability
- Combined pricing and MAR
- Composio API overview
- Composio Proxy request
- Composio tools and proxy behavior
- Composio HubSpot toolkit
- Composio tool schemas
- Composio toolkit versioning
- HubSpot contact listing
- HubSpot permission scopes