# API keys Source: https://dev.kernel.ai/api-reference/endpoint/api-keys Authenticate requests to the Kernel API using API keys passed in the `x-api-key` header. ## Authentication Every request must include an API key: ```bash curl theme={null} curl https://api.kernel.ai/rest/v1/entity-resolution \ -H "x-api-key: $KERNEL_API_KEY" \ -H "Content-Type: application/json" \ -d '{"legal_name": "Stripe"}' ``` Requests without a valid key receive a `403 Forbidden` response with body `{ "message": "Forbidden" }`. ## Creating an API key 1. Go to **Settings > API keys** in the [Kernel app](https://app.kernel.ai) 2. Click **Create key** and optionally give it a name 3. Copy the key value and signing secret — both are shown only once Store your API key in an environment variable and never commit it to source control. ```bash theme={null} export KERNEL_API_KEY="ker_your_api_key_here" ``` ## Key value The key value is a string you pass in the `x-api-key` header. After creation, the full key is displayed once — it cannot be retrieved later. If you lose a key, delete it and create a new one. ## Webhook signing secret Each API key comes with a webhook signing secret (prefixed with `whsec_`). Use this secret to verify that webhook payloads were sent by Kernel. See [Webhooks](/api-reference/endpoint/webhooks) for the verification process. The signing secret is shown once when you create an API key. If you need a new secret, delete the key and create a new one. ## Deleting a key Deleting an API key immediately revokes it. Any requests using that key will receive a `401 Unauthorized` response. To delete a key, go to **Settings > API keys**, open the key's menu, and select **Delete key**. ## Security best practices * Store API keys in environment variables, never in source code * Use separate keys for development and production * Rotate keys if you suspect they have been leaked * Delete keys you no longer need # Combined Source: https://dev.kernel.ai/api-reference/endpoint/combined POST /v1/combined Starts an entity resolution job and then runs one or more follow-up enrichments. Returns immediately with an `id` — poll `GET /v1/combined/{job_id}` until the status is `completed`. When both follow-ups are requested, they run in parallel after entity resolution completes. Starts an entity resolution job and then runs one or more follow-up enrichments in one request. Use `jobs: ["firmographics"]` to resolve an entity and then enrich it with operational status, location, headcount, revenue, and industry data. Use `jobs: ["resolve-parent"]` to resolve an entity and then look up its parent and top-parent hierarchy. Use `jobs: ["resolve-parent", "firmographics"]` to run the full bundle — the two follow-ups run in parallel after entity resolution completes. The endpoint accepts the same entity-resolution inputs as [`POST /v1/entity-resolution`](/api-reference/endpoint/create-entity-resolution), plus a required `jobs` array that selects the follow-up enrichment(s). This is an async operation. Poll [`GET /v1/combined/{job_id}`](/api-reference/endpoint/get-combined) until `status` is `completed`, or provide a `webhook_url` to receive a callback. ## Credit usage Credits are charged for entity resolution plus each follow-up that runs: | Bundle | Cost | | - | - | | Entity resolution + resolve parent | 3 credits | | Entity resolution + firmographics | 3 credits | | Entity resolution + resolve parent + firmographics | 5 credits | If entity resolution does not find a match, the follow-up cost(s) are refunded automatically and the job completes with `kernel_id: null`, the requested follow-up fields set to `null`, and `identity_resolution_reasoning` explaining the resolution attempt. ## Examples ### Resolve then resolve parent ```bash curl theme={null} curl -X POST https://api.kernel.ai/rest/v1/combined \ -H "x-api-key: $KERNEL_API_KEY" \ -H "Content-Type: application/json" \ -d '{"jobs": ["resolve-parent"], "website": "stripe.com"}' ``` ### Resolve then enrich firmographics ```bash curl theme={null} curl -X POST https://api.kernel.ai/rest/v1/combined \ -H "x-api-key: $KERNEL_API_KEY" \ -H "Content-Type: application/json" \ -d '{"jobs": ["firmographics"], "website": "stripe.com"}' ``` ### Resolve, resolve parent, then enrich firmographics ```bash curl theme={null} curl -X POST https://api.kernel.ai/rest/v1/combined \ -H "x-api-key: $KERNEL_API_KEY" \ -H "Content-Type: application/json" \ -d '{"jobs": ["resolve-parent", "firmographics"], "website": "stripe.com"}' ``` All three requests return the same immediate response: ```json Response (202) theme={null} { "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", "status": "processing" } ``` ## Request body | Field | Type | Required | Description | | - | - | - | - | | `jobs` | `string[]` | Yes | Follow-up job(s): `["firmographics"]`, `["resolve-parent"]`, or `["resolve-parent", "firmographics"]` | | `legal_name` | `string` | No\* | Registered legal name | | `trading_name` | `string` | No\* | Brand or trading name | | `website` | `string` | No\* | Company website URL | | `linkedin_url` | `string` | No\* | LinkedIn URL for the company | | `country` | `string` | No\* | Country name or ISO code | | `city` | `string` | No\* | City | | `state` | `string` | No\* | State or province | | `postal_code` | `string` | No\* | ZIP or postal code | | `address` | `string` | No\* | Street address | | `email` | `string` | No\* | Contact email | | `phone` | `string` | No\* | Contact phone | | `company_registration_number` | `string` | No\* | Primary incorporation/registration number. The same number can exist in more than one country — pair it with `company_registration_country` when known. | | `company_registration_country` | `string` | No | Registry jurisdiction for `company_registration_number` (ISO 3166-1 alpha-2 preferred). Falls back to `country` when omitted. | | `external_id` | `string` | No\* | Your internal identifier. Echoed back on `record.external_id` in the completed result. | | `match_to_linkedin` | `boolean` | No | Also match the company's LinkedIn profile | | `identity_bias` | `string` | No | `"NAME_BIAS"` or `"URL_BIAS"` | | `webhook_url` | `string` | No | HTTPS URL for completion/failure callbacks | \*At least one identifying field is required. ## Polling for results After receiving an `id`, poll [`GET /v1/combined/{job_id}`](/api-reference/endpoint/get-combined) with exponential backoff. ## Related endpoints * [`GET /v1/combined/{job_id}`](/api-reference/endpoint/get-combined) — Poll for results * [`POST /v1/entity-resolution`](/api-reference/endpoint/create-entity-resolution) — Resolve an entity only * [`POST /v1/firmographics`](/api-reference/endpoint/get-firmographics) — Enrich an already-resolved entity * [`POST /v1/resolve-parent`](/api-reference/endpoint/resolve-parent) — Resolve parentage for an already-resolved entity # Resolve entity Source: https://dev.kernel.ai/api-reference/endpoint/create-entity-resolution POST /v1/entity-resolution Starts an entity resolution job for a company. Returns immediately with an `id` — poll `GET /v1/entity-resolution/{job_id}` until the status is `completed`. Submit a company to resolve its identity. The endpoint returns `202` with an `id` — use it to poll the [Get entity resolution result](/api-reference/endpoint/get-entity-resolution) endpoint until the status is `completed`. No fields are required, but providing at least one identifying field improves resolution accuracy. ## Examples ### Minimal — legal name only ```bash curl theme={null} curl -X POST https://api.kernel.ai/rest/v1/entity-resolution \ -H "x-api-key: $KERNEL_API_KEY" \ -H "Content-Type: application/json" \ -d '{"legal_name": "Stripe"}' ``` ```json Response (202) theme={null} { "id": "550e8400-e29b-41d4-a716-446655440000", "status": "processing" } ``` ### Full — all fields ```bash curl theme={null} curl -X POST https://api.kernel.ai/rest/v1/entity-resolution \ -H "x-api-key: $KERNEL_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "legal_name": "Stripe, Inc.", "trading_name": "Stripe", "website": "https://stripe.com", "linkedin_url": "https://linkedin.com/company/stripe", "match_to_linkedin": true, "identity_bias": "NAME_BIAS", "country": "US", "city": "South San Francisco", "state": "CA", "postal_code": "94070", "email": "info@stripe.com", "company_registration_number": "01234567", "company_registration_country": "GB", "external_id": "stripe-001", "webhook_url": "https://example.com/webhooks/kernel" }' ``` ```json Response (202) theme={null} { "id": "550e8400-e29b-41d4-a716-446655440000", "status": "processing" } ``` ## Input fields All fields are optional. Provide as many as available to improve resolution accuracy. | Field | Type | Description | | - | - | - | | `legal_name` | string | Registered legal name of the company (e.g. `"Stripe, Inc."`) | | `trading_name` | string | Primary brand or trading name (e.g. `"Stripe"`) | | `website` | string | Company website URL | | `linkedin_url` | string | LinkedIn URL for the company (e.g. `"https://linkedin.com/company/stripe"`). Used as an additional signal for entity resolution. | | `country` | string | Country name or ISO 3166-1 alpha-2 code (operating / CRM country). Also used as a fallback registry jurisdiction when `company_registration_country` is omitted and `company_registration_number` is set. | | `city` | string | City | | `state` | string | State or province | | `postal_code` | string | ZIP or postal code | | `address` | string | Street address | | `email` | string | Email address | | `external_id` | string | Your own identifier for this record. Echoed back on `record.external_id` in the completed result. | | `company_registration_number` | string | Primary incorporation/registration number. The same number can exist in more than one country — pair it with `company_registration_country` when known. | | `company_registration_country` | string | Registry jurisdiction for `company_registration_number` (ISO 3166-1 alpha-2 preferred, e.g. `"GB"`, `"CH"`, `"HU"`). England, Scotland, Wales, and Northern Ireland map to **GB** (Companies House). | | `match_to_linkedin` | boolean | When `true`, Kernel matches the resolved entity to a LinkedIn company profile. Result appears in the `linkedin` field. Defaults to `false` | | `identity_bias` | string | Bias the resolver toward name or URL matching when they conflict. One of: `NAME_BIAS`, `URL_BIAS`. Defaults to `URL_BIAS` | | `webhook_url` | string | HTTPS URL to receive webhook callbacks when the job completes or fails | ## Input normalization You do not need to clean or normalize inputs before sending them: * Company names are case-insensitive — `"ACME CORP"`, `"Acme Corp"`, and `"acme corp"` are equivalent * Common suffixes like `Inc.`, `LLC`, `Ltd.`, `GmbH` are handled automatically * Website URLs are normalized — `"acme.com"` and `"https://www.acme.com/"` resolve the same way * Country accepts both codes (`"US"`) and full names (`"United States"`) # Lookup LinkedIn company Source: https://dev.kernel.ai/api-reference/endpoint/create-linkedin-lookup POST /v1/lookup/linkedin Starts a provisional LinkedIn company lookup job. Returns immediately with an `id` — poll `GET /v1/lookup/linkedin/{job_id}` until the status is `completed`. Provide at least one of `name`, `website`, or `linkedin_url`. Matching priority: LinkedIn URL → website → name. Async. Poll with the returned `id`, or pass `webhook_url` for a callback. Not Kernel-verified. `provenance.kernel_approved` is always `false`. Profile fields use the `linkedin_*` prefix — not Kernel firmographics. ## Examples ### By website ```bash curl theme={null} curl -X POST https://api.kernel.ai/rest/v1/lookup/linkedin \ -H "x-api-key: $KERNEL_API_KEY" \ -H "Content-Type: application/json" \ -d '{"website": "stripe.com"}' ``` ```json Response (202) theme={null} { "id": "550e8400-e29b-41d4-a716-446655440000", "status": "processing" } ``` ### By LinkedIn URL ```bash curl theme={null} curl -X POST https://api.kernel.ai/rest/v1/lookup/linkedin \ -H "x-api-key: $KERNEL_API_KEY" \ -H "Content-Type: application/json" \ -d '{"linkedin_url": "https://www.linkedin.com/company/stripe"}' ``` ## Request body | Field | Type | Required | Description | | - | - | - | - | | `name` | `string` | No\* | Company name (low confidence alone) | | `website` | `string` | No\* | Website or domain | | `linkedin_url` | `string` | No\* | LinkedIn company URL | | `webhook_url` | `string` | No | HTTPS callback URL | \*At least one of `name`, `website`, or `linkedin_url`. ## Related endpoints * [Get LinkedIn lookup result](/api-reference/endpoint/get-linkedin-lookup) * [LinkedIn lookup result](/api-reference/schemas/linkedin-lookup-result) # Crosscheck Source: https://dev.kernel.ai/api-reference/endpoint/crosscheck POST /v1/crosscheck Resolves a company to a canonical entity, creating it if it is new, then runs the full CRM crosscheck pass on it. Returns immediately with an `id` — poll `GET /v1/crosscheck/{job_id}` until the status is `completed`. The pass covers duplicate detection, corporate hierarchy, operational status, regional-subsidiary classification, and the resulting recommended action. Resolves a company to a canonical entity — creating it if it is new to your dataset — then runs the full CRM crosscheck pass on it in one request. The result is split into two blocks: `crosscheck` carries the recommended action, duplicate grouping, and operational status; `parentage` carries the corporate hierarchy (immediate, ultimate, and top operating parent, plus regional-subsidiary classification) in the same shape as [`GET /v1/combined/{job_id}`](/api-reference/endpoint/get-combined#with-parentage). The endpoint accepts the same inputs as [`POST /v1/entity-resolution`](/api-reference/endpoint/create-entity-resolution), except that `external_id` is required. It identifies the record in your CRM, which the pass needs because duplicates and hierarchy are evaluated relative to the rest of your dataset. This is an async operation. Poll [`GET /v1/crosscheck/{job_id}`](/api-reference/endpoint/get-crosscheck) until `status` is `completed`, or provide a `webhook_url` to receive a callback. Crosscheck results are never cached. Each call re-runs the pass, because duplicates, hierarchy, and the recommended action change as your dataset changes. ## Credit usage | Outcome | Cost | | - | - | | Entity resolved and crosschecked | 5 credits | | Entity resolved, crosscheck pass did not run | 1 credit | The pass does not run when no entity is resolved, or when the `external_id` does not match an account in your Kernel dataset. In those cases the job still completes, `crosscheck` and `parentage` are both returned as `null`, and the crosscheck portion of the cost is refunded automatically. ## Examples ### Crosscheck a CRM record ```bash curl theme={null} curl -X POST https://api.kernel.ai/rest/v1/crosscheck \ -H "x-api-key: $KERNEL_API_KEY" \ -H "Content-Type: application/json" \ -d '{"external_id": "0014x00001LMZCDAA5", "legal_name": "Stripe, Inc.", "website": "stripe.com"}' ``` ### Crosscheck and match LinkedIn ```bash curl theme={null} curl -X POST https://api.kernel.ai/rest/v1/crosscheck \ -H "x-api-key: $KERNEL_API_KEY" \ -H "Content-Type: application/json" \ -d '{"external_id": "0014x00001LMZCDAA5", "website": "stripe.com", "match_to_linkedin": true}' ``` Both requests return the same immediate response: ```json Response (202) theme={null} { "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", "status": "processing" } ``` ## Request body `external_id` is required — it selects which account in your dataset the crosscheck pass runs on. You must also provide at least one of `legal_name`, `trading_name`, `website`, or `kernel_id` so the entity can be resolved. Requests missing either are rejected with a `400`. | Field | Type | Required | Description | | - | - | - | - | | `external_id` | `string` | Yes | Your CRM identifier for the record to clean. Echoed back on `record.external_id`. | | `legal_name` | `string` | No\* | Registered legal name | | `trading_name` | `string` | No\* | Brand or trading name | | `website` | `string` | No\* | Company website URL | | `kernel_id` | `string` | No\* | Resolve against a known Kernel entity | | `linkedin_url` | `string` | No | LinkedIn URL for the company | | `country` | `string` | No | Country name or ISO 3166-1 alpha-2 code | | `city` | `string` | No | City | | `state` | `string` | No | State or province | | `postal_code` | `string` | No | ZIP or postal code | | `address` | `string` | No | Street address | | `email` | `string` | No | Email address. Only the domain portion is used for matching. | | `phone` | `string` | No | Contact phone | | `company_registration_number` | `string` | No | Company registration number | | `match_to_linkedin` | `boolean` | No | When `true`, also match the resolved entity to a LinkedIn company profile. Result appears in `record.linkedin`. Defaults to `false` | | `identity_bias` | `string` | No | Bias the resolver toward name or URL matching when they conflict. One of `NAME_BIAS`, `URL_BIAS`. Defaults to `URL_BIAS` | | `webhook_url` | `string` | No | HTTPS URL to receive callbacks when the job completes or fails | \*At least one of `legal_name`, `trading_name`, `website`, or `kernel_id` is required. ## Polling for results After receiving an `id`, poll [`GET /v1/crosscheck/{job_id}`](/api-reference/endpoint/get-crosscheck) with exponential backoff. A full crosscheck runs identity resolution and the complete crosscheck pass, so it typically takes longer than the single-purpose endpoints. ## Related endpoints * [`GET /v1/crosscheck/{job_id}`](/api-reference/endpoint/get-crosscheck) — Poll for results * [`POST /v1/entity-resolution`](/api-reference/endpoint/create-entity-resolution) — Resolve an entity only * [`POST /v1/combined`](/api-reference/endpoint/combined) — Resolve an entity and enrich firmographics or parentage * [`POST /v1/resolve-parent`](/api-reference/endpoint/resolve-parent) — Resolve parentage for an already-resolved entity # Get combined result Source: https://dev.kernel.ai/api-reference/endpoint/get-combined GET /v1/combined/{job_id} Returns the status and result of a combined job. When `status` is `completed`, the `record` object contains the entity resolution result and the requested enrichment. Returns the status and result of a combined job started with [`POST /v1/combined`](/api-reference/endpoint/combined). When `status` is `completed`, the `record` field contains: * The entity resolution result (`kernel_id`, `company_registration`, `company_registration_number`, `identity_resolution_*`, `legal_info`, `trading_info`, `entity_classification`, and optionally `linkedin`) * The follow-up enrichment result under `firmographics` or `parentage`, depending on the `jobs` value submitted * Your `external_id`, echoed back on `record.external_id`, if you included one in the request Prefer `company_registration` for the registration number, registry country, and source. `company_registration_number` is a deprecated alias of `company_registration.number`. If entity resolution does not find a match, the job still completes: `record.kernel_id` is `null`, the identity detail fields and any requested follow-up fields are `null`, and `identity_resolution_confidence` and `identity_resolution_reasoning` explain the resolution attempt. See [No match](#no-match). ## Processing response While the combined job is running, the response includes a `subprocesses` object showing the status of each step: ```json theme={null} { "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", "status": "processing", "created_at": "2025-06-05T12:00:00Z", "subprocesses": { "entity-resolution": "completed", "resolve-parent": "processing", "firmographics": "pending" } } ``` Each subprocess follows the same `pending → processing → completed | failed` lifecycle. Poll until the top-level `status` is `completed` or `failed`. ## Completed response examples ### With firmographics ```json theme={null} { "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", "status": "completed", "created_at": "2025-06-05T12:00:00Z", "completed_at": "2025-06-05T12:00:05Z", "record": { "kernel_id": "6347422643", "company_registration": { "number": "01234567", "country": "GB", "source": "request" }, "company_registration_number": "01234567", "identity_type": "legal_entity", "identity_resolution_confidence": "HIGH", "identity_resolution_reasoning": "Matched by domain and legal name.", "legal_info": { "country": "US", "reasoning": "Confirmed via Stripe terms of service page.", "trading_name": "Stripe, Inc.", "confidence": "HIGH", "legal_name": "Stripe, Inc.", "website": "https://stripe.com" }, "trading_info": { "country": "US", "website": "https://stripe.com", "reasoning": "Primary brand site confirmed via domain ownership.", "trading_name": "Stripe", "confidence": "HIGH" }, "entity_classification": { "type": "Company", "subtype": "Operating", "reasoning": "Classified as an operating company based on commercial activity." }, "firmographics": { "kernel_id": "6347422643", "op_status": { "operational_status": "Active", "reasoning": "Website is live." }, "location": { "operating": { "city": "South San Francisco", "country": "US" } }, "headcount": { "count": 7000 }, "revenue": { "usd": 1000000000 }, "industry": { "naics": { "version": "NAICS 2022", "sector": { "value": "52 - Finance and Insurance", "code": "52", "label": "Finance and Insurance" }, "subsector": { "value": "522 - Credit Intermediation and Related Activities", "code": "522", "label": "Credit Intermediation and Related Activities" }, "industry_group": { "value": "5223 - Activities Related to Credit Intermediation", "code": "5223", "label": "Activities Related to Credit Intermediation" }, "industry": { "value": "52232 - Financial Transactions Processing, Reserve, and Clearinghouse Activities", "code": "52232", "label": "Financial Transactions Processing, Reserve, and Clearinghouse Activities" }, "national_industry": { "value": "522320 - Financial Transactions Processing, Reserve, and Clearinghouse Activities", "code": "522320", "label": "Financial Transactions Processing, Reserve, and Clearinghouse Activities" }, "reasoning": "- Payment processing and related financial tools are provided to businesses through online and in-person checkout products.\n- The activity is classified under 522320: Financial Transactions Processing, Reserve, and Clearinghouse Activities, because transaction processing is delivered as a financial service.\n- Reusable software publishing is not established as the principal offering, since payment acceptance and financial services are emphasized." }, "sic": { "version": "SIC 1987", "division": { "value": "H - Finance, Insurance, and Real Estate", "code": "H", "label": "Finance, Insurance, and Real Estate" }, "major_group": { "value": "60 - Depository Institutions", "code": "60", "label": "Depository Institutions" }, "industry_group": { "value": "609 - Functions Related To Depository Banking", "code": "609", "label": "Functions Related To Depository Banking" }, "industry": { "value": "6099 - Functions Related To Depository Banking, Not Elsewhere Classified", "code": "6099", "label": "Functions Related To Depository Banking, Not Elsewhere Classified" }, "reasoning": "- Payment processing and financial tools are presented as the principal activity, with businesses offered services to accept and optimize payments online and in person.\n- The activity is classified under 6099: Functions Related To Depository Banking, Not Elsewhere Classified, as payment services are delivered to merchants.\n- Computer software is used to support payment services, but reusable software is not presented as the principal product sold." }, "nace": { "version": "NACE Rev. 2.1", "section": { "value": "L - Financial and insurance activities", "code": "L", "label": "Financial and insurance activities" }, "division": { "value": "66 - Activities auxiliary to financial services and insurance activities", "code": "66", "label": "Activities auxiliary to financial services and insurance activities" }, "group": { "value": "66.1 - Activities auxiliary to financial services, except insurance and pension funding", "code": "66.1", "label": "Activities auxiliary to financial services, except insurance and pension funding" }, "class": { "value": "66.19 - Other activities auxiliary to financial services, except insurance and pension funding", "code": "66.19", "label": "Other activities auxiliary to financial services, except insurance and pension funding" }, "reasoning": "- Payment processing and related financial services are presented as Stripe’s principal offerings, enabling businesses to accept payments online and in person.\n- These transaction services are classified under 66.19 as activities auxiliary to financial services, rather than as monetary intermediation.\n- The software-services alternative is less suitable because payment acceptance and financial transactions are presented as the customer-facing service." } } }, "external_id": "stripe-001" } } ``` ### With parentage ```json theme={null} { "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", "status": "completed", "created_at": "2025-06-05T12:00:00Z", "completed_at": "2025-06-05T12:00:05Z", "record": { "kernel_id": "6347422643", "company_registration": null, "company_registration_number": null, "identity_type": "legal_entity", "identity_resolution_confidence": "HIGH", "identity_resolution_reasoning": "Matched by domain and legal name.", "legal_info": { "country": "US", "reasoning": "Confirmed via Stripe terms of service page.", "trading_name": "Stripe, Inc.", "confidence": "HIGH", "legal_name": "Stripe, Inc.", "website": "https://stripe.com" }, "trading_info": { "country": "US", "website": "https://stripe.com", "reasoning": "Primary brand site confirmed via domain ownership.", "trading_name": "Stripe", "confidence": "HIGH" }, "entity_classification": { "type": "Company", "subtype": "Operating", "reasoning": "Classified as an operating company based on commercial activity." }, "parentage": { "kernel_id": "6347422643", "parent": null, "top_parent": { "kernel_id": "6347422643", "trading_name": "Stripe", "legal_name": "Stripe, Inc.", "website": "https://stripe.com", "country": "US", "entity_category": "Company", "entity_sub_category": "Operating", "confidence": null }, "top_operating_parent": { "kernel_id": "6347422643", "trading_name": "Stripe", "legal_name": "Stripe, Inc.", "website": "https://stripe.com", "country": "US", "entity_category": "Company", "entity_sub_category": "Operating", "confidence": null }, "regional_subsidiary": { "is_regional": false, "regional_scope": null, "reasoning": null } } } } ``` ### With firmographics and parentage ```json theme={null} { "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", "status": "completed", "created_at": "2025-06-05T12:00:00Z", "completed_at": "2025-06-05T12:00:05Z", "record": { "kernel_id": "6347422643", "company_registration": null, "company_registration_number": null, "identity_type": "legal_entity", "identity_resolution_confidence": "HIGH", "identity_resolution_reasoning": "Matched by domain and legal name.", "legal_info": { "country": "US", "reasoning": "Confirmed via Stripe terms of service page.", "trading_name": "Stripe, Inc.", "confidence": "HIGH", "legal_name": "Stripe, Inc.", "website": "https://stripe.com" }, "trading_info": { "country": "US", "website": "https://stripe.com", "reasoning": "Primary brand site confirmed via domain ownership.", "trading_name": "Stripe", "confidence": "HIGH" }, "entity_classification": { "type": "Company", "subtype": "Operating", "reasoning": "Classified as an operating company based on commercial activity." }, "firmographics": { "kernel_id": "6347422643", "op_status": { "operational_status": "Active", "reasoning": "Website is live." }, "location": { "operating": { "street": null, "city": "South San Francisco", "state": "California", "country": "United States", "postcode": "94080", "reasoning": "Address derived from company registration records." }, "registered": { "street": "354 Oyster Point Blvd", "city": "South San Francisco", "state": "California", "country": "United States", "postcode": "94080", "reasoning": "Address from official registry filing." } }, "headcount": { "count": 7000, "count_entity": 7000, "count_consolidated": 7000, "confidence": "HIGH", "reasoning": "Headcount derived from annual report figures." }, "revenue": { "usd": 1000000000, "usd_entity": 1000000000, "consolidated_usd": 1000000000, "confidence": "HIGH", "local_currency": "USD", "local_currency_entity": "USD", "local": 1000000000, "local_entity": 1000000000, "consolidated_local": 1000000000, "consolidated_currency": "USD", "reasoning": "Revenue sourced from audited annual financial statements.", "source": "identified" }, "industry": { "naics": { "version": "NAICS 2022", "sector": { "value": "52 - Finance and Insurance", "code": "52", "label": "Finance and Insurance" }, "subsector": { "value": "522 - Credit Intermediation and Related Activities", "code": "522", "label": "Credit Intermediation and Related Activities" }, "industry_group": { "value": "5223 - Activities Related to Credit Intermediation", "code": "5223", "label": "Activities Related to Credit Intermediation" }, "industry": { "value": "52232 - Financial Transactions Processing, Reserve, and Clearinghouse Activities", "code": "52232", "label": "Financial Transactions Processing, Reserve, and Clearinghouse Activities" }, "national_industry": { "value": "522320 - Financial Transactions Processing, Reserve, and Clearinghouse Activities", "code": "522320", "label": "Financial Transactions Processing, Reserve, and Clearinghouse Activities" }, "reasoning": "- Payment processing and related financial tools are provided to businesses through online and in-person checkout products.\n- The activity is classified under 522320: Financial Transactions Processing, Reserve, and Clearinghouse Activities, because transaction processing is delivered as a financial service.\n- Reusable software publishing is not established as the principal offering, since payment acceptance and financial services are emphasized." }, "sic": { "version": "SIC 1987", "division": { "value": "H - Finance, Insurance, and Real Estate", "code": "H", "label": "Finance, Insurance, and Real Estate" }, "major_group": { "value": "60 - Depository Institutions", "code": "60", "label": "Depository Institutions" }, "industry_group": { "value": "609 - Functions Related To Depository Banking", "code": "609", "label": "Functions Related To Depository Banking" }, "industry": { "value": "6099 - Functions Related To Depository Banking, Not Elsewhere Classified", "code": "6099", "label": "Functions Related To Depository Banking, Not Elsewhere Classified" }, "reasoning": "- Payment processing and financial tools are presented as the principal activity, with businesses offered services to accept and optimize payments online and in person.\n- The activity is classified under 6099: Functions Related To Depository Banking, Not Elsewhere Classified, as payment services are delivered to merchants.\n- Computer software is used to support payment services, but reusable software is not presented as the principal product sold." }, "nace": { "version": "NACE Rev. 2.1", "section": { "value": "L - Financial and insurance activities", "code": "L", "label": "Financial and insurance activities" }, "division": { "value": "66 - Activities auxiliary to financial services and insurance activities", "code": "66", "label": "Activities auxiliary to financial services and insurance activities" }, "group": { "value": "66.1 - Activities auxiliary to financial services, except insurance and pension funding", "code": "66.1", "label": "Activities auxiliary to financial services, except insurance and pension funding" }, "class": { "value": "66.19 - Other activities auxiliary to financial services, except insurance and pension funding", "code": "66.19", "label": "Other activities auxiliary to financial services, except insurance and pension funding" }, "reasoning": "- Payment processing and related financial services are presented as Stripe’s principal offerings, enabling businesses to accept payments online and in person.\n- These transaction services are classified under 66.19 as activities auxiliary to financial services, rather than as monetary intermediation.\n- The software-services alternative is less suitable because payment acceptance and financial transactions are presented as the customer-facing service." } } }, "parentage": { "kernel_id": "6347422643", "parent": null, "top_parent": { "kernel_id": "6347422643", "trading_name": "Stripe", "legal_name": "Stripe, Inc.", "website": "https://stripe.com", "country": "US", "entity_category": "Company", "entity_sub_category": "Operating", "confidence": null }, "top_operating_parent": { "kernel_id": "6347422643", "trading_name": "Stripe", "legal_name": "Stripe, Inc.", "website": "https://stripe.com", "country": "US", "entity_category": "Company", "entity_sub_category": "Operating", "confidence": null }, "regional_subsidiary": { "is_regional": false, "regional_scope": null, "reasoning": null } } } } ``` ## No match If entity resolution does not find a match, the follow-up credits are refunded, the follow-up jobs are skipped, and the job completes with `kernel_id: null`. The requested follow-up fields (`firmographics`, `parentage`) are returned as `null`, along with `linkedin` if `match_to_linkedin` was requested. `identity_resolution_confidence` and `identity_resolution_reasoning` remain populated to explain the resolution attempt: ```json theme={null} { "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", "status": "completed", "created_at": "2025-06-05T12:00:00Z", "completed_at": "2025-06-05T12:00:05Z", "record": { "kernel_id": null, "company_registration": null, "company_registration_number": null, "identity_resolution_confidence": "HIGH", "identity_resolution_reasoning": "Company identified as Acme Inc. via legal name and website alignment, but no matching entity exists in Kernel's database.", "legal_info": null, "trading_info": null, "entity_classification": null, "firmographics": null, "parentage": null } } ``` ## Failed response If the job fails for another reason, the response uses `jobid` instead of `id` and includes `error_message` and `error_type`: ```json theme={null} { "jobid": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", "status": "failed", "error_message": "Job failed", "error_type": "unknown" } ``` # Get credits Source: https://dev.kernel.ai/api-reference/endpoint/get-credits GET /v1/credits Returns the remaining API credits and billing mode for the organization associated with your API key. ## Example ```bash curl theme={null} curl https://api.kernel.ai/rest/v1/credits \ -H "x-api-key: $KERNEL_API_KEY" ``` ```json Response (200) theme={null} { "balance": 452, "billing_mode": "billable" } ``` ## Response fields | Field | Type | Description | | - | - | - | | `balance` | `number` | Remaining API credits. Decremented per job based on job type cost. Always `100` for `exempt` organizations. | | `billing_mode` | `string` | Billing mode for this organization. One of: `billable`, `exempt`. Exempt organizations have unlimited credits. | ## Credit costs | Job type | Cost | | - | - | | Entity resolution | 1 credit | | Firmographic enrichment | 2 credits | | Resolve parent | 2 credits | | Combined | 3 credits | Credits are deducted when a job starts and refunded if the job fails. ## Errors | Status | Response | Cause | | - | - | - | | 401 | `{"error":"Missing x-api-key header"}` | No API key provided | | 404 | `{"error":"Organization not found"}` | API key does not map to an organization | | 503 | `{"error":"Service unavailable"}` | Backend temporarily unavailable | # Get crosscheck result Source: https://dev.kernel.ai/api-reference/endpoint/get-crosscheck GET /v1/crosscheck/{job_id} Returns the status and result of a crosscheck job. When `status` is `completed`, the `record` object contains the resolved `identity` and the `crosscheck` outcome. Returns the status and result of a crosscheck job started with [`POST /v1/crosscheck`](/api-reference/endpoint/crosscheck). When `status` is `completed`, the `record` field contains: * `kernel_id` for the resolved entity, and your `external_id` echoed back * `identity` — the resolution result (`identity_type`, `identity_resolution_confidence`, `identity_resolution_reasoning`, `legal_info`, `trading_info`, `entity_classification`) * `linkedin` — the LinkedIn match, if `match_to_linkedin` was requested * `crosscheck` — the recommended action, duplicate grouping, and operational status, or `null` if the pass did not run. See [Crosscheck not run](#crosscheck-not-run). * `parentage` — the corporate hierarchy, in the same shape as [`GET /v1/combined/{job_id}`](/api-reference/endpoint/get-combined#with-parentage). `null` under the same conditions as `crosscheck`. ## Completed response ```json theme={null} { "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", "status": "completed", "created_at": "2025-06-05T12:00:00Z", "completed_at": "2025-06-05T12:04:12Z", "record": { "kernel_id": "6347422643", "external_id": "0014x00001LMZCDAA5", "identity": { "identity_type": "legal_entity", "identity_resolution_confidence": "HIGH", "identity_resolution_reasoning": "Matched by domain and legal name.", "company_registration_number": null, "legal_info": { "country": "US", "reasoning": "Confirmed via Stripe terms of service page.", "trading_name": "Stripe, Inc.", "confidence": "HIGH", "legal_name": "Stripe, Inc.", "website": "https://stripe.com" }, "trading_info": { "country": "US", "website": "https://stripe.com", "reasoning": "Primary brand site confirmed via domain ownership.", "trading_name": "Stripe", "confidence": "HIGH" }, "entity_classification": { "type": "Company", "subtype": "Operating", "reasoning": "Classified as an operating company based on commercial activity." } }, "crosscheck": { "recommended_action": { "action": "Associate", "association_type": "reparent", "reasoning": "The regional entity is controlled by the identified operating parent." }, "duplicate": { "type": "REGIONAL", "reasoning": "Same trading name and website in a different country.", "group_id": "60498", "duplicate_of": { "kernel_id": "9900374156", "external_id": "0014x00001LMZCDAA5" }, "members": [ { "external_id": "0014x00001LMZCDAA5", "kernel_id": "9900374156", "type": "PRIMARY", "reasoning": null }, { "external_id": "0014x00001oXQfLAAW", "kernel_id": "7643512876", "type": "REGIONAL", "reasoning": "Same trading name and website in a different country." } ], "checked_at": "2026-07-29T09:14:07.642Z" }, "op_status": { "operational_status": "Active", "reasoning": "The company has an active website and current evidence of business operations." }, "checked_at": "2026-07-29T09:14:09.771Z" }, "parentage": { "kernel_id": "6347422643", "parent": { "kernel_id": "9900374156", "external_id": "0014x00001ParentAAA", "trading_name": "Stripe UK", "legal_name": "Stripe Payments UK Ltd", "website": "https://stripe.com", "country": "GB", "entity_category": "Company", "entity_sub_category": "Operating", "confidence": "HIGH", "reasoning": "The regional entity is controlled by the identified operating parent." }, "top_parent": { "kernel_id": "8514783664", "external_id": "0014x00001TopParentA", "trading_name": "Stripe", "legal_name": "Stripe, Inc.", "website": "https://stripe.com", "country": "US", "entity_category": "Company", "entity_sub_category": "HoldCo/Investment", "confidence": "HIGH" }, "top_operating_parent": { "kernel_id": "9900374156", "external_id": "0014x00001ParentAAA", "trading_name": "Stripe UK", "legal_name": "Stripe Payments UK Ltd", "website": "https://stripe.com", "country": "GB", "entity_category": "Company", "entity_sub_category": "Operating", "confidence": "HIGH" }, "regional_subsidiary": { "is_regional": true, "regional_scope": "United Kingdom", "reasoning": "The entity operates within the United Kingdom under the wider corporate group." } } } } ``` ## Reading the crosscheck result | Field | Description | | - | - | | `crosscheck.recommended_action.action` | Recommended action: `Delete`, `Merge`, `Associate`, `Associate (missing parent)`, or `None` | | `crosscheck.recommended_action.association_type` | How to associate, when the action is an Associate variant: `set_initial_parent`, `reparent`, `create_parent`, or `remove_parent` | | `crosscheck.duplicate.type` | How this record is linked into its duplicate group. `PRIMARY` means it is the surviving record | | `crosscheck.duplicate.duplicate_of` | The canonical record this one duplicates, or `null` | | `crosscheck.duplicate.members` | Every record in the duplicate group, each with its own `type` | | `crosscheck.op_status.operational_status` | `Active`, `Out of business`, `Absorbed`, or `Undetermined` | | `crosscheck.checked_at` | When the crosscheck pass last ran | An `action` of `None` means no change is recommended for the record. ## Reading the parentage result `parentage` matches the shape returned by [`GET /v1/combined/{job_id}`](/api-reference/endpoint/get-combined#with-parentage), so hierarchy reads the same wherever it appears. | Field | Description | | - | - | | `parentage.parent` | Immediate parent, with `reasoning` for the assignment. `null` when the entity has none | | `parentage.top_parent` | Ultimate parent at the top of the hierarchy. For standalone entities this points to the entity itself, with `parent` `null` | | `parentage.top_operating_parent` | Highest operating (non-holding) parent | | `parentage.regional_subsidiary` | Whether the entity operates as a regional subsidiary, and its country scope | Each entity carries `kernel_id`, `trading_name`, `legal_name`, `website`, `country`, `entity_category`, `entity_sub_category`, and `confidence`. Crosscheck adds `external_id`, populated when that parent also exists in your CRM. ## Crosscheck not run The pass is skipped when no entity is resolved, or when the `external_id` does not match an account in your Kernel dataset. The job still completes, `crosscheck` and `parentage` are both `null`, and the crosscheck portion of the credit cost is refunded: ```json theme={null} { "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", "status": "completed", "created_at": "2025-06-05T12:00:00Z", "completed_at": "2025-06-05T12:00:05Z", "record": { "kernel_id": null, "external_id": "0014x00001LMZCDAA5", "identity": { "identity_resolution_confidence": "HIGH", "identity_resolution_reasoning": "Company identified as Acme Inc. via legal name and website alignment, but no matching entity exists in Kernel's database.", "company_registration_number": null, "legal_info": null, "trading_info": null, "entity_classification": null }, "crosscheck": null, "parentage": null } } ``` ## Failed response If the job fails, the response uses `jobid` instead of `id` and includes `error_message` and `error_type`: ```json theme={null} { "jobid": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", "status": "failed", "error_message": "Job failed", "error_type": "unknown" } ``` # Get entity resolution result Source: https://dev.kernel.ai/api-reference/endpoint/get-entity-resolution GET /v1/entity-resolution/{job_id} Returns the status and result of an entity resolution job. When `status` is `completed`, the `record` object contains the resolved entity data. Poll this endpoint with the `id` returned by [Resolve entity](/api-reference/endpoint/create-entity-resolution) to check the status and retrieve the result. ## Status lifecycle Jobs progress linearly to a terminal state: ``` pending → processing → completed | failed ``` Once a job reaches `completed` or `failed`, the status does not change. ## Result structure When `status` is `completed`, the `record` field contains the resolved identity with confidence levels and structured legal and trading information. Prefer `record.company_registration` for the registration number, registry country, and source when known. `record.company_registration_number` is a deprecated alias of `company_registration.number`. If you included an `external_id` in the original request, it is echoed back on `record.external_id` so you can correlate the result with the record you submitted. For pending or processing jobs, `record` is absent. For failed jobs, `record` is absent and `error_message` with `error_type` are present instead. ## Example ```bash curl theme={null} curl https://api.kernel.ai/rest/v1/entity-resolution/550e8400-e29b-41d4-a716-446655440000 \ -H "x-api-key: $KERNEL_API_KEY" ``` ```json Response (200) — completed theme={null} { "id": "550e8400-e29b-41d4-a716-446655440000", "status": "completed", "created_at": "2025-06-05T12:00:00Z", "completed_at": "2025-06-05T12:00:05Z", "record": { "kernel_id": "6347422643", "company_registration": { "number": "01234567", "country": "GB", "source": "request" }, "company_registration_number": "01234567", "identity_type": "legal_entity", "identity_resolution_confidence": "HIGH", "identity_resolution_reasoning": "Company identified as Stripe, Inc. via legal name, website, and country alignment. Official Stripe entity confirmed via terms page.", "legal_info": { "country": "US", "reasoning": "Confirmed via Stripe terms of service page.", "trading_name": "Stripe", "confidence": "HIGH", "legal_name": "Stripe, Inc.", "website": "https://stripe.com" }, "trading_info": { "country": "US", "website": "https://stripe.com", "reasoning": "Primary brand site confirmed via domain ownership.", "trading_name": "Stripe", "confidence": "HIGH" }, "entity_classification": { "type": "Company", "subtype": "Operating", "reasoning": "Classified as an operating company based on commercial activity." }, "external_id": "stripe-001" } } ``` ```json Response (200) — still processing theme={null} { "id": "550e8400-e29b-41d4-a716-446655440000", "status": "processing", "created_at": "2025-06-05T12:00:00Z" } ``` ```json Response (200) — failed theme={null} { "jobid": "550e8400-e29b-41d4-a716-446655440000", "status": "failed", "created_at": "2025-06-05T12:00:00Z", "completed_at": "2025-06-05T12:00:05Z", "error_message": "Entity not found", "error_type": "kernel_id_not_found" } ``` ## Polling guidance * Use exponential backoff between polls (start at 2 seconds, cap at 30 seconds). * Jobs that do not exist yet (or whose ID is unknown) return `{ "status": "pending" }`. ### Polling example ```typescript TypeScript theme={null} const API_KEY = "your_api_key"; const BASE_URL = "https://api.kernel.ai/rest"; const headers = { "x-api-key": API_KEY, "Content-Type": "application/json" }; async function resolveEntity(input: Record): Promise { const res = await fetch(`${BASE_URL}/v1/entity-resolution`, { method: "POST", headers, body: JSON.stringify(input), }); if (!res.ok) throw new Error(`POST failed: ${res.status}`); const data = await res.json(); return data.id; } async function pollResult(id: string, timeoutMs = 120_000): Promise> { const start = Date.now(); let interval = 2000; while (Date.now() - start < timeoutMs) { const res = await fetch(`${BASE_URL}/v1/entity-resolution/${id}`, { headers }); if (!res.ok) throw new Error(`GET failed: ${res.status}`); const data: Record = await res.json(); if (data.status === "completed") return data.record as Record; if (data.status === "failed") throw new Error("Job failed — retry with more identifying fields"); await new Promise((r) => setTimeout(r, interval)); interval = Math.min(interval * 2, 30_000); } throw new Error(`Job ${id} did not complete within ${timeoutMs / 1000}s`); } const id = await resolveEntity({ legal_name: "Stripe, Inc.", website: "https://stripe.com", country: "US" }); const result = await pollResult(id); console.log(result.identity_type); // "legal_entity" ``` For the full `IdentityResult` schema, see [Completed result](/api-reference/schemas/entity-resolution-result). # Enrich firmographics Source: https://dev.kernel.ai/api-reference/endpoint/get-firmographics POST /v1/firmographics Starts a firmographic enrichment job for a resolved entity. Returns immediately with an `id` — poll `GET /v1/firmographics/{job_id}` until the status is `completed`. Starts a firmographic enrichment job for a resolved entity. Returns immediately with an `id` — poll `GET /v1/firmographics/{job_id}` until the status is `completed`. Use the `kernel_id` returned by [entity resolution](/api-reference/endpoint/create-entity-resolution) to enrich the entity with operational status, location, headcount, revenue, and industry data. This is an async operation. Use the returned `id` to poll for results, or provide a `webhook_url` to receive a callback when the job completes. ## Examples ### Enrich a resolved entity ```bash curl theme={null} curl -X POST https://api.kernel.ai/rest/v1/firmographics \ -H "x-api-key: $KERNEL_API_KEY" \ -H "Content-Type: application/json" \ -d '{"kernel_id": "2532551796"}' ``` ```json Response (202) theme={null} { "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", "status": "processing" } ``` ```json Response (202) — with webhook theme={null} { "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", "status": "processing" } ``` ## Request body | Field | Type | Required | Description | | - | - | - | - | | `kernel_id` | `string` | Yes | The `kernel_id` of a resolved entity to enrich | | `webhook_url` | `string` | No | HTTPS URL to receive a callback when the job completes or fails | ## Polling for results After receiving an `id`, poll [Get firmographic enrichment job](/api-reference/endpoint/get-firmographics-job) with exponential backoff (start at 2 seconds, max 30 seconds). For the full firmographic result schema, see [Firmographic result](/api-reference/schemas/firmographic-result). ## Related endpoints * [Get firmographic enrichment job](/api-reference/endpoint/get-firmographics-job) — Poll for job status and results * [Resolve entity](/api-reference/endpoint/create-entity-resolution) — Resolve an entity first to get a kernel\_id # Get firmographic enrichment result Source: https://dev.kernel.ai/api-reference/endpoint/get-firmographics-job GET /v1/firmographics/{job_id} Returns the status and result of a firmographic enrichment job. When `status` is `completed`, the `record` field contains the enriched firmographic data. Poll this endpoint to check the status and retrieve the result of a firmographic enrichment job. ## Status lifecycle Jobs progress linearly to a terminal state: ``` pending → processing → completed | failed ``` Once a job reaches `completed` or `failed`, the status does not change. ## Result structure When `status` is `completed`, the `record` field contains the firmographic data with operational status, location, headcount, revenue, and industry — each group including a reasoning field. For pending or processing jobs, only `status` is returned. For failed jobs, `record` is absent. ## Example ```bash curl theme={null} curl https://api.kernel.ai/rest/v1/firmographics/test-firmo-001 \ -H "x-api-key: $KERNEL_API_KEY" ``` ```json Response (200) — completed theme={null} { "id": "test-firmo-001", "status": "completed", "created_at": "2026-06-08T14:00:32.411Z", "completed_at": "2026-06-08T14:53:53.151Z", "record": { "kernel_id": "7944166432", "op_status": { "operational_status": "Active", "reasoning": "Entity is actively operating." }, "location": { "operating": { "street": null, "city": "Singrauli", "state": "Madhya Pradesh", "country": "India", "postcode": "486889", "reasoning": "Address derived from company registration records." }, "registered": { "street": "P.O. Singrauli Colliery", "city": "Singrauli", "state": "Madhya Pradesh", "country": "India", "postcode": "486889", "reasoning": "Address from official registry filing." } }, "headcount": { "count": 13307, "count_entity": 13307, "count_consolidated": 13307, "confidence": "HIGH", "reasoning": "Headcount derived from annual report figures." }, "revenue": { "usd": 2613846573, "usd_entity": 2613846573, "consolidated_usd": 2613846573, "confidence": "HIGH", "local_currency": "INR", "local_currency_entity": "INR", "local": 217820547750, "local_entity": 217820547750, "consolidated_local": 217820547750, "consolidated_currency": "INR", "reasoning": "Revenue sourced from audited annual financial statements.", "source": "identified" }, "industry": { "naics": { "version": "NAICS 2022", "sector": { "value": "21 - Mining, Quarrying, and Oil and Gas Extraction", "code": "21", "label": "Mining, Quarrying, and Oil and Gas Extraction" }, "subsector": { "value": "212 - Mining (except Oil and Gas)", "code": "212", "label": "Mining (except Oil and Gas)" }, "industry_group": { "value": "2121 - Coal Mining", "code": "2121", "label": "Coal Mining" }, "industry": { "value": "21211 - Coal Mining", "code": "21211", "label": "Coal Mining" }, "national_industry": null, "reasoning": "- Coal production and marketing are identified as the target’s activities, and non-coking coal, washed coal, and beneficiation rejects are listed as products.\n- The activity is classified under 21211: Coal Mining because coal is extracted and produced for sale.\n- A surface or underground mining method is not established, so a more specific national industry code is not supported." }, "sic": { "version": "SIC 1987", "division": { "value": "B - Mining", "code": "B", "label": "Mining" }, "major_group": { "value": "12 - Coal Mining", "code": "12", "label": "Coal Mining" }, "industry_group": null, "industry": null, "reasoning": "- Coal production and marketing are identified as Northern Coalfields Limited’s operating activities, and multiple coal products are described.\n- 12: Coal Mining is supported because coal is produced through mining rather than merely traded or marketed.\n- A surface or underground mining method is not specified, so neither more specific coal-mining industry is supported." }, "nace": { "version": "NACE Rev. 2.1", "section": { "value": "B - Mining and quarrying", "code": "B", "label": "Mining and quarrying" }, "division": { "value": "05 - Mining of coal and lignite", "code": "05", "label": "Mining of coal and lignite" }, "group": { "value": "05.1 - Mining of hard coal", "code": "05.1", "label": "Mining of hard coal" }, "class": { "value": "05.10 - Mining of hard coal", "code": "05.10", "label": "Mining of hard coal" }, "reasoning": "- Coal production and marketing are identified as Northern Coalfields Limited’s operations, and its annual report describes a mine-to-market mission.\n- The target is classified under hard coal mining because coal is produced through its own mining operations.\n- A wholesale classification is not preferred because coal production, rather than resale alone, is documented as the target’s activity." } } } } ``` ```json Response (200) — pending theme={null} { "status": "pending" } ``` ```json Response (200) — failed theme={null} { "jobid": "test-firmo-001", "status": "failed", "created_at": "2026-06-08T14:00:32.411Z", "completed_at": "2026-06-08T14:00:50.456Z", "error_message": "Entity not found", "error_type": "kernel_id_not_found" } ``` `confidence` and `reasoning` fields may be `null` when the value is estimated or unavailable. ## Polling guidance * Use exponential backoff between polls (start at 2 seconds, cap at 30 seconds). * Jobs that do not exist yet (or whose ID is unknown) return `{ "status": "pending" }`. * Enrichment typically takes 30 seconds to 5 minutes depending on data availability. For the full `FirmographicResult` schema, see [Firmographic result](/api-reference/schemas/firmographic-result). # Get LinkedIn lookup result Source: https://dev.kernel.ai/api-reference/endpoint/get-linkedin-lookup GET /v1/lookup/linkedin/{job_id} Poll the status and result of a LinkedIn lookup job submitted via Lookup LinkedIn company. Poll with the `id` from [Lookup LinkedIn company](/api-reference/endpoint/create-linkedin-lookup). ## Status lifecycle ``` pending → processing → completed | failed ``` When `completed`, `record` holds the provisional match and profile. No match still completes with `match_method: "none"` and `profile: null`. See [LinkedIn lookup result](/api-reference/schemas/linkedin-lookup-result). ## Example ```bash curl theme={null} curl https://api.kernel.ai/rest/v1/lookup/linkedin/550e8400-e29b-41d4-a716-446655440000 \ -H "x-api-key: $KERNEL_API_KEY" ``` ```json Response (200) — completed theme={null} { "id": "550e8400-e29b-41d4-a716-446655440000", "status": "completed", "created_at": "2026-06-08T14:00:32.411Z", "completed_at": "2026-06-08T14:00:38.151Z", "record": { "match": { "linkedin_url": "https://www.linkedin.com/company/stripe", "slug": "stripe", "match_method": "website", "confidence": "HIGH" }, "profile": { "linkedin_name": "Stripe", "linkedin_website": "https://stripe.com", "linkedin_headcount": 8000, "linkedin_industry": "Financial Services", "linkedin_country": "United States", "linkedin_company_size_range": "1001-5000", "linkedin_company_type": "Privately Held", "linkedin_locality": "San Francisco, CA", "linkedin_address": null, "linkedin_founded_year": 2010, "linkedin_follower_count": 500000 }, "provenance": { "kernel_approved": false } } } ``` ## Related endpoints * [Lookup LinkedIn company](/api-reference/endpoint/create-linkedin-lookup) # Get resolve parent result Source: https://dev.kernel.ai/api-reference/endpoint/get-resolve-parent GET /v1/resolve-parent/{job_id} Returns the status and result of a parent hierarchy resolution job. When `status` is `completed`, the `record` object contains the parent hierarchy data. Poll this endpoint to check the status and retrieve the result of a parent hierarchy resolution job. ## Status lifecycle Jobs progress linearly to a terminal state: ``` pending → processing → completed | failed ``` Once a job reaches `completed` or `failed`, the status does not change. ## Result structure When `status` is `completed`, the `record` field contains the parent hierarchy data with `parent`, `top_parent`, `top_operating_parent` (conditionally present), and `regional_subsidiary`. For pending or processing jobs, only `status` is returned. For failed jobs, `record` is absent and `error_message` with `error_type` are present instead. ## Example ```bash curl theme={null} curl https://api.kernel.ai/rest/v1/resolve-parent/a1b2c3d4-e5f6-7890-abcd-ef1234567890 \ -H "x-api-key: $KERNEL_API_KEY" ``` ```json Response (200) — completed, parent found theme={null} { "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", "status": "completed", "created_at": "2025-06-05T12:00:00Z", "completed_at": "2025-06-05T12:00:05Z", "record": { "kernel_id": "6347422643", "parent": { "kernel_id": "7944166432", "trading_name": "Alphabet Inc.", "legal_name": "Alphabet Inc.", "website": "https://abc.xyz", "country": "US", "entity_category": "Company", "entity_sub_category": "HoldCo/Investment", "reasoning": "Google LLC is a wholly-owned subsidiary of Alphabet Inc., its parent holding company.", "confidence": "HIGH" }, "top_parent": { "kernel_id": "7944166432", "trading_name": "Alphabet Inc.", "legal_name": "Alphabet Inc.", "website": "https://abc.xyz", "country": "US", "entity_category": "Company", "entity_sub_category": "HoldCo/Investment", "confidence": "HIGH" }, "top_operating_parent": { "kernel_id": "6347422643", "trading_name": "Google", "legal_name": "Google LLC", "website": "https://google.com", "country": "US", "entity_category": "Company", "entity_sub_category": "Operating", "confidence": "HIGH" }, "regional_subsidiary": { "is_regional": false, "regional_scope": null, "reasoning": null } } } ``` ```json Response (200) — completed, no parent (standalone entity) theme={null} { "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", "status": "completed", "created_at": "2025-06-05T12:00:00Z", "completed_at": "2025-06-05T12:00:05Z", "record": { "kernel_id": "6347422643", "parent": null, "top_parent": { "kernel_id": "6347422643", "trading_name": "Stripe", "legal_name": "Stripe, Inc.", "website": "https://stripe.com", "country": "US", "entity_category": "Company", "entity_sub_category": "Operating", "confidence": null }, "top_operating_parent": { "kernel_id": "6347422643", "trading_name": "Stripe", "legal_name": "Stripe, Inc.", "website": "https://stripe.com", "country": "US", "entity_category": "Company", "entity_sub_category": "Operating", "confidence": null }, "regional_subsidiary": { "is_regional": false, "regional_scope": null, "reasoning": null } } } ``` ```json Response (200) — pending theme={null} { "status": "pending" } ``` ```json Response (200) — failed theme={null} { "jobid": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", "status": "failed", "created_at": "2025-06-05T12:00:00Z", "completed_at": "2025-06-05T12:00:05Z", "error_message": "Entity not found", "error_type": "kernel_id_not_found" } ``` ## Response fields ### `record.parent` `object | null` — The immediate parent entity. `null` when the entity has no parent (standalone). | Field | Type | Description | | - | - | - | | `kernel_id` | `string` | Kernel ID of the parent entity | | `trading_name` | `string \| null` | Parent trading name | | `legal_name` | `string \| null` | Parent registered legal name | | `website` | `string \| null` | Parent company website URL | | `country` | `string \| null` | Parent country (ISO 3166-1 alpha-2 or full name) | | `entity_category` | `string \| null` | Parent entity category. One of: `Company`, `Government`, `Education` | | `entity_sub_category` | `string \| null` | Parent entity sub-category. One of: `Operating`, `HoldCo/Investment`, `Business Unit`, `Establishment` | | `reasoning` | `string \| null` | Explanation of why this entity was identified as the parent | | `confidence` | `string \| null` | Confidence in the parent identification. One of: `HIGH`, `MEDIUM`, `LOW` | ### `record.top_parent` `object | null` — The ultimate parent entity at the top of the corporate hierarchy. For standalone entities, `top_parent` points to the entity itself and `parent` is `null`. Has the same fields as `parent` except it does not include `reasoning` (only `confidence`). ### `record.top_operating_parent` `object | null` — The topmost operating company (excluding HoldCo/investment vehicles) found by looking up the corporate hierarchy from the queried entity. This field is **conditionally present**: * **Present** when the entity is an operating company or when an operating company is found above it in the hierarchy * **Omitted** for standalone entities that are not operating companies (e.g. HoldCos with no tree) When present, the value is `null` if no operating company exists in the upward chain (e.g. a HoldCo whose entire parent chain consists of other HoldCos). Has the same fields as `top_parent` (no `reasoning`, includes `confidence`). ### `record.regional_subsidiary` `object` — Whether the queried entity operates as a regional subsidiary of its parent. | Field | Type | Description | | - | - | - | | `is_regional` | `boolean \| null` | `true` if the entity is a regional subsidiary, `false` if not. `null` when not yet determined. | | `regional_scope` | `string \| null` | The country scope of the regional operation (e.g. `"United States"`, `"India"`). `null` when not a regional subsidiary or not yet determined. | | `reasoning` | `string \| null` | Explanation of the regional subsidiary classification | ## Polling guidance * Use exponential backoff between polls (start at 2 seconds, cap at 30 seconds). * Jobs that do not exist yet (or whose ID is unknown) return `{ "status": "pending" }`. ## Related endpoints * [Resolve parent](/api-reference/endpoint/resolve-parent) — Start a parent hierarchy resolution job # Resolve parent Source: https://dev.kernel.ai/api-reference/endpoint/resolve-parent POST /v1/resolve-parent Starts a parent hierarchy resolution job for a resolved entity. Returns immediately with an `id` — poll `GET /v1/resolve-parent/{job_id}` until the status is `completed`. Starts a parent hierarchy resolution job for a resolved entity. Returns immediately with an `id` — poll `GET /v1/resolve-parent/{job_id}` until the status is `completed`. Use the `kernel_id` from a previous [Resolve entity](/api-reference/endpoint/create-entity-resolution) call. ## Examples ### Resolve the parent hierarchy for an entity ```bash curl theme={null} curl -X POST https://api.kernel.ai/rest/v1/resolve-parent \ -H "x-api-key: $KERNEL_API_KEY" \ -H "Content-Type: application/json" \ -d '{"kernel_id": "6347422643"}' ``` ```json Response (202) theme={null} { "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", "status": "processing" } ``` ### With webhook callback ```bash curl theme={null} curl -X POST https://api.kernel.ai/rest/v1/resolve-parent \ -H "x-api-key: $KERNEL_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "kernel_id": "6347422643", "webhook_url": "https://example.com/webhooks/kernel" }' ``` ```json Response (202) theme={null} { "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", "status": "processing" } ``` ## Request body | Field | Type | Required | Description | | - | - | - | - | | `kernel_id` | `string` | Yes | The `kernel_id` of a resolved entity | | `webhook_url` | `string` | No | HTTPS URL to receive webhook callbacks when the job completes or fails | ## Polling for results After receiving an `id`, poll [Get resolve parent result](/api-reference/endpoint/get-resolve-parent) with exponential backoff (start at 2 seconds, max 30 seconds). ## Related endpoints * [Get resolve parent result](/api-reference/endpoint/get-resolve-parent) — Poll for job status and results # Webhooks Source: https://dev.kernel.ai/api-reference/endpoint/webhooks Kernel can send HTTP callbacks (webhooks) when jobs complete or fail. This lets you receive results without polling. ## Enabling webhooks Include a `webhook_url` field when creating a job. All async endpoints — entity resolution, firmographic enrichment, and resolve parent — support webhooks: **Entity resolution:** ```bash curl theme={null} curl -X POST https://api.kernel.ai/rest/v1/entity-resolution \ -H "x-api-key: $KERNEL_API_KEY" \ -H "Content-Type: application/json" \ -d '{"legal_name": "Stripe", "webhook_url": "https://example.com/webhooks/kernel"}' ``` **Firmographic enrichment** (via the service API): ```bash curl theme={null} curl -X POST https://api.kernel.ai/rest/v1/firmographics \ -H "x-api-key: $KERNEL_API_KEY" \ -H "Content-Type: application/json" \ -d '{"kernel_id": "6347422643", "webhook_url": "https://example.com/webhooks/kernel"}' ``` **Resolve parent:** ```bash curl theme={null} curl -X POST https://api.kernel.ai/rest/v1/resolve-parent \ -H "x-api-key: $KERNEL_API_KEY" \ -H "Content-Type: application/json" \ -d '{"kernel_id": "6347422643", "webhook_url": "https://example.com/webhooks/kernel"}' ``` The URL must be an HTTPS URL that accepts POST requests. ## Webhook payload When a job completes or fails, Kernel sends a POST request to your `webhook_url` with the following JSON body: ```json theme={null} { "event": "entity-resolution.completed", "timestamp": "2026-06-08T15:30:00Z", "data": { "id": "550e8400-e29b-41d4-a716-446655440000", "status": "completed", "created_at": "2026-06-08T15:00:00Z", "completed_at": "2026-06-08T15:00:32Z", "record": { ... } } } ``` `data` matches the result you get when polling the job's GET endpoint. If you included an `external_id` in the original request, it is echoed back on `data.record.external_id` so you can correlate the callback with the record you submitted. For failed jobs, `status` is `"failed"`, `record` is `null`, and `error_message` with `error_type` are included: ```json theme={null} { "event": "entity-resolution.failed", "timestamp": "2026-06-08T15:31:00Z", "data": { "jobid": "550e8400-e29b-41d4-a716-446655440000", "status": "failed", "created_at": "2026-06-08T15:00:00Z", "completed_at": "2026-06-08T15:00:32Z", "record": null, "error_message": "Entity not found", "error_type": "kernel_id_not_found" } } ``` The `error_message` field is sanitized — internal details like stack traces, UUIDs, and kernel IDs are stripped before delivery. ## Event types | Event | Trigger | | - | - | | `entity-resolution.completed` | An entity resolution job finished successfully | | `entity-resolution.failed` | An entity resolution job failed | | `firmographic-enrichment.completed` | A firmographic enrichment job finished successfully | | `firmographic-enrichment.failed` | A firmographic enrichment job failed | | `resolve-parent.completed` | A resolve-parent job finished successfully | | `resolve-parent.failed` | A resolve-parent job failed | ## Request headers | Header | Description | | - | - | | `Content-Type` | `application/json` | | `X-Kernel-Signature` | `sha256=` — verify this to confirm the payload is from Kernel | | `X-Kernel-Event` | The event type (e.g. `entity-resolution.completed`) | | `X-Kernel-Delivery` | A unique ID for this delivery attempt | ## Verifying signatures Your signing secret is generated when you create an API key and is shown once. To verify a webhook: 1. Compute the HMAC-SHA256 of the raw request body using your signing secret 2. Compare the result (as hex) to the value in the `X-Kernel-Signature` header (after removing the `sha256=` prefix) 3. Use a constant-time comparison to prevent timing attacks ```python theme={null} import hmac, hashlib def verify_signature(body: bytes, signature: str, secret: str) -> bool: expected = hmac.new(secret.encode(), body, hashlib.sha256).hexdigest() return hmac.compare_digest(expected, signature.removeprefix("sha256=")) ``` ## Retry policy If your endpoint returns a non-2xx status or times out (5 second limit), Kernel retries up to 3 times with exponential backoff: | Attempt | Delay | | - | - | | 1 | Immediate | | 2 | 30 seconds | | 3 | 2 minutes | After 3 failed attempts, the delivery is marked as permanently failed. # Introduction Source: https://dev.kernel.ai/api-reference/introduction Kernel API reference ## Base URL ``` https://api.kernel.ai/rest ``` All requests must be sent to this base URL over HTTPS. ## What is entity resolution? Entity resolution is the reasoning-based process Kernel uses to decide what real-world entity a company record represents. It uses names, websites, addresses, email domains, and other signals — not just a simple name lookup — to match records to a canonical entity in Kernel's database. Each resolved entity returns a structured identity result with confidence levels, legal and trading information, and entity classification. The process is asynchronous — you submit a company, get back an `id`, and poll for the result. ## What is firmographic enrichment? Firmographic enrichment adds operational status, location, headcount, revenue, and industry data to a resolved entity. You submit a `kernel_id` from entity resolution and receive structured firmographic data. Like entity resolution, it runs asynchronously. For the full firmographic result schema, see [Firmographic result](/api-reference/schemas/firmographic-result). ## Authentication All endpoints are authenticated using an API key in the `x-api-key` header: ``` x-api-key: ``` Generate and manage API keys from [Settings > API keys](https://app.kernel.ai) in the Kernel app. Store your API key in an environment variable and never commit it to source control. ```bash theme={null} export KERNEL_API_KEY="ker_your_api_key_here" ``` ## Async workflow All operations run asynchronously. Each one returns an `id` you poll until the result is ready. 1. **Start** — call [Resolve entity](/api-reference/endpoint/create-entity-resolution) with the company details. 2. **Poll** — call [Get entity resolution result](/api-reference/endpoint/get-entity-resolution) with the `id`. Use exponential backoff between requests (start at 2 seconds, max 30 seconds). 3. **Read result** — when `status` is `completed`, the `record` object is included with the resolved identity. When `status` is `failed`, `record` is `null`. Jobs transition linearly: `pending` → `processing` → `completed` | `failed`. Terminal states do not change. ## Job types The API uses a job-based architecture. Each endpoint corresponds to a specific job type that determines how the request is processed. The job type is determined by the endpoint path — you do not specify it explicitly. | Endpoint | Description | | - | - | | `POST /v1/entity-resolution` | Async entity resolution | | `GET /v1/entity-resolution/{job_id}` | Poll entity resolution result | | `POST /v1/resolve-parent` | Async parent hierarchy resolution | | `GET /v1/resolve-parent/{job_id}` | Poll resolve parent result | | `POST /v1/firmographics` | Async firmographic enrichment | | `GET /v1/firmographics/{job_id}` | Poll firmographic enrichment result | ## Data formats The API uses the following standards for structured fields: | Data type | Standard | Example | | - | - | - | | Country | ISO 3166-1 alpha-2 preferred, any format accepted | `US`, `United States`, `United States of America` | | Date and time | ISO 8601 | `2025-05-28T14:30:00Z` | | Confidence | Enum | `HIGH`, `MEDIUM`, `LOW` | ## Errors The API uses standard HTTP status codes: | Status | Meaning | Action | | - | - | - | | `403` | Forbidden — missing or invalid API key | Check your API key | | `429` | Rate limit exceeded | Wait for `Retry-After` seconds, then retry | | `500` | Internal server error | Retry with exponential backoff | ## Rate limits Rate limiting is not currently enforced but will be added in a future update. We recommend building retry logic with exponential backoff and respecting `429` responses and `Retry-After` headers when they are introduced. ## Versioning The current API version is **v1**. We will give at least 6 months notice before deprecating a version. Breaking changes will always be introduced under a new path prefix (e.g. `/v2/`). ## Related topics Create and manage API keys for authentication. Receive HTTP callbacks when jobs complete or fail. # Completed result Source: https://dev.kernel.ai/api-reference/schemas/entity-resolution-result This object is returned in `record` when you poll `GET /v1/entity-resolution/{job_id}` and `status` is `completed`. The result contains the resolved identity type and structured legal and trading information. Confidence levels are `HIGH`, `MEDIUM`, or `LOW`. ## Top-level fields ### `kernel_id` `string | null` — A 10-digit unique identifier for the resolved entity in Kernel's central database. The same company always resolves to the same `kernel_id`. `null` when the entity could not be determined. ### `company_registration` `object | null` — Structured registration identity when a registration number is known. `null` when unknown. | Field | Type | Description | | - | - | - | | `number` | `string \| null` | Registration / national ID | | `country` | `string \| null` | Registry jurisdiction as ISO 3166-1 alpha-2 when known | | `source` | `string \| null` | Where the number came from: `registry`, `companies_house`, or `request` | ### `company_registration_number` Deprecated `string | null` — Same value as `company_registration.number`. Prefer `company_registration` for number, country, and source. `null` when unknown. ### `identity_type` `string` — The resolved identity classification. One of: | Value | Meaning | | - | - | | `legal_entity` | Resolved to a registered legal entity | | `trading_entity` | Resolved to a trading identity | ### `identity_resolution_confidence` `string` — Overall confidence in the identity resolution. One of: `HIGH`, `MEDIUM`, `LOW`. ### `identity_resolution_reasoning` `string` — A brief explanation of why the entity was identified as this account, citing the key evidence used. ### `entity_classification` `object | null` — Classification of the resolved entity by entity category. `null` when classification is unavailable. Contains: | Field | Type | Description | | | - | - | - | - | | `type` | string | Entity category (e.g. `"Company"`, `"Government"`, `"Education"`) | | | `subtype` | string | Entity sub-category (e.g. `"Operating"`, `"HoldCo/Investment"`, `"Business Unit"`) | | | `reasoning` | \`string | null\` | Explanation of the classification | ## `legal_info` `object` — Information about the legal entity. | Field | Type | Description | | | - | - | - | - | | `legal_name` | \`string | null\` | Registered legal name (e.g. `"Stripe, Inc."`) | | `website` | \`string | null\` | Official URL of the legal entity | | `country` | \`string | null\` | Country of the legal entity | | `trading_name` | \`string | null\` | Trading name associated with the legal entity | | `confidence` | `string` | Confidence in the legal entity info. One of: `HIGH`, `MEDIUM`, `LOW` | | | `reasoning` | `string` | Explanation of how the legal entity was identified | | ## `trading_info` `object` — Information about the trading identity. | Field | Type | Description | | | - | - | - | - | | `trading_name` | \`string | null\` | Primary trading name (e.g. `"Stripe"`) | | `website` | \`string | null\` | Primary trading website URL | | `country` | \`string | null\` | Country of the trading entity's operational region | | `confidence` | `string` | Confidence in the trading identity info. One of: `HIGH`, `MEDIUM`, `LOW` | | | `reasoning` | `string` | Explanation of how the trading identity was identified | | ## `linkedin` `object | null` — LinkedIn company profile match. Only present when `match_to_linkedin` was set to `true` in the request. | Field | Type | Description | | - | - | - | | `url` | `string \| null` | Full LinkedIn company profile URL | | `slug` | `string \| null` | Company slug extracted from the LinkedIn URL | | `match_type` | `string \| null` | How the profile was matched. One of: `actual`, `indicative`, `none` | | `reasoning` | `string \| null` | Explanation of how the LinkedIn match was determined | ## `external_id` `string` — Echoed back from your request. Present only when you included an `external_id` in the submitted record. Use it to correlate this result with the record you sent. ## Examples ```json Matched entity theme={null} { "kernel_id": "6347422643", "company_registration": { "number": "01234567", "country": "GB", "source": "request" }, "company_registration_number": "01234567", "identity_type": "legal_entity", "identity_resolution_confidence": "HIGH", "identity_resolution_reasoning": "Company identified as Stripe, Inc. via legal name, website, and country alignment.", "legal_info": { "country": "US", "reasoning": "Confirmed via Stripe terms of service page.", "trading_name": "Stripe", "confidence": "HIGH", "legal_name": "Stripe, Inc.", "website": "https://stripe.com" }, "trading_info": { "country": "US", "website": "https://stripe.com", "reasoning": "Primary brand site confirmed via domain ownership.", "trading_name": "Stripe", "confidence": "HIGH" }, "entity_classification": { "type": "Company", "subtype": "Operating", "reasoning": "Classified as an operating company based on commercial activity." }, "linkedin": { "url": "https://www.linkedin.com/company/stripe", "slug": "stripe", "match_type": "actual", "reasoning": "Matched via verified website domain stripe.com." }, "external_id": "stripe-001" } ``` ```json No match — entity not found in Kernel's database theme={null} { "kernel_id": null, "company_registration": null, "company_registration_number": null, "identity_resolution_confidence": "HIGH", "identity_resolution_reasoning": "Company identified as Acme Inc. via legal name and website alignment.", "legal_info": null, "trading_info": null, "entity_classification": null } ``` When identity resolution runs but the entity cannot be matched to a Kernel account, `kernel_id` is `null` and identity detail fields (`legal_info`, `trading_info`, `entity_classification`) are `null`. `company_registration` and `company_registration_number` are `null` when no registration number is available. The `identity_resolution_confidence` and `identity_resolution_reasoning` fields remain populated to explain the resolution attempt. If the `linkedin` field was requested (`match_to_linkedin: true`), it will be `null` in the no-match case. # Firmographic result Source: https://dev.kernel.ai/api-reference/schemas/firmographic-result This object is returned in the `record` field when you call [Get firmographics](/api-reference/endpoint/get-firmographics) or poll a completed [enrichment job](/api-reference/endpoint/get-firmographics-job). The result contains five groups of firmographic data, each always present as an object. Individual fields within each group may be `null` when the value is estimated or unavailable. ## Top-level fields ### `kernel_id` `string` — The unique identifier for the entity in Kernel's database. Same `kernel_id` returned by entity resolution. ### `op_status` `object` — Operational status of the entity. Contains: | Field | Type | Description | | - | - | - | | `operational_status` | `string \| null` | Current status. One of: `Active`, `Out of business`, `Absorbed`, `Undetermined` | | `reasoning` | `string \| null` | Explanation of how the operational status was determined | ### `location` `object` — Operating and registered addresses. Contains: | Field | Type | Description | | - | - | - | | `operating` | `Address` | Primary operating address | | `registered` | `Address` | Registered/legal address | Each `Address` contains: | Field | Type | Description | | - | - | - | | `street` | `string \| null` | Street address | | `city` | `string \| null` | City | | `state` | `string \| null` | State or province | | `country` | `string \| null` | Country | | `postcode` | `string \| null` | ZIP or postal code | | `reasoning` | `string \| null` | Explanation of how the address was determined | ### `headcount` `object` — Headcount data for the entity. Use `count` for the recommended headline figure; `count_entity` and `count_consolidated` expose the underlying entity-direct and consolidated figures. Contains: | Field | Type | Description | | - | - | - | | `count` | `number \| null` | **Recommended headcount.** Kernel automatically picks the entity-direct or consolidated figure based on entity category. Equals `count_entity` or `count_consolidated`. | | `count_entity` | `number \| null` | Entity-direct headcount, excluding subsidiaries | | `count_consolidated` | `number \| null` | Consolidated headcount including subsidiaries | | `confidence` | `string \| null` | Confidence in the figure. One of: `HIGH`, `MEDIUM`, `LOW` | | `reasoning` | `string \| null` | Explanation of how the headcount was determined | ### `revenue` `object` — Revenue data for the entity. Mirrors the headcount structure: the top-level `usd` / `local` / `local_currency` fields hold the **recommended** figure, while `*_entity` and `consolidated_*` expose the underlying entity-direct and consolidated figures. Contains: | Field | Type | Description | | - | - | - | | `usd` | `number \| null` | **Recommended annual revenue in USD.** Kernel automatically picks entity-direct or consolidated based on entity category. Equals `usd_entity` or `consolidated_usd`. | | `usd_entity` | `number \| null` | Entity-direct annual revenue in USD, excluding subsidiaries | | `consolidated_usd` | `number \| null` | Consolidated annual revenue in USD including subsidiaries | | `confidence` | `string \| null` | Confidence in the figure. One of: `HIGH`, `MEDIUM`, `LOW` | | `local_currency` | `string \| null` | Local currency of the recommended source figure | | `local_currency_entity` | `string \| null` | Local currency of the entity-direct source figure | | `local` | `number \| null` | Recommended annual revenue in local currency, matching `usd` | | `local_entity` | `number \| null` | Entity-direct annual revenue in local currency | | `consolidated_local` | `number \| null` | Consolidated revenue in local currency | | `consolidated_currency` | `string \| null` | Currency of the consolidated source figure | | `reasoning` | `string \| null` | Explanation of how the revenue figure was determined | | `source` | `string \| null` | Source of the revenue data. One of: `identified`, `estimated` | ### `industry` `object` — Industry classification under three standards. Contains: | Field | Type | Description | | - | - | - | | `naics` | `Standard` | NAICS 2022. Levels, top to bottom: `sector`, `subsector`, `industry_group`, `industry`, `national_industry` | | `sic` | `Standard` | SIC 1987. Levels, top to bottom: `division`, `major_group`, `industry_group`, `industry` | | `nace` | `Standard` | NACE Rev. 2.1. Levels, top to bottom: `section`, `division`, `group`, `class` | Each `Standard` contains: | Field | Type | Description | | - | - | - | | `version` | `string` | The edition of the standard the codes come from | | One key per level | `Level \| null` | The levels listed above for that standard | | `reasoning` | `string \| null` | Explanation of how the classification was determined, as 3 to 5 hyphen bullets | Each `Level` contains: | Field | Type | Description | | - | - | - | | `value` | `string` | The code and label joined as `code - label`, for example `52 - Finance and Insurance` | | `code` | `string \| null` | The classification code. Always a string, for example `31-33`, `66.19` or `I` | | `label` | `string` | The name of the classification | Kernel classifies to the deepest level the evidence supports and fills the levels above it. When the evidence supports only a higher level, the lower levels are `null`. When it supports none, every level and `reasoning` are `null`. `reasoning` can also be `null` on a classified standard when no explanation meets the reasoning rules. If an activity fits no top-level category of a standard, its top level is `{ "value": "Other", "code": null, "label": "Other" }`, every lower level is `null`, and `reasoning` explains why. This is the only case where `code` is `null`. ## Examples ```json Full result theme={null} { "kernel_id": "7944166432", "op_status": { "operational_status": "Active", "reasoning": "Entity is actively operating with no signs of cessation or absorption." }, "location": { "operating": { "street": null, "city": "Singrauli", "state": "Madhya Pradesh", "country": "India", "postcode": "486889", "reasoning": "Address derived from company registration records." }, "registered": { "street": "P.O. Singrauli Colliery", "city": "Singrauli", "state": "Madhya Pradesh", "country": "India", "postcode": "486889", "reasoning": "Address from official registry filing." } }, "headcount": { "count": 13307, "count_entity": 13307, "count_consolidated": 13307, "confidence": "HIGH", "reasoning": "Headcount derived from annual report figures." }, "revenue": { "usd": 2613846573, "usd_entity": 2613846573, "consolidated_usd": 2613846573, "confidence": "HIGH", "local_currency": "INR", "local_currency_entity": "INR", "local": 217820547750, "local_entity": 217820547750, "consolidated_local": 217820547750, "consolidated_currency": "INR", "reasoning": "Revenue sourced from audited annual financial statements.", "source": "identified" }, "industry": { "naics": { "version": "NAICS 2022", "sector": { "value": "21 - Mining, Quarrying, and Oil and Gas Extraction", "code": "21", "label": "Mining, Quarrying, and Oil and Gas Extraction" }, "subsector": { "value": "212 - Mining (except Oil and Gas)", "code": "212", "label": "Mining (except Oil and Gas)" }, "industry_group": { "value": "2121 - Coal Mining", "code": "2121", "label": "Coal Mining" }, "industry": { "value": "21211 - Coal Mining", "code": "21211", "label": "Coal Mining" }, "national_industry": null, "reasoning": "- Coal production and marketing are identified as the target’s activities, and non-coking coal, washed coal, and beneficiation rejects are listed as products.\n- The activity is classified under 21211: Coal Mining because coal is extracted and produced for sale.\n- A surface or underground mining method is not established, so a more specific national industry code is not supported." }, "sic": { "version": "SIC 1987", "division": { "value": "B - Mining", "code": "B", "label": "Mining" }, "major_group": { "value": "12 - Coal Mining", "code": "12", "label": "Coal Mining" }, "industry_group": null, "industry": null, "reasoning": "- Coal production and marketing are identified as Northern Coalfields Limited’s operating activities, and multiple coal products are described.\n- 12: Coal Mining is supported because coal is produced through mining rather than merely traded or marketed.\n- A surface or underground mining method is not specified, so neither more specific coal-mining industry is supported." }, "nace": { "version": "NACE Rev. 2.1", "section": { "value": "B - Mining and quarrying", "code": "B", "label": "Mining and quarrying" }, "division": { "value": "05 - Mining of coal and lignite", "code": "05", "label": "Mining of coal and lignite" }, "group": { "value": "05.1 - Mining of hard coal", "code": "05.1", "label": "Mining of hard coal" }, "class": { "value": "05.10 - Mining of hard coal", "code": "05.10", "label": "Mining of hard coal" }, "reasoning": "- Coal production and marketing are identified as Northern Coalfields Limited’s operations, and its annual report describes a mine-to-market mission.\n- The target is classified under hard coal mining because coal is produced through its own mining operations.\n- A wholesale classification is not preferred because coal production, rather than resale alone, is documented as the target’s activity." } } } ``` ```json Partial result — inner fields null theme={null} { "kernel_id": "2532551796", "op_status": { "operational_status": "Active", "reasoning": null }, "location": { "operating": { "street": "354 Oyster Point Blvd", "city": "South San Francisco", "state": "California", "country": "United States", "postcode": null, "reasoning": null }, "registered": { "street": null, "city": null, "state": null, "country": null, "postcode": null, "reasoning": null } }, "headcount": { "count": 5300, "count_entity": 5300, "count_consolidated": 8150, "confidence": null, "reasoning": null }, "revenue": { "usd": null, "consolidated_usd": null, "confidence": null, "local_currency": null, "consolidated_local": null, "consolidated_currency": null, "local": null, "reasoning": null, "source": null }, "industry": { "naics": { "version": "NAICS 2022", "sector": { "value": "52 - Finance and Insurance", "code": "52", "label": "Finance and Insurance" }, "subsector": { "value": "522 - Credit Intermediation and Related Activities", "code": "522", "label": "Credit Intermediation and Related Activities" }, "industry_group": { "value": "5223 - Activities Related to Credit Intermediation", "code": "5223", "label": "Activities Related to Credit Intermediation" }, "industry": { "value": "52232 - Financial Transactions Processing, Reserve, and Clearinghouse Activities", "code": "52232", "label": "Financial Transactions Processing, Reserve, and Clearinghouse Activities" }, "national_industry": { "value": "522320 - Financial Transactions Processing, Reserve, and Clearinghouse Activities", "code": "522320", "label": "Financial Transactions Processing, Reserve, and Clearinghouse Activities" }, "reasoning": "- Payment processing and related financial tools are provided to businesses through online and in-person checkout products.\n- The activity is classified under 522320: Financial Transactions Processing, Reserve, and Clearinghouse Activities, because transaction processing is delivered as a financial service.\n- Reusable software publishing is not established as the principal offering, since payment acceptance and financial services are emphasized." }, "sic": { "version": "SIC 1987", "division": { "value": "H - Finance, Insurance, and Real Estate", "code": "H", "label": "Finance, Insurance, and Real Estate" }, "major_group": { "value": "60 - Depository Institutions", "code": "60", "label": "Depository Institutions" }, "industry_group": { "value": "609 - Functions Related To Depository Banking", "code": "609", "label": "Functions Related To Depository Banking" }, "industry": { "value": "6099 - Functions Related To Depository Banking, Not Elsewhere Classified", "code": "6099", "label": "Functions Related To Depository Banking, Not Elsewhere Classified" }, "reasoning": "- Payment processing and financial tools are presented as the principal activity, with businesses offered services to accept and optimize payments online and in person.\n- The activity is classified under 6099: Functions Related To Depository Banking, Not Elsewhere Classified, as payment services are delivered to merchants.\n- Computer software is used to support payment services, but reusable software is not presented as the principal product sold." }, "nace": { "version": "NACE Rev. 2.1", "section": { "value": "L - Financial and insurance activities", "code": "L", "label": "Financial and insurance activities" }, "division": { "value": "66 - Activities auxiliary to financial services and insurance activities", "code": "66", "label": "Activities auxiliary to financial services and insurance activities" }, "group": { "value": "66.1 - Activities auxiliary to financial services, except insurance and pension funding", "code": "66.1", "label": "Activities auxiliary to financial services, except insurance and pension funding" }, "class": { "value": "66.19 - Other activities auxiliary to financial services, except insurance and pension funding", "code": "66.19", "label": "Other activities auxiliary to financial services, except insurance and pension funding" }, "reasoning": "- Payment processing and related financial services are presented as Stripe’s principal offerings, enabling businesses to accept payments online and in person.\n- These transaction services are classified under 66.19 as activities auxiliary to financial services, rather than as monetary intermediation.\n- The software-services alternative is less suitable because payment acceptance and financial transactions are presented as the customer-facing service." } } } ``` All five groups are always present as objects. Inner fields like `count`, `usd`, `reasoning`, and `confidence` may be `null` when the data is unavailable or not yet determined. # LinkedIn lookup result Source: https://dev.kernel.ai/api-reference/schemas/linkedin-lookup-result Returned in `record` when a [LinkedIn lookup job](/api-reference/endpoint/get-linkedin-lookup) completes. Not Kernel-verified. `provenance.kernel_approved` is always `false`. Fields use the `linkedin_*` prefix so they are not Kernel firmographics. ## `match` | Field | Type | Description | | - | - | - | | `linkedin_url` | `string \| null` | Matched LinkedIn company URL | | `slug` | `string \| null` | LinkedIn company slug | | `match_method` | `string` | `linkedin_url`, `website`, `name`, or `none` | | `confidence` | `string` | `HIGH`, `MEDIUM`, or `LOW` | ## `profile` `object \| null` — `null` when `match_method` is `none`. | Field | Type | | - | - | | `linkedin_name` | `string \| null` | | `linkedin_website` | `string \| null` | | `linkedin_headcount` | `number \| null` | | `linkedin_industry` | `string \| null` | | `linkedin_country` | `string \| null` | | `linkedin_company_size_range` | `string \| null` | | `linkedin_company_type` | `string \| null` | | `linkedin_locality` | `string \| null` | | `linkedin_address` | `string \| null` | | `linkedin_founded_year` | `number \| null` | | `linkedin_follower_count` | `number \| null` | | `linkedin_description` | `string \| null` | ## `provenance` | Field | Type | Description | | - | - | - | | `kernel_approved` | `boolean` | Always `false` | ## Example ```json theme={null} { "match": { "linkedin_url": "https://www.linkedin.com/company/stripe", "slug": "stripe", "match_method": "website", "confidence": "HIGH" }, "profile": { "linkedin_name": "Stripe", "linkedin_website": "https://stripe.com", "linkedin_headcount": 8000, "linkedin_industry": "Financial Services", "linkedin_country": "United States", "linkedin_company_size_range": "1001-5000", "linkedin_company_type": "Privately Held", "linkedin_locality": "San Francisco, CA", "linkedin_address": null, "linkedin_founded_year": 2010, "linkedin_follower_count": 500000 }, "provenance": { "kernel_approved": false } } ``` # API keys Source: https://dev.kernel.ai/guides/api-keys Create an API key and make your first authenticated request This guide walks you through creating an API key and using it to authenticate requests to the Kernel API. ## Create an API key 1. Open the [Kernel app](https://app.kernel.ai) and navigate to **Settings > API keys** 2. Click **Create key** — optionally name it (e.g. "Production API") 3. Copy the **key value** and **signing secret** — both are shown only once Save your key and signing secret somewhere secure, like a password manager or environment variable. You will not be able to see them again. ## Authenticate a request Pass the key in the `x-api-key` header of every API request: ```bash curl theme={null} curl -X POST https://api.kernel.ai/rest/v1/entity-resolution \ -H "x-api-key: $KERNEL_API_KEY" \ -H "Content-Type: application/json" \ -d '{"legal_name": "Stripe"}' ``` For full authentication details, see [API keys](/api-reference/endpoint/api-keys). ## What is the signing secret? The signing secret (prefixed with `whsec_`) lets you verify that webhook payloads were sent by Kernel. It is different from your API key — the API key authenticates requests **to** Kernel, while the signing secret verifies that webhooks are **from** Kernel. To learn how to verify webhook signatures, see [Webhooks](/api-reference/endpoint/webhooks). ## Next steps Submit a company and get back its resolved identity. Full endpoint documentation, authentication, and error handling. # OpenAPI spec Source: https://dev.kernel.ai/guides/openapi-spec The Kernel API is described by an OpenAPI 3.1 spec that you can use with Postman, Insomnia, or any tool that supports OpenAPI. Download openapi.json ## Import into Postman 1. Download the spec above. 2. Open Postman and click **Import** (`Ctrl+O` / `Cmd+O`). 3. Drag the file in or click **Upload Files**. 4. Postman generates a **Kernel API** collection with all endpoints, example bodies, and path parameters. 5. Set your API key: click the collection, go to **Authorization**, set type to **API Key**, key to `x-api-key`, and value to your key. # Quickstart Source: https://dev.kernel.ai/guides/quickstart Resolve your first company and get firmographic data Resolve a company to its canonical entity and enrich it with firmographic data using the Kernel API. You'll make four API calls: start entity resolution, get the identity result, start firmographic enrichment, and get the enrichment result. ## Prerequisites * A Kernel API key — [create one in Settings > API keys](https://app.kernel.ai) * `curl` in your terminal (or use the examples below in any HTTP client) ## 1. Start entity resolution Send a `POST` request with a company name: ```bash curl theme={null} curl -X POST https://api.kernel.ai/rest/v1/entity-resolution \ -H "x-api-key: $KERNEL_API_KEY" \ -H "Content-Type: application/json" \ -d '{"legal_name": "Stripe"}' ``` You'll receive a `202` with an `id`: ```json Response (202) theme={null} { "id": "550e8400-e29b-41d4-a716-446655440000", "status": "processing" } ``` ## 2. Get the result Poll the job endpoint with the `id` from step 1: ```bash curl theme={null} curl https://api.kernel.ai/rest/v1/entity-resolution/550e8400-e29b-41d4-a716-446655440000 \ -H "x-api-key: $KERNEL_API_KEY" ``` When the job is complete, you'll get the resolved identity: ```json Response (200) theme={null} { "id": "550e8400-e29b-41d4-a716-446655440000", "status": "completed", "created_at": "2025-06-05T12:00:00Z", "completed_at": "2025-06-05T12:00:05Z", "record": { "kernel_id": "2532551796", "company_registration": null, "company_registration_number": null, "identity_type": "legal_entity", "identity_resolution_confidence": "HIGH", "identity_resolution_reasoning": "Company identified as Stripe, Inc. via legal name, website, and country alignment.", "legal_info": { "country": "US", "reasoning": "Confirmed via terms of service page.", "trading_name": "Stripe", "confidence": "HIGH", "legal_name": "Stripe, Inc.", "website": "https://stripe.com" }, "trading_info": { "country": "US", "website": "https://stripe.com", "reasoning": "Primary brand site confirmed via domain ownership.", "trading_name": "Stripe", "confidence": "HIGH" }, "entity_classification": { "type": "Company", "subtype": "Operating", "reasoning": "Classified as an operating company based on commercial activity." } } } ``` ## 3. Start firmographic enrichment Use the `kernel_id` from the resolved entity to start a firmographic enrichment job: ```bash curl theme={null} curl -X POST https://api.kernel.ai/rest/v1/firmographics \ -H "x-api-key: $KERNEL_API_KEY" \ -H "Content-Type: application/json" \ -d '{"kernel_id": "2532551796"}' ``` You'll receive a `202` with a firmographic enrichment `id`: ```json Response (202) theme={null} { "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", "status": "processing" } ``` ## 4. Get firmographic data Poll the firmographic enrichment job endpoint with the `id` from step 3: ```bash curl theme={null} curl https://api.kernel.ai/rest/v1/firmographics/a1b2c3d4-e5f6-7890-abcd-ef1234567890 \ -H "x-api-key: $KERNEL_API_KEY" ``` When the job is complete, you'll get firmographic data in the `record` object: ```json Response (200) theme={null} { "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", "status": "completed", "created_at": "2025-06-05T12:01:00Z", "completed_at": "2025-06-05T12:02:00Z", "record": { "kernel_id": "2532551796", "op_status": { "operational_status": "Active", "reasoning": "Entity is actively operating." }, "location": { "operating": { "street": "354 Oyster Point Blvd", "city": "South San Francisco", "state": "California", "country": "United States", "postcode": null, "reasoning": null }, "registered": { "street": null, "city": null, "state": null, "country": null, "postcode": null, "reasoning": null } }, "headcount": { "count": 5300, "count_entity": 5300, "count_consolidated": 8150, "confidence": "HIGH", "reasoning": null }, "revenue": { "usd": null, "consolidated_usd": null, "confidence": null, "local_currency": null, "consolidated_local": null, "consolidated_currency": null, "local": null, "reasoning": null, "source": null }, "industry": { "naics": { "version": "NAICS 2022", "sector": { "value": "52 - Finance and Insurance", "code": "52", "label": "Finance and Insurance" }, "subsector": { "value": "522 - Credit Intermediation and Related Activities", "code": "522", "label": "Credit Intermediation and Related Activities" }, "industry_group": { "value": "5223 - Activities Related to Credit Intermediation", "code": "5223", "label": "Activities Related to Credit Intermediation" }, "industry": { "value": "52232 - Financial Transactions Processing, Reserve, and Clearinghouse Activities", "code": "52232", "label": "Financial Transactions Processing, Reserve, and Clearinghouse Activities" }, "national_industry": { "value": "522320 - Financial Transactions Processing, Reserve, and Clearinghouse Activities", "code": "522320", "label": "Financial Transactions Processing, Reserve, and Clearinghouse Activities" }, "reasoning": "- Payment processing and related financial tools are provided to businesses through online and in-person checkout products.\n- The activity is classified under 522320: Financial Transactions Processing, Reserve, and Clearinghouse Activities, because transaction processing is delivered as a financial service.\n- Reusable software publishing is not established as the principal offering, since payment acceptance and financial services are emphasized." }, "sic": { "version": "SIC 1987", "division": { "value": "H - Finance, Insurance, and Real Estate", "code": "H", "label": "Finance, Insurance, and Real Estate" }, "major_group": { "value": "60 - Depository Institutions", "code": "60", "label": "Depository Institutions" }, "industry_group": { "value": "609 - Functions Related To Depository Banking", "code": "609", "label": "Functions Related To Depository Banking" }, "industry": { "value": "6099 - Functions Related To Depository Banking, Not Elsewhere Classified", "code": "6099", "label": "Functions Related To Depository Banking, Not Elsewhere Classified" }, "reasoning": "- Payment processing and financial tools are presented as the principal activity, with businesses offered services to accept and optimize payments online and in person.\n- The activity is classified under 6099: Functions Related To Depository Banking, Not Elsewhere Classified, as payment services are delivered to merchants.\n- Computer software is used to support payment services, but reusable software is not presented as the principal product sold." }, "nace": { "version": "NACE Rev. 2.1", "section": { "value": "L - Financial and insurance activities", "code": "L", "label": "Financial and insurance activities" }, "division": { "value": "66 - Activities auxiliary to financial services and insurance activities", "code": "66", "label": "Activities auxiliary to financial services and insurance activities" }, "group": { "value": "66.1 - Activities auxiliary to financial services, except insurance and pension funding", "code": "66.1", "label": "Activities auxiliary to financial services, except insurance and pension funding" }, "class": { "value": "66.19 - Other activities auxiliary to financial services, except insurance and pension funding", "code": "66.19", "label": "Other activities auxiliary to financial services, except insurance and pension funding" }, "reasoning": "- Payment processing and related financial services are presented as Stripe’s principal offerings, enabling businesses to accept payments online and in person.\n- These transaction services are classified under 66.19 as activities auxiliary to financial services, rather than as monetary intermediation.\n- The software-services alternative is less suitable because payment acceptance and financial transactions are presented as the customer-facing service." } } } } ``` Firmographic enrichment is asynchronous. Use exponential backoff while polling, starting at 2 seconds and capping at 30 seconds. ## Next steps Full endpoint documentation, authentication, and error handling. Full schema for the firmographic response object.