> For the complete documentation index, see [llms.txt](https://help.delpha.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://help.delpha.io/delpha-api-and-mcp/api/changelog.md).

# Changelog

Every version of this document, newest first, with the day it reached production. Additive changes — new fields, new operations, new optional parameters — ship without a path-version change and bump `info.version`; see **Versioning and deprecation** for what each kind of change means for a caller.

#### 2.3.6 — released 2026-10-21

* `website` no longer declares `format: uri` on any operation that takes one (email, legal ID, LinkedIn profile, LinkedIn company page, website, ultimate parent and company search), and neither does `linkedin` on the website operation. A bare domain such as `delpha.io` is accepted on every one of them, and the annotation allowed strict clients to refuse it before any request was sent. Each description now says so, and the request-body `website` examples on these operations show both forms.
* The LinkedIn `url` fields keep `format: uri`, and their descriptions now say what the format score checks: a URL without a scheme (`http://` or `https://`) is answered `validity: 0`, with `normalized_value` unaffected.
* Two descriptions no longer claim a role the service does not perform: the legal-ID `website` (registry selection reads `legal_id_type` and `address.country` only, as documented) and the LinkedIn profile `website`.

#### 2.3.5 — released 2026-10-19

* The LinkedIn profile operation now requires a person's first and last name (or a profile url) before it accepts a job: a company name alone is refused before any credit is reserved, and the company-page operation likewise no longer accepts a person's name alone.
* A request with an absent or empty body is now refused with the same field-level guidance a missing field receives, and a body that is not a JSON object with one plain sentence, instead of an internal parsing message.

#### 2.3.4 — released 2026-10-16

* Every operation now publishes `x-codeSamples`: the request in curl, Python (`requests`), Node.js and raw HTTP, built from the operation itself — a placeholder API key where one is needed, an `Idempotency-Key` on every submit that accepts one (generated per request in curl, Python and Node.js, a placeholder in the raw HTTP request), and the status and body of the response printed. Every request body now publishes an example (`examples.default`), and that example is the body the samples send.
* A new **Code examples** section shows a submit and its polling loop, an idempotent submit, a batch and a test-mode call, each in curl, Python and Node.js.

#### 2.3.3 — released 2026-10-12

* `POST /v1/phone` and `POST /v1/name` are retitled "Validate & normalize phone number" and "Validate & normalize person name", and their descriptions now say what each is for and what it does not do: neither searches — each validates and normalizes the number or name it is given. The phone descriptions, on `POST /v1/phone` and `GET /v1/phone/{job_id}`, now list the scores a phone result carries — `validity`, `completeness` and `consistency`, with a `confidence` rating of the parse; `accuracy` is not assessed for phone numbers — and describe `area` as a place name, which can be a city or region rather than the country. The `phone` and `country_code` descriptions say plainly how a national-format number gets its country, and the name descriptions say exactly what normalization removes. Summaries and descriptions only, including the `phone`, `country_code` and `country` field descriptions — no field added, removed or renamed, and prices are unchanged.
* `POST /v1/phone` now uses `country` when it is the only country given: a national-format `phone` sent with `country` and no `country_code` is normalized with that country when Delpha recognizes the name (for example `France`). Only some country names are recognized, and a national-format number sent with one that is not is still left unnormalized; `country_code` covers every country. Before this release such a request was accepted, but its number was not normalized whatever the country. Requests that carry `country_code`, or a number in E.164 form, behave as before.
* New: `GET /v1/pricing` returns the current credit price of every use case — its route segment (`use_case`), the operation it is billed as (`operation`, the `x-credit-operation` value its operations publish) and the credits charged — read from the same price table every reservation is priced from. A price is per request for a single or synchronous operation and per item for a batch. When the current table cannot be read the operation answers 503 with `Retry-After`, never a partial list.
* `GET /v1/pricing` is free and takes no credential: it publishes `security: []`, so it answers no 401 or 403, reserves no credit, and returns the same list to every caller whatever key the request carries, or none. Its only limit is the shared per-operation floor — its `x-rate-limit` publishes the floor alone — so its responses carry neither the quota headers nor `X-Delpha-Mode`.
* A new extension, `x-credit-free: true`, marks an operation that is never billed; it is published in place of `x-credit-operation`, which every other operation that admits work keeps publishing. `GET /v1/pricing` is also the first operation whose `x-mcp-annotations` publish `readOnlyHint: true`.

#### 2.3.2 — released 2026-09-29

* The MCP hints (`x-mcp-annotations`) now say what each operation does, and no operation is published as read-only. Every operation that reserves credits — the eight job submits, the eight batch submits and the synchronous routes — is `readOnlyHint: false` and `idempotentHint: false`: an accepted call debits credits, creates a job or call record and is kept in the team's resolution history, and a repeat is a new charge. `POST /v1/name` and its batch and `GET /v1/company` are `openWorldHint: false`: they compute from the request and Delpha's own data and reach no external system. The result reads — single and batch — are `readOnlyHint: false` with `idempotentHint: true`: a read adds no charge and a repeat returns the same answer, but the read that observes a finished job settles its charge (or refunds it when the job failed or produced no usable result), and a read past the job's time limit marks the job failed. Each result read now states this in its description and in `x-side-effects`.
* New `x-mcp-omit` extension on `POST /v1/website`, `POST /v1/linkedin-profile`, `POST /v1/linkedin-company-page` (`email`) and `POST /v1/phone` (`country`): fields the MCP server withholds from its tool input because another field carries the same signal. The REST contract is unchanged and still accepts them.
* Every job submit now opens with the input it needs, and the descriptions say what leaves Delpha for a website search (a web-search provider and Delpha's AI provider) and for a legal-ID lookup (the selected country's public registry; a company found there is added to Delpha's datalake). `legal_id` and the legal-ID `address` are described as the company's registry number and registered address, never a person's. An email sent to the LinkedIn tools is used only for its domain, and the descriptions now say so.
* The **Data sources and privacy** table now covers every operation, the company ones included: what `POST /v1/website`, `POST /v1/legal-id` and `POST /v1/ultimate` send outside Delpha and to whom, and that a legal-ID registry result is kept in Delpha's company datalake. `POST /v1/ultimate` states its recipients in its own description too.
* `POST /v1/linkedin-company-page/batch` items no longer list `first_name` and `last_name`, which the lookup never used; they are still accepted. The company-page batch result example now shows a company page instead of a person's profile.
* A `GET /v1/linkedin-profile/{job_id}` result now reports an outdated profile URL: `url_changed` is true when the URL you submitted was not found while exactly one other profile matching the person was, and `suggested_url` names that profile. LinkedIn does not redirect a profile whose address was changed, so the old address simply stops working. `scores.validity` still checks the URL's format only, and the URL you submit is no longer requested at all.

#### 2.3.1 — released 2026-09-24

* `GET /v1/linkedin-company-page/{job_id}` now has its own result schema. Its candidates no longer list `job_title` or `profile_name`, and the result no longer lists `fallback_used`: on a company page the first was always null, the second was null or repeated the page name, and the third was always false, because the name-only fallback searches for a person. Read the page name from `headline` or `company_name`. `GET /v1/linkedin-profile/{job_id}` is unchanged.

#### 2.3.0 — released 2026-09-23

* A new **Data sources and privacy** guide. For every operation that can return information about a person it states what the request supplies, where the result comes from, and which values leave Delpha and to what kind of provider; the providers themselves are named individually in Delpha's sub-processor list. It also publishes what each store keeps and for how long, including the resolution-history window your team sets and the retention that applies when it is set to 0.
* Every operation that spends credits now states its own side effects in its description: what a call reserves, what is recorded and for how long, what a repeat submission costs, and what a test-mode call does instead.
* The operations that can return information about a person each carry one sentence naming where their result comes from, and what — if anything — is sent outside Delpha to produce it.
* The guide also states Delpha's role for each call (processor for the customer under the GDPR, service provider under the CCPA, controller of its cross-customer verification cache) and gives anyone whose data was checked a direct contact for access, correction and erasure requests.
* Every operation that starts a job now publishes `idempotentHint: false` in `x-mcp-annotations`: without an `Idempotency-Key`, repeating a submit starts a new job and a new charge. Each operation's side-effect note is also published on its own, as `x-side-effects`.
* The ultimate-parent operations describe the parent they return as the commercial parent — the operating group a company is sold to and routed under — with passive holding entities flagged `is_discarded` and a financial owner returned separately. The `getUltimateParentResult` field list names `source_url`, the field the result actually carries.
* Descriptions throughout are now statements of what an operation does and returns rather than instructions to the caller, and the tag summaries describe the operations instead of the product.
* Three corrections. `email_domain_qualification` is documented as the five values the API returns, each defined as a property of the address's domain. The ultimate-parent documentation states that GLEIF metadata is carried when a match is found and is `null` when none is. The name operation no longer claims to return signals it has never computed; its description now lists what it does return, and states that characters outside the Latin script are removed during normalization.

#### 2.2.0 — released 2026-09-23

* LinkedIn profile and company-page requests now have separate schemas, including batch items, with operation-specific parameter descriptions and URL examples. The single company-page schema no longer advertises `first_name` or `last_name`; existing callers can still send them.
* Corrected the email label documentation to list `No`, `OK`, and `OddFormat`. Website documentation now explains when a redirect destination is adopted — same registrable domain, or the evidence ranking it above the original, or a corroborating search candidate — its host-only normalization, and the `Changed` and `Unknown` verdicts: `Changed` reports an adopted move, and `Unknown` means the request named no company, so accuracy had no basis.
* The LinkedIn result `label` now reads `OK`, the casing every other use case already publishes, instead of `Ok`. Update any comparison against `"Ok"`. The API accepts both spellings from the verification backend and will keep doing so, so nothing is lost in transit; only the value the API publishes changes. Batch results are normalized the same way, in both the inline payload and the downloadable file.

#### 2.1.0 — released 2026-09-23

* Every legal-ID suggestion and match (`GET /v1/legal-id/{job_id}`) now carries `site_type` — `headquarters`, `branch`, or `unknown` when the register holds no value; an open vocabulary, so treat it as a string — and `vat`, the entity's VAT identifier when one is known. They are the fields `GET /v1/company` already publishes for the same record (spelled `site_type` and `VAT` there).
* This was more than a documentation gap: the verification backend was already returning both, and `GET /v1/legal-id/batch/{job_id}` already carried them, while the single poller discarded them before the response was written.

#### 2.0.0 — released 2026-09-16

* Withdrawn: the address operations (`POST /v1/address`, its poller and its batch pair). The postal-address verification is no longer offered on the public API.
* Withdrawn: the LinkedIn import operations (`POST /v1/linkedin-import` and its poller) and the LinkedIn scraper operations (`POST /v1/linkedin-scraper` and its poller).
* Withdrawn: the combined LinkedIn operations (`POST /v1/linkedin`, its poller and its batch pair), deprecated since 1.2.0 in favour of `/v1/linkedin-profile` and `/v1/linkedin-company-page`, which are unchanged and take the same body.
* Withdrawn: `POST /v1/email-insights`.
* Results now name fields the verification backends were already returning and this document did not describe: `email_address_qualification` on an email result (`Spam Trap` / `Role-based`, which takes precedence over the domain qualification), `confidence` in a phone result's scores, `activity_score` and `is_prepaid` on both phone operations, `type` on a LinkedIn result, and `headquarters_site` on every legal-ID suggestion and match.
* One of those was more than a documentation gap: a phone result's `scores.confidence` was being discarded before the response was written, so `POST /v1/phone` and `GET /v1/phone/{job_id}` never carried it while `POST /v1/phone/batch` did. Both now return it.

#### 1.5.0 — released 2026-09-15

* Test mode: an API key can now be created in test mode, and calls made with one are answered from a published table of canned results — no credits reserved or settled, no verification backend or data provider queried, and the same operations, schemas, validation, idempotency and polling contract as a live key. The mode is chosen when the key is created and cannot be edited afterwards.
* Every response the API renders to a test-mode call carries `X-Delpha-Mode: sandbox`; a live response carries no such header. The 401, 403 and shared-floor 429 the gateway answers itself carry none of the per-request headers.
* A test-mode job is complete when it is accepted, so its first poll answers 200 rather than the transient 202 — the submit, its `Location` and `Retry-After` and its idempotency behaviour are unchanged.
* Webhook events for a test-mode job carry `data.mode`, and the `WebhookEvent` schema now declares it. Test-mode and live jobs are isolated: polling one with the other mode's key answers 404.
* `POST /v1/email-insights` is served by a different service and has no test-mode implementation, so a test-mode key is refused there instead of being served a live, billable answer.

#### 1.4.0 — released 2026-09-15

* Every response the API renders now reports what is left of your allowance: `X-RateLimit-Limit`, `X-RateLimit-Remaining` and `X-RateLimit-Reset`, plus the `RateLimit` and `RateLimit-Policy` structured fields. The gateway's own 401 and 403 are answered before the API sees the request and carry none of them.
* Rate limits are counted per credential owner and per operation — per team for an API key, per OAuth client for the client-credentials flow — in fixed 60-second windows, so one caller's burst no longer consumes another's headroom below the shared floor.
* A 429 now takes one of two documented shapes: your own allowance answers with the standard error envelope (`code: rate_limited`), the quota headers and a `Retry-After` of the seconds left in the window; the per-operation floor shared by all callers answers earlier, with `Retry-After: 1`.
* Each operation's `x-rate-limit` extension now publishes the policy that governs it, its quota and window, and the headers it returns.

#### 1.3.1 — released 2026-09-14

* Every value of the error `code` enum now carries its own published meaning, the status it usually rides on and what to do about it — in the document, on the error reference page, and on every endpoint page that references the error envelope.
* The OAuth `api/access` scope is documented as all-access: per-use-case scoping, per-key credit ceilings and expiry are properties of an API key.
* Batch settlement is documented as partial — only the items that succeed are charged.
* Each published document now describes only the environment it is published for: the production document lists the production server alone, and every example names production. A client generated from it offers one base URL instead of two.
* These guide and reference pages are generated from the document itself, so they change in the release that changes the API.

#### 1.3.0 — released 2026-09-10

* Cursor pagination on `GET /v1/company`: the `cursor` query parameter, `next_cursor` on the result, a nullable `page` on a cursor page, and the 422 that says a cursor was refused.

#### 1.2.0 — released 2026-09-10

* The agent integration guide in the document's own description — the source these pages are generated from.
* Signed webhook lifecycle events (`sent`, `done`, `error`) published as a `webhooks` section, with the event schema.
* `Deprecation` and `Link` response headers on every response of a deprecated operation.

#### 1.1.0 — released 2026-09-10

* A typed error envelope: a stable machine-readable `code`, a `request_id` for support correlation, and a `doc_url` once the error reference is published.
* The gateway's 401, 403 and 429 documented on every operation.
* Per-operation idempotency and rate-limit extensions (`x-idempotency`, `x-rate-limit`), plus typical latency, submit/poll pairing and credit operation.

#### 1.0.0 — released 2025-07-21

* First published OpenAPI document for the public API.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://help.delpha.io/delpha-api-and-mcp/api/changelog.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
