# Ocean.io — 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)

Ocean.io API for company and people search, enrichment, lookup, and discovery. Find lookalike companies, enrich contacts, reveal emails/phones, and more.

**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

### Lookalike Company Search

Search for companies using filters (industry, size, location, technologies, revenue, headcount growth, etc.) and/or lookalike domains. Returns enriched company profiles. Use the size parameter to control max results (1-10,000), defaults to 50. Use searchAfter from the previous response to paginate.

`POST /v3/search/companies`

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

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `size` | integer | No | Max results to return (1-10,000). Default: 50. |
| `searchAfter` | string | No | Pagination cursor returned by the previous response to get the next page of results. |
| `companiesFilters` | object | No | Company filters object with these fields: lookalikeDomains: string[] (domains to find similar companies), includeDomains: string[] (only return these domains), excludeDomains: string[] (exclude these domains), companySizes: string[] (enum: "0-1", "2-10", "11-50", "51-200", "201-500", "501-1000", "1001-5000", "5001-10000", "10001-50000", "50001-100000", "100001-500000", "500000+"), revenues: string[] (enum: "0-1M", "1-10M", "10-50M", "50-100M", "100-500M", "500-1000M", ">1000M"), primaryLocations: object {includeCountries: string[] (ISO 3166 alpha-2 codes), excludeCountries: string[], includeRegions: object[] ({country: string, region: string}), excludeRegions: object[], includeCities: object[] ({country: string, city: string}), excludeCities: object[], geolocation: object {latitude: number, longitude: number, radius: integer (meters)}}, otherLocations: object (same structure as primaryLocations), industries: object {industries: string[] (values from /v2/data-fields), mode: string ("anyOf"\|"allOf")}, excludeIndustries: string[], industryCategories: object {industryCategories: string[], mode: string}, excludeIndustryCategories: string[], linkedinIndustries: string[], excludeLinkedinIndustries: string[], technologies: object {apps: object {anyOf: string[], allOf: string[], noneOf: string[]}, categories: object {anyOf: string[], allOf: string[], noneOf: string[]}}, keywords: object {anyOf: string[], allOf: string[], noneOf: string[]}, yearFounded: object {from: integer, to: integer}, employeeCountOcean: object {from: integer, to: integer}, employeeCountLinkedin: object {from: integer, to: integer}, ecommerce: boolean, headcountGrowth: object {asPercentage: boolean (required), growthRange: object {from: number, to: number} (required), months: string (enum: "Three months", "Six months", "Twelve months") (required)}, departmentHeadcountGrowth: object {anyOf: object[], allOf: object[]}, webTraffic: object {visits: object {from: integer, to: integer}, views: object {from: integer, to: integer}}, socialMedias: object {medias: object {anyOf: string[], allOf: string[], noneOf: string[]}, minCount: integer}, mobileApps: object {from: integer, to: integer}, fundingRound: object {types: string[] (enum: "Seed", "Series A", "Angel", "Series B", "Pre-Seed", "Grant", "Series C", "Convertible Note", "Debt Financing", "Series D", "Corporate Round", "Private Equity", etc.), raised: object {from: integer, to: integer}, date: object {from: string (YYYY-MM-DD), to: string}}, locationsCount: object {from: integer, to: integer}, countriesCount: object {from: integer, to: integer}, departmentSizes: object[] ({department: string, from: integer, to: integer}), updatedWithinMonths: integer, minRelevance: string (A is most relevant), maxRelevance: string, companyMatchingMode: string ("precise"\|"broad") |
| `peopleFilters` | object | No | People filters to find companies with matching employees: lookalikeLinkedinHandles: string[], countries: string[] (ISO 3166 alpha-2), excludeCountries: string[], regions: string[], states: object[] ({country: string, abbreviation: string}), excludeStates: object[], cities: object[] ({country: string, city: string}), names: string[], seniorities: string[] (enum: "Owner", "Founder", "Board Member", "C-Level", "Partner", "VP", "Head", "Director", "Manager", "Other"), departments: string[] (enum: "Accounting and Finance", "Board", "Business Support", "Customer Relations", "Design", "Editorial Personnel", "Engineering", "Founder/Owner", "Healthcare", "HR", "Legal", "Management", "Manufacturing", "Marketing and Advertising", "Operations", "PR and Communications", "Procurement", "Product", "Quality Control", "R&D", "Sales", "Security", "Supply Chain", "Other"), jobTitleKeywords: object {anyOf: string[], allOf: string[], noneOf: string[]}, skills: object {anyOf: string[], allOf: string[], noneOf: string[]}, allJobDescriptions: object {anyOf: string[], allOf: string[], noneOf: string[]}, currentJobDescription: object {anyOf: string[], allOf: string[], noneOf: string[]}, profileDescription: object {anyOf: string[], allOf: string[], noneOf: string[]}, includePeopleIds: string[], includeLinkedinHandles: string[], excludePeopleIds: string[], excludeLinkedinHandles: string[], fieldsExist: string[], fieldsNotExist: string[], changedPositionAfter: string (YYYY-MM-DD), changedPositionBefore: string (YYYY-MM-DD), updatedWithinMonths: integer |
| `fields` | array | No | string[] - Fields to return in Company objects (reduces bandwidth). Options: "domain", "countries", "primaryCountry", "companySize", "industryCategories", "industries", "linkedinIndustry", "ecommerce", "keywords", "employeeCountOcean", "employeeCountLinkedin", "revenue", "yearFounded", "description", "emails", "phones", "logo", "technologies", "technologyCategories", "mobileApps", "webTraffic", "medias", "name", "legalName", "locations", "departmentSizes", "rootUrl", "faxes", "impressum", "fundingRound", "redirectedFrom", "updatedAt", "headcountGrowth", "headcountGrowthPerDepartment". Nested fields also supported (e.g. "phones.number", "webTraffic.visits", "medias.linkedin", "locations.country"). |

```bash
curl -X POST 'https://api.orth.sh/v1/run' \
  -H 'Authorization: Bearer $ORTHOGONAL_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{"api":"ocean-io","path":"/v3/search/companies","body":{"size":"<integer>","searchAfter":"<string>","companiesFilters":"<object>","peopleFilters":"<object>","fields":"<array>"}}'
```

### Get Data Fields

Returns all valid filter values for Ocean.io search endpoints: industries, industry categories, technologies, technology categories, regions, LinkedIn industries, departments, seniorities, and company sizes. Use these values when building search filters.

`GET /v2/data-fields`

**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":"ocean-io","path":"/v2/data-fields","method":"GET"}'
```

### Warmup Companies

Check available companies in Ocean.io database and trigger data gathering for missing ones. Use before searching to improve coverage for specific domains.

`POST /v2/warmup/companies`

**Cost:** Free

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `domains` | array | Yes | string[] - List of company website domains to check availability and trigger data gathering for missing ones. Example: ["newstartup.com", "example.io"] |

```bash
curl -X POST 'https://api.orth.sh/v1/run' \
  -H 'Authorization: Bearer $ORTHOGONAL_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{"api":"ocean-io","path":"/v2/warmup/companies","body":{"domains":"<array>"}}'
```

### Lookalike People Search

Search for people using filters (job title, seniority, department, skills, location) with optional company filters. Returns enriched person profiles. Use the size parameter to control max results (1-10,000). Use searchAfter from the previous response to paginate.

`POST /v3/search/people`

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

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `size` | integer | No | Max results to return (1-10,000). Default: 50. |
| `searchAfter` | string | No | Pagination cursor returned by the previous response to get the next page of results. |
| `peopleFilters` | object | No | People filters object. Fields: lookalikeLinkedinHandles: string[], countries: string[] (ISO 3166 alpha-2), excludeCountries: string[], regions: string[], states: object[] ({country: string, abbreviation: string}), excludeStates: object[], cities: object[] ({country: string, city: string}), names: string[], seniorities: string[] (enum: "Owner", "Founder", "Board Member", "C-Level", "Partner", "VP", "Head", "Director", "Manager", "Other"), departments: string[] (enum: "Accounting and Finance", "Board", "Business Support", "Customer Relations", "Design", "Editorial Personnel", "Engineering", "Founder/Owner", "Healthcare", "HR", "Legal", "Management", "Manufacturing", "Marketing and Advertising", "Operations", "PR and Communications", "Procurement", "Product", "Quality Control", "R&D", "Sales", "Security", "Supply Chain", "Other"), jobTitleKeywords: object {anyOf: string[], allOf: string[], noneOf: string[]}, skills: object {anyOf: string[], allOf: string[], noneOf: string[]}, allJobDescriptions: object {anyOf: string[], allOf: string[], noneOf: string[]}, currentJobDescription: object {anyOf: string[], allOf: string[], noneOf: string[]}, profileDescription: object {anyOf: string[], allOf: string[], noneOf: string[]}, includePeopleIds: string[], includeLinkedinHandles: string[], excludePeopleIds: string[], excludeLinkedinHandles: string[], fieldsExist: string[], fieldsNotExist: string[], changedPositionAfter: string (YYYY-MM-DD), changedPositionBefore: string (YYYY-MM-DD), updatedWithinMonths: integer |
| `companiesFilters` | object | No | Company filters to scope people search. Fields: lookalikeDomains: string[], includeDomains: string[], excludeDomains: string[], companySizes: string[] (enum: "0-1", "2-10", "11-50", "51-200", "201-500", "501-1000", "1001-5000", "5001-10000", "10001-50000", "50001-100000", "100001-500000", "500000+"), revenues: string[] (enum: "0-1M", "1-10M", "10-50M", "50-100M", "100-500M", "500-1000M", ">1000M"), primaryLocations: object {includeCountries: string[], excludeCountries: string[], includeRegions: object[], excludeRegions: object[], includeCities: object[], excludeCities: object[], geolocation: object {latitude: number, longitude: number, radius: integer}}, otherLocations: object (same as primaryLocations), industries: object {industries: string[], mode: string ("anyOf"\|"allOf")}, industryCategories: object {industryCategories: string[], mode: string}, technologies: object {apps: object {anyOf: string[], allOf: string[], noneOf: string[]}, categories: object {anyOf: string[], allOf: string[], noneOf: string[]}}, keywords: object {anyOf: string[], allOf: string[], noneOf: string[]}, yearFounded: object {from: integer, to: integer}, employeeCountOcean: object {from: integer, to: integer}, employeeCountLinkedin: object {from: integer, to: integer}, ecommerce: boolean, headcountGrowth: object {asPercentage: boolean, growthRange: object {from: number, to: number}, months: string ("Three months"\|"Six months"\|"Twelve months")}, fundingRound: object {types: string[], raised: object {from: integer, to: integer}, date: object {from: string, to: string}}, updatedWithinMonths: integer, minRelevance: string, maxRelevance: string |
| `peoplePerCompany` | integer | No | Number of people to return per company. If unset, returns all matching people. |
| `jobTitleThreshold` | number | No | Job title similarity threshold (0-1). Controls how strictly job titles are matched. |
| `fields` | array | No | string[] - Fields to return in Person objects (reduces bandwidth). Options: "id", "domain", "name", "firstName", "lastName", "country", "state", "location", "linkedinUrl", "seniorities", "departments", "photo", "jobTitle", "jobTitleEnglish", "currentJobDescription", "experiences", "summary", "skills", "email", "updatedAt". Nested fields: "experiences.domain", "experiences.jobTitle", "experiences.dateFrom", "experiences.dateTo", "experiences.description", "experiences.linkedinCompanyHandle", "email.address". |

```bash
curl -X POST 'https://api.orth.sh/v1/run' \
  -H 'Authorization: Bearer $ORTHOGONAL_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{"api":"ocean-io","path":"/v3/search/people","body":{"size":"<integer>","searchAfter":"<string>","peopleFilters":"<object>","companiesFilters":"<object>","peoplePerCompany":"<integer>","jobTitleThreshold":"<number>","fields":"<array>"}}'
```

### Lookup People

Lookup and enrich multiple people by LinkedIn handle or Ocean.io ID (max 1000 total). Costs 0.05 credits per handle/ID. People not found return null.

`POST /v2/lookup/people`

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

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `linkedinHandles` | array | No | string[] - List of LinkedIn profile handles to lookup (e.g. ["john-doe", "jane-smith"]). Max 1000 combined with oceanIds. Cost: 0.05 credits per handle. |
| `oceanIds` | array | No | string[] - List of Ocean.io person IDs to lookup. Max 1000 combined with linkedinHandles. Cost: 0.05 credits per ID. |
| `fields` | array | No | string[] - Fields to return in Person objects (reduces bandwidth). If not specified, all fields returned. Options: "id", "domain", "name", "firstName", "lastName", "country", "state", "location", "linkedinUrl", "seniorities", "departments", "photo", "jobTitle", "jobTitleEnglish", "currentJobDescription", "experiences", "summary", "skills", "email", "updatedAt". Nested: "experiences.domain", "experiences.jobTitle", "experiences.dateFrom", "experiences.dateTo", "experiences.description", "experiences.linkedinCompanyHandle", "email.address". |

```bash
curl -X POST 'https://api.orth.sh/v1/run' \
  -H 'Authorization: Bearer $ORTHOGONAL_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{"api":"ocean-io","path":"/v2/lookup/people","body":{"linkedinHandles":"<array>","oceanIds":"<array>","fields":"<array>"}}'
```

### Enrich Company

Match a company with Ocean.io database and enrich it with additional information (industry, size, revenue, technologies, contacts, etc.).

`POST /v2/enrich/company`

**Estimated cost:** $0.01

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `company` | object | No | object - Company to match. Fields: domain: string (company website domain, e.g. "stripe.com"), name: string (company name), registrationNumber: string (company registration number), email: string (company email), phone: string (company phone), countryCode: string (ISO 3166 alpha-2), state: string, city: string, streetAddress: string, postalCode: string, address: string (full address), facebook: string (Facebook handle), twitter: string (Twitter handle), linkedin: string (LinkedIn company handle), instagram: string, xing: string, youtube: string |
| `people` | array | No | object[] - People to help match company (improves accuracy). Each element: id: string (Ocean.io person ID), name: string (full name), firstName: string, lastName: string, jobTitle: string, email: string, phone: string, facebook: string (Facebook handle), twitter: string (Twitter handle), linkedin: string (LinkedIn handle, NOT full URL, e.g. "satyanadella"), country: string (ISO 3166 alpha-2) |
| `fields` | array | No | string[] - Fields to return in Company objects (reduces bandwidth). If not specified, all fields returned. Options: "domain", "countries", "primaryCountry", "companySize", "industryCategories", "industries", "linkedinIndustry", "ecommerce", "keywords", "employeeCountOcean", "employeeCountLinkedin", "revenue", "yearFounded", "description", "emails", "phones", "logo", "technologies", "technologyCategories", "mobileApps", "webTraffic", "medias", "name", "legalName", "locations", "departmentSizes", "rootUrl", "faxes", "impressum", "fundingRound", "redirectedFrom", "updatedAt", "headcountGrowth", "headcountGrowthPerDepartment". Nested fields also supported: "phones.number", "phones.country", "phones.primary", "webTraffic.visits", "webTraffic.pageViews", "webTraffic.pagesPerVisit", "medias.linkedin", "medias.twitter", "medias.youtube", "medias.facebook", "medias.xing", "medias.tiktok", "medias.instagram", "locations.primary", "locations.country", "locations.locality", "locations.region", "locations.postalCode", "locations.streetAddress", "locations.state", "locations.regionCode", "mobileApps.link", "mobileApps.name", "faxes.number", "faxes.country", "faxes.primary", "impressum.company", "impressum.address", "impressum.email", "impressum.phone", "impressum.fax", "impressum.vat", "impressum.url", "impressum.people", "fundingRound.date", "fundingRound.type", "fundingRound.moneyRaisedInUsd", "fundingRound.cbUrl", "headcountGrowth.threeMonths", "headcountGrowth.threeMonthsPercentage", "headcountGrowth.sixMonths", "headcountGrowth.sixMonthsPercentage", "headcountGrowth.twelveMonths", "headcountGrowth.twelveMonthsPercentage". |

```bash
curl -X POST 'https://api.orth.sh/v1/run' \
  -H 'Authorization: Bearer $ORTHOGONAL_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{"api":"ocean-io","path":"/v2/enrich/company","body":{"company":"<object>","people":"<array>","fields":"<array>"}}'
```

### Enrich Person

Match a person with Ocean.io database and enrich with additional information (job title, company, location, social profiles, etc.).

`POST /v2/enrich/person`

**Estimated cost:** $0.01

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `person` | object | Yes | object - Person to match. Fields: id: string (Ocean.io person ID), name: string (full name), firstName: string, lastName: string, jobTitle: string, email: string, phone: string, facebook: string (Facebook handle), twitter: string (Twitter handle), linkedin: string (LinkedIn handle, NOT full URL, e.g. "satyanadella"), country: string (ISO 3166 alpha-2) |
| `company` | object | No | object - Company context to improve person matching. Fields: domain: string (company website domain, e.g. "stripe.com"), name: string (company name), registrationNumber: string (company registration number), email: string (company email), phone: string (company phone), countryCode: string (ISO 3166 alpha-2), state: string, city: string, streetAddress: string, postalCode: string, address: string (full address), facebook: string (Facebook handle), twitter: string (Twitter handle), linkedin: string (LinkedIn company handle), instagram: string, xing: string, youtube: string |

```bash
curl -X POST 'https://api.orth.sh/v1/run' \
  -H 'Authorization: Bearer $ORTHOGONAL_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{"api":"ocean-io","path":"/v2/enrich/person","body":{"person":"<object>","company":"<object>"}}'
```

### Lookup Companies

Lookup and enrich multiple companies by domain (max 1000). Domain redirections are handled automatically. Companies not found return null.

`POST /v2/lookup/companies`

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

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `domains` | array | Yes | string[] - List of company website domains to lookup (max 1000). Domain redirections handled automatically. Example: ["stripe.com", "google.com"] |
| `fields` | array | No | string[] - Fields to return in Company objects (reduces bandwidth). If not specified, all fields returned. Options: "domain", "countries", "primaryCountry", "companySize", "industryCategories", "industries", "linkedinIndustry", "ecommerce", "keywords", "employeeCountOcean", "employeeCountLinkedin", "revenue", "yearFounded", "description", "emails", "phones", "logo", "technologies", "technologyCategories", "mobileApps", "webTraffic", "medias", "name", "legalName", "locations", "departmentSizes", "rootUrl", "faxes", "impressum", "fundingRound", "redirectedFrom", "updatedAt", "headcountGrowth", "headcountGrowthPerDepartment". |

```bash
curl -X POST 'https://api.orth.sh/v1/run' \
  -H 'Authorization: Bearer $ORTHOGONAL_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{"api":"ocean-io","path":"/v2/lookup/companies","body":{"domains":"<array>","fields":"<array>"}}'
```

---

Full details and an interactive quickstart: https://orthogonal.com/discover/ocean-io
