Article

A company data API response, field by field: an example account record

Six properties of a sound account record from a company data API: a stable ID, lookup keys, dated attributes, versioned labels, nulls for unknowns and safe paging. An annotated response, then three providers' domain lookups.

11 min read

An account record from a company data API is only as useful as what you can check in it. This post reads one example response field by field and draws six properties from it that a sound record carries: a stable identifier, keys to look a company up by, a date on each attribute, a version on each label, nulls that mean unknown and paging that does not skip. It then applies the same checklist to the domain lookups that Apollo, People Data Labs and Crunchbase document, so you can hold any provider's response to the same tests.

Which fields belong in the account record schema of a company enrichment API?

An account record from a company enrichment API should carry six things: a stable company identifier, the keys you can look the company up by, each attribute with the date it refers to, a version name on every label, null wherever a value is unknown, and list paging that returns every row once.

The six are properties of the record, not a list of attributes. Industry, headcount and headquarters country are the core of firmographic data, and providers name them differently. What decides whether they hold up in your systems is the frame around them: whether the record can be found again, whether each value can be aged, and whether an unknown can be told from a zero. Data enrichment writes into records you already keep, so a weak frame surfaces later as values nobody can date or trace.

Each property turns into a test you can run on sample data before you sign.

PropertyWhy it mattersTest on a sample
A stable company identifierNames, websites and tickers change; the key must notFetch the same 20 companies twice, a week apart, and compare the IDs
Keys to look a company up byYour systems hold domains, tickers, ISINs or LEIs, not the vendor's IDLook up 50 of your accounts by domain and by identifier, and count exact matches and misses
A date on each attributeA count without its date cannot be aged or comparedFind the date that goes with each attribute and compute its age on the day you load it
A version on each labelA label changes meaning when the definitions behind it changeCheck that every labelled field names the version it was set under
Null for unknownZero and unknown lead to different decisionsCount zeros in fields that cannot truly be zero, such as founding year or headcount
Paging that does not skipA skipped page is a silent gap in your copyWalk every page of one query and compare the row count with the count of distinct IDs

An example company data API response for one account record, field by field

Here is an illustrative response for Acme Robotics from the Fokals company endpoint. The record opens with a stable company ID, carries the listing's identifiers, dates its headcount by the day the count refers to, names the version of its website labels, marks generated text as AI-written and uses null where a value is unknown.

Assumptions: Acme Robotics is an invented listed company, every value below is illustrative, and only selected fields of the record are shown. Comments are added for reading; the API sends plain JSON.

GET /api/v1/companies/3f6c2a9e-8d41-4b7a-9c55-0e2f1a7b6d10
Authorization: Bearer fk_live_...
{
  "data": {
    // The stable company ID, a UUID: key your own tables on it
    "id": "3f6c2a9e-8d41-4b7a-9c55-0e2f1a7b6d10",
    "name": "Acme Robotics",
    // One of public, subsidiary, private or unknown
    "status": "public",
    "hq_country": "US",
    // Not known, so null: never 0
    "founded_year": null,
    // A headcount and the day it refers to travel together
    "employees": 1450,
    "employees_as_of": "2025-12-31",
    "domain": "acme-robotics.example",
    "ticker": "ACME",
    "exchange": "NASDAQ",
    // The listing's keys; each one is null when not known
    "identifiers": {
      "ticker": "ACME", "exchange": "NASDAQ", "mic": "XNAS",
      "isin": "US0000000002", "lei": "54930000000000000002",
      "figi": "BBG000000007", "cik": "0000123456"
    },
    // The last two headcount points, each with its own date
    "headcount_change": {
      "from": 1200, "to": 1450,
      "from_as_of": "2024-12-31", "to_as_of": "2025-12-31"
    },
    // Counts, the top intent topic and score, and two timestamps
    "summary": {
      "industry": "software", "business_model": "b2b",
      "tech_count": 23, "open_postings": 41, "new_postings_30d": 9,
      "top_topic": "crm", "top_score": 71.5, "surge_topics": ["crm"],
      "last_change_at": "2026-09-20T03:12:44.101Z",
      "last_read_at": "2026-10-06T04:10:00Z"
    },
    // Website labels, under the name of their version
    "labels": {
      "version": "...", "industry": "software", "business_model": "b2b",
      "sales_motion": "sales_led", "growth_stage": "scaleup", "has_api": true
    },
    // Generated text, marked as such, with the evidence it was written from
    "briefs": [
      { "kind": "brief", "version": "...", "text": "...",
        "evidence": { }, "generated_at": "2026-10-06T05:00:00Z", "ai_text": true }
    ]
  }
}

Four things in it repay a close reading.

  • The key comes first. The company ID is a UUID, which RFC 9562 defines as 128 bits long and requiring no central registration. In Fokals data it is stable and every dataset that describes a company carries it, beside the other identifiers that make company data joinable.
  • The headcount carries its own date. The headcount travels with the day it refers to, and the headcount change names the date of both of its points. Times are ISO 8601 in UTC with a trailing Z, the suffix that RFC 3339 defines as a UTC offset of 00:00. In the list of companies, each row also carries the time the record itself last changed, not the time a signal arrived.
  • Labels name their version. The website labels carry the name of their version, and a breaking change ships as a new version with at least 90 days' notice.
  • Unknown is null. A value that is not known is null, and so is each identifier that is not known. RFC 8259 lists null as one of the three literal names a JSON value can take, apart from any number or string, so the founding year above reads as unknown and never as zero.

The briefs are the one generated part of the record. Each is marked as AI-written, names its version, and carries the evidence it was written from. Every other field is collected, counted or scored.

The record also comes with a contract. Within version 1, fields and endpoints are added without notice and nothing documented is renamed, removed or given a new meaning, so a client should ignore fields it does not know. A breaking change goes into a new version, and the old one stays for at least six months after the new one is announced. The fields are documented in the data dictionary and the API reference.

Firmographic attributes from a website domain: how company data APIs find the company

Company data APIs find a company from its website domain by matching a normalised domain, in lower case and without the scheme, path or leading www, to the domains their records hold. A sound API answers with one stable company ID or a clear miss, so every firmographic attribute that follows attaches to the right company.

A CRM or product database often holds a website and little else, which makes domain matching the usual first step of enrichment. Two cases make a domain harder than it looks. A company can run several websites, and a brand of a listed group has a website of its own. And a domain names a website, not a legal entity or a security, so the record has to carry the other keys before it can join to holdings or filings. Deciding which records describe the same company is entity resolution, and the domain is where it starts.

In the Fokals API a company is fetched by its company ID. To find the ID, the list of companies takes a text filter matched within a name or website, and exact lookups by ISIN, LEI, FIGI, or ticker, narrowed to an exchange by its venue code or MIC when one is given. Case and spaces are ignored in an ISIN, LEI or FIGI, and one that fails its shape or check digit is refused with a 400 error instead of being matched loosely.

GET /api/v1/companies?q=acme-robotics.example
GET /api/v1/companies?isin=US0000000002
GET /api/v1/companies?ticker=ACME&exchange=XNAS
GET /api/v1/companies/3f6c2a9e-8d41-4b7a-9c55-0e2f1a7b6d10

From the text search, keep the row whose domain equals yours. Build the map from your domains to company IDs once, store it, and fetch by ID from then on. A brand or subsidiary carries the identifiers of its listed parent, so the same map reaches the security behind a brand's website. An ID that is not in the index answers 404, so a miss stays a plain miss.

Paging a list without gaps

A lookup returns one record; a sync walks thousands of pages, and that is where a copy goes quietly wrong. With offsets, a row inserted ahead of your position pushes every later row back one place, and a row is read twice; a row removed pulls the next one into a page already read, and it is skipped. Cursor pagination names the last row read instead of a count of rows, so it resumes after that row whatever moved before it.

In the Fokals API every paged list arrives in an envelope with its rows and a next cursor, and the last page's cursor is null. A cursor is tied to the query that made it, is sent back with the same parameters, and can be stored and resumed later. The list of companies runs from the most recent change to a record, then by company ID, and takes an updated-since filter, so a sync asks only for the records changed since its last run. The feeds of signals, website changes and postings run oldest first from a time you set, so the last cursor is the bookmark for incremental sync. Bulk exports page through any dataset by its keys; the comparison of API and bulk file delivery sets the two routes side by side.

Company enrichment by website domain at Apollo, People Data Labs and Crunchbase

Apollo's Organization Enrichment endpoint takes a bare domain and returns one organization. People Data Labs' Company Enrichment API takes a website, name, ticker or social profile and returns a match with a likelihood score. Crunchbase finds an organization by a website predicate in its search API, then returns the entity by UUID or permalink.

We read each provider's API reference on 7 October 2026; the table below sets what each documents against the checklist.

Apollo

Apollo's Organization Enrichment reference documents one call for enriching one company.

GET https://api.apollo.io/api/v1/organizations/enrich?domain=acme-robotics.example

The domain is passed bare, with no www and no @ sign; the website address is another accepted way to identify the company, and the company name can be added to help the match. The response holds one organization object, whose example carries its ID, name, website address, primary domain, industry, estimated employee count and founding year. The example shows values it does not hold as null, and the reference states that the headcount growth fields return null when growth data is not available for the company.

People Data Labs

People Data Labs documents its Company Enrichment API as a one-to-one match against its company profiles, and its quickstart calls it by website.

GET https://api.peopledatalabs.com/v5/company/enrich?website=acme-robotics.example

The reference asks for at least one of a name, a ticker, a website or a social profile, with location fields to narrow the match; a record's own ID can be sent instead, and is then the only input used. Each match carries a likelihood from 1 to 10, a minimum likelihood can be set, required fields can be named, and no match returns 404. Its output reference gives null to any field without data, with the profile fields at the top level of the response. In the company schema the ID is a unique hashed value for one company record, the affiliated profiles name the IDs of parents and subsidiaries, and the dataset version names the data release the record came from.

Crunchbase

Crunchbase serves API v4. Its entity lookup takes a UUID or a permalink, with lists of field and card IDs choosing the fields and related collections returned, and the guide asks clients to treat every field and relationship as optional. To start from a domain, Search Organization Entities accepts a predicate on the website address, with operators that include an exact domain match and a domain-includes match.

GET  https://api.crunchbase.com/v4/data/entities/organizations/{entity_id}
POST https://api.crunchbase.com/v4/data/searches/organizations

The organization schema carries a UUID, a permalink, the website address and the record's creation and update times, with the founding date typed as a date with its precision. Search pages hold up to 1,000 rows and move forward or back by the UUID of the last or first row of the current page, as the search guide explains.

ChecklistApolloPeople Data LabsCrunchbase
Lookup from a domainBare domain as a query parameter, or the website addressWebsite, name, ticker or social profile, at least oneSearch predicate on the website with an exact domain operator
Record identifierAn ID on the organization objectA unique hashed ID per company record, accepted back as an inputA UUID and a permalink, either one accepted by the lookup
Dates in the recordDated funding fieldsDate of the latest funding; the data release the record came fromCreation and update times; founding date with its precision
Match and missCompany name accepted to help the matchLikelihood from 1 to 10, a minimum to accept, 404 on no matchA lookup by UUID or permalink names one entity
Missing valuesNull in the example; growth fields null when unavailableNull for any field without dataEvery field and relationship treated as optional
PagingOne company per call; a bulk endpoint takes up to tenOne company per call; a bulk endpoint takes severalSearch pages by UUID cursor, after or before

Clearbit, which its home page says has joined HubSpot, has a guide of its own in Clearbit alternatives.

Worked example: merging the Acme Robotics record into a CRM

Here is the record above merged into a CRM account, step by step, so you can redo it. The example is illustrative.

Assumptions:

  • Acme Robotics is an invented company, and every figure here is illustrative.
  • Your CRM account for it was last edited by hand on 1 March 2024: 900 employees, founded 2011, country US, ISIN empty.
  • The API returns the record shown above: 1,450 employees as of 31 December 2025, 1,200 as of 31 December 2024, founding year null, country US, ISIN US0000000002.
  • The merge rule: write an API value only when it is not null and, for a dated value, only when its date is later than the date of the value it replaces.
  • The merge runs on 7 October 2026.

The working, field by field:

  1. Employees. 31 December 2025 is later than 1 March 2024, so 1,450 replaces 900, and the as-of date is stored beside it. On the day of the merge the count is 280 days old: 273 days from 31 December to 30 September, plus 7.
  2. Growth. 1,450 less 1,200 is 250, and 250 / 1,200 = 0.208, a rise of 20.8% between two as-of dates a year apart.
  3. Founding year. The API value is null, so 2011 stays. A merge that read null as 0 would replace a known year with year 0.
  4. ISIN. The CRM field is empty and the API value is set, so it is written.
  5. Country. Both say US, so nothing is written.

Two fields are written and two are left as they were. The same rule matters in aggregate. Take four accounts whose employee counts come back as 1,450, null, 300 and null. The mean of the known values is (1,450 + 300) / 2 = 875. Read the nulls as zero and the mean becomes 1,750 / 4 = 437.5, half as large, with two accounts counted as having no staff on no evidence.

Both rules depend on a record that carries nulls and dates in the first place. For an enrichment pipeline in full, see enriching company records in your data product, and for keeping a copy in step, incremental sync of company data.

Frequently asked questions

What is a company enrichment API?

A company enrichment API takes something you already hold about a company, usually its website domain, and returns a record of attributes about it: name, headquarters country, size, industry, identifiers and more. A sound one returns a stable company ID with the record, so that later calls and other datasets join on that key rather than on the domain, and dates each attribute so you can tell how old it is.

What does null mean in a company data API response?

Null means the value is not known. JSON defines null as a literal of its own, separate from zero and from the empty string, and a well-built API uses it for exactly that. Keep it as null when you load the record: a merge that writes zero for null turns an unknown headcount into a company with no staff and pulls every average down.

How do I look up a company by its website domain?

Reduce the website address to its registrable domain, in lower case and without the scheme, the path or a leading www, then send it to the provider's lookup by domain or website. Keep the stable company ID that comes back and fetch by that ID from then on, because a company can run several websites and its domains change over time.

Why does an account record need a stable company ID?

Names change, websites move and tickers change with corporate actions, so none of them makes a lasting key. A stable company ID stays the same for the life of the record, which lets you key your own tables on it, join every dataset from the same vendor on it, and tell an updated company apart from a new one.

How should a company data API page through long lists?

By cursor over a fixed order. Each page returns its rows with an opaque cursor for the next page, and the last page returns none. Send the cursor back with the same parameters, store it to resume later, and check on a sample that the number of rows you received equals the number of distinct company IDs among them.

The queries and code on this page are examples to adapt. Test them in your own environment before you rely on them.

What this page says about the products it names was checked against their public documentation on 7 October 2026. Product and company names are trademarks of their owners. Fokals is not affiliated with them or endorsed by them.