External Data

For instructions on how to authenticate to use this endpoint, see API overview.

Endpoints

PATCH
POST
POST
GET
POST
GET
GET
POST
POST
GET
POST
GET
POST
POST
POST
POST
GET
GET

Update external data sources revenue analytics config

Update the revenue analytics configuration and return the full external data source.

Required API key scopes

external_data_source:write

Path parameters

  • id
    string

Request parameters

  • created_via
  • client_secret
    string
  • account_id
    string
  • prefix
    string | null
  • description
    string | null
  • direct_query_enabled
    boolean
  • auto_sync_new_schemas
    boolean
  • auto_sync_schema_patterns
    array | null
  • job_inputs

Example request

PATCH /api/projects/:project_id/external_data_sources/:id/revenue_analytics_config
export POSTHOG_PERSONAL_API_KEY=[your personal api key]
curl -X PATCH \
-H "Authorization: Bearer $POSTHOG_PERSONAL_API_KEY" \
<ph_app_host>/api/projects/:project_id/external_data_sources/:id/revenue_analytics_config/\
-d created_at="string"

Example response

Status 200 No response body

Create external data sources update cdc settings

Update CDC tuning fields without enabling/disabling.

Lets users edit cdc_auto_drop_slot, cdc_lag_warning_threshold_mb, and cdc_lag_critical_threshold_mb independently. These fields are universal across engines. Engine-specific identifiers (slot name, management mode, …) are immutable post-enable — switching them requires disable + enable.

Required API key scopes

external_data_source:write

Path parameters

  • id
    string

Request parameters

  • created_via
  • client_secret
    string
  • account_id
    string
  • prefix
    string | null
  • description
    string | null
  • direct_query_enabled
    boolean
  • auto_sync_new_schemas
    boolean
  • auto_sync_schema_patterns
    array | null
  • job_inputs

Example request

POST /api/projects/:project_id/external_data_sources/:id/update_cdc_settings
export POSTHOG_PERSONAL_API_KEY=[your personal api key]
curl
-H 'Content-Type: application/json'\
-H "Authorization: Bearer $POSTHOG_PERSONAL_API_KEY" \
<ph_app_host>/api/projects/:project_id/external_data_sources/:id/update_cdc_settings/\
-d client_secret="string",\
-d account_id="string"

Example response

Status 200 No response body

Create external data sources update webhook inputs

Also available via the PostHog MCP server:

  • external-data-sources-update-webhook-inputs-create — Update webhook inputs (signing secret, etc.)

Create, Read, Update and Delete External data Sources.

Required API key scopes

external_data_source:write

Path parameters

  • id
    string

Request parameters

  • created_via
  • client_secret
    string
  • account_id
    string
  • prefix
    string | null
  • description
    string | null
  • direct_query_enabled
    boolean
  • auto_sync_new_schemas
    boolean
  • auto_sync_schema_patterns
    array | null
  • job_inputs

Response


Example request

POST /api/projects/:project_id/external_data_sources/:id/update_webhook_inputs
export POSTHOG_PERSONAL_API_KEY=[your personal api key]
curl
-H 'Content-Type: application/json'\
-H "Authorization: Bearer $POSTHOG_PERSONAL_API_KEY" \
<ph_app_host>/api/projects/:project_id/external_data_sources/:id/update_webhook_inputs/\
-d client_secret="string",\
-d account_id="string"

Example response

Status 200
RESPONSE
{
"success": true
}

Retrieve external data sources webhook info

Also available via the PostHog MCP server:

  • external-data-sources-webhook-info-retrieve — Get webhook status for a source

Create, Read, Update and Delete External data Sources.

Required API key scopes

external_data_source:read

Path parameters

  • id
    string

Response


Example request

GET /api/projects/:project_id/external_data_sources/:id/webhook_info
export POSTHOG_PERSONAL_API_KEY=[your personal api key]
curl \
-H "Authorization: Bearer $POSTHOG_PERSONAL_API_KEY" \
<ph_app_host>/api/projects/:project_id/external_data_sources/:id/webhook_info/

Example response

Status 200
RESPONSE
{
"supports_webhooks": true,
"exists": true,
"auto_creation_blocked_reason": "string",
"hog_function": {
"id": "string",
"name": "string",
"enabled": true,
"created_at": "string",
"status": {}
},
"webhook_url": "string",
"schema_mapping": {
"property1": "string",
"property2": "string"
},
"inputs": {
"property1": {
"value": null,
"templating": "hog",
"bytecode": [
null
],
"bytecode_contract": "string",
"order": 0,
"transpiled": null
},
"property2": {
"value": null,
"templating": "hog",
"bytecode": [
null
],
"bytecode_contract": "string",
"order": 0,
"transpiled": null
}
},
"external_status": {
"exists": true,
"url": "string",
"enabled_events": [
"string"
],
"status": "string",
"description": "string",
"created_at": "string",
"api_version": "string",
"error": "string"
},
"missing_events": [
"string"
],
"missing_inputs": [
"string"
]
}

Create external data sources check cdc prerequisites

Also available via the PostHog MCP server:

  • external-data-sources-check-cdc-prerequisites-create — Check Postgres CDC prerequisites

Validate CDC prerequisites against a live Postgres connection.

Used by the source wizard to surface ✅/❌ checks before source creation, and by the self-managed setup popup to verify user-created publications.

Required API key scopes

external_data_source:write

Response


Example request

POST /api/projects/:project_id/external_data_sources/check_cdc_prerequisites
export POSTHOG_PERSONAL_API_KEY=[your personal api key]
curl
-H 'Content-Type: application/json'\
-H "Authorization: Bearer $POSTHOG_PERSONAL_API_KEY" \
<ph_app_host>/api/projects/:project_id/external_data_sources/check_cdc_prerequisites/

Example response

Status 200 Whether the Postgres database satisfies CDC prerequisites.
RESPONSE
{
"valid": true,
"errors": [
"string"
]
}
Status 400 Invalid config, disallowed host, or connection failure.


List all external data sources connections

Create, Read, Update and Delete External data Sources.

Required API key scopes

external_data_source:read

Example request

GET /api/projects/:project_id/external_data_sources/connections
export POSTHOG_PERSONAL_API_KEY=[your personal api key]
curl \
-H "Authorization: Bearer $POSTHOG_PERSONAL_API_KEY" \
<ph_app_host>/api/projects/:project_id/external_data_sources/connections/

Example response

Status 200
RESPONSE
{
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
"schema_name": "string",
"prefix": "string",
"engine": "duckdb",
"source_type": "Ashby",
"access_method": "warehouse",
"supports_hogql": true,
"is_builtin_managed_warehouse": true,
"description": "string"
}

Create external data sources credential accounts

List the accounts a source's typed-in credentials can reach, in the shared IntegrationAccount shape.

The OAuth twin takes an integration id because the token already lives on the server. Here the credentials are still in the form, so they arrive in the body — POST, not GET, to keep a private key out of the URL and out of anything that logs one. Nothing is cached for the same reason: the cache key would have to include the credentials.

Required API key scopes

external_data_source:write

Request parameters

  • source_type
    string
  • credentials
    object
  • api_version
    string | null

Response


Example request

POST /api/projects/:project_id/external_data_sources/credential_accounts
export POSTHOG_PERSONAL_API_KEY=[your personal api key]
curl
-H 'Content-Type: application/json'\
-H "Authorization: Bearer $POSTHOG_PERSONAL_API_KEY" \
<ph_app_host>/api/projects/:project_id/external_data_sources/credential_accounts/\
-d source_type="string",\
-d credentials="object"

Example response

Status 200
RESPONSE
{
"accounts": [
{
"value": "string",
"display_name": "string",
"is_primary": true,
"badges": [
"string"
],
"group": "string",
"secondary_text": "string"
}
]
}

Create external data sources database schema

Create, Read, Update and Delete External data Sources.

Required API key scopes

external_data_source:write

Request parameters

  • source_type

Example request

POST /api/projects/:project_id/external_data_sources/database_schema
export POSTHOG_PERSONAL_API_KEY=[your personal api key]
curl
-H 'Content-Type: application/json'\
-H "Authorization: Bearer $POSTHOG_PERSONAL_API_KEY" \
<ph_app_host>/api/projects/:project_id/external_data_sources/database_schema/\
-d source_type=undefined

Example response

Status 200 No response body

List all external data sources direct connection options

Source types the user can add as a direct connection, driven by the direct-SQL capability surface so the picker never drifts from the engines we actually support.

Required API key scopes

external_data_source:read

Example request

GET /api/projects/:project_id/external_data_sources/direct_connection_options
export POSTHOG_PERSONAL_API_KEY=[your personal api key]
curl \
-H "Authorization: Bearer $POSTHOG_PERSONAL_API_KEY" \
<ph_app_host>/api/projects/:project_id/external_data_sources/direct_connection_options/

Example response

Status 200
RESPONSE
{
"source_type": "Ashby",
"label": "string",
"icon_path": "string"
}

Create external data sources draft custom manifest

Draft a Custom REST source manifest from API documentation using an LLM.

Reads the docs (a URL fetched server-side, or pasted text / OpenAPI spec), asks the model to author a RESTAPIConfig manifest, and validates it against the create-path checks — repairing against validation errors up to a small budget. Returns the manifest for the user to review and tweak in the builder before creating the source; it does NOT create anything. Gated by the dwh-custom-source-ai-builder flag, and requires the org to have approved AI data processing, since the docs are sent to the LLM gateway.

Required API key scopes

external_data_source:write

Request parameters

  • source_name
    string
    Default:
  • docs_url
  • docs_text
    string

Response


Example request

POST /api/projects/:project_id/external_data_sources/draft_custom_manifest
export POSTHOG_PERSONAL_API_KEY=[your personal api key]
curl
-H 'Content-Type: application/json'\
-H "Authorization: Bearer $POSTHOG_PERSONAL_API_KEY" \
<ph_app_host>/api/projects/:project_id/external_data_sources/draft_custom_manifest/\
-d source_name="string"

Example response

Status 200
RESPONSE
{
"draft_status": "ok",
"manifest_json": "string",
"resource_names": [
"string"
],
"attempts": 0,
"error": "string"
}

Retrieve external data sources oauth accounts

List the accounts/properties a connected OAuth integration exposes, in the shared IntegrationAccount shape. The logic lives in each source (via OAuthMixin.get_oauth_accounts); this endpoint just routes by source type, applies the optional search filter, and serializes.

Required API key scopes

external_data_source:write

Query parameters

  • integration_id
    integer
  • search
    string
  • source_type
    string

Response


Example request

GET /api/projects/:project_id/external_data_sources/oauth_accounts
export POSTHOG_PERSONAL_API_KEY=[your personal api key]
curl \
-H "Authorization: Bearer $POSTHOG_PERSONAL_API_KEY" \
<ph_app_host>/api/projects/:project_id/external_data_sources/oauth_accounts/

Example response

Status 200
RESPONSE
{
"accounts": [
{
"value": "string",
"display_name": "string",
"is_primary": true,
"badges": [
"string"
],
"group": "string",
"secondary_text": "string"
}
]
}

Create external data sources preview resource

Read a bounded sample of rows for one resource of a Custom REST source.

Lets a manifest author verify data_selector, primary_key, and the incremental cursor_path against live data before creating the source. Only source_type: "Custom" is supported — other source types return 400. The read is bounded (single page per resource, capped row count, short timeouts, no redirects). Manifest, validation, and SSRF problems return 400; a live fetch failure returns 200 with error set and empty rows.

Required API key scopes

external_data_source:write

Request parameters

  • source_type
  • payload
    object
  • resource_name
    string
  • limit
    integer
    Default: 10

Response


Example request

POST /api/projects/:project_id/external_data_sources/preview_resource
export POSTHOG_PERSONAL_API_KEY=[your personal api key]
curl
-H 'Content-Type: application/json'\
-H "Authorization: Bearer $POSTHOG_PERSONAL_API_KEY" \
<ph_app_host>/api/projects/:project_id/external_data_sources/preview_resource/\
-d source_type=undefined,\
-d resource_name="string"

Example response

Status 200
RESPONSE
{
"rows": [
{}
],
"row_count": 0,
"columns": [
{
"name": "string",
"type": "string"
}
],
"error": "string"
}

Create external data sources setup

One-shot data warehouse source setup.

Validate credentials, discover available tables, enable them all with sensible sync defaults (incremental where supported, else append, else full refresh), and create the source in a single call — the caller never has to assemble a schemas array. For sources that support webhooks (e.g. Stripe), a webhook is auto-registered after creation: on success webhook-capable tables switch to real-time webhook sync (unlocking webhook-only tables); on failure the polling defaults stay in place. For fine-grained table/sync control, use the lower-level database_schema + create flow instead.

Required API key scopes

external_data_source:write

Request parameters

  • source_type
  • payload
    object
  • prefix
    string | null
  • description
    string | null
  • direct_query_enabled
    boolean
    Default: false

Response


Example request

POST /api/projects/:project_id/external_data_sources/setup
export POSTHOG_PERSONAL_API_KEY=[your personal api key]
curl
-H 'Content-Type: application/json'\
-H "Authorization: Bearer $POSTHOG_PERSONAL_API_KEY" \
<ph_app_host>/api/projects/:project_id/external_data_sources/setup/\
-d source_type=undefined

Example response

Status 201
RESPONSE
{
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
"webhook": {
"success": true,
"webhook_url": "string",
"error": "string",
"pending_inputs": [
"string"
]
}
}

Create external data sources source prefix

Create, Read, Update and Delete External data Sources.

Required API key scopes

external_data_source:write

Request parameters

  • created_via
  • client_secret
    string
  • account_id
    string
  • prefix
    string | null
  • description
    string | null
  • direct_query_enabled
    boolean
  • auto_sync_new_schemas
    boolean
  • auto_sync_schema_patterns
    array | null
  • job_inputs

Example request

POST /api/projects/:project_id/external_data_sources/source_prefix
export POSTHOG_PERSONAL_API_KEY=[your personal api key]
curl
-H 'Content-Type: application/json'\
-H "Authorization: Bearer $POSTHOG_PERSONAL_API_KEY" \
<ph_app_host>/api/projects/:project_id/external_data_sources/source_prefix/\
-d client_secret="string",\
-d account_id="string"

Example response

Status 200 No response body

Create external data sources store credentials

Validate and store credentials for a data warehouse source without creating the source.

Backs the source connect page: the user enters credentials directly in PostHog, they are checked against a live connection, then stashed encrypted in a temporary store. The returned credential id can be passed to setup as {'credential_id': <id>} to create the source — so secrets never travel through an agent conversation. The stash is single-use: it is deleted as soon as setup consumes it, and expires after 24 hours if never consumed.

Required API key scopes

external_data_source:write

Request parameters

  • source_type
  • payload
    object

Response


Example request

POST /api/projects/:project_id/external_data_sources/store_credentials
export POSTHOG_PERSONAL_API_KEY=[your personal api key]
curl
-H 'Content-Type: application/json'\
-H "Authorization: Bearer $POSTHOG_PERSONAL_API_KEY" \
<ph_app_host>/api/projects/:project_id/external_data_sources/store_credentials/\
-d source_type=undefined,\
-d payload="object"

Example response

Status 201
RESPONSE
{
"credential_id": "13c40afa-2996-4a0c-b2e9-68fba9462242",
"source_type": "string",
"created_at": "2019-08-24T14:15:22Z",
"expires_at": "2019-08-24T14:15:22Z"
}

List all external data sources stored credentials

List credentials the requesting user stored via the source connect page that haven't been consumed yet.

Returns metadata only (id, source type, timestamps) — never the secrets themselves. Stored credentials are scoped to their creator: only the user who filled the connect page can list or consume them. They are temporary too: they disappear once consumed by setup or when they expire. Newest first, so after a user confirms they've finished the connect page, the first entry for the source type is the one to pass to setup.

Required API key scopes

external_data_source:read

Query parameters

  • search
    string
  • source_type
    string

Example request

GET /api/projects/:project_id/external_data_sources/stored_credentials
export POSTHOG_PERSONAL_API_KEY=[your personal api key]
curl \
-H "Authorization: Bearer $POSTHOG_PERSONAL_API_KEY" \
<ph_app_host>/api/projects/:project_id/external_data_sources/stored_credentials/

Example response

Status 200
RESPONSE
{
"credential_id": "13c40afa-2996-4a0c-b2e9-68fba9462242",
"source_type": "string",
"created_at": "2019-08-24T14:15:22Z",
"expires_at": "2019-08-24T14:15:22Z"
}

Retrieve external data sources wizard

Create, Read, Update and Delete External data Sources.

Required API key scopes

external_data_source:read

Query parameters

  • source_type
    string

Example request

GET /api/projects/:project_id/external_data_sources/wizard
export POSTHOG_PERSONAL_API_KEY=[your personal api key]
curl \
-H "Authorization: Bearer $POSTHOG_PERSONAL_API_KEY" \
<ph_app_host>/api/projects/:project_id/external_data_sources/wizard/

Example response

Status 200
RESPONSE
{
"property1": {
"caption": null,
"category": null,
"disabledReason": null,
"docsUrl": null,
"existingSource": null,
"featureFlag": null,
"featured": false,
"fields": [
{
"caption": null,
"label": "string",
"name": "string",
"placeholder": "string",
"required": true,
"secret": true,
"type": "text"
}
],
"iconClassName": null,
"iconPath": "string",
"keywords": null,
"label": null,
"name": "Ashby",
"permissionsCaption": null,
"releaseStatus": null,
"suggestedTables": [],
"supportsColumnSelection": true,
"unreleasedSource": null,
"webhookFields": null,
"webhookManualOnly": null,
"webhookSetupCaption": null,
"versions": [
"string"
],
"defaultVersion": "string",
"apiDocsUrl": null,
"deprecatedVersions": [
{
"version": "string",
"sunsetAt": null
}
],
"tables": null
},
"property2": {
"caption": null,
"category": null,
"disabledReason": null,
"docsUrl": null,
"existingSource": null,
"featureFlag": null,
"featured": false,
"fields": [
{
"caption": null,
"label": "string",
"name": "string",
"placeholder": "string",
"required": true,
"secret": true,
"type": "text"
}
],
"iconClassName": null,
"iconPath": "string",
"keywords": null,
"label": null,
"name": "Ashby",
"permissionsCaption": null,
"releaseStatus": null,
"suggestedTables": [],
"supportsColumnSelection": true,
"unreleasedSource": null,
"webhookFields": null,
"webhookManualOnly": null,
"webhookSetupCaption": null,
"versions": [
"string"
],
"defaultVersion": "string",
"apiDocsUrl": null,
"deprecatedVersions": [
{
"version": "string",
"sunsetAt": null
}
],
"tables": null
}
}