> ## Documentation Index
> Fetch the complete documentation index at: https://docs.trustblock.run/llms.txt
> Use this file to discover all available pages before exploring further.

# Get a project's Etherscan card

> Trustblock API route to get a project's Etherscan card



## OpenAPI

````yaml GET /v1/project/etherscan-card
openapi: 3.0.0
info:
  title: Trustblock Public API
  version: 1.1.0
  description: >
    The public routes of the Trustblock API, as they behave today.


    This document is a description, not a promise. It covers only the `/v1`
    routes that are available

    to callers outside Trustblock; internal routes used by the website and by
    administrators are

    deliberately absent. Where current behaviour is inconsistent and under
    review, the route says so

    rather than picking the answer we would prefer.


    Every route requires a bearer token. There is no unauthenticated route.
  contact:
    name: Trustblock documentation
    url: https://docs.trustblock.run
servers:
  - url: https://api.trustblock.run
    description: Production. This is the only server.
security: []
tags:
  - name: Project security
    description: Read the published audit state of a project.
  - name: Cards
    description: Compact summaries for third-party block explorers.
  - name: Publishing
    description: Routes for audit providers to publish and correct their own audits.
paths:
  /v1/project/etherscan-card:
    get:
      tags:
        - Cards
      summary: Get a project's Etherscan card
      description: >
        A rendered summary of a project's audit state, shaped for the Etherscan
        contract page:

        display strings, an image and a status colour.


        Identified the same way as `/v1/project/security`, and subject to the
        same `chain`/`address`

        pairing rule. **This route consumes no API credit.**


        **The five cards.** The worst state wins, in this order:


        | State | `centerText` | `statusColor` | `isFound` / `status` |

        |---|---|---|---|

        | Incident | "Incident 24 May 2026" | `#E84353` red | `true` |

        | Open critical | "2 open critical findings" | `#E84353` red | `true` |

        | Acknowledged critical | "1 critical acknowledged, not fixed" |
        `#F08D3C` orange | `true` |

        | None open | "No open critical findings" | `#67A22F` green | `true` |

        | No audit | "No audit on Trustblock" | `#F08D3C` orange | `false` |


        "Open" means neither fixed nor acknowledged, across every audit still in
        force. An incident is

        shown while it is later than the latest audit in force, or less than
        twelve months old.


        **The contract line.** When the request names a contract (`chain` +
        `address`) and an audit's own

        scope names that address, the card carries `contractLine`, for example
        "This address was in the

        scope of the Hacken audit of 9 Sep 2026". Otherwise the field is absent
        and the card stays

        project-level.


        **Caching.** A lookup by `chain` + `address` alone may be answered from
        a cache for up to five

        minutes, so a publish or a correction reaches the card within that time.
        A `200` carries

        `Cache-Control: public, max-age=300`; an error carries none. The key
        check is cached for five

        minutes too: a revoked key can keep reaching the cards for up to five
        minutes.


        **A missing project and a failure are different answers.** When the
        project is unknown or has

        no audit, or `chain` is a chain Trustblock does not record, this route
        answers `200` with

        `isFound: false` and the "No audit on Trustblock" card - that is a real
        answer and is meant to be

        rendered (or hidden, on `status: false`). When the lookup itself fails,
        it answers an error status

        instead: `503` if a dependency was briefly unreachable, `500` otherwise.
        Neither is a statement

        about the project, and neither should be cached as one.
      operationId: getProjectEtherscanCard
      parameters:
        - in: query
          name: domain
          required: false
          schema:
            type: string
        - in: query
          name: slug
          required: false
          schema:
            type: string
        - in: query
          name: chain
          required: false
          description: >-
            One of the chain names below, or a decimal EVM chain id (`1`, `56`,
            `8453`...). A chain Trustblock does not record - an unknown id or
            name - answers `200` with `isFound: false` (no card), never an
            error.
          schema:
            type: string
            example: ethereum
        - in: query
          name: address
          required: false
          schema:
            type: string
      responses:
        '200':
          description: A card, found or not found.
          headers:
            Cache-Control:
              description: >-
                `public, max-age=300`. A card may be reused for five minutes.
                Error answers carry no Cache-Control.
              schema:
                type: string
                example: public, max-age=300
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GetEtherscanCardResponse'
        '400':
          description: The query is unusable - for example `chain` without `address`.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '401':
          description: No `Authorization` header was sent.
        '403':
          description: The bearer token is not a recognised key.
        '500':
          description: The lookup failed. This is not a statement about the project.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '503':
          description: >-
            A dependency was briefly unreachable and the request is worth
            retrying. Carries `Retry-After`, in seconds.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
      security:
        - BearerAuth: []
components:
  schemas:
    GetEtherscanCardResponse:
      type: object
      required:
        - isFound
        - imageUrl
        - centerText
        - statusColor
        - extra
      properties:
        isFound:
          type: boolean
          description: >-
            False for the "No audit on Trustblock" card: an unknown project, a
            project with no audit, or a chain Trustblock does not record.
            `imageUrl`, `centerText` and `statusColor` are still sent; the other
            card fields are then absent.
        status:
          type: boolean
          description: >-
            The same value as `isFound`, under the name Etherscan's multichain
            template reads.
        contractLine:
          type: string
          description: >-
            Present only when the request named a contract (`chain` + `address`)
            and an audit's own scope names that address: "This address was in
            the scope of the Hacken audit of 9 Sep 2026", or "This address was
            in the scope of 2 audits; latest: Hacken, 8 May 2026". Absent
            otherwise, never null.
        imageUrl:
          type: string
        centerText:
          type: string
          description: >-
            One short line. The worst state wins: "Incident 3 Aug 2026" (red),
            "2 open critical findings" (red), "2 criticals acknowledged, not
            fixed" (orange), "No open critical findings" (green), or "No audit
            on Trustblock" (orange, `isFound: false`).
        statusColor:
          $ref: '#/components/schemas/EtherscanCardStatusColor'
        topLeftText:
          type: string
        topRightText:
          type: string
          description: For example "Last audit Aug 2026".
        centerText2:
          type: string
          description: For example "3 audits by 2 firms". Plain text.
        centerText3:
          type: string
        iconUrl:
          type: string
        url:
          type: string
          description: The project's page on Trustblock.
        isAIScan:
          type: boolean
        extra:
          $ref: '#/components/schemas/Extra'
    Error:
      type: object
      required:
        - message
        - extra
      properties:
        message:
          type: string
          description: A short, non-localised description of the failure.
          example: Not found.
        code:
          type: string
          description: A stable machine-readable code, where one applies.
        diagnoses:
          type: array
          description: Field-level detail, present on validation failures.
          items:
            type: object
        extra:
          $ref: '#/components/schemas/Extra'
    EtherscanCardStatusColor:
      type: string
      description: Hex colour for the card, matching its status.
      enum:
        - '#F08D3C'
        - '#E84353'
        - '#67A22F'
    Extra:
      type: object
      description: Present on every response, including errors.
      required:
        - requestId
      properties:
        requestId:
          type: string
          description: Quote this when reporting a problem.
  securitySchemes:
    BearerAuth:
      type: http
      scheme: bearer
      description: >
        `Authorization: Bearer <key>`.


        For the project and card routes, the key is an API key belonging to an
        onboarded integrator or

        to an active audit provider. The publishing routes accept only an audit
        provider's credential.

        Sending no `Authorization` header produces `401`; sending one that is
        not recognised produces

        `403`.

````

This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.