We’re migrating our integration from XMLRPC to the REST API (v2 where possible, falling back to v1 where needed). The migration is going well, but we’ve identified several areas where v2 doesn’t yet have equivalent endpoints, forcing us to mix v1 and v2 calls. We wanted to flag these in case v2 additions are planned, and to ask one question about authentication.
Endpoints where we’re falling back to REST v1:
- Opportunities by contact — No way to filter opportunities by contact_id in v2. We’re using GET /v1/opportunities?contact_id={id}.
- Pipeline stages — No v2 endpoint for pipeline stage definitions. We’re using GET /v1/opportunity/stage_pipeline.
- Users — No v2 endpoint for user lookup. We’re using GET /v1/users and GET /v1/users/{id}.
- Email opt-in — The v2 PATCH /v2/contacts/{id} doesn’t accept opt_in_reason as a top-level field. We’re using PATCH /v1/contacts/{id} with opt_in_reason to opt in contacts. There also doesn’t appear to be any REST endpoint (v1 or v2) for opting out a contact — the old XMLRPC APIEmailService.optOut was the only way to do this.
- Contact create with duplicate_option — The v2 POST /v2/contacts doesn’t support the duplicate_option parameter that v1 had (Email, EmailAndName, etc.). We’ve implemented a search-then-create pattern as a workaround, but native duplicate handling would be cleaner.
- Custom field filtering — v2 contact filters support email, given_name, family_name, company_id, etc., but there’s no way to filter contacts by custom field values. This isn’t blocking for us currently, but we wanted to mention it.
v2 behavior note — custom_fields on PATCH
We discovered that PATCH /v2/contacts/{id} treats the custom_fields array as a full replacement — any field not included in the array is removed from the contact. The old XMLRPC update was a merge (only specified fields were changed). We’ve worked around this with a read-merge-write pattern (GET current fields, merge our updates, PATCH the complete array), but wanted to confirm this is the intended behavior and not a bug.
I’ve attempted to create a ticket with this info twice, but after submission, no ticket is generated.