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

# Submit Contracts for Decoding

> Submit up to 100 contracts (with their ABIs) for decoding in one request. Each item is validated and queued independently; the response reports a per-item result matched by index. Successful items are queued as "pending" and can be tracked with GET /v1/contracts/submissions or at dune.com/workspace. Submissions are attributed to the user who created the API key. "upgrade" submissions and protected namespaces are always routed to manual review.

<Info>
  Minimum required API key scope: `Read/Write`. Submissions are attributed to the user who created the API key.
</Info>

## Description

Submit up to 100 contracts for decoding in a single request. Each item is validated and queued independently: the response carries one result per item, matched by `index`, so a bad ABI in one item does not stop the others.

Successful items are queued as `pending` and can be tracked with [List Contract Submissions](./list) or in the [Dune UI](https://dune.com/contracts/new). Items that fail validation carry an `error` describing what to fix.

<Note>
  ABI upgrades, renames, deletions, and submissions to protected namespaces are always routed to manual review. Expect them to show `needs_manual_review` rather than being decoded automatically.
</Note>

## Request Fields

Each entry in `submissions` mirrors the fields of the submission form. See the [decoding guide](/web-app/decoding/decoding-contracts) for what the flags mean.

| Field                                   | Notes                                                                                                                                               |
| --------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------- |
| `blockchain_name`                       | Chain the contract is deployed on, e.g. `ethereum`, `base`. Must be a chain Dune decodes.                                                           |
| `address`                               | Contract address. Hex for EVM chains; Tron base58 addresses are accepted when `blockchain_name` is `tron`.                                          |
| `project_name`                          | Namespace the decoded tables are grouped under. Case is preserved.                                                                                  |
| `contract_name`                         | Contract name used in decoded table names. Case is preserved.                                                                                       |
| `abi`                                   | The ABI as a JSON array, or as a string containing the JSON array (the shape most exports produce).                                                 |
| `has_multiple_instances`                | `true` for [dynamic contracts](/web-app/decoding/decoding-contracts#are-there-several-instances-of-this-contract-dynamic-contract) sharing one ABI. |
| `is_created_by_factory`                 | `true` for contracts created by a [factory](/web-app/decoding/decoding-contracts#is-it-created-by-a-factory-contract-factory-contract).             |
| `is_proxy`                              | `true` when the address is a proxy; submit the implementation's ABI.                                                                                |
| `is_manual_abi`                         | `true` when the ABI was written or edited by hand rather than fetched from an explorer.                                                             |
| `submission_type`                       | `new` (default), `upgrade`, `rename`, `delete`, or `other`.                                                                                         |
| `resubmission_reason`                   | Why you are resubmitting. Required for `delete` and `other`.                                                                                        |
| `old_project_name`, `old_contract_name` | Required for `rename`: the names the contract is decoded under today. `project_name` and `contract_name` then carry the new names.                  |
| `idempotency_key`                       | Optional, at most 128 characters, unique per account. See below.                                                                                    |

For `delete`, `project_name` and `contract_name` name the contract to remove.

## Idempotency

If a request fails part way through or you lose the response, retrying a batch without keys creates duplicate submissions. Give each item an `idempotency_key` you control, such as `abi-refresh-2026-09-10/0`. Resubmitting an item whose key you already used returns the existing submission with `replayed: true` instead of creating a new one. Keys are scoped to your account.

## Plan Requirements

* Free plans can submit new contracts for a single blockchain per request.
* Batches spanning more than one `blockchain_name`, and any `upgrade`, `rename`, `delete`, or `other` submission, require the plan behind the API key to be paid (the team's plan for a team key). Otherwise the request fails with `403` and a reason.
* Read-only plans cannot submit.

## Pricing

Submitting contracts does not consume credits.

## Related Endpoints

* [List Contract Submissions](./list) - Track the status of your submissions

<RequestExample>
  ```bash cURL theme={null}
  curl -X POST "https://api.dune.com/api/v1/contracts/decode" \
    -H "X-DUNE-API-KEY: YOUR_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "submissions": [
        {
          "blockchain_name": "ethereum",
          "address": "0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984",
          "project_name": "uniswap",
          "contract_name": "UniswapToken",
          "abi": [{"type": "event", "name": "Transfer", "inputs": []}],
          "has_multiple_instances": false,
          "is_created_by_factory": false,
          "is_manual_abi": false,
          "is_proxy": false,
          "idempotency_key": "uniswap-token/ethereum/1"
        }
      ]
    }'
  ```

  ```python Python theme={null}
  import json
  import requests

  url = "https://api.dune.com/api/v1/contracts/decode"
  headers = {"X-DUNE-API-KEY": "YOUR_API_KEY"}

  with open("UniswapToken.abi.json") as f:
      abi = json.load(f)

  payload = {
      "submissions": [
          {
              "blockchain_name": "ethereum",
              "address": "0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984",
              "project_name": "uniswap",
              "contract_name": "UniswapToken",
              "abi": abi,
              "has_multiple_instances": False,
              "is_created_by_factory": False,
              "is_manual_abi": False,
              "is_proxy": False,
              "idempotency_key": "uniswap-token/ethereum/1",
          }
      ]
  }

  response = requests.post(url, json=payload, headers=headers)
  for result in response.json()["results"]:
      print(result)
  ```

  ```javascript JavaScript theme={null}
  const url = 'https://api.dune.com/api/v1/contracts/decode';

  const response = await fetch(url, {
    method: 'POST',
    headers: {
      'X-DUNE-API-KEY': 'YOUR_API_KEY',
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      submissions: [
        {
          blockchain_name: 'ethereum',
          address: '0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984',
          project_name: 'uniswap',
          contract_name: 'UniswapToken',
          abi: [{ type: 'event', name: 'Transfer', inputs: [] }],
          has_multiple_instances: false,
          is_created_by_factory: false,
          is_manual_abi: false,
          is_proxy: false,
          idempotency_key: 'uniswap-token/ethereum/1'
        }
      ]
    })
  });

  const data = await response.json();
  console.log(data.results);
  ```
</RequestExample>

<ResponseExample>
  ```json Example Response theme={null}
  {
    "results": [
      {
        "index": 0,
        "submission_id": "0b1e4c2a-7d3f-4e5b-9a6c-8d7e6f5a4b3c",
        "status": "pending"
      },
      {
        "index": 1,
        "error": "abi must be valid JSON"
      }
    ]
  }
  ```

  ```json Replayed Item theme={null}
  {
    "results": [
      {
        "index": 0,
        "submission_id": "0b1e4c2a-7d3f-4e5b-9a6c-8d7e6f5a4b3c",
        "status": "pending",
        "replayed": true
      }
    ]
  }
  ```

  ```json Plan Required theme={null}
  {
    "error": "Resubmissions and multi-chain batches require a paid team plan. Submit new contracts for one chain at a time, or upgrade your plan."
  }
  ```
</ResponseExample>


## OpenAPI

````yaml POST /v1/contracts/decode
openapi: 3.0.1
info:
  contact: {}
  description: Dune API
  title: DuneAPI
  version: '1.0'
servers:
  - url: https://api.dune.com/api
security: []
paths:
  /v1/contracts/decode:
    post:
      summary: Submit contracts for decoding
      description: >-
        Submit up to 100 contracts (with their ABIs) for decoding in one
        request. Each item is validated and queued independently; the response
        reports a per-item result matched by index. Successful items are queued
        as "pending" and can be tracked with GET /v1/contracts/submissions or at
        dune.com/workspace. Submissions are attributed to the user who created
        the API key. "upgrade" submissions and protected namespaces are always
        routed to manual review.
      parameters:
        - description: API Key for the service
          in: header
          name: X-Dune-Api-Key
          required: true
          schema:
            type: string
        - description: API Key, alternative to using the HTTP header X-Dune-Api-Key
          in: query
          name: api_key
          schema:
            type: string
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/models.SubmitContractsRequest'
        description: Batch of contract submissions
        required: true
        x-originalParamName: body
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/models.SubmitContractsResponse'
          description: OK
        '400':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/models.Error400'
          description: Bad Request
        '401':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/models.Error401'
          description: Unauthorized
        '403':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/models.Error403'
          description: Forbidden
        '429':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/models.Error429'
          description: Too Many Requests
        '500':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/models.Error500'
          description: Internal Server Error
components:
  schemas:
    models.SubmitContractsRequest:
      properties:
        submissions:
          items:
            $ref: '#/components/schemas/models.ContractSubmissionInput'
          maxItems: 100
          minItems: 1
          type: array
      required:
        - submissions
      type: object
    models.SubmitContractsResponse:
      properties:
        results:
          items:
            $ref: '#/components/schemas/models.ContractSubmissionResult'
          type: array
      type: object
    models.Error400:
      properties:
        error:
          example: Bad Request
          type: string
      type: object
    models.Error401:
      properties:
        error:
          example: Invalid API Key
          type: string
      type: object
    models.Error403:
      properties:
        error:
          example: >-
            Not allowed to execute query. Query is archived, unsaved or not
            enough permissions
          type: string
      type: object
    models.Error429:
      properties:
        error:
          example: >-
            Too Many Requests - Too many requests hit the API too quickly (rate
            limited).
          type: string
      type: object
    models.Error500:
      properties:
        error:
          example: Internal error
          type: string
      type: object
    models.ContractSubmissionInput:
      properties:
        abi:
          description: >-
            ABI is the contract ABI, either as a JSON array or as a JSON-encoded
            string containing the array.
          items:
            type: object
          type: array
        address:
          example: '0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984'
          type: string
        blockchain_name:
          example: ethereum
          type: string
        contract_name:
          example: UniswapToken
          type: string
        has_multiple_instances:
          type: boolean
        idempotency_key:
          description: >-
            IdempotencyKey makes the item safe to retry. It is unique per
            account (at most 128

            characters); resubmitting an item with a key you already used
            returns the existing

            submission with replayed=true instead of creating a new one.
          example: abi-refresh-2026-09-09/0
          type: string
        is_created_by_factory:
          type: boolean
        is_manual_abi:
          type: boolean
        is_proxy:
          type: boolean
        old_contract_name:
          type: string
        old_project_name:
          description: >-
            OldProjectName and OldContractName are required for "rename"
            submissions and name the

            contract as it is decoded today; project_name and contract_name
            carry the new names.

            "delete" submissions target project_name and contract_name directly.
          type: string
        project_name:
          example: uniswap
          type: string
        resubmission_reason:
          type: string
        submission_type:
          description: >-
            SubmissionType defaults to "new". "upgrade" submissions always go to
            manual review.
          enum:
            - new
            - upgrade
            - rename
            - delete
            - other
          example: new
          type: string
      required:
        - abi
        - address
        - blockchain_name
        - contract_name
        - project_name
      type: object
    models.ContractSubmissionResult:
      properties:
        error:
          example: abi must be valid JSON
          type: string
        index:
          type: integer
        replayed:
          description: >-
            Replayed is true when idempotency_key matched an earlier submission;
            submission_id then

            refers to that submission and nothing new was created.
          type: boolean
        status:
          enum:
            - pending
          example: pending
          type: string
        submission_id:
          example: 01J8Z2X4K7Q9R3T5V6W8Y0A1B2
          type: string
      type: object

````