# OpenFunnel — Orthogonal API

> Pay-per-use API on Orthogonal. Each call is billed to your Orthogonal balance.
> Base API: `https://api.orth.sh/v1/run` · [llms.txt](https://orthogonal.com/llms.txt) · [browse all APIs](https://orthogonal.com/discover)

GTM intelligence platform. Search companies by traits/signals, enrich accounts with firmographic data, find and enrich people, get account timelines and insights, and deploy signal-monitoring agents.

**Verified:** yes

## Access

**Run API:** `POST https://api.orth.sh/v1/run`
**Auth:** `Authorization: Bearer $ORTHOGONAL_API_KEY`
Get an API key at https://orthogonal.com/dashboard/settings/api-keys

Every call goes through the unified Run API: send the API `slug`, the endpoint `path`, and the `query`/`body` parameters. The response is `{ "success": true, "price": "<usd>", "data": { ... } }`.

## Endpoints

### Instant search on traits

Search for companies by describing their traits or characteristics.

Use natural language to find companies matching specific criteria like:
- **Industry**: "healthcare companies", "fintech startups"
- **Products**: "companies with voice AI products", "payment processing platforms"
- **Business model**: "B2B SaaS companies", "companies that sell to restaurants"
- **Technology**: "companies using Kubernetes", "AI-first startups"

Returns companies ranked by relevance with similarity scores.

`GET /api/v1/account/search-by-traits`

**Cost:** Free

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `query` | string | Yes | Natural language description of company traits |
| `limit` | number | No | Max results to return |
| `query` | string | Yes | Describe the type of companies you're looking for |
| `limit` | integer | No | Maximum number of results to return (1-100) |

```bash
curl -X POST 'https://api.orth.sh/v1/run' \
  -H 'Authorization: Bearer $ORTHOGONAL_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{"api":"openfunnel","path":"/api/v1/account/search-by-traits","method":"GET","query":{"query":"<string>","limit":"<integer>"},"body":{"query":"<string>","limit":"<number>"}}'
```

### List People Ids

List People Ids

`POST /api/v1/people/filtered-people`

**Cost:** Free

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `filters` | string | No | Filters using V2 field names (matching /people/filters endpoint output) |
| `sort_key` | string | No |  |
| `sort_direction` | string | No |  |
| `page` | integer | No |  |
| `page_size` | integer | No |  |

```bash
curl -X POST 'https://api.orth.sh/v1/run' \
  -H 'Authorization: Bearer $ORTHOGONAL_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{"api":"openfunnel","path":"/api/v1/people/filtered-people","body":{"filters":"<string>","sort_key":"<string>","sort_direction":"<string>","page":"<integer>","page_size":"<integer>"}}'
```

### Get Accounts

Get Accounts V2

`POST /api/v2/account/batch`

**Cost:** Free

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `account_ids` | string | No | List of account IDs to get details for. Either account_ids or account_domains is required. |
| `account_domains` | string | No | List of account domains to get details for. Either account_ids or account_domains is required. |
| `icp_people_page` | integer | No | Page number for icp_people pagination (1-indexed, default 1) |
| `icp_people_page_size` | integer | No | Number of icp_people to return per page (default 100, max 500) |
| `max_signals_per_account` | integer | No | Maximum number of most recent signals to return per account (default 10, max 100) |
| `raw_content` | boolean | No | When false, it fetches faster responses that omit job_title, job_posting, post_content, and similar content-derived fields. Set to true to fetch full signal_content for each signal (job postings, social posts, etc.). |

```bash
curl -X POST 'https://api.orth.sh/v1/run' \
  -H 'Authorization: Bearer $ORTHOGONAL_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{"api":"openfunnel","path":"/api/v2/account/batch","body":{"account_ids":"<string>","account_domains":"<string>","icp_people_page":"<integer>","icp_people_page_size":"<integer>","max_signals_per_account":"<integer>","raw_content":"<boolean>"}}'
```

### Get People Filters

Get People Filters

`GET /api/v1/people/filters`

**Cost:** Free

_No parameters required._

```bash
curl -X POST 'https://api.orth.sh/v1/run' \
  -H 'Authorization: Bearer $ORTHOGONAL_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{"api":"openfunnel","path":"/api/v1/people/filters","method":"GET"}'
```

### Search Accounts By Name Or Domain

Search accounts by name or domain with fuzzy matching.

`GET /api/v1/account/search-by-name-or-domain`

**Cost:** Free

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `query` | string | Yes | Search query (company name or domain) |
| `limit` | number | No | Max results to return |
| `query` | string | Yes | Search query to match against account name or domain |
| `limit` | integer | No | Maximum number of results to return (1-50) |

```bash
curl -X POST 'https://api.orth.sh/v1/run' \
  -H 'Authorization: Bearer $ORTHOGONAL_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{"api":"openfunnel","path":"/api/v1/account/search-by-name-or-domain","method":"GET","query":{"query":"<string>","limit":"<integer>"},"body":{"query":"<string>","limit":"<number>"}}'
```

### Get People

Get people details by IDs (comma-separated).

`GET /api/v1/people/batch`

**Cost:** Free

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `people_ids` | number[] | Yes | List of people IDs to fetch |
| `people_ids` | string | Yes | Comma-separated list of people IDs (e.g., '101,102,103') |

```bash
curl -X POST 'https://api.orth.sh/v1/run' \
  -H 'Authorization: Bearer $ORTHOGONAL_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{"api":"openfunnel","path":"/api/v1/people/batch","method":"GET","query":{"people_ids":"<string>"},"body":{"people_ids":"<number>"}}'
```

### List Accounts

List Account Ids

`POST /api/v2/account/filtered-accounts`

**Cost:** Free

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `filters` | string | No | Filters using V2 field names (matching /filters endpoint output) |
| `sort_key` | string | No |  |
| `sort_direction` | string | No |  |
| `page` | integer | No |  |
| `page_size` | integer | No |  |

```bash
curl -X POST 'https://api.orth.sh/v1/run' \
  -H 'Authorization: Bearer $ORTHOGONAL_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{"api":"openfunnel","path":"/api/v2/account/filtered-accounts","body":{"filters":"<string>","sort_key":"<string>","sort_direction":"<string>","page":"<integer>","page_size":"<integer>"}}'
```

### Get Timeline

Get chronological activity timeline for an account.

Returns events from account_timeline_insights table within the specified time range.

Args:
    account_id: The account ID to get timeline for
    days: How many days back to look (default 30, max 365)
    alert_types: Optional comma-separated filter ('openfunnel', 'crm')
    limit: Maximum events per page (default 50, max 500)
    offset: Number of events to skip for pagination
    user_id: Authenticated user ID (from API key)

Returns:
    TimelineResponse with events and pagination metadata

`GET /api/v1/account/{account_id}/timeline`

**Cost:** Free

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `account_id` | string | Yes | Path parameter — substitute directly into the endpoint `path`. |
| `days` | integer | No | Number of days back to look |
| `alert_types` | string | No | Comma-separated alert types to filter (e.g., 'openfunnel,crm') |
| `limit` | integer | No | Maximum events per page |
| `offset` | integer | No | Number of events to skip |

```bash
# Replace {account_id} in "path" with real values before sending
curl -X POST 'https://api.orth.sh/v1/run' \
  -H 'Authorization: Bearer $ORTHOGONAL_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{"api":"openfunnel","path":"/api/v1/account/{account_id}/timeline","method":"GET","query":{"days":"<integer>","alert_types":"<string>","limit":"<integer>","offset":"<integer>"}}'
```

### Get Account Filters

Get Account Filters

`GET /api/v2/account/filters`

**Cost:** Free

_No parameters required._

```bash
curl -X POST 'https://api.orth.sh/v1/run' \
  -H 'Authorization: Bearer $ORTHOGONAL_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{"api":"openfunnel","path":"/api/v2/account/filters","method":"GET"}'
```

### List ICPs

List all ICP profiles for the authenticated user.

`GET /api/v1/icp/list`

**Cost:** Free

_No parameters required._

```bash
curl -X POST 'https://api.orth.sh/v1/run' \
  -H 'Authorization: Bearer $ORTHOGONAL_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{"api":"openfunnel","path":"/api/v1/icp/list","method":"GET"}'
```

### Get Signal

Get signal details by ID with optional date filtering.

`POST /api/v1/signal`

**Cost:** Free

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `signal_id` | integer | Yes | Signal ID to get details for |
| `filters` | GetSignalFilters · object | No | Optional filters to apply when querying signals. All filters are combined with AND logic. |

```bash
curl -X POST 'https://api.orth.sh/v1/run' \
  -H 'Authorization: Bearer $ORTHOGONAL_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{"api":"openfunnel","path":"/api/v1/signal","body":{"signal_id":"<integer>","filters":"<object>"}}'
```

### List Signals

List Signals

`POST /api/v1/signal/get-signal-list`

**Cost:** Free

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `filters` | SignalFilters · object | No | Optional filters to apply when querying signals. All filters are combined with AND logic. |
| `pagination` | PaginationParams · object | No | Pagination parameters for the request |

```bash
curl -X POST 'https://api.orth.sh/v1/run' \
  -H 'Authorization: Bearer $ORTHOGONAL_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{"api":"openfunnel","path":"/api/v1/signal/get-signal-list","body":{"filters":"<object>","pagination":"<object>"}}'
```

### Deploy Deep Hiring Signal

Deploy a Deep Hiring signal.

OpenFunnel Deep Hiring Agent find deep company activities that are buried inside job postings not just limited to technographics.

Ask activities like:
- I want to target companies using Kubernetes (this is a technographics example)
- I want to target companies scaling their PLG motion
- I want to target companies moving from VM based deployment to Kubernetes based Deployments
- I want to target companies moving from Heroku to AWS

`POST /api/v1/signal/deploy/deep-hiring-agent`

**Estimated cost:** Dynamic — use `"dryRun": true` in the Run API request to check the exact cost before calling.

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `name` | string | No | Name/identifier for this signal run |
| `search_query` | string | No | Hiring goal (e.g. 'companies hiring AI engineers') |
| `timeframe` | integer | No | Time limit in days (180) |
| `icp_id` | integer | No | ICP ID to use for filtering |
| `repeat` | boolean | No | Whether this signal should recur daily |
| `account_audience_name` | string | No | Audience name for auto-adding discovered accounts |
| `people_audience_name` | string | No | Audience name for people enrichment |
| `max_credit_limit` | integer | Yes | Maximum OpenFunnel credits to spend on this signal run. 1 credit = $0.044 USD. Typical range: 50-100 credits ($2.20-$4.40). The signal stops once this limit is reached. |
| `enable_safe_crm_addition` | boolean | No | Auto-add discovered accounts to CRM. New/unassigned accounts are created and assigned to you; existing accounts get signals enriched. Ownership is never changed. |
| `auto_enrich_people_emails` | boolean | No | Automatically enrich discovered people with work emails. Requires people_audience_name to be set. Uses email enrichment credits. |

```bash
curl -X POST 'https://api.orth.sh/v1/run' \
  -H 'Authorization: Bearer $ORTHOGONAL_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{"api":"openfunnel","path":"/api/v1/signal/deploy/deep-hiring-agent","body":{"name":"<string>","search_query":"<string>","timeframe":"<integer>","icp_id":"<integer>","repeat":"<boolean>","account_audience_name":"<string>","people_audience_name":"<string>","max_credit_limit":"<integer>","enable_safe_crm_addition":"<boolean>","auto_enrich_people_emails":"<boolean>"}}'
```

### Deep Enrich

End-to-end company qualification and people enrichment.

1. Creates or finds the account for the given domain.
2. Finds intent signals for the company.
3. Enriches the account with people — finds relevant team members and ICP qualifies them.

Requires either `icp_id` or `target_icp_roles`. Runs in background — use `account_id` to get latest account status. Deep enrichment can take 15-30 minutes to find intent signals and people.

`POST /api/v1/enrich/deep-enrich`

**Estimated cost:** $0.132

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `domain` | string | Yes | Request model for end-to-end company qualification and people enrichment. |
| `goal` | string | No | Search goal (overrides default pitch) |
| `icp_id` | integer | No | ICP ID to fetch target roles from |
| `target_icp_roles` | string[] | No | Target ICP roles (overrides icp_id roles) |
| `timeframe` | integer | No | Timeframe in days to search back |
| `max_jobs_to_check` | integer | No | Max jobs to check for relevance |
| `campaign_name` | string | No | Campaign name to create for enriched people |
| `people_locations` | string[] | No | Target people locations (overrides ICP) |
| `people_sub_locations` | string[] | No | Target people sub-locations (overrides ICP) |

```bash
curl -X POST 'https://api.orth.sh/v1/run' \
  -H 'Authorization: Bearer $ORTHOGONAL_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{"api":"openfunnel","path":"/api/v1/enrich/deep-enrich","body":{"domain":"<string>","goal":"<string>","icp_id":"<integer>","target_icp_roles":"<string>","timeframe":"<integer>","max_jobs_to_check":"<integer>","campaign_name":"<string>","people_locations":"<string>","people_sub_locations":"<string>"}}'
```

### Search Lookalikes

Find lookalike companies from a natural-language description, with optional firmographic filters.Use it for queries such as:Healthcare companies building with voice AICompanies that provide customer support software for B2CCompanies that build workflow automation for non technical industriesYou can also restrict results to your ICP by applying filters for company size, funding stage, and headquarters country.Omitting filtersIf you omit filters, search runs across all company sizes, funding stages, and supported locations. Use the optional firmographic filters below to restrict results to your ICP.ExampleThis request finds 100 healthcare companies building with voice AI in the US, with 50-500 employees, and funded at Series A or Series B.curl -sS -G "https://api.openfunnel.dev/api/v1/account/search-lookalikes" \  -H "X-API-Key: YOUR_API_KEY" \  -H "X-User-ID: you@company.com" \  --data-urlencode "query=Healthcare companies building with voice AI" \  --data-urlencode "limit=100" \  --data-urlencode "min_employees=50" \  --data-urlencode "max_employees=500" \  --data-urlencode "funding_stages=Series A" \  --data-urlencode "funding_stages=Series B" \  --data-urlencode "locations=us"

`GET /api/v1/account/search-lookalikes`

**Cost:** Free

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `query` | string | Yes | Describe the kinds of companies you want to find. |
| `limit` | integer | No | Maximum number of companies to return. Default 10, max 100. |
| `min_employees` | integer | No | Minimum employee count, inclusive. |
| `max_employees` | integer | No | Maximum employee count, inclusive. |
| `funding_stages` | enum<string>[] | No | Funding stages to include. Repeat the parameter to send multiple values. |
| `locations` | enum<string>[] | No | Headquarters country filters using supported lowercase country codes. Repeat the parameter to send multiple values. |

```bash
curl -X POST 'https://api.orth.sh/v1/run' \
  -H 'Authorization: Bearer $ORTHOGONAL_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{"api":"openfunnel","path":"/api/v1/account/search-lookalikes","method":"GET","query":{"query":"<string>","limit":"<integer>","min_employees":"<integer>","max_employees":"<integer>","funding_stages":"<string>","locations":"<string>"}}'
```

### Deploy Deep Company Search Signal

Deploy a Deep Company Search signal using the TAQ framework (Trait, Activity, Qualifier).

Discover companies by combining up to three stages:

- **Trait** (`trait`, required) — What the company *is*: industry, stage, characteristics
- **Activity** (`activity`, optional) — What the company *does*: hiring patterns, tech adoption, activities
- **Qualifier** (`qualifier`, optional) — Who *works there*: team composition, department headcount, specific roles

**Examples:**
- Trait: "Health-tech companies" + Activity: "Building voice AI tools" + Qualifier: "Has a VP of Engineering"
- Trait: "Fintech startups" + Activity: "Hiring ML engineers"
- Trait: "B2B SaaS" + Qualifier: "Has a dedicated Customer Success team of 10+"

`POST /api/v1/signal/deploy/deep-company-search-agent`

**Estimated cost:** Dynamic — use `"dryRun": true` in the Run API request to check the exact cost before calling.

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `name` | string | Yes | Name/identifier for this signal run |
| `trait` | string | Yes | What describes the company — industry, specific description, or services they provide (e.g. 'Health-tech companies', 'Fintech startups', 'Insurance companies', 'Companies that provide DevOps consulting'). |
| `activity` | string | No | What the company is currently doing that indicates buying intent or an upcoming pain-point: facing specific pain points, building internal functions, trying to solve something in-house, or hiring for a specific problem (e.g. 'Building AI-powered analytics in-house', 'Hiring ML engineers to replace manual QA', 'Struggling with claims processing automation'). |
| `qualifier` | string | No | What the company already has (deal-breakers) — required conditions for your product to work (e.g. 'Has at least one SDR', 'Has a DevOps team', 'Has a Sales team in EMEA', 'Has a dedicated Customer Success team of 10+'). Uses LLM-driven qualification on company people data. |
| `icp_id` | integer | No | ICP ID to use for filtering |
| `repeat` | boolean | No | Whether this signal should recur daily |
| `account_audience_name` | string | No | Audience name for auto-adding discovered accounts |
| `people_audience_name` | string | No | Audience name for people enrichment |
| `max_credit_limit` | integer | Yes | Maximum OpenFunnel credits to spend on this signal run. 1 credit = $0.044 USD. Typical range: 50-100 credits ($2.20-$4.40). The signal stops once this limit is reached. |
| `enable_safe_crm_addition` | boolean | No | Auto-add discovered accounts to CRM. New/unassigned accounts are created and assigned to you; existing accounts get signals enriched. Ownership is never changed. |
| `auto_enrich_people_emails` | boolean | No | Automatically enrich discovered people with work emails. Requires people_audience_name to be set. Uses email enrichment credits. |

```bash
curl -X POST 'https://api.orth.sh/v1/run' \
  -H 'Authorization: Bearer $ORTHOGONAL_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{"api":"openfunnel","path":"/api/v1/signal/deploy/deep-company-search-agent","body":{"name":"<string>","trait":"<string>","activity":"<string>","qualifier":"<string>","icp_id":"<integer>","repeat":"<boolean>","account_audience_name":"<string>","people_audience_name":"<string>","max_credit_limit":"<integer>","enable_safe_crm_addition":"<boolean>","auto_enrich_people_emails":"<boolean>"}}'
```

### Insights Feed

Get cross-account insights feed.Returns insights across all accounts for the authenticated user,with optional filtering by date range, alert type, sentiment, and account IDs.

`GET /api/v1/insights/feed`

**Cost:** Free

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `days` | integer | No | Number of days back to look |
| `alert_type` | string | No | Filter by alert type: 'openfunnel' or 'crm' |
| `sentiment` | string | No | Filter by sentiment: 'positive', 'negative', or 'neutral' |
| `account_ids` | string | No | Comma-separated account IDs to filter by |
| `limit` | integer | No | Maximum insights per page |
| `offset` | integer | No | Number of insights to skip |

```bash
curl -X POST 'https://api.orth.sh/v1/run' \
  -H 'Authorization: Bearer $ORTHOGONAL_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{"api":"openfunnel","path":"/api/v1/insights/feed","method":"GET","query":{"days":"<integer>","alert_type":"<string>","sentiment":"<string>","account_ids":"<string>","limit":"<integer>","offset":"<integer>"}}'
```

### Deploy Social Listening Signal

Deploy a Social Listening signal.

OpenFunnel Company Social Listening Agents listen for any announcements or conversations that a company is making across LinkedIn, Twitter, or Google.

Listen on things like:
- I want to target companies who raised seed funding
- I want to target companies posting about attending RSAC conference
- I want to target companies opening remote offices
- I want to target companies adding AI to their existing stack

`POST /api/v1/signal/deploy/social-listening-agent`

**Estimated cost:** Dynamic — use `"dryRun": true` in the Run API request to check the exact cost before calling.

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `name` | string | Yes | Name/identifier for this signal run |
| `search_query` | string | Yes | LinkedIn search keyword (e.g. 'AI tools') |
| `timeframe` | integer | Yes | Time limit in days (1-180) |
| `signal_target` | enum<string> | No | Whether to discover accounts or people |
| `icp_id` | integer | No | ICP ID to use for filtering |
| `repeat` | boolean | No | Whether this signal should recur daily |
| `account_audience_name` | string | No | Audience name for auto-adding discovered accounts |
| `people_audience_name` | string | No | Audience name for people enrichment |
| `max_credit_limit` | integer | Yes | Maximum OpenFunnel credits to spend on this signal run. 1 credit = $0.044 USD. Typical range: 50-100 credits ($2.20-$4.40). The signal stops once this limit is reached. |
| `enable_safe_crm_addition` | boolean | No | Auto-add discovered accounts to CRM. New/unassigned accounts are created and assigned to you; existing accounts get signals enriched. Ownership is never changed. |
| `auto_enrich_people_emails` | boolean | No | Automatically enrich discovered people with work emails. Requires people_audience_name to be set. Uses email enrichment credits. |

```bash
curl -X POST 'https://api.orth.sh/v1/run' \
  -H 'Authorization: Bearer $ORTHOGONAL_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{"api":"openfunnel","path":"/api/v1/signal/deploy/social-listening-agent","body":{"name":"<string>","search_query":"<string>","timeframe":"<integer>","signal_target":"<string>","icp_id":"<integer>","repeat":"<boolean>","account_audience_name":"<string>","people_audience_name":"<string>","max_credit_limit":"<integer>","enable_safe_crm_addition":"<boolean>","auto_enrich_people_emails":"<boolean>"}}'
```

### Deploy Competitor Engagement Signal

Deploy a Competitor Engagement signal.

Find and qualify every ICP liking or commenting on posts by any LinkedIn profile.

`POST /api/v1/signal/deploy/competitor-engagement-agent`

**Estimated cost:** Dynamic — use `"dryRun": true` in the Run API request to check the exact cost before calling.

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `name` | string | Yes | Name/identifier for this signal run |
| `linkedin_url` | string | Yes | LinkedIn profile URL to monitor for engagement |
| `timeframe` | integer | No | Time limit in days (1-180) |
| `icp_id` | integer | No | ICP ID to use for filtering |
| `repeat` | boolean | No | Whether this signal should recur daily |
| `account_audience_name` | string | No | Audience name for auto-adding discovered accounts |
| `people_audience_name` | string | No | Audience name for people enrichment |
| `max_credit_limit` | integer | Yes | Maximum OpenFunnel credits to spend on this signal run. 1 credit = $0.044 USD. Typical range: 50-100 credits ($2.20-$4.40). The signal stops once this limit is reached. |
| `enable_safe_crm_addition` | boolean | No | Auto-add discovered accounts to CRM. New/unassigned accounts are created and assigned to you; existing accounts get signals enriched. Ownership is never changed. |
| `auto_enrich_people_emails` | boolean | No | Automatically enrich discovered people with work emails. Requires people_audience_name to be set. Uses email enrichment credits. |

```bash
curl -X POST 'https://api.orth.sh/v1/run' \
  -H 'Authorization: Bearer $ORTHOGONAL_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{"api":"openfunnel","path":"/api/v1/signal/deploy/competitor-engagement-agent","body":{"name":"<string>","linkedin_url":"<string>","timeframe":"<integer>","icp_id":"<integer>","repeat":"<boolean>","account_audience_name":"<string>","people_audience_name":"<string>","max_credit_limit":"<integer>","enable_safe_crm_addition":"<boolean>","auto_enrich_people_emails":"<boolean>"}}'
```

### Get ICP options

Return all valid option values for creating an ICP.

Call this endpoint first to discover the allowed values for each field
before calling `/api/v1/icp/create`.

**Response fields:**

- **employee_ranges**: Valid company size range labels (e.g. "1-10", "11-50").
  Pass one or more of these in `employee_ranges` when creating an ICP.
- **funding_stages**: Valid funding stage names (e.g. "Seed", "Series A").
  Use these for `min_funding` and `max_funding` when creating an ICP.
- **locations**: Valid company HQ country/region options with `value` (code) and
  `label` (display name). Use the `value` field for `location` when creating an ICP.
- **sub_locations**: Valid US state and city options with `value` (code) and
  `label` (display name). Use the `value` field for `sub_locations` when creating an ICP.
  Only applicable when `location` is exclusively `["us"]`.
- **people_locations**: Valid country/region options for targeting people by geography.
  Use the `value` field for `people_locations` when creating an ICP.
- **people_sub_locations**: Valid US state and city options for targeting people by
  sub-region. Use the `value` field for `people_sub_locations` when creating an ICP.
  Only applicable when `people_locations` is exclusively `["us"]`.

`GET /api/v1/icp/options`

**Cost:** Free

_No parameters required._

```bash
curl -X POST 'https://api.orth.sh/v1/run' \
  -H 'Authorization: Bearer $ORTHOGONAL_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{"api":"openfunnel","path":"/api/v1/icp/options","method":"GET"}'
```

### Deploy Competitor Activity Signal

Deploy a Competitor Activity signal.

Monitor potential customers your competitors are engaging with. This competitor activity agent surfaces accounts and people that your competitors are actively reaching out to on LinkedIn.

`POST /api/v1/signal/deploy/competitor-activity-agent`

**Estimated cost:** Dynamic — use `"dryRun": true` in the Run API request to check the exact cost before calling.

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `name` | string | Yes | Name/identifier for this signal run |
| `linkedin_url` | string | Yes | LinkedIn profile URL of competitor salesperson to monitor |
| `timeframe` | integer | No | Time limit in days (1-180) |
| `icp_id` | integer | No | ICP ID to use for filtering |
| `repeat` | boolean | No | Whether this signal should recur daily |
| `account_audience_name` | string | No | Audience name for auto-adding discovered accounts |
| `people_audience_name` | string | No | Audience name for people enrichment |
| `max_credit_limit` | integer | Yes | Maximum OpenFunnel credits to spend on this signal run. 1 credit = $0.044 USD. Typical range: 50-100 credits ($2.20-$4.40). The signal stops once this limit is reached. |
| `enable_safe_crm_addition` | boolean | No | Auto-add discovered accounts to CRM. New/unassigned accounts are created and assigned to you; existing accounts get signals enriched. Ownership is never changed. |
| `auto_enrich_people_emails` | boolean | No | Automatically enrich discovered people with work emails. Requires people_audience_name to be set. Uses email enrichment credits. |

```bash
curl -X POST 'https://api.orth.sh/v1/run' \
  -H 'Authorization: Bearer $ORTHOGONAL_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{"api":"openfunnel","path":"/api/v1/signal/deploy/competitor-activity-agent","body":{"name":"<string>","linkedin_url":"<string>","timeframe":"<integer>","icp_id":"<integer>","repeat":"<boolean>","account_audience_name":"<string>","people_audience_name":"<string>","max_credit_limit":"<integer>","enable_safe_crm_addition":"<boolean>","auto_enrich_people_emails":"<boolean>"}}'
```

### Deploy Technography Search Signal

Deploy a Technography Search signal.

OpenFunnel Technography Agents help you find companies based on their technology stack and infrastructure choices.

`POST /api/v1/signal/deploy/technography-search-agent`

**Estimated cost:** Dynamic — use `"dryRun": true` in the Run API request to check the exact cost before calling.

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `name` | string | No | Name/identifier for this signal run |
| `technographic_list` | string[] | No | List of technologies to search for (e.g. ['Snowflake', 'Databricks']) |
| `technographic_variations` | string[] | No | Alternate names/variations of the technologies |
| `exclude_company_name` | string | No | Company name to exclude from results |
| `technography_context` | string | No | Additional context for the technology search |
| `timeframe` | integer | No | Time limit in days (1-365) |
| `icp_filters` | Icp Filters · object | No | ICP filters with target_roles and company_criteria |
| `icp_id` | integer | No | ICP ID to use for filtering |
| `repeat` | boolean | No | Whether this signal should recur daily |
| `account_audience_name` | string | No | Audience name for auto-adding discovered accounts |
| `people_audience_name` | string | No | Audience name for people enrichment |
| `max_credit_limit` | integer | Yes | Maximum OpenFunnel credits to spend on this signal run. 1 credit = $0.044 USD. Typical range: 50-100 credits ($2.20-$4.40). The signal stops once this limit is reached. |
| `enable_safe_crm_addition` | boolean | No | Auto-add discovered accounts to CRM. New/unassigned accounts are created and assigned to you; existing accounts get signals enriched. Ownership is never changed. |
| `auto_enrich_people_emails` | boolean | No | Automatically enrich discovered people with work emails. Requires people_audience_name to be set. Uses email enrichment credits. |

```bash
curl -X POST 'https://api.orth.sh/v1/run' \
  -H 'Authorization: Bearer $ORTHOGONAL_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{"api":"openfunnel","path":"/api/v1/signal/deploy/technography-search-agent","body":{"name":"<string>","technographic_list":"<string>","technographic_variations":"<string>","exclude_company_name":"<string>","technography_context":"<string>","timeframe":"<integer>","icp_filters":"<object>","icp_id":"<integer>","repeat":"<boolean>","account_audience_name":"<string>","people_audience_name":"<string>","max_credit_limit":"<integer>","enable_safe_crm_addition":"<boolean>","auto_enrich_people_emails":"<boolean>"}}'
```

### Deploy ICP Job Change Signal

Deploy an ICP Job Change signal.

Find newly joined people in your ICP at your target companies - new joinees come in with budgets, plans and ideas; it's an ideal time to outreach.
OpenFunnel segregates new joinees from promotions so your outreach is relevant and not landing to the wrong people.

`POST /api/v1/signal/deploy/icp-job-change-agent`

**Estimated cost:** Dynamic — use `"dryRun": true` in the Run API request to check the exact cost before calling.

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `name` | string | Yes | Name/identifier for this signal run |
| `icp_id` | integer | No | ICP ID to use for filtering |
| `repeat` | boolean | No | Whether this signal should recur daily |
| `account_audience_name` | string | No | Audience name for auto-adding discovered accounts |
| `people_audience_name` | string | No | Audience name for people enrichment |
| `max_credit_limit` | integer | Yes | Maximum OpenFunnel credits to spend on this signal run. 1 credit = $0.044 USD. Typical range: 50-100 credits ($2.20-$4.40). The signal stops once this limit is reached. |
| `enable_safe_crm_addition` | boolean | No | Auto-add discovered accounts to CRM. New/unassigned accounts are created and assigned to you; existing accounts get signals enriched. Ownership is never changed. |
| `auto_enrich_people_emails` | boolean | No | Automatically enrich discovered people with work emails. Requires people_audience_name to be set. Uses email enrichment credits. |

```bash
curl -X POST 'https://api.orth.sh/v1/run' \
  -H 'Authorization: Bearer $ORTHOGONAL_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{"api":"openfunnel","path":"/api/v1/signal/deploy/icp-job-change-agent","body":{"name":"<string>","icp_id":"<integer>","repeat":"<boolean>","account_audience_name":"<string>","people_audience_name":"<string>","max_credit_limit":"<integer>","enable_safe_crm_addition":"<boolean>","auto_enrich_people_emails":"<boolean>"}}'
```

### Create ICP

Create a new Ideal Customer Profile (ICP).

An ICP defines the target company and people segments for signal discovery.

**Before calling this endpoint**, call `GET /api/v1/icp/options` to retrieve
all valid values for employee_ranges, funding stages, locations, and sub_locations.

**Required fields:**

- **name**: A descriptive name for the ICP (e.g., "Mid-market SaaS companies in US").
- **target_roles**: List of job titles or role descriptions to target.
  Examples: ["Head of Engineering", "VP of Product", "Senior Leaders in Engineering & Product"].
- **employee_ranges**: Company size filters. Provide one or more range labels from
  the `employee_ranges` list returned by `/api/v1/icp/options`.
  Multiple ranges are collapsed to an overall min/max employee count internally.
- **location**: List of company HQ location codes. Use the `value` field from the
  `locations` list returned by `/api/v1/icp/options` (e.g., ["us", "uk", "ca"]).

**Optional fields:**

- **min_funding** / **max_funding**: Funding stage range. Both must be provided together.
  Use values from the `funding_stages` list returned by `/api/v1/icp/options`.
- **employee_count_funding_config**: How to combine employee count and funding criteria.
  Only valid when funding is set. Values: `"AND"` (company must match both employee count
  AND funding stage) or `"OR"` (company must match either). Omit or set to null if no
  combination logic is needed.
- **sub_locations**: US state or city codes. Use the `value` field from the
  `sub_locations` list returned by `/api/v1/icp/options`
  (e.g., ["ca", "san-francisco-ca", "ny"]).
  **Only applicable when `location` is exclusively `["us"]`.**
- **people_locations**: Geographic filter for target people. Use the `value` field from
  the `people_locations` list returned by `/api/v1/icp/options` (e.g., ["us", "ca"]).
- **people_sub_locations**: Sub-region codes for people locations. Use the `value` field
  from the `people_sub_locations` list returned by `/api/v1/icp/options`
  (e.g., ["san-francisco-ca", "austin-tx"]).
  **Only applicable when `people_locations` is exclusively `["us"]`.**

`POST /api/v1/icp/create`

**Cost:** Free

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `name` | string | Yes |  |
| `target_roles` | string[] | Yes |  |
| `employee_ranges` | string[] | Yes |  |
| `location` | string[] | Yes |  |
| `min_funding` | string | No |  |
| `max_funding` | string | No |  |
| `employee_count_funding_config` | enum<string> | No |  |
| `sub_locations` | string[] | No |  |
| `people_locations` | string[] | No |  |
| `people_sub_locations` | string[] | No |  |

```bash
curl -X POST 'https://api.orth.sh/v1/run' \
  -H 'Authorization: Bearer $ORTHOGONAL_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{"api":"openfunnel","path":"/api/v1/icp/create","body":{"name":"<string>","target_roles":"<string>","employee_ranges":"<string>","location":"<string>","min_funding":"<string>","max_funding":"<string>","employee_count_funding_config":"<string>","sub_locations":"<string>","people_locations":"<string>","people_sub_locations":"<string>"}}'
```

### Insight Detail

Get full detail for a single insight.
Returns the insight with its underlying signal data and related insights
from the same account.

`GET /api/v1/insights/{insight_id}`

**Cost:** Free

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `insight_id` | string | Yes | Path parameter — substitute directly into the endpoint `path`. |

```bash
# Replace {insight_id} in "path" with real values before sending
curl -X POST 'https://api.orth.sh/v1/run' \
  -H 'Authorization: Bearer $ORTHOGONAL_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{"api":"openfunnel","path":"/api/v1/insights/{insight_id}","method":"GET"}'
```

### My Alerts

Get alerts (notifications) sent to the authenticated user.

Returns notification history with the actual insights from each alert.
Always scoped to the individual user who set up the saved view.

`GET /api/v1/insights/alerts`

**Cost:** Free

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `days` | integer | No | Number of days back to look |
| `limit` | integer | No | Maximum alerts per page |
| `offset` | integer | No | Number of alerts to skip |

```bash
curl -X POST 'https://api.orth.sh/v1/run' \
  -H 'Authorization: Bearer $ORTHOGONAL_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{"api":"openfunnel","path":"/api/v1/insights/alerts","method":"GET","query":{"days":"<integer>","limit":"<integer>","offset":"<integer>"}}'
```

### Create Account Audience Endpoint

Create Account Audience Endpoint

`POST /api/v1/audience/create-account-audience`

**Estimated cost:** Dynamic — use `"dryRun": true` in the Run API request to check the exact cost before calling.

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `name` | string | Yes | Name for the new audience |
| `account_ids` | integer[] | Yes | List of account IDs to include |

```bash
curl -X POST 'https://api.orth.sh/v1/run' \
  -H 'Authorization: Bearer $ORTHOGONAL_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{"api":"openfunnel","path":"/api/v1/audience/create-account-audience","body":{"name":"<string>","account_ids":"<integer>"}}'
```

### Get Summary

Get comprehensive account summary for quick overview.Returns a single-call overview including:Basic account informationSignal counts by typeRecent signals (last 5)People count and key contactsCRM statusTagsArgs:account_id: The account ID to get summary foruser_id: Authenticated user ID (from API key)Returns:AccountSummary with all overview information

`GET /api/v1/account/{account_id}/summary`

**Cost:** Free

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `account_id` | string | Yes | Path parameter — substitute directly into the endpoint `path`. |

```bash
# Replace {account_id} in "path" with real values before sending
curl -X POST 'https://api.orth.sh/v1/run' \
  -H 'Authorization: Bearer $ORTHOGONAL_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{"api":"openfunnel","path":"/api/v1/account/{account_id}/summary","method":"GET"}'
```

### Get Audience

Get audience details by ID.

`POST /api/v1/audience`

**Cost:** Free

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `audience_id` | integer | Yes | Audience ID to get details for |

```bash
curl -X POST 'https://api.orth.sh/v1/run' \
  -H 'Authorization: Bearer $ORTHOGONAL_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{"api":"openfunnel","path":"/api/v1/audience","body":{"audience_id":"<integer>"}}'
```

### List Audiences

List audiences with optional pagination.

`POST /api/v1/audience/get-audience-list`

**Cost:** Free

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `pagination` | PaginationParams · object | No | Request to list audiences with optional pagination. |

```bash
curl -X POST 'https://api.orth.sh/v1/run' \
  -H 'Authorization: Bearer $ORTHOGONAL_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{"api":"openfunnel","path":"/api/v1/audience/get-audience-list","body":{"pagination":"<object>"}}'
```

### Check Job Status

Check the status of a CRM sync job.
Returns the current status and, when completed, the full sync results.
Status values:

pending: Job created, not yet started
running: Sync is in progress
completed: Sync finished - check result field for details
failed: Sync failed - check error_message for details

Polling recommendation: Poll every 3-5 seconds.

`POST /api/v1/crm/check-job-status`

**Cost:** Free

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `job_id` | string | Yes | Job ID returned from sync-accounts-job or sync-people-job |

```bash
curl -X POST 'https://api.orth.sh/v1/run' \
  -H 'Authorization: Bearer $ORTHOGONAL_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{"api":"openfunnel","path":"/api/v1/crm/check-job-status","body":{"job_id":"<string>"}}'
```

### Update ICP

Update an existing Ideal Customer Profile (ICP).

Only the fields included in the request body will be modified — all other
fields remain unchanged. The `id` field is always required to identify
which ICP to update.

**Before calling this endpoint**, call `GET /api/v1/icp/options` to retrieve
all valid values for employee_ranges, funding stages, locations, and sub_locations.

**Required fields:**

- **id**: The numeric ID of the ICP to update (returned by `/api/v1/icp/list`
  or `/api/v1/icp/create`).

**Updatable fields (all optional — include only what you want to change):**

- **name**: A descriptive name for the ICP. Must be non-empty and unique
  among the user's ICPs.
- **target_roles**: List of job titles or role descriptions to target.
  Must contain at least one role if provided.
  Examples: ["Head of Engineering", "VP of Product"].
- **employee_ranges**: Company size filters. Provide one or more range labels
  from the `employee_ranges` list returned by `/api/v1/icp/options`.
  Must contain at least one range if provided.
- **location**: List of company HQ location codes. Use the `value` field from
  the `locations` list returned by `/api/v1/icp/options` (e.g., ["us", "uk"]).
  Must contain at least one location if provided.
- **min_funding** / **max_funding**: Funding stage bounds. Each can be updated
  independently. Set to `null` to clear (stored as `"Any"`). A value of `"Any"`
  means no constraint on that bound. Use values from the `funding_stages` list
  returned by `/api/v1/icp/options`.
- **employee_count_funding_config**: How to combine employee count and funding
  criteria. Values: `"AND"` or `"OR"`. Only valid when funding is set. Set to
  `null` to clear.
- **sub_locations**: US state or city codes. Use the `value` field from the
  `sub_locations` list returned by `/api/v1/icp/options`
  (e.g., ["ca", "san-francisco-ca"]). **Only applicable when `location` is
  exclusively `["us"]`.** Set to `null` or `[]` to clear. If changing `location`
  away from `["us"]`, you must also clear this field.
- **people_locations**: Geographic filter for target people. Use the `value`
  field from the `people_locations` list returned by `/api/v1/icp/options`.
  Set to `null` or `[]` to clear.
- **people_sub_locations**: Sub-region codes for people locations. Use the
  `value` field from the `people_sub_locations` list returned by
  `/api/v1/icp/options`. **Only applicable when `people_locations` is
  exclusively `["us"]`.** Set to `null` or `[]` to clear. If changing
  `people_locations` away from `["us"]`, you must also clear this field.

**Cross-field validation:**

- `sub_locations` requires `location` to be `["us"]` (checked against the
  final merged state, not just the request).
- `people_sub_locations` requires `people_locations` to be `["us"]`.
- `employee_count_funding_config` requires at least one of `min_funding` or
  `max_funding` to be a non-`"Any"` value.

`PATCH /api/v1/icp/update`

**Cost:** Free

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `id` | integer | Yes |  |
| `name` | string | No |  |
| `target_roles` | string[] | No |  |
| `employee_ranges` | string[] | No |  |
| `min_funding` | string | No |  |
| `max_funding` | string | No |  |
| `employee_count_funding_config` | enum<string> | No |  |
| `location` | string[] | No |  |
| `sub_locations` | string[] | No |  |
| `people_locations` | string[] | No |  |
| `people_sub_locations` | string[] | No |  |

```bash
curl -X POST 'https://api.orth.sh/v1/run' \
  -H 'Authorization: Bearer $ORTHOGONAL_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{"api":"openfunnel","path":"/api/v1/icp/update","method":"PATCH","body":{"id":"<integer>","name":"<string>","target_roles":"<string>","employee_ranges":"<string>","min_funding":"<string>","max_funding":"<string>","employee_count_funding_config":"<string>","location":"<string>","sub_locations":"<string>","people_locations":"<string>","people_sub_locations":"<string>"}}'
```

---

Full details and an interactive quickstart: https://orthogonal.com/discover/openfunnel
