To look up a company by domain in Java, POST the domain to /v1/companies/enrich with the JDK's built-in HttpClient. You need Java 17 and an API key. No library is required.
TL;DR
- Takes about 10 minutes and one file of under 60 lines.
- Spends one LeadOcean record per company found. A domain we hold nothing for returns 404 and costs nothing.
- Handles 429 by waiting for the
Retry-Afterheader, then retrying up to five times.
Prerequisites
- Java 17 or newer. The
HttpClientAPI has been in the JDK since Java 11. - A LeadOcean API key in the environment as
$LEADOCEAN_API_KEY. The Free plan gives you one key and 1,000 records for life, no card. - A list of domains such as
acme.com. Use your own.
Step 1: Set the key and the request
Export the key in your shell, then build one reusable HttpClient. Never hard-code the key in source.
export LEADOCEAN_API_KEY="paste-your-key-here"The request is a POST to https://api.leadocean.io/v1/companies/enrich with the header x-api-key and a flat JSON body: {"domain": "acme.com"}. The same endpoint also accepts linkedin_url. See the company lookup docs (October 2026).
Step 2: Add the lookup with retries
Free allows 5 requests a second per account, Solo 50 and Agency 200. Above that the API answers 429 with a Retry-After header (limits docs, September 2026). The method below sleeps for that long and tries again.
import java.net.URI;
import java.net.http.*;
import java.nio.file.*;
import java.util.List;
public class Lookup {
static final HttpClient HTTP = HttpClient.newHttpClient();
static final String KEY = System.getenv("LEADOCEAN_API_KEY");
static String lookup(String domain) throws Exception {
var req = HttpRequest.newBuilder(URI.create("https://api.leadocean.io/v1/companies/enrich"))
.header("x-api-key", KEY).header("content-type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString("{\"domain\":\"" + domain + "\"}")).build();
for (int attempt = 0; attempt < 5; attempt++) {
var res = HTTP.send(req, HttpResponse.BodyHandlers.ofString());
switch (res.statusCode()) {
case 200: return res.body();
case 404: return null;
case 429:
long secs = Long.parseLong(res.headers().firstValue("Retry-After").orElse("1"));
Thread.sleep(secs * 1000);
break;
default: throw new IllegalStateException(res.statusCode() + " " + res.body());
}
}
throw new IllegalStateException("Still rate limited: " + domain);
}A 429 is free, so retrying does not spend records. Any other status stops the run with the body, which names the problem.
Step 3: Loop over domains and write results
Enrich returns one company per call, so there is no cursor to follow here. The loop is the paging: one request per domain, one JSON line per hit.
public static void main(String[] args) throws Exception {
var domains = List.of("acme.com", "example.org", "nosuchcompany.test");
var lines = new java.util.ArrayList<String>();
for (var d : domains) {
var json = lookup(d);
if (json == null) { System.out.println("no match: " + d); continue; }
lines.add(json.replace("\n", ""));
}
Files.write(Path.of("companies.jsonl"), lines);
System.out.println("wrote " + lines.size() + " companies");
}
}Each line in companies.jsonl is a full response. Parse it with Jackson or Gson when you need fields.
Step 4: Check your account before a big run
Before you loop over thousands of domains, read your balance. GET /v1/account and GET /v1/usage are free, so call them as often as you like.
curl -s https://api.leadocean.io/v1/account -H "x-api-key: $LEADOCEAN_API_KEY"It returns your account details and plan. Run it once before the job and once after, so you know what the job spent.
Step 5: Run it
Java 11 and later run a single source file directly, with no build step.
java Lookup.javaSave the code as Lookup.java first. The class name must match the file name. If you see Connection refused or a timeout, check your network or proxy settings, since the API is plain HTTPS on port 443.
Once it works, move the lookup method into your own service. Keep the retry loop and the 404 handling. Those two branches are what make it safe to run unattended.
Make it faster and safer
The sample is sequential on purpose. One thread at a time rarely passes even the Free plan's 5 requests a second, and it keeps the retry logic simple.
When you need speed, send several lookups at once with HttpClient.sendAsync or a fixed thread pool. Keep the pool size below your plan's requests a second. Free allows 5, Solo 50 and Agency 200.
Trim domains before you send them. Strip https://, www. and any path, and lowercase the host. A clean acme.com matches more often than https://www.Acme.com/about.
Deduplicate the list first. Looking up the same domain twice spends two records when both calls find the company. A LinkedHashSet removes repeats and keeps the order.
What you get
The program prints a line for each domain with no match, then a total of how many companies it wrote. A domain with no match costs nothing.
Each saved line has this top-level shape (response shape from the API reference, placeholder values):
{
"success": true,
"data": {
"company_data": {
"company_name": "Acme",
"company_domain": "acme.com",
"company_type": "Privately Held",
"company_industries": [{ "name2": "Software Development", "priority": 1 }],
"company_employees": { "number_of_employees": 120, "number_of_employees_code": "51-200" },
"company_primary_address": { "city": "San Francisco", "country_code": "US" },
"company_number_of_detected_technologies": 2
},
"company_detected_technologies": [
{ "technology_product": { "name": "Example CDN" }, "technology_category": { "name2": "Content Delivery Network" } }
],
"company_metrics": { "completion_score": 90, "marketability_score": 80 },
"meta": { "sources": ["own"], "schema": "leadocean.company.v1" }
},
"meta": { "source": "leadocean" }
}Response shape from the company lookup docs (October 2026), placeholder values. Fields we hold nothing for come back as null. company_data also carries funding, revenue, NAICS and SIC codes, and company_number_of_profiles when we hold them.
Troubleshooting
| Error | Cause | Fix |
|---|---|---|
| 401 | Missing or wrong x-api-key, often because $LEADOCEAN_API_KEY is not exported in this shell | Run echo $LEADOCEAN_API_KEY, then create a key at app.leadocean.io if it is blank. |
| 429 | You sent more than the plan allows: 5 a second on Free, 50 on Solo, 200 on Agency | The code already waits for Retry-After. To go faster, add a short sleep between calls or move up a plan. |
| 402 | The 1,000 free records are spent | Upgrade on the pricing page. Solo is $97 a month, Agency $497. |
| 404 | No company held for that domain | Expected, and free. Check the spelling, or try the company linkedin_url. |
FAQ
Do I need a JSON library?
Not to send the request or save the response. Add Jackson or Gson only when you want typed fields. The sample builds its one-field body by hand.
How do I look up many domains quickly?
Use a thread pool, but cap it under your plan's requests a second. The 429 retry covers short bursts.
Where does cursor paging apply?
On search, not enrich. /v1/companies/search takes a flat JSON body, limit from 1 to 100, and a cursor for the next page. One search pages to 10,000 rows. Size a list first with GET /v1/companies/count, which is free.
How much does a lookup cost?
One record for each company returned. A 404 costs nothing. See pricing for plan limits.
Is there a version for other languages?
Yes: Go, C# and TypeScript. More guides are in the blog hub.
Look up your first company by domain in Java
Free to start. No credit card. 1,000 records to spend whenever you like.
Get your free API key →