---
title: "Look up an artifact's claim"
method: GET
path: "/api/v1/artifacts/claim"
tags: ["Delegations"]
---

# Look up an artifact's claim

`GET /api/v1/artifacts/claim`

## Request

- Base URL: `https://api.proof.holdings`
- URL: `https://api.proof.holdings/api/v1/artifacts/claim`
- Auth: none required

Public, no API key. Has a domain published a delegation for this exact artifact, and where was it looked for? The answer is decided by carrier evidence read live — the npm manifest, the MCP registry entry the package names, an endpoint's own and host cards, and the delegating domains' `_mcp` DNS pointers and `.well-known` cards — never by the issuer's registry alone: `claimed` only when a token read from one of those places is signed by this issuer, names exactly this artifact and is in force. Every place read is listed with its result. Answers are stored and reused for up to an hour (five minutes when a place could not be read). The found tokens are returned so the answer can be verified without trusting this endpoint.

## Query parameters

- `type` 'url' | 'purl', required: `purl` for a package, `url` for an https endpoint
- `delegate` string, required: The artifact identifier, canonicalized as at delegation issuance (a purl version, qualifiers or subpath are rejected). Exactly one; a repeated parameter is rejected

## Response `200`

The claim answer

- ArtifactClaim: Whether a domain has published a delegation for this exact artifact, and every place that was checked. A delegation attests who authorized the artifact — not that it is safe, audited or endorsed
  - `delegate` string, required: The canonical artifact identity the answer is about
  - `delegate_type` 'url' | 'purl', required
  - `artifact_path` string, nullable, required: The artifact's page on proof.holdings (`/npm/…`, `/pypi/…`, `/endpoint/…`); null for a class with no page
  - `claim` 'claimed' | 'no_claim_found', required: `claimed` only when a token read from a checked location is signed by this issuer, names exactly this artifact and is in force. A delegation that was issued but never published is not a claim, and is not disclosed
  - `checked_at` string, date-time, required: When the answer was checked; answers are reused for up to an hour (five minutes when a location could not be read)
  - `locations` ArtifactClaimLocation[], required
    - `id` 'npm_metadata' | 'mcp_registry' | 'endpoint_url' | 'host_server_card' | 'host_agent_card' | 'host_agent_card_legacy' | 'delegating_domains', required: Which place was read. `delegating_domains` is ONE row covering the `_mcp` DNS pointer and the `.well-known` MCP and agent cards of up to 5 domains holding a delegation for this artifact here; it names no domain unless a delegation for this artifact was found there
    - `location` string, required: The place, named for a reader
    - `url` string, nullable, required: The address read, when the place has one a reader can open
    - `result` 'found_in_force' | 'found_not_in_force' | 'found_other_artifact' | 'found_unverifiable' | 'nothing_published' | 'not_applicable' | 'unchecked', required: What the place yielded. `unchecked` means it could not be read (see `reason`) and is never a negative; `nothing_published` means the place answered and carries no delegation — a card without one, or an address that answered it has no card (404 or 410; at a card address also an endpoint refusing a plain read with 400, 401 or 405, or a web page where a card would be)
    - `reason` 'unreachable' | 'not_json' | 'too_large' | 'insecure_redirect' | 'timed_out' | 'rate_limited' | 'status_unavailable' | 'depends_on_unread_location' | 'invalid_pointer' | 'dns_lookup_failed' | 'ambiguous_entry' | 'null', nullable, required: Why the place could not be read; null unless `result` is `unchecked`
    - `detail` string, required: One sentence on what was read and what it carried
    - `checked_at` string, date-time, required
  - `delegations` ArtifactClaimDelegation[], required
    - `principal` string, required: The domain that authorized this artifact
    - `proof_id` string, required
    - `scope` string[], required
    - `issued_at` string, date-time, required
    - `expires_at` string, date-time, required
    - `token` string, required: The published delegation token as found — verify it yourself against the issuer's JWKS, with the artifact identity YOU resolved as the expected delegate
    - `found_at` string[], required: The locations it was read from
    - `profile` ArtifactClaimProfileLink, required: A public profile of the delegating account that shows the principal domain. Exactly one of the two fields is present
      - `username` string: Present when the profile has a username (`/u/{username}`)
      - `profile_id` string: Present when the profile has no username (`/p/{profile_id}`)
  - `listing` object, nullable, required: Directory listing context for the artifact. Always null today — reserved for the MCP directory's listings

## Other responses

- `400`: `invalid_delegate` (the identifier could not be canonicalized; the message names why) or `validation_error` (a missing, repeated or over-long parameter)
- `429`: Rate limit exceeded
- `503`: `artifact_claim_busy` (the live-check budget is spent and no stored answer exists — retry after `Retry-After` seconds) or `artifact_claim_unavailable` (the check could not be completed)

---

[API](https://skmtc.dev/proof/apis/proof-holdings-api.md) · [All operations](https://skmtc.dev/proof/apis/proof-holdings-api/llms.txt) · [OpenAPI document](https://skmtc.dev/proof/apis/proof-holdings-api/revisions/b15f506de696?raw)
