Skip to content

fix(hubspot): correct list membership requests - #446

Merged
Shubhank-Jonnada merged 2 commits into
masterfrom
sj/445-hubspot-list-membership-20260820-1341
Aug 20, 2026
Merged

fix(hubspot): correct list membership requests#446
Shubhank-Jonnada merged 2 commits into
masterfrom
sj/445-hubspot-list-membership-20260820-1341

Conversation

@Shubhank-Jonnada

@Shubhank-Jonnada Shubhank-Jonnada commented Aug 20, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Requests the HubSpot crm.lists.write scope required by add_contact_to_list.
  • Sends the documented JSON array of contact IDs to the v3 list-membership endpoint.
  • Aligns the action output schema and tests with HubSpot's documented record-ID arrays.
  • Documents static-list limitations, reconnection requirements, and live-test configuration.
  • Bumps the HubSpot integration from 2.2.1 to 3.0.0 because the corrected output contract is a breaking schema change.

Closes #445.

Why

The action previously requested only crm.lists.read and sent { "recordIds": [...] }. HubSpot requires crm.lists.write and documents the body as a raw array of record IDs, so the action failed at authorization and would then have sent an incompatible request shape.

HubSpot API reference

Flow

flowchart LR
    A["add_contact_to_list"] --> B["PUT /crm/v3/lists/{listId}/memberships/add"]
    B --> C["JSON body: array of contact IDs"]
    C --> D["HubSpot validates crm.lists.write"]
    D --> E["Manual or snapshot list updated"]
Loading

Verification

  • python -m pytest hubspot -q — 281 passed.
  • HubSpot structure validation passed; only the existing oauth and content heuristic warning remains.
  • Code, lint, format, security, dependency audit, config sync, and fetch-pattern checks passed.
  • Version check passes with the recommended major bump: 2.2.13.0.0.
  • README checks passed.
  • Added an opt-in destructive live test; it skips without configured HubSpot test credentials and was not executed against a live account locally.

Rollout

The platform OAuth provider must also include crm.lists.write (Autohive PR #5556). Existing HubSpot connections must reconnect after both changes are deployed.

Author commitment

  • Verified the endpoint, request body, response fields, scope, and list-type limitation against HubSpot's official documentation.
  • Added meaningful mocked regression coverage and an opt-in live integration test.
  • Ran the repository's local validation, code-quality, test, README, and version checks.
  • Updated user and maintainer documentation.

@github-actions

github-actions Bot commented Aug 20, 2026

Copy link
Copy Markdown

🔍 Integration Validation Results

Commit: 0a16616eb2f8f61719bd04a96b653fdcfb7d8d9d · fix(hubspot): use major version for output contract
Changed directories: hubspot

Check Result
Structure ⚠️ Passed with warnings
Code ⚠️ Passed with warnings
Tests ✅ Passed
README ✅ Passed
Version ✅ Passed
⚠️ Structure Check output
Validating 1 integration(s)...

============================================================
Integration: hubspot
============================================================

Warnings (1):
  ⚠️ Potentially unused scopes (please verify): oauth, content

============================================================
SUMMARY
============================================================
Integrations validated: 1
Total errors: 0
Total warnings: 1

⚠️ Validation passed with warnings - please review
⚠️ Code Check output
----------------------------------------
Checking: hubspot
----------------------------------------

🐍 Checking Python syntax...
   ✅ Syntax OK

📥 Checking imports...
   ✅ Imports OK

📄 Checking JSON files...
   ✅ JSON files OK

🔍 Linting with ruff...
   ✅ Lint OK

🎨 Checking formatting with ruff...
   ✅ Formatting OK

🔒 Scanning for security issues with bandit...
   ✅ Security OK

🛡️ Checking dependencies for vulnerabilities with pip-audit...
   ✅ Dependencies OK

🔗 Checking config-code sync...
   ⚠️ Existing integration has config-code input drift; treating as historic warning
   ⚠️ Action 'create_note': parameter 'associations' accessed in code but not defined in input_schema
   ⚠️ Action 'create_contact': parameter 'properties' is required in schema but accessed with inputs.get() (safe for missing)
   ⚠️ Action 'update_contact': parameter 'properties' is required in schema but accessed with inputs.get() (safe for missing)
   ⚠️ Action 'search_contacts': parameter 'query' is required in schema but accessed with inputs.get() (safe for missing)
   ⚠️ Action 'add_ticket_comment': parameter 'is_public' defined in input_schema but never accessed in code
   ⚠️ Action 'create_company': parameter 'properties' is required in schema but accessed with inputs.get() (safe for missing)
   ⚠️ Action 'update_company': parameter 'properties' is required in schema but accessed with inputs.get() (safe for missing)
   ⚠️ Action 'search_companies': parameter 'query' is required in schema but accessed with inputs.get() (safe for missing)
   ⚠️ Action 'get_deals': parameter 'after' accessed in code but not defined in input_schema
   ⚠️ Action 'search_deals': parameter 'after' accessed in code but not defined in input_schema
   ⚠️ Action 'search_deals': parameter 'max_total' accessed in code but not defined in input_schema
   ⚠️ Action 'search_deals': parameter 'year' accessed in code but not defined in input_schema
   ⚠️ Action 'search_deals': parameter 'fetch_all' accessed in code but not defined in input_schema
   ⚠️ Action 'create_deal': parameter 'properties' is required in schema but accessed with inputs.get() (safe for missing)
   ⚠️ Action 'update_deal': parameter 'properties' is required in schema but accessed with inputs.get() (safe for missing)
   ⚠️ Action 'get_lists': parameter 'include_filters' defined in input_schema but never accessed in code
   ⚠️ Action 'get_marketing_emails': parameter 'archived' accessed in code but not defined in input_schema
   ⚠️ Action 'get_marketing_emails': parameter 'status' defined in input_schema but never accessed in code
   ⚠️ Action 'get_marketing_emails': parameter 'name' defined in input_schema but never accessed in code
   ⚠️ Action 'get_campaign_assets': parameter 'end_date' accessed in code but not defined in input_schema
   ⚠️ Action 'get_campaign_assets': parameter 'start_date' accessed in code but not defined in input_schema
   ⚠️ Action 'get_campaign_performance': parameter 'end_date' accessed in code but not defined in input_schema
   ⚠️ Action 'get_campaign_performance': parameter 'start_date' accessed in code but not defined in input_schema
   ✅ Config-code sync OK

🔄 Checking fetch patterns...
   ✅ Fetch patterns OK

========================================
✅ CODE CHECK PASSED
========================================
✅ Tests Check output
Integration      Tests  Coverage        Status
----------------------------------------------
hubspot        281/281       88%      ✅ Passed
----------------------------------------------
Total          281/281            ✅ All passed

✅ Tests passed: hubspot
✅ README Check output
========================================
✅ README CHECK PASSED
========================================
✅ Version Check output
✅ hubspot: 2.2.1 → 3.0.0 (major bump)

========================================
✅ VERSION CHECK PASSED
========================================

@Shubhank-Jonnada
Shubhank-Jonnada requested review from NinosMan, ProRedCat and TheRealAgentK and removed request for TheRealAgentK August 20, 2026 02:04
@Shubhank-Jonnada
Shubhank-Jonnada merged commit 5db6e16 into master Aug 20, 2026
4 checks passed
@Shubhank-Jonnada
Shubhank-Jonnada deleted the sj/445-hubspot-list-membership-20260820-1341 branch August 20, 2026 02:08
@Shubhank-Jonnada

Copy link
Copy Markdown
Contributor Author

Local verification has been completed. All locally covered HubSpot actions are passing, and the live list-membership write succeeded.

Local test results

Check Result
Full HubSpot test suite 281 passed
Contact and list action tests 39 passed
Integration structure validation Passed
Syntax, imports, JSON, lint, formatting and security checks Passed
Version and README checks Passed

Live result snapshot

Step Result
List validation Manual list found and ready
Contact validation Existing sample contact found
crm.lists.write authorization Passed; no MISSING_SCOPES response
Add contact to list Contact successfully added
Membership verification Contact confirmed in the manual list

The live write confirmed that the scope and array request payload are correct. HubSpot omitted empty arrays from the successful response, which exposed a separate output-schema validation edge case; that follow-up is addressed in #448.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fix(hubspot): correct list membership permissions and payload

2 participants