# Crustdata — Orthogonal API

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

Comprehensive B2B data platform providing firmographic data, growth metrics, people profiles, and web intelligence for companies worldwide.

**Verified:** yes

## Access

**Run API:** `POST https://api.orthogonal.com/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

### Person Enrichment

Enrich one or more individuals by LinkedIn URL or business email. Returns employment history, education, skills, contact info, and GitHub profiles. Provide at least one of linkedin_profile_url or business_email. Multiple values can be comma-separated. Use fields to select specific data and reduce response size.

`GET /screener/person/enrich`

**Estimated cost:** $1.563

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `linkedin_profile_url` | string | No | Comma-separated LinkedIn profile URLs to enrich (e.g. "https://www.linkedin.com/in/satyanadella"). |
| `business_email` | string | No | Comma-separated business email addresses to enrich. |
| `enrich_realtime` | boolean | No | If true, performs real-time web search when data not found in database. Slower but finds more profiles. |
| `fields` | string | No | Comma-separated fields to return. Recommended: "name,title,headline,email,current_employers,past_employers,education_background,skills,linkedin_profile_url,linkedin_flagship_url". Available fields: name, location, email, title, last_updated, headline, summary, num_of_connections, skills, profile_picture_url, profile_picture_permalink, twitter_handle, languages, all_employers, past_employers, current_employers, education_background, all_titles, all_schools, all_degrees, linkedin_profile_url, linkedin_flagship_url. NOT AVAILABLE (access denied): github_profiles, personal_contact_info.personal_emails, personal_contact_info.phone_numbers. |

```bash
curl -X POST 'https://api.orthogonal.com/v1/run' \
  -H 'Authorization: Bearer $ORTHOGONAL_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{"api":"crustdata","path":"/screener/person/enrich","method":"GET","query":{"linkedin_profile_url":"<string>","business_email":"<string>","enrich_realtime":"<boolean>","fields":"<string>"}}'
```

### Company Enrichment

Enrich one or more companies by domain, name, or Crustdata company ID. Returns comprehensive firmographic data: headcount, revenue, funding, employer reviews, web traffic, news, job openings, founders, and decision makers. Provide at least one of company_domain, company_name, or company_id. Multiple values can be comma-separated (e.g. company_domain=stripe.com,hubspot.com).

`GET /screener/company`

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

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `company_domain` | string | No | Comma-separated company domains (e.g. "stripe.com,hubspot.com"). Use this OR company_name OR company_id. |
| `company_name` | string | No | Comma-separated company names to enrich. |
| `company_id` | string | No | Comma-separated Crustdata company IDs. |
| `fields` | string | No | Comma-separated fields to return. Omit for all defaults. Examples: company_name, company_website_domain, headcount.headcount, linkedin_company_url, founded_year, company_type, industry, job_openings, news_articles, decision_makers, founders.profiles. Use fields to reduce large payloads. |
| `enrich_realtime` | string | No | Set to "True" to enrich companies not yet in database in real-time (takes ~10 minutes). |

```bash
curl -X POST 'https://api.orthogonal.com/v1/run' \
  -H 'Authorization: Bearer $ORTHOGONAL_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{"api":"crustdata","path":"/screener/company","method":"GET","query":{"company_domain":"<string>","company_name":"<string>","company_id":"<string>","fields":"<string>","enrich_realtime":"<string>"}}'
```

### Company Identification

Identify one or more companies in Crustdata's database by domain, name, LinkedIn URL, Crunchbase URL, or company ID. Returns matching companies with relevance scores. Only one identifier field is needed.

`POST /screener/identify/`

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

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `query_company_name` | string | No | Name of the company to identify. |
| `query_company_website` | string | No | Company website domain (e.g. "hubspot.com"). |
| `query_company_linkedin_url` | string | No | LinkedIn profile URL of the company. |
| `query_company_crunchbase_url` | string | No | Crunchbase profile URL of the company. |
| `query_company_id` | string | No | Company ID in Crustdata's database. |
| `count` | integer | No | Maximum number of results to return. Default: 10. |

```bash
curl -X POST 'https://api.orthogonal.com/v1/run' \
  -H 'Authorization: Bearer $ORTHOGONAL_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{"api":"crustdata","path":"/screener/identify/","body":{"query_company_name":"<string>","query_company_website":"<string>","query_company_linkedin_url":"<string>","query_company_crunchbase_url":"<string>","query_company_id":"<string>","count":"<integer>"}}'
```

### Job Listings

Get job listings from Crustdata's database. Filter by company, date, location, and more. Returns a fields-and-rows structure where fields describe column names/types and rows contain the data. Use Company Identification endpoint first to get company_id values for filtering. Pagination billing: call the first page normally and save billing.requestId from the Orthogonal /v1/run response. For later page, offset, or cursor calls on the same logical search, pass parentRequestId with unchanged non-pagination parameters. Valid continuation calls still get their own request IDs and quoted price, but are charged 0. Changing filters starts a new billable request.

`POST /data_lab/job_listings/Table/`

**Estimated cost:** $0.313

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `dataset` | object | Yes | Must be {"name": "job_listings", "id": "joblisting"}. |
| `filters` | object | Yes | Filter object: {"op": "and", "conditions": [...]}. Each condition: {"column": "...", "type": "...", "value": ...}. Key columns: company_id (type: "in", value: [7576, 680992]), date_updated (type: ">", value: "2024-01-01"), job_title_name, job_location, remote_status. Types: "in", "not in", ">", "<", ">=", "<=", "=". |
| `offset` | integer | No | Pagination offset. Default: 0. For later offset pages of the same logical search, keep non-pagination parameters unchanged and pass top-level parentRequestId from the first Orthogonal /v1/run response. |
| `count` | integer | No | Number of rows to return (min: 1). Default: 100. |
| `sorts` | array | No | Sorting criteria array. Usually empty []. |
| `tickers` | array | No | Ticker symbols. Usually empty []. |
| `groups` | array | No | Grouping. Usually empty []. |
| `aggregations` | array | No | Aggregations. Usually empty []. |
| `functions` | array | No | Functions. Usually empty []. |

```bash
curl -X POST 'https://api.orthogonal.com/v1/run' \
  -H 'Authorization: Bearer $ORTHOGONAL_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{"api":"crustdata","path":"/data_lab/job_listings/Table/","body":{"dataset":"<object>","filters":"<object>","offset":"<integer>","count":"<integer>","sorts":"<array>","tickers":"<array>","groups":"<array>","aggregations":"<array>","functions":"<array>"}}'
```

### Gartner Reviews

Get Gartner Peer Insights review data for companies. Filter by review rating, company ID, and other metrics. Returns a fields-and-rows structure. Note: requires Crustdata credits for this dataset. Pagination billing: call the first page normally and save billing.requestId from the Orthogonal /v1/run response. For later page, offset, or cursor calls on the same logical search, pass parentRequestId with unchanged non-pagination parameters. Valid continuation calls still get their own request IDs and quoted price, but are charged 0. Changing filters starts a new billable request.

`POST /data_lab/gartner_reviews/Table/`

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

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `dataset` | object | Yes | Must be {"name": "gartner_reviews", "id": "gartnerreview"}. |
| `filters` | object | Yes | Filter object: {"op": "and", "conditions": [...]}. Each condition: {"column": "...", "type": "...", "value": ...}. Key columns: gartner_review_overall_rating (type: "=>", value: "4"), company_id (type: "in", value: [...]). Types: "in", "=>", "<=", "=". |
| `offset` | integer | No | Pagination offset. Default: 0. For later offset pages of the same logical search, keep non-pagination parameters unchanged and pass top-level parentRequestId from the first Orthogonal /v1/run response. |
| `limit` | integer | No | Number of results (max 100). Default: 100. |
| `sorts` | array | No | Sorting criteria. Usually empty []. |
| `tickers` | array | No | Ticker symbols. Usually empty []. |
| `groups` | array | No | Grouping. Usually empty []. |
| `aggregations` | array | No | Aggregations. Usually empty []. |
| `functions` | array | No | Functions. Usually empty []. |

```bash
curl -X POST 'https://api.orthogonal.com/v1/run' \
  -H 'Authorization: Bearer $ORTHOGONAL_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{"api":"crustdata","path":"/data_lab/gartner_reviews/Table/","body":{"dataset":"<object>","filters":"<object>","offset":"<integer>","limit":"<integer>","sorts":"<array>","tickers":"<array>","groups":"<array>","aggregations":"<array>","functions":"<array>"}}'
```

### Company Search (In-DB)

Search millions of companies in Crustdata's database with advanced filtering. Supports nested AND/OR filter logic, sorting, and cursor-based pagination. Returns up to 1000 results per request. Filter by company name, HQ country, industry, employee metrics, funding, revenue, year founded, and more. Uses (.) for fuzzy text matching and [.] for exact token matching. Note: This API is in beta. Pagination billing: call the first page normally and save billing.requestId from the Orthogonal /v1/run response. For later page, offset, or cursor calls on the same logical search, pass parentRequestId with unchanged non-pagination parameters. Valid continuation calls still get their own request IDs and quoted price, but are charged 0. Changing filters starts a new billable request.

`POST /screener/companydb/search`

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

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `filters` | object | Yes | Filter object with "op" ("and"/"or") and "conditions" array. Supports nested AND/OR logic. Each condition has: "filter_type" (field name), "type" (operator), "value". filter_type options: company_name, hq_country, hq_location, largest_headcount_country, linkedin_industries, linkedin_categories, crunchbase_categories, markets, company_website_domain, year_founded, employee_count_range, employee_metrics.latest_count, employee_metrics.growth_12m_percent, employee_metrics.growth_6m_percent, follower_metrics.latest_count, estimated_revenue_lower_bound_usd, crunchbase_total_investment_usd, crunchbase_valuation_usd, last_funding_round_type (values: seed, series_a, series_b, series_c, series_d, series_e), last_funding_date, acquisition_status, linkedin_id. Operators: "=", "!=", "in", "not_in", ">", "<", ">=", "<=", "(.)" (fuzzy text match). Example: {"op": "and", "conditions": [{"filter_type": "linkedin_industries", "type": "(.)", "value": "technology"}, {"filter_type": "employee_metrics.growth_12m_percent", "type": ">=", "value": 30}]} |
| `limit` | integer | No | Results per request (default: 20, max: 1000). |
| `cursor` | string | No | Pagination cursor from previous response (next_cursor field). For later cursor pages of the same logical search, keep non-pagination parameters unchanged and pass top-level parentRequestId from the first Orthogonal /v1/run response. |
| `sorts` | array | No | Array of sort objects. Each has "column" (field name) and "order" ("asc" or "desc"). Example: [{"column": "employee_metrics.growth_12m_percent", "order": "desc"}] |

```bash
curl -X POST 'https://api.orthogonal.com/v1/run' \
  -H 'Authorization: Bearer $ORTHOGONAL_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{"api":"crustdata","path":"/screener/companydb/search","body":{"filters":"<object>","limit":"<integer>","cursor":"<string>","sorts":"<array>"}}'
```

### People Search (In-DB)

Search millions of professional profiles in Crustdata's database with advanced filtering. Supports nested AND/OR filter logic and cursor-based pagination. Returns up to 1000 results per request with employment history, education, skills, emails, and social profiles. Pagination billing: call the first page normally and save billing.requestId from the Orthogonal /v1/run response. For later page, offset, or cursor calls on the same logical search, pass parentRequestId with unchanged non-pagination parameters. Valid continuation calls still get their own request IDs and quoted price, but are charged 0. Changing filters starts a new billable request.

`POST /screener/persondb/search`

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

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `filters` | object | Yes | Filter object with "op" ("and"/"or") and "conditions" array. Each condition has: "column" (field name), "type" (operator), "value". SUPPORTED COLUMNS: current_employers.title, current_employers.name, current_employers.seniority_level (CXO, VP, Director, Manager, Senior, Entry), past_employers.title, past_employers.name, region, skills, languages, name, first_name, last_name, headline, years_of_experience_raw, recently_changed_jobs, emails, linkedin_profile_url. SUPPORTED OPERATORS: "=", "!=", "in", "not_in", ">", "<", "(.)" (fuzzy text match). NOT SUPPORTED: "country" column (use "region" instead), "current_employers.headcount", "education_background.field_of_study", "between" operator, ">="/"<=" operators, "preview" parameter. Example: {"op": "and", "conditions": [{"column": "current_employers.seniority_level", "type": "=", "value": "CXO"}, {"column": "region", "type": "=", "value": "San Francisco Bay Area"}]} |
| `limit` | integer | No | Results per request (default: 20, max: 1000). |
| `cursor` | string | No | Pagination cursor from previous response (next_cursor field). For later cursor pages of the same logical search, keep non-pagination parameters unchanged and pass top-level parentRequestId from the first Orthogonal /v1/run response. |
| `post_processing` | object | No | Additional filtering options applied to search results. |

```bash
curl -X POST 'https://api.orthogonal.com/v1/run' \
  -H 'Authorization: Bearer $ORTHOGONAL_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{"api":"crustdata","path":"/screener/persondb/search","body":{"filters":"<object>","limit":"<integer>","cursor":"<string>","post_processing":"<object>"}}'
```

---

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