---
title: "Get Certificate"
method: GET
path: "/v1/certificates/{sha256}"
tags: ["certificates"]
---

# Get Certificate

`GET /v1/certificates/{sha256}`

## Request

- Base URL: `https://api.ctindex.io`
- URL: `https://api.ctindex.io/v1/certificates/{sha256}`
- Auth: one of:
  - API key in header `X-API-Key`
  - HTTP bearer

Return full certificate details for the given SHA-256.

Raw cert bytes were moved out of the hot ``certificates`` table in
task #66; pass ``?include_raw=true`` to opt in to the join against
``certificates_raw``. Without that flag the route never touches the
cold table and never allocates the cert body in memory.

## Path parameters

- `sha256` string, required

## Query parameters

- `include_raw` boolean: When true, fetch the raw cert bytes from cold storage and return them as PEM in ``raw_pem``. Defaults to false so the hot detail path stays small (task #66 hot/cold split). A 202 ``raw_pending`` response means the upstream fetch continues in the background — retry the same call at most 3 times; a 410 ``raw_unavailable`` response is TERMINAL (task #755): stop retrying and fetch the leaf from the upstream CT log via ``log_id``/``leaf_index``.
- `include_enrichment` boolean: When true, attach RDAP registration + live DNS + ASN/hosting context for the certificate's primary hostname under ``enrichment`` (task #501). Opt-in; a slow/failed source degrades to a partial block and never fails the lookup.
- `include_parsed_extensions` boolean: When true, parse the raw cert bytes and attach the ``parsed_extensions`` view (EKU, SAN types, basic constraints, SCT list — GH #205). Best-effort: when the raw bytes are not in cold storage the view is omitted rather than failing the lookup.

## Cookies

- `ctix_session` string, nullable

## Response `200`

Successful Response

- V1CertificateDetail
  - `sha256` string, required
  - `subject_cn` string, nullable
  - `subject_o` string, nullable
  - `sans` string[]
  - `issuer_cn` string, nullable
  - `issuer_o` string, nullable
  - `not_before` string, date-time, nullable
  - `not_after` string, date-time, nullable
  - `is_wildcard` boolean
  - `is_precert` boolean: True when this row is a CT precertificate (poison-extension log entry), False for a final leaf certificate. Precert and final-leaf twins have different SHA-256 hashes and are returned as separate rows; present on every list and detail row. Exception (GH #262): get_expiring_certs collapses twin pairs to the final leaf by default.
  - `precert_sha256` string, nullable: SHA-256 fingerprint of the CT precertificate twin that was collapsed into this final-leaf row (get_expiring_certs default twin collapsing, GH #262). Omitted when no twin was collapsed.
  - `key_type` string, nullable
  - `key_size` integer, nullable
  - `signature_algorithm` string, nullable
  - `is_weak_crypto` boolean, nullable
  - `key_fields_source` string, nullable
  - `first_seen` string, date-time, nullable: When CertIndex wrote this certificate to its database (batch-write timestamp). Multiple unrelated certificates often share an identical first_seen within the same ingestion batch. It is not the CT-log append time and is never substituted for a missing logged_at. Compare with logged_at to measure detection latency.
  - `logged_at` string, date-time, nullable: Timestamp from the CT log entry itself (MerkleTreeLeaf TimestampedEntry.timestamp, RFC 6962 §3.4) — when the log committed this certificate, NOT when CertIndex ingested it. Null for rows indexed before this field shipped, for crt.sh-sourced rows (reconciled_from_crtsh=true), and for any path that could not supply it. A null value means the CT-log timestamp is unavailable for that row; it does not mean the certificate was observed at first_seen, and first_seen is never synthesized into logged_at. Compare with first_seen (CertIndex write time) to measure detection latency. See logged_at_coverage disclosure block.
  - `reconciled_from_crtsh` boolean, nullable
  - `last_seen` string, date-time, nullable
  - `match_class` string, nullable: Attribution class when match_class_filter was supplied on search: first_party, lookalike_candidate, third_party_integration, substring_collision, or shared_hosting. Null on unfiltered search.
  - `match_reason` string, nullable: Semicolon-separated rule=value audit string for match_class. Null on unfiltered search.
  - `from_cold_tier` boolean, nullable: True when this certificate was served exclusively from the Tier 1 cold ClickHouse index (historical data not present in the hot Neon index). Absent/null for certificates served from the primary index. Cold-sourced rows carry key_fields_source='unavailable' and no raw_pem.
  - `raw_pem` string, nullable
  - `log_id` string, nullable
  - `leaf_index` integer, nullable
  - `enrichment` DomainEnrichmentOutput: RDAP + DNS + ASN context for a single domain (task #501).
    - `domain` string, required
    - `registration` EnrichmentRegistration
      - `registrar` string, nullable
      - `created` string, nullable
      - `updated` string, nullable
      - `expires` string, nullable
      - `status` string[]
      - `nameservers` string[]
    - `dns` EnrichmentDNS
      - `a` string[]
      - `aaaa` string[]
      - `mx` EnrichmentMX[]
        - `preference` integer, required
        - `exchange` string, required
      - `ns` string[]
      - `txt` string[]
    - `asn` EnrichmentASN[]
      - `ip` string, required
      - `asn` integer, nullable
      - `prefix` string, nullable
      - `country` string, nullable
      - `network_owner` string, nullable
    - `signals` EnrichmentSignals: Derived attribution signals for a domain. Attached under ``enrichment.signals`` only when the caller passes ``include_signals=true`` AND holds a paid plan (Pro or higher — the free tier gets a 403 ``tier_not_entitled``). Signals are derived from the domain's currently-valid certificates and TXT inventory: issuer diversity, wildcard breadth, third-party vendor fingerprints, and explicit weak-crypto reasons.
      - `issuer_diversity_score` number
      - `distinct_issuers` integer
      - `issuers` string[]
      - `wildcard_breadth` integer
      - `wildcard_names` string[]
      - `third_party_vendors` ThirdPartyVendor[]
        - `vendor` string, required
        - `source` string, required
        - `evidence` string, nullable
      - `weak_crypto_reasons` string[]
      - `certs_considered` integer
      - `certs_capped` boolean
      - `partial` boolean
      - `errors` string, nullable
    - `fetched_at` string, nullable
    - `partial` boolean
    - `errors` object, nullable
    - `cached` boolean
  - `parsed_extensions` ParsedExtensions: Customer-facing extension view parsed from the raw cert bytes (GH #205) — EKU, SAN breakdown by type, basic constraints and the embedded SCT list, so consumers don't have to parse PEM themselves.
    - `extended_key_usage` string[], nullable
    - `san_types` object
    - `basic_constraints` object, nullable
    - `sct_list` object[]
    - `is_precert_poisoned` boolean

## Other responses

- `422`: Validation Error

---

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