Overview
The Neon CRM connector extracts objects from the Neon CRM v2 REST API and lands them in your data lake. It discovers the set of streams and their schemas from an internal mapping and then, for each stream, lists all record IDs via the collection endpoint and fetches each record by ID. The run model is full-replace per stream: every sync re-reads all IDs for the selected streams and rewrites their rows. There is no incremental windowing or delete propagation in this connector.
Authentication & Setup
Provide:
Organization ID (
org_id)API Key (
api_key)
Requests use HTTP Basic authentication with org_id as the username and api_key as the password against the base URL https://api.neoncrm.com/v2. The built-in Test action validates credentials by calling /accounts with a 1-row page.
Sync Strategy
Discovery
The connector loads a table map from an internal schema provider and exposes those streams for discovery and sync.
For each selected stream, the connector emits the schema (field names and types) and unique keys derived from the stream’s
indexes.
Full-replace extraction
For each stream in the active catalog:
Emit schema & keys (from the table map).
List all record IDs for the stream using either:
GET /{table}with pagination, orGET /accounts/{accountId}/{table}for tables that require an account context (see “Account-scoped streams” below).
Fetch each record by ID via
GET /{table}/{id}(or the account-scoped path) and write it.Emit a
record_countmetric for the stream.
This results in a complete refresh of the stream’s rows each run. There are no incremental bookmarks and the connector does not emit deletes.
Account-scoped streams
Some listing endpoints require an Account ID (e.g., patterns like /accounts/{accountId}/memberships). For those streams, the connector:
First fetches all account IDs, combining individual and company accounts from
/accounts?userType=INDIVIDUALand/accounts?userType=COMPANY.Then enumerates the child records per account via
/accounts/{accountId}/{table}and aggregates all child IDs before fetching details.When fetching a single account record by ID, the response shape is normalized from either
individualAccountorcompanyAccount.
Special handling: Custom fields
For the customFields stream, the listing API requires a category query param. The connector loops over the categories:
Account, Donation, Event, Attendee, Individual, Company, Product, Prospect, Grant
…collects IDs per category, de-duplicates them, then fetches each by ID.
Pagination
Collection endpoints use page parameters
currentPage(0-based) andpageSize(default 200).The connector increments pages until
currentPagereachespagination.totalPages.
Retries & rate limits
429 Too Many Requests → the connector logs the condition, sleeps for RETRY_DELAY (default 30s), and retries automatically.
All requests have retry with backoff, up to RETRY_LIMIT attempts (default 5).
4xx/5xx responses produce descriptive errors (401/403/404 have custom messages; other statuses raise a generic error including the URI and params).
State & deletes
State/bookmarks: none — each run fully replaces rows per stream.
Deletes: none are emitted; downstream tables are refreshed by overwrite/merge.
Primary Keys & Uniqueness
Each stream declares one or more unique keys via its
indexesentry in the stream’s table map.The default record ID field is
id(oraccountIdfor accounts); some streams override this with a different key when listing IDs.Key properties are emitted along with the schema for merge/upsert consistency.
Error Handling & Record Shaping
Before writing, responses are pruned to the declared columns; any unmapped fields are dropped, and missing mapped fields are set to
null.The connector normalizes account detail responses, selecting either
individualAccountorcompanyAccountpayloads.
Streams
accounts
Listing:
GET /accounts(paged; run twice withuserType=INDIVIDUALanduserType=COMPANYwhen collecting IDs for child streams).Detail:
GET /accounts/{accountId}; payload normalized fromindividualAccount/companyAccount.Keys: from the table map
indexes(typicallyaccountId).
customFields
Listing:
GET /customFields?category=<…>for each of: Account, Donation, Event, Attendee, Individual, Company, Product, Prospect, Grant.Detail:
GET /customFields/{id}.Keys: from the table map
indexes.
Account-scoped child streams (example pattern: memberships, but the exact set is defined in the table map)
Listing:
GET /accounts/{accountId}/{table}for each account.Detail:
GET /{table}/{id}.Keys: from the table map
indexes.
For every stream above, the connector emits the schema and unique keys from the table map and writes all columns exactly as defined there.
Metrics
After each stream completes, the connector emits:
record_count(counter): total rows written for that stream.
Known Limitations & Notes
No incremental sync: runs are full-replace per stream; plan scheduling accordingly for large accounts.
Account-scoped streams may multiply API volume (per-account iteration).
Custom fields require category-based listing; if a category is restricted, that subset may be missing.
HTTP errors propagate with descriptive messages; 429s are retried with delay.
Columns & types are constrained to the table map; unexpected fields in responses are dropped.
