# API Documentation

#### Supported Blockchains <a href="#supported-blockchains" id="supported-blockchains"></a>

**Endpoint:** GET /api/v1/chain/list

**Description:** Retrieve a list of all supported blockchains for contract analysis. Use the `chainid` value from the response when analyzing contracts.

### Endpoint

````
| | |
|---|---|
| **Method** | `POST` |
| **Path** | `/api/v1/portal/contract/analyze-risk` (Swagger advertises `/v1/portal/contract/analyze-risk`; the live base path is `/api`) |
| **Content-Type** | `application/json` |
| **Auth** | API key in body (`api_key`). No header-based auth. |
| **Idempotency** | Per `(user_id, address, chain_id)`. Re-calls return the cached result without a new charge. |
| **Async** | First call for a fresh contract returns **202 pending**. Client polls the same endpoint until **200 ready**. |

## Request body

```json
{
  "api_key":  "string",
  "address":  "string",
  "chain_id": "string"
}
```

| Field | Type | Required | Notes |
|---|---|---|---|
| `api_key` | string | yes | Risk-API scoped access token issued in the portal. |
| `address` | string | yes | Contract address. EVM addresses must be `0x`-prefixed; non-EVM follows the chain's native format. |
| `chain_id` | string | yes | Decimal string (e.g. `"1"`, `"8453"`, `"56"`). |

Empty or malformed JSON, or any missing field, → **400 `INVALID_REQUEST_PAYLOAD`**.
````

### Successful responses

````
Both 200 and 202 share a single envelope shape. Branch on the `status` field — only the matching subset of fields is populated.

### 200 OK — `status: "ready"`

The analysis is cached; result is returned inline. The user has been charged for this `(address, chain_id)` exactly once across the lifetime of the API key (subsequent ready-hits are free).

```json
{
  "status":     "ready",
  "address":    "0xdac17f958d2ee523a2206206994597c13d831ec7",
  "chain_id":   "1",
  "query_name": "token-risk",
  "results":    { /* analyzer output, shape depends on query */ }
}
```

| Field | Type | Notes |
|---|---|---|
| `status` | enum | `"ready"` for 200. |
| `address` | string | Echoed from request. |
| `chain_id` | string | Echoed from request. |
| `query_name` | string | Identifier of the analyzer query that produced `results`. |
| `results` | object/array | Free-shape analyzer payload. Stable per `query_name`/`query_version` upstream. |

### 202 Accepted — `status: "pending"`

The contract has not been analyzed yet. `gld-service-data-analyze` enqueues a background task and returns immediately. Client should retry after `retry_after_seconds`.

```json
{
  "status":              "pending",
  "retry_after_seconds": 30
}
```

| Field | Type | Notes |
|---|---|---|
| `status` | enum | `"pending"` for 202. |
| `retry_after_seconds` | int | Currently `30`. Client should treat as advisory (lower bound). |

A pending response is **not billed**. Billing happens on the first successful 200.
````

### Error responses

````
| HTTP | `error_code` | When |
|---|---|---|
| `400` | `INVALID_REQUEST_PAYLOAD` | Body is not JSON / required fields missing / fails struct validation. |
| `400` | `INVALID_ADDRESS_FORMAT` | Address fails chain-specific format check (passthrough from data-analyze). |
| `400` | `INVALID_QUERY_NAME` | Resolved query name is not registered (configuration issue, normally not surfaced). |
| `400` | `ANALYSIS_FAILED` | Background analysis terminally failed (`ANALYSIS_FAILED`, `ANALYSIS_TIMEOUT`, `ANALYSIS_CANCELED` from data-analyze are all surfaced under this code). |
| `400` | `INTERNAL_ERROR` | Catch-all for unclassified errors. |
| `401`/`404` | — | Returned when the supplied `api_key` is not found / not in `risk-api` scope. Status code is the verbatim passthrough from `gld-service-user`. |
| `402` | `INSUFFICIENT_FUNDS` | Billing balance is below the per-call price. User must top up. |
| `429` | `RATE_LIMIT_EXCEEDED` | Per-key rate limit exceeded (passthrough from data-analyze). |

### Error body

```json
{
  "error_code": "INSUFFICIENT_FUNDS",
  "message":    "insufficient funds"
}
```

For payload-shape errors only `error_code` is guaranteed; for validator failures the body additionally includes `error` with the validator string. Clients should branch on `error_code` and treat `message`/`error` as human-readable detail.
````

### Examples

````
### cURL — fresh request (202 → poll → 200)

```bash
curl -sS -X POST  \
  -H 'Content-Type: application/json' \
  -d '{"api_key":"sk_live_…","address":"0xdac17f958d2ee523a2206206994597c13d831ec7","chain_id":"1"}'
# → 202 {"status":"pending","retry_after_seconds":30}

# wait 30s, retry the same request
# → 200 {"status":"ready","address":"…","chain_id":"1","query_name":"token-risk","results":{…}}
```
````

### Polling pseudocode

````
```python
while True:
    r = post(url, json=body)
    if r.status_code == 200:
        return r.json()["results"]
    if r.status_code == 202:
        sleep(r.json().get("retry_after_seconds", 30))
        continue
    raise ApiError(r.status_code, r.json())
````

### Behavior notes

* **Pending is free.** Polling does not deduct from the user's balance. Only the first 200 response charges.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://glide.gitbook.io/main/glider-api/individuals-or-pay-as-you-go/api-documentation.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
