> 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/ultimate-parent.md).

# Ultimate Parent

Resolve the commercial parent of a company: the operating group it is sold to and routed under. Submit a company (name + website, optional country) — the website anchors the resolution — and the API returns a job\_id you poll until the result is ready. The response includes the commercial parent, the full ownership chain with passive holding entities flagged `is_discarded`, the ultimate financial parent when a financial owner such as a fund sits above the operating group, GLEIF Legal Entity Identifier (LEI) data for each entity where a match is found, and the resolver's reasoning with its cited source URL.

## Find & validate ultimate parent

> Resolve a company's ultimate parent from one of its subsidiaries, brands or divisions: send \`company\_name\` and \`website\`, both required. The parent returned is the \*\*commercial parent\*\*: the operating group the company is sold to and routed under. Passive holding entities set aside on the way up are flagged \`is\_discarded\` in the ownership chain, and when a financial owner such as a fund sits above the operating group it is returned separately as \`ultimate\_financial\_parent\`. The result also carries the full ownership chain, the relationship type and a confidence score; each entity carries GLEIF metadata in \`lei\_data\` when a match is found, \`null\` when none is.\
> \
> The resolution is anchored on the company's website, not on its name alone: the website binds the name to one specific entity and seeds the search. Ownership is resolved from a live web search plus GLEIF/LEI lookups, not from a static database.\
> \
> Async: poll \`getUltimateParentResult\` with the returned \`job\_id\`.\
> \
> The company name, website and country you supply are sent to Delpha's AI providers, which search the web; the parent found is checked against GLEIF's public LEI register.\
> \
> A live-mode call reserves credits and creates a job record retained for 10 days; unless your team has set resolution retention to 0, the call and its result are also recorded in your team's resolution history for the window your team configured (up to 30 days on the free tier, 180 on a paid plan). Re-submitting the same input starts a new job and a new charge, unless the request carries an \`Idempotency-Key\` already used with the same body within the last 24 hours — that returns the original \`job\_id\` and reserves nothing. Test-mode calls are answered from the published fixture table and reserve nothing — see the API documentation's \*\*Test mode\*\* section.

```json
{"openapi":"3.1.0","info":{"title":"Delpha Data Quality API","version":"2.3.6"},"tags":[{"name":"Ultimate Parent","description":"Resolve the commercial parent of a company: the operating group it is sold to and routed under. Submit a company (name + website, optional country) — the website anchors the resolution — and the API returns a job_id you poll until the result is ready. The response includes the commercial parent, the full ownership chain with passive holding entities flagged `is_discarded`, the ultimate financial parent when a financial owner such as a fund sits above the operating group, GLEIF Legal Entity Identifier (LEI) data for each entity where a match is found, and the resolver's reasoning with its cited source URL."}],"servers":[{"url":"https://api.delpha.io","description":"Production API server"}],"security":[{"oauth2":["api/access"]},{"apiKey":[]}],"components":{"securitySchemes":{"oauth2":{"type":"oauth2","description":"OAuth 2.0 client-credentials flow (machine-to-machine). Token URL: https://secure.delpha.io/oauth2/token. The `api/access` scope is all-access: it grants every operation this document publishes. Per-use-case scoping, per-key credit ceilings and expiry are properties of an API key, not of this flow — use an API key when a credential must be restricted.","flows":{"clientCredentials":{"tokenUrl":"https://secure.delpha.io/oauth2/token","scopes":{"api/access":"Access to the public API"}}}},"apiKey":{"type":"http","scheme":"bearer","bearerFormat":"dlp_","description":"Native Delpha API key. Send it as an HTTP bearer token (`Authorization: Bearer dlp_...`). Keys are issued from the Delpha app (Developer → API keys) and are billed per team against the team's credit balance."}},"schemas":{"UltimateSubmitOutput":{"additionalProperties":true,"description":"Response after submitting an ultimate-parent resolution job.","properties":{"code":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"description":"Stable machine-readable status/error code (see ErrorCode).","title":"Code"},"request_id":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"description":"The API Gateway request id, for support correlation.","title":"Request Id"},"doc_url":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"description":"Link to error documentation (present when published).","title":"Doc Url"},"job_id":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"description":"The job ID. Required if status_code <= 300.","title":"Job Id"},"message":{"description":"The message to return","title":"Message","type":"string"},"status":{"description":"The status of the process","enum":["SUCCESS","ERROR"],"title":"Status","type":"string"},"status_code":{"description":"The HTTP status code to return","title":"Status Code","type":"integer"}},"required":["message","status","status_code"],"title":"UltimateSubmitOutput","type":"object"},"Error":{"type":"object","title":"Error","description":"Typed error envelope emitted by the API for handler-level 4xx/5xx responses. Extends the success envelope with a stable machine-readable `code` and a correlation `request_id`.","properties":{"status":{"type":"string","enum":["ERROR"],"description":"Always \"ERROR\" for an error response."},"status_code":{"type":"integer","description":"The HTTP status code of the response."},"message":{"type":"string","description":"Human-readable, PII-free error message."},"code":{"type":"string","enum":["validation_error","unauthorized","payment_required","not_found","conflict","rate_limited","backend_error","backend_timeout","service_unavailable","job_timeout","internal_error","unsupported_registry","idempotency_key_reuse","idempotency_in_progress","idempotency_key_invalid"],"description":"Stable machine-readable error code. `ok` and `job_running` are the success-side codes and never appear in an error body."},"request_id":{"type":"string","description":"API Gateway request id, for support correlation. The same value is returned in the `x-amzn-RequestId` response header on every response, including the 401/403/429 API Gateway generates itself."},"doc_url":{"type":"string","description":"Link to error documentation. Present when error documentation is published."}},"required":["status","status_code","message"],"additionalProperties":true},"GatewayError":{"type":"object","title":"GatewayError","description":"Error body returned by API Gateway itself, before a handler runs: 401 (no or invalid credential), 403 (the API key's scopes do not cover this operation, or the path is not routed here) and 429 (stage throttle; carries `Retry-After`). It has no `code` and no `request_id`; correlate it through the `x-amzn-RequestId` response header instead. A 401 a handler emits after the gateway admitted the request carries the full `Error` envelope.","properties":{"status":{"type":"string","enum":["ERROR"],"description":"Always \"ERROR\"."},"status_code":{"type":"integer","description":"The HTTP status code of the response (401, 403 or 429)."},"message":{"type":"string","description":"Human-readable error message."}},"required":["message"],"additionalProperties":true},"UltimateSubmitInput":{"additionalProperties":false,"description":"Payload to submit a new ultimate-parent resolution job.","properties":{"company_name":{"description":"Free-form company name as it appears commercially or legally (e.g. `Sephora Brasil`, `Waymo`, `Acme Corp`). Required.","minLength":1,"title":"Company Name","type":"string"},"website":{"description":"Company's primary website, as a URL or a bare domain (e.g. `https://www.sephora.com.br/` or `waymo.com`). Required — the anchor of the resolution: it binds the name to a specific entity and seeds the web search.","minLength":1,"title":"Website","type":"string"},"country":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"description":"Optional country to disambiguate when the website's jurisdiction is unclear (e.g. `France`, `United States`, `Germany`). Free-form name; not constrained to ISO codes.","title":"Country"}},"required":["company_name","website"],"title":"UltimateSubmitInput","type":"object"}},"headers":{"RateLimitLimit":{"description":"Your request allowance for this operation in the current 60-second window. It is counted per credential owner AND per operation: spending it on one operation does not reduce what you may send to another.","schema":{"type":"string"}},"RateLimitRemaining":{"description":"Requests still available to you on this operation in the current window. `0` on the request that exhausts it and on the refusals that follow.","schema":{"type":"string"}},"RateLimitReset":{"description":"When the current window resets, as **UTC epoch seconds** — an absolute instant, not a number of seconds to wait. Use `Retry-After` for the delay.","schema":{"type":"string"}},"RateLimit":{"description":"What is left of the allowance, as a structured field of `draft-ietf-httpapi-ratelimit-headers` (an Internet-Draft, not a published standard): `\"<policy>\";r=<remaining>;t=<seconds to reset>`. Exactly one policy governs a request, so the list always carries one member.","schema":{"type":"string"}},"RateLimitPolicy":{"description":"The allowance that governed this request, as a structured field of `draft-ietf-httpapi-ratelimit-headers` (an Internet-Draft, not a published standard): `\"<policy>\";q=<quota>;w=<window seconds>`. `submit` governs submit and synchronous operations, `poll` the poll operations; the policy for each operation is also published in its `x-rate-limit`. `GET /v1/pricing` is governed by neither and never carries this header.","schema":{"type":"string"}},"DelphaMode":{"description":"Present on every response the API renders to a **test-mode** key on an operation that takes a credential, and on no other: absence means the call was live. A test-mode call is answered from the published fixture table, reserves no credits and reaches no verification backend. The 401, 403 and shared-floor 429 the gateway answers before the API sees the request carry no per-request headers, so they never carry this one, and neither does `GET /v1/pricing`, which takes no credential. See the *Test mode* section of this document.","schema":{"type":"string","enum":["sandbox"]}}}},"paths":{"/v1/ultimate":{"post":{"tags":["Ultimate Parent"],"summary":"Find & validate ultimate parent","description":"Resolve a company's ultimate parent from one of its subsidiaries, brands or divisions: send `company_name` and `website`, both required. The parent returned is the **commercial parent**: the operating group the company is sold to and routed under. Passive holding entities set aside on the way up are flagged `is_discarded` in the ownership chain, and when a financial owner such as a fund sits above the operating group it is returned separately as `ultimate_financial_parent`. The result also carries the full ownership chain, the relationship type and a confidence score; each entity carries GLEIF metadata in `lei_data` when a match is found, `null` when none is.\n\nThe resolution is anchored on the company's website, not on its name alone: the website binds the name to one specific entity and seeds the search. Ownership is resolved from a live web search plus GLEIF/LEI lookups, not from a static database.\n\nAsync: poll `getUltimateParentResult` with the returned `job_id`.\n\nThe company name, website and country you supply are sent to Delpha's AI providers, which search the web; the parent found is checked against GLEIF's public LEI register.\n\nA live-mode call reserves credits and creates a job record retained for 10 days; unless your team has set resolution retention to 0, the call and its result are also recorded in your team's resolution history for the window your team configured (up to 30 days on the free tier, 180 on a paid plan). Re-submitting the same input starts a new job and a new charge, unless the request carries an `Idempotency-Key` already used with the same body within the last 24 hours — that returns the original `job_id` and reserves nothing. Test-mode calls are answered from the published fixture table and reserve nothing — see the API documentation's **Test mode** section.","operationId":"submitUltimateParent","responses":{"202":{"description":"Accepted / still running — poll the result route with the returned job_id.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UltimateSubmitOutput"}}},"headers":{"Location":{"description":"Poll URL for this job (present when the response carries a job_id).","schema":{"type":"string"}},"Retry-After":{"description":"Seconds to wait before polling again.","schema":{"type":"integer"}},"Idempotent-Replayed":{"description":"Set to 'true' when this 202 replays a previously accepted request with the same Idempotency-Key (no new job, no additional charge).","schema":{"type":"string"}},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"},"X-Delpha-Mode":{"$ref":"#/components/headers/DelphaMode"}}},"400":{"description":"Validation error — the request body or query parameters were rejected.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"},"X-Delpha-Mode":{"$ref":"#/components/headers/DelphaMode"}}},"401":{"description":"Authentication failed — invalid or missing OAuth 2.0 token or API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayError"}}},"headers":{}},"402":{"description":"Payment required — the team has insufficient credits.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"},"X-Delpha-Mode":{"$ref":"#/components/headers/DelphaMode"}}},"403":{"description":"Forbidden — the credential is valid but not allowed here: the API key's scopes do not cover this operation, or the operation is not routed in this environment (API Gateway then answers `Missing Authentication Token`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayError"}}},"headers":{}},"409":{"description":"Conflict — the `Idempotency-Key` was already used with a different request body (`idempotency_key_reuse`: a new key admits the new body, the original body replays the original job), or the original request with this key is still being processed (`idempotency_in_progress`: the same request answers with the original job once that one is admitted).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"},"X-Delpha-Mode":{"$ref":"#/components/headers/DelphaMode"}}},"429":{"description":"Too many requests — one of two limits was exceeded. Your allowance for this operation in the current 60-second window: an `Error` body with `code: rate_limited`, `Retry-After` set to the seconds left in the window, and the quota headers with `X-RateLimit-Remaining: 0`; nothing is charged. Or the per-operation floor every caller of that operation shares: a `GatewayError` body with `Retry-After: 1` and no quota headers, refused before the API sees the request.","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/Error"},{"$ref":"#/components/schemas/GatewayError"}]}}},"headers":{"Retry-After":{"description":"Seconds to wait before retrying: the time left in your current window on the allowance refusal, and `1` on the shared per-operation floor.","schema":{"type":"integer"}},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit","description":"Present on the allowance refusal only. The shared per-operation floor is refused by the gateway, whose responses carry no quota headers."},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining","description":"Present on the allowance refusal only. The shared per-operation floor is refused by the gateway, whose responses carry no quota headers."},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset","description":"Present on the allowance refusal only. The shared per-operation floor is refused by the gateway, whose responses carry no quota headers."},"RateLimit":{"$ref":"#/components/headers/RateLimit","description":"Present on the allowance refusal only. The shared per-operation floor is refused by the gateway, whose responses carry no quota headers."},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy","description":"Present on the allowance refusal only. The shared per-operation floor is refused by the gateway, whose responses carry no quota headers."},"X-Delpha-Mode":{"$ref":"#/components/headers/DelphaMode","description":"Present on the allowance refusal only. The shared per-operation floor is refused by the gateway, whose responses carry no per-request headers."}}},"502":{"description":"Bad gateway — the upstream service returned an error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"},"X-Delpha-Mode":{"$ref":"#/components/headers/DelphaMode"}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UltimateSubmitInput"}}}}}}}}
```

## Get ultimate-parent result

> Fetch the result of a previously submitted \`submitUltimateParent\` job by \`job\_id\`. The resolver walks ownership upward from the queried company and returns as \`ultimate\_parent\` the \*\*commercial parent\*\* — the operating group the company is sold to and routed under, not necessarily the top legal owner. Passive holding entities set aside on the way up stay in \`ownership\_chain\` flagged \`is\_discarded\`; when a financial owner such as a fund sits above the operating group, it is returned separately as \`ultimate\_financial\_parent\`.\
> \
> Top-level \`result\` fields: \`ultimate\_parent\` (\`CompanyEntity\`), \`relationship\_type\` (\`Wholly Owned\` / \`Joint Venture\` / \`Member Firm/Franchise\` / \`Portfolio Company\` / \`Brand/Division\` / \`Independent\`), \`confidence\` (a number in \`\[0, 1]\` reported by the resolver), \`comment\`, \`source\_url\` (cited URL, may be \`null\`), \`ownership\_chain\` (\*\*bottom-up\*\* array; index 0 is the queried company), and \`ultimate\_financial\_parent\` (\`CompanyEntity\` or \`null\`). Each \`CompanyEntity\` carries \`legal\_name\`, \`commercial\_name\`, \`country\`, \`website\`, \`website\_validated\`, \`is\_ultimate\_financial\_parent\`, \`is\_discarded\` and \`lei\_data\` (GLEIF metadata or \`null\`).\
> \
> Reading a result starts no work and adds no charge, but it finalizes the job's accounting once: the job's charge is settled when its result is first delivered, and refunded when the job failed, exceeded its time limit or produced no usable result — a job past its time limit is marked failed by that read. Repeating the call returns the same answer and never charges again.

```json
{"openapi":"3.1.0","info":{"title":"Delpha Data Quality API","version":"2.3.6"},"tags":[{"name":"Ultimate Parent","description":"Resolve the commercial parent of a company: the operating group it is sold to and routed under. Submit a company (name + website, optional country) — the website anchors the resolution — and the API returns a job_id you poll until the result is ready. The response includes the commercial parent, the full ownership chain with passive holding entities flagged `is_discarded`, the ultimate financial parent when a financial owner such as a fund sits above the operating group, GLEIF Legal Entity Identifier (LEI) data for each entity where a match is found, and the resolver's reasoning with its cited source URL."}],"servers":[{"url":"https://api.delpha.io","description":"Production API server"}],"security":[{"oauth2":["api/access"]},{"apiKey":[]}],"components":{"securitySchemes":{"oauth2":{"type":"oauth2","description":"OAuth 2.0 client-credentials flow (machine-to-machine). Token URL: https://secure.delpha.io/oauth2/token. The `api/access` scope is all-access: it grants every operation this document publishes. Per-use-case scoping, per-key credit ceilings and expiry are properties of an API key, not of this flow — use an API key when a credential must be restricted.","flows":{"clientCredentials":{"tokenUrl":"https://secure.delpha.io/oauth2/token","scopes":{"api/access":"Access to the public API"}}}},"apiKey":{"type":"http","scheme":"bearer","bearerFormat":"dlp_","description":"Native Delpha API key. Send it as an HTTP bearer token (`Authorization: Bearer dlp_...`). Keys are issued from the Delpha app (Developer → API keys) and are billed per team against the team's credit balance."}},"schemas":{"UltimatePullOutput":{"additionalProperties":true,"description":"Response after retrieving the status and result of an ultimate-parent job.","properties":{"code":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"description":"Stable machine-readable status/error code (see ErrorCode).","title":"Code"},"request_id":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"description":"The API Gateway request id, for support correlation.","title":"Request Id"},"doc_url":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"description":"Link to error documentation (present when published).","title":"Doc Url"},"job_id":{"description":"The job ID echoed back from the request.","title":"Job Id","type":"string"},"message":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"description":"A human-readable message describing the current state or outcome of the job.","title":"Message"},"status":{"description":"The status of the process. Note: SUCCESS at status_code=202 means 'still running'.","enum":["SUCCESS","ERROR"],"title":"Status","type":"string"},"status_code":{"description":"The HTTP status code representing the job's current state. 404 means the job id was never issued.","title":"Status Code","type":"integer"},"result":{"anyOf":[{"$ref":"#/components/schemas/UltimateResult"},{"type":"null"}],"default":null,"description":"The corporate hierarchy resolution. Present only when status_code == 200."}},"required":["job_id","status","status_code"],"title":"UltimatePullOutput","type":"object"},"UltimateResult":{"additionalProperties":true,"description":"The corporate hierarchy resolution: ultimate parent, ownership chain, and supporting evidence.","properties":{"ultimate_parent":{"$ref":"#/components/schemas/CompanyEntity","description":"The commercial parent of the requested company: the operating group it is sold to and routed under."},"relationship_type":{"anyOf":[{"$ref":"#/components/schemas/RelationshipType"},{"type":"null"}],"default":null,"description":"How the requested company relates to the ultimate parent."},"confidence":{"description":"Resolver-reported confidence score in the resolved ultimate parent, from 0 to 1.","maximum":1,"minimum":0,"title":"Confidence","type":"number"},"ownership_chain":{"description":"Ordered chain from the requested company up to the ultimate parent. Empty if the requested company IS the ultimate parent. May contain intermediate holding entities; the entity with `is_ultimate_financial_parent=True` (if any) is also exposed at top level as `ultimate_financial_parent` for convenience.","items":{"$ref":"#/components/schemas/CompanyEntity"},"title":"Ownership Chain","type":"array"},"ultimate_financial_parent":{"anyOf":[{"$ref":"#/components/schemas/CompanyEntity"},{"type":"null"}],"default":null,"description":"Populated only when the ultimate financial parent differs from the commercial parent returned as `ultimate_parent` (e.g., a fund above the operating group is the actual financial owner). When populated, this is the same object as the chain entity whose `is_ultimate_financial_parent` is True."},"comment":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"description":"The resolver's reasoning for the resolved hierarchy, as text. Useful for verification / auditability.","title":"Comment"},"source_url":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"description":"A URL the resolver cited as the basis for its conclusion (typically the parent's IR page or annual report).","title":"Source Url"},"subsidiary_commercial_name":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"description":"The resolver's normalized commercial name for the queried (input) company. Useful when callers pass a fuzzy or legal name and want to see how it was resolved.","title":"Subsidiary Commercial Name"},"ultimate_parent_source_level":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"description":"The authority level of the evidence the resolver relied on for the ultimate-parent conclusion (e.g., 'Securities Filing', 'Annual Report', 'Press Release').","title":"Ultimate Parent Source Level"},"evidence_summary":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"description":"One-line trace summarizing the resolver's reasoning steps (identity verification, chain traversal, discard logic, GTM selection). Useful for audit and debugging.","title":"Evidence Summary"},"is_self_ultimate":{"anyOf":[{"type":"boolean"},{"type":"null"}],"default":null,"description":"True when the queried company is its own ultimate parent (no further hierarchy above it).","title":"Is Self Ultimate"}},"required":["ultimate_parent","confidence"],"title":"UltimateResult","type":"object"},"CompanyEntity":{"additionalProperties":true,"description":"A single entity in the corporate hierarchy — used for the ultimate parent and each link of the ownership chain.","properties":{"legal_name":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"description":"The official legal name of the entity.","title":"Legal Name"},"commercial_name":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"description":"The commonly-used commercial / trade name.","title":"Commercial Name"},"country":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"description":"The country where the entity is headquartered or registered.","title":"Country"},"website":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"description":"The entity's primary website URL.","title":"Website"},"website_validated":{"anyOf":[{"type":"boolean"},{"type":"null"}],"default":null,"description":"True if the website was reachable and resolved cleanly during normalization.","title":"Website Validated"},"lei_data":{"anyOf":[{"$ref":"#/components/schemas/LeiData"},{"type":"null"}],"default":null,"description":"GLEIF Legal Entity Identifier metadata. Null if no match was found at >=80 fuzzy-match score."},"is_ultimate_financial_parent":{"default":false,"description":"True for the chain entity that the resolver identified as the ultimate financial parent (when it differs from the commercial parent returned as `ultimate_parent`).","title":"Is Ultimate Financial Parent","type":"boolean"},"entity_type":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"description":"The entity's legal form / classification as identified by the resolver (e.g., 'Corporation', 'Holding Shell/Foundation', 'Trust').","title":"Entity Type"},"ownership_status":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"description":"Free-form ownership status of the entity as reported by the resolver (e.g., 'Unknown', 'Active').","title":"Ownership Status"},"is_discarded":{"anyOf":[{"type":"boolean"},{"type":"null"}],"default":null,"description":"True when the resolver excluded this entity from the strategic operating chain (e.g., passive holding companies above an operating conglomerate). Lets callers distinguish operating links from holding overlays.","title":"Is Discarded"},"comment":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"description":"Per-entity annotation from the resolver (e.g., 'Target operating entity', 'Passive holding for control purposes').","title":"Comment"}},"title":"CompanyEntity","type":"object"},"LeiData":{"additionalProperties":true,"description":"GLEIF Legal Entity Identifier metadata, populated by a follow-up GLEIF lookup.","properties":{"lei_number":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"description":"The 20-character LEI identifier.","title":"Lei Number"},"lei_source":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"description":"The source of the LEI lookup (typically 'GLEIF').","title":"Lei Source"},"legal_name":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"description":"The official legal name as registered with the LEI authority.","title":"Legal Name"},"headquarters_address":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"string"},{"type":"null"}],"default":null,"description":"Headquarters postal address from the LEI registry. May be a structured dict or a formatted string.","title":"Headquarters Address"},"legal_jurisdiction":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"description":"Legal jurisdiction (ISO 3166-1 alpha-2 country code).","title":"Legal Jurisdiction"},"legal_id":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"description":"National legal identifier (e.g., SIREN in France).","title":"Legal Id"},"registered_at":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"string"},{"type":"null"}],"default":null,"description":"Registration authority data from the LEI registry. May be a structured dict with code/jurisdictions or an ISO date string.","title":"Registered At"}},"title":"LeiData","type":"object"},"RelationshipType":{"description":"How the requested company relates to its ultimate parent.","enum":["Wholly Owned","Member Firm/Franchise","Portfolio Company","Brand/Division","Independent","Joint Venture"],"title":"RelationshipType","type":"string"},"Error":{"type":"object","title":"Error","description":"Typed error envelope emitted by the API for handler-level 4xx/5xx responses. Extends the success envelope with a stable machine-readable `code` and a correlation `request_id`.","properties":{"status":{"type":"string","enum":["ERROR"],"description":"Always \"ERROR\" for an error response."},"status_code":{"type":"integer","description":"The HTTP status code of the response."},"message":{"type":"string","description":"Human-readable, PII-free error message."},"code":{"type":"string","enum":["validation_error","unauthorized","payment_required","not_found","conflict","rate_limited","backend_error","backend_timeout","service_unavailable","job_timeout","internal_error","unsupported_registry","idempotency_key_reuse","idempotency_in_progress","idempotency_key_invalid"],"description":"Stable machine-readable error code. `ok` and `job_running` are the success-side codes and never appear in an error body."},"request_id":{"type":"string","description":"API Gateway request id, for support correlation. The same value is returned in the `x-amzn-RequestId` response header on every response, including the 401/403/429 API Gateway generates itself."},"doc_url":{"type":"string","description":"Link to error documentation. Present when error documentation is published."}},"required":["status","status_code","message"],"additionalProperties":true},"GatewayError":{"type":"object","title":"GatewayError","description":"Error body returned by API Gateway itself, before a handler runs: 401 (no or invalid credential), 403 (the API key's scopes do not cover this operation, or the path is not routed here) and 429 (stage throttle; carries `Retry-After`). It has no `code` and no `request_id`; correlate it through the `x-amzn-RequestId` response header instead. A 401 a handler emits after the gateway admitted the request carries the full `Error` envelope.","properties":{"status":{"type":"string","enum":["ERROR"],"description":"Always \"ERROR\"."},"status_code":{"type":"integer","description":"The HTTP status code of the response (401, 403 or 429)."},"message":{"type":"string","description":"Human-readable error message."}},"required":["message"],"additionalProperties":true}},"headers":{"RateLimitLimit":{"description":"Your request allowance for this operation in the current 60-second window. It is counted per credential owner AND per operation: spending it on one operation does not reduce what you may send to another.","schema":{"type":"string"}},"RateLimitRemaining":{"description":"Requests still available to you on this operation in the current window. `0` on the request that exhausts it and on the refusals that follow.","schema":{"type":"string"}},"RateLimitReset":{"description":"When the current window resets, as **UTC epoch seconds** — an absolute instant, not a number of seconds to wait. Use `Retry-After` for the delay.","schema":{"type":"string"}},"RateLimit":{"description":"What is left of the allowance, as a structured field of `draft-ietf-httpapi-ratelimit-headers` (an Internet-Draft, not a published standard): `\"<policy>\";r=<remaining>;t=<seconds to reset>`. Exactly one policy governs a request, so the list always carries one member.","schema":{"type":"string"}},"RateLimitPolicy":{"description":"The allowance that governed this request, as a structured field of `draft-ietf-httpapi-ratelimit-headers` (an Internet-Draft, not a published standard): `\"<policy>\";q=<quota>;w=<window seconds>`. `submit` governs submit and synchronous operations, `poll` the poll operations; the policy for each operation is also published in its `x-rate-limit`. `GET /v1/pricing` is governed by neither and never carries this header.","schema":{"type":"string"}},"DelphaMode":{"description":"Present on every response the API renders to a **test-mode** key on an operation that takes a credential, and on no other: absence means the call was live. A test-mode call is answered from the published fixture table, reserves no credits and reaches no verification backend. The 401, 403 and shared-floor 429 the gateway answers before the API sees the request carry no per-request headers, so they never carry this one, and neither does `GET /v1/pricing`, which takes no credential. See the *Test mode* section of this document.","schema":{"type":"string","enum":["sandbox"]}}}},"paths":{"/v1/ultimate/{job_id}":{"get":{"tags":["Ultimate Parent"],"summary":"Get ultimate-parent result","description":"Fetch the result of a previously submitted `submitUltimateParent` job by `job_id`. The resolver walks ownership upward from the queried company and returns as `ultimate_parent` the **commercial parent** — the operating group the company is sold to and routed under, not necessarily the top legal owner. Passive holding entities set aside on the way up stay in `ownership_chain` flagged `is_discarded`; when a financial owner such as a fund sits above the operating group, it is returned separately as `ultimate_financial_parent`.\n\nTop-level `result` fields: `ultimate_parent` (`CompanyEntity`), `relationship_type` (`Wholly Owned` / `Joint Venture` / `Member Firm/Franchise` / `Portfolio Company` / `Brand/Division` / `Independent`), `confidence` (a number in `[0, 1]` reported by the resolver), `comment`, `source_url` (cited URL, may be `null`), `ownership_chain` (**bottom-up** array; index 0 is the queried company), and `ultimate_financial_parent` (`CompanyEntity` or `null`). Each `CompanyEntity` carries `legal_name`, `commercial_name`, `country`, `website`, `website_validated`, `is_ultimate_financial_parent`, `is_discarded` and `lei_data` (GLEIF metadata or `null`).\n\nReading a result starts no work and adds no charge, but it finalizes the job's accounting once: the job's charge is settled when its result is first delivered, and refunded when the job failed, exceeded its time limit or produced no usable result — a job past its time limit is marked failed by that read. Repeating the call returns the same answer and never charges again.","operationId":"getUltimateParentResult","responses":{"200":{"description":"Job succeeded — the result payload is populated.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UltimatePullOutput"}}},"headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"},"X-Delpha-Mode":{"$ref":"#/components/headers/DelphaMode"}}},"202":{"description":"Accepted / still running — poll the result route with the returned job_id.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UltimatePullOutput"}}},"headers":{"Location":{"description":"Poll URL for this job (present when the response carries a job_id).","schema":{"type":"string"}},"Retry-After":{"description":"Seconds to wait before polling again.","schema":{"type":"integer"}},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"},"X-Delpha-Mode":{"$ref":"#/components/headers/DelphaMode"}}},"400":{"description":"Validation error — the request body or query parameters were rejected.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"},"X-Delpha-Mode":{"$ref":"#/components/headers/DelphaMode"}}},"401":{"description":"Authentication failed — invalid or missing OAuth 2.0 token or API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayError"}}},"headers":{}},"403":{"description":"Forbidden — the credential is valid but not allowed here: the API key's scopes do not cover this operation, or the operation is not routed in this environment (API Gateway then answers `Missing Authentication Token`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayError"}}},"headers":{}},"404":{"description":"Not found — no job exists for this id, or it belongs to another team.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"},"X-Delpha-Mode":{"$ref":"#/components/headers/DelphaMode"}}},"409":{"description":"Conflict — the credit reservation expired before delivery; resubmit.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"},"X-Delpha-Mode":{"$ref":"#/components/headers/DelphaMode"}}},"429":{"description":"Too many requests — one of two limits was exceeded. Your allowance for this operation in the current 60-second window: an `Error` body with `code: rate_limited`, `Retry-After` set to the seconds left in the window, and the quota headers with `X-RateLimit-Remaining: 0`; nothing is charged. Or the per-operation floor every caller of that operation shares: a `GatewayError` body with `Retry-After: 1` and no quota headers, refused before the API sees the request.","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/Error"},{"$ref":"#/components/schemas/GatewayError"}]}}},"headers":{"Retry-After":{"description":"Seconds to wait before retrying: the time left in your current window on the allowance refusal, and `1` on the shared per-operation floor.","schema":{"type":"integer"}},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit","description":"Present on the allowance refusal only. The shared per-operation floor is refused by the gateway, whose responses carry no quota headers."},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining","description":"Present on the allowance refusal only. The shared per-operation floor is refused by the gateway, whose responses carry no quota headers."},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset","description":"Present on the allowance refusal only. The shared per-operation floor is refused by the gateway, whose responses carry no quota headers."},"RateLimit":{"$ref":"#/components/headers/RateLimit","description":"Present on the allowance refusal only. The shared per-operation floor is refused by the gateway, whose responses carry no quota headers."},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy","description":"Present on the allowance refusal only. The shared per-operation floor is refused by the gateway, whose responses carry no quota headers."},"X-Delpha-Mode":{"$ref":"#/components/headers/DelphaMode","description":"Present on the allowance refusal only. The shared per-operation floor is refused by the gateway, whose responses carry no per-request headers."}}},"500":{"description":"Internal error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"},"X-Delpha-Mode":{"$ref":"#/components/headers/DelphaMode"}}},"502":{"description":"Bad gateway — the upstream service returned an error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"},"X-Delpha-Mode":{"$ref":"#/components/headers/DelphaMode"}}},"503":{"description":"Service unavailable — a downstream dependency was unreachable.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"},"X-Delpha-Mode":{"$ref":"#/components/headers/DelphaMode"}}},"504":{"description":"Gateway timeout — the job exceeded its processing ceiling.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"},"X-Delpha-Mode":{"$ref":"#/components/headers/DelphaMode"}}}},"parameters":[{"name":"job_id","in":"path","required":true,"description":"Opaque job identifier returned by `submitUltimateParent`.","schema":{"type":"string"}}]}}}}
```

## Submit a batch of ultimate-parent resolution items

> Submit 1..100 ultimate-parent resolution items for asynchronous batch processing as ONE job (never a per-item fan-out). Returns a \`job\_id\` immediately (202); poll \`GET /v1/ultimate/batch/{job\_id}\` for status and results. Each item follows \`UltimateSubmitInput\`; see that component for its fields. It uses the runtime validation of \`POST /v1/ultimate\`. A payload with 0 items or more than 100 is rejected with 422.\
> \
> A live-mode call reserves credits and creates a job record retained for 10 days; unless your team has set resolution retention to 0, the call and its result are also recorded in your team's resolution history for the window your team configured (up to 30 days on the free tier, 180 on a paid plan). Re-submitting the same input starts a new job and a new charge, unless the request carries an \`Idempotency-Key\` already used with the same body within the last 24 hours — that returns the original \`job\_id\` and reserves nothing. Test-mode calls are answered from the published fixture table and reserve nothing — see the API documentation's \*\*Test mode\*\* section.

```json
{"openapi":"3.1.0","info":{"title":"Delpha Data Quality API","version":"2.3.6"},"tags":[{"name":"Ultimate Parent","description":"Resolve the commercial parent of a company: the operating group it is sold to and routed under. Submit a company (name + website, optional country) — the website anchors the resolution — and the API returns a job_id you poll until the result is ready. The response includes the commercial parent, the full ownership chain with passive holding entities flagged `is_discarded`, the ultimate financial parent when a financial owner such as a fund sits above the operating group, GLEIF Legal Entity Identifier (LEI) data for each entity where a match is found, and the resolver's reasoning with its cited source URL."}],"servers":[{"url":"https://api.delpha.io","description":"Production API server"}],"security":[{"oauth2":["api/access"]},{"apiKey":[]}],"components":{"securitySchemes":{"oauth2":{"type":"oauth2","description":"OAuth 2.0 client-credentials flow (machine-to-machine). Token URL: https://secure.delpha.io/oauth2/token. The `api/access` scope is all-access: it grants every operation this document publishes. Per-use-case scoping, per-key credit ceilings and expiry are properties of an API key, not of this flow — use an API key when a credential must be restricted.","flows":{"clientCredentials":{"tokenUrl":"https://secure.delpha.io/oauth2/token","scopes":{"api/access":"Access to the public API"}}}},"apiKey":{"type":"http","scheme":"bearer","bearerFormat":"dlp_","description":"Native Delpha API key. Send it as an HTTP bearer token (`Authorization: Bearer dlp_...`). Keys are issued from the Delpha app (Developer → API keys) and are billed per team against the team's credit balance."}},"schemas":{"BatchSubmitOutput":{"additionalProperties":true,"description":"Response after submitting a batch quality job.","properties":{"code":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"description":"Stable machine-readable status/error code (see ErrorCode).","title":"Code"},"request_id":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"description":"The API Gateway request id, for support correlation.","title":"Request Id"},"doc_url":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"description":"Link to error documentation (present when published).","title":"Doc Url"},"job_id":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"description":"The job ID. Required if status <= 300.","title":"Job Id"},"item_count":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"description":"Number of items accepted in the batch (present on success).","title":"Item Count"},"message":{"description":"The message to return","title":"Message","type":"string"},"status":{"description":"The status of the process","enum":["SUCCESS","ERROR"],"title":"Status","type":"string"},"status_code":{"description":"The status code to return","title":"Status Code","type":"integer"}},"required":["message","status","status_code"],"title":"BatchSubmitOutput","type":"object"},"GatewayError":{"type":"object","title":"GatewayError","description":"Error body returned by API Gateway itself, before a handler runs: 401 (no or invalid credential), 403 (the API key's scopes do not cover this operation, or the path is not routed here) and 429 (stage throttle; carries `Retry-After`). It has no `code` and no `request_id`; correlate it through the `x-amzn-RequestId` response header instead. A 401 a handler emits after the gateway admitted the request carries the full `Error` envelope.","properties":{"status":{"type":"string","enum":["ERROR"],"description":"Always \"ERROR\"."},"status_code":{"type":"integer","description":"The HTTP status code of the response (401, 403 or 429)."},"message":{"type":"string","description":"Human-readable error message."}},"required":["message"],"additionalProperties":true},"Error":{"type":"object","title":"Error","description":"Typed error envelope emitted by the API for handler-level 4xx/5xx responses. Extends the success envelope with a stable machine-readable `code` and a correlation `request_id`.","properties":{"status":{"type":"string","enum":["ERROR"],"description":"Always \"ERROR\" for an error response."},"status_code":{"type":"integer","description":"The HTTP status code of the response."},"message":{"type":"string","description":"Human-readable, PII-free error message."},"code":{"type":"string","enum":["validation_error","unauthorized","payment_required","not_found","conflict","rate_limited","backend_error","backend_timeout","service_unavailable","job_timeout","internal_error","unsupported_registry","idempotency_key_reuse","idempotency_in_progress","idempotency_key_invalid"],"description":"Stable machine-readable error code. `ok` and `job_running` are the success-side codes and never appear in an error body."},"request_id":{"type":"string","description":"API Gateway request id, for support correlation. The same value is returned in the `x-amzn-RequestId` response header on every response, including the 401/403/429 API Gateway generates itself."},"doc_url":{"type":"string","description":"Link to error documentation. Present when error documentation is published."}},"required":["status","status_code","message"],"additionalProperties":true},"UltimateBatchSubmitInput":{"description":"Batch envelope for `POST /v1/ultimate/batch`: `{\"items\": [...]}` (1..100 items, 422 beyond). Each item follows `UltimateSubmitInput`; see that component for its fields. It uses the runtime validation of `POST /v1/ultimate`.","properties":{"items":{"description":"The batch items (1..100), each a single-route input payload.","items":{"$ref":"#/components/schemas/UltimateSubmitInput"},"maxItems":100,"minItems":1,"title":"Items","type":"array"}},"required":["items"],"title":"UltimateBatchSubmitInput","type":"object"},"UltimateSubmitInput":{"additionalProperties":false,"description":"Payload to submit a new ultimate-parent resolution job.","properties":{"company_name":{"description":"Free-form company name as it appears commercially or legally (e.g. `Sephora Brasil`, `Waymo`, `Acme Corp`). Required.","minLength":1,"title":"Company Name","type":"string"},"website":{"description":"Company's primary website, as a URL or a bare domain (e.g. `https://www.sephora.com.br/` or `waymo.com`). Required — the anchor of the resolution: it binds the name to a specific entity and seeds the web search.","minLength":1,"title":"Website","type":"string"},"country":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"description":"Optional country to disambiguate when the website's jurisdiction is unclear (e.g. `France`, `United States`, `Germany`). Free-form name; not constrained to ISO codes.","title":"Country"}},"required":["company_name","website"],"title":"UltimateSubmitInput","type":"object"}},"headers":{"RateLimitLimit":{"description":"Your request allowance for this operation in the current 60-second window. It is counted per credential owner AND per operation: spending it on one operation does not reduce what you may send to another.","schema":{"type":"string"}},"RateLimitRemaining":{"description":"Requests still available to you on this operation in the current window. `0` on the request that exhausts it and on the refusals that follow.","schema":{"type":"string"}},"RateLimitReset":{"description":"When the current window resets, as **UTC epoch seconds** — an absolute instant, not a number of seconds to wait. Use `Retry-After` for the delay.","schema":{"type":"string"}},"RateLimit":{"description":"What is left of the allowance, as a structured field of `draft-ietf-httpapi-ratelimit-headers` (an Internet-Draft, not a published standard): `\"<policy>\";r=<remaining>;t=<seconds to reset>`. Exactly one policy governs a request, so the list always carries one member.","schema":{"type":"string"}},"RateLimitPolicy":{"description":"The allowance that governed this request, as a structured field of `draft-ietf-httpapi-ratelimit-headers` (an Internet-Draft, not a published standard): `\"<policy>\";q=<quota>;w=<window seconds>`. `submit` governs submit and synchronous operations, `poll` the poll operations; the policy for each operation is also published in its `x-rate-limit`. `GET /v1/pricing` is governed by neither and never carries this header.","schema":{"type":"string"}},"DelphaMode":{"description":"Present on every response the API renders to a **test-mode** key on an operation that takes a credential, and on no other: absence means the call was live. A test-mode call is answered from the published fixture table, reserves no credits and reaches no verification backend. The 401, 403 and shared-floor 429 the gateway answers before the API sees the request carry no per-request headers, so they never carry this one, and neither does `GET /v1/pricing`, which takes no credential. See the *Test mode* section of this document.","schema":{"type":"string","enum":["sandbox"]}}}},"paths":{"/v1/ultimate/batch":{"post":{"tags":["Ultimate Parent"],"summary":"Submit a batch of ultimate-parent resolution items","description":"Submit 1..100 ultimate-parent resolution items for asynchronous batch processing as ONE job (never a per-item fan-out). Returns a `job_id` immediately (202); poll `GET /v1/ultimate/batch/{job_id}` for status and results. Each item follows `UltimateSubmitInput`; see that component for its fields. It uses the runtime validation of `POST /v1/ultimate`. A payload with 0 items or more than 100 is rejected with 422.\n\nA live-mode call reserves credits and creates a job record retained for 10 days; unless your team has set resolution retention to 0, the call and its result are also recorded in your team's resolution history for the window your team configured (up to 30 days on the free tier, 180 on a paid plan). Re-submitting the same input starts a new job and a new charge, unless the request carries an `Idempotency-Key` already used with the same body within the last 24 hours — that returns the original `job_id` and reserves nothing. Test-mode calls are answered from the published fixture table and reserve nothing — see the API documentation's **Test mode** section.","operationId":"submitUltimateBatch","responses":{"202":{"description":"Accepted / still running — poll the result route with the returned job_id.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BatchSubmitOutput"}}},"headers":{"Location":{"description":"Poll URL for this job (present when the response carries a job_id).","schema":{"type":"string"}},"Retry-After":{"description":"Seconds to wait before polling again.","schema":{"type":"integer"}},"Idempotent-Replayed":{"description":"Set to 'true' when this 202 replays a previously accepted request with the same Idempotency-Key (no new job, no additional charge).","schema":{"type":"string"}},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"},"X-Delpha-Mode":{"$ref":"#/components/headers/DelphaMode"}}},"401":{"description":"Authentication failed — invalid or missing OAuth 2.0 token or API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayError"}}},"headers":{}},"402":{"description":"Payment required — the team has insufficient credits.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"},"X-Delpha-Mode":{"$ref":"#/components/headers/DelphaMode"}}},"403":{"description":"Forbidden — the credential is valid but not allowed here: the API key's scopes do not cover this operation, or the operation is not routed in this environment (API Gateway then answers `Missing Authentication Token`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayError"}}},"headers":{}},"409":{"description":"Conflict — the `Idempotency-Key` was already used with a different request body (`idempotency_key_reuse`: a new key admits the new body, the original body replays the original job), or the original request with this key is still being processed (`idempotency_in_progress`: the same request answers with the original job once that one is admitted).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"},"X-Delpha-Mode":{"$ref":"#/components/headers/DelphaMode"}}},"422":{"description":"Unprocessable entity — the request is well-formed but cannot be processed: a documented size/shape bound was violated (`validation_error`), or a legal-ID request names a registry / country Delpha cannot query (`unsupported_registry` — refused before any credit is reserved; the message lists the supported countries).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"},"X-Delpha-Mode":{"$ref":"#/components/headers/DelphaMode"}}},"429":{"description":"Too many requests — one of two limits was exceeded. Your allowance for this operation in the current 60-second window: an `Error` body with `code: rate_limited`, `Retry-After` set to the seconds left in the window, and the quota headers with `X-RateLimit-Remaining: 0`; nothing is charged. Or the per-operation floor every caller of that operation shares: a `GatewayError` body with `Retry-After: 1` and no quota headers, refused before the API sees the request.","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/Error"},{"$ref":"#/components/schemas/GatewayError"}]}}},"headers":{"Retry-After":{"description":"Seconds to wait before retrying: the time left in your current window on the allowance refusal, and `1` on the shared per-operation floor.","schema":{"type":"integer"}},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit","description":"Present on the allowance refusal only. The shared per-operation floor is refused by the gateway, whose responses carry no quota headers."},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining","description":"Present on the allowance refusal only. The shared per-operation floor is refused by the gateway, whose responses carry no quota headers."},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset","description":"Present on the allowance refusal only. The shared per-operation floor is refused by the gateway, whose responses carry no quota headers."},"RateLimit":{"$ref":"#/components/headers/RateLimit","description":"Present on the allowance refusal only. The shared per-operation floor is refused by the gateway, whose responses carry no quota headers."},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy","description":"Present on the allowance refusal only. The shared per-operation floor is refused by the gateway, whose responses carry no quota headers."},"X-Delpha-Mode":{"$ref":"#/components/headers/DelphaMode","description":"Present on the allowance refusal only. The shared per-operation floor is refused by the gateway, whose responses carry no per-request headers."}}},"500":{"description":"Internal error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"},"X-Delpha-Mode":{"$ref":"#/components/headers/DelphaMode"}}},"502":{"description":"Bad gateway — the upstream service returned an error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"},"X-Delpha-Mode":{"$ref":"#/components/headers/DelphaMode"}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UltimateBatchSubmitInput"}}}}}}}}
```

## Get ultimate-parent resolution batch job status

> Poll a batch of ultimate-parent resolution items submitted via \`POST /v1/ultimate/batch\`. 202 while running (with \`item\_count\`/\`processed\_count\` progress); 200 once SUCCEEDED (with \`counts\`, a presigned \`result\_url\`, and \`result\_data\` inlined when <=1MB); 409 if the credit reservation expired before delivery (resubmit); 500 if the job failed; 504 past the 24h ceiling.\
> \
> Reading a result starts no work and adds no charge, but it finalizes the job's accounting once: the job's charge is settled when its result is first delivered, and refunded when the job failed, exceeded its time limit or produced no usable result — a job past its time limit is marked failed by that read. Repeating the call returns the same answer and never charges again.

```json
{"openapi":"3.1.0","info":{"title":"Delpha Data Quality API","version":"2.3.6"},"tags":[{"name":"Ultimate Parent","description":"Resolve the commercial parent of a company: the operating group it is sold to and routed under. Submit a company (name + website, optional country) — the website anchors the resolution — and the API returns a job_id you poll until the result is ready. The response includes the commercial parent, the full ownership chain with passive holding entities flagged `is_discarded`, the ultimate financial parent when a financial owner such as a fund sits above the operating group, GLEIF Legal Entity Identifier (LEI) data for each entity where a match is found, and the resolver's reasoning with its cited source URL."}],"servers":[{"url":"https://api.delpha.io","description":"Production API server"}],"security":[{"oauth2":["api/access"]},{"apiKey":[]}],"components":{"securitySchemes":{"oauth2":{"type":"oauth2","description":"OAuth 2.0 client-credentials flow (machine-to-machine). Token URL: https://secure.delpha.io/oauth2/token. The `api/access` scope is all-access: it grants every operation this document publishes. Per-use-case scoping, per-key credit ceilings and expiry are properties of an API key, not of this flow — use an API key when a credential must be restricted.","flows":{"clientCredentials":{"tokenUrl":"https://secure.delpha.io/oauth2/token","scopes":{"api/access":"Access to the public API"}}}},"apiKey":{"type":"http","scheme":"bearer","bearerFormat":"dlp_","description":"Native Delpha API key. Send it as an HTTP bearer token (`Authorization: Bearer dlp_...`). Keys are issued from the Delpha app (Developer → API keys) and are billed per team against the team's credit balance."}},"schemas":{"UltimateBatchPullOutput":{"additionalProperties":true,"description":"Response for `GET /v1/ultimate/batch/{job_id}`. Each `result_data.items[]` entry is keyed to its request item by `dispatch_key` (`{\"record_id\": \"<job_id>#<index>\"}`). On success its `result` is the SAME object `GET /v1/ultimate/{job_id}` returns for a single item (see `UltimateResult`), EXCEPT `relationship_type` here is a **nullable string** rather than the strict enum. On failure it carries an `error` string instead of `result`.","properties":{"code":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"description":"Stable machine-readable status/error code (see ErrorCode).","title":"Code"},"request_id":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"description":"The API Gateway request id, for support correlation.","title":"Request Id"},"doc_url":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"description":"Link to error documentation (present when published).","title":"Doc Url"},"message":{"description":"A human-readable message describing the current state or outcome of the job.","title":"Message","type":"string"},"status":{"description":"The status of the process","enum":["SUCCESS","ERROR"],"title":"Status","type":"string"},"status_code":{"description":"The HTTP status code representing the job's current state.","title":"Status Code","type":"integer"},"counts":{"anyOf":[{"$ref":"#/components/schemas/CountsModel"},{"type":"null"}],"default":null,"description":"Item-level outcome counts (present only once the job has completed)."},"result_url":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"description":"Presigned URL (1h expiry) to download the full batch result JSON from S3.","title":"Result Url"},"result_data":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"default":null,"description":"The full batch result JSON, inlined (opaque). Present only when status_code == 200 and the result file is <=1MB; otherwise omitted (fetch `result_url` instead). Shape: `{job_id, usecase, counts, items: [...]}`; its `result` is the SAME object `GET /v1/ultimate/{job_id}` returns for a single item (see `UltimateResult`), EXCEPT `relationship_type` here is a **nullable string** rather than the strict enum.","title":"Result Data"},"item_count":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"description":"Total number of items in the batch (present while the job is running).","title":"Item Count"},"processed_count":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"description":"Number of items processed so far (present while the job is running; may be absent early in the job's lifecycle).","title":"Processed Count"},"process_time":{"anyOf":[{"minimum":0,"type":"number"},{"type":"null"}],"default":null,"description":"The total time taken to process the job, in seconds.","title":"Process Time"}},"required":["message","status","status_code"],"title":"UltimateBatchPullOutput","type":"object"},"CountsModel":{"description":"Item-level outcome counts for a completed batch job.","properties":{"total":{"description":"Total number of items submitted.","title":"Total","type":"integer"},"succeeded":{"description":"Number of items that succeeded.","title":"Succeeded","type":"integer"},"failed":{"description":"Number of items that failed.","title":"Failed","type":"integer"}},"required":["total","succeeded","failed"],"title":"CountsModel","type":"object"},"Error":{"type":"object","title":"Error","description":"Typed error envelope emitted by the API for handler-level 4xx/5xx responses. Extends the success envelope with a stable machine-readable `code` and a correlation `request_id`.","properties":{"status":{"type":"string","enum":["ERROR"],"description":"Always \"ERROR\" for an error response."},"status_code":{"type":"integer","description":"The HTTP status code of the response."},"message":{"type":"string","description":"Human-readable, PII-free error message."},"code":{"type":"string","enum":["validation_error","unauthorized","payment_required","not_found","conflict","rate_limited","backend_error","backend_timeout","service_unavailable","job_timeout","internal_error","unsupported_registry","idempotency_key_reuse","idempotency_in_progress","idempotency_key_invalid"],"description":"Stable machine-readable error code. `ok` and `job_running` are the success-side codes and never appear in an error body."},"request_id":{"type":"string","description":"API Gateway request id, for support correlation. The same value is returned in the `x-amzn-RequestId` response header on every response, including the 401/403/429 API Gateway generates itself."},"doc_url":{"type":"string","description":"Link to error documentation. Present when error documentation is published."}},"required":["status","status_code","message"],"additionalProperties":true},"GatewayError":{"type":"object","title":"GatewayError","description":"Error body returned by API Gateway itself, before a handler runs: 401 (no or invalid credential), 403 (the API key's scopes do not cover this operation, or the path is not routed here) and 429 (stage throttle; carries `Retry-After`). It has no `code` and no `request_id`; correlate it through the `x-amzn-RequestId` response header instead. A 401 a handler emits after the gateway admitted the request carries the full `Error` envelope.","properties":{"status":{"type":"string","enum":["ERROR"],"description":"Always \"ERROR\"."},"status_code":{"type":"integer","description":"The HTTP status code of the response (401, 403 or 429)."},"message":{"type":"string","description":"Human-readable error message."}},"required":["message"],"additionalProperties":true}},"headers":{"RateLimitLimit":{"description":"Your request allowance for this operation in the current 60-second window. It is counted per credential owner AND per operation: spending it on one operation does not reduce what you may send to another.","schema":{"type":"string"}},"RateLimitRemaining":{"description":"Requests still available to you on this operation in the current window. `0` on the request that exhausts it and on the refusals that follow.","schema":{"type":"string"}},"RateLimitReset":{"description":"When the current window resets, as **UTC epoch seconds** — an absolute instant, not a number of seconds to wait. Use `Retry-After` for the delay.","schema":{"type":"string"}},"RateLimit":{"description":"What is left of the allowance, as a structured field of `draft-ietf-httpapi-ratelimit-headers` (an Internet-Draft, not a published standard): `\"<policy>\";r=<remaining>;t=<seconds to reset>`. Exactly one policy governs a request, so the list always carries one member.","schema":{"type":"string"}},"RateLimitPolicy":{"description":"The allowance that governed this request, as a structured field of `draft-ietf-httpapi-ratelimit-headers` (an Internet-Draft, not a published standard): `\"<policy>\";q=<quota>;w=<window seconds>`. `submit` governs submit and synchronous operations, `poll` the poll operations; the policy for each operation is also published in its `x-rate-limit`. `GET /v1/pricing` is governed by neither and never carries this header.","schema":{"type":"string"}},"DelphaMode":{"description":"Present on every response the API renders to a **test-mode** key on an operation that takes a credential, and on no other: absence means the call was live. A test-mode call is answered from the published fixture table, reserves no credits and reaches no verification backend. The 401, 403 and shared-floor 429 the gateway answers before the API sees the request carry no per-request headers, so they never carry this one, and neither does `GET /v1/pricing`, which takes no credential. See the *Test mode* section of this document.","schema":{"type":"string","enum":["sandbox"]}}}},"paths":{"/v1/ultimate/batch/{job_id}":{"get":{"tags":["Ultimate Parent"],"summary":"Get ultimate-parent resolution batch job status","description":"Poll a batch of ultimate-parent resolution items submitted via `POST /v1/ultimate/batch`. 202 while running (with `item_count`/`processed_count` progress); 200 once SUCCEEDED (with `counts`, a presigned `result_url`, and `result_data` inlined when <=1MB); 409 if the credit reservation expired before delivery (resubmit); 500 if the job failed; 504 past the 24h ceiling.\n\nReading a result starts no work and adds no charge, but it finalizes the job's accounting once: the job's charge is settled when its result is first delivered, and refunded when the job failed, exceeded its time limit or produced no usable result — a job past its time limit is marked failed by that read. Repeating the call returns the same answer and never charges again.","operationId":"getUltimateBatchResult","responses":{"200":{"description":"Job succeeded — the result payload is populated.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UltimateBatchPullOutput"}}},"headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"},"X-Delpha-Mode":{"$ref":"#/components/headers/DelphaMode"}}},"202":{"description":"Accepted / still running — poll the result route with the returned job_id.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UltimateBatchPullOutput"}}},"headers":{"Location":{"description":"Poll URL for this job (present when the response carries a job_id).","schema":{"type":"string"}},"Retry-After":{"description":"Seconds to wait before polling again.","schema":{"type":"integer"}},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"},"X-Delpha-Mode":{"$ref":"#/components/headers/DelphaMode"}}},"400":{"description":"Validation error — the request body or query parameters were rejected.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"},"X-Delpha-Mode":{"$ref":"#/components/headers/DelphaMode"}}},"401":{"description":"Authentication failed — invalid or missing OAuth 2.0 token or API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayError"}}},"headers":{}},"403":{"description":"Forbidden — the credential is valid but not allowed here: the API key's scopes do not cover this operation, or the operation is not routed in this environment (API Gateway then answers `Missing Authentication Token`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayError"}}},"headers":{}},"404":{"description":"Not found — no job exists for this id, or it belongs to another team.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"},"X-Delpha-Mode":{"$ref":"#/components/headers/DelphaMode"}}},"409":{"description":"Conflict — the credit reservation expired before delivery; resubmit.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"},"X-Delpha-Mode":{"$ref":"#/components/headers/DelphaMode"}}},"429":{"description":"Too many requests — one of two limits was exceeded. Your allowance for this operation in the current 60-second window: an `Error` body with `code: rate_limited`, `Retry-After` set to the seconds left in the window, and the quota headers with `X-RateLimit-Remaining: 0`; nothing is charged. Or the per-operation floor every caller of that operation shares: a `GatewayError` body with `Retry-After: 1` and no quota headers, refused before the API sees the request.","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/Error"},{"$ref":"#/components/schemas/GatewayError"}]}}},"headers":{"Retry-After":{"description":"Seconds to wait before retrying: the time left in your current window on the allowance refusal, and `1` on the shared per-operation floor.","schema":{"type":"integer"}},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit","description":"Present on the allowance refusal only. The shared per-operation floor is refused by the gateway, whose responses carry no quota headers."},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining","description":"Present on the allowance refusal only. The shared per-operation floor is refused by the gateway, whose responses carry no quota headers."},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset","description":"Present on the allowance refusal only. The shared per-operation floor is refused by the gateway, whose responses carry no quota headers."},"RateLimit":{"$ref":"#/components/headers/RateLimit","description":"Present on the allowance refusal only. The shared per-operation floor is refused by the gateway, whose responses carry no quota headers."},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy","description":"Present on the allowance refusal only. The shared per-operation floor is refused by the gateway, whose responses carry no quota headers."},"X-Delpha-Mode":{"$ref":"#/components/headers/DelphaMode","description":"Present on the allowance refusal only. The shared per-operation floor is refused by the gateway, whose responses carry no per-request headers."}}},"500":{"description":"Internal error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"},"X-Delpha-Mode":{"$ref":"#/components/headers/DelphaMode"}}},"503":{"description":"Service unavailable — a downstream dependency was unreachable.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"},"X-Delpha-Mode":{"$ref":"#/components/headers/DelphaMode"}}},"504":{"description":"Gateway timeout — the job exceeded its processing ceiling.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer"}},"X-RateLimit-Limit":{"$ref":"#/components/headers/RateLimitLimit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/RateLimitRemaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/RateLimitReset"},"RateLimit":{"$ref":"#/components/headers/RateLimit"},"RateLimit-Policy":{"$ref":"#/components/headers/RateLimitPolicy"},"X-Delpha-Mode":{"$ref":"#/components/headers/DelphaMode"}}}},"parameters":[{"name":"job_id","in":"path","required":true,"description":"The unique identifier of the ultimate-parent resolution batch job.","schema":{"type":"string"}}]}}}}
```


---

# 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/ultimate-parent.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.
