Summary and recommendation
ChurnZero exposes a single HTTP endpoint - https://analytics.churnzero.net/i - that handles all write operations (upsert, event tracking, delete) via HTTP GET with query parameters.
Authentication is a plain appKey passed as a query parameter on every request;
treat it as a secret and suppress full URL logging in any pipeline.
The API is write- and event-oriented: no bulk-read, no pagination, and no POST/PUT/PATCH/DELETE HTTP methods are documented.
Rate-limit thresholds and headers are not published;
contact ChurnZero support before building high-volume pipelines.
Integrating ChurnZero into an identity graph requires pairing accountExternalId and contactExternalId as the composite key - there is no standalone Contact identity without an Account anchor.
API quick reference
| Has user API | Yes |
| Auth method | API Key (appKey query parameter) |
| Base URL | Official docs |
| SCIM available | No |
| SCIM plan required | N/A |
Authentication
Auth method: API Key (appKey query parameter)
Setup steps
- Log in to ChurnZero as an Admin.
- Navigate to Admin > App Settings > API.
- Copy the appKey value shown on that page.
- Pass the appKey as a query parameter on every API request: ?appKey=YOUR_KEY.
User object / data model
| Field | Type | Description | On create | On update | Notes |
|---|---|---|---|---|---|
| accountExternalId | string | Unique identifier of the parent Account in your system. | required | required | Must match an existing Account record. |
| contactExternalId | string | Unique identifier of the Contact (end-user) in your system. | required | required | Used as the primary key for upsert operations. |
| string | Contact's email address. | recommended | optional | Used for matching and communication features. | |
| firstName | string | Contact's first name. | optional | optional | |
| lastName | string | Contact's last name. | optional | optional | |
| phone | string | Contact's phone number. | optional | optional | |
| title | string | Contact's job title. | optional | optional | |
| isUnsubscribed | boolean | Whether the contact is unsubscribed from communications. | optional | optional | |
| name | string | Account name (used on Account entity). | recommended | optional | Applies to Account entity, not Contact. |
| billingAddressLine1 | string | Account billing address line 1. | optional | optional | Account-level field. |
| arr | number | Annual Recurring Revenue for the Account. | optional | optional | Account-level field; drives health scoring. |
| renewalDate | date | Account renewal date. | optional | optional | Account-level field; ISO 8601 format. |
| customField.* | string|number|date|boolean | Custom attributes defined in ChurnZero admin. | optional | optional | Prefix custom attribute names as configured in the ChurnZero UI. |
Core endpoints
Upsert Contact (create or update)
- Method: GET
- URL:
https://analytics.churnzero.net/i - Watch out for: ChurnZero's API uses GET requests with query parameters for all write operations, including creates and updates.
Request example
GET /i?appKey=KEY&action=setAttribute&entity=Contact&accountExternalId=ACC1&contactExternalId=USR1&email=user@example.com&firstName=Jane
Response example
HTTP 200 OK
{"status":"success"}
Upsert Account
- Method: GET
- URL:
https://analytics.churnzero.net/i - Watch out for: Account must exist before associating Contacts; upsert creates it if absent.
Request example
GET /i?appKey=KEY&action=setAttribute&entity=Account&accountExternalId=ACC1&name=Acme+Corp&arr=50000
Response example
HTTP 200 OK
{"status":"success"}
Track Event
- Method: GET
- URL:
https://analytics.churnzero.net/i - Watch out for: eventDate must be ISO 8601; future dates are rejected.
Request example
GET /i?appKey=KEY&action=trackEvent&accountExternalId=ACC1&contactExternalId=USR1&eventName=Login&eventDate=2024-01-15T10:00:00Z
Response example
HTTP 200 OK
{"status":"success"}
Increment Attribute
- Method: GET
- URL:
https://analytics.churnzero.net/i - Watch out for: Only numeric custom attributes support increment; standard fields do not.
Request example
GET /i?appKey=KEY&action=incrementAttribute&entity=Contact&accountExternalId=ACC1&contactExternalId=USR1&attr_LoginCount=1
Response example
HTTP 200 OK
{"status":"success"}
Delete Contact
- Method: GET
- URL:
https://analytics.churnzero.net/i - Watch out for: Deletion is permanent; no soft-delete or recovery endpoint is documented.
Request example
GET /i?appKey=KEY&action=deleteContact&accountExternalId=ACC1&contactExternalId=USR1
Response example
HTTP 200 OK
{"status":"success"}
Delete Account
- Method: GET
- URL:
https://analytics.churnzero.net/i - Watch out for: Deleting an Account cascades to all associated Contacts and their event history.
Request example
GET /i?appKey=KEY&action=deleteAccount&accountExternalId=ACC1
Response example
HTTP 200 OK
{"status":"success"}
Rate limits, pagination, and events
Rate limits: ChurnZero's public documentation does not explicitly publish rate-limit thresholds or headers.
Rate-limit headers: No
Retry-After header: No
Rate-limit notes: No rate-limit tiers, headers, or Retry-After behavior are documented in official sources. Contact ChurnZero support for current limits.
Pagination method: none
Default page size: 0
Max page size: 0
Pagination pointer: Not documented
Webhooks available: No
Webhook notes: ChurnZero does not document outbound webhooks for user/contact lifecycle events in its public API documentation.
Alternative event strategy: Use ChurnZero's native integrations (Salesforce, HubSpot, Segment) or poll via the API for state changes.
SCIM API status
- SCIM available: No
- SCIM version: Not documented
- Plan required: N/A
- Endpoint: Not documented
Limitations:
- No SCIM provisioning is documented in official ChurnZero help center or developer docs.
- SSO via SAML is supported but does not include SCIM-based user provisioning/deprovisioning.
Common scenarios
Provisioning a new Contact requires an Account upsert first;
if the Account does not exist, the Contact write will fail or produce an orphaned record.
Profile updates use setAttribute with upsert semantics - omit unchanged fields, but note the API returns success even when contactExternalId is new, silently creating a record rather than erroring.
Deprovisioning is irreversible: deleteContact is permanent with no soft-delete or recovery endpoint, and deleteAccount cascades to all associated Contacts and their full event history.
Confirm both externalId values against your identity graph before issuing any delete call.
Provision a new user (Contact) on signup
- Ensure the parent Account exists by calling setAttribute on entity=Account with accountExternalId and name.
- Call setAttribute on entity=Contact with accountExternalId, contactExternalId, email, firstName, lastName.
- Optionally track a 'Signup' event via trackEvent to record the onboarding moment.
Watch out for: If the Account does not exist, the Contact upsert will fail or create an orphaned record. Always upsert the Account first.
Update user profile attributes
- Call setAttribute on entity=Contact with accountExternalId, contactExternalId, and only the fields that changed.
- Omit unchanged fields; setAttribute performs a partial update (upsert semantics).
Watch out for: There is no PATCH-style partial update confirmation; the API returns success even if the contactExternalId does not yet exist, creating a new record.
Deprovision a user on account cancellation
- Call deleteContact with accountExternalId and contactExternalId to remove the individual user.
- If the entire account is being removed, call deleteAccount with accountExternalId to cascade-delete all contacts.
Watch out for: Deletion is irreversible and cascades. Confirm the correct externalId values before calling delete; there is no undo or soft-delete endpoint.
Why building this yourself is a trap
The most common integration trap is assuming standard REST conventions apply. Every write - including deletes - is an HTTP GET, which means request logging, proxies, and CDN caches may inadvertently replay or suppress destructive operations.
Entity type strings ('Account', 'Contact') are case-sensitive, and custom attribute names must exactly match the strings configured in the ChurnZero admin UI; a mismatch returns success with no data written, making silent failures hard to detect. No official SDK exists, so all integrations are raw HTTP;
teams building against this API should implement their own idempotency and error-detection layer. Webhooks for contact lifecycle events are not documented, so downstream identity graph sync must be driven by your system of record pushing to ChurnZero, not the reverse.
Automate ChurnZero workflows without one-off scripts
Stitchflow builds and maintains end-to-end IT automation across your SaaS stack, including apps without APIs. Built for exactly how your company works, with human approvals where they matter.