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

# EIP-712 Signature Security

> Analyze an EIP-712 typed-data signing request before the user signs it. Returns a risk assessment with `recommended_action` (`ALLOW`, `WARN`, or `BLOCK`).

<Note>
  Request fields accept both `camelCase` and `snake_case`. See [Request Field Names](/#request-field-names).
</Note>

Analyze an EIP-712 typed-data signing request **before the user signs it**. The response is a risk assessment with an actionable recommendation.

Typical findings: unlimited permits, a login message that actually approves transfers, a blacklisted spender, or a suspicious marketplace order.

## Request Notes

* **`eip712Message`** — pass through as the dApp sent it to the wallet (`types` must include `EIP712Domain`, plus `primaryType`, `domain`, and `message`).
* **`url`** — send it whenever you have it. Without it, the blacklisted-URL checkpoint cannot fire.
* **`chainId`** — integer. e.g. `1` for Ethereum.

## Response Notes

### `recommended_action`

Use this field as the decision. Do not compute your own cutoff from `overall_score` — that mapping can change.

| Value     | Meaning                                          |
| --------- | ------------------------------------------------ |
| `"ALLOW"` | No significant risk detected.                    |
| `"WARN"`  | Suspicious signals — warn before the user signs. |
| `"BLOCK"` | Strong risk — recommend blocking the signature.  |

A single severe finding is enough to reach `BLOCK`. Do not treat `risk_details` as a tally.

### `intent`

What the user is actually signing.

| Value               | Description                                                     |
| ------------------- | --------------------------------------------------------------- |
| `"TOKEN_APPROVAL"`  | ERC-20 permit or allowance to a spender.                        |
| `"NFT_APPROVAL"`    | ERC-721/1155 approval to a spender or operator.                 |
| `"TOKEN_TRANSFER"`  | EIP-3009 gasless transfer — moves funds outright, no allowance. |
| `"ORDER_SIGNATURE"` | Marketplace order (Seaport, OpenSea listings).                  |
| `"DELEGATION"`      | Delegating control to another address.                          |
| `"STAKING"`         | Staking-related signature.                                      |
| `"LOGIN"`           | Sign-in / authentication message. Typically low risk.           |
| `"UNKNOWN"`         | Could not classify.                                             |

### Risk Level Scale

Used for `overall_risk_level` and every nested `risk_level`. `overall_score` is the maximum checkpoint score (0–5).

| Score | Label                |
| ----- | -------------------- |
| 0     | `"No Obvious Risk"`  |
| 1     | `"Caution"`          |
| 2     | `"Low Risk"`         |
| 3     | `"Medium Risk"`      |
| 4     | `"High Risk"`        |
| 5     | `"Significant Risk"` |

### `risk_details`

Each item is a checkpoint that fired. The array is empty when nothing fired.

Branch on `name`, not on `description`. Identifiers are stable; wording is not.

| Field                  | Use it for                            |
| ---------------------- | ------------------------------------- |
| `name`                 | Which check fired.                    |
| `value`                | Evidence for that check.              |
| `score` / `risk_level` | Severity of this finding at runtime.  |
| `description`          | Human-readable text. Do not parse it. |

Which time-window checkpoint applies depends on `intent` (approval vs marketplace order vs login). You do not need to pick one — the response names the checkpoint that fired.

### `entities`

Risk enrichment for addresses extracted from the message, plus the URL and verifying contract when those apply.

| Key                          | Present when                                                                     |
| ---------------------------- | -------------------------------------------------------------------------------- |
| `entities.addresses`         | Always. Map of address → `{score, risk_level}`.                                  |
| `entities.url`               | `url` was sent in the request (and enrichment succeeded).                        |
| `entities.verifyingContract` | The domain declares a `verifyingContract`. Shortcut to that address's risk data. |

A missing `entities.url` means either no `url` was supplied, or enrichment was unavailable. Threat-intelligence timeouts do not turn the call into a `500` — the response is still served from structural analysis.


## OpenAPI

````yaml POST /v2/hashdit/eip712-security
openapi: 3.1.0
info:
  title: HashDit API
  description: >-
    HashDit threat intelligence API for domain security analysis, blockchain
    address classification, address poisoning detection, address security
    assessment, transaction simulation, transaction security, token security,
    Solana token security, token approval security, and EIP-712 signature
    security
  version: 2.0.0
servers:
  - url: https://service.hashdit.io
security: []
paths:
  /v2/hashdit/eip712-security:
    post:
      summary: EIP-712 Signature Security
      description: >-
        Analyze an EIP-712 typed-data signing request before the user signs it.
        Returns a risk assessment with `recommended_action` (`ALLOW`, `WARN`, or
        `BLOCK`).
      operationId: eip712Security
      parameters:
        - name: X-API-KEY
          in: header
          description: Your HashDit API key
          required: true
          schema:
            type: string
      requestBody:
        description: >-
          EIP-712 typed-data payload. Pass `eip712Message` through as the dApp
          sent it to the wallet.
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/Eip712SecurityRequest'
            examples:
              Unlimited permit:
                summary: Permit on a dApp URL — typical wallet pre-sign check
                value:
                  address: '0x1d99c0ac928f58595b9d060c79f799fa38d171f4'
                  chainId: 1
                  url: https://app.uniswap.org
                  eip712Message:
                    primaryType: Permit
                    types:
                      EIP712Domain:
                        - name: name
                          type: string
                        - name: chainId
                          type: uint256
                        - name: verifyingContract
                          type: address
                      Permit:
                        - name: owner
                          type: address
                        - name: spender
                          type: address
                        - name: value
                          type: uint256
                        - name: nonce
                          type: uint256
                        - name: deadline
                          type: uint256
                    domain:
                      chainId: 1
                      name: USD Coin
                      verifyingContract: '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48'
                    message:
                      owner: '0x1d99c0ac928f58595b9d060c79f799fa38d171f4'
                      spender: '0x68b3465833fb72a70ecdf485e0e4c7bd8665fc45'
                      value: 1000000
                      nonce: 5
                      deadline: 1775000000
      responses:
        '200':
          description: >-
            Successful response. Envelope is `{code, status, data}`. Use
            `data.recommended_action` as the decision.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Eip712SecurityResponse'
              examples:
                Unlimited permit:
                  summary: '`BLOCK` — blacklisted URL and unlimited permit'
                  value:
                    code: '0'
                    status: ok
                    data:
                      overall_score: 5
                      overall_risk_level: Significant Risk
                      intent: TOKEN_APPROVAL
                      recommended_action: BLOCK
                      risk_details:
                        - name: eip712_url_blacklisted
                          value:
                            url: https://malicious-dapp.com
                          score: 5
                          risk_level: Significant Risk
                          description: >-
                            There are potential risks in the dApp url based on
                            the threat intelligence.
                        - name: eip712_permit_max_uint_allowance
                          value:
                            max_value: >-
                              115792089237316195423570985008687907853269984665640564039457584007913129639935
                            threshold: extreme
                          score: 4
                          risk_level: High Risk
                          description: >-
                            Permit-like signature contains near-unlimited
                            allowance.
                      entities:
                        addresses:
                          '0x68b3465833fb72a70ecdf485e0e4c7bd8665fc45':
                            score: 0
                            risk_level: No Obvious Risk
                          '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48':
                            score: 0
                            risk_level: No Obvious Risk
                        url:
                          score: 5
                          risk_level: Significant Risk
                        verifyingContract:
                          score: 0
                          risk_level: No Obvious Risk
                Clean:
                  summary: '`ALLOW` — no checkpoints fired'
                  value:
                    code: '0'
                    status: ok
                    data:
                      overall_score: 0
                      overall_risk_level: No Obvious Risk
                      intent: TOKEN_APPROVAL
                      recommended_action: ALLOW
                      risk_details: []
                      entities:
                        addresses:
                          '0x68b3465833fb72a70ecdf485e0e4c7bd8665fc45':
                            score: 0
                            risk_level: No Obvious Risk
                        verifyingContract:
                          score: 0
                          risk_level: No Obvious Risk
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '422':
          $ref: '#/components/responses/UnprocessableEntity'
        '429':
          $ref: '#/components/responses/RateLimitExceeded'
        '500':
          $ref: '#/components/responses/InternalServerError'
components:
  schemas:
    Eip712SecurityRequest:
      type: object
      required:
        - address
        - chainId
        - eip712Message
      properties:
        address:
          type: string
          description: Signer's wallet address.
          example: '0x1d99c0ac928f58595b9d060c79f799fa38d171f4'
        chainId:
          type: integer
          description: Chain of the signing request.
          example: 1
        url:
          type: string
          description: >-
            URL of the dApp requesting the signature. Enables domain-reputation
            checks. Send it whenever you have it.
          example: https://app.uniswap.org
        eip712Message:
          $ref: '#/components/schemas/Eip712Message'
    Eip712SecurityResponse:
      type: object
      properties:
        code:
          type: string
          description: API status code. `"0"` indicates success.
          example: '0'
        status:
          type: string
          example: ok
        data:
          $ref: '#/components/schemas/Eip712SecurityData'
    Eip712Message:
      type: object
      description: >-
        Standard EIP-712 typed-data payload. Pass through whatever the dApp
        handed the wallet.
      required:
        - types
        - primaryType
        - domain
        - message
      properties:
        types:
          type: object
          description: Type definitions. Must include `EIP712Domain`.
          additionalProperties:
            type: array
            items:
              $ref: '#/components/schemas/Eip712TypeField'
        primaryType:
          type: string
          description: Primary struct name, e.g. `Permit`.
          example: Permit
        domain:
          type: object
          description: >-
            EIP-712 domain separator fields (`name`, `chainId`,
            `verifyingContract`, …).
          additionalProperties: true
        message:
          type: object
          description: The typed message body.
          additionalProperties: true
    Eip712SecurityData:
      type: object
      properties:
        overall_score:
          type: integer
          description: Maximum risk score across all checkpoints, 0–5.
        overall_risk_level:
          type: string
          description: Label for `overall_score`.
        intent:
          type: string
          description: >-
            What the user is actually signing. See the endpoint page for the
            value list.
        recommended_action:
          type: string
          description: >-
            `"ALLOW"`, `"WARN"`, or `"BLOCK"`. Use this as the decision — do not
            derive a cutoff from `overall_score`.
          enum:
            - ALLOW
            - WARN
            - BLOCK
        risk_details:
          type: array
          description: >-
            Triggered checkpoints. Empty when nothing fired. Branch on `name`,
            not `description`.
          items:
            $ref: '#/components/schemas/Eip712RiskDetail'
        entities:
          $ref: '#/components/schemas/Eip712Entities'
    CurrentServiceError:
      type: object
      properties:
        code:
          type: string
          description: >-
            Error code. Typically `-1` for client errors, `-2` for server
            errors, or `401` / `429` for auth and rate limits.
        status:
          type: string
          description: Short error status string.
        detail:
          type: string
          description: Human-readable explanation of the error.
      required:
        - code
        - status
    MissingAPIKeyErrorResponse:
      type: object
      properties:
        code:
          type: string
          description: '`401`'
          example: '401'
        status:
          type: string
          description: Missing API key
          example: Missing API key
        detail:
          type: string
          description: Missing API key
          example: Missing API key
      required:
        - code
        - status
        - detail
    RateLimitExceededErrorResponse:
      type: object
      properties:
        code:
          type: string
          description: '`429`'
          example: '429'
        status:
          type: string
          description: '`error`'
          example: error
        message:
          type: string
          description: Rate limit exceeded
          example: Rate limit exceeded
    Eip712TypeField:
      type: object
      required:
        - name
        - type
      properties:
        name:
          type: string
        type:
          type: string
    Eip712RiskDetail:
      type: object
      properties:
        name:
          type: string
          description: Stable checkpoint identifier. Branch on this, not on `description`.
        value:
          type: object
          description: >-
            Checkpoint-specific evidence. Shape depends on `name` — see the
            catalogue on the endpoint page.
          additionalProperties: true
        score:
          type: integer
          description: 0–5 for this finding.
        risk_level:
          type: string
          description: Label for `score`.
        description:
          type: string
          description: >-
            Explanation of what was detected. Wording is not stable — do not
            parse it.
    Eip712Entities:
      type: object
      properties:
        addresses:
          type: object
          description: >-
            Always present. Map of address → `{score, risk_level}` for every
            address extracted from the message.
          additionalProperties:
            $ref: '#/components/schemas/Eip712EntityRisk'
        url:
          $ref: '#/components/schemas/Eip712EntityRisk'
          description: >-
            Present when `url` was supplied in the request (and enrichment
            succeeded).
        verifyingContract:
          $ref: '#/components/schemas/Eip712EntityRisk'
          description: Present when the domain declares a `verifyingContract`.
    Eip712EntityRisk:
      type: object
      properties:
        score:
          type: integer
          description: 0–5.
        risk_level:
          type: string
  responses:
    BadRequest:
      description: >-
        Bad request — malformed or missing field, unsupported chain, or invalid
        address.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/CurrentServiceError'
          examples:
            Invalid request:
              summary: Malformed or missing field
              value:
                code: '-1'
                status: invalid request
                detail: …
            Unsupported chain:
              summary: Chain not enabled for this endpoint
              value:
                code: '-1'
                status: unsupported chain
                detail: 'unsupported chainId: 137'
            Invalid address:
              summary: Address fails the format check for that chain
              value:
                code: '-1'
                status: invalid address
                detail: …
    Unauthorized:
      description: >-
        Missing or invalid `X-API-KEY`. This is the response customers see on
        current-service endpoints.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/MissingAPIKeyErrorResponse'
          examples:
            Missing API key:
              summary: Missing or invalid API key
              value:
                code: '401'
                status: Missing API key
                detail: Missing API key
    UnprocessableEntity:
      description: Schema validation failed. `detail` names the failing field path.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/CurrentServiceError'
          examples:
            Field required:
              summary: Schema validation
              value:
                code: '-1'
                status: invalid request
                detail: 'chainId: field required'
            Field path:
              summary: detail names the failing field path
              value:
                code: '-1'
                status: invalid request
                detail: evm_transactions[0].from
    RateLimitExceeded:
      description: Rate limit exceeded
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/RateLimitExceededErrorResponse'
          examples:
            Rate limit exceeded:
              summary: Rate limit exceeded error
              value:
                code: '429'
                status: error
                message: Rate limit exceeded
    InternalServerError:
      description: Server-side failure
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/CurrentServiceError'
          examples:
            Internal server error:
              summary: Internal server error
              value:
                code: '-2'
                status: internal server error
                detail: internal server error

````