feat(data-warehouse): implement justcall import source - #67824
Merged
Conversation
Implements the JustCall (cloud phone, SMS, and sales-dialer) data warehouse import source end-to-end as a ResumableSource over JustCall's REST/JSON v2.1 API. Endpoints: calls, texts, contacts, users, phone_numbers, and sales_dialer_calls. Calls, texts, and sales dialer calls sync incrementally via JustCall's `from_datetime` server-side filter (ascending, day-granular watermark on the account-timezone `*_user_date` field); the remaining endpoints are full refresh. All outbound HTTP goes through the tracked session. Pagination rebuilds the page query each request so the time filter stays attached on every page, and resume state checkpoints the current page after each yielded batch. Ships behind `unreleasedSource=True` with `releaseStatus=alpha`. Generated-By: PostHog Code Task-Id: 9952b8ef-a3ac-4fd4-839b-f4551df47f94
Contributor
|
Hey @Gilbert09! 👋 It looks like your git author email on this PR isn't your
You can fix it for this repo with: git config user.email "you@posthog.com"Or set it globally with |
Contributor
|
Reviews (1): Last reviewed commit: "feat(data-warehouse): implement justcall..." | Re-trigger Greptile |
Compute the incremental fields once per endpoint instead of three repeated dict lookups, and drop the redundant list() around the ENDPOINTS tuple. Addresses a Greptile review nit; behavior is unchanged. Generated-By: PostHog Code Task-Id: 9952b8ef-a3ac-4fd4-839b-f4551df47f94
…odies Register the JustCall API key/secret (and the combined Authorization header value) for value-based redaction on a single reused tracked session, so the raw credentials can't leak into request logs or captured HTTP samples on a failed sync. Stop logging the verbatim upstream response body on error — these endpoints return calls, texts, and contacts, so the raw payload could copy customer PII or echoed credentials into logs; status and endpoint are enough to debug. Generated-By: PostHog Code Task-Id: 290b0f1a-e63a-4c56-a24f-386f63407b22
Generated-By: PostHog Code Task-Id: 290b0f1a-e63a-4c56-a24f-386f63407b22
Contributor
PR overviewAll previously flagged issues have been addressed. No open security concerns remain on this pull request. Security reviewNo open security issues remain on this pull request. Fixed/addressed: 1 · PR risk: 0/10 |
MarconLP
approved these changes
Jul 2, 2026
The api_key is part of the Authorization credential sent to JustCall. Marking it as a plain text, non-secret field meant it was classified as non-sensitive and returned by the source settings API, letting anyone who can view the source config copy stored credential material. Treat it like the api_secret (PASSWORD type, secret=True), matching the convention used by every other API-key source, and lock it in with a parametrized test. Generated-By: PostHog Code Task-Id: c9d9ce24-26dc-4843-afa3-a35bdb05a6fc
Generated-By: PostHog Code Task-Id: c9d9ce24-26dc-4843-afa3-a35bdb05a6fc
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
PostHog can't pull data from JustCall, a cloud phone, SMS/WhatsApp, and sales-dialer platform. Teams that run their support or sales calls through JustCall have no way to join that telephony activity with the rest of their product and customer data in PostHog. The connector was scaffolded (registered with
unreleasedSource=Trueand an emptysource.py) but had no sync logic.Changes
Implements the
justcallsource end-to-end as aResumableSourceover JustCall's REST/JSON v2.1 API, following theimplementing-warehouse-sourcesskill'ssource.py/settings.py/justcall.pysplit.Endpoints synced:
calls,texts,contacts,users,phone_numbers, andsales_dialer_calls.Authorizationheader (api_key:api_secret), matching JustCall v2.1.calls,texts, andsales_dialer_callssync incrementally via JustCall's server-sidefrom_datetimefilter, requesting rows ascending withsort=datetimeso the watermark advances monotonically. The cursor is the account-timezone*_user_datefield (day-granular;from_datetimere-fetches the boundary day and the primary-key merge dedupes the overlap).contacts,users, andphone_numbersare full refresh because JustCall exposes no server-side time filter for them.from_datetime/sort/orderstay attached on every page (JustCall'snext_page_linkisn't followed because I couldn't verify it preserves the filter on later pages, and dropping it would re-walk full history each incremental sync). A short page ends pagination; resume state checkpoints the current page after each yielded batch.make_tracked_session().get_non_retryable_errors(401/403),canonical_descriptions.pyfrom the official API docs, and setslists_tables_without_credentials = Trueso the public docs render the table catalog.unreleasedSource=TruewithreleaseStatus=alpha.SOURCES.md(movesjustcallinto the Implemented table) and adds the user-facing posthog.com doc (see agent context).The existing
frontend/public/services/justcall.pngicon is reused.How did you test this code?
Automated tests I (the agent) actually ran, all passing in the project venv:
tests/test_justcall.py(transport) -_format_cursorcoercion,_build_params(incremental vs full-refresh, per-endpointordercasing),_build_url,validate_credentialsstatus mapping, andget_rowsbehavior: page-forward pagination stopping on a short page, checkpoint-per-page resume state, resuming from saved page, and that thefrom_datetimefilter is attached only for time-filterable endpoints.tests/test_justcall_source.py(source class) -source_type, config fields/labels, non-retryable error matching,get_schemas(onlycalls/texts/sales_dialer_callsadvertise incremental), credential plumbing, resumable-manager binding,source_for_pipelineargument plumbing, documented-tables rendering, and canonical-description coverage of every endpoint.test_source_categories.py(1312 passed) andtest_source_config_generator.py(snapshot passed).I did not run a live end-to-end sync - that needs a real JustCall account. See the uncertainty note below.
Automatic notifications
Docs update
User-facing doc written per the
documenting-warehouse-sourcesskill atcontents/docs/cdp/sources/justcall.md(sourceIdJustCall, alpha callout,<SourceParameters />+<SourceTables />). It lives in the posthog.com repo, which isn't checked out in this environment, so it still needs to land there.docsUrlinget_source_configalready points athttps://posthog.com/docs/cdp/sources/justcall, andaudit_source_docscouldn't be run here (no posthog.com checkout).🤖 Agent context
Autonomy: Human-driven (agent-assisted)
Authored by Claude (Claude Code). Skills invoked:
implementing-warehouse-sourcesanddocumenting-warehouse-sources.Key decisions:
aircallsource (also telephony, API key + token,ResumableSource), diverging where JustCall differs (rawAuthorizationheader,data+next_page_linkenvelope, 0-indexed pages, split UTC/user-timezone date fields).ResumableSourceonly. JustCall's webhook API is a natural follow-up, but full webhook support (management + signature verification) is unverifiable without account credentials, so I kept the first cut to the resumable pull path.Authorization: api_key:api_secretheader shape, and the 401 envelope with unauthenticated curl, and pulled query params / object fields / thedata+next_page_linkenvelope from JustCall's v2.1 reference docs. I could not run the future-date-cutoff smoke test the skill recommends for confirmingfrom_datetimeactually filters (no credentials). I enabled incremental anyway for the three endpoints wherefrom_datetimeis a documented, load-bearing core filter, requesting ascending explicitly and preserving the filter on every page so the failure mode is bounded (extra API cost, not watermark corruption). This is called out in a code comment.pnpm run generate:source-configsneeds a database, which isn't available here, so I hand-wrote the two-fieldJustCallSourceConfigto exactly match the generator's deterministic output (verified againstAircallSourceConfig). CI regenerates it. Same forschema:build- theJustCallenum value already exists inschema-general.ts/schema_enums.py, so no schema regeneration was needed.Agent-authored - please review; do not self-merge.